<commit_before>/*
 * Copyright (C) 2011
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <string>
#include <cstring>
#include <fstream>
using std::string;
using std::ofstream;

#include <utils.hpp>
#include <Exceptions.hpp>
#include <Timer.hpp>
using isa::utils::toStringValue;
using isa::Exceptions::OpenCLError;
using LOFAR::NSTimer;

#ifndef GPU_DATA_HPP
#define GPU_DATA_HPP

namespace isa {

namespace OpenCL {

template< typename T > class GPUData {
public:
	GPUData(string name, bool deletePolicy = false, bool devRO = false);
	~GPUData();

	inline string getName() const;

	// Allocation of host data
	void allocateHostData(T *data, size_t size);
	void allocateHostData(long long unsigned int nrElements);
	void deleteHostData();

	// Allocation of device data
	void allocateDeviceData(cl::Buffer *data, size_t size);
	void allocateDeviceData(long long unsigned int nrElements) throw (OpenCLError);
	void allocateDeviceData() throw (OpenCLError);
	void deleteDeviceData();

	// Memory transfers
	void copyHostToDevice(bool async = false) throw (OpenCLError);
	void copyDeviceToHost(bool async = false) throw (OpenCLError);
	void dumpDeviceToDisk() throw (OpenCLError);

	// OpenCL
	inline void setCLContext(cl::Context *context);
	inline void setCLQueue(cl::CommandQueue *queue);

	// Access host data
	inline T *getHostData();
	inline T *getHostDataAt(long long unsigned int startintPoint);
	inline void *getRawHostData();
	inline size_t getHostDataSize() const;
	inline T operator[](long long unsigned int item);

	// Access device data
	inline cl::Buffer *getDeviceData();
	inline size_t getDeviceDataSize() const;

	// Timers
	inline double getH2DTime() const;
	inline double getD2HTime() const;

private:
	cl::Context *clContext;
	cl::CommandQueue *clQueue;
	NSTimer timerH2D;
	NSTimer	timerD2H;

	bool deleteHost;
	bool deviceReadOnly;
	T *hostData;
	size_t hostDataSize;
	cl::Buffer *deviceData;
	size_t deviceDataSize;

	string name;
};

// Implementations

template< typename T > GPUData< T >::GPUData(string name, bool deletePolicy, bool devRO) : clContext(0), clQueue(0), timerH2D(NSTimer(name + "_H2D", false, false)), timerD2H(NSTimer(name + "_D2H", false, false)), deleteHost(deletePolicy), deviceReadOnly(devRO), hostData(0), hostDataSize(0), deviceData(0), deviceDataSize(0), name(name) {}

template< typename T > GPUData< T >::~GPUData() {
	deleteHostData();
	deleteDeviceData();
}

template< typename T > void GPUData< T >::allocateHostData(T *data, size_t size) {
	deleteHostData();

	hostData = data;
	hostDataSize = size;
}

template< typename T > void GPUData< T >::allocateHostData(long long unsigned int nrElements) {
	size_t newSize = nrElements * sizeof(T);

	if ( newSize != hostDataSize ) {
		deleteHostData();

		hostData = new T [nrElements];
		hostDataSize = newSize;
	}
	memset(getRawHostData(), 0, newSize);
}

template< typename T > void GPUData< T >::deleteHostData() {
	if ( deleteHost && hostDataSize != 0 ) {
		delete [] hostData;
		hostData = 0;
		hostDataSize = 0;
	}
}

template< typename T > void GPUData< T >::allocateDeviceData(cl::Buffer *data, size_t size) {
	deleteDeviceData();

	deviceData = data;
	deviceDataSize = size;
}

template< typename T > void GPUData< T >::allocateDeviceData(long long unsigned int nrElements) throw (OpenCLError) {
	size_t newSize = nrElements * sizeof(T);
	if ( newSize != deviceDataSize ) {
		deleteDeviceData();

		try {
			if ( deviceReadOnly ) {
				deviceData = new cl::Buffer(*clContext, CL_MEM_READ_ONLY, newSize, NULL, NULL);
			}
			else {
				deviceData = new cl::Buffer(*clContext, CL_MEM_READ_WRITE, newSize, NULL, NULL);
			}
		}
		catch ( cl::Error err ) {
			throw  OpenCLError("Impossible to allocate " + name + " device memory: " + toStringValue< cl_int >(err.err()));
		}
		deviceDataSize = newSize;
	}
}

template< typename T > void GPUData< T >::allocateDeviceData() throw (OpenCLError) {
	deleteDeviceData();

	try {
		if ( deviceReadOnly ) {
			deviceData = new cl::Buffer(*clContext, CL_MEM_READ_ONLY, hostDataSize, NULL, NULL);
		}
		else {
			deviceData = new cl::Buffer(*clContext, CL_MEM_READ_WRITE, hostDataSize, NULL, NULL);
		}
	}
	catch ( cl::Error err ) {
		throw  OpenCLError("Impossible to allocate " + name + " device memory: " + toStringValue< cl_int >(err.err()));
	}
	deviceDataSize = hostDataSize;
}

template< typename T > void GPUData< T >::deleteDeviceData() {
	if ( deviceDataSize != 0 ) {
		delete deviceData;
		deviceData = 0;
		deviceDataSize = 0;
	}
}

template< typename T > void GPUData< T >::copyHostToDevice(bool async) throw (OpenCLError) {
	if ( hostDataSize != deviceDataSize ) {
		throw OpenCLError("Impossible to copy " + name + ": different memory sizes.");
	}

	if ( async ) {
		try {
			clQueue->enqueueWriteBuffer(*deviceData, CL_FALSE, 0, deviceDataSize, getRawHostData(), NULL, NULL);
		}
		catch ( cl::Error err ) {
			throw OpenCLError("Impossible to copy " + name + " to device: " + toStringValue< cl_int >(err.err()));
		}
	}
	else {
		cl::Event clEvent;

		try {
			timerH2D.start();
			clQueue->enqueueWriteBuffer(*deviceData, CL_TRUE, 0, deviceDataSize, getRawHostData(), NULL, &clEvent);
			clEvent.wait();
			timerH2D.stop();
		}
		catch ( cl::Error err ) {
			timerH2D.reset();
			throw OpenCLError("Impossible to copy " + name + " to device: " + toStringValue< cl_int >(err.err()));
		}
	}
}

template< typename T > void GPUData< T >::copyDeviceToHost(bool async) throw (OpenCLError) {
	if ( hostDataSize != deviceDataSize ) {
		throw OpenCLError("Impossible to copy " + name + ": different memory sizes.");
	}

	if ( async ) {
		try {
			clQueue->enqueueReadBuffer(*deviceData, CL_FALSE, 0, hostDataSize, getRawHostData(), NULL, NULL);
		}
		catch ( cl::Error err ) {
			throw OpenCLError("Impossible to copy " + name + " to host: " + toStringValue< cl_int >(err.err()));
		}
	}
	else {
		cl::Event clEvent;

		try {
			timerD2H.start();
			clQueue->enqueueReadBuffer(*deviceData, CL_TRUE, 0, hostDataSize, getRawHostData(), NULL, &clEvent);
			clEvent.wait();
			timerD2H.stop();
		}
		catch ( cl::Error err ) {
			timerD2H.reset();
			throw OpenCLError("Impossible to copy " + name + " to host: " + toStringValue< cl_int >(err.err()));
		}
	}

}

template< typename T > void GPUData< T >::dumpDeviceToDisk() throw (OpenCLError) {
	GPUData< T > temp = GPUData< T >("temp", true);

	temp.setCLContext(clContext);
	temp.setCLQueue(clQueue);
	temp.allocateHostData(hostDataSize / sizeof(T));
	temp.allocateDeviceData(deviceData, deviceDataSize);
	temp.copyDeviceToHost();

	ofstream oFile(("./" + name + ".bin").c_str(), ofstream::binary);
	oFile.write(reinterpret_cast< char * >(temp.getRawHostData()), temp.getHostDataSize());
	oFile.close();
}

template< typename T > inline void GPUData< T >::setCLContext(cl::Context *context) {
	clContext = context;
}

template< typename T > inline void GPUData< T >::setCLQueue(cl::CommandQueue *queue) {
	clQueue = queue;
}

template< typename T > inline T *GPUData< T >::getHostData() {
	return hostData;
}

template< typename T > inline T *GPUData< T >::getHostDataAt(long long unsigned int startingPoint) {
	return &(hostData[startingPoint])
}

template< typename T > inline void *GPUData< T >::getRawHostData() {
	return reinterpret_cast< void * >(hostData);
}

template< typename T > inline size_t GPUData< T >::getHostDataSize() const {
	return hostDataSize;
}

template< typename T > inline T GPUData< T >::operator[](long long unsigned int item) {
	return hostData[item];
}

template< typename T > inline cl::Buffer *GPUData< T >::getDeviceData() {
	return deviceData;
}

template< typename T > inline size_t GPUData< T >::getDeviceDataSize() const {
	return deviceDataSize;
}

template< typename T > inline string GPUData< T >::getName() const {
	return name;
}

template< typename T > inline double GPUData< T >::getH2DTime() const {
	return timerH2D.getElapsed();
}

template< typename T > inline double GPUData< T >::getD2HTime() const {
	return timerD2H.getElapsed();
}

} // OpenCL
} // isa

#endif // GPU_DATA_HPP

<commit_msg>Added the raw (void *) counterpart.<commit_after>/*
 * Copyright (C) 2011
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <string>
#include <cstring>
#include <fstream>
using std::string;
using std::ofstream;

#include <utils.hpp>
#include <Exceptions.hpp>
#include <Timer.hpp>
using isa::utils::toStringValue;
using isa::Exceptions::OpenCLError;
using LOFAR::NSTimer;

#ifndef GPU_DATA_HPP
#define GPU_DATA_HPP

namespace isa {

namespace OpenCL {

template< typename T > class GPUData {
public:
	GPUData(string name, bool deletePolicy = false, bool devRO = false);
	~GPUData();

	inline string getName() const;

	// Allocation of host data
	void allocateHostData(T *data, size_t size);
	void allocateHostData(long long unsigned int nrElements);
	void deleteHostData();

	// Allocation of device data
	void allocateDeviceData(cl::Buffer *data, size_t size);
	void allocateDeviceData(long long unsigned int nrElements) throw (OpenCLError);
	void allocateDeviceData() throw (OpenCLError);
	void deleteDeviceData();

	// Memory transfers
	void copyHostToDevice(bool async = false) throw (OpenCLError);
	void copyDeviceToHost(bool async = false) throw (OpenCLError);
	void dumpDeviceToDisk() throw (OpenCLError);

	// OpenCL
	inline void setCLContext(cl::Context *context);
	inline void setCLQueue(cl::CommandQueue *queue);

	// Access host data
	inline T *getHostData();
	inline T *getHostDataAt(long long unsigned int startintPoint);
	inline void *getRawHostData();
	inline void *getRawHostDataAt(long long unsigned int startingPoint);
	inline size_t getHostDataSize() const;
	inline T operator[](long long unsigned int item);

	// Access device data
	inline cl::Buffer *getDeviceData();
	inline size_t getDeviceDataSize() const;

	// Timers
	inline double getH2DTime() const;
	inline double getD2HTime() const;

private:
	cl::Context *clContext;
	cl::CommandQueue *clQueue;
	NSTimer timerH2D;
	NSTimer	timerD2H;

	bool deleteHost;
	bool deviceReadOnly;
	T *hostData;
	size_t hostDataSize;
	cl::Buffer *deviceData;
	size_t deviceDataSize;

	string name;
};

// Implementations

template< typename T > GPUData< T >::GPUData(string name, bool deletePolicy, bool devRO) : clContext(0), clQueue(0), timerH2D(NSTimer(name + "_H2D", false, false)), timerD2H(NSTimer(name + "_D2H", false, false)), deleteHost(deletePolicy), deviceReadOnly(devRO), hostData(0), hostDataSize(0), deviceData(0), deviceDataSize(0), name(name) {}

template< typename T > GPUData< T >::~GPUData() {
	deleteHostData();
	deleteDeviceData();
}

template< typename T > void GPUData< T >::allocateHostData(T *data, size_t size) {
	deleteHostData();

	hostData = data;
	hostDataSize = size;
}

template< typename T > void GPUData< T >::allocateHostData(long long unsigned int nrElements) {
	size_t newSize = nrElements * sizeof(T);

	if ( newSize != hostDataSize ) {
		deleteHostData();

		hostData = new T [nrElements];
		hostDataSize = newSize;
	}
	memset(getRawHostData(), 0, newSize);
}

template< typename T > void GPUData< T >::deleteHostData() {
	if ( deleteHost && hostDataSize != 0 ) {
		delete [] hostData;
		hostData = 0;
		hostDataSize = 0;
	}
}

template< typename T > void GPUData< T >::allocateDeviceData(cl::Buffer *data, size_t size) {
	deleteDeviceData();

	deviceData = data;
	deviceDataSize = size;
}

template< typename T > void GPUData< T >::allocateDeviceData(long long unsigned int nrElements) throw (OpenCLError) {
	size_t newSize = nrElements * sizeof(T);
	if ( newSize != deviceDataSize ) {
		deleteDeviceData();

		try {
			if ( deviceReadOnly ) {
				deviceData = new cl::Buffer(*clContext, CL_MEM_READ_ONLY, newSize, NULL, NULL);
			}
			else {
				deviceData = new cl::Buffer(*clContext, CL_MEM_READ_WRITE, newSize, NULL, NULL);
			}
		}
		catch ( cl::Error err ) {
			throw  OpenCLError("Impossible to allocate " + name + " device memory: " + toStringValue< cl_int >(err.err()));
		}
		deviceDataSize = newSize;
	}
}

template< typename T > void GPUData< T >::allocateDeviceData() throw (OpenCLError) {
	deleteDeviceData();

	try {
		if ( deviceReadOnly ) {
			deviceData = new cl::Buffer(*clContext, CL_MEM_READ_ONLY, hostDataSize, NULL, NULL);
		}
		else {
			deviceData = new cl::Buffer(*clContext, CL_MEM_READ_WRITE, hostDataSize, NULL, NULL);
		}
	}
	catch ( cl::Error err ) {
		throw  OpenCLError("Impossible to allocate " + name + " device memory: " + toStringValue< cl_int >(err.err()));
	}
	deviceDataSize = hostDataSize;
}

template< typename T > void GPUData< T >::deleteDeviceData() {
	if ( deviceDataSize != 0 ) {
		delete deviceData;
		deviceData = 0;
		deviceDataSize = 0;
	}
}

template< typename T > void GPUData< T >::copyHostToDevice(bool async) throw (OpenCLError) {
	if ( hostDataSize != deviceDataSize ) {
		throw OpenCLError("Impossible to copy " + name + ": different memory sizes.");
	}

	if ( async ) {
		try {
			clQueue->enqueueWriteBuffer(*deviceData, CL_FALSE, 0, deviceDataSize, getRawHostData(), NULL, NULL);
		}
		catch ( cl::Error err ) {
			throw OpenCLError("Impossible to copy " + name + " to device: " + toStringValue< cl_int >(err.err()));
		}
	}
	else {
		cl::Event clEvent;

		try {
			timerH2D.start();
			clQueue->enqueueWriteBuffer(*deviceData, CL_TRUE, 0, deviceDataSize, getRawHostData(), NULL, &clEvent);
			clEvent.wait();
			timerH2D.stop();
		}
		catch ( cl::Error err ) {
			timerH2D.reset();
			throw OpenCLError("Impossible to copy " + name + " to device: " + toStringValue< cl_int >(err.err()));
		}
	}
}

template< typename T > void GPUData< T >::copyDeviceToHost(bool async) throw (OpenCLError) {
	if ( hostDataSize != deviceDataSize ) {
		throw OpenCLError("Impossible to copy " + name + ": different memory sizes.");
	}

	if ( async ) {
		try {
			clQueue->enqueueReadBuffer(*deviceData, CL_FALSE, 0, hostDataSize, getRawHostData(), NULL, NULL);
		}
		catch ( cl::Error err ) {
			throw OpenCLError("Impossible to copy " + name + " to host: " + toStringValue< cl_int >(err.err()));
		}
	}
	else {
		cl::Event clEvent;

		try {
			timerD2H.start();
			clQueue->enqueueReadBuffer(*deviceData, CL_TRUE, 0, hostDataSize, getRawHostData(), NULL, &clEvent);
			clEvent.wait();
			timerD2H.stop();
		}
		catch ( cl::Error err ) {
			timerD2H.reset();
			throw OpenCLError("Impossible to copy " + name + " to host: " + toStringValue< cl_int >(err.err()));
		}
	}

}

template< typename T > void GPUData< T >::dumpDeviceToDisk() throw (OpenCLError) {
	GPUData< T > temp = GPUData< T >("temp", true);

	temp.setCLContext(clContext);
	temp.setCLQueue(clQueue);
	temp.allocateHostData(hostDataSize / sizeof(T));
	temp.allocateDeviceData(deviceData, deviceDataSize);
	temp.copyDeviceToHost();

	ofstream oFile(("./" + name + ".bin").c_str(), ofstream::binary);
	oFile.write(reinterpret_cast< char * >(temp.getRawHostData()), temp.getHostDataSize());
	oFile.close();
}

template< typename T > inline void GPUData< T >::setCLContext(cl::Context *context) {
	clContext = context;
}

template< typename T > inline void GPUData< T >::setCLQueue(cl::CommandQueue *queue) {
	clQueue = queue;
}

template< typename T > inline T *GPUData< T >::getHostData() {
	return hostData;
}

template< typename T > inline T *GPUData< T >::getHostDataAt(long long unsigned int startingPoint) {
	return &(hostData[startingPoint])
}

template< typename T > inline void *GPUData< T >::getRawHostData() {
	return reinterpret_cast< void * >(hostData);
}

template< typename T > inline void *GPUData< T >::getRawHostDataAt(long long unsigned int startingPoint) {
	return reinterpret_cast< void * >(&(hostData[startingPoint]));
}

template< typename T > inline size_t GPUData< T >::getHostDataSize() const {
	return hostDataSize;
}

template< typename T > inline T GPUData< T >::operator[](long long unsigned int item) {
	return hostData[item];
}

template< typename T > inline cl::Buffer *GPUData< T >::getDeviceData() {
	return deviceData;
}

template< typename T > inline size_t GPUData< T >::getDeviceDataSize() const {
	return deviceDataSize;
}

template< typename T > inline string GPUData< T >::getName() const {
	return name;
}

template< typename T > inline double GPUData< T >::getH2DTime() const {
	return timerH2D.getElapsed();
}

template< typename T > inline double GPUData< T >::getD2HTime() const {
	return timerD2H.getElapsed();
}

} // OpenCL
} // isa

#endif // GPU_DATA_HPP

<|endoftext|>


<commit_before>/*
[CyoJSON] cyojson.hpp

The MIT License (MIT)

Copyright (c) 2016 Graham Bull

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#ifndef __CYOJSON_HPP
#define __CYOJSON_HPP

////////////////////////////////////////////////////////////////////////////////

namespace cyojson
{
    class Parser
    {
    public:
        class Callbacks
        {
        public:
            virtual void ObjectStart(const char* path) { }
            virtual void ObjectEnd(const char* path) { }
            virtual void ArrayStart(const char* path) { }
            virtual void ArrayEnd(const char* path) { }
            virtual void Value(const char* path, const char* value) { }
        };

        bool Parse(const char* json, Callbacks& callbacks);

        int getLine() const { return line_; }
        int getColumn() const { return column_; }

    private:
        int line_ = 0;
        int column_ = 0;
    };
}

#include "detail/cyojson.hpp"

////////////////////////////////////////////////////////////////////////////////

#endif //__CYOJSON_HPP
<commit_msg>prevent warnings on unreferenced parameters<commit_after>/*
[CyoJSON] cyojson.hpp

The MIT License (MIT)

Copyright (c) 2016 Graham Bull

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#ifndef __CYOJSON_HPP
#define __CYOJSON_HPP

////////////////////////////////////////////////////////////////////////////////

#ifndef UNREFERENCED_PARAMETER
#   define UNREFERENCED_PARAMETER(p) (void)(p)
#endif

namespace cyojson
{
    class Parser
    {
    public:
        class Callbacks
        {
        public:
            virtual void ObjectStart(const char* path);
            virtual void ObjectEnd(const char* path);
            virtual void ArrayStart(const char* path);
            virtual void ArrayEnd(const char* path);
            virtual void Value(const char* path, const char* value);
        };

        bool Parse(const char* json, Callbacks& callbacks);

        int getLine() const { return line_; }
        int getColumn() const { return column_; }

    private:
        int line_ = 0;
        int column_ = 0;
    };

    inline void Parser::Callbacks::ObjectStart(const char* path) { UNREFERENCED_PARAMETER(path); }
    inline void Parser::Callbacks::ObjectEnd(const char* path) { UNREFERENCED_PARAMETER(path); }
    inline void Parser::Callbacks::ArrayStart(const char* path) { UNREFERENCED_PARAMETER(path); }
    inline void Parser::Callbacks::ArrayEnd(const char* path) { UNREFERENCED_PARAMETER(path); }
    inline void Parser::Callbacks::Value(const char* path, const char* value) { UNREFERENCED_PARAMETER(path); UNREFERENCED_PARAMETER(value); }
}

#include "detail/cyojson.hpp"

////////////////////////////////////////////////////////////////////////////////

#endif //__CYOJSON_HPP
<|endoftext|>


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

#ifndef DBN_DBN_HPP
#define DBN_DBN_HPP

#include <tuple>

#include "rbm.hpp"
#include "tuple_utils.hpp"
#include "dbn_trainer.hpp"
#include "conjugate_gradient.hpp"

namespace dll {

/*!
 * \brief A Deep Belief Network implementation
 */
template<typename Desc>
struct dbn {
    using desc = Desc;

    using tuple_type = typename desc::layers::tuple_type;
    tuple_type tuples;

    static constexpr const std::size_t layers = desc::layers::layers;

    template <std::size_t N>
    using rbm_type = typename std::tuple_element<N, tuple_type>::type;

    using weight = typename rbm_type<0>::weight;

    //No arguments by default
    dbn(){};

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

    //No moving
    dbn(dbn&& dbn) = delete;
    dbn& operator=(dbn&& dbn) = delete;

    void display() const {
        std::size_t parameters = 0;

        detail::for_each(tuples, [&parameters](auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_visible = rbm_t::num_visible;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            parameters += num_visible * num_hidden;

            std::cout << "RBM: " << num_visible << "->" << num_hidden
                << ": " << (num_visible * num_hidden) << " parameters" << std::endl;
        });

        std::cout << "Total parameters: " << parameters << std::endl;
    }

    void store(std::ostream& os) const {
        detail::for_each(tuples, [&os](auto& rbm){
            rbm.store(os);
        });
    }

    void load(std::istream& is){
        detail::for_each(tuples, [&is](auto& rbm){
            rbm.load(is);
        });
    }

    template<std::size_t N>
    auto layer() -> typename std::add_lvalue_reference<rbm_type<N>>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    constexpr auto layer() const -> typename std::add_lvalue_reference<typename std::add_const<rbm_type<N>>::type>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    static constexpr std::size_t num_visible(){
        return rbm_type<N>::num_visible;
    }

    template<std::size_t N>
    static constexpr std::size_t num_hidden(){
        return rbm_type<N>::num_hidden;
    }

    /*{{{ Pretrain */

    /*!
     * \brief Pretrain the network by training all layers in an unsupervised
     * manner.
     */
    template<typename Samples>
    void pretrain(const Samples& training_data, std::size_t max_epochs){
        using training_t = std::vector<etl::dyn_vector<typename Samples::value_type::value_type>>;

        //Convert data to an useful form
        training_t data;
        data.reserve(training_data.size());

        for(auto& sample : training_data){
            data.emplace_back(sample);
        }

        training_t next_a;
        training_t next_s;

        auto input = std::ref(data);

        detail::for_each_i(tuples, [&input, &next_a, &next_s, max_epochs](std::size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_visible = rbm_t::num_visible;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            auto input_size = static_cast<const training_t&>(input).size();

            //Train each layer but the last one
            if(I <= layers - 2){
                std::cout << "DBN: Train layer " << I << " (" << num_visible << "->" << num_hidden << ") with " << input_size << " entries" << std::endl;

                rbm.train(static_cast<const training_t&>(input), max_epochs);

                //Get the activation probabilities for the next level
                if(I < layers - 2){
                    next_a.clear();
                    next_a.reserve(input_size);
                    next_s.clear();
                    next_s.reserve(input_size);

                    for(std::size_t i = 0; i < input_size; ++i){
                        next_a.emplace_back(num_hidden);
                        next_s.emplace_back(num_hidden);
                    }

                    for(size_t i = 0; i < input_size; ++i){
                        rbm.activate_hidden(next_a[i], next_s[i], static_cast<const training_t&>(input)[i], static_cast<const training_t&>(input)[i]);
                    }

                    input = std::ref(next_a);
                }
            }
        });
    }

    /*}}}*/

    /*{{{ With labels */

    template<typename Samples, typename Labels>
    void train_with_labels(const Samples& training_data, const Labels& training_labels, std::size_t labels, std::size_t max_epochs){
        dll_assert(training_data.size() == training_labels.size(), "There must be the same number of values than labels");
        dll_assert(num_visible<layers - 1>() == num_hidden<layers - 2>() + labels, "There is no room for the labels units");

        using training_t = std::vector<etl::dyn_vector<typename Samples::value_type::value_type>>;

        //Convert data to an useful form
        training_t data;
        data.reserve(training_data.size());

        for(auto& sample : training_data){
            data.emplace_back(sample);
        }

        auto input = std::cref(data);

        detail::for_each_i(tuples, [&input, &training_labels, labels, max_epochs](size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            static training_t next;

            next.reserve(static_cast<const training_t&>(input).size());

            rbm.train(static_cast<const training_t&>(input), max_epochs);

            if(I < layers - 1){
                auto append_labels = (I + 1 == layers - 1);

                for(auto& training_item : static_cast<const training_t&>(input)){
                    etl::dyn_vector<weight> next_item_a(num_hidden + (append_labels ? labels : 0));
                    etl::dyn_vector<weight> next_item_s(num_hidden + (append_labels ? labels : 0));
                    rbm.activate_hidden(next_item_a, next_item_s, training_item, training_item);
                    next.emplace_back(std::move(next_item_a));
                }

                //If the next layers is the last layer
                if(append_labels){
                    for(size_t i = 0; i < training_labels.size(); ++i){
                        auto label = training_labels[i];

                        for(size_t l = 0; l < labels; ++l){
                            next[i][num_hidden + l] = label == l ? 1.0 : 0.0;
                        }
                    }
                }
            }

            input = std::cref(next);
        });
    }

    template<typename TrainingItem>
    size_t predict_labels(const TrainingItem& item_data, std::size_t labels){
        dll_assert(num_visible<layers - 1>() == num_hidden<layers - 2>() + labels, "There is no room for the labels units");

        etl::dyn_vector<typename TrainingItem::value_type> item(item_data);

        etl::dyn_vector<weight> output_a(num_visible<layers - 1>());
        etl::dyn_vector<weight> output_s(num_visible<layers - 1>());

        auto input_ref = std::cref(item);

        detail::for_each_i(tuples, [labels,&input_ref,&output_a,&output_s](size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            auto& input = static_cast<const etl::dyn_vector<weight>&>(input_ref);

            if(I == layers - 1){
                static etl::dyn_vector<weight> h1_a(num_hidden);
                static etl::dyn_vector<weight> h1_s(num_hidden);

                rbm.activate_hidden(h1_a, h1_s, input, input);
                rbm.activate_visible(h1_a, h1_s, output_a, output_s);
            } else {
                static etl::dyn_vector<weight> next_a(num_hidden);
                static etl::dyn_vector<weight> next_s(num_hidden);
                static etl::dyn_vector<weight> big_next_a(num_hidden + labels);

                rbm.activate_hidden(next_a, next_s, input, input);

                //If the next layers is the last layer
                if(I + 1 == layers - 1){
                    for(std::size_t i = 0; i < next_a.size(); ++i){
                        big_next_a[i] = next_a[i];
                    }

                    for(size_t l = 0; l < labels; ++l){
                        big_next_a[num_hidden + l] = 0.1;
                    }

                    input_ref = std::cref(big_next_a);
                } else {
                    input_ref = std::cref(next_a);
                }

            }
        });

        size_t label = 0;
        weight max = 0;
        for(size_t l = 0; l < labels; ++l){
            auto value = output_a[num_visible<layers - 1>() - labels + l];

            if(value > max){
                max = value;
                label = l;
            }
        }

        return label;
    }

    /*}}}*/

    /*{{{ Predict */

    template<typename Sample>
    etl::dyn_vector<weight> predict_weights(const Sample& item_data){
        etl::dyn_vector<weight> result(num_hidden<layers - 1>());

        etl::dyn_vector<typename Sample::value_type> item(item_data);

        auto input = std::cref(item);

        detail::for_each_i(tuples, [&item, &input, &result](std::size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            static etl::dyn_vector<weight> next(num_hidden);
            static etl::dyn_vector<weight> next_s(num_hidden);
            auto& output = (I == layers - 1) ? result : next;

            rbm.activate_hidden(output, next_s, static_cast<const Sample&>(input), static_cast<const Sample&>(input));

            input = std::cref(next);
        });

        return result;
    }

    template<typename Weights>
    size_t predict_final(const Weights& result){
        size_t label = 0;
        weight max = 0;
        for(size_t l = 0; l < result.size(); ++l){
            auto value = result[l];

            if(value > max){
                max = value;
                label = l;
            }
        }

        return label;
    }

    template<typename Sample>
    size_t predict(const Sample& item){
        auto result = predict_weights(item);
        return predict_final(result);;
    }

    /*}}}*/

    template<typename Samples, typename Labels>
    weight fine_tune(const Samples& training_data, Labels& labels, size_t max_epochs, size_t batch_size){
        typedef typename std::remove_reference<decltype(*this)>::type this_type;

        dll::dbn_trainer<this_type> trainer;
        return trainer.train(*this, training_data, labels, max_epochs, batch_size);
    }
};

} //end of namespace dll

#endif
<commit_msg>Add another way to use predict weights<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DBN_DBN_HPP
#define DBN_DBN_HPP

#include <tuple>

#include "rbm.hpp"
#include "tuple_utils.hpp"
#include "dbn_trainer.hpp"
#include "conjugate_gradient.hpp"

namespace dll {

/*!
 * \brief A Deep Belief Network implementation
 */
template<typename Desc>
struct dbn {
    using desc = Desc;

    using tuple_type = typename desc::layers::tuple_type;
    tuple_type tuples;

    static constexpr const std::size_t layers = desc::layers::layers;

    template <std::size_t N>
    using rbm_type = typename std::tuple_element<N, tuple_type>::type;

    using weight = typename rbm_type<0>::weight;

    double learning_rate = 0.1;

    //No arguments by default
    dbn(){};

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

    //No moving
    dbn(dbn&& dbn) = delete;
    dbn& operator=(dbn&& dbn) = delete;

    void display() const {
        std::size_t parameters = 0;

        detail::for_each(tuples, [&parameters](auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_visible = rbm_t::num_visible;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            parameters += num_visible * num_hidden;

            std::cout << "RBM: " << num_visible << "->" << num_hidden
                << ": " << (num_visible * num_hidden) << " parameters" << std::endl;
        });

        std::cout << "Total parameters: " << parameters << std::endl;
    }

    void store(std::ostream& os) const {
        detail::for_each(tuples, [&os](auto& rbm){
            rbm.store(os);
        });
    }

    void load(std::istream& is){
        detail::for_each(tuples, [&is](auto& rbm){
            rbm.load(is);
        });
    }

    template<std::size_t N>
    auto layer() -> typename std::add_lvalue_reference<rbm_type<N>>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    constexpr auto layer() const -> typename std::add_lvalue_reference<typename std::add_const<rbm_type<N>>::type>::type {
        return std::get<N>(tuples);
    }

    template<std::size_t N>
    static constexpr std::size_t num_visible(){
        return rbm_type<N>::num_visible;
    }

    template<std::size_t N>
    static constexpr std::size_t num_hidden(){
        return rbm_type<N>::num_hidden;
    }

    /*{{{ Pretrain */

    /*!
     * \brief Pretrain the network by training all layers in an unsupervised
     * manner.
     */
    template<typename Samples>
    void pretrain(const Samples& training_data, std::size_t max_epochs){
        using training_t = std::vector<etl::dyn_vector<typename Samples::value_type::value_type>>;

        //Convert data to an useful form
        training_t data;
        data.reserve(training_data.size());

        for(auto& sample : training_data){
            data.emplace_back(sample);
        }

        training_t next_a;
        training_t next_s;

        auto input = std::ref(data);

        detail::for_each_i(tuples, [&input, &next_a, &next_s, max_epochs](std::size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_visible = rbm_t::num_visible;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            auto input_size = static_cast<const training_t&>(input).size();

            //Train each layer but the last one
            if(I <= layers - 2){
                std::cout << "DBN: Train layer " << I << " (" << num_visible << "->" << num_hidden << ") with " << input_size << " entries" << std::endl;

                rbm.train(static_cast<const training_t&>(input), max_epochs);

                //Get the activation probabilities for the next level
                if(I < layers - 2){
                    next_a.clear();
                    next_a.reserve(input_size);
                    next_s.clear();
                    next_s.reserve(input_size);

                    for(std::size_t i = 0; i < input_size; ++i){
                        next_a.emplace_back(num_hidden);
                        next_s.emplace_back(num_hidden);
                    }

                    for(size_t i = 0; i < input_size; ++i){
                        rbm.activate_hidden(next_a[i], next_s[i], static_cast<const training_t&>(input)[i], static_cast<const training_t&>(input)[i]);
                    }

                    input = std::ref(next_a);
                }
            }
        });
    }

    /*}}}*/

    /*{{{ With labels */

    template<typename Samples, typename Labels>
    void train_with_labels(const Samples& training_data, const Labels& training_labels, std::size_t labels, std::size_t max_epochs){
        dll_assert(training_data.size() == training_labels.size(), "There must be the same number of values than labels");
        dll_assert(num_visible<layers - 1>() == num_hidden<layers - 2>() + labels, "There is no room for the labels units");

        using training_t = std::vector<etl::dyn_vector<typename Samples::value_type::value_type>>;

        //Convert data to an useful form
        training_t data;
        data.reserve(training_data.size());

        for(auto& sample : training_data){
            data.emplace_back(sample);
        }

        auto input = std::cref(data);

        detail::for_each_i(tuples, [&input, &training_labels, labels, max_epochs](size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            static training_t next;

            next.reserve(static_cast<const training_t&>(input).size());

            rbm.train(static_cast<const training_t&>(input), max_epochs);

            if(I < layers - 1){
                auto append_labels = (I + 1 == layers - 1);

                for(auto& training_item : static_cast<const training_t&>(input)){
                    etl::dyn_vector<weight> next_item_a(num_hidden + (append_labels ? labels : 0));
                    etl::dyn_vector<weight> next_item_s(num_hidden + (append_labels ? labels : 0));
                    rbm.activate_hidden(next_item_a, next_item_s, training_item, training_item);
                    next.emplace_back(std::move(next_item_a));
                }

                //If the next layers is the last layer
                if(append_labels){
                    for(size_t i = 0; i < training_labels.size(); ++i){
                        auto label = training_labels[i];

                        for(size_t l = 0; l < labels; ++l){
                            next[i][num_hidden + l] = label == l ? 1.0 : 0.0;
                        }
                    }
                }
            }

            input = std::cref(next);
        });
    }

    template<typename TrainingItem>
    size_t predict_labels(const TrainingItem& item_data, std::size_t labels){
        dll_assert(num_visible<layers - 1>() == num_hidden<layers - 2>() + labels, "There is no room for the labels units");

        etl::dyn_vector<typename TrainingItem::value_type> item(item_data);

        etl::dyn_vector<weight> output_a(num_visible<layers - 1>());
        etl::dyn_vector<weight> output_s(num_visible<layers - 1>());

        auto input_ref = std::cref(item);

        detail::for_each_i(tuples, [labels,&input_ref,&output_a,&output_s](size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            auto& input = static_cast<const etl::dyn_vector<weight>&>(input_ref);

            if(I == layers - 1){
                static etl::dyn_vector<weight> h1_a(num_hidden);
                static etl::dyn_vector<weight> h1_s(num_hidden);

                rbm.activate_hidden(h1_a, h1_s, input, input);
                rbm.activate_visible(h1_a, h1_s, output_a, output_s);
            } else {
                static etl::dyn_vector<weight> next_a(num_hidden);
                static etl::dyn_vector<weight> next_s(num_hidden);
                static etl::dyn_vector<weight> big_next_a(num_hidden + labels);

                rbm.activate_hidden(next_a, next_s, input, input);

                //If the next layers is the last layer
                if(I + 1 == layers - 1){
                    for(std::size_t i = 0; i < next_a.size(); ++i){
                        big_next_a[i] = next_a[i];
                    }

                    for(size_t l = 0; l < labels; ++l){
                        big_next_a[num_hidden + l] = 0.1;
                    }

                    input_ref = std::cref(big_next_a);
                } else {
                    input_ref = std::cref(next_a);
                }

            }
        });

        size_t label = 0;
        weight max = 0;
        for(size_t l = 0; l < labels; ++l){
            auto value = output_a[num_visible<layers - 1>() - labels + l];

            if(value > max){
                max = value;
                label = l;
            }
        }

        return label;
    }

    /*}}}*/

    /*{{{ Predict */

    template<typename Sample, typename Output>
    void predict_weights(const Sample& item_data, Output& result){
        etl::dyn_vector<typename Sample::value_type> item(item_data);

        auto input = std::cref(item);

        detail::for_each_i(tuples, [&item, &input, &result](std::size_t I, auto& rbm){
            if(I != layers - 1){
                typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
                constexpr const auto num_hidden = rbm_t::num_hidden;

                static etl::dyn_vector<weight> next(num_hidden);
                static etl::dyn_vector<weight> next_s(num_hidden);

                rbm.activate_hidden(next, next_s, static_cast<const Sample&>(input), static_cast<const Sample&>(input));

                input = std::cref(next);
            }
        });

        constexpr const auto num_hidden = rbm_type<layers - 1>::num_hidden;

        static etl::dyn_vector<weight> next_s(num_hidden);

        layer<layers - 1>().activate_hidden(result, next_s, static_cast<const Sample&>(input), static_cast<const Sample&>(input));
    }

    template<typename Sample>
    etl::dyn_vector<weight> predict_weights(const Sample& item_data){
        etl::dyn_vector<weight> result(num_hidden<layers - 1>());

        etl::dyn_vector<typename Sample::value_type> item(item_data);

        auto input = std::cref(item);

        detail::for_each_i(tuples, [&item, &input, &result](std::size_t I, auto& rbm){
            typedef typename std::remove_reference<decltype(rbm)>::type rbm_t;
            constexpr const auto num_hidden = rbm_t::num_hidden;

            static etl::dyn_vector<weight> next(num_hidden);
            static etl::dyn_vector<weight> next_s(num_hidden);
            auto& output = (I == layers - 1) ? result : next;

            rbm.activate_hidden(output, next_s, static_cast<const Sample&>(input), static_cast<const Sample&>(input));

            input = std::cref(next);
        });

        return result;
    }

    template<typename Weights>
    size_t predict_final(const Weights& result){
        size_t label = 0;
        weight max = 0;
        for(size_t l = 0; l < result.size(); ++l){
            auto value = result[l];

            if(value > max){
                max = value;
                label = l;
            }
        }

        return label;
    }

    template<typename Sample>
    size_t predict(const Sample& item){
        auto result = predict_weights(item);
        return predict_final(result);;
    }

    /*}}}*/

    template<typename Samples, typename Labels>
    weight fine_tune(const Samples& training_data, Labels& labels, size_t max_epochs, size_t batch_size){
        typedef typename std::remove_reference<decltype(*this)>::type this_type;

        dll::dbn_trainer<this_type> trainer;
        return trainer.train(*this, training_data, labels, max_epochs, batch_size);
    }
};

} //end of namespace dll

#endif
<|endoftext|>


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

/*!
 * \file
 * \brief Contains runtime matrix implementation
 */

#pragma once

#include "etl/dyn_base.hpp"    //The base class and utilities

namespace etl {

template <typename Matrix, typename Enable = void>
struct static_check_square {};

template <typename Matrix>
struct static_check_square<Matrix, std::enable_if_t<all_fast<Matrix>::value && is_2d<Matrix>::value>> {
    static_assert(etl_traits<Matrix>::template dim<0>() == etl_traits<Matrix>::template dim<1>(), "Static matrix must be square");
};

/*!
 * \brief Matrix with run-time fixed dimensions.
 *
 * The matrix support an arbitrary number of dimensions.
 */
template <typename Matrix>
struct sym_matrix final {
    using matrix_t = Matrix; ///< The adapted matrix type

    static_assert(etl_traits<matrix_t>::dimensions() == 2, "Symmetric matrix must be two-dimensional");
    using scs = static_check_square<matrix_t>; ///< static_check trick

    static constexpr const std::size_t n_dimensions = matrix_t::D;                           ///< The number of dimensions
    static constexpr const order storage_order      = matrix_t::SO;                          ///< The storage order
    static constexpr const std::size_t alignment    = intrinsic_traits<matrix_t>::alignment; ///< The memory alignment

    using value_type        = value_t<matrix_t>; ///< The value type
    using memory_type       = value_type*;       ///< The memory type
    using const_memory_type = const value_type*; ///< The const memory type
    using iterator          = memory_type;       ///< The type of iterator
    using const_iterator    = const_memory_type; ///< The type of const iterator

    /*!
     * \brief The vectorization type for V
     */
    template<typename V = default_vec>
    using vec_type               = typename V::template vec_type<value_t>;

private:
    matrix_t matrix; ///< The adapted matrix

public:
    sym_matrix() noexcept {
        matrix = value_type(0);
    }

    sym_matrix(value_type value) noexcept : matrix(value) {
        //Nothing else to init
    }

    sym_matrix(std::size_t dim) noexcept : matrix(dim, dim) {
        matrix = value_type(0);
    }

    sym_matrix(std::size_t dim, value_type value) noexcept : matrix(dim, dim, value) {
        //Nothing else to init
    }

    sym_matrix(const sym_matrix& rhs) = default;
    sym_matrix& operator=(const sym_matrix& rhs) = default;

    sym_matrix(sym_matrix&& rhs) = default;
    sym_matrix& operator=(sym_matrix&& rhs) = default;

    /*!
     * \brief Returns the number of dimensions of the matrix
     * \return the number of dimensions of the matrix
     */
    static constexpr std::size_t dimensions() noexcept {
        return 2;
    }
};

} //end of namespace etl
<commit_msg>More features to the symmetric matrix adapter<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Contains runtime matrix implementation
 */

#pragma once

#include "etl/dyn_base.hpp"    //The base class and utilities

namespace etl {

namespace sym_detail {

template <typename Matrix, typename Enable = void>
struct static_check_square {};

template <typename Matrix>
struct static_check_square<Matrix, std::enable_if_t<all_fast<Matrix>::value && is_2d<Matrix>::value>> {
    static_assert(etl_traits<Matrix>::template dim<0>() == etl_traits<Matrix>::template dim<1>(), "Static matrix must be square");
};

/*!
 * \brief A proxy representing a reference to a mutable element of a symmetric matrix
 * \tparam M The matrix type
 */
template <typename M>
struct symmetric_reference {
    using matrix_type        = M;                                ///< The matrix type
    using value_type         = typename matrix_type::value_type; ///< The value type
    using raw_pointer_type   = value_type*;                      ///< A raw pointer type
    using raw_reference_type = value_type&;                      ///< A raw reference type

    matrix_type& matrix;   ///< Reference to the matrix
    std::size_t i;         ///< The first index
    std::size_t j;         ///< The second index
    value_type& value;     ///< Reference to the value
    value_type& sym_value; ///< Reference to the symmetric value

    /*!
     * \brief Constructs a new symmetric_reference
     * \param matrix The source matrix
     * \param i The index i of the first dimension
     * \param j The index j of the second dimension
     */
    symmetric_reference(matrix_type& matrix, std::size_t i, std::size_t j)
            : matrix(matrix), i(i), j(j), value(matrix(i, j)), sym_value(matrix(j, i)) {
        //Nothing else to init
    }

    /*!
     * \brief Sets a new value to the proxy reference
     * \param rhs The new value
     * \return a reference to the proxy reference
     */
    symmetric_reference& operator=(const value_type& rhs) {
        value = rhs;
        if(i != j){
            sym_value = rhs;
        }
        return *this;
    }

    /*!
     * \brief Adds a new value to the proxy reference
     * \param rhs The new value
     * \return a reference to the proxy reference
     */
    symmetric_reference& operator+=(value_type rhs) {
        value += rhs;
        if(i != j){
            sym_value += rhs;
        }
        return *this;
    }

    /*!
     * \brief Subtract a new value from the proxy reference
     * \param rhs The new value
     * \return a reference to the proxy reference
     */
    symmetric_reference& operator-=(value_type rhs) {
        value -= rhs;
        if(i != j){
            sym_value -= rhs;
        }
        return *this;
    }

    /*!
     * \brief Multiply by a new value the proxy reference
     * \param rhs The new value
     * \return a reference to the proxy reference
     */
    symmetric_reference& operator*=(value_type rhs) {
        value *= rhs;
        if(i != j){
            sym_value *= rhs;
        }
        return *this;
    }

    /*!
     * \brief Divide by a new value the proxy reference
     * \param rhs The new value
     * \return a reference to the proxy reference
     */
    symmetric_reference& operator/=(value_type rhs) {
        value /= rhs;
        if(i != j){
            sym_value /= rhs;
        }
        return *this;
    }

    /*!
     * \brief Modulo by a new value the proxy reference
     * \param rhs The new value
     * \return a reference to the proxy reference
     */
    symmetric_reference& operator%=(value_type rhs) {
        value %= rhs;
        if(i != j){
            sym_value %= rhs;
        }
        return *this;
    }

    /*!
     * \brief Casts the proxy reference to the raw reference type
     * \return a raw reference to the element
     */
    operator const value_type&() {
        return value;
    }
};

} //end of namespace sym_detail

/*!
 * \brief A symmetric matrix adapter.
 *
 * This is only a prototype.
 */
template <typename Matrix>
struct sym_matrix final {
    using matrix_t = Matrix; ///< The adapted matrix type

    static_assert(etl_traits<matrix_t>::is_value, "Symmetric matrix only works with value classes");
    static_assert(etl_traits<matrix_t>::dimensions() == 2, "Symmetric matrix must be two-dimensional");
    using scs = sym_detail::static_check_square<matrix_t>; ///< static_check trick

    static constexpr const std::size_t n_dimensions = matrix_t::D;                           ///< The number of dimensions
    static constexpr const order storage_order      = matrix_t::SO;                          ///< The storage order
    static constexpr const std::size_t alignment    = intrinsic_traits<matrix_t>::alignment; ///< The memory alignment

    using value_type        = value_t<matrix_t>; ///< The value type
    using memory_type       = value_type*;       ///< The memory type
    using const_memory_type = const value_type*; ///< The const memory type
    using iterator          = memory_type;       ///< The type of iterator
    using const_iterator    = const_memory_type; ///< The type of const iterator

    /*!
     * \brief The vectorization type for V
     */
    template<typename V = default_vec>
    using vec_type               = typename V::template vec_type<value_t>;

private:
    matrix_t matrix; ///< The adapted matrix

public:
    sym_matrix() noexcept : matrix(value_type()) {
        //Nothing else to init
    }

    sym_matrix(value_type value) noexcept : matrix(value) {
        //Nothing else to init
    }

    sym_matrix(std::size_t dim) noexcept : matrix(dim, dim, value_type()) {
        //Nothing else to init
    }

    sym_matrix(std::size_t dim, value_type value) noexcept : matrix(dim, dim, value) {
        //Nothing else to init
    }

    sym_matrix(const sym_matrix& rhs) = default;
    sym_matrix& operator=(const sym_matrix& rhs) = default;

    sym_matrix(sym_matrix&& rhs) = default;
    sym_matrix& operator=(sym_matrix&& rhs) = default;

    /*!
     * \brief Returns the number of dimensions of the matrix
     * \return the number of dimensions of the matrix
     */
    static constexpr std::size_t dimensions() noexcept {
        return 2;
    }

    /*!
     * \brief Access the (i, j) element of the 2D matrix
     * \param i The index of the first dimension
     * \param j The index of the second dimension
     * \return a reference to the (i,j) element
     *
     * Accessing an element outside the matrix results in Undefined Behaviour.
     */
    sym_detail::symmetric_reference<matrix_t> operator()(std::size_t i, std::size_t j) noexcept {
        return {matrix, i, j};
    }

    /*!
     * \brief Access the (i, j) element of the 2D matrix
     * \param i The index of the first dimension
     * \param j The index of the second dimension
     * \return a reference to the (i,j) element
     *
     * Accessing an element outside the matrix results in Undefined Behaviour.
     */
    const value_type& operator()(std::size_t i, std::size_t j) const noexcept {
        return matrix(i, j);
    }

    /*!
     * \returns the value at the given index
     * This function never alters the state of the container.
     * \param i The index
     * \return the value at the given index.
     */
    value_type read_flat(std::size_t i) const noexcept {
        return matrix.read_flat(i);
    }
};

template <typename Matrix>
struct etl_traits<sym_matrix<Matrix>> : etl_traits<Matrix> {};

} //end of namespace etl
<|endoftext|>


<commit_before>#include "tpetra_solvers.h"

int symm = 0;

int main(int argc, char *argv[]) {
    bool success = false;
    try {
        json j;
        std::string outputDir, outputFile;
        if (argv[1] == NULL) {
            std::cout << "No input file was specified" << std::endl;
            std::cout << "Usage: ./tpetra_solvers <.mtx file> ['-d output_dir' | '-f output_file']" << std::endl;
            return -1;
        }
        for (int i = 2; i < argc; i++) {
            //std::cout << "arg[" << i << "]: " << argv[i] << std::endl;
            if (strcmp(argv[i], "-f") == 0) { //output to file
                i++;
                outputFile = argv[i];
            } else if (strcmp(argv[i], "-d") == 0) {
                i++;
                outputDir = argv[i];
            }
        }

        //  General setup for Teuchos/communication
        std::string inputFile = argv[1];
        belosSolvers = determineSolvers(inputFile);
        Teuchos::GlobalMPISession mpiSession(&argc, &argv);
        Platform &platform = Tpetra::DefaultPlatform::getDefaultPlatform();
        comm = platform.getComm();
        RCP<NT> node = platform.getNode();
        myRank = comm->getRank();

        RCP<MAT> A = Reader::readSparseFile(inputFile, comm, node, true);
        Teuchos::oblackholestream blackhole;
        std::ostream &out = (myRank == 0) ? std::cout : blackhole;
        std::ofstream outputLoc;

        //  How to output results
        if (outputDir.empty() && outputFile.empty()) {
            // Print to screen
            //fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(out));
            //*fos << "No output directory or file was specified. Printing to screen" << std::endl;
            unsigned long found = inputFile.find_last_of("/\\");
            inputFile = inputFile.substr(found + 1);
        } else if (outputDir.size() && outputFile.empty()) {
            // Print to directory
            unsigned long found = inputFile.find_last_of("/\\");
            std::string outputFilename = outputDir + "/" + inputFile.substr(found + 1) + ".json";
            if (myRank == 0)
                std::cout << "Printing to " << outputFilename << std::endl;
            inputFile = inputFile.substr(found + 1);
            outputLoc.open(outputFilename.c_str());
            //fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(outputLoc));
        } else if (outputDir.empty() && outputFile.size()) {
            if (myRank == 0)
                std::cout << "Printing to " << outputFile << std::endl;
            outputLoc.open(outputFile.c_str());
            //fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(outputLoc));
        }
        // Do all the work
        belosSolve(A, inputFile, j);
        if (myRank == 0)
	        outputLoc << std::setw(4) << j << "," << std::endl;
    }
    TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success)
}

RCP<PRE> getIfpack2Preconditoner(const RCP<const MAT> &A,
        std::string ifpack2PrecChoice) {
    RCP<PRE> prec;
    Ifpack2::Factory ifpack2Factory;
    prec = ifpack2Factory.create(ifpack2PrecChoice, A);
    prec->initialize();
    prec->compute();
    return prec;
}

RCP<BSM> getBelosSolver(const RCP<const MAT> &A,
        std::string belosSolverChoice) {
    Belos::SolverFactory<ST, MV, OP> belosFactory;
    RCP<ParameterList> solverParams = parameterList();
    Teuchos::Array<std::string> s = belosFactory.supportedSolverNames();
    //*fos << s << std::endl;
    solverParams->set("Verbosity", 0);
    //solverParams->set ("Num Blocks", 40);
    solverParams->set("Maximum Iterations", 10000);
    solverParams->set("Convergence Tolerance", 1.0e-5);
    RCP<BSM> solver = belosFactory.create(belosSolverChoice, solverParams);
    return solver;
}

//  https://code.google.com/p/trilinos/wiki/Tpetra_Belos_CreateSolver
void belosSolve(const RCP<const MAT> &A, const std::string &inputFile, json &j) {
    // Create solver and preconditioner
    Teuchos::Time timer("timer", false);
    Teuchos::Time overall_timer("overall_timer", false);
    RCP<PRE> prec;
    RCP<BSM> solver;
    RCP<MV> origVector = rcp(new MV(A->getRangeMap(), 1));
    origVector->randomize();

    std::string matrixName = inputFile.substr(inputFile.find_last_of("/") + 1);

    overall_timer.start(true);
    //  Solving linear system with all prec/solver pairs
    for (auto precIter : ifpack2Precs) {
        for (auto solverIter : belos_all) {
            timer.start(true);
            solver = Teuchos::null;
            prec = Teuchos::null;
            //*fos << inputFile << ", " << comm->getSize() << ", ";
            //j[inputFile][solverIter][precIter]["matrix_name"] = inputFile;
            j[matrixName][solverIter][precIter]["num_procs"] = comm->getSize();
            try {
                solver = getBelosSolver(A, solverIter);
                if (precIter.compare("None"))
                    prec = getIfpack2Preconditoner(A, precIter);
            } catch (const std::exception &exc) {
                //*fos << solverIter << ", " << precIter << ", PREC-SOLVER_ERROR, ";
                //*fos << timer.totalElapsedTime() << std::endl;
                j[matrixName][solverIter][precIter]["status"] = "prec/solver_error";
                if (myRank == 0)
                    std::cerr << exc.what() << std::endl;
                break;
            }
            try {
                //  Create the x and randomized b multivectors
                RCP<MV> x = rcp(new MV(A->getDomainMap(), 1));
                origVector->randomize();
                RCP<MV> b = origVector;

                //  Create the linear problem
                RCP<LP> problem = rcp(new LP(A, x, b));
                if (precIter.compare("None"))
                    problem->setRightPrec(prec);
                problem->setProblem(); //done adding to the linear problem
                solver->setProblem(problem); //add the linear problem to the solver
            } catch (const std::exception &exc) {
                //*fos << solverIter << ", " << precIter << ", CREATION_ERROR, ";
                //*fos << timer.totalElapsedTime() << std::endl;
                //j["solver"] = solverIter;
                //j["preconditioner"] = precIter;
                //j["status"] = "creation_error";
                j[matrixName][solverIter][precIter]["status"] = "creation_error";
                if (myRank == 0)
                    std::cerr << exc.what() << std::endl;
                break;
            }
            try {
                //  Solve the linear problem
                Belos::ReturnType result = solver->solve();
                timer.stop();
                //*fos << std::string(solverIter) << ", " << precIter; // output solver/prec pair
                if (result == Belos::Converged) {
                    //*fos << ", converged, ";
                    j[matrixName][solverIter][precIter]["status"] = "converged";
                } else {
                    //*fos << ", unconverged, ";
                    j[matrixName][solverIter][precIter]["status"] = "unconverged";
                }
                //*fos << solver->getNumIters() << ", " << timer.totalElapsedTime() << std::endl;
                //j["solver"] = solverIter;
                //j["preconditioner"] = precIter;
                //j["iterations"] = solver->getNumIters();
                j[matrixName][solverIter][precIter]["time"] = timer.totalElapsedTime();
                j[matrixName][solverIter][precIter]["iterations"] = solver->getNumIters();
                //j["time"] = timer.totalElapsedTime();
            } catch (const std::exception &exc) {
                //*fos << solverIter << ", " << precIter << ", SOLVING_ERROR, ";
                //*fos << timer.totalElapsedTime() << std::endl;
                //j["solver"] = solverIter;
                //j["preconditioner"] = precIter;
                //j["status"] = "solving_error";
                j[matrixName][solverIter][precIter]["status"] = "solving_error";
                if (myRank == 0)
                    std::cerr << exc.what() << std::endl;
                break;
            }
        }
    }
}

STRINGS determineSolvers(const std::string &inputFile) {
    std::ifstream file(inputFile);
    std::string firstLine, firstNumbers;
    unsigned int rows, cols;
    if (file.good()) {
        std::getline(file, firstLine);
        std::getline(file, firstNumbers);
        while (firstNumbers.find("%") == 0) {
            std::getline(file, firstNumbers);
        }
        std::stringstream ss(firstNumbers);
        ss >> rows >> cols;
    }
    file.close();
    /*
    if (firstLine.find("symmetric") != std::string::npos) { // include all
        symm = 1;
        return belos_all;
    } else if (firstLine.find("general") != std::string::npos) { // only include sq+rec
        symm = 0;
        return belos_sq;
    } else {
        //  Should never be here
        exit(-1);
    }
    */
    return belos_all;
}
<commit_msg>Working json output when using >1 process<commit_after>#include "tpetra_solvers.h"

int symm = 0;

int main(int argc, char *argv[]) {
    bool success = false;
    try {
        json j;
        std::string outputDir, outputFile;
        if (argv[1] == NULL) {
            std::cout << "No input file was specified" << std::endl;
            std::cout << "Usage: ./tpetra_solvers <.mtx file> ['-d output_dir' | '-f output_file']" << std::endl;
            return -1;
        }
        for (int i = 2; i < argc; i++) {
            //std::cout << "arg[" << i << "]: " << argv[i] << std::endl;
            if (strcmp(argv[i], "-f") == 0) { //output to file
                i++;
                outputFile = argv[i];
            } else if (strcmp(argv[i], "-d") == 0) {
                i++;
                outputDir = argv[i];
            }
        }

        //  General setup for Teuchos/communication
        std::string inputFile = argv[1];
        belosSolvers = determineSolvers(inputFile);
        Teuchos::GlobalMPISession mpiSession(&argc, &argv);
        Platform &platform = Tpetra::DefaultPlatform::getDefaultPlatform();
        comm = platform.getComm();
        RCP<NT> node = platform.getNode();
        myRank = comm->getRank();

        RCP<MAT> A = Reader::readSparseFile(inputFile, comm, node, true);
        Teuchos::oblackholestream blackhole;
        std::ostream &out = (myRank == 0) ? std::cout : blackhole;
        std::ofstream outputLoc;

        //  How to output results
        if (outputDir.empty() && outputFile.empty()) {
            // Print to screen
            //fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(out));
            //*fos << "No output directory or file was specified. Printing to screen" << std::endl;
            unsigned long found = inputFile.find_last_of("/\\");
            inputFile = inputFile.substr(found + 1);
        } else if (outputDir.size() && outputFile.empty()) {
            // Print to directory
            unsigned long found = inputFile.find_last_of("/\\");
            std::string outputFilename = outputDir + "/" + inputFile.substr(found + 1) + ".json";
            if (myRank == 0) {
                std::cout << "Printing to " << outputFilename << std::endl;
                inputFile = inputFile.substr(found + 1);
                outputLoc.open(outputFilename.c_str());
            }
            //fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(outputLoc));
        } else if (outputDir.empty() && outputFile.size()) {
            if (myRank == 0) {
                std::cout << "Printing to " << outputFile << std::endl;
                outputLoc.open(outputFile.c_str());
            }
            //fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(outputLoc));
        }
        // Do all the work
        belosSolve(A, inputFile, j);
        if (myRank == 0) {
	        outputLoc << std::setw(4) << j << "," << std::endl;
            outputLoc.close();
        }
    }
    TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success)
}

RCP<PRE> getIfpack2Preconditoner(const RCP<const MAT> &A,
        std::string ifpack2PrecChoice) {
    RCP<PRE> prec;
    Ifpack2::Factory ifpack2Factory;
    prec = ifpack2Factory.create(ifpack2PrecChoice, A);
    prec->initialize();
    prec->compute();
    return prec;
}

RCP<BSM> getBelosSolver(const RCP<const MAT> &A,
        std::string belosSolverChoice) {
    Belos::SolverFactory<ST, MV, OP> belosFactory;
    RCP<ParameterList> solverParams = parameterList();
    Teuchos::Array<std::string> s = belosFactory.supportedSolverNames();
    //*fos << s << std::endl;
    solverParams->set("Verbosity", 0);
    //solverParams->set ("Num Blocks", 40);
    solverParams->set("Maximum Iterations", 10000);
    solverParams->set("Convergence Tolerance", 1.0e-5);
    RCP<BSM> solver = belosFactory.create(belosSolverChoice, solverParams);
    return solver;
}

//  https://code.google.com/p/trilinos/wiki/Tpetra_Belos_CreateSolver
void belosSolve(const RCP<const MAT> &A, const std::string &inputFile, json &j) {
    // Create solver and preconditioner
    Teuchos::Time timer("timer", false);
    Teuchos::Time overall_timer("overall_timer", false);
    RCP<PRE> prec;
    RCP<BSM> solver;
    RCP<MV> origVector = rcp(new MV(A->getRangeMap(), 1));
    origVector->randomize();

    std::string matrixName = inputFile.substr(inputFile.find_last_of("/") + 1);

    overall_timer.start(true);
    //  Solving linear system with all prec/solver pairs
    for (auto precIter : ifpack2Precs) {
        for (auto solverIter : belos_all) {
            timer.start(true);
            solver = Teuchos::null;
            prec = Teuchos::null;
            //*fos << inputFile << ", " << comm->getSize() << ", ";
            //j[inputFile][solverIter][precIter]["matrix_name"] = inputFile;
            if (myRank == 0)
                j[matrixName][solverIter][precIter]["num_procs"] = comm->getSize();
            try {
                solver = getBelosSolver(A, solverIter);
                if (precIter.compare("None"))
                    prec = getIfpack2Preconditoner(A, precIter);
            } catch (const std::exception &exc) {
                //*fos << solverIter << ", " << precIter << ", PREC-SOLVER_ERROR, ";
                //*fos << timer.totalElapsedTime() << std::endl;
                if (myRank == 0) {
                    j[matrixName][solverIter][precIter]["status"] = "prec/solver_error";
                    std::cerr << exc.what() << std::endl;
                }
                break;
            }
            try {
                //  Create the x and randomized b multivectors
                RCP<MV> x = rcp(new MV(A->getDomainMap(), 1));
                origVector->randomize();
                RCP<MV> b = origVector;

                //  Create the linear problem
                RCP<LP> problem = rcp(new LP(A, x, b));
                if (precIter.compare("None"))
                    problem->setRightPrec(prec);
                problem->setProblem(); //done adding to the linear problem
                solver->setProblem(problem); //add the linear problem to the solver
            } catch (const std::exception &exc) {
                //*fos << solverIter << ", " << precIter << ", CREATION_ERROR, ";
                //*fos << timer.totalElapsedTime() << std::endl;
                //j["solver"] = solverIter;
                //j["preconditioner"] = precIter;
                //j["status"] = "creation_error";
                if (myRank == 0) {
                    j[matrixName][solverIter][precIter]["status"] = "creation_error";
                    std::cerr << exc.what() << std::endl;
                }
                break;
            }
            try {
                //  Solve the linear problem
                Belos::ReturnType result = solver->solve();
                timer.stop();
                //*fos << std::string(solverIter) << ", " << precIter; // output solver/prec pair
                if (result == Belos::Converged) {
                    //*fos << ", converged, ";
                    if (myRank == 0)
                        j[matrixName][solverIter][precIter]["status"] = "converged";
                } else {
                    //*fos << ", unconverged, ";
                    if (myRank == 0)
                        j[matrixName][solverIter][precIter]["status"] = "unconverged";
                }
                //*fos << solver->getNumIters() << ", " << timer.totalElapsedTime() << std::endl;
                //j["solver"] = solverIter;
                //j["preconditioner"] = precIter;
                //j["iterations"] = solver->getNumIters();
                if (myRank == 0) {
                    j[matrixName][solverIter][precIter]["time"] = timer.totalElapsedTime();
                    j[matrixName][solverIter][precIter]["iterations"] = solver->getNumIters();
                }
                //j["time"] = timer.totalElapsedTime();
            } catch (const std::exception &exc) {
                //*fos << solverIter << ", " << precIter << ", SOLVING_ERROR, ";
                //*fos << timer.totalElapsedTime() << std::endl;
                //j["solver"] = solverIter;
                //j["preconditioner"] = precIter;
                //j["status"] = "solving_error";
                if (myRank == 0) {
                    j[matrixName][solverIter][precIter]["status"] = "solving_error";
                    std::cerr << exc.what() << std::endl;
                }
                break;
            }
        }
    }
}

STRINGS determineSolvers(const std::string &inputFile) {
    std::ifstream file(inputFile);
    std::string firstLine, firstNumbers;
    unsigned int rows, cols;
    if (file.good()) {
        std::getline(file, firstLine);
        std::getline(file, firstNumbers);
        while (firstNumbers.find("%") == 0) {
            std::getline(file, firstNumbers);
        }
        std::stringstream ss(firstNumbers);
        ss >> rows >> cols;
    }
    file.close();
    /*
    if (firstLine.find("symmetric") != std::string::npos) { // include all
        symm = 1;
        return belos_all;
    } else if (firstLine.find("general") != std::string::npos) { // only include sq+rec
        symm = 0;
        return belos_sq;
    } else {
        //  Should never be here
        exit(-1);
    }
    */
    return belos_all;
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkTransferFunctionCanvas.h"

#include <itkObject.h>

#include <QColorDialog>
#include <QPainter>
#include <QMouseEvent>

QmitkTransferFunctionCanvas::QmitkTransferFunctionCanvas(QWidget * parent,
    Qt::WindowFlags f) :
  QWidget(parent, f),
  m_GrabbedHandle(-1),
  m_Lower(0.0),
  m_Upper(1.0),
  m_Min(0.0),
  m_Max(1.0),
  m_Histogram(0),
  m_ImmediateUpdate(false),
  m_Range(0.0f),
  m_LineEditAvailable(false),
  m_XEdit(0),
  m_YEdit(0)
{
  setEnabled(false);
  setFocusPolicy(Qt::ClickFocus);
}

void QmitkTransferFunctionCanvas::paintEvent(QPaintEvent* ev)
{
  QWidget::paintEvent(ev);
}

std::pair<int,int> QmitkTransferFunctionCanvas::FunctionToCanvas(
    std::pair<vtkFloatingPointType,vtkFloatingPointType> functionPoint)
{
  //std::cout<<"F2C.first: "<<(int)((functionPoint.first - m_Lower) /  (m_Upper - m_Lower) * width())<<" F2C.second: "<<(int)(height() * (1 - functionPoint.second))<<std::endl;
  return std::make_pair((int) ((functionPoint.first - m_Lower) / (m_Upper
      - m_Lower) * contentsRect().width()) + contentsRect().x(), (int) (contentsRect().height() * (1 - functionPoint.second)) + contentsRect().y());
}

std::pair<vtkFloatingPointType,vtkFloatingPointType> QmitkTransferFunctionCanvas::CanvasToFunction(
    std::pair<int,int> canvasPoint)
{
  //std::cout<<"C2F.first: "<<(canvasPoint.first * (m_Upper - m_Lower) / width() + m_Lower)<<" C2F.second: "<<(1.0 - (vtkFloatingPointType)canvasPoint.second / height())<<std::endl;
  return std::make_pair((canvasPoint.first - contentsRect().x()) * (m_Upper - m_Lower) / contentsRect().width()
      + m_Lower, 1.0 - (vtkFloatingPointType) (canvasPoint.second - contentsRect().y()) / contentsRect().height());
}

void QmitkTransferFunctionCanvas::mouseDoubleClickEvent(QMouseEvent* mouseEvent)
{
  int nearHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
  if (nearHandle != -1)
  {
    this->DoubleClickOnHandle(nearHandle);
  }
}

/** returns index of a near handle or -1 if none is near
 */
int QmitkTransferFunctionCanvas::GetNearHandle(int /*x*/, int /*y*/,
    unsigned int /*maxSquaredDistance*/)
{
  return -1;
}

void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent* mouseEvent)
{

  if (m_LineEditAvailable)
  {
    m_XEdit->clear();
    if(m_YEdit)
      m_YEdit->clear();
  }

  m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());

  if ( (mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1)
  {
    this->AddFunctionPoint(
        this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(),
            mouseEvent->pos().y())).first,
        this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second);
    m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(),
        mouseEvent->pos().y());
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  }
  else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1)
  {
     this->RemoveFunctionPoint(this->GetFunctionX(m_GrabbedHandle));
     m_GrabbedHandle = -1;
     mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  }
  update();

  // m_TransferFunction->UpdateVtkFunctions();
}

void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent* mouseEvent)
{
  if (m_GrabbedHandle != -1)
  {
    std::pair<vtkFloatingPointType,vtkFloatingPointType>
        newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(),
            mouseEvent->y()));

    // X Clamping
    {
      // Check with predecessor
      if( m_GrabbedHandle > 0 )
        if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1))
          newPos.first = this->GetFunctionX(m_GrabbedHandle);

      // Check with sucessor
      if( m_GrabbedHandle < this->GetFunctionSize()-1 )
        if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1))
          newPos.first = this->GetFunctionX(m_GrabbedHandle);

      // Clamping to histogramm
           if (newPos.first < m_Min) newPos.first = m_Min;
      else if (newPos.first > m_Max) newPos.first = m_Max;
    }

    // Y Clamping
    {
           if (newPos.second < 0.0) newPos.second = 0.0;
      else if (newPos.second > 1.0) newPos.second = 1.0;
    }

    // Move selected point
    this->MoveFunctionPoint(m_GrabbedHandle, newPos);

    /*
    // Search again selected point ??????? should not be required, seems like a legacy workaround/bugfix
    // and no longer required
    m_GrabbedHandle = -1;
    for (int i = 0; i < this->GetFunctionSize(); i++)
    {
      if (this->GetFunctionX(i) == newPos.first)
      {
        m_GrabbedHandle = i;
        break;
      }
    }
    */

    update();

    //if (m_ImmediateUpdate)
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();

  }
}

void QmitkTransferFunctionCanvas::mouseReleaseEvent(QMouseEvent*)
{
  // m_GrabbedHandle = -1;
  update();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}

void QmitkTransferFunctionCanvas::PaintHistogram(QPainter &p)
{
  if(m_Histogram)
  {
    p.save();

    p.setPen(Qt::gray);

    int displayWidth = contentsRect().width();
    int displayHeight = contentsRect().height();

    double windowLeft = m_Lower;
    double windowRight = m_Upper;

    double step = (windowRight-windowLeft)/double(displayWidth);

    double pos = windowLeft;

    for (int x = 0; x < displayWidth; x++)
    {
      double left = pos;
      double right = pos + step;

      float height = m_Histogram->GetRelativeBin( left , right );

      if (height >= 0)
        p.drawLine(x, displayHeight*(1-height), x, displayHeight);

      pos += step;
    }

    p.restore();
  }
}

void QmitkTransferFunctionCanvas::keyPressEvent(QKeyEvent * e)
{
  if( m_GrabbedHandle == -1)
    return;

  switch(e->key())
  {
    case Qt::Key_Delete:
      if(this->GetFunctionSize() > 1)
      {
        this->RemoveFunctionPoint(GetFunctionX(m_GrabbedHandle));
        m_GrabbedHandle = -1;
      }
      break;

    case Qt::Key_Left:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)-1 , GetFunctionY(m_GrabbedHandle))));
      break;

    case Qt::Key_Right:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)+1 , GetFunctionY(m_GrabbedHandle))));
      break;

    case Qt::Key_Up:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)+0.001)));
      break;

    case Qt::Key_Down:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)-0.001)));
      break;
  }

  update();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}

// Update immediatly while changing the transfer function
void QmitkTransferFunctionCanvas::SetImmediateUpdate(bool state)
{
  m_ImmediateUpdate = state;
}
<commit_msg>Revert "Data members initialised in QmitkTransferFunctionCanvas constructor" (bug-16367-trac-2891-crash-in-volume-visualisation-plugin)<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkTransferFunctionCanvas.h"

#include <itkObject.h>

#include <QColorDialog>
#include <QPainter>
#include <QMouseEvent>

QmitkTransferFunctionCanvas::QmitkTransferFunctionCanvas(QWidget * parent,
    Qt::WindowFlags f) :
  QWidget(parent, f), m_GrabbedHandle(-1), m_Lower(0.0f), m_Upper(1.0f), m_Min(
      0.0f), m_Max(1.0f)
{
  setEnabled(false);
  setFocusPolicy(Qt::ClickFocus);
  m_LineEditAvailable = false;
}

void QmitkTransferFunctionCanvas::paintEvent(QPaintEvent* ev)
{
  QWidget::paintEvent(ev);
}

std::pair<int,int> QmitkTransferFunctionCanvas::FunctionToCanvas(
    std::pair<vtkFloatingPointType,vtkFloatingPointType> functionPoint)
{
  //std::cout<<"F2C.first: "<<(int)((functionPoint.first - m_Lower) /  (m_Upper - m_Lower) * width())<<" F2C.second: "<<(int)(height() * (1 - functionPoint.second))<<std::endl;
  return std::make_pair((int) ((functionPoint.first - m_Lower) / (m_Upper
      - m_Lower) * contentsRect().width()) + contentsRect().x(), (int) (contentsRect().height() * (1 - functionPoint.second)) + contentsRect().y());
}

std::pair<vtkFloatingPointType,vtkFloatingPointType> QmitkTransferFunctionCanvas::CanvasToFunction(
    std::pair<int,int> canvasPoint)
{
  //std::cout<<"C2F.first: "<<(canvasPoint.first * (m_Upper - m_Lower) / width() + m_Lower)<<" C2F.second: "<<(1.0 - (vtkFloatingPointType)canvasPoint.second / height())<<std::endl;
  return std::make_pair((canvasPoint.first - contentsRect().x()) * (m_Upper - m_Lower) / contentsRect().width()
      + m_Lower, 1.0 - (vtkFloatingPointType) (canvasPoint.second - contentsRect().y()) / contentsRect().height());
}

void QmitkTransferFunctionCanvas::mouseDoubleClickEvent(QMouseEvent* mouseEvent)
{
  int nearHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());
  if (nearHandle != -1)
  {
    this->DoubleClickOnHandle(nearHandle);
  }
}

/** returns index of a near handle or -1 if none is near
 */
int QmitkTransferFunctionCanvas::GetNearHandle(int /*x*/, int /*y*/,
    unsigned int /*maxSquaredDistance*/)
{
  return -1;
}

void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent* mouseEvent)
{

  if (m_LineEditAvailable)
  {
    m_XEdit->clear();
    if(m_YEdit)
      m_YEdit->clear();
  }

  m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y());

  if ( (mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1)
  {
    this->AddFunctionPoint(
        this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(),
            mouseEvent->pos().y())).first,
        this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second);
    m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(),
        mouseEvent->pos().y());
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  }
  else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1)
  {
     this->RemoveFunctionPoint(this->GetFunctionX(m_GrabbedHandle));
     m_GrabbedHandle = -1;
     mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  }
  update();

  // m_TransferFunction->UpdateVtkFunctions();
}

void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent* mouseEvent)
{
  if (m_GrabbedHandle != -1)
  {
    std::pair<vtkFloatingPointType,vtkFloatingPointType>
        newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(),
            mouseEvent->y()));

    // X Clamping
    {
      // Check with predecessor
      if( m_GrabbedHandle > 0 )
        if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1))
          newPos.first = this->GetFunctionX(m_GrabbedHandle);

      // Check with sucessor
      if( m_GrabbedHandle < this->GetFunctionSize()-1 )
        if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1))
          newPos.first = this->GetFunctionX(m_GrabbedHandle);

      // Clamping to histogramm
           if (newPos.first < m_Min) newPos.first = m_Min;
      else if (newPos.first > m_Max) newPos.first = m_Max;
    }

    // Y Clamping
    {
           if (newPos.second < 0.0) newPos.second = 0.0;
      else if (newPos.second > 1.0) newPos.second = 1.0;
    }

    // Move selected point
    this->MoveFunctionPoint(m_GrabbedHandle, newPos);

    /*
    // Search again selected point ??????? should not be required, seems like a legacy workaround/bugfix
    // and no longer required
    m_GrabbedHandle = -1;
    for (int i = 0; i < this->GetFunctionSize(); i++)
    {
      if (this->GetFunctionX(i) == newPos.first)
      {
        m_GrabbedHandle = i;
        break;
      }
    }
    */

    update();

    //if (m_ImmediateUpdate)
      mitk::RenderingManager::GetInstance()->RequestUpdateAll();

  }
}

void QmitkTransferFunctionCanvas::mouseReleaseEvent(QMouseEvent*)
{
  // m_GrabbedHandle = -1;
  update();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}

void QmitkTransferFunctionCanvas::PaintHistogram(QPainter &p)
{
  if(m_Histogram)
  {
    p.save();

    p.setPen(Qt::gray);

    int displayWidth = contentsRect().width();
    int displayHeight = contentsRect().height();

    double windowLeft = m_Lower;
    double windowRight = m_Upper;

    double step = (windowRight-windowLeft)/double(displayWidth);

    double pos = windowLeft;

    for (int x = 0; x < displayWidth; x++)
    {
      double left = pos;
      double right = pos + step;

      float height = m_Histogram->GetRelativeBin( left , right );

      if (height >= 0)
        p.drawLine(x, displayHeight*(1-height), x, displayHeight);

      pos += step;
    }

    p.restore();
  }
}

void QmitkTransferFunctionCanvas::keyPressEvent(QKeyEvent * e)
{
  if( m_GrabbedHandle == -1)
    return;

  switch(e->key())
  {
    case Qt::Key_Delete:
      if(this->GetFunctionSize() > 1)
      {
        this->RemoveFunctionPoint(GetFunctionX(m_GrabbedHandle));
        m_GrabbedHandle = -1;
      }
      break;

    case Qt::Key_Left:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)-1 , GetFunctionY(m_GrabbedHandle))));
      break;

    case Qt::Key_Right:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)+1 , GetFunctionY(m_GrabbedHandle))));
      break;

    case Qt::Key_Up:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)+0.001)));
      break;

    case Qt::Key_Down:
      this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)-0.001)));
      break;
  }

  update();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}

// Update immediatly while changing the transfer function
void QmitkTransferFunctionCanvas::SetImmediateUpdate(bool state)
{
  m_ImmediateUpdate = state;
}
<|endoftext|>


<commit_before>// Author: Enrico Guiraud, Danilo Piparo CERN  12/2016

/*************************************************************************
 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/**
  \defgroup dataframe DataFrame
ROOT's RDataFrame allows to analyse data stored in TTrees with a high level interface.
*/

#ifndef ROOT_RDATAFRAME
#define ROOT_RDATAFRAME

#include "ROOT/RDF/RInterface.hxx"
#include "ROOT/RDF/Utils.hxx"
#include "ROOT/RStringView.hxx"
#include "RtypesCore.h"

#include <memory>
#include <ostream>
#include <string>
#include <vector>

class TDirectory;
class TTree;

namespace ROOT {
namespace RDF {
class RDataSource;
}

namespace RDFDetail = ROOT::Detail::RDF;
namespace RDFInternal = ROOT::Internal::RDF;
namespace TTraits = ROOT::TypeTraits;

class RDataFrame : public ROOT::RDF::RInterface<RDFDetail::RLoopManager> {
public:
   using ColumnNames_t = RDFDetail::ColumnNames_t;
   RDataFrame(std::string_view treeName, std::string_view filenameglob, const ColumnNames_t &defaultBranches = {});
   RDataFrame(std::string_view treename, const std::vector<std::string> &filenames,
              const ColumnNames_t &defaultBranches = {});
   RDataFrame(std::string_view treeName, ::TDirectory *dirPtr, const ColumnNames_t &defaultBranches = {});
   RDataFrame(TTree &tree, const ColumnNames_t &defaultBranches = {});
   RDataFrame(ULong64_t numEntries);
   RDataFrame(std::unique_ptr<ROOT::RDF::RDataSource>, const ColumnNames_t &defaultBranches = {});
};

} // ns ROOT

/// Print a RDataFrame at the prompt
namespace cling {
std::string printValue(ROOT::RDataFrame *tdf);
} // ns cling

#endif // ROOT_RDATAFRAME
<commit_msg>[DF] Include explicitly TROOT.h in RDataFrame.hxx<commit_after>// Author: Enrico Guiraud, Danilo Piparo CERN  12/2016

/*************************************************************************
 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/**
  \defgroup dataframe DataFrame
ROOT's RDataFrame allows to analyse data stored in TTrees with a high level interface.
*/

#ifndef ROOT_RDATAFRAME
#define ROOT_RDATAFRAME

#include "TROOT.h" // To allow ROOT::EnableImplicitMT without including ROOT.h
#include "ROOT/RDF/RInterface.hxx"
#include "ROOT/RDF/Utils.hxx"
#include "ROOT/RStringView.hxx"
#include "RtypesCore.h"

#include <memory>
#include <ostream>
#include <string>
#include <vector>

class TDirectory;
class TTree;

namespace ROOT {
namespace RDF {
class RDataSource;
}

namespace RDFDetail = ROOT::Detail::RDF;
namespace RDFInternal = ROOT::Internal::RDF;
namespace TTraits = ROOT::TypeTraits;

class RDataFrame : public ROOT::RDF::RInterface<RDFDetail::RLoopManager> {
public:
   using ColumnNames_t = RDFDetail::ColumnNames_t;
   RDataFrame(std::string_view treeName, std::string_view filenameglob, const ColumnNames_t &defaultBranches = {});
   RDataFrame(std::string_view treename, const std::vector<std::string> &filenames,
              const ColumnNames_t &defaultBranches = {});
   RDataFrame(std::string_view treeName, ::TDirectory *dirPtr, const ColumnNames_t &defaultBranches = {});
   RDataFrame(TTree &tree, const ColumnNames_t &defaultBranches = {});
   RDataFrame(ULong64_t numEntries);
   RDataFrame(std::unique_ptr<ROOT::RDF::RDataSource>, const ColumnNames_t &defaultBranches = {});
};

} // ns ROOT

/// Print a RDataFrame at the prompt
namespace cling {
std::string printValue(ROOT::RDataFrame *tdf);
} // ns cling

#endif // ROOT_RDATAFRAME
<|endoftext|>