<commit_before>#pragma once
/**
	@file
	@brief pseudrandom generator
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/

#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp>
#endif
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <wincrypt.h>
#ifdef _MSC_VER
#pragma comment (lib, "advapi32.lib")
#endif
#include <cybozu/critical_section.hpp>
#else
#include <sys/types.h>
#include <fcntl.h>
#endif

namespace cybozu {

class RandomGenerator {
	RandomGenerator(const RandomGenerator&);
	void operator=(const RandomGenerator&);
public:
#ifdef _WIN32
	RandomGenerator()
		: prov_(0)
		, pos_(bufSize)
	{
		DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET };
		for (int i = 0; i < 2; i++) {
			if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return;
		}
#ifdef CYBOZU_DONT_USE_EXCEPTION
		prov_ = 0;
#else
		throw cybozu::Exception("randomgenerator");
#endif
	}
	bool read_inner(void *buf, size_t byteSize)
	{
		if (prov_ == 0) return false;
		return CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) != 0;
	}
	~RandomGenerator()
	{
		if (prov_) {
			CryptReleaseContext(prov_, 0);
		}
	}
	/*
		fill buf[0..bufNum-1] with random data
		@note bufNum is not byte size
	*/
	template<class T>
	void read(bool *pb, T *buf, size_t bufNum)
	{
		cybozu::AutoLockCs al(cs_);
		const size_t byteSize = sizeof(T) * bufNum;
		if (byteSize > bufSize) {
			if (!read_inner(buf, byteSize)) {
				*pb = false;
				return;
			}
		} else {
			if (pos_ + byteSize > bufSize) {
				read_inner(buf_, bufSize);
				pos_ = 0;
			}
			memcpy(buf, buf_ + pos_, byteSize);
			pos_ += byteSize;
		}
		*pb = true;
	}
private:
	HCRYPTPROV prov_;
	static const size_t bufSize = 1024;
	char buf_[bufSize];
	size_t pos_;
	cybozu::CriticalSection cs_;
#else
	RandomGenerator()
		: fp_(::fopen("/dev/urandom", "rb"))
	{
#ifndef CYBOZU_DONT_USE_EXCEPTION
		if (!fp_) throw cybozu::Exception("randomgenerator");
#endif
	}
	~RandomGenerator()
	{
		if (fp_) ::fclose(fp_);
	}
	/*
		fill buf[0..bufNum-1] with random data
		@note bufNum is not byte size
	*/
	template<class T>
	void read(bool *pb, T *buf, size_t bufNum)
	{
		const size_t byteSize = sizeof(T) * bufNum;
		*pb = ::fread(buf, 1, (int)byteSize, fp_) == byteSize;
	}
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
	template<class T>
	void read(T *buf, size_t bufNum)
	{
		bool b;
		read(&b, buf, bufNum);
		if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum;
	}
	uint32_t get32()
	{
		uint32_t ret;
		read(&ret, 1);
		return ret;
	}
	uint64_t get64()
	{
		uint64_t ret;
		read(&ret, 1);
		return ret;
	}
	uint32_t operator()()
	{
		return get32();
	}
#endif
private:
	FILE *fp_;
};

template<class T, class RG>
void shuffle(T* v, size_t n, RG& rg)
{
	if (n <= 1) return;
	for (size_t i = 0; i < n - 1; i++) {
		size_t r = i + size_t(rg.get64() % (n - i));
		using namespace std;
		swap(v[i], v[r]);
	}
}

template<class V, class RG>
void shuffle(V& v, RG& rg)
{
	shuffle(v.data(), v.size(), rg);
}

} // cybozu
<commit_msg>return false if RandomGenerator fails init<commit_after>#pragma once
/**
	@file
	@brief pseudrandom generator
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/

#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp>
#endif
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <wincrypt.h>
#ifdef _MSC_VER
#pragma comment (lib, "advapi32.lib")
#endif
#include <cybozu/critical_section.hpp>
#else
#include <sys/types.h>
#include <fcntl.h>
#endif

namespace cybozu {

class RandomGenerator {
	RandomGenerator(const RandomGenerator&);
	void operator=(const RandomGenerator&);
public:
#ifdef _WIN32
	RandomGenerator()
		: prov_(0)
		, pos_(bufSize)
	{
		DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET };
		for (int i = 0; i < 2; i++) {
			if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return;
		}
#ifdef CYBOZU_DONT_USE_EXCEPTION
		prov_ = 0;
#else
		throw cybozu::Exception("randomgenerator");
#endif
	}
	bool read_inner(void *buf, size_t byteSize)
	{
		if (prov_ == 0) return false;
		return CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) != 0;
	}
	~RandomGenerator()
	{
		if (prov_) {
			CryptReleaseContext(prov_, 0);
		}
	}
	/*
		fill buf[0..bufNum-1] with random data
		@note bufNum is not byte size
	*/
	template<class T>
	void read(bool *pb, T *buf, size_t bufNum)
	{
		cybozu::AutoLockCs al(cs_);
		const size_t byteSize = sizeof(T) * bufNum;
		if (byteSize > bufSize) {
			if (!read_inner(buf, byteSize)) {
				*pb = false;
				return;
			}
		} else {
			if (pos_ + byteSize > bufSize) {
				read_inner(buf_, bufSize);
				pos_ = 0;
			}
			memcpy(buf, buf_ + pos_, byteSize);
			pos_ += byteSize;
		}
		*pb = true;
	}
private:
	HCRYPTPROV prov_;
	static const size_t bufSize = 1024;
	char buf_[bufSize];
	size_t pos_;
	cybozu::CriticalSection cs_;
#else
	RandomGenerator()
		: fp_(::fopen("/dev/urandom", "rb"))
	{
#ifndef CYBOZU_DONT_USE_EXCEPTION
		if (!fp_) throw cybozu::Exception("randomgenerator");
#endif
	}
	~RandomGenerator()
	{
		if (fp_) ::fclose(fp_);
	}
	/*
		fill buf[0..bufNum-1] with random data
		@note bufNum is not byte size
	*/
	template<class T>
	void read(bool *pb, T *buf, size_t bufNum)
	{
		if (fp_ == 0) {
			*pb = false;
			return;
		}
		const size_t byteSize = sizeof(T) * bufNum;
		*pb = ::fread(buf, 1, (int)byteSize, fp_) == byteSize;
	}
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
	template<class T>
	void read(T *buf, size_t bufNum)
	{
		bool b;
		read(&b, buf, bufNum);
		if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum;
	}
	uint32_t get32()
	{
		uint32_t ret;
		read(&ret, 1);
		return ret;
	}
	uint64_t get64()
	{
		uint64_t ret;
		read(&ret, 1);
		return ret;
	}
	uint32_t operator()()
	{
		return get32();
	}
#endif
private:
	FILE *fp_;
};

template<class T, class RG>
void shuffle(T* v, size_t n, RG& rg)
{
	if (n <= 1) return;
	for (size_t i = 0; i < n - 1; i++) {
		size_t r = i + size_t(rg.get64() % (n - i));
		using namespace std;
		swap(v[i], v[r]);
	}
}

template<class V, class RG>
void shuffle(V& v, RG& rg)
{
	shuffle(v.data(), v.size(), rg);
}

} // cybozu
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef PANDORA_PSIZE_H
#define PANDORA_PSIZE_H

#include <stdexcept>
#include <algorithm>
#include <initializer_list>

namespace nix {
namespace hdf5 {

template<typename T>
class PSizeBase {

public:

    typedef T        value_type;
    typedef T       *iterator;
    typedef const T *const_iterator;
    typedef T       &reference;
    typedef const T  const_reference;
    typedef T       *pointer;
    typedef size_t   difference_type;
    typedef size_t   size_type;

    PSizeBase()
        : rank(0), dims(nullptr)
    {
    }

    explicit PSizeBase(size_t _rank)
        : rank(_rank), dims(nullptr)
    {
        allocate();
    }

    explicit PSizeBase(size_t _rank, T fillValue)
        : rank(_rank), dims(nullptr)
    {
        allocate();
        fill(fillValue);
    }

    PSizeBase(std::initializer_list<T> args)
        : rank(args.size())
    {
        allocate();
        std::copy(args.begin(), args.end(), dims);
    }

    //copy
    PSizeBase(const PSizeBase &other)
        : rank(other.rank), dims(nullptr)
    {
        allocate();
        std::copy(other.dims, other.dims + rank, dims);
    }

    //move (not tested due to: http://llvm.org/bugs/show_bug.cgi?id=12208)
    PSizeBase(PSizeBase &&other)
        : rank(other.rank), dims(other.dims)
    {
        other.dims = nullptr;
        other.rank = 0;
    }

    //copy and move assignment operator (not tested, see above)
    PSizeBase& operator=(PSizeBase other) {
        swap(other);
        return *this;
    }

    T& operator[] (const size_t index) {
        const PSizeBase *this_const = const_cast<const PSizeBase*>(this);
        return const_cast<T&>(this_const->operator[](index));
    }

    const T& operator[] (const size_t index) const {
        if (index + 1 > rank) {
            throw std::out_of_range ("Index out of bounds");
        }
        return dims[index];
    }

    PSizeBase<T>& operator++() {
        std::for_each(begin(), end(), [](T &val) {
            val++;
        });
        return *this;
    }

    PSizeBase<T> operator++(int) {
        PSizeBase<T> snapshot(*this);
        operator++();
        return snapshot;
    }

    PSizeBase<T>& operator+=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] += rhs.dims[i];
        }

        return *this;
    }

    PSizeBase<T>& operator+=(T val) {
        for (size_t i = 0; i < rank; i++) {
            dims[i] += val;
        }

        return *this;
    }

    PSizeBase<T>& operator+=(int val) {
        return operator+=(static_cast<T>(val));
    }

    PSizeBase<T>& operator--() {
        std::for_each(begin(), end(), [](T &val) {
            val--;
        });
        return *this;
    }

    PSizeBase<T> operator--(int) {
        PSizeBase<T> snapshot(*this);
        operator--();
        return snapshot;
    }

    PSizeBase<T>& operator-=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] -= rhs.dims[i];
        }

        return *this;
    }

    PSizeBase<T>& operator-=(T val) {
        for (size_t i = 0; i < rank; i++) {
            dims[i] -= val;
        }

        return *this;
    }

    PSizeBase<T>& operator-=(int val) {
        return operator-=(static_cast<T>(val));
    }

    void swap(PSizeBase &other) {
        using std::swap;
        swap(dims, other.dims);
        rank = other.rank;
    }

    PSizeBase<T>& operator*=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] *= rhs.dims[i];
        }

        return *this;
    }

    PSizeBase<T>& operator/=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] /= rhs.dims[i];
        }

        return *this;
    }

    size_t size() const { return rank; }

    size_t nelms() const {
        size_t product = 1;
        std::for_each(begin(), end(), [&](T val) {
            product *= val;
        });
        return product;
    }

    size_t dot(const PSizeBase<T> &other) const {
        if(size() != other.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        size_t res  = 0;
        for (size_t i = 0; i < rank; i++) {
            res += dims[i] * other.dims[i];
        }

        return res;
    }

    T* data() { return dims; }

    const T* data() const {return dims; }

    void fill(T value) {
        std::fill_n(dims, rank, value);
    }

    ~PSizeBase(){
        delete[] dims;
    }

    //we are modelling a boost::Collection
    iterator begin() { return dims; }

    iterator end() { return dims + rank; }

    const_iterator begin() const { return dims; }

    const_iterator end() const { return dims + rank; }

    bool empty() const { return rank == 0; }

private:

    void allocate() {
        if (rank > 0) {
            dims = new T[rank];
        }
    }

    size_t   rank;
    T *dims;
};

template<typename T>
PSizeBase<T> operator-(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs -= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs += rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(PSizeBase<T> lhs, T rhs)
{
    lhs += rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(T lhs, const PSizeBase<T> &rhs)
{
    return operator+(rhs, lhs);
}

template<typename T>
PSizeBase<T> operator+(PSizeBase<T> lhs, int rhs)
{
    lhs += rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(int lhs, const PSizeBase<T> &rhs)
{
    return operator+(rhs, lhs);
}

template<typename T>
PSizeBase<T> operator*(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs *= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator*(PSizeBase<T> lhs, T rhs)
{
    lhs *= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator*(T lhs, const PSizeBase<T> &rhs)
{
    return operator*(rhs, lhs);
}

template<typename T>
PSizeBase<T> operator/(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs /= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator/(PSizeBase<T> lhs, T rhs)
{
    lhs /= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator/(T lhs, const PSizeBase<T> &rhs)
{
    return operator/(rhs, lhs);
}

template<typename T>
inline bool operator==(const PSizeBase<T> &lhs, const PSizeBase<T> &rhs)
{
    if (lhs.size() != rhs.size())
        return false;

    for (size_t i = 0; i < lhs.size(); i++) {
        if (lhs[i] != rhs[i])
            return false;
    }

    return true;
}

template<typename T>
inline bool operator!=(const PSizeBase<T> &lhs, const PSizeBase<T> &rhs)
{
    return !operator==(lhs, rhs);
}

/* *****  */

typedef PSizeBase<hsize_t>  PSize;

typedef PSizeBase<hssize_t> PSSize;

} // namespace hdf5
} // namespace nix

#endif // PANDORA_PSIZE_H
<commit_msg>PSize: Use (u)int64_t as inner type instead of h(s)size_t<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef PANDORA_PSIZE_H
#define PANDORA_PSIZE_H

#include <cstdint>
#include <stdexcept>
#include <algorithm>
#include <initializer_list>

namespace nix {
namespace hdf5 {

template<typename T>
class PSizeBase {

public:

    typedef T        value_type;
    typedef T       *iterator;
    typedef const T *const_iterator;
    typedef T       &reference;
    typedef const T  const_reference;
    typedef T       *pointer;
    typedef size_t   difference_type;
    typedef size_t   size_type;

    PSizeBase()
        : rank(0), dims(nullptr)
    {
    }

    explicit PSizeBase(size_t _rank)
        : rank(_rank), dims(nullptr)
    {
        allocate();
    }

    explicit PSizeBase(size_t _rank, T fillValue)
        : rank(_rank), dims(nullptr)
    {
        allocate();
        fill(fillValue);
    }

    PSizeBase(std::initializer_list<T> args)
        : rank(args.size())
    {
        allocate();
        std::copy(args.begin(), args.end(), dims);
    }

    //copy
    PSizeBase(const PSizeBase &other)
        : rank(other.rank), dims(nullptr)
    {
        allocate();
        std::copy(other.dims, other.dims + rank, dims);
    }

    //move (not tested due to: http://llvm.org/bugs/show_bug.cgi?id=12208)
    PSizeBase(PSizeBase &&other)
        : rank(other.rank), dims(other.dims)
    {
        other.dims = nullptr;
        other.rank = 0;
    }

    //copy and move assignment operator (not tested, see above)
    PSizeBase& operator=(PSizeBase other) {
        swap(other);
        return *this;
    }

    T& operator[] (const size_t index) {
        const PSizeBase *this_const = const_cast<const PSizeBase*>(this);
        return const_cast<T&>(this_const->operator[](index));
    }

    const T& operator[] (const size_t index) const {
        if (index + 1 > rank) {
            throw std::out_of_range ("Index out of bounds");
        }
        return dims[index];
    }

    PSizeBase<T>& operator++() {
        std::for_each(begin(), end(), [](T &val) {
            val++;
        });
        return *this;
    }

    PSizeBase<T> operator++(int) {
        PSizeBase<T> snapshot(*this);
        operator++();
        return snapshot;
    }

    PSizeBase<T>& operator+=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] += rhs.dims[i];
        }

        return *this;
    }

    PSizeBase<T>& operator+=(T val) {
        for (size_t i = 0; i < rank; i++) {
            dims[i] += val;
        }

        return *this;
    }

    PSizeBase<T>& operator+=(int val) {
        return operator+=(static_cast<T>(val));
    }

    PSizeBase<T>& operator--() {
        std::for_each(begin(), end(), [](T &val) {
            val--;
        });
        return *this;
    }

    PSizeBase<T> operator--(int) {
        PSizeBase<T> snapshot(*this);
        operator--();
        return snapshot;
    }

    PSizeBase<T>& operator-=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] -= rhs.dims[i];
        }

        return *this;
    }

    PSizeBase<T>& operator-=(T val) {
        for (size_t i = 0; i < rank; i++) {
            dims[i] -= val;
        }

        return *this;
    }

    PSizeBase<T>& operator-=(int val) {
        return operator-=(static_cast<T>(val));
    }

    void swap(PSizeBase &other) {
        using std::swap;
        swap(dims, other.dims);
        rank = other.rank;
    }

    PSizeBase<T>& operator*=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] *= rhs.dims[i];
        }

        return *this;
    }

    PSizeBase<T>& operator/=(const PSizeBase<T> &rhs) {
        if(size() != rhs.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        for (size_t i = 0; i < rank; i++) {
            dims[i] /= rhs.dims[i];
        }

        return *this;
    }

    size_t size() const { return rank; }

    size_t nelms() const {
        size_t product = 1;
        std::for_each(begin(), end(), [&](T val) {
            product *= val;
        });
        return product;
    }

    size_t dot(const PSizeBase<T> &other) const {
        if(size() != other.size()) {
            throw std::out_of_range (""); //fixme: use different exception
        }

        size_t res  = 0;
        for (size_t i = 0; i < rank; i++) {
            res += dims[i] * other.dims[i];
        }

        return res;
    }

    T* data() { return dims; }

    const T* data() const {return dims; }

    void fill(T value) {
        std::fill_n(dims, rank, value);
    }

    ~PSizeBase(){
        delete[] dims;
    }

    //we are modelling a boost::Collection
    iterator begin() { return dims; }

    iterator end() { return dims + rank; }

    const_iterator begin() const { return dims; }

    const_iterator end() const { return dims + rank; }

    bool empty() const { return rank == 0; }

private:

    void allocate() {
        if (rank > 0) {
            dims = new T[rank];
        }
    }

    size_t   rank;
    T *dims;
};

template<typename T>
PSizeBase<T> operator-(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs -= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs += rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(PSizeBase<T> lhs, T rhs)
{
    lhs += rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(T lhs, const PSizeBase<T> &rhs)
{
    return operator+(rhs, lhs);
}

template<typename T>
PSizeBase<T> operator+(PSizeBase<T> lhs, int rhs)
{
    lhs += rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator+(int lhs, const PSizeBase<T> &rhs)
{
    return operator+(rhs, lhs);
}

template<typename T>
PSizeBase<T> operator*(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs *= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator*(PSizeBase<T> lhs, T rhs)
{
    lhs *= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator*(T lhs, const PSizeBase<T> &rhs)
{
    return operator*(rhs, lhs);
}

template<typename T>
PSizeBase<T> operator/(PSizeBase<T> lhs, const PSizeBase<T> &rhs)
{
    lhs /= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator/(PSizeBase<T> lhs, T rhs)
{
    lhs /= rhs;
    return lhs;
}

template<typename T>
PSizeBase<T> operator/(T lhs, const PSizeBase<T> &rhs)
{
    return operator/(rhs, lhs);
}

template<typename T>
inline bool operator==(const PSizeBase<T> &lhs, const PSizeBase<T> &rhs)
{
    if (lhs.size() != rhs.size())
        return false;

    for (size_t i = 0; i < lhs.size(); i++) {
        if (lhs[i] != rhs[i])
            return false;
    }

    return true;
}

template<typename T>
inline bool operator!=(const PSizeBase<T> &lhs, const PSizeBase<T> &rhs)
{
    return !operator==(lhs, rhs);
}

/* *****  */

typedef PSizeBase<uint64_t>  PSize;

typedef PSizeBase<int64_t> PSSize;

} // namespace hdf5
} // namespace nix

#endif // PANDORA_PSIZE_H
<|endoftext|>


<commit_before>#ifndef DAVIX_DEPRECATED
#define DAVIX_DEPRECATED

#include <vector>
#include <string>
#include <utils/davix_types.hpp>
#include <utils/davix_uri.hpp>

#ifndef __DAVIX_INSIDE__
#error "Only davix.h or davix.hpp should be included."
#endif

/**
  @file deprecated.hpp
  @author Devresse Adrien

  @brief Deprecated class / functions of Davix for ABI/ API compatibility

   Each call to one of these function kill a kitten.
   Please love kittens and don't use them
 */

namespace Davix {

struct HttpCacheTokenInternal;

class DAVIX_EXPORT HttpCacheToken
{
public:

    HttpCacheToken();

    HttpCacheToken(const HttpCacheToken & orig);

    virtual ~HttpCacheToken();

    HttpCacheToken & operator=(const HttpCacheToken &);

    const Uri & getrequestUri() const;

    const Uri & getCachedRedirection() const;
private:
    HttpCacheTokenInternal* d_ptr;

    friend struct HttpCacheTokenAccessor;
};

class DAVIX_EXPORT FileInfoInterface{
public:
    virtual ~FileInfoInterface(){}

    virtual const std::type_info & getType() =0;

    virtual FileInfoInterface* getClone() = 0;
};

template <class T>
class DAVIX_EXPORT FileInfo : public FileInfoInterface{
public:
    virtual ~FileInfo(){}

    virtual const std::type_info & getType(){
        return typeid(*static_cast<T*>(this));
    }

    virtual FileInfoInterface* getClone(){
        return new T(*static_cast<T*>(this));
    }
};

class DAVIX_EXPORT FileInfoSize :
        public FileInfo<FileInfoSize>{
public:
    FileInfoSize() : size(0){}
    FileInfoSize(dav_size_t s) : size(s){}
    FileInfoSize(const FileInfoSize & orig) : size(orig.size) {}
    virtual ~FileInfoSize(){}
    dav_size_t size;
};

class DAVIX_EXPORT FileInfoHash :
    public FileInfo<FileInfoHash>{
public:
    FileInfoHash(const FileInfoHash & orig) : hash(orig.hash), hash_type(orig.hash_type) {}
    virtual ~FileInfoHash(){}
    std::string hash;
    std::string hash_type;
};

class DAVIX_EXPORT FileInfoName :
    public FileInfo<FileInfoName>{
public:
    FileInfoName(const FileInfoName & orig) : name(orig.name){}
    virtual ~FileInfoName(){}
    std::string name;
};

class DAVIX_EXPORT FileInfoProtocolType :
    public FileInfo<FileInfoProtocolType>{
public:
    FileInfoProtocolType() : protocol(){}
    FileInfoProtocolType(const FileInfoProtocolType & orig) : protocol(orig.protocol){}
    FileInfoProtocolType(const std::string & s) : protocol(s){}
    virtual ~FileInfoProtocolType(){}
    std::string protocol;
};

typedef std::vector<FileInfoInterface*> Properties;

class DAVIX_EXPORT Replica {
public:
    Replica() :
        uri(),
        props(){}
    Replica(const Replica & orig) :
        uri(orig.uri),
        props() {
        props.reserve(orig.props.size());
        for(Properties::iterator it = props.begin(); it < props.end(); ++it){
            props.push_back((*it)->getClone());
        }
    }

    virtual ~Replica(){
        for(Properties::iterator it = props.begin(); it < props.end(); ++it)
            delete *it;
    }

    Uri uri;
    Properties props;
};

typedef std::deque<Replica> ReplicaVec;

struct HookIntern;

///
/// \brief The HookTraits class
///
///  Base class for Daivx Hook functions
///
struct HookTraits{
    HookTraits();
    virtual ~HookTraits();

    virtual std::type_info & getType() =0;

    // internal
    HookIntern* d_ptr;
};

template <class T>
struct Hook: HookTraits{
    virtual std::type_info & getType(){
        return typeid(*static_cast<T>(this));
    }
};

class HttpRequest;

typedef void (*CallbackHeader)(HttpRequest &, const std::string &, std::string &);

struct HookSendHeader : public Hook<HookSendHeader>{
    CallbackHeader hook;
};

struct HookReceiveHeader : public Hook<HookReceiveHeader>{
    CallbackHeader hook;
};

typedef void (*CallbackRequestExec)(HttpRequest &);

struct HookRequestPreExec : public Hook<HookRequestPreExec>{
    CallbackRequestExec hook;
};

struct HookRequestPostExec : public Hook<HookRequestPostExec>{
    CallbackRequestExec hook;
};

} // namespace Davix

#endif
<commit_msg>- fix compilation error on clang due to const reference on typeinfo<commit_after>#ifndef DAVIX_DEPRECATED
#define DAVIX_DEPRECATED

#include <vector>
#include <string>
#include <utils/davix_types.hpp>
#include <utils/davix_uri.hpp>

#ifndef __DAVIX_INSIDE__
#error "Only davix.h or davix.hpp should be included."
#endif

/**
  @file deprecated.hpp
  @author Devresse Adrien

  @brief Deprecated class / functions of Davix for ABI/ API compatibility

   Each call to one of these function kill a kitten.
   Please love kittens and don't use them
 */

namespace Davix {

struct HttpCacheTokenInternal;

class DAVIX_EXPORT HttpCacheToken
{
public:

    HttpCacheToken();

    HttpCacheToken(const HttpCacheToken & orig);

    virtual ~HttpCacheToken();

    HttpCacheToken & operator=(const HttpCacheToken &);

    const Uri & getrequestUri() const;

    const Uri & getCachedRedirection() const;
private:
    HttpCacheTokenInternal* d_ptr;

    friend struct HttpCacheTokenAccessor;
};

class DAVIX_EXPORT FileInfoInterface{
public:
    virtual ~FileInfoInterface(){}

    virtual const std::type_info & getType() =0;

    virtual FileInfoInterface* getClone() = 0;
};

template <class T>
class DAVIX_EXPORT FileInfo : public FileInfoInterface{
public:
    virtual ~FileInfo(){}

    virtual const std::type_info & getType(){
        return typeid(*static_cast<T*>(this));
    }

    virtual FileInfoInterface* getClone(){
        return new T(*static_cast<T*>(this));
    }
};

class DAVIX_EXPORT FileInfoSize :
        public FileInfo<FileInfoSize>{
public:
    FileInfoSize() : size(0){}
    FileInfoSize(dav_size_t s) : size(s){}
    FileInfoSize(const FileInfoSize & orig) : size(orig.size) {}
    virtual ~FileInfoSize(){}
    dav_size_t size;
};

class DAVIX_EXPORT FileInfoHash :
    public FileInfo<FileInfoHash>{
public:
    FileInfoHash(const FileInfoHash & orig) : hash(orig.hash), hash_type(orig.hash_type) {}
    virtual ~FileInfoHash(){}
    std::string hash;
    std::string hash_type;
};

class DAVIX_EXPORT FileInfoName :
    public FileInfo<FileInfoName>{
public:
    FileInfoName(const FileInfoName & orig) : name(orig.name){}
    virtual ~FileInfoName(){}
    std::string name;
};

class DAVIX_EXPORT FileInfoProtocolType :
    public FileInfo<FileInfoProtocolType>{
public:
    FileInfoProtocolType() : protocol(){}
    FileInfoProtocolType(const FileInfoProtocolType & orig) : protocol(orig.protocol){}
    FileInfoProtocolType(const std::string & s) : protocol(s){}
    virtual ~FileInfoProtocolType(){}
    std::string protocol;
};

typedef std::vector<FileInfoInterface*> Properties;

class DAVIX_EXPORT Replica {
public:
    Replica() :
        uri(),
        props(){}
    Replica(const Replica & orig) :
        uri(orig.uri),
        props() {
        props.reserve(orig.props.size());
        for(Properties::iterator it = props.begin(); it < props.end(); ++it){
            props.push_back((*it)->getClone());
        }
    }

    virtual ~Replica(){
        for(Properties::iterator it = props.begin(); it < props.end(); ++it)
            delete *it;
    }

    Uri uri;
    Properties props;
};

typedef std::deque<Replica> ReplicaVec;

struct HookIntern;

///
/// \brief The HookTraits class
///
///  Base class for Daivx Hook functions
///
struct HookTraits{
    HookTraits();
    virtual ~HookTraits();

    virtual const std::type_info & getType() =0;

    // internal
    HookIntern* d_ptr;
};

template <class T>
struct Hook: HookTraits{
    virtual const std::type_info & getType(){
        return typeid(*static_cast<T>(this));
    }
};

class HttpRequest;

typedef void (*CallbackHeader)(HttpRequest &, const std::string &, std::string &);

struct HookSendHeader : public Hook<HookSendHeader>{
    CallbackHeader hook;
};

struct HookReceiveHeader : public Hook<HookReceiveHeader>{
    CallbackHeader hook;
};

typedef void (*CallbackRequestExec)(HttpRequest &);

struct HookRequestPreExec : public Hook<HookRequestPreExec>{
    CallbackRequestExec hook;
};

struct HookRequestPostExec : public Hook<HookRequestPostExec>{
    CallbackRequestExec hook;
};

} // namespace Davix

#endif
<|endoftext|>


<commit_before><commit_msg>Implement TF style padding. Verify TF SAME mode working fine. All tests passing. Several fails on TF VALID mode.<commit_after><|endoftext|>


<commit_before>#pragma once

#include <string>
#include <stdint.h>

typedef std::string String;

// int8-64 definitions.
typedef	int8_t		int8;
typedef int16_t		int16;
typedef int32_t		int32;
typedef int64_t     int64;

// uint8-64 definitions.
typedef uint8_t		uint8;
typedef uint16_t	uint16;
typedef	uint32_t	uint32;
typedef uint64_t    uint64;

// f32-64 definitions.
typedef float		float32;
typedef double		float64;

// int8-64 assertions.
static_assert(sizeof(int8) == 1, "sizeof(int8) != 1");
static_assert(sizeof(int16) == 2, "sizeof(int16) != 2");
static_assert(sizeof(int32) == 4, "sizeof(int32) != 4");
static_assert(sizeof(int64) == 8, "sizeof(int64) != 8");

// uint8-64 assertions.
static_assert(sizeof(uint8) == 1, "sizeof(uint8) != 1");
static_assert(sizeof(uint16) == 2, "sizeof(uint16) != 2");
static_assert(sizeof(uint32) == 4, "sizeof(uint32) != 4");
static_assert(sizeof(uint64) == 8, "sizeof(uint64) != 8");

// float32-64 assertions.
static_assert(sizeof(float32) == 4, "sizeof(float32) != 4");
static_assert(sizeof(float64) == 8, "sizeof(float64) != 8");<commit_msg>changed typedefs to using in types.hpp<commit_after>#pragma once

#include <string>
#include <stdint.h>

using String	= std::string;

// int8-64 definitions.
using int8		= int8_t;
using int16		= int16_t;
using int32		= int32_t;
using int64		= int64_t;

// uint8-64 definitions.
using uint8		= uint8_t;
using uint16	= uint16_t;
using uint32	= uint32_t;
using uint64	= uint64_t;

// f32-64 definitions.
using float32	= float;
using float64	= double;

// int8-64 assertions.
static_assert(sizeof(int8) == 1, "sizeof(int8) != 1");
static_assert(sizeof(int16) == 2, "sizeof(int16) != 2");
static_assert(sizeof(int32) == 4, "sizeof(int32) != 4");
static_assert(sizeof(int64) == 8, "sizeof(int64) != 8");

// uint8-64 assertions.
static_assert(sizeof(uint8) == 1, "sizeof(uint8) != 1");
static_assert(sizeof(uint16) == 2, "sizeof(uint16) != 2");
static_assert(sizeof(uint32) == 4, "sizeof(uint32) != 4");
static_assert(sizeof(uint64) == 8, "sizeof(uint64) != 8");

// float32-64 assertions.
static_assert(sizeof(float32) == 4, "sizeof(float32) != 4");
static_assert(sizeof(float64) == 8, "sizeof(float64) != 8");<|endoftext|>


<commit_before>#include <mlopen.h>
#include "test.hpp"
#include <array>
#include <iterator>
#include <memory>
#include <utility>
#include <iostream>
#include <mlopen/tensor.hpp>
#include <mlopen/convolution.hpp>
#include <limits>

// #include "network_data.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"
#include "driver.hpp"
#include "get_handle.hpp"

template<class T>
tensor<T> get_output_tensor(const mlopen::ConvolutionDescriptor& filter, const tensor<T>& input, const tensor<T>& weights)
{
    assert(filter.GetBackwardOutputTensor(filter.GetForwardOutputTensor(input.desc, weights.desc), weights.desc) == input.desc);
    return tensor<T>{filter.GetForwardOutputTensor(input.desc, weights.desc)};
}

template<class T>
struct conv_base
{
    tensor<T> input;
    tensor<T> weights;
    tensor<T> out;
    mlopen::ConvolutionDescriptor filter;
    int bias;

    void fail(float=0)
    {
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Weights tensor: " << weights.desc.ToString() << std::endl;
        std::cout << "Output tensor: " << out.desc.ToString() << std::endl;
    }
};

template<class T>
struct verify_forward_conv : conv_base<T>
{
    using conv_base<T>::input;
    using conv_base<T>::weights;
    using conv_base<T>::out;
    using conv_base<T>::filter;
    using conv_base<T>::bias;

    verify_forward_conv(const tensor<T>& pinput, const tensor<T>& pweights, const mlopen::ConvolutionDescriptor& pfilter, int pbias = 0)
    {
        input = pinput;
        weights = pweights;
        filter = pfilter;
        bias = pbias;
    }

    tensor<T> cpu()
    {
        auto out = get_output_tensor(filter, input, weights);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

        int wei_c, wei_h, wei_w;
        std::tie(std::ignore, wei_c, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

        out.par_for_each([&](int o, int w, int i, int j)
        {
            const int start_x = i * filter.v - filter.pad_h;
            const int start_y = j * filter.u - filter.pad_w;

            double acc = bias;
            ford(wei_c, wei_h, wei_w)([&](int k, int x, int y)
            {
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    acc += input(o, k, in_x, in_y) * weights(w, k, x, y);
                }
            });
            out(o, w, i, j) = acc;
        });
        return out;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();
        auto out = get_output_tensor(filter, input, weights);

        auto in_dev = handle.Write(input.data);
        auto wei_dev = handle.Write(weights.data);
        auto out_dev = handle.Create<T>(out.data.size());

		size_t workspace_size = filter.ForwardGetWorkSpaceSize(weights.desc, out.desc);

		std::vector<char> workspace(workspace_size);
		auto workspace_dev = workspace_size != 0 ? handle.Write(workspace) : nullptr;

        int ret_algo_count;
        mlopenConvAlgoPerf_t perf;

        int alpha = 1, beta = 1;

        filter.FindConvFwdAlgorithm(handle,
            input.desc,
            in_dev.get(),
            weights.desc,
            wei_dev.get(),
            out.desc,
            out_dev.get(),
            1,
            &ret_algo_count,
            &perf,
            mlopenConvolutionFastest,
            workspace_dev.get(),
            workspace_size,
            0); // MD: Not performing exhaustiveSearch by default for now

        filter.ConvolutionForward(handle,
            &alpha,
            input.desc,
            in_dev.get(),
            weights.desc,
            wei_dev.get(),
            perf.fwd_algo,
            &beta,
            out.desc,
            out_dev.get(),
            workspace_dev.get(),
            workspace_size);

        out.data = handle.Read<T>(out_dev, out.data.size());
        return out;
    }

    void fail(float=0)
    {
        std::cout << "Forward convolution: " << std::endl;
        this->conv_base<T>::fail();
    }

};

template<class T>
struct verify_backward_conv : conv_base<T>
{
    using conv_base<T>::input;
    using conv_base<T>::weights;
    using conv_base<T>::out;
    using conv_base<T>::filter;
    using conv_base<T>::bias;

    verify_backward_conv(const tensor<T>& pinput, const tensor<T>& pweights, const tensor<T>& pout, const mlopen::ConvolutionDescriptor& pfilter, int pbias = 0)
    {
        input = pinput;
        weights = pweights;
        out = pout;
        filter = pfilter;
        bias = pbias;
    }

    tensor<T> cpu()
    {
        std::fill(input.begin(), input.end(), 0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

        int wei_c, wei_h, wei_w;
        std::tie(std::ignore, wei_c, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = mlopen::tie4(out.desc.GetLengths());

        par_ford(out_n, wei_c)([&](int o, int k)
        {
            ford(out_c, out_h, out_w, wei_h, wei_w)([&](int w, int i, int j, int x, int y)
            {
                const int start_x = i * filter.v - filter.pad_h;
                const int start_y = j * filter.u - filter.pad_w;
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    input(o, k, in_x, in_y) += out(o, w, i, j) * weights(w, k, x, y);
                }
            });
        });
        return input;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();
        std::fill(input.begin(), input.end(), 0);

        auto out_dev = handle.Write(out.data);
        auto wei_dev = handle.Write(weights.data);
        auto in_dev = handle.Create<T>(input.data.size());

        int ret_algo_count;
        mlopenConvAlgoPerf_t perf;

        int alpha = 1, beta = 1;

        filter.FindConvBwdDataAlgorithm(handle,
            out.desc,
            out_dev.get(),
            weights.desc,
            wei_dev.get(),
            input.desc,
            in_dev.get(),
            1,
            &ret_algo_count,
            &perf,
            mlopenConvolutionFastest,
            nullptr,
            10,
            0); // MD: Not performing exhaustiveSearch by default for now

        filter.ConvolutionBackwardData(handle,
            &alpha,
            out.desc,
            out_dev.get(),
            weights.desc,
            wei_dev.get(),
            perf.bwd_data_algo,
            &beta,
            input.desc,
            in_dev.get(),
            nullptr,
            0);

        input.data = handle.Read<T>(in_dev, input.data.size());
        return input;
    }

    void fail(float)
    {
        std::cout << "Backward convolution: " << std::endl;
        this->conv_base<T>::fail();
    }

};

template<class T>
struct verify_backward_weights_conv : conv_base<T>
{
    using conv_base<T>::input;
    using conv_base<T>::weights;
    using conv_base<T>::out;
    using conv_base<T>::filter;
    using conv_base<T>::bias;

    verify_backward_weights_conv(const tensor<T>& pinput, const tensor<T>& pweights, const tensor<T>& pout, const mlopen::ConvolutionDescriptor& pfilter, int pbias = 0)
    {
        input = pinput;
        weights = pweights;
        out = pout;
        filter = pfilter;
        bias = pbias;
    }

    tensor<T> cpu()
    {
        std::fill(weights.begin(), weights.end(), 0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

        int wei_c, wei_h, wei_w;
        std::tie(std::ignore, wei_c, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = mlopen::tie4(out.desc.GetLengths());

        par_ford(out_c, wei_c, wei_h, wei_w)([&](int w, int k, int x, int y)
        {
            double acc = 0.0;
            ford(out_n, out_h, out_w)([&](int o, int i, int j)
            {
                const int start_x = i * filter.v - filter.pad_h;
                const int start_y = j * filter.u - filter.pad_w;
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    acc += input(o, k, in_x, in_y) * out(o, w, i, j);
                }
            });
            weights(w, k, x, y) = acc;
        });
        return weights;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();
        std::fill(weights.begin(), weights.end(), 0);

        auto out_dev = handle.Write(out.data);
        auto wei_dev = handle.Create<T>(weights.data.size());
        auto in_dev = handle.Write(input.data);

        std::size_t workspace_size = filter.ConvolutionBackwardWeightsGetWorkSpaceSize(out.desc, input.desc, weights.desc);

        std::vector<char> workspace(workspace_size);
        auto workspace_dev = handle.Write(workspace);

        int ret_algo_count;
        mlopenConvAlgoPerf_t perf;

        int alpha = 1, beta = 1;
        filter.FindConvBwdWeightsAlgorithm(handle,
            out.desc,
            out_dev.get(),
            input.desc,
            in_dev.get(),
            weights.desc,
            wei_dev.get(),
            1,
            &ret_algo_count,
            &perf,
            mlopenConvolutionFastest,
            workspace_dev.get(),
            workspace_size,
            0); // MD: Not performing exhaustiveSearch by default for now

        filter.ConvolutionBackwardWeights(handle,
            &alpha,
            out.desc,
            out_dev.get(),
            input.desc,
            in_dev.get(),
            perf.bwd_weights_algo,
            &beta,
            weights.desc,
            wei_dev.get(),
            workspace_dev.get(),
            workspace_size);

        weights.data = handle.Read<T>(wei_dev, weights.data.size());
        return weights;
    }

    void fail(float)
    {
        std::cout << "Backward weights convolution: " << std::endl;
        this->conv_base<T>::fail();
    }

};

template<class T>
struct conv_driver : test_driver
{
    tensor<T> input;
    tensor<T> weights;
    mlopen::ConvolutionDescriptor filter;

    conv_driver()
    {
        add(input, "input", get_input_tensor());
        add(weights, "weights", get_weights_tensor());
        add(filter, "filter", generate_data(get_filters()));
    }

    std::vector<mlopen::ConvolutionDescriptor> get_filters()
    {
        return {
            mlopen::ConvolutionDescriptor{0, 0}
            // mlopen::ConvolutionDescriptor{1, 1}
        };
    }

    void run()
    {
        int wei_h, wei_w;
        std::tie(std::ignore, std::ignore, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());
        if (input.desc.GetLengths().at(1) == weights.desc.GetLengths().at(1) &&
            wei_h > filter.pad_h &&
            wei_w > filter.pad_w
        )
        {
            auto out_p = verify(verify_forward_conv<T>{input, weights, filter});
            for(auto& x:out_p.first) x = (long(x+1)*2) % 17; // Clamp big numbers
            verify(verify_backward_conv<T>{input, weights, out_p.first, filter});
#if MLOPEN_USE_TINYGEMM
            verify(verify_backward_weights_conv<T>{input, weights, out_p.first, filter});
#endif
        }
    }
};

int main(int argc, const char *argv[])
{
    test_drive<conv_driver<float>>(argc, argv);
}
<commit_msg>Fix out parameter<commit_after>#include <mlopen.h>
#include "test.hpp"
#include <array>
#include <iterator>
#include <memory>
#include <utility>
#include <iostream>
#include <mlopen/tensor.hpp>
#include <mlopen/convolution.hpp>
#include <limits>

// #include "network_data.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"
#include "driver.hpp"
#include "get_handle.hpp"

template<class T>
tensor<T> get_output_tensor(const mlopen::ConvolutionDescriptor& filter, const tensor<T>& input, const tensor<T>& weights)
{
    assert(filter.GetBackwardOutputTensor(filter.GetForwardOutputTensor(input.desc, weights.desc), weights.desc) == input.desc);
    return tensor<T>{filter.GetForwardOutputTensor(input.desc, weights.desc)};
}

template<class T>
struct conv_base
{
    tensor<T> input;
    tensor<T> weights;
    tensor<T> out;
    mlopen::ConvolutionDescriptor filter;
    int bias;

    void fail(float=0)
    {
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Weights tensor: " << weights.desc.ToString() << std::endl;
        std::cout << "Output tensor: " << out.desc.ToString() << std::endl;
    }
};

template<class T>
struct verify_forward_conv : conv_base<T>
{
    using conv_base<T>::input;
    using conv_base<T>::weights;
    using conv_base<T>::out;
    using conv_base<T>::filter;
    using conv_base<T>::bias;

    verify_forward_conv(const tensor<T>& pinput, const tensor<T>& pweights, const mlopen::ConvolutionDescriptor& pfilter, int pbias = 0)
    {
        input = pinput;
        weights = pweights;
        filter = pfilter;
        bias = pbias;
    }

    tensor<T> cpu()
    {
        out = get_output_tensor(filter, input, weights);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

        int wei_c, wei_h, wei_w;
        std::tie(std::ignore, wei_c, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

        out.par_for_each([&](int o, int w, int i, int j)
        {
            const int start_x = i * filter.v - filter.pad_h;
            const int start_y = j * filter.u - filter.pad_w;

            double acc = bias;
            ford(wei_c, wei_h, wei_w)([&](int k, int x, int y)
            {
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    acc += input(o, k, in_x, in_y) * weights(w, k, x, y);
                }
            });
            out(o, w, i, j) = acc;
        });
        return out;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();
        out = get_output_tensor(filter, input, weights);

        auto in_dev = handle.Write(input.data);
        auto wei_dev = handle.Write(weights.data);
        auto out_dev = handle.Create<T>(out.data.size());

		size_t workspace_size = filter.ForwardGetWorkSpaceSize(weights.desc, out.desc);

		std::vector<char> workspace(workspace_size);
		auto workspace_dev = workspace_size != 0 ? handle.Write(workspace) : nullptr;

        int ret_algo_count;
        mlopenConvAlgoPerf_t perf;

        int alpha = 1, beta = 1;

        filter.FindConvFwdAlgorithm(handle,
            input.desc,
            in_dev.get(),
            weights.desc,
            wei_dev.get(),
            out.desc,
            out_dev.get(),
            1,
            &ret_algo_count,
            &perf,
            mlopenConvolutionFastest,
            workspace_dev.get(),
            workspace_size,
            0); // MD: Not performing exhaustiveSearch by default for now

        filter.ConvolutionForward(handle,
            &alpha,
            input.desc,
            in_dev.get(),
            weights.desc,
            wei_dev.get(),
            perf.fwd_algo,
            &beta,
            out.desc,
            out_dev.get(),
            workspace_dev.get(),
            workspace_size);

        out.data = handle.Read<T>(out_dev, out.data.size());
        return out;
    }

    void fail(float=0)
    {
        std::cout << "Forward convolution: " << std::endl;
        this->conv_base<T>::fail();
    }

};

template<class T>
struct verify_backward_conv : conv_base<T>
{
    using conv_base<T>::input;
    using conv_base<T>::weights;
    using conv_base<T>::out;
    using conv_base<T>::filter;
    using conv_base<T>::bias;

    verify_backward_conv(const tensor<T>& pinput, const tensor<T>& pweights, const tensor<T>& pout, const mlopen::ConvolutionDescriptor& pfilter, int pbias = 0)
    {
        input = pinput;
        weights = pweights;
        out = pout;
        filter = pfilter;
        bias = pbias;
    }

    tensor<T> cpu()
    {
        std::fill(input.begin(), input.end(), 0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

        int wei_c, wei_h, wei_w;
        std::tie(std::ignore, wei_c, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = mlopen::tie4(out.desc.GetLengths());

        par_ford(out_n, wei_c)([&](int o, int k)
        {
            ford(out_c, out_h, out_w, wei_h, wei_w)([&](int w, int i, int j, int x, int y)
            {
                const int start_x = i * filter.v - filter.pad_h;
                const int start_y = j * filter.u - filter.pad_w;
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    input(o, k, in_x, in_y) += out(o, w, i, j) * weights(w, k, x, y);
                }
            });
        });
        return input;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();
        std::fill(input.begin(), input.end(), 0);

        auto out_dev = handle.Write(out.data);
        auto wei_dev = handle.Write(weights.data);
        auto in_dev = handle.Create<T>(input.data.size());

        int ret_algo_count;
        mlopenConvAlgoPerf_t perf;

        int alpha = 1, beta = 1;

        filter.FindConvBwdDataAlgorithm(handle,
            out.desc,
            out_dev.get(),
            weights.desc,
            wei_dev.get(),
            input.desc,
            in_dev.get(),
            1,
            &ret_algo_count,
            &perf,
            mlopenConvolutionFastest,
            nullptr,
            10,
            0); // MD: Not performing exhaustiveSearch by default for now

        filter.ConvolutionBackwardData(handle,
            &alpha,
            out.desc,
            out_dev.get(),
            weights.desc,
            wei_dev.get(),
            perf.bwd_data_algo,
            &beta,
            input.desc,
            in_dev.get(),
            nullptr,
            0);

        input.data = handle.Read<T>(in_dev, input.data.size());
        return input;
    }

    void fail(float)
    {
        std::cout << "Backward convolution: " << std::endl;
        this->conv_base<T>::fail();
    }

};

template<class T>
struct verify_backward_weights_conv : conv_base<T>
{
    using conv_base<T>::input;
    using conv_base<T>::weights;
    using conv_base<T>::out;
    using conv_base<T>::filter;
    using conv_base<T>::bias;

    verify_backward_weights_conv(const tensor<T>& pinput, const tensor<T>& pweights, const tensor<T>& pout, const mlopen::ConvolutionDescriptor& pfilter, int pbias = 0)
    {
        input = pinput;
        weights = pweights;
        out = pout;
        filter = pfilter;
        bias = pbias;
    }

    tensor<T> cpu()
    {
        std::fill(weights.begin(), weights.end(), 0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

        int wei_c, wei_h, wei_w;
        std::tie(std::ignore, wei_c, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = mlopen::tie4(out.desc.GetLengths());

        par_ford(out_c, wei_c, wei_h, wei_w)([&](int w, int k, int x, int y)
        {
            double acc = 0.0;
            ford(out_n, out_h, out_w)([&](int o, int i, int j)
            {
                const int start_x = i * filter.v - filter.pad_h;
                const int start_y = j * filter.u - filter.pad_w;
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    acc += input(o, k, in_x, in_y) * out(o, w, i, j);
                }
            });
            weights(w, k, x, y) = acc;
        });
        return weights;
    }

    tensor<T> gpu()
    {
        auto&& handle = get_handle();
        std::fill(weights.begin(), weights.end(), 0);

        auto out_dev = handle.Write(out.data);
        auto wei_dev = handle.Create<T>(weights.data.size());
        auto in_dev = handle.Write(input.data);

        std::size_t workspace_size = filter.ConvolutionBackwardWeightsGetWorkSpaceSize(out.desc, input.desc, weights.desc);

        std::vector<char> workspace(workspace_size);
        auto workspace_dev = handle.Write(workspace);

        int ret_algo_count;
        mlopenConvAlgoPerf_t perf;

        int alpha = 1, beta = 1;
        filter.FindConvBwdWeightsAlgorithm(handle,
            out.desc,
            out_dev.get(),
            input.desc,
            in_dev.get(),
            weights.desc,
            wei_dev.get(),
            1,
            &ret_algo_count,
            &perf,
            mlopenConvolutionFastest,
            workspace_dev.get(),
            workspace_size,
            0); // MD: Not performing exhaustiveSearch by default for now

        filter.ConvolutionBackwardWeights(handle,
            &alpha,
            out.desc,
            out_dev.get(),
            input.desc,
            in_dev.get(),
            perf.bwd_weights_algo,
            &beta,
            weights.desc,
            wei_dev.get(),
            workspace_dev.get(),
            workspace_size);

        weights.data = handle.Read<T>(wei_dev, weights.data.size());
        return weights;
    }

    void fail(float)
    {
        std::cout << "Backward weights convolution: " << std::endl;
        this->conv_base<T>::fail();
    }

};

template<class T>
struct conv_driver : test_driver
{
    tensor<T> input;
    tensor<T> weights;
    mlopen::ConvolutionDescriptor filter;

    conv_driver()
    {
        add(input, "input", get_input_tensor());
        add(weights, "weights", get_weights_tensor());
        add(filter, "filter", generate_data(get_filters()));
    }

    std::vector<mlopen::ConvolutionDescriptor> get_filters()
    {
        return {
            mlopen::ConvolutionDescriptor{0, 0}
            // mlopen::ConvolutionDescriptor{1, 1}
        };
    }

    void run()
    {
        int wei_h, wei_w;
        std::tie(std::ignore, std::ignore, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());
        if (input.desc.GetLengths().at(1) == weights.desc.GetLengths().at(1) &&
            wei_h > filter.pad_h &&
            wei_w > filter.pad_w
        )
        {
            auto out_p = verify(verify_forward_conv<T>{input, weights, filter});
            for(auto& x:out_p.first) x = (long(x+1)*2) % 17; // Clamp big numbers
            verify(verify_backward_conv<T>{input, weights, out_p.first, filter});
#if MLOPEN_USE_TINYGEMM
            verify(verify_backward_weights_conv<T>{input, weights, out_p.first, filter});
#endif
        }
    }
};

int main(int argc, const char *argv[])
{
    test_drive<conv_driver<float>>(argc, argv);
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006 by Ingo Kloecker <kloecker@kde.org>                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/
#include <QDebug>

#include "akonadi.h"
#include "akonadiconnection.h"
#include "storage/datastore.h"
#include "storage/entity.h"

#include "create.h"
#include "imapparser.h"
#include "response.h"

using namespace Akonadi;

Create::Create(): Handler()
{
}

Create::~Create()
{
}

bool Create::handleLine(const QByteArray& line )
{
    // parse out the reference name and mailbox name
    const int startOfCommand = line.indexOf( ' ' ) + 1;
    const int startOfMailbox = line.indexOf( ' ', startOfCommand ) + 1;
    QByteArray mailbox;
    const int pos = PIM::ImapParser::parseQuotedString( line, mailbox, startOfMailbox );
    QList<QByteArray> mimeTypes;
    PIM::ImapParser::parseParenthesizedList( line, mimeTypes, pos );
    qDebug() << "mailbox: " << mailbox << " mimeTypes: " << mimeTypes << " pos: " << pos;

    // strip off a trailing '/'
    if ( !mailbox.isEmpty() && mailbox[0] == '/' )
      mailbox = mailbox.right( mailbox.size() - 1 );

    // Responses:
    // OK - create completed
    // NO - create failure: can't create mailbox with that name
    // BAD - command unknown or arguments invalid
    Response response;
    response.setTag( tag() );

    if ( mailbox.isEmpty() || mailbox.contains( "//" ) ) {
        response.setError();
        response.setString( "Invalid argument" );
        emit responseAvailable( response );
        deleteLater();
        return true;
    }

    DataStore *db = connection()->storageBackend();
    const int startOfLocation = mailbox.indexOf( '/' );
    const QByteArray topLevelName = mailbox.left( startOfLocation );

    Location toplevel = db->locationByName( topLevelName );
    if ( !toplevel.isValid() )
        return failureResponse( "Cannot create folder " + mailbox + " in  unknown toplevel folder " + topLevelName );

    Resource resource = db->resourceById( toplevel.resourceId() );

    // first check whether location already exists
    if ( db->locationByName( mailbox ).isValid() )
        return failureResponse( "A folder with that name does already exist" );

    // we have to create all superior hierarchical folders, so look for the
    // starting point
    QList<QByteArray> foldersToCreate;
    foldersToCreate.append( mailbox );
    for ( int endOfSupFolder = mailbox.lastIndexOf( '/', mailbox.size() - 1 );
          endOfSupFolder > 0;
          endOfSupFolder = mailbox.lastIndexOf( '/', endOfSupFolder - 2 ) ) {
        // check whether the superior hierarchical folder exists
        if ( ! db->locationByName( mailbox.left( endOfSupFolder ) ).isValid() ) {
            // the superior folder does not exist, so it has to be created
            foldersToCreate.prepend( mailbox.left( endOfSupFolder ) );
        }
        else {
            // the superior folder exists, so we can stop here
            break;
        }
    }

    // now we try to create all necessary folders
    // first check whether the existing superior folder can contain subfolders
    const int endOfSupFolder = foldersToCreate[0].lastIndexOf( '/' );
    if ( endOfSupFolder > 0 ) {
        bool canContainSubfolders = false;
        const QList<MimeType> mimeTypes = db->mimeTypesForLocation( db->locationByName( mailbox.left( endOfSupFolder ) ).id() );
        foreach ( MimeType m, mimeTypes ) {
            if ( m.mimeType().toLower() == "inode/directory" ) {
                canContainSubfolders = true;
                break;
            }
        }
        if ( !canContainSubfolders )
            return failureResponse( "Superior folder cannot contain subfolders" );
    }
    // everything looks good, now we create the folders
    foreach ( QByteArray folderName, foldersToCreate ) {
        int locationId = 0;
        if ( ! db->appendLocation( folderName, resource, &locationId ) )
            return failureResponse( "Adding " + folderName + " to the database failed" );
        // FIXME what to do if appending the mime type fails?
        foreach ( QByteArray mimeType, mimeTypes )
          db->appendMimeTypeForLocation( locationId, QString::fromUtf8(mimeType) );
    }

    response.setSuccess();
    response.setString( "CREATE completed" );
    emit responseAvailable( response );

    deleteLater();
    return true;
}

<commit_msg>cleanup SVN_SILENT<commit_after>/***************************************************************************
 *   Copyright (C) 2006 by Ingo Kloecker <kloecker@kde.org>                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/
#include <QDebug>

#include "akonadi.h"
#include "akonadiconnection.h"
#include "storage/datastore.h"
#include "storage/entity.h"

#include "create.h"
#include "imapparser.h"
#include "response.h"

using namespace Akonadi;

Create::Create(): Handler()
{
}

Create::~Create()
{
}

bool Create::handleLine(const QByteArray& line )
{
    // parse out the reference name and mailbox name
    const int startOfCommand = line.indexOf( ' ' ) + 1;
    const int startOfMailbox = line.indexOf( ' ', startOfCommand ) + 1;
    QByteArray mailbox;
    const int pos = PIM::ImapParser::parseQuotedString( line, mailbox, startOfMailbox );
    QList<QByteArray> mimeTypes;
    PIM::ImapParser::parseParenthesizedList( line, mimeTypes, pos );

    // strip off a trailing '/'
    if ( !mailbox.isEmpty() && mailbox[0] == '/' )
        mailbox = mailbox.right( mailbox.size() - 1 );

    // Responses:
    // OK - create completed
    // NO - create failure: can't create mailbox with that name
    // BAD - command unknown or arguments invalid
    Response response;
    response.setTag( tag() );

    if ( mailbox.isEmpty() || mailbox.contains( "//" ) ) {
        response.setError();
        response.setString( "Invalid argument" );
        emit responseAvailable( response );
        deleteLater();
        return true;
    }

    DataStore *db = connection()->storageBackend();
    const int startOfLocation = mailbox.indexOf( '/' );
    const QByteArray topLevelName = mailbox.left( startOfLocation );

    Location toplevel = db->locationByName( topLevelName );
    if ( !toplevel.isValid() )
        return failureResponse( "Cannot create folder " + mailbox + " in  unknown toplevel folder " + topLevelName );

    Resource resource = db->resourceById( toplevel.resourceId() );

    // first check whether location already exists
    if ( db->locationByName( mailbox ).isValid() )
        return failureResponse( "A folder with that name does already exist" );

    // we have to create all superior hierarchical folders, so look for the
    // starting point
    QList<QByteArray> foldersToCreate;
    foldersToCreate.append( mailbox );
    for ( int endOfSupFolder = mailbox.lastIndexOf( '/', mailbox.size() - 1 );
          endOfSupFolder > 0;
          endOfSupFolder = mailbox.lastIndexOf( '/', endOfSupFolder - 2 ) ) {
        // check whether the superior hierarchical folder exists
        if ( ! db->locationByName( mailbox.left( endOfSupFolder ) ).isValid() ) {
            // the superior folder does not exist, so it has to be created
            foldersToCreate.prepend( mailbox.left( endOfSupFolder ) );
        }
        else {
            // the superior folder exists, so we can stop here
            break;
        }
    }

    // now we try to create all necessary folders
    // first check whether the existing superior folder can contain subfolders
    const int endOfSupFolder = foldersToCreate[0].lastIndexOf( '/' );
    if ( endOfSupFolder > 0 ) {
        bool canContainSubfolders = false;
        const QList<MimeType> mimeTypes = db->mimeTypesForLocation( db->locationByName( mailbox.left( endOfSupFolder ) ).id() );
        foreach ( MimeType m, mimeTypes ) {
            if ( m.mimeType().toLower() == "inode/directory" ) {
                canContainSubfolders = true;
                break;
            }
        }
        if ( !canContainSubfolders )
            return failureResponse( "Superior folder cannot contain subfolders" );
    }
    // everything looks good, now we create the folders
    foreach ( QByteArray folderName, foldersToCreate ) {
        int locationId = 0;
        if ( ! db->appendLocation( folderName, resource, &locationId ) )
            return failureResponse( "Adding " + folderName + " to the database failed" );
        // FIXME what to do if appending the mime type fails?
        foreach ( QByteArray mimeType, mimeTypes )
            db->appendMimeTypeForLocation( locationId, QString::fromUtf8(mimeType) );
    }

    response.setSuccess();
    response.setString( "CREATE completed" );
    emit responseAvailable( response );

    deleteLater();
    return true;
}

<|endoftext|>


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

//
// Sorts functions by their static use count. This helps reduce the size of wasm
// binaries because fewer bytes are needed to encode references to frequently
// used functions.
//

#include <memory>

#include <wasm.h>
#include <pass.h>

namespace wasm {

struct ReorderFunctions : public WalkerPass<PostWalker<ReorderFunctions, Visitor<ReorderFunctions>>> {
  std::map<Name, uint32_t> counts;

  void visitModule(Module *module) {
    if (module->start.is()) {
      counts[module->start]++;
    }
    for (auto& curr : module->exports) {
      counts[curr->value]++;
    }
    for (auto& curr : module->table.names) {
      counts[curr]++;
    }
    sort(module->functions.begin(), module->functions.end(), [this](
      std::unique_ptr<Function>& a,
      std::unique_ptr<Function>& b) -> bool {
      if (this->counts[a->name] == this->counts[b->name]) {
        return strcmp(a->name.str, b->name.str) > 0;
      }
      return this->counts[a->name] > this->counts[b->name];
    });
    counts.clear();
  }

  void visitCall(Call *curr) {
    counts[curr->target]++;
  }
};

static RegisterPass<ReorderFunctions> registerPass("reorder-functions", "sorts functions by access frequency");

} // namespace wasm
<commit_msg>Pass sort comparison function arguments by const-reference (#472)<commit_after>/*
 * Copyright 2016 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// Sorts functions by their static use count. This helps reduce the size of wasm
// binaries because fewer bytes are needed to encode references to frequently
// used functions.
//

#include <memory>

#include <wasm.h>
#include <pass.h>

namespace wasm {

struct ReorderFunctions : public WalkerPass<PostWalker<ReorderFunctions, Visitor<ReorderFunctions>>> {
  std::map<Name, uint32_t> counts;

  void visitModule(Module *module) {
    if (module->start.is()) {
      counts[module->start]++;
    }
    for (auto& curr : module->exports) {
      counts[curr->value]++;
    }
    for (auto& curr : module->table.names) {
      counts[curr]++;
    }
    std::sort(module->functions.begin(), module->functions.end(), [this](
      const std::unique_ptr<Function>& a,
      const std::unique_ptr<Function>& b) -> bool {
      if (this->counts[a->name] == this->counts[b->name]) {
        return strcmp(a->name.str, b->name.str) > 0;
      }
      return this->counts[a->name] > this->counts[b->name];
    });
    counts.clear();
  }

  void visitCall(Call *curr) {
    counts[curr->target]++;
  }
};

static RegisterPass<ReorderFunctions> registerPass("reorder-functions", "sorts functions by access frequency");

} // namespace wasm
<|endoftext|>


<commit_before>/*
    Copyright (c) 2008 Tobias Koenig <tokoe@kde.org>

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

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

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

#include <QtCore/QDebug>

#include "nepomukmanager.h"

#include "searchqueryiteratorinterface.h"

#include "entities.h"

using namespace Akonadi;

static qint64 uriToItemId( const QString &uri )
{
  if ( uri.isEmpty() )
    return -1;

  bool ok = false;

  const QUrl url( uri );
  const qint64 id = url.queryItemValue( QLatin1String( "item" ) ).toLongLong( &ok );

  if ( !ok )
    return -1;
  else
    return id;
}

NepomukManager::NepomukManager( QObject* parent )
  : QObject( parent ),
    mValid( true )
{
  Q_ASSERT( mInstance == 0 );
  mInstance = this;

  mSearchInterface = new org::kde::Akonadi::Search( QLatin1String( "org.kde.Akonadi.Search" ), QLatin1String( "/Search" ),
                                                    QDBusConnection::sessionBus(), this );

  if ( !mSearchInterface->isValid() ) {
    qWarning() << "Nepomuk QueryServer interface not found!";
    mValid = false;
  }
}

NepomukManager::~NepomukManager()
{
  stopSearches();
}

bool NepomukManager::addSearch( const Location &location )
{
  if ( !mSearchInterface->isValid() || !mValid )
    return false;

  QMutexLocker lock( &mMutex );
  if ( location.remoteId().isEmpty() )
    return false;

  // TODO: search statement is stored in remoteId currently, port to attributes!
  const QString searchStatement = location.remoteId();

  const QString queryPath = mSearchInterface->createQuery( searchStatement );
  org::kde::Akonadi::SearchQuery *query = new org::kde::Akonadi::SearchQuery( QLatin1String( "org.kde.Akonadi.Search" ),
                                                                              queryPath, QDBusConnection::sessionBus(), 0 );

  if ( !query->isValid() ) {
    qWarning() << "Nepomuk QueryServer: Query could not be instantiated!";
    return false;
  }

  connect( query, SIGNAL( hitsChanged( const QStringList& ) ),
           this, SLOT( hitsAdded( const QStringList& ) ) );
  connect( query, SIGNAL( hitsRemoved( const QStringList& ) ),
           this, SLOT( hitsRemoved( const QStringList& ) ) );

  mQueryMap.insert( query, location.id() );
  mQueryInvMap.insert( location.id(), query ); // needed for fast lookup in removeSearch()

  // load all hits that are currently available...
  const QString iteratorPath = query->allHits();

  org::kde::Akonadi::SearchQueryIterator *iterator =
                  new org::kde::Akonadi::SearchQueryIterator( QLatin1String( "org.kde.Akonadi.Search" ), iteratorPath,
                                                              QDBusConnection::sessionBus(), 0 );

  while ( iterator->next() ) {
    const QString uri = iterator->currentUri();

    const qint64 itemId = uriToItemId( uri );
    if ( itemId == -1 ) {
      qWarning() << "Nepomuk QueryServer: Retrieved invalid item id from server!";
      continue;
    }

    Entity::addToRelation<LocationPimItemRelation>( location.id(), itemId );
  }

  iterator->close();

  // ... and start the change monitoring for future changes
  query->start();

  qDebug( "--------------- added search for loc %lld", location.id() );

  return true;
}

bool NepomukManager::removeSearch( qint64 locationId )
{
  org::kde::Akonadi::SearchQuery *query = mQueryInvMap.value( locationId );
  if ( !query || !query->isValid() ) {
    qWarning() << "Nepomuk QueryServer: Query could not be removed!";
  } else {
    query->stop();
    query->close();
  }

  // cleanup mappings
  mQueryInvMap.remove( locationId );
  mQueryMap.remove( query );

  qDebug( "--------------- removed search for loc %lld", locationId );

  return true;
}

void NepomukManager::reloadSearches()
{
  Resource resource = Resource::retrieveByName( QLatin1String( "akonadi_search_resource" ) );
  if ( !resource.isValid() ) {
    qWarning() << "Nepomuk QueryServer: No valid search resource found!";
    return;
  }

  const Location::List locations = resource.locations();
  Q_FOREACH ( const Location location, locations ) {
    addSearch( location );
  }
}

void NepomukManager::stopSearches()
{
  Resource resource = Resource::retrieveByName( QLatin1String( "akonadi_search_resource" ) );
  if ( !resource.isValid() ) {
    qWarning() << "Nepomuk QueryServer: No valid search resource found!";
    return;
  }

  const Location::List locations = resource.locations();
  Q_FOREACH ( const Location location, locations ) {
    removeSearch( location.id() );
  }
}

void NepomukManager::hitsAdded( const QStringList &hits )
{
  qDebug( "--------------- hits added 1" );

  org::kde::Akonadi::SearchQuery *query = qobject_cast<org::kde::Akonadi::SearchQuery*>( sender() );
  if ( !query ) {
    qWarning() << "Nepomuk QueryServer: Got signal from non-existing search query!";
    return;
  }

  qDebug( "--------------- hits added 2" );

  mMutex.lock();
  qint64 locationId = mQueryMap.value( query );
  mMutex.unlock();

  Q_FOREACH( const QString uri, hits ) {
    const qint64 itemId = uriToItemId( uri );

    if ( itemId == -1 ) {
      qWarning() << "Nepomuk QueryServer: Retrieved invalid item id from server!";
      continue;
    }

    Entity::addToRelation<LocationPimItemRelation>( locationId, itemId );
  }
}

void NepomukManager::hitsRemoved( const QStringList &hits )
{
  qDebug( "--------------- hits removed 1" );

  org::kde::Akonadi::SearchQuery *query = qobject_cast<org::kde::Akonadi::SearchQuery*>( sender() );
  if ( !query ) {
    qWarning() << "Nepomuk QueryServer: Got signal from non-existing search query!";
    return;
  }

  qDebug( "--------------- hits removed 2" );

  mMutex.lock();
  qint64 locationId = mQueryMap.value( query );
  mMutex.unlock();

  Q_FOREACH( const QString uri, hits ) {
    const qint64 itemId = uriToItemId( uri );

    if ( itemId == -1 ) {
      qWarning() << "Nepomuk QueryServer: Retrieved invalid item id from server!";
      continue;
    }

    Entity::removeFromRelation<LocationPimItemRelation>( locationId, itemId );
  }
}

#include "nepomukmanager.moc"
<commit_msg>SVN_SILENT: compile++<commit_after>/*
    Copyright (c) 2008 Tobias Koenig <tokoe@kde.org>

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

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

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

#include <QtCore/QDebug>
#include <QtCore/QUrl>

#include "nepomukmanager.h"

#include "searchqueryiteratorinterface.h"

#include "entities.h"

using namespace Akonadi;

static qint64 uriToItemId( const QString &uri )
{
  if ( uri.isEmpty() )
    return -1;

  bool ok = false;

  const QUrl url( uri );
  const qint64 id = url.queryItemValue( QLatin1String( "item" ) ).toLongLong( &ok );

  if ( !ok )
    return -1;
  else
    return id;
}

NepomukManager::NepomukManager( QObject* parent )
  : QObject( parent ),
    mValid( true )
{
  Q_ASSERT( mInstance == 0 );
  mInstance = this;

  mSearchInterface = new org::kde::Akonadi::Search( QLatin1String( "org.kde.Akonadi.Search" ), QLatin1String( "/Search" ),
                                                    QDBusConnection::sessionBus(), this );

  if ( !mSearchInterface->isValid() ) {
    qWarning() << "Nepomuk QueryServer interface not found!";
    mValid = false;
  }
}

NepomukManager::~NepomukManager()
{
  stopSearches();
}

bool NepomukManager::addSearch( const Location &location )
{
  if ( !mSearchInterface->isValid() || !mValid )
    return false;

  QMutexLocker lock( &mMutex );
  if ( location.remoteId().isEmpty() )
    return false;

  // TODO: search statement is stored in remoteId currently, port to attributes!
  const QString searchStatement = location.remoteId();

  const QString queryPath = mSearchInterface->createQuery( searchStatement );
  org::kde::Akonadi::SearchQuery *query = new org::kde::Akonadi::SearchQuery( QLatin1String( "org.kde.Akonadi.Search" ),
                                                                              queryPath, QDBusConnection::sessionBus(), 0 );

  if ( !query->isValid() ) {
    qWarning() << "Nepomuk QueryServer: Query could not be instantiated!";
    return false;
  }

  connect( query, SIGNAL( hitsChanged( const QStringList& ) ),
           this, SLOT( hitsAdded( const QStringList& ) ) );
  connect( query, SIGNAL( hitsRemoved( const QStringList& ) ),
           this, SLOT( hitsRemoved( const QStringList& ) ) );

  mQueryMap.insert( query, location.id() );
  mQueryInvMap.insert( location.id(), query ); // needed for fast lookup in removeSearch()

  // load all hits that are currently available...
  const QString iteratorPath = query->allHits();

  org::kde::Akonadi::SearchQueryIterator *iterator =
                  new org::kde::Akonadi::SearchQueryIterator( QLatin1String( "org.kde.Akonadi.Search" ), iteratorPath,
                                                              QDBusConnection::sessionBus(), 0 );

  while ( iterator->next() ) {
    const QString uri = iterator->currentUri();

    const qint64 itemId = uriToItemId( uri );
    if ( itemId == -1 ) {
      qWarning() << "Nepomuk QueryServer: Retrieved invalid item id from server!";
      continue;
    }

    Entity::addToRelation<LocationPimItemRelation>( location.id(), itemId );
  }

  iterator->close();

  // ... and start the change monitoring for future changes
  query->start();

  qDebug( "--------------- added search for loc %lld", location.id() );

  return true;
}

bool NepomukManager::removeSearch( qint64 locationId )
{
  org::kde::Akonadi::SearchQuery *query = mQueryInvMap.value( locationId );
  if ( !query || !query->isValid() ) {
    qWarning() << "Nepomuk QueryServer: Query could not be removed!";
  } else {
    query->stop();
    query->close();
  }

  // cleanup mappings
  mQueryInvMap.remove( locationId );
  mQueryMap.remove( query );

  qDebug( "--------------- removed search for loc %lld", locationId );

  return true;
}

void NepomukManager::reloadSearches()
{
  Resource resource = Resource::retrieveByName( QLatin1String( "akonadi_search_resource" ) );
  if ( !resource.isValid() ) {
    qWarning() << "Nepomuk QueryServer: No valid search resource found!";
    return;
  }

  const Location::List locations = resource.locations();
  Q_FOREACH ( const Location location, locations ) {
    addSearch( location );
  }
}

void NepomukManager::stopSearches()
{
  Resource resource = Resource::retrieveByName( QLatin1String( "akonadi_search_resource" ) );
  if ( !resource.isValid() ) {
    qWarning() << "Nepomuk QueryServer: No valid search resource found!";
    return;
  }

  const Location::List locations = resource.locations();
  Q_FOREACH ( const Location location, locations ) {
    removeSearch( location.id() );
  }
}

void NepomukManager::hitsAdded( const QStringList &hits )
{
  qDebug( "--------------- hits added 1" );

  org::kde::Akonadi::SearchQuery *query = qobject_cast<org::kde::Akonadi::SearchQuery*>( sender() );
  if ( !query ) {
    qWarning() << "Nepomuk QueryServer: Got signal from non-existing search query!";
    return;
  }

  qDebug( "--------------- hits added 2" );

  mMutex.lock();
  qint64 locationId = mQueryMap.value( query );
  mMutex.unlock();

  Q_FOREACH( const QString uri, hits ) {
    const qint64 itemId = uriToItemId( uri );

    if ( itemId == -1 ) {
      qWarning() << "Nepomuk QueryServer: Retrieved invalid item id from server!";
      continue;
    }

    Entity::addToRelation<LocationPimItemRelation>( locationId, itemId );
  }
}

void NepomukManager::hitsRemoved( const QStringList &hits )
{
  qDebug( "--------------- hits removed 1" );

  org::kde::Akonadi::SearchQuery *query = qobject_cast<org::kde::Akonadi::SearchQuery*>( sender() );
  if ( !query ) {
    qWarning() << "Nepomuk QueryServer: Got signal from non-existing search query!";
    return;
  }

  qDebug( "--------------- hits removed 2" );

  mMutex.lock();
  qint64 locationId = mQueryMap.value( query );
  mMutex.unlock();

  Q_FOREACH( const QString uri, hits ) {
    const qint64 itemId = uriToItemId( uri );

    if ( itemId == -1 ) {
      qWarning() << "Nepomuk QueryServer: Retrieved invalid item id from server!";
      continue;
    }

    Entity::removeFromRelation<LocationPimItemRelation>( locationId, itemId );
  }
}

#include "nepomukmanager.moc"
<|endoftext|>