<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2019 ScyllaDB Ltd.
 */

#pragma once

// Clang currently only supports the TS
#if __has_include(<coroutine>) && !defined(__clang__)
#include <coroutine>
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std
#elif __has_include(<experimental/coroutine>)
#include <experimental/coroutine>
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental
#else
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental

// We are not exactly allowed to defined anything in the std namespace, but this
// makes coroutines work with libstdc++. All of this is experimental anyway.

namespace std::experimental {

template<typename Promise = void>
class coroutine_handle {
    void* _pointer = nullptr;
public:
    coroutine_handle() = default;

    coroutine_handle &operator=(nullptr_t) noexcept {
        _pointer = nullptr;
        return *this;
    }

    explicit operator bool() const noexcept { return _pointer; }

    static coroutine_handle from_address(void* ptr) noexcept {
        coroutine_handle hndl;
        hndl._pointer =ptr;
        return hndl;
    }
    void* address() const noexcept { return _pointer; }

    static coroutine_handle from_promise(Promise& promise) noexcept {
        coroutine_handle hndl;
        hndl._pointer = __builtin_coro_promise(&promise, alignof(Promise), true);
        return hndl;
    }
    Promise& promise() const noexcept {
        return *reinterpret_cast<Promise*>(__builtin_coro_promise(_pointer, alignof(Promise), false));
    }

    void operator()() noexcept { resume(); }

    void resume() const noexcept { __builtin_coro_resume(_pointer); }
    void destroy() const noexcept { __builtin_coro_destroy(_pointer); }
    bool done() const noexcept { return __builtin_coro_done(_pointer); }

    operator coroutine_handle<>() const noexcept;
};

template<>
class coroutine_handle<void> {
    void* _pointer = nullptr;
public:
    coroutine_handle() = default;

    coroutine_handle &operator=(nullptr_t) noexcept {
        _pointer = nullptr;
        return *this;
    }

    explicit operator bool() const noexcept { return _pointer; }

    static coroutine_handle from_address(void* ptr) noexcept {
        coroutine_handle hndl;
        hndl._pointer = ptr;
        return hndl;
    }
    void* address() const noexcept { return _pointer; }

    void operator()() noexcept { resume(); }

    void resume() const noexcept { __builtin_coro_resume(_pointer); }
    void destroy() const noexcept { __builtin_coro_destroy(_pointer); }
    bool done() const noexcept { return __builtin_coro_done(_pointer); }
};

struct suspend_never {
    constexpr bool await_ready() const noexcept { return true; }
    template<typename T>
    constexpr void await_suspend(coroutine_handle<T>) noexcept { }
    constexpr void await_resume() noexcept { }
};

struct suspend_always {
    constexpr bool await_ready() const noexcept { return false; }
    template<typename T>
    constexpr void await_suspend(coroutine_handle<T>) noexcept { }
    constexpr void await_resume() noexcept { }
};

template <typename Promise>
coroutine_handle<Promise>::operator coroutine_handle<>() const noexcept {
    return coroutine_handle<>::from_address(address());
}

template<typename T, typename... Args>
class coroutine_traits { };

}

#endif
<commit_msg>std-coroutine: include <coroutine> for LLVM-15<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2019 ScyllaDB Ltd.
 */

#pragma once

// Clang < 15 only supports the TS
#if __has_include(<coroutine>) && (!defined(__clang__) || __clang_major__ >= 15)
#include <coroutine>
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std
#elif __has_include(<experimental/coroutine>)
#include <experimental/coroutine>
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental
#else
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental

// We are not exactly allowed to defined anything in the std namespace, but this
// makes coroutines work with libstdc++. All of this is experimental anyway.

namespace std::experimental {

template<typename Promise = void>
class coroutine_handle {
    void* _pointer = nullptr;
public:
    coroutine_handle() = default;

    coroutine_handle &operator=(nullptr_t) noexcept {
        _pointer = nullptr;
        return *this;
    }

    explicit operator bool() const noexcept { return _pointer; }

    static coroutine_handle from_address(void* ptr) noexcept {
        coroutine_handle hndl;
        hndl._pointer =ptr;
        return hndl;
    }
    void* address() const noexcept { return _pointer; }

    static coroutine_handle from_promise(Promise& promise) noexcept {
        coroutine_handle hndl;
        hndl._pointer = __builtin_coro_promise(&promise, alignof(Promise), true);
        return hndl;
    }
    Promise& promise() const noexcept {
        return *reinterpret_cast<Promise*>(__builtin_coro_promise(_pointer, alignof(Promise), false));
    }

    void operator()() noexcept { resume(); }

    void resume() const noexcept { __builtin_coro_resume(_pointer); }
    void destroy() const noexcept { __builtin_coro_destroy(_pointer); }
    bool done() const noexcept { return __builtin_coro_done(_pointer); }

    operator coroutine_handle<>() const noexcept;
};

template<>
class coroutine_handle<void> {
    void* _pointer = nullptr;
public:
    coroutine_handle() = default;

    coroutine_handle &operator=(nullptr_t) noexcept {
        _pointer = nullptr;
        return *this;
    }

    explicit operator bool() const noexcept { return _pointer; }

    static coroutine_handle from_address(void* ptr) noexcept {
        coroutine_handle hndl;
        hndl._pointer = ptr;
        return hndl;
    }
    void* address() const noexcept { return _pointer; }

    void operator()() noexcept { resume(); }

    void resume() const noexcept { __builtin_coro_resume(_pointer); }
    void destroy() const noexcept { __builtin_coro_destroy(_pointer); }
    bool done() const noexcept { return __builtin_coro_done(_pointer); }
};

struct suspend_never {
    constexpr bool await_ready() const noexcept { return true; }
    template<typename T>
    constexpr void await_suspend(coroutine_handle<T>) noexcept { }
    constexpr void await_resume() noexcept { }
};

struct suspend_always {
    constexpr bool await_ready() const noexcept { return false; }
    template<typename T>
    constexpr void await_suspend(coroutine_handle<T>) noexcept { }
    constexpr void await_resume() noexcept { }
};

template <typename Promise>
coroutine_handle<Promise>::operator coroutine_handle<>() const noexcept {
    return coroutine_handle<>::from_address(address());
}

template<typename T, typename... Args>
class coroutine_traits { };

}

#endif
<|endoftext|>


<commit_before>#pragma GCC optimize ("O3")
#include <bits/stdc++.h>

using namespace std;
const int N = (1<<17) , M = (1<<14), OO = 0x3f3f3f3f;

int n, q;
int t, a, b;

int parent[N];

int findParent(int x){
	if(parent[x] == x)	return x;
	return parent[x] = findParent(parent[x]);
}

bool sameSet(int a, int b){
	return findParent(a) == findParent(b);
}

void unionSet(int a, int b){
	int pa = findParent(a), pb = findParent(b);
	if(pa == pb)	return;
	parent[pb] = pa;
}

void init(){
	for(int i = 0 ; i <= n ; ++i)	parent[i] = i;
}

int main(){
  // freopen("i.in", "rt", stdin);
  // freopen("o.out", "wt", stdout);
	scanf("%d %d", &n, &q);
  init();
  while(q--){
  	scanf("%d %d %d", &t, &a, &b);
  	if(t){		//Make Friends
  		unionSet(a, b);
  	}else{		//Are Friends?
  		printf("%d\n", sameSet(a, b));
  	}
  }
	return 0;
}

<commit_msg>Edited DSU naming<commit_after>#include <cstdio>
#include <numeric>

using namespace std;
const int N = 1e5+5 , M = (1<<14), OO = 0x3f3f3f3f;

int n, q;
int t, a, b;

int parent[N];
inline void init(){
  iota(parent, parent+N, 0);
}

int findParent(int x){
	if(parent[x] == x)	return x;
	return parent[x] = findParent(parent[x]);
}

inline bool sameSet(int a, int b){
	return findParent(a) == findParent(b);
}

inline void merge(int a, int b){
	a = findParent(a), b = findParent(b);
	if(a == b)	return;
	parent[b] = a;
}

int main(){
	scanf("%d %d", &n, &q);
  init();
  while(q--){
  	scanf("%d %d %d", &t, &a, &b);
  	if(t){		//Make Friends
  		merge(a, b);
  	}else{		//Are Friends?
  		printf("%d\n", sameSet(a, b));
  	}
  }
	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2017 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#ifndef VCF2MULTIALIGN_DISPATCH_FN_HH
#define VCF2MULTIALIGN_DISPATCH_FN_HH

#include <cassert>
#include <cstdint>
#include <cstdio>
#include <dispatch/dispatch.h>
#include <iostream>
#include <string>
#include <stdexcept>

namespace vcf2multialign { namespace detail {

	template <typename Fn>
	class dispatch_fn_context
	{
	public:
		typedef Fn function_type;

	protected:
		function_type m_fn;

	public:
		dispatch_fn_context(Fn &&fn):
			m_fn(std::move(fn))
		{
		}

		static void call_fn(void *dispatch_context)
		{
			assert(dispatch_context);
			auto *ctx(reinterpret_cast <dispatch_fn_context *>(dispatch_context));

			try
			{
				ctx->m_fn();
			}
			catch (std::exception const &exc)
			{
				std::cerr << "Caught exception: " << exc.what() << std::endl;
			}
			catch (...)
			{
				std::cerr << "Caught non-std::exception." << std::endl;
			}

			delete ctx;
		}
	};

	template <typename t_owner, void(t_owner::*t_fn)()>
	void call_member_function(void *ctx)
	{
		t_owner *owner(static_cast <t_owner *>(ctx));
		(owner->*t_fn)();
	}
}}

namespace vcf2multialign {

	// Allow passing pointer-to-member-function to dispatch_async_f without std::function.
	template <typename t_owner, void(t_owner::*t_fn)()>
	void dispatch_async_f(dispatch_queue_t queue, t_owner *obj)
	{
		dispatch_async_f(queue, obj, detail::call_member_function <t_owner, t_fn>);
	}

	template <typename t_owner, void(t_owner::*t_fn)()>
	void dispatch_barrier_async_f(dispatch_queue_t queue, t_owner *obj)
	{
		dispatch_barrier_async_f(queue, obj, detail::call_member_function <t_owner, t_fn>);
	}

	template <typename Fn>
	void dispatch_async_fn(dispatch_queue_t queue, Fn fn)
	{
		// A new expression doesn't leak memory if the object construction throws an exception.
		typedef detail::dispatch_fn_context <Fn> context_type;
		auto *ctx(new context_type(std::move(fn)));
		dispatch_async_f(queue, ctx, &context_type::call_fn);
	}

	template <typename Fn>
	void dispatch_barrier_async_fn(dispatch_queue_t queue, Fn fn)
	{
		typedef detail::dispatch_fn_context <Fn> context_type;
		auto *ctx(new context_type(std::move(fn)));
		dispatch_barrier_async_f(queue, ctx, &context_type::call_fn);
	}

	template <typename t_dispatch>
	class dispatch_ptr
	{
	protected:
		t_dispatch	m_ptr{};

	public:
		dispatch_ptr()
		{
		}

		dispatch_ptr(t_dispatch ptr, bool retain = false):
			m_ptr(ptr)
		{
			if (m_ptr && retain)
				dispatch_retain(m_ptr);
		}

		~dispatch_ptr()
		{
			if (m_ptr)
				dispatch_release(m_ptr);
		}

		dispatch_ptr(dispatch_ptr const &other):
			dispatch_ptr(other.m_ptr)
		{
		}

		dispatch_ptr(dispatch_ptr &&other):
			m_ptr(other.m_ptr)
		{
			other.m_ptr = nullptr;
		}

		bool operator==(dispatch_ptr const &other) const
		{
			return m_ptr == other.m_ptr;
		}

		bool operator!=(dispatch_ptr const &other) const
		{
			return !(*this == other);
		}

		dispatch_ptr &operator=(dispatch_ptr const &other) &
		{
			if (*this != other)
			{
				if (m_ptr)
					dispatch_release(m_ptr);

				m_ptr = other.m_ptr;
				dispatch_retain(m_ptr);
			}
			return *this;
		}

		dispatch_ptr &operator=(dispatch_ptr &&other) &
		{
			if (*this != other)
			{
				m_ptr = other.m_ptr;
				other.m_ptr = nullptr;
			}
			return *this;
		}

		t_dispatch operator*() { return m_ptr; }
	};

	template <typename t_dispatch>
	void swap(dispatch_ptr <t_dispatch> &lhs, dispatch_ptr <t_dispatch> &rhs)
	{
		using std::swap;
		swap(lhs.m_ptr, rhs.m_ptr);
	}
}

#endif
<commit_msg>Retain the dispatch pointer when needed<commit_after>/*
 * Copyright (c) 2016-2017 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#ifndef VCF2MULTIALIGN_DISPATCH_FN_HH
#define VCF2MULTIALIGN_DISPATCH_FN_HH

#include <cassert>
#include <cstdint>
#include <cstdio>
#include <dispatch/dispatch.h>
#include <iostream>
#include <string>
#include <stdexcept>

namespace vcf2multialign { namespace detail {

	template <typename Fn>
	class dispatch_fn_context
	{
	public:
		typedef Fn function_type;

	protected:
		function_type m_fn;

	public:
		dispatch_fn_context(Fn &&fn):
			m_fn(std::move(fn))
		{
		}

		static void call_fn(void *dispatch_context)
		{
			assert(dispatch_context);
			auto *ctx(reinterpret_cast <dispatch_fn_context *>(dispatch_context));

			try
			{
				ctx->m_fn();
			}
			catch (std::exception const &exc)
			{
				std::cerr << "Caught exception: " << exc.what() << std::endl;
			}
			catch (...)
			{
				std::cerr << "Caught non-std::exception." << std::endl;
			}

			delete ctx;
		}
	};

	template <typename t_owner, void(t_owner::*t_fn)()>
	void call_member_function(void *ctx)
	{
		t_owner *owner(static_cast <t_owner *>(ctx));
		(owner->*t_fn)();
	}
}}

namespace vcf2multialign {

	// Allow passing pointer-to-member-function to dispatch_async_f without std::function.
	template <typename t_owner, void(t_owner::*t_fn)(void)>
	void dispatch_async_f(dispatch_queue_t queue, t_owner *obj)
	{
		dispatch_async_f(queue, obj, detail::call_member_function <t_owner, t_fn>);
	}

	template <typename t_owner, void(t_owner::*t_fn)()>
	void dispatch_barrier_async_f(dispatch_queue_t queue, t_owner *obj)
	{
		dispatch_barrier_async_f(queue, obj, detail::call_member_function <t_owner, t_fn>);
	}

	template <typename Fn>
	void dispatch_async_fn(dispatch_queue_t queue, Fn fn)
	{
		// A new expression doesn't leak memory if the object construction throws an exception.
		typedef detail::dispatch_fn_context <Fn> context_type;
		auto *ctx(new context_type(std::move(fn)));
		dispatch_async_f(queue, ctx, &context_type::call_fn);
	}

	template <typename Fn>
	void dispatch_barrier_async_fn(dispatch_queue_t queue, Fn fn)
	{
		typedef detail::dispatch_fn_context <Fn> context_type;
		auto *ctx(new context_type(std::move(fn)));
		dispatch_barrier_async_f(queue, ctx, &context_type::call_fn);
	}

	template <typename t_dispatch>
	class dispatch_ptr
	{
	protected:
		t_dispatch	m_ptr{};

	public:
		dispatch_ptr()
		{
		}

		dispatch_ptr(t_dispatch ptr, bool retain = false):
			m_ptr(ptr)
		{
			if (m_ptr && retain)
				dispatch_retain(m_ptr);
		}

		~dispatch_ptr()
		{
			if (m_ptr)
				dispatch_release(m_ptr);
		}

		dispatch_ptr(dispatch_ptr const &other):
			dispatch_ptr(other.m_ptr, true)
		{
		}

		dispatch_ptr(dispatch_ptr &&other):
			m_ptr(other.m_ptr)
		{
			other.m_ptr = nullptr;
		}

		bool operator==(dispatch_ptr const &other) const
		{
			return m_ptr == other.m_ptr;
		}

		bool operator!=(dispatch_ptr const &other) const
		{
			return !(*this == other);
		}

		dispatch_ptr &operator=(dispatch_ptr const &other) &
		{
			if (*this != other)
			{
				if (m_ptr)
					dispatch_release(m_ptr);

				m_ptr = other.m_ptr;
				dispatch_retain(m_ptr);
			}
			return *this;
		}

		dispatch_ptr &operator=(dispatch_ptr &&other) &
		{
			if (*this != other)
			{
				m_ptr = other.m_ptr;
				other.m_ptr = nullptr;
			}
			return *this;
		}

		t_dispatch operator*() { return m_ptr; }
	};

	template <typename t_dispatch>
	void swap(dispatch_ptr <t_dispatch> &lhs, dispatch_ptr <t_dispatch> &rhs)
	{
		using std::swap;
		swap(lhs.m_ptr, rhs.m_ptr);
	}
}

#endif
<|endoftext|>


<commit_before>//@	{
//@	"targets":[{"name":"converters.hpp","type":"include"}]
//@	}

#ifndef TEMPLE_CONVERTERS_HPP
#define TEMPLE_CONVERTERS_HPP

#include "error.hpp"
#include <cstdlib>
#include <cerrno>
#include <locale.h>
#include <cmath>
#include <limits>
#include <cinttypes>
#include <cstdio>
#include <type_traits>

namespace Temple
	{
	struct Locale
		{
		Locale():m_handle(newlocale(LC_ALL,"C",0))
			{m_loc_old=uselocale(m_handle);}
		~Locale()
			{
			uselocale(m_loc_old);
			freelocale(m_handle);
			}

		locale_t m_handle;
		locale_t m_loc_old;
		};

	template<size_t size>
	struct Integer
		{};

	template<>
	struct Integer<1>
		{using type=int8_t;};

	template<>
	struct Integer<2>
		{using type=int16_t;};

	template<>
	struct Integer<4>
		{using type=int32_t;};

	template<>
	struct Integer<8>
		{using type=int64_t;};

//Helpers for numeric types

	template<class StringType,class ExceptionHandler>
	long strtol(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtol(str.c_str(),&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	long long strtoll(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtoll(str.c_str(),&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	unsigned long strtoul(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;

		if(*str.c_str()=='-')
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}
		errno=0;
		auto x=::strtoul(str.c_str(),&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	unsigned long long strtoull(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		if(*str.c_str()=='-')
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		errno=0;
		auto x=::strtoull(str.c_str(),&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	float strtof(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtof(str.c_str(),&endptr);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid floating point number."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	double strtod(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtod(str.c_str(),&endptr);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid floating point number."),eh);}

		return x;
		}

//	String to number converters

	template<class T>
	struct Converter
		{
		template<class StringType,class ExceptionHandler>
		static const StringType& convert(const StringType& value,ExceptionHandler& eh)
			{return value;}
		};

	template<>
	struct Converter<int8_t>
		{
		template<class StringType,class ExceptionHandler>
		static int8_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtol(value,eh);
			if(x<-128 || x>127)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<int16_t>
		{
		template<class StringType,class ExceptionHandler>
		static int16_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtol(value,eh);
			if(x<-32768 || x>32767)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<int32_t>
		{
		template<class StringType,class ExceptionHandler>
		static int32_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtoll(value,eh);
			if(x<-2147483648 || x>2147483647)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<int64_t>
		{
		template<class StringType,class ExceptionHandler>
		static int64_t convert(const StringType& value,ExceptionHandler& eh)
			{return strtoll(value,eh);}
		};

	template<>
	struct Converter<uint8_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint8_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtol(value,eh);
			if(x>0xff)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<uint16_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint16_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtoul(value,eh);
			if(x>0xffff)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<uint32_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint32_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtoull(value,eh);
			if(x>0xffffffff)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<uint64_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint64_t convert(const StringType& value,ExceptionHandler& eh)
			{return strtoull(value,eh);}
		};

	template<>
	struct Converter<float>
		{
		template<class StringType,class ExceptionHandler>
		static float convert(const StringType& value,ExceptionHandler& eh)
			{return strtof(value,eh);}
		};

	template<>
	struct Converter<double>
		{
		template<class StringType,class ExceptionHandler>
		static double convert(const StringType& value,ExceptionHandler& eh)
			{return strtod(value,eh);}
		};

//	Wrapper function

	template<class T,class StringType,class ExceptionHandler>
	T convert(const StringType& value,ExceptionHandler& eh)
		{return Converter<T>::convert(value,eh);}

//	Helper for counting digits
	template<class T>
	static constexpr size_t digits() noexcept
		{return static_cast<size_t>( std::log10( std::numeric_limits<T>::max() ) ) + 1;}

//	Number to string conversion

	template<class Number>
	auto convert(Number i) noexcept
		{
		std::array<char,digits<Number>() + 2> buffer; //Sign + nul character
		sprintf(buffer.data(),"%" PRIdMAX ,static_cast<intmax_t>(i));
		return buffer;
		}

	template<>
	auto convert<float>(float x) noexcept
		{
		std::array<char,16> buffer;
		sprintf(buffer.data(),"%.9g",x);
		return buffer;
		}

	template<>
	auto convert<double>(double x) noexcept
		{
		std::array<char,24> buffer;
		sprintf(buffer.data(),"%.17g",x);
		return buffer;
		}
	}

#endif
<commit_msg>Skip whitespace<commit_after>//@	{
//@	"targets":[{"name":"converters.hpp","type":"include"}]
//@	}

#ifndef TEMPLE_CONVERTERS_HPP
#define TEMPLE_CONVERTERS_HPP

#include "error.hpp"
#include <cstdlib>
#include <cerrno>
#include <locale.h>
#include <cmath>
#include <limits>
#include <cinttypes>
#include <cstdio>
#include <type_traits>

namespace Temple
	{
	struct Locale
		{
		Locale():m_handle(newlocale(LC_ALL,"C",0))
			{m_loc_old=uselocale(m_handle);}
		~Locale()
			{
			uselocale(m_loc_old);
			freelocale(m_handle);
			}

		locale_t m_handle;
		locale_t m_loc_old;
		};

	template<size_t size>
	struct Integer
		{};

	template<>
	struct Integer<1>
		{using type=int8_t;};

	template<>
	struct Integer<2>
		{using type=int16_t;};

	template<>
	struct Integer<4>
		{using type=int32_t;};

	template<>
	struct Integer<8>
		{using type=int64_t;};

//Helpers for numeric types

	template<class StringType,class ExceptionHandler>
	long strtol(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtol(str.c_str(),&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value «",str.c_str(),"» is out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	long long strtoll(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtoll(str.c_str(),&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value «",str.c_str(),"» is out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	const char* signCheck(const StringType& str,ExceptionHandler& eh)
		{
		auto ptr=str.c_str();
		while(*ptr!='\0' && isspace(*ptr))
			{++ptr;}
		if(*ptr=='-')
			{raise(Temple::Error("Value «",str.c_str(),"» is out of range."),eh);}
		return ptr;
		}

	template<class StringType,class ExceptionHandler>
	unsigned long strtoul(const StringType& str,ExceptionHandler& eh)
		{
		auto ptr=signCheck(str,eh);
		errno=0;
		char* endptr=nullptr;
		auto x=::strtoul(ptr,&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	unsigned long long strtoull(const StringType& str,ExceptionHandler& eh)
		{
		auto ptr=signCheck(str,eh);
		errno=0;
		char* endptr=nullptr;
		auto x=::strtoull(ptr,&endptr,0);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid integer."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	float strtof(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtof(str.c_str(),&endptr);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid floating point number."),eh);}

		return x;
		}

	template<class StringType,class ExceptionHandler>
	double strtod(const StringType& str,ExceptionHandler& eh)
		{
		char* endptr=nullptr;
		errno=0;
		auto x=::strtod(str.c_str(),&endptr);
		if(errno==ERANGE)
			{raise(Temple::Error("Value ",str.c_str()," out of range."),eh);}

		if(*endptr!='\0' || endptr==str.c_str())
			{raise(Temple::Error("«",str.c_str(),"» is not a valid floating point number."),eh);}

		return x;
		}

//	String to number converters

	template<class T>
	struct Converter
		{
		template<class StringType,class ExceptionHandler>
		static const StringType& convert(const StringType& value,ExceptionHandler& eh)
			{return value;}
		};

	template<>
	struct Converter<int8_t>
		{
		template<class StringType,class ExceptionHandler>
		static int8_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtol(value,eh);
			if(x<-128 || x>127)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<int16_t>
		{
		template<class StringType,class ExceptionHandler>
		static int16_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtol(value,eh);
			if(x<-32768 || x>32767)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<int32_t>
		{
		template<class StringType,class ExceptionHandler>
		static int32_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtoll(value,eh);
			if(x<-2147483648 || x>2147483647)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<int64_t>
		{
		template<class StringType,class ExceptionHandler>
		static int64_t convert(const StringType& value,ExceptionHandler& eh)
			{return strtoll(value,eh);}
		};

	template<>
	struct Converter<uint8_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint8_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtol(value,eh);
			if(x>0xff)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<uint16_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint16_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtoul(value,eh);
			if(x>0xffff)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<uint32_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint32_t convert(const StringType& value,ExceptionHandler& eh)
			{
			auto x=strtoull(value,eh);
			if(x>0xffffffff)
				{raise(Temple::Error("Value ",value.c_str()," out of range."),eh);}
			return x;
			}
		};

	template<>
	struct Converter<uint64_t>
		{
		template<class StringType,class ExceptionHandler>
		static uint64_t convert(const StringType& value,ExceptionHandler& eh)
			{return strtoull(value,eh);}
		};

	template<>
	struct Converter<float>
		{
		template<class StringType,class ExceptionHandler>
		static float convert(const StringType& value,ExceptionHandler& eh)
			{return strtof(value,eh);}
		};

	template<>
	struct Converter<double>
		{
		template<class StringType,class ExceptionHandler>
		static double convert(const StringType& value,ExceptionHandler& eh)
			{return strtod(value,eh);}
		};

//	Wrapper function

	template<class T,class StringType,class ExceptionHandler>
	T convert(const StringType& value,ExceptionHandler& eh)
		{return Converter<T>::convert(value,eh);}

//	Helper for counting digits
	template<class T>
	static constexpr size_t digits() noexcept
		{return static_cast<size_t>( std::log10( std::numeric_limits<T>::max() ) ) + 1;}

//	Number to string conversion

	template<class Number>
	auto convert(Number i) noexcept
		{
		std::array<char,digits<Number>() + 2> buffer; //Sign + nul character
		sprintf(buffer.data(),"%" PRIdMAX ,static_cast<intmax_t>(i));
		return buffer;
		}

	template<>
	auto convert<float>(float x) noexcept
		{
		std::array<char,16> buffer;
		sprintf(buffer.data(),"%.9g",x);
		return buffer;
		}

	template<>
	auto convert<double>(double x) noexcept
		{
		std::array<char,24> buffer;
		sprintf(buffer.data(),"%.17g",x);
		return buffer;
		}
	}

#endif
<|endoftext|>


<commit_before>/*************************************************************************/
/*  array.cpp                                                            */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* 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.                */
/*************************************************************************/

#include "array.h"

#include "core/hashfuncs.h"
#include "core/object.h"
#include "core/variant.h"
#include "core/vector.h"

class ArrayPrivate {
public:
	SafeRefCount refcount;
	Vector<Variant> array;
};

void Array::_ref(const Array &p_from) const {

	ArrayPrivate *_fp = p_from._p;

	ERR_FAIL_COND(!_fp); // should NOT happen.

	if (_fp == _p)
		return; // whatever it is, nothing to do here move along

	bool success = _fp->refcount.ref();

	ERR_FAIL_COND(!success); // should really not happen either

	_unref();

	_p = p_from._p;
}

void Array::_unref() const {

	if (!_p)
		return;

	if (_p->refcount.unref()) {
		memdelete(_p);
	}
	_p = NULL;
}

Variant &Array::operator[](int p_idx) {

	return _p->array.write[p_idx];
}

const Variant &Array::operator[](int p_idx) const {

	return _p->array[p_idx];
}

int Array::size() const {

	return _p->array.size();
}
bool Array::empty() const {

	return _p->array.empty();
}
void Array::clear() {

	_p->array.clear();
}

bool Array::operator==(const Array &p_array) const {

	return _p == p_array._p;
}

uint32_t Array::hash() const {

	uint32_t h = hash_djb2_one_32(0);

	for (int i = 0; i < _p->array.size(); i++) {

		h = hash_djb2_one_32(_p->array[i].hash(), h);
	}
	return h;
}
void Array::operator=(const Array &p_array) {

	_ref(p_array);
}
void Array::push_back(const Variant &p_value) {

	_p->array.push_back(p_value);
}

Error Array::resize(int p_new_size) {

	return _p->array.resize(p_new_size);
}

void Array::insert(int p_pos, const Variant &p_value) {

	_p->array.insert(p_pos, p_value);
}

void Array::erase(const Variant &p_value) {

	_p->array.erase(p_value);
}

Variant Array::front() const {
	ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
	return operator[](0);
}

Variant Array::back() const {
	ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
	return operator[](_p->array.size() - 1);
}

int Array::find(const Variant &p_value, int p_from) const {

	return _p->array.find(p_value, p_from);
}

int Array::rfind(const Variant &p_value, int p_from) const {

	if (_p->array.size() == 0)
		return -1;

	if (p_from < 0) {
		// Relative offset from the end
		p_from = _p->array.size() + p_from;
	}
	if (p_from < 0 || p_from >= _p->array.size()) {
		// Limit to array boundaries
		p_from = _p->array.size() - 1;
	}

	for (int i = p_from; i >= 0; i--) {

		if (_p->array[i] == p_value) {
			return i;
		}
	}

	return -1;
}

int Array::find_last(const Variant &p_value) const {

	return rfind(p_value);
}

int Array::count(const Variant &p_value) const {

	if (_p->array.size() == 0)
		return 0;

	int amount = 0;
	for (int i = 0; i < _p->array.size(); i++) {

		if (_p->array[i] == p_value) {
			amount++;
		}
	}

	return amount;
}

bool Array::has(const Variant &p_value) const {
	return _p->array.find(p_value, 0) != -1;
}

void Array::remove(int p_pos) {

	_p->array.remove(p_pos);
}

void Array::set(int p_idx, const Variant &p_value) {

	operator[](p_idx) = p_value;
}

const Variant &Array::get(int p_idx) const {

	return operator[](p_idx);
}

Array Array::duplicate(bool p_deep) const {

	Array new_arr;
	int element_count = size();
	new_arr.resize(element_count);
	for (int i = 0; i < element_count; i++) {
		new_arr[i] = p_deep ? get(i).duplicate(p_deep) : get(i);
	}

	return new_arr;
}

int Array::_fix_slice_index(int p_index, int p_arr_len, int p_top_mod) {
	p_index = CLAMP(p_index, -p_arr_len, p_arr_len + p_top_mod);
	if (p_index < 0) {
		p_index = (p_index % p_arr_len + p_arr_len) % p_arr_len; // positive modulo
	}
	return p_index;
}

int Array::_clamp_index(int p_index) const {
	return CLAMP(p_index, -size() + 1, size() - 1);
}

#define ARRAY_GET_DEEP(idx, is_deep) is_deep ? get(idx).duplicate(is_deep) : get(idx)

Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound
	Array new_arr;

	p_begin = Array::_fix_slice_index(p_begin, size(), -1); // can't start out of range
	p_end = Array::_fix_slice_index(p_end, size(), 0);

	int x = p_begin;
	int new_arr_i = 0;

	ERR_FAIL_COND_V(p_step == 0, new_arr);
	if (Array::_clamp_index(p_begin) == Array::_clamp_index(p_end)) { // don't include element twice
		new_arr.resize(1);
		// new_arr[0] = 1;
		new_arr[0] = ARRAY_GET_DEEP(Array::_clamp_index(p_begin), p_deep);
		return new_arr;
	} else {
		int element_count = ceil((int)MAX(0, (p_end - p_begin) / p_step)) + 1;
		if (element_count == 1) { // delta going in wrong direction to reach end
			new_arr.resize(0);
			return new_arr;
		}
		new_arr.resize(element_count);
	}

	// if going backwards, have to have a different terminating condition
	if (p_step < 0) {
		while (x >= p_end) {
			new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep);
			x += p_step;
			new_arr_i += 1;
		}
	} else if (p_step > 0) {
		while (x <= p_end) {
			new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep);
			x += p_step;
			new_arr_i += 1;
		}
	}

	return new_arr;
}

struct _ArrayVariantSort {

	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
		bool valid = false;
		Variant res;
		Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
		if (!valid)
			res = false;
		return res;
	}
};

Array &Array::sort() {

	_p->array.sort_custom<_ArrayVariantSort>();
	return *this;
}

struct _ArrayVariantSortCustom {

	Object *obj;
	StringName func;

	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {

		const Variant *args[2] = { &p_l, &p_r };
		Variant::CallError err;
		bool res = obj->call(func, args, 2, err);
		if (err.error != Variant::CallError::CALL_OK)
			res = false;
		return res;
	}
};
Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {

	ERR_FAIL_NULL_V(p_obj, *this);

	SortArray<Variant, _ArrayVariantSortCustom, true> avs;
	avs.compare.obj = p_obj;
	avs.compare.func = p_function;
	avs.sort(_p->array.ptrw(), _p->array.size());
	return *this;
}

void Array::shuffle() {

	const int n = _p->array.size();
	if (n < 2)
		return;
	Variant *data = _p->array.ptrw();
	for (int i = n - 1; i >= 1; i--) {
		const int j = Math::rand() % (i + 1);
		const Variant tmp = data[j];
		data[j] = data[i];
		data[i] = tmp;
	}
}

template <typename Less>
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {

	int lo = 0;
	int hi = p_array.size();
	if (p_before) {
		while (lo < hi) {
			const int mid = (lo + hi) / 2;
			if (p_less(p_array.get(mid), p_value)) {
				lo = mid + 1;
			} else {
				hi = mid;
			}
		}
	} else {
		while (lo < hi) {
			const int mid = (lo + hi) / 2;
			if (p_less(p_value, p_array.get(mid))) {
				hi = mid;
			} else {
				lo = mid + 1;
			}
		}
	}
	return lo;
}

int Array::bsearch(const Variant &p_value, bool p_before) {

	return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
}

int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {

	ERR_FAIL_NULL_V(p_obj, 0);

	_ArrayVariantSortCustom less;
	less.obj = p_obj;
	less.func = p_function;

	return bisect(_p->array, p_value, p_before, less);
}

Array &Array::invert() {

	_p->array.invert();
	return *this;
}

void Array::push_front(const Variant &p_value) {

	_p->array.insert(0, p_value);
}

Variant Array::pop_back() {

	if (!_p->array.empty()) {
		int n = _p->array.size() - 1;
		Variant ret = _p->array.get(n);
		_p->array.resize(n);
		return ret;
	}
	return Variant();
}

Variant Array::pop_front() {

	if (!_p->array.empty()) {
		Variant ret = _p->array.get(0);
		_p->array.remove(0);
		return ret;
	}
	return Variant();
}

Variant Array::min() const {

	Variant minval;
	for (int i = 0; i < size(); i++) {
		if (i == 0) {
			minval = get(i);
		} else {
			bool valid;
			Variant ret;
			Variant test = get(i);
			Variant::evaluate(Variant::OP_LESS, test, minval, ret, valid);
			if (!valid) {
				return Variant(); //not a valid comparison
			}
			if (bool(ret)) {
				//is less
				minval = test;
			}
		}
	}
	return minval;
}

Variant Array::max() const {

	Variant maxval;
	for (int i = 0; i < size(); i++) {
		if (i == 0) {
			maxval = get(i);
		} else {
			bool valid;
			Variant ret;
			Variant test = get(i);
			Variant::evaluate(Variant::OP_GREATER, test, maxval, ret, valid);
			if (!valid) {
				return Variant(); //not a valid comparison
			}
			if (bool(ret)) {
				//is less
				maxval = test;
			}
		}
	}
	return maxval;
}

const void *Array::id() const {
	return _p->array.ptr();
}

Array::Array(const Array &p_from) {

	_p = NULL;
	_ref(p_from);
}

Array::Array() {

	_p = memnew(ArrayPrivate);
	_p->refcount.init();
}
Array::~Array() {

	_unref();
}
<commit_msg>Don't try to slice empty arrays<commit_after>/*************************************************************************/
/*  array.cpp                                                            */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* 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.                */
/*************************************************************************/

#include "array.h"

#include "core/hashfuncs.h"
#include "core/object.h"
#include "core/variant.h"
#include "core/vector.h"

class ArrayPrivate {
public:
	SafeRefCount refcount;
	Vector<Variant> array;
};

void Array::_ref(const Array &p_from) const {

	ArrayPrivate *_fp = p_from._p;

	ERR_FAIL_COND(!_fp); // should NOT happen.

	if (_fp == _p)
		return; // whatever it is, nothing to do here move along

	bool success = _fp->refcount.ref();

	ERR_FAIL_COND(!success); // should really not happen either

	_unref();

	_p = p_from._p;
}

void Array::_unref() const {

	if (!_p)
		return;

	if (_p->refcount.unref()) {
		memdelete(_p);
	}
	_p = NULL;
}

Variant &Array::operator[](int p_idx) {

	return _p->array.write[p_idx];
}

const Variant &Array::operator[](int p_idx) const {

	return _p->array[p_idx];
}

int Array::size() const {

	return _p->array.size();
}
bool Array::empty() const {

	return _p->array.empty();
}
void Array::clear() {

	_p->array.clear();
}

bool Array::operator==(const Array &p_array) const {

	return _p == p_array._p;
}

uint32_t Array::hash() const {

	uint32_t h = hash_djb2_one_32(0);

	for (int i = 0; i < _p->array.size(); i++) {

		h = hash_djb2_one_32(_p->array[i].hash(), h);
	}
	return h;
}
void Array::operator=(const Array &p_array) {

	_ref(p_array);
}
void Array::push_back(const Variant &p_value) {

	_p->array.push_back(p_value);
}

Error Array::resize(int p_new_size) {

	return _p->array.resize(p_new_size);
}

void Array::insert(int p_pos, const Variant &p_value) {

	_p->array.insert(p_pos, p_value);
}

void Array::erase(const Variant &p_value) {

	_p->array.erase(p_value);
}

Variant Array::front() const {
	ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
	return operator[](0);
}

Variant Array::back() const {
	ERR_FAIL_COND_V_MSG(_p->array.size() == 0, Variant(), "Can't take value from empty array.");
	return operator[](_p->array.size() - 1);
}

int Array::find(const Variant &p_value, int p_from) const {

	return _p->array.find(p_value, p_from);
}

int Array::rfind(const Variant &p_value, int p_from) const {

	if (_p->array.size() == 0)
		return -1;

	if (p_from < 0) {
		// Relative offset from the end
		p_from = _p->array.size() + p_from;
	}
	if (p_from < 0 || p_from >= _p->array.size()) {
		// Limit to array boundaries
		p_from = _p->array.size() - 1;
	}

	for (int i = p_from; i >= 0; i--) {

		if (_p->array[i] == p_value) {
			return i;
		}
	}

	return -1;
}

int Array::find_last(const Variant &p_value) const {

	return rfind(p_value);
}

int Array::count(const Variant &p_value) const {

	if (_p->array.size() == 0)
		return 0;

	int amount = 0;
	for (int i = 0; i < _p->array.size(); i++) {

		if (_p->array[i] == p_value) {
			amount++;
		}
	}

	return amount;
}

bool Array::has(const Variant &p_value) const {
	return _p->array.find(p_value, 0) != -1;
}

void Array::remove(int p_pos) {

	_p->array.remove(p_pos);
}

void Array::set(int p_idx, const Variant &p_value) {

	operator[](p_idx) = p_value;
}

const Variant &Array::get(int p_idx) const {

	return operator[](p_idx);
}

Array Array::duplicate(bool p_deep) const {

	Array new_arr;
	int element_count = size();
	new_arr.resize(element_count);
	for (int i = 0; i < element_count; i++) {
		new_arr[i] = p_deep ? get(i).duplicate(p_deep) : get(i);
	}

	return new_arr;
}

int Array::_fix_slice_index(int p_index, int p_arr_len, int p_top_mod) {
	p_index = CLAMP(p_index, -p_arr_len, p_arr_len + p_top_mod);
	if (p_index < 0) {
		p_index = (p_index % p_arr_len + p_arr_len) % p_arr_len; // positive modulo
	}
	return p_index;
}

int Array::_clamp_index(int p_index) const {
	return CLAMP(p_index, -size() + 1, size() - 1);
}

#define ARRAY_GET_DEEP(idx, is_deep) is_deep ? get(idx).duplicate(is_deep) : get(idx)

Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound
	Array new_arr;

	if (empty()) // Don't try to slice empty arrays.
		return new_arr;

	p_begin = Array::_fix_slice_index(p_begin, size(), -1); // can't start out of range
	p_end = Array::_fix_slice_index(p_end, size(), 0);

	int x = p_begin;
	int new_arr_i = 0;

	ERR_FAIL_COND_V(p_step == 0, new_arr);
	if (Array::_clamp_index(p_begin) == Array::_clamp_index(p_end)) { // don't include element twice
		new_arr.resize(1);
		// new_arr[0] = 1;
		new_arr[0] = ARRAY_GET_DEEP(Array::_clamp_index(p_begin), p_deep);
		return new_arr;
	} else {
		int element_count = ceil((int)MAX(0, (p_end - p_begin) / p_step)) + 1;
		if (element_count == 1) { // delta going in wrong direction to reach end
			new_arr.resize(0);
			return new_arr;
		}
		new_arr.resize(element_count);
	}

	// if going backwards, have to have a different terminating condition
	if (p_step < 0) {
		while (x >= p_end) {
			new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep);
			x += p_step;
			new_arr_i += 1;
		}
	} else if (p_step > 0) {
		while (x <= p_end) {
			new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep);
			x += p_step;
			new_arr_i += 1;
		}
	}

	return new_arr;
}

struct _ArrayVariantSort {

	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
		bool valid = false;
		Variant res;
		Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
		if (!valid)
			res = false;
		return res;
	}
};

Array &Array::sort() {

	_p->array.sort_custom<_ArrayVariantSort>();
	return *this;
}

struct _ArrayVariantSortCustom {

	Object *obj;
	StringName func;

	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {

		const Variant *args[2] = { &p_l, &p_r };
		Variant::CallError err;
		bool res = obj->call(func, args, 2, err);
		if (err.error != Variant::CallError::CALL_OK)
			res = false;
		return res;
	}
};
Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {

	ERR_FAIL_NULL_V(p_obj, *this);

	SortArray<Variant, _ArrayVariantSortCustom, true> avs;
	avs.compare.obj = p_obj;
	avs.compare.func = p_function;
	avs.sort(_p->array.ptrw(), _p->array.size());
	return *this;
}

void Array::shuffle() {

	const int n = _p->array.size();
	if (n < 2)
		return;
	Variant *data = _p->array.ptrw();
	for (int i = n - 1; i >= 1; i--) {
		const int j = Math::rand() % (i + 1);
		const Variant tmp = data[j];
		data[j] = data[i];
		data[i] = tmp;
	}
}

template <typename Less>
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {

	int lo = 0;
	int hi = p_array.size();
	if (p_before) {
		while (lo < hi) {
			const int mid = (lo + hi) / 2;
			if (p_less(p_array.get(mid), p_value)) {
				lo = mid + 1;
			} else {
				hi = mid;
			}
		}
	} else {
		while (lo < hi) {
			const int mid = (lo + hi) / 2;
			if (p_less(p_value, p_array.get(mid))) {
				hi = mid;
			} else {
				lo = mid + 1;
			}
		}
	}
	return lo;
}

int Array::bsearch(const Variant &p_value, bool p_before) {

	return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
}

int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {

	ERR_FAIL_NULL_V(p_obj, 0);

	_ArrayVariantSortCustom less;
	less.obj = p_obj;
	less.func = p_function;

	return bisect(_p->array, p_value, p_before, less);
}

Array &Array::invert() {

	_p->array.invert();
	return *this;
}

void Array::push_front(const Variant &p_value) {

	_p->array.insert(0, p_value);
}

Variant Array::pop_back() {

	if (!_p->array.empty()) {
		int n = _p->array.size() - 1;
		Variant ret = _p->array.get(n);
		_p->array.resize(n);
		return ret;
	}
	return Variant();
}

Variant Array::pop_front() {

	if (!_p->array.empty()) {
		Variant ret = _p->array.get(0);
		_p->array.remove(0);
		return ret;
	}
	return Variant();
}

Variant Array::min() const {

	Variant minval;
	for (int i = 0; i < size(); i++) {
		if (i == 0) {
			minval = get(i);
		} else {
			bool valid;
			Variant ret;
			Variant test = get(i);
			Variant::evaluate(Variant::OP_LESS, test, minval, ret, valid);
			if (!valid) {
				return Variant(); //not a valid comparison
			}
			if (bool(ret)) {
				//is less
				minval = test;
			}
		}
	}
	return minval;
}

Variant Array::max() const {

	Variant maxval;
	for (int i = 0; i < size(); i++) {
		if (i == 0) {
			maxval = get(i);
		} else {
			bool valid;
			Variant ret;
			Variant test = get(i);
			Variant::evaluate(Variant::OP_GREATER, test, maxval, ret, valid);
			if (!valid) {
				return Variant(); //not a valid comparison
			}
			if (bool(ret)) {
				//is less
				maxval = test;
			}
		}
	}
	return maxval;
}

const void *Array::id() const {
	return _p->array.ptr();
}

Array::Array(const Array &p_from) {

	_p = NULL;
	_ref(p_from);
}

Array::Array() {

	_p = memnew(ArrayPrivate);
	_p->refcount.init();
}
Array::~Array() {

	_unref();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "progressbar.h"
#include "image.h"
#include "algo/threaded_copy.h"
#include "dwi/gradient.h"
#include "dwi/tensor.h"

using namespace MR;
using namespace App;
using namespace std;

typedef float value_type;

#define DEFAULT_NITER 2

void usage ()
{

  REFERENCES
  +  "Veraart, J.; Sijbers, J.; Sunaert, S.; Leemans, A. & Jeurissen, B. " // Internal
     "Weighted linear least squares estimation of diffusion MRI parameters: strengths, limitations, and pitfalls. "
     "NeuroImage, 2013, 81, 335-346";

  ARGUMENTS
  + Argument ("dwi", "the input dwi image.").type_image_in ()
  + Argument ("dt", "the output dt image.").type_image_out ();

  OPTIONS
  + Option ("mask", "only perform computation within the specified binary brain mask image.")
  + Argument ("image").type_image_in()
  + Option ("b0", "the output b0 image.")
  + Argument ("image").type_image_out()
  + Option ("dkt", "the output dkt image.")
  + Argument ("image").type_image_out()
  + Option ("iter","number of iterative reweightings (default: " + str(DEFAULT_NITER) + "); set to 0 for ordinary linear least squares.")
  + Argument ("integer").type_integer (0, 10)
  + Option ("predicted_signal", "the predicted dwi image.")
  + Argument ("image").type_image_out()
  + DWI::GradImportOptions();

  AUTHOR = "Ben Jeurissen (ben.jeurissen@uantwerpen.be)";

  DESCRIPTION
  + "Diffusion (kurtosis) tensor estimation using iteratively reweighted linear least squares estimator.";
}

template <class MASKType, class B0Type, class DKTType, class PredictType>
class Processor
{
  public:
    Processor (const Eigen::MatrixXd& b, const int iter, MASKType* mask_image, B0Type* b0_image, DKTType* dkt_image, PredictType* predict_image) :
      mask_image (mask_image),
      b0_image (b0_image),
      dkt_image (dkt_image),
      predict_image (predict_image),
      dwi(b.rows()),
      p(b.cols()),
      w(b.rows()),
      work(b.cols(),b.cols()),
      llt(work.rows()),
      b(b),
      maxit(iter) { }

    template <class DWIType, class DTType>
      void operator() (DWIType& dwi_image, DTType& dt_image)
      {
        if (mask_image) {
          assign_pos_of (dwi_image, 0, 3).to (*mask_image);
          if (!mask_image->value())
            return;
        }

        for (auto l = Loop (3) (dwi_image); l; ++l)
          dwi[dwi_image.index(3)] = dwi_image.value();

        double small_intensity = 1.0e-6 * dwi.maxCoeff();
        for (int i = 0; i < dwi.rows(); i++) {
          if (dwi[i] < small_intensity)
            dwi[i] = small_intensity;
          dwi[i] = std::log (dwi[i]);
        }

        work.setZero();
        work.selfadjointView<Eigen::Lower>().rankUpdate (b.transpose());
        p = llt.compute (work.selfadjointView<Eigen::Lower>()).solve(b.transpose()*dwi);
        for (int it = 0; it < maxit; it++) {
          w = (b*p).array().exp();
          work.setZero();
          work.selfadjointView<Eigen::Lower>().rankUpdate (b.transpose()*w.asDiagonal());
          p = llt.compute (work.selfadjointView<Eigen::Lower>()).solve(b.transpose()*w.asDiagonal()*dwi);
        }

        if (b0_image) {
          assign_pos_of (dwi_image, 0, 3).to (*b0_image);
          b0_image->value() = exp(p[6]);
        }

        for (auto l = Loop(3)(dt_image); l; ++l) {
          dt_image.value() = p[dt_image.index(3)];
        }

        if (dkt_image) {
          assign_pos_of (dwi_image, 0, 3).to (*dkt_image);
          double adc_sq = (p[0]+p[1]+p[2])*(p[0]+p[1]+p[2])/9.0;
          for (auto l = Loop(3)(*dkt_image); l; ++l) {
            dkt_image->value() = p[dkt_image->index(3)+7]/adc_sq;
          }
        }

        if (predict_image) {
          assign_pos_of (dwi_image, 0, 3).to (*predict_image);
          dwi = (b*p).array().exp();
          for (auto l = Loop(3)(*predict_image); l; ++l) {
            predict_image->value() = dwi[predict_image->index(3)];
          }
        }

      }

  private:
    copy_ptr<MASKType> mask_image;
    copy_ptr<B0Type> b0_image;
    copy_ptr<DKTType> dkt_image;
    copy_ptr<PredictType> predict_image;
    Eigen::VectorXd dwi;
    Eigen::VectorXd p;
    Eigen::VectorXd w;
    Eigen::MatrixXd work;
    Eigen::LLT<Eigen::MatrixXd> llt;
    const Eigen::MatrixXd& b;
    const int maxit;
};

template <class MASKType, class B0Type, class DKTType, class PredictType>
inline Processor<MASKType, B0Type, DKTType, PredictType> processor (const Eigen::MatrixXd& b, const int& iter, MASKType* mask_image, B0Type* b0_image, DKTType* dkt_image, PredictType* predict_image) {
  return { b, iter, mask_image, b0_image, dkt_image, predict_image };
}

void run ()
{
  auto dwi = Header::open (argument[0]).get_image<value_type>();
  auto grad = DWI::get_valid_DW_scheme (dwi);

  Image<bool>* mask = nullptr;
  auto opt = get_options ("mask");
  if (opt.size()) {
    mask = new Image<bool> (Image<bool>::open (opt[0][0]));
    check_dimensions (dwi, *mask, 0, 3);
  }

  auto iter = get_option_value ("iter", DEFAULT_NITER);

  Header header (dwi);
  header.datatype() = DataType::Float32;
  header.set_ndim (4);

  Image<value_type>* predict = nullptr;
  opt = get_options ("predicted_signal");
  if (opt.size()) {
    predict = new Image<value_type> (Image<value_type>::create (opt[0][0], header));
  }

  header.size(3) = 6;
  auto dt = Image<value_type>::create (argument[1], header);

  Image<value_type>* b0 = nullptr;
  opt = get_options ("b0");
  if (opt.size()) {
    header.set_ndim (3);
    b0 = new Image<value_type> (Image<value_type>::create (opt[0][0], header));
  }

  Image<value_type>* dkt = nullptr;
  opt = get_options ("dkt");
  if (opt.size()) {
    header.set_ndim (4);
    header.size(3) = 15;
    dkt = new Image<value_type> (Image<value_type>::create (opt[0][0], header));
  }

  Eigen::MatrixXd b = -DWI::grad2bmatrix<double> (grad, opt.size()>0);

  ThreadedLoop("computing tensors", dwi, 0, 3).run (processor (b, iter, mask, b0, dkt, predict), dwi, dt);
}

<commit_msg>Fix bug in the cholesky version of dwi2tensor<commit_after>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "progressbar.h"
#include "image.h"
#include "algo/threaded_copy.h"
#include "dwi/gradient.h"
#include "dwi/tensor.h"

using namespace MR;
using namespace App;
using namespace std;

typedef float value_type;

#define DEFAULT_NITER 2

void usage ()
{

  REFERENCES
  +  "Veraart, J.; Sijbers, J.; Sunaert, S.; Leemans, A. & Jeurissen, B. " // Internal
     "Weighted linear least squares estimation of diffusion MRI parameters: strengths, limitations, and pitfalls. "
     "NeuroImage, 2013, 81, 335-346";

  ARGUMENTS
  + Argument ("dwi", "the input dwi image.").type_image_in ()
  + Argument ("dt", "the output dt image.").type_image_out ();

  OPTIONS
  + Option ("mask", "only perform computation within the specified binary brain mask image.")
  + Argument ("image").type_image_in()
  + Option ("b0", "the output b0 image.")
  + Argument ("image").type_image_out()
  + Option ("dkt", "the output dkt image.")
  + Argument ("image").type_image_out()
  + Option ("iter","number of iterative reweightings (default: " + str(DEFAULT_NITER) + "); set to 0 for ordinary linear least squares.")
  + Argument ("integer").type_integer (0, 10)
  + Option ("predicted_signal", "the predicted dwi image.")
  + Argument ("image").type_image_out()
  + DWI::GradImportOptions();

  AUTHOR = "Ben Jeurissen (ben.jeurissen@uantwerpen.be)";

  DESCRIPTION
  + "Diffusion (kurtosis) tensor estimation using iteratively reweighted linear least squares estimator.";
}

template <class MASKType, class B0Type, class DKTType, class PredictType>
class Processor
{
  public:
    Processor (const Eigen::MatrixXd& b, const int iter, MASKType* mask_image, B0Type* b0_image, DKTType* dkt_image, PredictType* predict_image) :
      mask_image (mask_image),
      b0_image (b0_image),
      dkt_image (dkt_image),
      predict_image (predict_image),
      dwi(b.rows()),
      p(b.cols()),
      w(b.rows()),
      work(b.cols(),b.cols()),
      llt(work.rows()),
      b(b),
      maxit(iter) { }

    template <class DWIType, class DTType>
      void operator() (DWIType& dwi_image, DTType& dt_image)
      {
        if (mask_image) {
          assign_pos_of (dwi_image, 0, 3).to (*mask_image);
          if (!mask_image->value())
            return;
        }

        for (auto l = Loop (3) (dwi_image); l; ++l)
          dwi[dwi_image.index(3)] = dwi_image.value();

        double small_intensity = 1.0e-6 * dwi.maxCoeff();
        for (int i = 0; i < dwi.rows(); i++) {
          if (dwi[i] < small_intensity)
            dwi[i] = small_intensity;
          dwi[i] = std::log (dwi[i]);
        }

        work.setZero();
        work.selfadjointView<Eigen::Lower>().rankUpdate (b.transpose());
        p = llt.compute (work.selfadjointView<Eigen::Lower>()).solve(b.transpose()*dwi);
        for (int it = 0; it < maxit; it++) {
          w = (b*p).array().exp();
          work.setZero();
          work.selfadjointView<Eigen::Lower>().rankUpdate (b.transpose()*w.asDiagonal());
          p = llt.compute (work.selfadjointView<Eigen::Lower>()).solve(b.transpose()*w.asDiagonal()*w.asDiagonal()*dwi);
        }

        if (b0_image) {
          assign_pos_of (dwi_image, 0, 3).to (*b0_image);
          b0_image->value() = exp(p[6]);
        }

        for (auto l = Loop(3)(dt_image); l; ++l) {
          dt_image.value() = p[dt_image.index(3)];
        }

        if (dkt_image) {
          assign_pos_of (dwi_image, 0, 3).to (*dkt_image);
          double adc_sq = (p[0]+p[1]+p[2])*(p[0]+p[1]+p[2])/9.0;
          for (auto l = Loop(3)(*dkt_image); l; ++l) {
            dkt_image->value() = p[dkt_image->index(3)+7]/adc_sq;
          }
        }

        if (predict_image) {
          assign_pos_of (dwi_image, 0, 3).to (*predict_image);
          dwi = (b*p).array().exp();
          for (auto l = Loop(3)(*predict_image); l; ++l) {
            predict_image->value() = dwi[predict_image->index(3)];
          }
        }

      }

  private:
    copy_ptr<MASKType> mask_image;
    copy_ptr<B0Type> b0_image;
    copy_ptr<DKTType> dkt_image;
    copy_ptr<PredictType> predict_image;
    Eigen::VectorXd dwi;
    Eigen::VectorXd p;
    Eigen::VectorXd w;
    Eigen::MatrixXd work;
    Eigen::LLT<Eigen::MatrixXd> llt;
    const Eigen::MatrixXd& b;
    const int maxit;
};

template <class MASKType, class B0Type, class DKTType, class PredictType>
inline Processor<MASKType, B0Type, DKTType, PredictType> processor (const Eigen::MatrixXd& b, const int& iter, MASKType* mask_image, B0Type* b0_image, DKTType* dkt_image, PredictType* predict_image) {
  return { b, iter, mask_image, b0_image, dkt_image, predict_image };
}

void run ()
{
  auto dwi = Header::open (argument[0]).get_image<value_type>();
  auto grad = DWI::get_valid_DW_scheme (dwi);

  Image<bool>* mask = nullptr;
  auto opt = get_options ("mask");
  if (opt.size()) {
    mask = new Image<bool> (Image<bool>::open (opt[0][0]));
    check_dimensions (dwi, *mask, 0, 3);
  }

  auto iter = get_option_value ("iter", DEFAULT_NITER);

  Header header (dwi);
  header.datatype() = DataType::Float32;
  header.set_ndim (4);

  Image<value_type>* predict = nullptr;
  opt = get_options ("predicted_signal");
  if (opt.size()) {
    predict = new Image<value_type> (Image<value_type>::create (opt[0][0], header));
  }

  header.size(3) = 6;
  auto dt = Image<value_type>::create (argument[1], header);

  Image<value_type>* b0 = nullptr;
  opt = get_options ("b0");
  if (opt.size()) {
    header.set_ndim (3);
    b0 = new Image<value_type> (Image<value_type>::create (opt[0][0], header));
  }

  Image<value_type>* dkt = nullptr;
  opt = get_options ("dkt");
  if (opt.size()) {
    header.set_ndim (4);
    header.size(3) = 15;
    dkt = new Image<value_type> (Image<value_type>::create (opt[0][0], header));
  }

  Eigen::MatrixXd b = -DWI::grad2bmatrix<double> (grad, opt.size()>0);

  ThreadedLoop("computing tensors", dwi, 0, 3).run (processor (b, iter, mask, b0, dkt, predict), dwi, dt);
}

<|endoftext|>


<commit_before>// Copyright (c) 2015
// Ravi Peters -- r.y.peters@tudelft.nl
// All rights reserved
// This file is part of masbcpp.
//
// masbcpp 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.
//
// masbcpp 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 masbcpp.  If not, see <http://www.gnu.org/licenses/>.

// #define VERBOSEPRINT 1;
// #define WITH_OPENMP 1;

#include <iostream>
#include <fstream>
#include <string>
#include <limits>

// OpenMP
#ifdef WITH_OPENMP
    #ifdef CLANG_OMP
        #include <libiomp/omp.h>
    #else
        #include <omp.h>
    #endif
#endif

// Vrui
#include <vrui/Geometry/ComponentArray.h>
#include <vrui/Math/Math.h>
#include <vrui/Misc/Timer.h>
// kdtree2
#include <kdtree2/kdtree2.hpp>
// cnpy
#include <cnpy/cnpy.h>
// tclap
#include <tclap/CmdLine.h>

// typedefs
#include "types.h"

// globals
Scalar initial_radius;
double denoise_preserve;
double denoise_planar;
const Scalar delta_convergance = 1E-5;
const uint iteration_limit = 30;
const Point nanPoint( std::numeric_limits<Scalar>::quiet_NaN() );

inline Scalar compute_radius(Point &p, Vector &n, Point &q)
{
    // this is basic goniometry
    double d = Geometry::mag(p-q);
    Scalar cos_theta = ( n * (p-q) ) / d;
    return d/(2*cos_theta);
}

inline Scalar cos_angle(Vector p, Vector q)
{
    // Calculate the cosine of angle between vector p and q, see http://en.wikipedia.org/wiki/Law_of_cosines#Vector_formulation
    Scalar result = p*q / ( Geometry::mag(p) * Geometry::mag(q) );
    if( result > 1 ) return 1;
    else if( result < -1 ) return -1;
    return result;
}

Point sb_point(Point &p, Vector &n, kdtree2::KDTree* kd_tree)
{
    uint j=0;
    Scalar r, r_previous = 0;
    Point q, c_next;
    Point c = p - n * initial_radius;

    while (1)
    {
        #ifdef VERBOSEPRINT
        std::cout << "\nloop iteration: " << j << ", p = (" << p[0] << "," << p[1] << "," << p[2] << ", n = (" << n[0] << "," << n[1] << "," << n[2] << ") \n";

        std::cout << "c = (" << c[0] << "," << c[1] << "," << c[2] << ")\n";
        #endif

        // find closest point to c
        kdtree2::KDTreeResultVector result;
        kd_tree->n_nearest(c,2,result);
        q = kd_tree->the_data[ result[0].idx ];

        #ifdef VERBOSEPRINT
        std::cout << "q = (" << q[0] << "," << q[1] << "," << q[2] << ")\n";
        #endif

        // handle case when q==p
        if( q == p )
        {
            // 1) if r_previous==SuperR, apparantly no other points on the halfspace spanned by -n => that's an infinite ball
            if( r_previous == initial_radius )
            {
                r = initial_radius;
                c = nanPoint;
                break;
            // 2) otherwise just pick the second closest point
            } else {
                q = kd_tree->the_data[ result[1].idx ];
            }
        }

        // compute radius
        r = compute_radius(p,n,q);

        #ifdef VERBOSEPRINT
        std::cout << "r = " << r << "\n";
        #endif

        // if r < 0 closest point was on the wrong side of plane with normal n => start over with SuperRadius on the right side of that plane
        if( r < 0 )
            r = initial_radius;
        // if r > SuperR, stop now because otherwise in case of planar surface point configuration, we end up in an infinite loop
        else if( r > initial_radius )
        {
            r = initial_radius;
            c = nanPoint;
            break;
        }

        // compute next ball center
        c_next = p - n * r;

        // denoising
        if( denoise_preserve or denoise_planar )
        {
            Scalar a = cos_angle(p-c_next, q-c_next);
            Scalar separation_angle = Math::acos(a);

            if( denoise_preserve and ( separation_angle < denoise_preserve and j>0 and r > Geometry::mag(q-p) ) )
            {
                // keep previous radius:
                r = r_previous;
                break;
            }
            if( denoise_planar and ( separation_angle < denoise_planar and j==0 ) )
            {
                r = initial_radius;
                c = nanPoint;
                break;
            }
        }

        // stop iteration if r has converged
        if( Math::abs(r_previous-r) < delta_convergance )
            break;

        // stop iteration if this looks like an infinite loop:
        if( j > iteration_limit )
            break;

        r_previous = r;
        c = c_next;
        j++;
    }

    return c;
}

PointList sb_points(PointList &points, VectorList &normals, kdtree2::KDTree* kd_tree, bool inner=1)
{
    PointList ma_coords(points.size());
    Point p;
    Vector n;

    #pragma omp parallel for private(p, n)
    for( uint i=0; i<points.size(); i++ )
    {
        p = points[i];
        if( inner )
            n = normals[i];
        else
            n = -normals[i];
        ma_coords[i] = sb_point(p, n, kd_tree);
    }
    return ma_coords;
}

int main(int argc, char **argv)
{
    // parse command line arguments
    try {
        TCLAP::CmdLine cmd("Computes a MAT point approximation", ' ', "0.1");

        TCLAP::UnlabeledValueArg<std::string> inputArg( "input", "path to directory with inside it a 'coords.npy' and a 'normals.npy' file", true, "", "input dir", cmd);
        TCLAP::UnlabeledValueArg<std::string> outputArg( "ouput", "path to output directory", true, "", "output dir", cmd);

        TCLAP::ValueArg<double> denoise_preserveArg("d","preserve","denoise preserve threshold",false,20,"double", cmd);
        TCLAP::ValueArg<double> denoise_planarArg("p","planar","denoise planar threshold",false,32,"double", cmd);
        TCLAP::ValueArg<double> initial_radiusArg("r","radius","initial ball radius",false,200,"double", cmd);

        cmd.parse(argc,argv);

        initial_radius = initial_radiusArg.getValue();
        denoise_preserve = (3.1415/180) * denoise_preserveArg.getValue();
        denoise_planar = (3.1415/180) * denoise_planarArg.getValue();

        std::string input_coords_path = inputArg.getValue()+"/coords.npy";
        std::string input_normals_path = inputArg.getValue()+"/normals.npy";

        // check for proper in-output arguments
        {
            std::ifstream infile(input_coords_path.c_str());
            if(!infile)
                throw TCLAP::ArgParseException("invalid filepath", inputArg.getValue());
        }
        {
            std::ifstream infile(input_normals_path.c_str());
            if(!infile)
                throw TCLAP::ArgParseException("invalid filepath", inputArg.getValue());
        }
        {
            std::string output_path = outputArg.getValue()+"/ma_coords_in.npy";
            std::ofstream outfile(output_path.c_str());
            if(!outfile)
                throw TCLAP::ArgParseException("invalid filepath", outputArg.getValue());
        }

        std::cout << "Parameters: denoise_preserve="<<denoise_preserve<<", denoise_planar="<<denoise_planar<<", initial_radius="<<initial_radius<<"\n";

        cnpy::NpyArray coords_npy = cnpy::npy_load( input_coords_path.c_str() );
        float* coords_carray = reinterpret_cast<float*>(coords_npy.data);

        uint num_points = coords_npy.shape[0];
        uint dim = coords_npy.shape[1];
        PointList coords(num_points);
        for ( int i=0; i<num_points; i++) coords[i] = Point(&coords_carray[i*3]);
        coords_npy.destruct();

        cnpy::NpyArray normals_npy = cnpy::npy_load( input_normals_path.c_str() );
        float* normals_carray = reinterpret_cast<float*>(normals_npy.data);
        VectorList normals(normals_npy.shape[0]);
        for ( int i=0; i<num_points; i++) normals[i] = Vector(&normals_carray[i*3]);
        normals_npy.destruct();

        Misc::Timer t0;
        kdtree2::KDTree* kd_tree;
        kd_tree = new kdtree2::KDTree(coords,true);
        kd_tree->sort_results = true;
        t0.elapse();
        std::cout<<"Constructed kd-tree in "<<t0.getTime()*1000.0<<" ms"<<std::endl;

        // omp_set_num_threads(4);

        {
            Scalar* ma_coords_in_carray = new Scalar[num_points*3];
            Misc::Timer t1;
            PointList ma_coords_in = sb_points(coords, normals, kd_tree, 1);
            t1.elapse();
            std::cout<<"Done shrinking interior balls, took "<<t1.getTime()*1000.0<<" ms"<<std::endl;

            for (int i=0; i<ma_coords_in.size(); i++)
                for (int j=0; j<3; j++)
                    ma_coords_in_carray[i*3+j] = ma_coords_in[i][j];

            const unsigned int c_size = ma_coords_in.size();
            const unsigned int shape[] = {c_size,3};
            cnpy::npy_save((outputArg.getValue()+"/ma_coords_in.npy").c_str(), ma_coords_in_carray, shape, 2, "w");
        }

        {
            Scalar* ma_coords_out_carray = new Scalar[num_points*3];
            Misc::Timer t2;
            PointList ma_coords_out = sb_points(coords, normals, kd_tree, 0);
            t2.elapse();
            std::cout<<"Done shrinking exterior balls, took "<<t2.getTime()*1000.0<<" ms"<<std::endl;

            for (int i=0; i<ma_coords_out.size(); i++)
                for (int j=0; j<3; j++)
                    ma_coords_out_carray[i*3+j] = ma_coords_out[i][j];

            const unsigned int c_size = ma_coords_out.size();
            const unsigned int shape[] = {c_size,3};
            cnpy::npy_save((outputArg.getValue()+"/ma_coords_out.npy").c_str(), ma_coords_out_carray, shape, 2, "w");
        }

    } catch (TCLAP::ArgException &e) { std::cerr << "Error: " << e.error() << " for " << e.argId() << std::endl; }

    return 0;
}
<commit_msg>report parameters in degrees not radians<commit_after>// Copyright (c) 2015
// Ravi Peters -- r.y.peters@tudelft.nl
// All rights reserved
// This file is part of masbcpp.
//
// masbcpp 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.
//
// masbcpp 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 masbcpp.  If not, see <http://www.gnu.org/licenses/>.

// #define VERBOSEPRINT 1;
// #define WITH_OPENMP 1;

#include <iostream>
#include <fstream>
#include <string>
#include <limits>

// OpenMP
#ifdef WITH_OPENMP
    #ifdef CLANG_OMP
        #include <libiomp/omp.h>
    #else
        #include <omp.h>
    #endif
#endif

// Vrui
#include <vrui/Geometry/ComponentArray.h>
#include <vrui/Math/Math.h>
#include <vrui/Misc/Timer.h>
// kdtree2
#include <kdtree2/kdtree2.hpp>
// cnpy
#include <cnpy/cnpy.h>
// tclap
#include <tclap/CmdLine.h>

// typedefs
#include "types.h"

// globals
Scalar initial_radius;
double denoise_preserve;
double denoise_planar;
const Scalar delta_convergance = 1E-5;
const uint iteration_limit = 30;
const Point nanPoint( std::numeric_limits<Scalar>::quiet_NaN() );

inline Scalar compute_radius(Point &p, Vector &n, Point &q)
{
    // this is basic goniometry
    double d = Geometry::mag(p-q);
    Scalar cos_theta = ( n * (p-q) ) / d;
    return d/(2*cos_theta);
}

inline Scalar cos_angle(Vector p, Vector q)
{
    // Calculate the cosine of angle between vector p and q, see http://en.wikipedia.org/wiki/Law_of_cosines#Vector_formulation
    Scalar result = p*q / ( Geometry::mag(p) * Geometry::mag(q) );
    if( result > 1 ) return 1;
    else if( result < -1 ) return -1;
    return result;
}

Point sb_point(Point &p, Vector &n, kdtree2::KDTree* kd_tree)
{
    uint j=0;
    Scalar r, r_previous = 0;
    Point q, c_next;
    Point c = p - n * initial_radius;

    while (1)
    {
        #ifdef VERBOSEPRINT
        std::cout << "\nloop iteration: " << j << ", p = (" << p[0] << "," << p[1] << "," << p[2] << ", n = (" << n[0] << "," << n[1] << "," << n[2] << ") \n";

        std::cout << "c = (" << c[0] << "," << c[1] << "," << c[2] << ")\n";
        #endif

        // find closest point to c
        kdtree2::KDTreeResultVector result;
        kd_tree->n_nearest(c,2,result);
        q = kd_tree->the_data[ result[0].idx ];

        #ifdef VERBOSEPRINT
        std::cout << "q = (" << q[0] << "," << q[1] << "," << q[2] << ")\n";
        #endif

        // handle case when q==p
        if( q == p )
        {
            // 1) if r_previous==SuperR, apparantly no other points on the halfspace spanned by -n => that's an infinite ball
            if( r_previous == initial_radius )
            {
                r = initial_radius;
                c = nanPoint;
                break;
            // 2) otherwise just pick the second closest point
            } else {
                q = kd_tree->the_data[ result[1].idx ];
            }
        }

        // compute radius
        r = compute_radius(p,n,q);

        #ifdef VERBOSEPRINT
        std::cout << "r = " << r << "\n";
        #endif

        // if r < 0 closest point was on the wrong side of plane with normal n => start over with SuperRadius on the right side of that plane
        if( r < 0 )
            r = initial_radius;
        // if r > SuperR, stop now because otherwise in case of planar surface point configuration, we end up in an infinite loop
        else if( r > initial_radius )
        {
            r = initial_radius;
            c = nanPoint;
            break;
        }

        // compute next ball center
        c_next = p - n * r;

        // denoising
        if( denoise_preserve or denoise_planar )
        {
            Scalar a = cos_angle(p-c_next, q-c_next);
            Scalar separation_angle = Math::acos(a);

            if( denoise_preserve and ( separation_angle < denoise_preserve and j>0 and r > Geometry::mag(q-p) ) )
            {
                // keep previous radius:
                r = r_previous;
                break;
            }
            if( denoise_planar and ( separation_angle < denoise_planar and j==0 ) )
            {
                r = initial_radius;
                c = nanPoint;
                break;
            }
        }

        // stop iteration if r has converged
        if( Math::abs(r_previous-r) < delta_convergance )
            break;

        // stop iteration if this looks like an infinite loop:
        if( j > iteration_limit )
            break;

        r_previous = r;
        c = c_next;
        j++;
    }

    return c;
}

PointList sb_points(PointList &points, VectorList &normals, kdtree2::KDTree* kd_tree, bool inner=1)
{
    PointList ma_coords(points.size());
    Point p;
    Vector n;

    #pragma omp parallel for private(p, n)
    for( uint i=0; i<points.size(); i++ )
    {
        p = points[i];
        if( inner )
            n = normals[i];
        else
            n = -normals[i];
        ma_coords[i] = sb_point(p, n, kd_tree);
    }
    return ma_coords;
}

int main(int argc, char **argv)
{
    // parse command line arguments
    try {
        TCLAP::CmdLine cmd("Computes a MAT point approximation", ' ', "0.1");

        TCLAP::UnlabeledValueArg<std::string> inputArg( "input", "path to directory with inside it a 'coords.npy' and a 'normals.npy' file", true, "", "input dir", cmd);
        TCLAP::UnlabeledValueArg<std::string> outputArg( "ouput", "path to output directory", true, "", "output dir", cmd);

        TCLAP::ValueArg<double> denoise_preserveArg("d","preserve","denoise preserve threshold",false,20,"double", cmd);
        TCLAP::ValueArg<double> denoise_planarArg("p","planar","denoise planar threshold",false,32,"double", cmd);
        TCLAP::ValueArg<double> initial_radiusArg("r","radius","initial ball radius",false,200,"double", cmd);

        cmd.parse(argc,argv);

        initial_radius = initial_radiusArg.getValue();
        denoise_preserve = (3.1415/180) * denoise_preserveArg.getValue();
        denoise_planar = (3.1415/180) * denoise_planarArg.getValue();

        std::string input_coords_path = inputArg.getValue()+"/coords.npy";
        std::string input_normals_path = inputArg.getValue()+"/normals.npy";

        // check for proper in-output arguments
        {
            std::ifstream infile(input_coords_path.c_str());
            if(!infile)
                throw TCLAP::ArgParseException("invalid filepath", inputArg.getValue());
        }
        {
            std::ifstream infile(input_normals_path.c_str());
            if(!infile)
                throw TCLAP::ArgParseException("invalid filepath", inputArg.getValue());
        }
        {
            std::string output_path = outputArg.getValue()+"/ma_coords_in.npy";
            std::ofstream outfile(output_path.c_str());
            if(!outfile)
                throw TCLAP::ArgParseException("invalid filepath", outputArg.getValue());
        }

        std::cout << "Parameters: denoise_preserve="<<denoise_preserveArg.getValue()<<", denoise_planar="<<denoise_planarArg.getValue()<<", initial_radius="<<initial_radius<<"\n";

        cnpy::NpyArray coords_npy = cnpy::npy_load( input_coords_path.c_str() );
        float* coords_carray = reinterpret_cast<float*>(coords_npy.data);

        uint num_points = coords_npy.shape[0];
        uint dim = coords_npy.shape[1];
        PointList coords(num_points);
        for ( int i=0; i<num_points; i++) coords[i] = Point(&coords_carray[i*3]);
        coords_npy.destruct();

        cnpy::NpyArray normals_npy = cnpy::npy_load( input_normals_path.c_str() );
        float* normals_carray = reinterpret_cast<float*>(normals_npy.data);
        VectorList normals(normals_npy.shape[0]);
        for ( int i=0; i<num_points; i++) normals[i] = Vector(&normals_carray[i*3]);
        normals_npy.destruct();

        Misc::Timer t0;
        kdtree2::KDTree* kd_tree;
        kd_tree = new kdtree2::KDTree(coords,true);
        kd_tree->sort_results = true;
        t0.elapse();
        std::cout<<"Constructed kd-tree in "<<t0.getTime()*1000.0<<" ms"<<std::endl;

        // omp_set_num_threads(4);

        {
            Scalar* ma_coords_in_carray = new Scalar[num_points*3];
            Misc::Timer t1;
            PointList ma_coords_in = sb_points(coords, normals, kd_tree, 1);
            t1.elapse();
            std::cout<<"Done shrinking interior balls, took "<<t1.getTime()*1000.0<<" ms"<<std::endl;

            for (int i=0; i<ma_coords_in.size(); i++)
                for (int j=0; j<3; j++)
                    ma_coords_in_carray[i*3+j] = ma_coords_in[i][j];

            const unsigned int c_size = ma_coords_in.size();
            const unsigned int shape[] = {c_size,3};
            cnpy::npy_save((outputArg.getValue()+"/ma_coords_in.npy").c_str(), ma_coords_in_carray, shape, 2, "w");
        }

        {
            Scalar* ma_coords_out_carray = new Scalar[num_points*3];
            Misc::Timer t2;
            PointList ma_coords_out = sb_points(coords, normals, kd_tree, 0);
            t2.elapse();
            std::cout<<"Done shrinking exterior balls, took "<<t2.getTime()*1000.0<<" ms"<<std::endl;

            for (int i=0; i<ma_coords_out.size(); i++)
                for (int j=0; j<3; j++)
                    ma_coords_out_carray[i*3+j] = ma_coords_out[i][j];

            const unsigned int c_size = ma_coords_out.size();
            const unsigned int shape[] = {c_size,3};
            cnpy::npy_save((outputArg.getValue()+"/ma_coords_out.npy").c_str(), ma_coords_out_carray, shape, 2, "w");
        }

    } catch (TCLAP::ArgException &e) { std::cerr << "Error: " << e.error() << " for " << e.argId() << std::endl; }

    return 0;
}
<|endoftext|>


<commit_before>#include "HighPrecisionTimer.h"
#include "Utilities.h"

HighPrecisionTimerInner::HighPrecisionTimerInner()
	: mIsCancelled(false)
{

}

void HighPrecisionTimerInner::startTimer()
{
	mIsCancelled = false;
	mTimer.start();
}

void HighPrecisionTimerInner::cancel()
{
	mIsCancelled = true;
}

void HighPrecisionTimerInner::startLoop(int milliseconds)
{
	//Q_ASSERT(mTimer.isValid());
	while (mTimer.elapsed() < milliseconds && !mIsCancelled)
	{
		QThread::usleep(50);
	}
	//mTimer.invalidate();
	if (mIsCancelled)
	{
		return;
	}
	Q_EMIT timeout();

}

HighPrecisionTimer::HighPrecisionTimer(QObject* parent /*= nullptr*/)
	: QObject(parent)
	, mThread(new QThread(this))
	, mInner(new HighPrecisionTimerInner)
	, mIsRunning(false)
{
	VERIFY(connect(this, SIGNAL(startInner(int)), mInner, SLOT(startLoop(int))));
	VERIFY(connect(mInner, SIGNAL(timeout()), this, SLOT(timeoutInner())));

	mThread->start(QThread::TimeCriticalPriority);
	mInner->moveToThread(mThread);

}

HighPrecisionTimer::~HighPrecisionTimer()
{
	cancel();
}

void HighPrecisionTimer::cancel()
{
    mIsRunning = false;
	mInner->cancel();
}

void HighPrecisionTimer::start(int milliseconds)
{
	if (mIsRunning)
	{
		cancel();
	}
	mIsRunning = true;
	mInner->startTimer();
	Q_EMIT startInner(milliseconds);
}

void HighPrecisionTimer::timeoutInner()
{
    if (mIsRunning)
    {
        mIsRunning = false;
        Q_EMIT timeout();
    }
}

<commit_msg>Clean thread exit on high precision timer<commit_after>#include "HighPrecisionTimer.h"
#include "Utilities.h"

HighPrecisionTimerInner::HighPrecisionTimerInner()
	: mIsCancelled(false)
{

}

void HighPrecisionTimerInner::startTimer()
{
	mIsCancelled = false;
	mTimer.start();
}

void HighPrecisionTimerInner::cancel()
{
	mIsCancelled = true;
}

void HighPrecisionTimerInner::startLoop(int milliseconds)
{
	//Q_ASSERT(mTimer.isValid());
	while (mTimer.elapsed() < milliseconds && !mIsCancelled)
	{
		QThread::usleep(50);
	}
	//mTimer.invalidate();
	if (mIsCancelled)
	{
		return;
	}
	Q_EMIT timeout();

}

HighPrecisionTimer::HighPrecisionTimer(QObject* parent /*= nullptr*/)
	: QObject(parent)
	, mThread(new QThread(this))
	, mInner(new HighPrecisionTimerInner)
	, mIsRunning(false)
{
	VERIFY(connect(this, SIGNAL(startInner(int)), mInner, SLOT(startLoop(int))));
	VERIFY(connect(mInner, SIGNAL(timeout()), this, SLOT(timeoutInner())));

	mThread->start(QThread::TimeCriticalPriority);
	mInner->moveToThread(mThread);

}

HighPrecisionTimer::~HighPrecisionTimer()
{
    mThread->quit();
	cancel();
    VERIFY(mThread->wait(5000));
}

void HighPrecisionTimer::cancel()
{
    mIsRunning = false;
	mInner->cancel();
}

void HighPrecisionTimer::start(int milliseconds)
{
	if (mIsRunning)
	{
		cancel();
	}
	mIsRunning = true;
	mInner->startTimer();
	Q_EMIT startInner(milliseconds);
}

void HighPrecisionTimer::timeoutInner()
{
    if (mIsRunning)
    {
        mIsRunning = false;
        Q_EMIT timeout();
    }
}

<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "thread.hh"
#include "posix.hh"
#include <ucontext.h>

/// \cond internal

namespace seastar {

thread_local jmp_buf_link g_unthreaded_context;
thread_local jmp_buf_link* g_current_context;

thread_context::thread_context(std::function<void ()> func)
        : _func(std::move(func)) {
    setup();
}

void
thread_context::setup() {
    // use setcontext() for the initial jump, as it allows us
    // to set up a stack, but continue with longjmp() as it's
    // much faster.
    ucontext_t initial_context;
    auto q = uint64_t(reinterpret_cast<uintptr_t>(this));
    auto main = reinterpret_cast<void (*)()>(&thread_context::s_main);
    auto r = getcontext(&initial_context);
    throw_system_error_on(r == -1);
    initial_context.uc_stack.ss_sp = _stack.get();
    initial_context.uc_stack.ss_size = _stack_size;
    initial_context.uc_link = nullptr;
    makecontext(&initial_context, main, 2, int(q), int(q >> 32));
    auto prev = g_current_context;
    _context.link = prev;
    _context.thread = this;
    g_current_context = &_context;
    if (setjmp(prev->jmpbuf) == 0) {
        setcontext(&initial_context);
    }
}

void
thread_context::switch_in() {
    // FIXME: use setjmp/longjmp after initial_switch_in, much faster
    auto prev = g_current_context;
    g_current_context = &_context;
    _context.link = prev;
    if (setjmp(prev->jmpbuf) == 0) {
        longjmp(_context.jmpbuf, 1);
    }
}

void
thread_context::switch_out() {
    g_current_context = _context.link;
    if (setjmp(_context.jmpbuf) == 0) {
        longjmp(g_current_context->jmpbuf, 1);
    }
}

void
thread_context::s_main(unsigned int lo, unsigned int hi) {
    uintptr_t q = lo | (uint64_t(hi) << 32);
    reinterpret_cast<thread_context*>(q)->main();
}

void
thread_context::main() {
    try {
        _func();
        _done.set_value();
    } catch (...) {
        _done.set_exception(std::current_exception());
    }
    g_current_context = _context.link;
    longjmp(g_current_context->jmpbuf, 1);
}

namespace thread_impl {

thread_context* get() {
    return g_current_context->thread;
}

void switch_in(thread_context* to) {
    to->switch_in();
}

void switch_out(thread_context* from) {
    from->switch_out();
}

void init() {
    g_unthreaded_context.link = nullptr;
    g_unthreaded_context.thread = nullptr;
    g_current_context = &g_unthreaded_context;
}

}

}

/// \endcond
<commit_msg>thread: remove obsolete FIXME<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "thread.hh"
#include "posix.hh"
#include <ucontext.h>

/// \cond internal

namespace seastar {

thread_local jmp_buf_link g_unthreaded_context;
thread_local jmp_buf_link* g_current_context;

thread_context::thread_context(std::function<void ()> func)
        : _func(std::move(func)) {
    setup();
}

void
thread_context::setup() {
    // use setcontext() for the initial jump, as it allows us
    // to set up a stack, but continue with longjmp() as it's
    // much faster.
    ucontext_t initial_context;
    auto q = uint64_t(reinterpret_cast<uintptr_t>(this));
    auto main = reinterpret_cast<void (*)()>(&thread_context::s_main);
    auto r = getcontext(&initial_context);
    throw_system_error_on(r == -1);
    initial_context.uc_stack.ss_sp = _stack.get();
    initial_context.uc_stack.ss_size = _stack_size;
    initial_context.uc_link = nullptr;
    makecontext(&initial_context, main, 2, int(q), int(q >> 32));
    auto prev = g_current_context;
    _context.link = prev;
    _context.thread = this;
    g_current_context = &_context;
    if (setjmp(prev->jmpbuf) == 0) {
        setcontext(&initial_context);
    }
}

void
thread_context::switch_in() {
    auto prev = g_current_context;
    g_current_context = &_context;
    _context.link = prev;
    if (setjmp(prev->jmpbuf) == 0) {
        longjmp(_context.jmpbuf, 1);
    }
}

void
thread_context::switch_out() {
    g_current_context = _context.link;
    if (setjmp(_context.jmpbuf) == 0) {
        longjmp(g_current_context->jmpbuf, 1);
    }
}

void
thread_context::s_main(unsigned int lo, unsigned int hi) {
    uintptr_t q = lo | (uint64_t(hi) << 32);
    reinterpret_cast<thread_context*>(q)->main();
}

void
thread_context::main() {
    try {
        _func();
        _done.set_value();
    } catch (...) {
        _done.set_exception(std::current_exception());
    }
    g_current_context = _context.link;
    longjmp(g_current_context->jmpbuf, 1);
}

namespace thread_impl {

thread_context* get() {
    return g_current_context->thread;
}

void switch_in(thread_context* to) {
    to->switch_in();
}

void switch_out(thread_context* from) {
    from->switch_out();
}

void init() {
    g_unthreaded_context.link = nullptr;
    g_unthreaded_context.thread = nullptr;
    g_current_context = &g_unthreaded_context;
}

}

}

/// \endcond
<|endoftext|>


<commit_before>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
  printf("Hello, this is Caleb\n");
  VideoCapture cap("videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;
}
<commit_msg>test code<commit_after>/*

*/

#include "lineFollowing.h"

using namespace std;
using namespace cv;

ControlMovements lineFollowingControl() {

  line_main();

  return ControlMovements();
}

void line_main() {
//  printf("Hello, this is Caleb\n");

  VideoCapture cap("videos/top_down_4.m4v");
  if (!cap.isOpened())  // check if we succeeded
    return;

  namedWindow("linesH", CV_WINDOW_NORMAL);
  Mat edges;
  for(;;)
  {
    Mat frame;
    cap >> frame; // get a new frame from camera
    cvtColor(frame, edges, CV_BGR2GRAY);
    GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
    Canny(edges, edges, 0, 30, 3);
    imshow("edges", edges);
    if(waitKey(30) >= 0) break;
  }
  // the camera will be deinitialized automatically in VideoCapture destructor
  return;
}
<|endoftext|>