<commit_before>#include "enrichment_tests.h"

#include <cmath>

#include <gtest/gtest.h>

#include "composition.h"
#include "context.h"
#include "cyc_limits.h"
#include "env.h"
#include "error.h"
#include "material.h"
#include "recorder.h"
#include "timer.h"

namespace cyclus {
namespace toolkit {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetUp() {
  Env::SetNucDataPath();

  feed_ = 0.0072;
  product_ = 0.05;
  tails_ = 0.002;

  assay_u_ = product_;
  mass_u_ = 10;

  Timer ti;
  Recorder rec;
  Context ctx(&ti, &rec);

  CompMap v;
  v[922350000] = assay_u_;
  v[922380000] = 1 - assay_u_;
  Composition::Ptr comp = Composition::CreateFromAtom(v);
  mat_ = Material::CreateUntracked(mass_u_, comp);

  SetEnrichmentParameters();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::TearDown() {}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetEnrichmentParameters() {
  double feed_val = (1 - 2 * feed_) * std::log(1 / feed_ - 1);
  double tails_val = (1 - 2 * tails_) * std::log(1 / tails_ - 1);
  double product_val = (1 - 2 * product_) * std::log(1 / product_ - 1);

  feed_qty_ = mass_u_ * (product_ - tails_) / (feed_ - tails_);
  tails_qty_ = mass_u_ * (product_ - feed_) / (feed_ - tails_);
  swu_ = mass_u_ * product_val + tails_qty_ * tails_val - feed_qty_ * feed_val;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, assays) {
  Assays a(feed_, product_, tails_);
  EXPECT_DOUBLE_EQ(feed_, a.Feed());
  EXPECT_DOUBLE_EQ(product_, a.Product());
  EXPECT_DOUBLE_EQ(tails_, a.Tails());
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, valuefunction) {
  EXPECT_THROW(ValueFunc(0 - eps()),
               ValueError);
  EXPECT_THROW(ValueFunc(1), ValueError);

  double step = 0.001;
  double test_value = 0;
  while (test_value < 1) {
    double expected = (1 - 2 * test_value) * std::log(1 / test_value - 1);
    EXPECT_DOUBLE_EQ(expected, ValueFunc(test_value));
    test_value += step;
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, material) {
  EXPECT_DOUBLE_EQ(assay_u_, UraniumAssay(mat_));
  EXPECT_DOUBLE_EQ(mass_u_, UraniumQty(mat_));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, enrichmentcalcs) {
  Assays assays(feed_, UraniumAssay(mat_),
                                    tails_);
  double product_qty = UraniumQty(mat_);
  EXPECT_DOUBLE_EQ(feed_qty_, FeedQty(product_qty, assays));
  EXPECT_DOUBLE_EQ(tails_qty_, TailsQty(product_qty, assays));
  EXPECT_NEAR(swu_, SwuRequired(product_qty, assays), 1e-8);
}

}  // namespace toolkit
}  // namespace cyclus
<commit_msg>fix test from atom to mass<commit_after>#include "enrichment_tests.h"

#include <cmath>

#include <gtest/gtest.h>

#include "composition.h"
#include "context.h"
#include "cyc_limits.h"
#include "env.h"
#include "error.h"
#include "material.h"
#include "recorder.h"
#include "timer.h"

namespace cyclus {
namespace toolkit {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetUp() {
  Env::SetNucDataPath();

  feed_ = 0.0072;
  product_ = 0.05;
  tails_ = 0.002;

  assay_u_ = product_;
  mass_u_ = 10;

  Timer ti;
  Recorder rec;
  Context ctx(&ti, &rec);

  CompMap v;
  v[922350000] = assay_u_;
  v[922380000] = 1 - assay_u_;
  Composition::Ptr comp = Composition::CreateFromMass(v);
  mat_ = Material::CreateUntracked(mass_u_, comp);

  SetEnrichmentParameters();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::TearDown() {}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetEnrichmentParameters() {
  double feed_val = (1 - 2 * feed_) * std::log(1 / feed_ - 1);
  double tails_val = (1 - 2 * tails_) * std::log(1 / tails_ - 1);
  double product_val = (1 - 2 * product_) * std::log(1 / product_ - 1);

  feed_qty_ = mass_u_ * (product_ - tails_) / (feed_ - tails_);
  tails_qty_ = mass_u_ * (product_ - feed_) / (feed_ - tails_);
  swu_ = mass_u_ * product_val + tails_qty_ * tails_val - feed_qty_ * feed_val;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, assays) {
  Assays a(feed_, product_, tails_);
  EXPECT_DOUBLE_EQ(feed_, a.Feed());
  EXPECT_DOUBLE_EQ(product_, a.Product());
  EXPECT_DOUBLE_EQ(tails_, a.Tails());
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, valuefunction) {
  EXPECT_THROW(ValueFunc(0 - eps()),
               ValueError);
  EXPECT_THROW(ValueFunc(1), ValueError);

  double step = 0.001;
  double test_value = 0;
  while (test_value < 1) {
    double expected = (1 - 2 * test_value) * std::log(1 / test_value - 1);
    EXPECT_DOUBLE_EQ(expected, ValueFunc(test_value));
    test_value += step;
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, material) {
  EXPECT_DOUBLE_EQ(assay_u_, UraniumAssay(mat_));
  EXPECT_DOUBLE_EQ(mass_u_, UraniumQty(mat_));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, enrichmentcalcs) {
  Assays assays(feed_, UraniumAssay(mat_),
                                    tails_);
  double product_qty = UraniumQty(mat_);
  EXPECT_DOUBLE_EQ(feed_qty_, FeedQty(product_qty, assays));
  EXPECT_DOUBLE_EQ(tails_qty_, TailsQty(product_qty, assays));
  EXPECT_NEAR(swu_, SwuRequired(product_qty, assays), 1e-8);
}

}  // namespace toolkit
}  // namespace cyclus
<|endoftext|>


<commit_before>#include "enrichment_tests.h"

#include <cmath>

#include <gtest/gtest.h>

#include "composition.h"
#include "context.h"
#include "cyc_limits.h"
#include "recorder.h"
#include "error.h"
#include "material.h"
#include "timer.h"

namespace cyclus {
namespace toolkit {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetUp() {
  feed_ = 0.0072;
  product_ = 0.05;
  tails_ = 0.002;

  assay_u_ = product_;
  mass_u_ = 10;

  Timer ti;
  Recorder rec;
  Context ctx(&ti, &rec);

  CompMap v;
  v[922350000] = assay_u_;
  v[922380000] = 1 - assay_u_;
  Composition::Ptr comp = Composition::CreateFromAtom(v);
  mat_ = Material::CreateUntracked(mass_u_, comp);

  SetEnrichmentParameters();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::TearDown() {}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetEnrichmentParameters() {
  double feed_val = (1 - 2 * feed_) * std::log(1 / feed_ - 1);
  double tails_val = (1 - 2 * tails_) * std::log(1 / tails_ - 1);
  double product_val = (1 - 2 * product_) * std::log(1 / product_ - 1);

  feed_qty_ = mass_u_ * (product_ - tails_) / (feed_ - tails_);
  tails_qty_ = mass_u_ * (product_ - feed_) / (feed_ - tails_);
  swu_ = mass_u_ * product_val + tails_qty_ * tails_val - feed_qty_ * feed_val;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, assays) {
  Assays a(feed_, product_, tails_);
  EXPECT_DOUBLE_EQ(feed_, a.Feed());
  EXPECT_DOUBLE_EQ(product_, a.Product());
  EXPECT_DOUBLE_EQ(tails_, a.Tails());
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, valuefunction) {
  EXPECT_THROW(ValueFunc(0 - eps()),
               ValueError);
  EXPECT_THROW(ValueFunc(1), ValueError);

  double step = 0.001;
  double test_value = 0;
  while (test_value < 1) {
    double expected = (1 - 2 * test_value) * std::log(1 / test_value - 1);
    EXPECT_DOUBLE_EQ(expected, ValueFunc(test_value));
    test_value += step;
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, material) {
  EXPECT_DOUBLE_EQ(assay_u_, UraniumAssay(mat_));
  EXPECT_DOUBLE_EQ(mass_u_, UraniumQty(mat_));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, enrichmentcalcs) {
  Assays assays(feed_, UraniumAssay(mat_),
                                    tails_);
  double product_qty = UraniumQty(mat_);
  EXPECT_DOUBLE_EQ(feed_qty_, FeedQty(product_qty, assays));
  EXPECT_DOUBLE_EQ(tails_qty_, TailsQty(product_qty, assays));
  EXPECT_NEAR(swu_, SwuRequired(product_qty, assays), 1e-8);
}

} // namespace toolkit
} // namespace cyclus
<commit_msg>fixed enrichment bug<commit_after>#include "enrichment_tests.h"

#include <cmath>

#include <gtest/gtest.h>

#include "composition.h"
#include "context.h"
#include "cyc_limits.h"
#include "recorder.h"
#include "error.h"
#include "material.h"
#include "timer.h"
#include "env.h"

namespace cyclus {
namespace toolkit {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetUp() {
  feed_ = 0.0072;
  product_ = 0.05;
  tails_ = 0.002;

  assay_u_ = product_;
  mass_u_ = 10;

  Timer ti;
  Recorder rec;
  Context ctx(&ti, &rec);

  CompMap v;
  v[922350000] = assay_u_;
  v[922380000] = 1 - assay_u_;
  Composition::Ptr comp = Composition::CreateFromAtom(v);
  mat_ = Material::CreateUntracked(mass_u_, comp);

  SetEnrichmentParameters();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::TearDown() {}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EnrichmentTests::SetEnrichmentParameters() {
  double feed_val = (1 - 2 * feed_) * std::log(1 / feed_ - 1);
  double tails_val = (1 - 2 * tails_) * std::log(1 / tails_ - 1);
  double product_val = (1 - 2 * product_) * std::log(1 / product_ - 1);

  feed_qty_ = mass_u_ * (product_ - tails_) / (feed_ - tails_);
  tails_qty_ = mass_u_ * (product_ - feed_) / (feed_ - tails_);
  swu_ = mass_u_ * product_val + tails_qty_ * tails_val - feed_qty_ * feed_val;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, assays) {
  Assays a(feed_, product_, tails_);
  EXPECT_DOUBLE_EQ(feed_, a.Feed());
  EXPECT_DOUBLE_EQ(product_, a.Product());
  EXPECT_DOUBLE_EQ(tails_, a.Tails());
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, valuefunction) {
  EXPECT_THROW(ValueFunc(0 - eps()),
               ValueError);
  EXPECT_THROW(ValueFunc(1), ValueError);

  double step = 0.001;
  double test_value = 0;
  while (test_value < 1) {
    double expected = (1 - 2 * test_value) * std::log(1 / test_value - 1);
    EXPECT_DOUBLE_EQ(expected, ValueFunc(test_value));
    test_value += step;
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, material) {
  Env::SetNucDataPath();
  EXPECT_DOUBLE_EQ(assay_u_, UraniumAssay(mat_));
  EXPECT_DOUBLE_EQ(mass_u_, UraniumQty(mat_));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(EnrichmentTests, enrichmentcalcs) {
  Env::SetNucDataPath();
  Assays assays(feed_, UraniumAssay(mat_),
                                    tails_);
  double product_qty = UraniumQty(mat_);
  EXPECT_DOUBLE_EQ(feed_qty_, FeedQty(product_qty, assays));
  EXPECT_DOUBLE_EQ(tails_qty_, TailsQty(product_qty, assays));
  EXPECT_NEAR(swu_, SwuRequired(product_qty, assays), 1e-8);
}

} // namespace toolkit
} // namespace cyclus
<|endoftext|>


<commit_before>#include <algorithm>
#include <string>
#include <vector>
#include <AGPU/agpu.h>

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef max
#undef min
#elif defined(__unix__) || defined(__APPLE__)
#include <sys/types.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <dirent.h>
#else
#error unsupported platform
#endif

#ifdef HAS_XLIB
#include <X11/Xlib.h>

struct CallXInitThreads
{
    CallXInitThreads()
    {
        XInitThreads();
    }
} callXInitThreads;

#endif

/**
 * ICD loaded platform info.
 */
class PlatformInfo
{
public:
    PlatformInfo();
    ~PlatformInfo();

    agpu_platform *platform;

#ifdef _WIN32
    HMODULE moduleHandle;
#else
    void *moduleHandle;
#endif

    agpu_bool hasRealMultithreading;
    agpu_bool isNative;
    agpu_bool isCrossPlatform;

};

PlatformInfo::PlatformInfo()
{
}

PlatformInfo::~PlatformInfo()
{
}

static bool hasBeenLoaded = false;
static std::vector<PlatformInfo*> loadedPlatforms;

std::wstring utf8ToUtf16(const std::string &utf8)
{
    int c = 0;
    size_t position = 0;
    std::wstring utf16;
    while (position < utf8.size())
    {
        int startChar = utf8[position++];
        if ((startChar & 0x80) == 0)
        {
            utf16.push_back(startChar);
            continue;
        }

        int charSize = 1;
        while ((startChar & (1 << (7 - charSize))) != 0)
        {
            charSize++;
        }

        --charSize;
        if (size_t(position + charSize) > utf8.size())
            break;

        printf("char size %d\n", charSize);
    }

    return utf16;
}

std::string utf16ToUtf8(const std::wstring &utf16)
{
    int c = 0;
    size_t position = 0;
    std::string utf8;
    while (position < utf16.size())
    {
        int startChar = utf16[position++];
        if (startChar < 128)
        {
            utf8.push_back(startChar);
            continue;
        }

        abort();
    }

    return utf8;
}
template<typename FT>
void dirEntriesDo(const std::string &dirPath, const FT &f)
{
#if defined(_WIN32)
    auto dirPathUtf16 = utf8ToUtf16(dirPath) + L"*";
    WIN32_FIND_DATAW findData;
    auto handle = FindFirstFileW(dirPathUtf16.c_str(), &findData);
    if (handle == INVALID_HANDLE_VALUE)
        return;

    f(utf16ToUtf8(findData.cFileName));
    while(FindNextFileW(handle, &findData))
        f(utf16ToUtf8(findData.cFileName));

    FindClose(handle);
#elif defined(__unix__) || defined(__APPLE__)
    auto dir = opendir(dirPath.c_str());
    if(!dir)
        return;

    struct dirent *entry;
    while((entry = readdir(dir)) != nullptr)
        f(entry->d_name);

    closedir(dir);
#else
#error unsupported platform
#endif
}

static std::string dirname(const std::string &path)
{
    auto lastPos = path.rfind('/');
#if defined(_WIN32)
    auto lastBPos = path.rfind('\\');
    if(lastPos == std::string::npos)
        lastPos = lastBPos;
    else if(lastPos != std::string::npos && lastBPos != std::string::npos)
        lastPos = std::max(lastPos, lastBPos);
#endif
    if(lastPos == std::string::npos)
        return path;

    return path.substr(0, lastPos);
}

static std::string extension(const std::string &path)
{
    auto dotPos = path.rfind('.');
    if (dotPos == std::string::npos)
        return std::string();
    return path.substr(dotPos + 1);
}
static bool isAbsolutePath(const std::string &path)
{
#if defined(_WIN32)
    return path.size() >= 2 && path[2] == ':';
#else
    return path.size() && path[0] == '/';
#endif
}

static bool isFile(const std::string &path)
{
#if defined(_WIN32)
    auto pathUtf16 = utf8ToUtf16(path);
    auto attributes = GetFileAttributesW(pathUtf16.c_str());
    return (attributes != INVALID_FILE_ATTRIBUTES) && ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
#else
    struct stat s;
    auto res = stat(path.c_str(), &s);
    return res == 0 && S_ISREG(s.st_mode);
#endif
}

static std::string joinPath(const std::string &path1, const std::string &path2)
{
    if(isAbsolutePath(path2))
        return path2;
#if defined(_WIN32)
    if(path1.back() == '\\' || path1.back() == '/')
        return path1 + path2;
    return path1 + "\\" + path2;
#else
    if(path1.back() == '/')
        return path1 + path2;
#endif
    return path1 + "/" + path2;
}

static void loadDriver(const std::string &path)
{
#if defined(_WIN32)
    auto ext = extension(path);
    if (ext != "dll")
        return;

    auto pathUtf16 = utf8ToUtf16(path);
    auto handle = LoadLibraryW(pathUtf16.c_str());
    if (handle == NULL)
        return;

    // Try to get the platform defined by the library.
    agpuGetPlatforms_FUN getPlatforms = (agpuGetPlatforms_FUN)GetProcAddress(handle, "agpuGetPlatforms");
    if (!getPlatforms)
    {
        FreeLibrary(handle);
        return;
    }

    // Get the driver platform count.
    agpu_size platformCount;
    getPlatforms(0, nullptr, &platformCount);

    // Get the driver platforms
    std::vector<agpu_platform*> platforms(platformCount);
    getPlatforms(agpu_size(platforms.size()), &platforms[0], &platformCount);

    // Ensure there is at least one platform defined.
    if (!platformCount)
    {
        FreeLibrary(handle);
        return;
    }

#else
    int flags = RTLD_NOW | RTLD_LOCAL;
#if defined(__linux__)
    flags |= RTLD_DEEPBIND;
#endif

    // Load only once.
    auto handle = dlopen(path.c_str(), flags | RTLD_NOLOAD );
    if(handle)
        return;

    // Is this a library?
    handle = dlopen(path.c_str(), flags);
    if(!handle)
    {
        fprintf(stderr, "Failed to load %s: %s\n", path.c_str(), dlerror());
        return;
    }

    // Try to get the platform defined by the library.
    agpuGetPlatforms_FUN getPlatforms = (agpuGetPlatforms_FUN)dlsym(handle, "agpuGetPlatforms");
    if(!getPlatforms)
    {
        dlclose(handle);
        return;
    }

    // Get the driver platform count.
    agpu_size platformCount;
    getPlatforms(0, nullptr, &platformCount);

    // Get the driver platforms
    std::vector<agpu_platform*> platforms(platformCount);
    getPlatforms(platforms.size(), &platforms[0], &platformCount);

    // Ensure there is at least one platform defined.
    if(!platformCount)
    {
        dlclose(handle);
        return;
    }

#endif

    // Got the platforms, store them.
    for (agpu_size i = 0; i < platformCount; ++i)
    {
        auto platform = platforms[i];
        auto platformInfo = new PlatformInfo();
        platformInfo->platform = platform;
        platformInfo->moduleHandle = handle;
        platformInfo->isNative = agpuIsNativePlatform(platform);
        platformInfo->hasRealMultithreading = agpuPlatformHasRealMultithreading(platform);
        platformInfo->isCrossPlatform = agpuIsCrossPlatform(platform);
        loadedPlatforms.push_back(platformInfo);
    }
}

static void loadDriversInPath(const std::string &folder)
{
    dirEntriesDo(folder, [&](const std::string &fileName) {
        auto fullPath = joinPath(folder, fileName);
        if(isFile(fullPath))
            loadDriver(fullPath);
    });
}

inline std::string getStringFromEnvironment(const char *varname)
{
#ifdef _WIN32
	char *buffer;
	size_t size;
	auto error = _dupenv_s(&buffer, &size, varname);;
	if (error) return std::string();
	if (!buffer) return std::string();
	std::string res = buffer;
	free(buffer);
	return res;
#else
	auto value = getenv(varname);
	if (!value)
		return std::string();
	return value;
#endif
}

static void loadPlatforms()
{
    // Single driver path
    auto driverPath = getStringFromEnvironment("AGPU_DRIVER_PATH");
    if(!driverPath.empty())
    {
        loadDriver(driverPath);
        return;
    }

    // Environment variable
    auto envPath = getStringFromEnvironment("AGPU_DRIVERS_PATH");
    if(!envPath.empty())
        loadDriversInPath(envPath);

    // Library relative path.
#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
    Dl_info info;
    if(dladdr((void*)&loadPlatforms, &info))
        loadDriversInPath(joinPath(dirname(info.dli_fname), "AgpuIcd/"));
#elif defined(_WIN32)
    HMODULE handle;
    if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)&loadPlatforms, &handle))
    {
        WCHAR modulePathBuffer[MAX_PATH];
        auto pathLength = GetModuleFileNameW(handle, modulePathBuffer, MAX_PATH);
        if (pathLength != MAX_PATH && pathLength != 0)
        {
            std::wstring modulePath(modulePathBuffer, modulePathBuffer + pathLength);
            loadDriversInPath(joinPath(dirname(utf16ToUtf8(modulePath)), "AgpuIcd\\"));
        }
    }
#endif

    // TODO: Executable relative path
    //loadDriversInPath("AgpuIcd");
    hasBeenLoaded = true;

    // Sort the platforms. Keep the relative orders given by a driver.
    std::stable_sort(loadedPlatforms.begin(), loadedPlatforms.end(), [](PlatformInfo *a, PlatformInfo *b) {
        if (a->hasRealMultithreading == b->hasRealMultithreading)
        {
            if (a->isNative == b->isNative)
                return a->isCrossPlatform > b->isCrossPlatform;
            return a->isNative > b->isNative;
        }

        return a->hasRealMultithreading > b->hasRealMultithreading;
    });
}

AGPU_EXPORT agpu_error agpuGetPlatforms ( agpu_size numplatforms, agpu_platform** platforms, agpu_size* ret_numplatforms )
{
    if (!hasBeenLoaded)
        loadPlatforms();

    if (!platforms && numplatforms == 0)
    {
        if (ret_numplatforms != nullptr)
        {
            *ret_numplatforms = (agpu_size)loadedPlatforms.size();
            return AGPU_OK;
        }
        else
            return AGPU_NULL_POINTER;
    }

    size_t retCount = std::min(numplatforms, (agpu_size)loadedPlatforms.size());

    // Pass the platforms
    for(size_t i = 0; i < retCount; ++i)
        platforms[i] = loadedPlatforms[i]->platform;

    // Set the rest to null.
    for(size_t i = retCount; i < numplatforms; ++i)
        platforms[i] = nullptr;

    if(ret_numplatforms)
        *ret_numplatforms = (agpu_size)retCount;
    return AGPU_OK;
}
<commit_msg>I am fixing an assertion failure when one of the icd implementations does not return valid platforms.<commit_after>#include <algorithm>
#include <string>
#include <vector>
#include <AGPU/agpu.h>

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef max
#undef min
#elif defined(__unix__) || defined(__APPLE__)
#include <sys/types.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <dirent.h>
#else
#error unsupported platform
#endif

#ifdef HAS_XLIB
#include <X11/Xlib.h>

struct CallXInitThreads
{
    CallXInitThreads()
    {
        XInitThreads();
    }
} callXInitThreads;

#endif

/**
 * ICD loaded platform info.
 */
class PlatformInfo
{
public:
    PlatformInfo();
    ~PlatformInfo();

    agpu_platform *platform;

#ifdef _WIN32
    HMODULE moduleHandle;
#else
    void *moduleHandle;
#endif

    agpu_bool hasRealMultithreading;
    agpu_bool isNative;
    agpu_bool isCrossPlatform;

};

PlatformInfo::PlatformInfo()
{
}

PlatformInfo::~PlatformInfo()
{
}

static bool hasBeenLoaded = false;
static std::vector<PlatformInfo*> loadedPlatforms;

std::wstring utf8ToUtf16(const std::string &utf8)
{
    int c = 0;
    size_t position = 0;
    std::wstring utf16;
    while (position < utf8.size())
    {
        int startChar = utf8[position++];
        if ((startChar & 0x80) == 0)
        {
            utf16.push_back(startChar);
            continue;
        }

        int charSize = 1;
        while ((startChar & (1 << (7 - charSize))) != 0)
        {
            charSize++;
        }

        --charSize;
        if (size_t(position + charSize) > utf8.size())
            break;

        printf("char size %d\n", charSize);
    }

    return utf16;
}

std::string utf16ToUtf8(const std::wstring &utf16)
{
    int c = 0;
    size_t position = 0;
    std::string utf8;
    while (position < utf16.size())
    {
        int startChar = utf16[position++];
        if (startChar < 128)
        {
            utf8.push_back(startChar);
            continue;
        }

        abort();
    }

    return utf8;
}
template<typename FT>
void dirEntriesDo(const std::string &dirPath, const FT &f)
{
#if defined(_WIN32)
    auto dirPathUtf16 = utf8ToUtf16(dirPath) + L"*";
    WIN32_FIND_DATAW findData;
    auto handle = FindFirstFileW(dirPathUtf16.c_str(), &findData);
    if (handle == INVALID_HANDLE_VALUE)
        return;

    f(utf16ToUtf8(findData.cFileName));
    while(FindNextFileW(handle, &findData))
        f(utf16ToUtf8(findData.cFileName));

    FindClose(handle);
#elif defined(__unix__) || defined(__APPLE__)
    auto dir = opendir(dirPath.c_str());
    if(!dir)
        return;

    struct dirent *entry;
    while((entry = readdir(dir)) != nullptr)
        f(entry->d_name);

    closedir(dir);
#else
#error unsupported platform
#endif
}

static std::string dirname(const std::string &path)
{
    auto lastPos = path.rfind('/');
#if defined(_WIN32)
    auto lastBPos = path.rfind('\\');
    if(lastPos == std::string::npos)
        lastPos = lastBPos;
    else if(lastPos != std::string::npos && lastBPos != std::string::npos)
        lastPos = std::max(lastPos, lastBPos);
#endif
    if(lastPos == std::string::npos)
        return path;

    return path.substr(0, lastPos);
}

static std::string extension(const std::string &path)
{
    auto dotPos = path.rfind('.');
    if (dotPos == std::string::npos)
        return std::string();
    return path.substr(dotPos + 1);
}
static bool isAbsolutePath(const std::string &path)
{
#if defined(_WIN32)
    return path.size() >= 2 && path[2] == ':';
#else
    return path.size() && path[0] == '/';
#endif
}

static bool isFile(const std::string &path)
{
#if defined(_WIN32)
    auto pathUtf16 = utf8ToUtf16(path);
    auto attributes = GetFileAttributesW(pathUtf16.c_str());
    return (attributes != INVALID_FILE_ATTRIBUTES) && ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
#else
    struct stat s;
    auto res = stat(path.c_str(), &s);
    return res == 0 && S_ISREG(s.st_mode);
#endif
}

static std::string joinPath(const std::string &path1, const std::string &path2)
{
    if(isAbsolutePath(path2))
        return path2;
#if defined(_WIN32)
    if(path1.back() == '\\' || path1.back() == '/')
        return path1 + path2;
    return path1 + "\\" + path2;
#else
    if(path1.back() == '/')
        return path1 + path2;
#endif
    return path1 + "/" + path2;
}

static void loadDriver(const std::string &path)
{
#if defined(_WIN32)
    auto ext = extension(path);
    if (ext != "dll")
        return;

    auto pathUtf16 = utf8ToUtf16(path);
    auto handle = LoadLibraryW(pathUtf16.c_str());
    if (handle == NULL)
        return;

    // Try to get the platform defined by the library.
    agpuGetPlatforms_FUN getPlatforms = (agpuGetPlatforms_FUN)GetProcAddress(handle, "agpuGetPlatforms");
    if (!getPlatforms)
    {
        FreeLibrary(handle);
        return;
    }

    // Get the driver platform count.
    agpu_size platformCount;
    getPlatforms(0, nullptr, &platformCount);

    // Get the driver platforms
    std::vector<agpu_platform*> platforms(platformCount);
	if (platformCount > 0)
		getPlatforms(agpu_size(platforms.size()), &platforms[0], &platformCount);

    // Ensure there is at least one platform defined.
    if (!platformCount)
    {
        FreeLibrary(handle);
        return;
    }

#else
    int flags = RTLD_NOW | RTLD_LOCAL;
#if defined(__linux__)
    flags |= RTLD_DEEPBIND;
#endif

    // Load only once.
    auto handle = dlopen(path.c_str(), flags | RTLD_NOLOAD );
    if(handle)
        return;

    // Is this a library?
    handle = dlopen(path.c_str(), flags);
    if(!handle)
    {
        fprintf(stderr, "Failed to load %s: %s\n", path.c_str(), dlerror());
        return;
    }

    // Try to get the platform defined by the library.
    agpuGetPlatforms_FUN getPlatforms = (agpuGetPlatforms_FUN)dlsym(handle, "agpuGetPlatforms");
    if(!getPlatforms)
    {
        dlclose(handle);
        return;
    }

    // Get the driver platform count.
    agpu_size platformCount;
    getPlatforms(0, nullptr, &platformCount);

    // Get the driver platforms
    std::vector<agpu_platform*> platforms(platformCount);
	if(platformCount > 0)
	    getPlatforms(platforms.size(), &platforms[0], &platformCount);

    // Ensure there is at least one platform defined.
    if(!platformCount)
    {
        dlclose(handle);
        return;
    }

#endif

    // Got the platforms, store them.
    for (agpu_size i = 0; i < platformCount; ++i)
    {
        auto platform = platforms[i];
        auto platformInfo = new PlatformInfo();
        platformInfo->platform = platform;
        platformInfo->moduleHandle = handle;
        platformInfo->isNative = agpuIsNativePlatform(platform);
        platformInfo->hasRealMultithreading = agpuPlatformHasRealMultithreading(platform);
        platformInfo->isCrossPlatform = agpuIsCrossPlatform(platform);
        loadedPlatforms.push_back(platformInfo);
    }
}

static void loadDriversInPath(const std::string &folder)
{
    dirEntriesDo(folder, [&](const std::string &fileName) {
        auto fullPath = joinPath(folder, fileName);
        if(isFile(fullPath))
            loadDriver(fullPath);
    });
}

inline std::string getStringFromEnvironment(const char *varname)
{
#ifdef _WIN32
	char *buffer;
	size_t size;
	auto error = _dupenv_s(&buffer, &size, varname);;
	if (error) return std::string();
	if (!buffer) return std::string();
	std::string res = buffer;
	free(buffer);
	return res;
#else
	auto value = getenv(varname);
	if (!value)
		return std::string();
	return value;
#endif
}

static void loadPlatforms()
{
    // Single driver path
    auto driverPath = getStringFromEnvironment("AGPU_DRIVER_PATH");
    if(!driverPath.empty())
    {
        loadDriver(driverPath);
        return;
    }

    // Environment variable
    auto envPath = getStringFromEnvironment("AGPU_DRIVERS_PATH");
    if(!envPath.empty())
        loadDriversInPath(envPath);

    // Library relative path.
#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
    Dl_info info;
    if(dladdr((void*)&loadPlatforms, &info))
        loadDriversInPath(joinPath(dirname(info.dli_fname), "AgpuIcd/"));
#elif defined(_WIN32)
    HMODULE handle;
    if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)&loadPlatforms, &handle))
    {
        WCHAR modulePathBuffer[MAX_PATH];
        auto pathLength = GetModuleFileNameW(handle, modulePathBuffer, MAX_PATH);
        if (pathLength != MAX_PATH && pathLength != 0)
        {
            std::wstring modulePath(modulePathBuffer, modulePathBuffer + pathLength);
            loadDriversInPath(joinPath(dirname(utf16ToUtf8(modulePath)), "AgpuIcd\\"));
        }
    }
#endif

    // TODO: Executable relative path
    //loadDriversInPath("AgpuIcd");
    hasBeenLoaded = true;

    // Sort the platforms. Keep the relative orders given by a driver.
    std::stable_sort(loadedPlatforms.begin(), loadedPlatforms.end(), [](PlatformInfo *a, PlatformInfo *b) {
        if (a->hasRealMultithreading == b->hasRealMultithreading)
        {
            if (a->isNative == b->isNative)
                return a->isCrossPlatform > b->isCrossPlatform;
            return a->isNative > b->isNative;
        }

        return a->hasRealMultithreading > b->hasRealMultithreading;
    });
}

AGPU_EXPORT agpu_error agpuGetPlatforms ( agpu_size numplatforms, agpu_platform** platforms, agpu_size* ret_numplatforms )
{
    if (!hasBeenLoaded)
        loadPlatforms();

    if (!platforms && numplatforms == 0)
    {
        if (ret_numplatforms != nullptr)
        {
            *ret_numplatforms = (agpu_size)loadedPlatforms.size();
            return AGPU_OK;
        }
        else
            return AGPU_NULL_POINTER;
    }

    size_t retCount = std::min(numplatforms, (agpu_size)loadedPlatforms.size());

    // Pass the platforms
    for(size_t i = 0; i < retCount; ++i)
        platforms[i] = loadedPlatforms[i]->platform;

    // Set the rest to null.
    for(size_t i = retCount; i < numplatforms; ++i)
        platforms[i] = nullptr;

    if(ret_numplatforms)
        *ret_numplatforms = (agpu_size)retCount;
    return AGPU_OK;
}
<|endoftext|>


<commit_before>#ifndef SELECT_SORT_HPP__
#define SELECT_SORT_HPP__

#include <algorithm>

namespace al {

template <typename __input_iterator>
static void select_sort(__input_iterator __first, __input_iterator __last)
{
    __input_iterator k;

    if (__first == __last)
        return ;

    for (__input_iterator i = __first; i != __last; i++) {
        k = i;
        for (__input_iterator j = i + 1; j != __last; j++) {
            if (*k > *j)
                k = j;
        }
        if (k != i) {
            std::swap(*k, *i);
        }
    }
}

}

#endif
<commit_msg>fix #ifndef...<commit_after>#ifndef __SELECT_SORT_HPP__
#define __SELECT_SORT_HPP__

#include <algorithm>

namespace al {

template <typename __input_iterator>
static void select_sort(__input_iterator __first, __input_iterator __last)
{
    __input_iterator k;

    if (__first == __last)
        return ;

    for (__input_iterator i = __first; i != __last; i++) {
        k = i;
        for (__input_iterator j = i + 1; j != __last; j++) {
            if (*k > *j)
                k = j;
        }
        if (k != i) {
            std::swap(*k, *i);
        }
    }
}

}

#endif
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-node is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_SERVER_DEFINE_HPP
#define LIBBITCOIN_SERVER_DEFINE_HPP

#include <bitcoin/bitcoin.hpp>

// We use the generic helper definitions in libbitcoin to define BCX_API
// and BCX_INTERNAL. BCX_API is used for the public API symbols. It either DLL
// imports or DLL exports (or does nothing for static build) BCX_INTERNAL is
// used for non-api symbols.

#if defined BCS_STATIC
    #define BCS_API
    #define BCS_INTERNAL
#elif defined BCS_DLL
    #define BCS_API      BC_HELPER_DLL_EXPORT
    #define BCS_INTERNAL BC_HELPER_DLL_LOCAL
#else
    #define BCS_API      BC_HELPER_DLL_IMPORT
    #define BCS_INTERNAL BC_HELPER_DLL_LOCAL
#endif

#endif
<commit_msg>Fix copyright.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-server.
 *
 * libbitcoin-server is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_SERVER_DEFINE_HPP
#define LIBBITCOIN_SERVER_DEFINE_HPP

#include <bitcoin/bitcoin.hpp>

// We use the generic helper definitions in libbitcoin to define BCX_API
// and BCX_INTERNAL. BCX_API is used for the public API symbols. It either DLL
// imports or DLL exports (or does nothing for static build) BCX_INTERNAL is
// used for non-api symbols.

#if defined BCS_STATIC
    #define BCS_API
    #define BCS_INTERNAL
#elif defined BCS_DLL
    #define BCS_API      BC_HELPER_DLL_EXPORT
    #define BCS_INTERNAL BC_HELPER_DLL_LOCAL
#else
    #define BCS_API      BC_HELPER_DLL_IMPORT
    #define BCS_INTERNAL BC_HELPER_DLL_LOCAL
#endif

#endif
<|endoftext|>


<commit_before>// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "unproject.h"
#include "model_proj_viewport.h"
#include "../unproject.h"
#include "../opengl/OpenGL_convenience.h"

#include <Eigen/Dense>
#include <Eigen/LU>

IGL_INLINE void igl::opengl2::unproject(
  const double winX,
  const double winY,
  const double winZ,
  double* objX,
  double* objY,
  double* objZ)
{
  Eigen::Vector3d obj;
  igl::opengl2::unproject(Eigen::Vector3d(winX,winY,winZ),obj);
  *objX = obj(0);
  *objY = obj(1);
  *objZ = obj(2);
}

template <typename Derivedwin, typename Derivedobj>
IGL_INLINE void igl::opengl2::unproject(
  const Eigen::PlainObjectBase<Derivedwin> & win,
  Eigen::PlainObjectBase<Derivedobj> & obj)
{
  obj = igl::opengl2::unproject(win).template cast<typename Derivedobj::Scalar>();
}

template <typename Derivedwin>
IGL_INLINE Eigen::PlainObjectBase<Derivedwin> igl::opengl2::unproject(
  const Eigen::PlainObjectBase<Derivedwin> & win)
{
  using namespace Eigen;
  typedef typename Derivedwin::Scalar Scalar;
  Matrix4d MV,P;
  Vector4d VPd;
  model_proj_viewport(MV,P,VPd);
  Vector3d wind = win.template cast<double>();
  Vector3d objd = igl::unproject(wind,MV,P,VPd);
  return objd.template cast<Scalar>();
}

#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
// generated by autoexplicit.sh
template Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > igl::opengl2::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&);
template void igl::opengl2::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
template void igl::opengl2::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
template Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > igl::opengl2::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&);
template void igl::opengl2::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
#endif
<commit_msg>try to get rid of error for daniele<commit_after>// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "unproject.h"
#include "model_proj_viewport.h"
#include "../unproject.h"
#include "../opengl/OpenGL_convenience.h"

#include <Eigen/Dense>
#include <Eigen/LU>

IGL_INLINE void igl::opengl2::unproject(
  const double winX,
  const double winY,
  const double winZ,
  double* objX,
  double* objY,
  double* objZ)
{
  Eigen::Vector3d obj;
  igl::opengl2::unproject(Eigen::Vector3d(winX,winY,winZ),obj);
  *objX = obj(0);
  *objY = obj(1);
  *objZ = obj(2);
}

template <typename Derivedwin, typename Derivedobj>
IGL_INLINE void igl::opengl2::unproject(
  const Eigen::PlainObjectBase<Derivedwin> & win,
  Eigen::PlainObjectBase<Derivedobj> & obj)
{
  const auto ret = igl::opengl2::unproject(win);
  obj = ret.template cast<typename Derivedobj::Scalar>();
}

template <typename Derivedwin>
IGL_INLINE Eigen::PlainObjectBase<Derivedwin> igl::opengl2::unproject(
  const Eigen::PlainObjectBase<Derivedwin> & win)
{
  using namespace Eigen;
  typedef typename Derivedwin::Scalar Scalar;
  Matrix4d MV,P;
  Vector4d VPd;
  model_proj_viewport(MV,P,VPd);
  Vector3d wind = win.template cast<double>();
  Vector3d objd = igl::unproject(wind,MV,P,VPd);
  return objd.template cast<Scalar>();
}

#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
// generated by autoexplicit.sh
template Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > igl::opengl2::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&);
template void igl::opengl2::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
template void igl::opengl2::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
template Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > igl::opengl2::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&);
template void igl::opengl2::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
#endif
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkGLCMLabelMapFilter_hxx
#define itkGLCMLabelMapFilter_hxx

#include "itkGLCMLabelMapFilter.h"
#include "itkMinimumMaximumImageCalculator.h"
#include "itkHistogramToTextureFeaturesFilter.h"
#include "itkConstNeighborhoodIterator.h"

namespace itk
{
template< typename TImage, typename TFeatureImage, class TSuperclass >
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::GLCMLabelMapFilter()
{

  this->SetNumberOfRequiredInputs(2);

  this->m_Min = NumericTraits< PixelType >::max();
  this->m_Max = NumericTraits< PixelType >::NonpositiveMin();

  this->m_NumberOfBinsPerAxis = DefaultBinsPerAxis;
  this->m_Normalize = false;

  m_WindowSize.Fill( 1 );
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::SetOffset(const OffsetType &offset)
{
  OffsetVectorType offsetVector;

  offsetVector.push_back(offset);
  this->SetOffsets(offsetVector);
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::SetPixelValueMinMax(PixelType min, PixelType max)
{
  itkDebugMacro("setting Min to " << min << "and Max to " << max);
  m_Min = min;
  m_Max = max;
  this->Modified();
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::BeforeThreadedGenerateData()
{
  Superclass::BeforeThreadedGenerateData();

  if ( this->m_Min == NumericTraits< PixelType >::max()
       && this->m_Max == NumericTraits< PixelType >::NonpositiveMin() )
    {

    // get the min and max of the feature image, to use those value as the bounds
    // of our
    // histograms
    typedef MinimumMaximumImageCalculator< FeatureImageType > MinMaxCalculatorType;
    typename MinMaxCalculatorType::Pointer minMax = MinMaxCalculatorType::New();
    minMax->SetImage( this->GetFeatureImage() );
    minMax->Compute();

    m_Min = minMax->GetMinimum();
    m_Max = minMax->GetMaximum();
    }

  typename OffsetVectorType::const_iterator iter = m_Offsets.begin();
  while( iter != m_Offsets.end() )
    {
    for ( unsigned int i = 0; i < ImageDimension; ++i )
      {
      m_WindowSize[i] = std::max<typename RadiusType::SizeValueType>(m_WindowSize[i], std::abs((*iter)[i]));
      }
    ++iter;
    }
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::ThreadedProcessLabelObject(LabelObjectType *labelObject)
{
  Superclass::ThreadedProcessLabelObject(labelObject);

  typedef typename LabelObjectType::LengthType  LengthType;

  const FeatureImageType *input = this->GetFeatureImage();

  // constant for a coocurrence matrix.
  const unsigned int measurementVectorSize = 2;

  //
  // Create Histogram
  //
  typename HistogramType::Pointer histogram = HistogramType::New();

  histogram->SetMeasurementVectorSize(measurementVectorSize);

  //initialize parameters
  MeasurementVectorType lowerBound(measurementVectorSize);
  MeasurementVectorType upperBound(measurementVectorSize);

  lowerBound.Fill( this->GetMin() );
  upperBound.Fill( this->GetMax() );

  // First, create an appropriate histogram with the right number of bins
  // and mins and maxs correct for the image type.
  typename HistogramType::SizeType size( histogram->GetMeasurementVectorSize() );
  size.Fill(m_NumberOfBinsPerAxis);
  histogram->Initialize(size, lowerBound, upperBound);

  typedef Statistics::HistogramToTextureFeaturesFilter<HistogramType> FeatureFilterType;
  typename FeatureFilterType::Pointer featureFilter = FeatureFilterType::New();

  const unsigned int numLines = labelObject->GetNumberOfLines();

  // compute bounding box
  RegionType bb = input->GetLargestPossibleRegion();

  bb.ShrinkByRadius( m_WindowSize );

  typedef itk::ConstNeighborhoodIterator< FeatureImageType > NeighborhoodIteratorType;
  typename NeighborhoodIteratorType::RadiusType radius = m_WindowSize;

  NeighborhoodIteratorType nIter( radius, input, bb );
  nIter.NeedToUseBoundaryConditionOff();

  for( unsigned int l = 0; l < numLines; ++l )
    {
    typename LabelObjectType::LineType line = labelObject->GetLine(l);

    IndexType idx = line.GetIndex();
    LengthType length = line.GetLength();

    // trim line for bounding box.
    if ( bb.GetIndex(0) > idx[0] )
      {
      length -= bb.GetIndex(0) - idx[0];
      idx[0] = bb.GetIndex(0);
      }

    if ( !bb.IsInside(idx) )
      {
      break;
      }

    if ( idx[0] + (IndexValueType)length > bb.GetUpperIndex()[0] )
      {
      length = bb.GetUpperIndex()[0] - idx[0] + 1;
      }

    nIter.SetLocation( idx );

    MeasurementVectorType cooccur( histogram->GetMeasurementVectorSize() );

    for( LengthType i = 0; i < length; ++i )
      {

      const PixelType p1 = nIter.GetCenterPixel();

      // to do use more efficient neighborIndex
      typename OffsetVectorType::const_iterator iter = m_Offsets.begin();
      while( iter != m_Offsets.end() )
        {

        const PixelType p2 = nIter.GetPixel(*iter);

        if (    p1 >= m_Min
                && p2 >= m_Min
                && p1 <= m_Max
                && p2 <= m_Max )
          {
          cooccur[0] = p1;
          cooccur[1] = p2;
          histogram->IncreaseFrequencyOfMeasurement(cooccur, 1.0 );

          cooccur[1] = p1;
          cooccur[0] = p2;
          histogram->IncreaseFrequencyOfMeasurement(cooccur, 1.0 );
          }
        ++iter;
        }
      ++nIter;
      } // end label object line
    }

  featureFilter->SetInput( histogram );
  featureFilter->Modified();
  featureFilter->Update();

  labelObject->SetEnergy( featureFilter->GetEnergy() );
  labelObject->SetEntropy( featureFilter->GetEntropy() );
  labelObject->SetCorrelation( featureFilter->GetCorrelation() );
  labelObject->SetInverseDifferenceMoment( featureFilter->GetInverseDifferenceMoment() );
  labelObject->SetInertia( featureFilter->GetInertia() );
  labelObject->SetClusterShade( featureFilter->GetClusterShade() );
  labelObject->SetClusterProminence( featureFilter->GetClusterProminence() );
  labelObject->SetHaralickCorrelation( featureFilter->GetHaralickCorrelation() );

}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Min: " << this->m_Min << std::endl;
  os << indent << "Max: " << this->m_Max << std::endl;

  os << indent << "NumberOfBinsPerAxis: " << this->m_NumberOfBinsPerAxis << std::endl;
  os << indent << "Normalize: " << this->m_Normalize << std::endl;

  os << indent << "WindowSize: " << this->m_WindowSize << std::endl;

}
} // end namespace itk
#endif
<commit_msg>Fix break issue in histogram creation<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkGLCMLabelMapFilter_hxx
#define itkGLCMLabelMapFilter_hxx

#include "itkGLCMLabelMapFilter.h"
#include "itkMinimumMaximumImageCalculator.h"
#include "itkHistogramToTextureFeaturesFilter.h"
#include "itkConstNeighborhoodIterator.h"

namespace itk
{
template< typename TImage, typename TFeatureImage, class TSuperclass >
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::GLCMLabelMapFilter()
{

  this->SetNumberOfRequiredInputs(2);

  this->m_Min = NumericTraits< PixelType >::max();
  this->m_Max = NumericTraits< PixelType >::NonpositiveMin();

  this->m_NumberOfBinsPerAxis = DefaultBinsPerAxis;
  this->m_Normalize = false;

  m_WindowSize.Fill( 1 );
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::SetOffset(const OffsetType &offset)
{
  OffsetVectorType offsetVector;

  offsetVector.push_back(offset);
  this->SetOffsets(offsetVector);
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::SetPixelValueMinMax(PixelType min, PixelType max)
{
  itkDebugMacro("setting Min to " << min << "and Max to " << max);
  m_Min = min;
  m_Max = max;
  this->Modified();
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::BeforeThreadedGenerateData()
{
  Superclass::BeforeThreadedGenerateData();

  if ( this->m_Min == NumericTraits< PixelType >::max()
       && this->m_Max == NumericTraits< PixelType >::NonpositiveMin() )
    {

    // get the min and max of the feature image, to use those value as the bounds
    // of our
    // histograms
    typedef MinimumMaximumImageCalculator< FeatureImageType > MinMaxCalculatorType;
    typename MinMaxCalculatorType::Pointer minMax = MinMaxCalculatorType::New();
    minMax->SetImage( this->GetFeatureImage() );
    minMax->Compute();

    m_Min = minMax->GetMinimum();
    m_Max = minMax->GetMaximum();
    }

  typename OffsetVectorType::const_iterator iter = m_Offsets.begin();
  while( iter != m_Offsets.end() )
    {
    for ( unsigned int i = 0; i < ImageDimension; ++i )
      {
      m_WindowSize[i] = std::max<typename RadiusType::SizeValueType>(m_WindowSize[i], std::abs((*iter)[i]));
      }
    ++iter;
    }
}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::ThreadedProcessLabelObject(LabelObjectType *labelObject)
{
  Superclass::ThreadedProcessLabelObject(labelObject);

  typedef typename LabelObjectType::LengthType  LengthType;

  const FeatureImageType *input = this->GetFeatureImage();

  // constant for a coocurrence matrix.
  const unsigned int measurementVectorSize = 2;

  //
  // Create Histogram
  //
  typename HistogramType::Pointer histogram = HistogramType::New();

  histogram->SetMeasurementVectorSize(measurementVectorSize);

  //initialize parameters
  MeasurementVectorType lowerBound(measurementVectorSize);
  MeasurementVectorType upperBound(measurementVectorSize);

  lowerBound.Fill( this->GetMin() );
  upperBound.Fill( this->GetMax() );

  // First, create an appropriate histogram with the right number of bins
  // and mins and maxs correct for the image type.
  typename HistogramType::SizeType size( histogram->GetMeasurementVectorSize() );
  size.Fill(m_NumberOfBinsPerAxis);
  histogram->Initialize(size, lowerBound, upperBound);

  typedef Statistics::HistogramToTextureFeaturesFilter<HistogramType> FeatureFilterType;
  typename FeatureFilterType::Pointer featureFilter = FeatureFilterType::New();

  const unsigned int numLines = labelObject->GetNumberOfLines();

  // compute bounding box
  RegionType bb = input->GetLargestPossibleRegion();

  bb.ShrinkByRadius( m_WindowSize );

  typedef itk::ConstNeighborhoodIterator< FeatureImageType > NeighborhoodIteratorType;
  typename NeighborhoodIteratorType::RadiusType radius = m_WindowSize;

  NeighborhoodIteratorType nIter( radius, input, bb );
  nIter.NeedToUseBoundaryConditionOff();

  for( unsigned int l = 0; l < numLines; ++l )
    {
    typename LabelObjectType::LineType line = labelObject->GetLine(l);

    IndexType idx = line.GetIndex();
    LengthType length = line.GetLength();

    // trim line for bounding box.
    if ( bb.GetIndex(0) > idx[0] )
      {
      length -= bb.GetIndex(0) - idx[0];
      idx[0] = bb.GetIndex(0);
      }

    if ( !bb.IsInside(idx) )
      {
      continue;
      }

    if ( idx[0] + (IndexValueType)length > bb.GetUpperIndex()[0] )
      {
      length = bb.GetUpperIndex()[0] - idx[0] + 1;
      }

    nIter.SetLocation( idx );

    MeasurementVectorType cooccur( histogram->GetMeasurementVectorSize() );

    for( LengthType i = 0; i < length; ++i )
      {

      const PixelType p1 = nIter.GetCenterPixel();

      // to do use more efficient neighborIndex
      typename OffsetVectorType::const_iterator iter = m_Offsets.begin();
      while( iter != m_Offsets.end() )
        {

        const PixelType p2 = nIter.GetPixel(*iter);

        if (    p1 >= m_Min
                && p2 >= m_Min
                && p1 <= m_Max
                && p2 <= m_Max )
          {
          cooccur[0] = p1;
          cooccur[1] = p2;
          histogram->IncreaseFrequencyOfMeasurement(cooccur, 1.0 );

          cooccur[1] = p1;
          cooccur[0] = p2;
          histogram->IncreaseFrequencyOfMeasurement(cooccur, 1.0 );
          }
        ++iter;
        }
      ++nIter;
      } // end label object line
    }

  featureFilter->SetInput( histogram );
  featureFilter->Modified();
  featureFilter->Update();

  labelObject->SetEnergy( featureFilter->GetEnergy() );
  labelObject->SetEntropy( featureFilter->GetEntropy() );
  labelObject->SetCorrelation( featureFilter->GetCorrelation() );
  labelObject->SetInverseDifferenceMoment( featureFilter->GetInverseDifferenceMoment() );
  labelObject->SetInertia( featureFilter->GetInertia() );
  labelObject->SetClusterShade( featureFilter->GetClusterShade() );
  labelObject->SetClusterProminence( featureFilter->GetClusterProminence() );
  labelObject->SetHaralickCorrelation( featureFilter->GetHaralickCorrelation() );

}

template< typename TImage, typename TFeatureImage, class TSuperclass >
void
GLCMLabelMapFilter< TImage, TFeatureImage, TSuperclass >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Min: " << this->m_Min << std::endl;
  os << indent << "Max: " << this->m_Max << std::endl;

  os << indent << "NumberOfBinsPerAxis: " << this->m_NumberOfBinsPerAxis << std::endl;
  os << indent << "Normalize: " << this->m_Normalize << std::endl;

  os << indent << "WindowSize: " << this->m_WindowSize << std::endl;

}
} // end namespace itk
#endif
<|endoftext|>


<commit_before>/*
 * This file is part of otf2xx (https://github.com/tud-zih-energy/otf2xx)
 * otf2xx - A wrapper for the Open Trace Format 2 library
 *
 * Copyright (c) 2013-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef INCLUDE_OTF2XX_CHRONO_CONVERT_HPP
#define INCLUDE_OTF2XX_CHRONO_CONVERT_HPP

#include <otf2xx/chrono/clock.hpp>
#include <otf2xx/chrono/ticks.hpp>
#include <otf2xx/chrono/time_point.hpp>

#include <otf2xx/definition/clock_properties.hpp>

#include <cassert>
#include <cmath>
#include <limits>

namespace otf2
{
namespace chrono
{

    /**
     * \brief class to convert between ticks and time points
     *
     * This class can convert between ticks and time points.
     * For this, it needs the number of ticks per second.
     *
     * \note The time epoch is assumed to be equal between the time point and
     *       time point represented with the number ticks given.
     */
    class convert
    {
        static_assert(clock::period::num == 1, "Don't mess around with chrono!");

    public:
        convert(otf2::chrono::ticks ticks_per_second =
                    otf2::chrono::ticks(otf2::chrono::clock::period::den),
                otf2::chrono::ticks offset = otf2::chrono::ticks(0))
        : offset_(offset.count()),
          factor_(static_cast<double>(clock::period::den) / ticks_per_second.count()),
          inverse_factor_(ticks_per_second.count() / static_cast<double>(clock::period::den))
        {
            // WARNING: Be careful, when changing clock::period::den.
            // You will have to think about every calculations twice, as there
            // might be narrowing and rounding anywhere.
            // We also assumed here, that we have nanoseconds or picoseconds resolution and the
            // input resolution is about nanoseconds or a few hundred
            // picoseconds.
            // These assumptions have to be double checked!

            assert(ticks_per_second.count() <= clock::period::den);
        }

        convert(const otf2::definition::clock_properties& cp)
        : convert(cp.ticks_per_second(), cp.start_time())
        {
        }

        /**
         * \brief converts from ticks to time point
         *
         * \param[in] ticks since epoch
         * \return time_point with a duration equal to the passed time
         *         since the epoch.
         */
        otf2::chrono::time_point operator()(otf2::chrono::ticks ticks) const
        {
            // VTTI please remember that those two inputs are uint64_t and then look at the next
            // line
            assert(ticks.count() >= offset_);

            auto tp = ticks.count() - offset_;

            assert(tp < static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / factor_);

            return time_point(otf2::chrono::duration(static_cast<int64_t>(tp * factor_)));
        }

        /**
         * \brief converts from time points to ticks
         *
         * \param[in] t a time point
         * \return number ticks equal to passed time of the duration of the time
         *         point
         */
        otf2::chrono::ticks operator()(time_point t) const
        {
            auto tp = t.time_since_epoch().count();

            assert(tp <
                   static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / inverse_factor_);

            // Note 1: Using ceil here has its origins in the observation that casting from double
            // to int in the other conversion above leads to an implicit round down. Thus, we
            // counter that here with an explicit round up.
            // Note 2: Using an multiplication with the inverse yields a better performance. Though,
            // there might be cases, where a different sequence of multiplication or division
            // operations would result in lower rounding errors.
            auto tpi = static_cast<uint64_t>(std::ceil(tp * inverse_factor_));

            assert(tpi >= -offset_);

            return ticks(tpi + offset_);
        }

    private:
        const uint64_t offset_;

        double factor_;
        double inverse_factor_;
    };

    /**
     * \brief converts from std::chrono::timepoint to otf2::chrono::time_point
     *
     * \param[in] tp the std::chrono time point
     * \return the same time point as otf2::chrono::time_point
     */
    template <typename Clock, typename Duration>
    otf2::chrono::time_point convert_time_point(std::chrono::time_point<Clock, Duration> tp)
    {
        return otf2::chrono::time_point(
            std::chrono::duration_cast<otf2::chrono::clock::duration>(tp.time_since_epoch()));
    }
} // namespace chrono
} // namespace otf2

#endif // INCLUDE_OTF2XX_CHRONO_CONVERT_HPP
<commit_msg>Use explciti ctors<commit_after>/*
 * This file is part of otf2xx (https://github.com/tud-zih-energy/otf2xx)
 * otf2xx - A wrapper for the Open Trace Format 2 library
 *
 * Copyright (c) 2013-2016, Technische Universität Dresden, Germany
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef INCLUDE_OTF2XX_CHRONO_CONVERT_HPP
#define INCLUDE_OTF2XX_CHRONO_CONVERT_HPP

#include <otf2xx/chrono/clock.hpp>
#include <otf2xx/chrono/ticks.hpp>
#include <otf2xx/chrono/time_point.hpp>

#include <otf2xx/definition/clock_properties.hpp>

#include <cassert>
#include <cmath>
#include <limits>

namespace otf2
{
namespace chrono
{

    /**
     * \brief class to convert between ticks and time points
     *
     * This class can convert between ticks and time points.
     * For this, it needs the number of ticks per second.
     *
     * \note The time epoch is assumed to be equal between the time point and
     *       time point represented with the number ticks given.
     */
    class convert
    {
        static_assert(clock::period::num == 1, "Don't mess around with chrono!");

    public:
        explicit convert(otf2::chrono::ticks ticks_per_second =
                             otf2::chrono::ticks(otf2::chrono::clock::period::den),
                         otf2::chrono::ticks offset = otf2::chrono::ticks(0))
        : offset_(offset.count()),
          factor_(static_cast<double>(clock::period::den) / ticks_per_second.count()),
          inverse_factor_(ticks_per_second.count() / static_cast<double>(clock::period::den))
        {
            // WARNING: Be careful, when changing clock::period::den.
            // You will have to think about every calculations twice, as there
            // might be narrowing and rounding anywhere.
            // We also assumed here, that we have nanoseconds or picoseconds resolution and the
            // input resolution is about nanoseconds or a few hundred
            // picoseconds.
            // These assumptions have to be double checked!

            assert(ticks_per_second.count() <= clock::period::den);
        }

        explicit convert(const otf2::definition::clock_properties& cp)
        : convert(cp.ticks_per_second(), cp.start_time())
        {
        }

        /**
         * \brief converts from ticks to time point
         *
         * \param[in] ticks since epoch
         * \return time_point with a duration equal to the passed time
         *         since the epoch.
         */
        otf2::chrono::time_point operator()(otf2::chrono::ticks ticks) const
        {
            // VTTI please remember that those two inputs are uint64_t and then look at the next
            // line
            assert(ticks.count() >= offset_);

            auto tp = ticks.count() - offset_;

            assert(tp < static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / factor_);

            return time_point(otf2::chrono::duration(static_cast<int64_t>(tp * factor_)));
        }

        /**
         * \brief converts from time points to ticks
         *
         * \param[in] t a time point
         * \return number ticks equal to passed time of the duration of the time
         *         point
         */
        otf2::chrono::ticks operator()(time_point t) const
        {
            auto tp = t.time_since_epoch().count();

            assert(tp <
                   static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / inverse_factor_);

            // Note 1: Using ceil here has its origins in the observation that casting from double
            // to int in the other conversion above leads to an implicit round down. Thus, we
            // counter that here with an explicit round up.
            // Note 2: Using an multiplication with the inverse yields a better performance. Though,
            // there might be cases, where a different sequence of multiplication or division
            // operations would result in lower rounding errors.
            auto tpi = static_cast<uint64_t>(std::ceil(tp * inverse_factor_));

            assert(tpi >= -offset_);

            return ticks(tpi + offset_);
        }

    private:
        const uint64_t offset_;

        double factor_;
        double inverse_factor_;
    };

    /**
     * \brief converts from std::chrono::timepoint to otf2::chrono::time_point
     *
     * \param[in] tp the std::chrono time point
     * \return the same time point as otf2::chrono::time_point
     */
    template <typename Clock, typename Duration>
    otf2::chrono::time_point convert_time_point(std::chrono::time_point<Clock, Duration> tp)
    {
        return otf2::chrono::time_point(
            std::chrono::duration_cast<otf2::chrono::clock::duration>(tp.time_since_epoch()));
    }
} // namespace chrono
} // namespace otf2

#endif // INCLUDE_OTF2XX_CHRONO_CONVERT_HPP
<|endoftext|>


<commit_before>/*
---------------------------------------------------------------------
    The template library textwolf implements an input iterator on
    a set of XML path expressions without backward references on an
    STL conforming input iterator as source. It does no buffering
    or read ahead and is dedicated for stream processing of XML
    for a small set of XML queries.
    Stream processing in this context refers to processing the
    document without buffering anything but the current result token
    processed with its tag hierarchy information.

    Copyright (C) 2010,2011,2012,2013,2014 Patrick Frey

    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 3.0 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

--------------------------------------------------------------------

	The latest version of textwolf can be found at 'http://github.com/patrickfrey/textwolf'
	For documentation see 'http://patrickfrey.github.com/textwolf'

--------------------------------------------------------------------
*/
/// \file textwolf/staticbuffer.hpp
/// \brief Fixed size buffer fulfilling the requirement of a back insertion sequence needed for textwolf output

#ifndef __TEXTWOLF_STATIC_BUFFER_HPP__
#define __TEXTWOLF_STATIC_BUFFER_HPP__
#include "textwolf/exception.hpp"
#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <stdexcept>

namespace textwolf {

/// \class StaticBuffer
/// \brief Simple back insertion sequence for storing the outputs of textwolf in a contant size buffer
class StaticBuffer :public throws_exception
{
public:
	/// \brief Constructor
	explicit StaticBuffer( std::size_t n)
		:m_pos(0),m_size(n),m_ar(0),m_allocated(true),m_overflow(false)
	{
		m_ar = (char*)std::calloc( n, sizeof(char));
		if (!m_ar) throw std::bad_alloc();
	}

	/// \brief Constructor
	StaticBuffer( char* p, std::size_t n, std::size_t i=0)
		:m_pos(i)
		,m_size(n)
		,m_ar(p)
		,m_allocated(false)
		,m_overflow(false) {}

	/// \brief Copy constructor
	StaticBuffer( const StaticBuffer& o)
		:m_pos(o.m_pos)
		,m_size(o.m_size)
		,m_ar(0)
		,m_allocated(o.m_allocated)
		,m_overflow(o.m_overflow)
	{
		m_ar = (char*)std::malloc( m_size * sizeof(char));
		if (!m_ar) throw std::bad_alloc();
		std::memcpy( m_ar, o.m_ar, m_size);
	}

	/// \brief Destructor
	~StaticBuffer()
	{
		if (m_allocated && m_ar) std::free(m_ar);
	}

	/// \brief Clear the buffer content
	void clear()
	{
		m_pos = 0;
		m_overflow = false;
	}

	/// \brief Append one character
	/// \param[in] ch the character to append
	void push_back( char ch)
	{
		if (m_pos < m_size)
		{
			m_ar[m_pos++] = ch;
		}
		else
		{
			m_overflow = true;
		}
	}

	/// \brief Append an array of characters
	/// \param[in] cc the characters to append
	/// \param[in] ccsize the number of characters to append
	void append( const char* cc, std::size_t ccsize)
	{
		if (m_pos+ccsize > m_size)
		{
			m_overflow = true;
			ccsize = m_size - m_pos;
		}
		std::memcpy( m_ar+m_pos, cc, ccsize);
		m_pos += ccsize;
	}

	/// \brief Return the number of characters in the buffer
	/// \return the number of characters (bytes)
	std::size_t size() const		{return m_pos;}

	/// \brief Return the buffer content as 0-terminated string
	/// \return the C-string
	const char* ptr() const			{return m_ar;}

	/// \brief Shrinks the size of the buffer or expands it with c
	/// \param [in] n new size of the buffer
	/// \param [in] c fill character if n bigger than the current fill size
	void resize( std::size_t n, char c=0)
	{
		if (m_pos>n)
		{
			m_pos=n;
		}
		else
		{
			if (m_size<n) n=m_size;
			while (n>m_pos) push_back(c);
		}
	}

	/// \brief random access of element
	/// \param [in] ii
	/// \return the character at this position
	char operator []( std::size_t ii) const
	{
		if (ii > m_pos) throw exception( DimOutOfRange);
		return m_ar[ii];
	}

	/// \brief random access of element reference
	/// \param [in] ii
	/// \return the reference to the character at this position
	char& at( std::size_t ii) const
	{
		if (ii > m_pos) throw exception( DimOutOfRange);
		return m_ar[ii];
	}

	/// \brief check for array bounds write
	/// \return true if a push_back would have caused an array bounds write
	bool overflow() const			{return m_overflow;}
private:
	StaticBuffer(){}			///< non copyable
private:
	std::size_t m_pos;			///< current cursor position of the buffer (number of added characters)
	std::size_t m_size;			///< allocation size of the buffer in bytes
	char* m_ar;				///< buffer content
	bool m_allocated;			///< true, if the buffer is allocated by this class and not passed by constructor
	bool m_overflow;			///< true, if an array bounds write would have happened with push_back
};

}//namespace
#endif
<commit_msg>fixed missing #include <new> for std::bad_alloc (fix for OSX)<commit_after>/*
---------------------------------------------------------------------
    The template library textwolf implements an input iterator on
    a set of XML path expressions without backward references on an
    STL conforming input iterator as source. It does no buffering
    or read ahead and is dedicated for stream processing of XML
    for a small set of XML queries.
    Stream processing in this context refers to processing the
    document without buffering anything but the current result token
    processed with its tag hierarchy information.

    Copyright (C) 2010,2011,2012,2013,2014 Patrick Frey

    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 3.0 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

--------------------------------------------------------------------

	The latest version of textwolf can be found at 'http://github.com/patrickfrey/textwolf'
	For documentation see 'http://patrickfrey.github.com/textwolf'

--------------------------------------------------------------------
*/
/// \file textwolf/staticbuffer.hpp
/// \brief Fixed size buffer fulfilling the requirement of a back insertion sequence needed for textwolf output

#ifndef __TEXTWOLF_STATIC_BUFFER_HPP__
#define __TEXTWOLF_STATIC_BUFFER_HPP__
#include "textwolf/exception.hpp"
#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <stdexcept>
#include <new>

namespace textwolf {

/// \class StaticBuffer
/// \brief Simple back insertion sequence for storing the outputs of textwolf in a contant size buffer
class StaticBuffer :public throws_exception
{
public:
	/// \brief Constructor
	explicit StaticBuffer( std::size_t n)
		:m_pos(0),m_size(n),m_ar(0),m_allocated(true),m_overflow(false)
	{
		m_ar = (char*)std::calloc( n, sizeof(char));
		if (!m_ar) throw std::bad_alloc();
	}

	/// \brief Constructor
	StaticBuffer( char* p, std::size_t n, std::size_t i=0)
		:m_pos(i)
		,m_size(n)
		,m_ar(p)
		,m_allocated(false)
		,m_overflow(false) {}

	/// \brief Copy constructor
	StaticBuffer( const StaticBuffer& o)
		:m_pos(o.m_pos)
		,m_size(o.m_size)
		,m_ar(0)
		,m_allocated(o.m_allocated)
		,m_overflow(o.m_overflow)
	{
		m_ar = (char*)std::malloc( m_size * sizeof(char));
		if (!m_ar) throw std::bad_alloc();
		std::memcpy( m_ar, o.m_ar, m_size);
	}

	/// \brief Destructor
	~StaticBuffer()
	{
		if (m_allocated && m_ar) std::free(m_ar);
	}

	/// \brief Clear the buffer content
	void clear()
	{
		m_pos = 0;
		m_overflow = false;
	}

	/// \brief Append one character
	/// \param[in] ch the character to append
	void push_back( char ch)
	{
		if (m_pos < m_size)
		{
			m_ar[m_pos++] = ch;
		}
		else
		{
			m_overflow = true;
		}
	}

	/// \brief Append an array of characters
	/// \param[in] cc the characters to append
	/// \param[in] ccsize the number of characters to append
	void append( const char* cc, std::size_t ccsize)
	{
		if (m_pos+ccsize > m_size)
		{
			m_overflow = true;
			ccsize = m_size - m_pos;
		}
		std::memcpy( m_ar+m_pos, cc, ccsize);
		m_pos += ccsize;
	}

	/// \brief Return the number of characters in the buffer
	/// \return the number of characters (bytes)
	std::size_t size() const		{return m_pos;}

	/// \brief Return the buffer content as 0-terminated string
	/// \return the C-string
	const char* ptr() const			{return m_ar;}

	/// \brief Shrinks the size of the buffer or expands it with c
	/// \param [in] n new size of the buffer
	/// \param [in] c fill character if n bigger than the current fill size
	void resize( std::size_t n, char c=0)
	{
		if (m_pos>n)
		{
			m_pos=n;
		}
		else
		{
			if (m_size<n) n=m_size;
			while (n>m_pos) push_back(c);
		}
	}

	/// \brief random access of element
	/// \param [in] ii
	/// \return the character at this position
	char operator []( std::size_t ii) const
	{
		if (ii > m_pos) throw exception( DimOutOfRange);
		return m_ar[ii];
	}

	/// \brief random access of element reference
	/// \param [in] ii
	/// \return the reference to the character at this position
	char& at( std::size_t ii) const
	{
		if (ii > m_pos) throw exception( DimOutOfRange);
		return m_ar[ii];
	}

	/// \brief check for array bounds write
	/// \return true if a push_back would have caused an array bounds write
	bool overflow() const			{return m_overflow;}
private:
	StaticBuffer(){}			///< non copyable
private:
	std::size_t m_pos;			///< current cursor position of the buffer (number of added characters)
	std::size_t m_size;			///< allocation size of the buffer in bytes
	char* m_ar;				///< buffer content
	bool m_allocated;			///< true, if the buffer is allocated by this class and not passed by constructor
	bool m_overflow;			///< true, if an array bounds write would have happened with push_back
};

}//namespace
#endif
<|endoftext|>


<commit_before>#ifndef ORG_EEROS_CONTROL_OUTPUT_HPP_
#define ORG_EEROS_CONTROL_OUTPUT_HPP_

#include <eeros/control/Signal.hpp>
#include <eeros/control/Block.hpp>

namespace eeros {
namespace control {

/**
 * Blocks can have inputs and outputs. This is the output class.
 * An output carries a signal. One or several inputs of other blocks
 * can be connected to this output.
 *
 * @tparam T - signal type (double - default type)
 * @since v0.4
 */

template < typename T = double >
class Output {
 public:
  /**
   * Constructs an output instance.
   */
  Output() : owner(nullptr) { }

  /**
   * Constructs an output instance.
   *
   * @param owner - the block which owns this output
   */
  Output(Block* owner) : owner(owner) { }

  /**
   * Returns the signal which is carried by this output.
   *
   * @return signal
   */
  virtual Signal<T>& getSignal() {
    return signal;
  }

  /**
   * Every input is owned by a block. Sets the owner of this input.
   *
   * @param block - owner of this input
   */
  virtual void setOwner(Block* block) {
    owner = block;
  }

 private:
  Signal<T> signal;
  Block* owner;
};

}
}

#endif /* ORG_EEROS_CONTROL_OUTPUT_HPP_ */
<commit_msg>Update Output.hpp<commit_after>#ifndef ORG_EEROS_CONTROL_OUTPUT_HPP_
#define ORG_EEROS_CONTROL_OUTPUT_HPP_

#include <eeros/control/Signal.hpp>
#include <eeros/control/Block.hpp>

namespace eeros {
namespace control {

/**
 * Blocks can have inputs and outputs. This is the output class.
 * An output carries a signal. One or several inputs of other blocks
 * can be connected to this output.
 *
 * @tparam T - signal type (double - default type)
 * @since v0.4
 */

template < typename T = double >
class Output {
 public:
  /**
   * Constructs an output instance.
   */
  Output() : owner(nullptr) { }

  /**
   * Constructs an output instance.
   *
   * @param owner - the block which owns this output
   */
  Output(Block* owner) : owner(owner) { }

  /**
   * Returns the signal which is carried by this output.
   *
   * @return signal
   */
  virtual Signal<T>& getSignal() {
    return signal;
  }

  /**
   * Every output is owned by a block. Sets the owner of this output.
   *
   * @param block - owner of this output
   */
  virtual void setOwner(Block* block) {
    owner = block;
  }

 private:
  Signal<T> signal;
  Block* owner;
};

}
}

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