<commit_before>/**
 *	\file
 */

#pragma once

#include <rleahylib/rleahylib.hpp>
#include <utility>
#include <type_traits>
#include <cmath>
#include <cstring>
#include <functional>
#include <algorithm>
#include <limits>
#include <unordered_map>
#include <fma.hpp>

#pragma GCC optimize ("fast-math")

namespace MCPP {

	/**
	 *	Generates simplex noise.
	 */
	class Simplex {

		private:

			Byte permutation [512];

			template <typename T>
			inline Byte get_random (T & gen, Byte bound) noexcept(noexcept(gen())) {

				typedef typename T::result_type stype;
				typedef typename std::make_unsigned<stype>::type type;

				union {
					type r;
					stype r_in;
				};

				//	If the bound is the maximum integer
				//	for the unsigned result type, it cannot
				//	be affected by modulo bias, so we simply
				//	return the next integer generated
				if (bound==std::numeric_limits<type>::max()) {

					r_in=gen();

					return r;

				}

				type d=static_cast<type>(bound)+1;
				//	This is the maximum number the random
				//	number generator may yield, divided
				//	by the divisor.
				type q=std::numeric_limits<type>::max()/d;

				//	Loop until we retrieve a random
				//	number unaffected by modulo bias
				//	over the given range
				do r_in=gen();
				while(
					//	This eliminates modulo bias by
					//	asking:
					//
					//	If I restrict the inputs to
					//	modulus to the range [(r/d)*d,((r/d)+1)*d)
					//	could I obtain all values within
					//	the bound given the maximum output
					//	of the random number generator?
					//
					//	If the answer is no a new number is
					//	obtained.
					//
					//	Example:
					//
					//	The function is called with a generator
					//	which generates [-128,127] (i.e. the range
					//	of a signed byte), and a bound of 5 (i.e.
					//	the output range is [0,5].
					//
					//	The union of r and r_in will map this range
					//	to an output range of [0,255] (i.e. the range
					//	of an unsigned byte).
					//
					//	If the random number generates a number on
					//	the range [252,255], modulo bias would occur.
					//
					//	Consider the outputs that would be yielded
					//	by blindly applying modulus to this range:
					//
					//	252 = 0
					//	253 = 1
					//	254 = 2
					//	255 = 3
					//
					//	The numbers 4 and 5 from the desired output
					//	range are not present, increasing the likelihood
					//	of obtaining outputs in the range [0,3].
					//
					//	In this case:
					//
					//	d=6
					//	q=255/6=42
					//
					//	Consider the case r=252:
					//
					//	(r/d)+1=43
					//
					//	This means that in order for 252 not to
					//	produce modulo bias (if not discarded)
					//	the random number generator would have to
					//	be capable of generating numbers up to
					//	at least (43*d)-1=257 (which it is not).
					//
					//	But we see that ((r/d)+1)>q, which
					//	causes this result to be discarded.
					((r/d)+1)>q
				);

				//	Current result will not produce
				//	modulo bias, apply modulus and return
				return static_cast<Byte>(r%d);

			}

			template <typename T>
			inline void init (T & gen) noexcept(noexcept(gen())) {

				//	Populate and shuffle the first half
				//	of the table using Fisher-Yates-Knuth
				//	shuffle
				for (Word i=0;i<(sizeof(permutation)/2);++i) {

					permutation[i]=static_cast<Byte>(i);

					std::swap(
						permutation[i],
						permutation[
							get_random(
								gen,
								static_cast<Byte>(i)
							)
						]
					);

				}

				//	Copy the first half of the table
				//	into the last half
				memcpy(
					&permutation[sizeof(permutation)/2],
					permutation,
					sizeof(permutation)/2
				);

			}

		public:

			/**
			 *	Creates a new simplex noise generator
			 *	with a randomly-chosen seed.
			 */
			Simplex ();
			/**
			 *	Creates a new simplex noise generator
			 *	seeded with a certain seed.
			 *
			 *	\param [in] seed
			 *		The seed which shall be used to
			 *		seed the noise generator.
			 */
			explicit Simplex (UInt64 seed) noexcept;
			/**
			 *	Creates a new simplex noise generator
			 *	seeded by a provided random number
			 *	generator.
			 *
			 *	\param [in] gen
			 *		A random number generator which
			 *		shall be used to seed the noise
			 *		generator.
			 */
			template <typename T, typename=typename std::enable_if<!std::numeric_limits<T>::is_integer>::type>
			explicit Simplex (T & gen) noexcept(noexcept(std::declval<Simplex>().init(gen))) {

				init(gen);

			}

			/**
			 *	Retrieves raw 2D noise.
			 *
			 *	\param [in] x
			 *		The x value.
			 *	\param [i] y
			 *		The y value.
			 *
			 *	\return
			 *		The raw noise output.
			 */
			Double operator () (Double x, Double y) const noexcept;
			/**
			 *	Retrieves raw 3D noise.
			 *
			 *	\param [in] x
			 *		The x value.
			 *	\param [in] y
			 *		The y value.
			 *	param [in] z
			 *		The z value.
			 *
			 *	\return
			 *		The raw noise output.
			 */
			Double operator () (Double x, Double y, Double z) const noexcept;
			/**
			 *	Retrieves raw 4D noise.
			 *
			 *	\param [in] w
			 *		The w value.
			 *	\param [in] x
			 *		The x value.
			 *	\param [in] y
			 *		The y value.
			 *	\param [in] z
			 *		The z value.
			 *
			 *	\return
			 *		The raw noise output.
			 */
			Double operator () (Double w, Double x, Double y, Double z) const noexcept;

	};

	/**
	 *	Selects a value from a range based on
	 *	a multiplier between 0 and 1.
	 *
	 *	\param [in] lo
	 *		The low end of the range to choose
	 *		from.
	 *	\param [in] hi
	 *		The high end of the range to choose
	 *		from.
	 *	\param [in] val
	 *		A value between zero and one (inclusive).
	 *		Input values close to one will yield
	 *		results close to \em hi, input values
	 *		close to zero will yield results close
	 *		to \em lo.
	 *
	 *	\return
	 *		A result chosen between \em lo and \em hi
	 *		according to \em val.  The exact algorithm
	 *		used shall be equivalent to ((hi-lo)*val)+lo.
	 */
	inline Double Select (Double lo, Double hi, Double val) noexcept {

		return fma(
			hi-lo,
			val,
			lo
		);

	}

	/**
	 *	Normalizes a value, yielding a value between 0
	 *	and 1 which specifies how far between a maximum
	 *	and minimum it is.
	 *
	 *	\param [in] lo
	 *		The number a \em val of 0 shall yield.
	 *	\param [in] hi
	 *		The number a \em val of 1 shall yield.
	 *	\param [in] val
	 *		A number between 0 and 1.
	 *
	 *	\return
	 *		A result chosen between \em lo and \em hi
	 *		such that this result multiplied by the
	 *		range gives the distance from \em lo.
	 *		For values of \em hi, 1 is returned, for
	 *		values of \em lo, 0 is returned, and all
	 *		values beteween 0 and 1 are placed proportionally
	 *		there between.
	 */
	inline Double Normalize (Double lo, Double hi, Double val) noexcept {

		if (lo==hi) {

			if (val==lo) return 0.5;
			if (val>lo) return 1;
			return 0;

		}

		bool complement;
		if (lo>hi) {

			complement=true;
			std::swap(lo,hi);

		} else {

			complement=false;

		}

		Double difference=val-lo;
		Double range=hi-lo;

		if (difference<0) return complement ? 1 : 0;
		if (difference>range) return complement ? 0 : 1;

		Double result=difference/range;

		return complement ? (1-result) : result;

	}

	/**
	 *	Given an input on a range, adjusts the value
	 *	such that it is on a different range.
	 *
	 *	\param [in] lo
	 *		The low end of the desired range.
	 *	\param [in] hi
	 *		The high end of the desired range.
	 *	\param [in] in_lo
	 *		The low end of the range of the
	 *		input.
	 *	\param [in] in_hi
	 *		The high end of the range of the
	 *		input.
	 *	\param [in] in
	 *		The input.
	 *
	 *	\return
	 *		The value that \em in would have were
	 *		it on the range given by \em lo, \em hi,
	 *		as opposed to the range \em in_lo, \em in_hi.
	 */
	inline Double Scale (Double lo, Double hi, Double in_lo, Double in_hi, Double in) noexcept {

		return Select(
			lo,
			hi,
			Normalize(
				in_lo,
				in_hi,
				in
			)
		);

	}

	/**
	 *	Given a simplex noise generator and
	 *	arguments to forward through to it,
	 *	adjusts the output of the noise
	 *	generator to place it on some
	 *	arbitrary range.
	 *
	 *	\tparam Args
	 *		The types of the arguments which
	 *		shall be forwarded through to the
	 *		simplex noise generator.
	 *
	 *	\param [in] lo
	 *		The low end of the desired range.
	 *	\param [in] hi
	 *		The high end of the desired range.
	 *	\param [in] gen
	 *		A reference to a simplex noise
	 *		generator.
	 *	\param [in] args
	 *		The arguments which shall be forwarded
	 *		through to \em gen.
	 *
	 *	\return
	 *		A noise value adjusted to the range
	 *		\em lo, \em hi.
	 */
	template <typename... Args>
	Double Scale (Double lo, Double hi, const Simplex & gen, Args &&... args) noexcept {

		return fma(
			gen(std::forward<Args>(args)...),
			(hi-lo)/2,
			(hi+lo)/2
		);

	}

	/**
	 *	\cond
	 */

	inline Double octave_helper (Double arg, Double frequency) noexcept {

		return arg*frequency;

	}

	/**
	 *	\endcond
	 */

	/**
	 *	Applies an octave filter to the output
	 *	of a certain generator.
	 *
	 *	\tparam T
	 *		The type of generator whose output
	 *		shall be filtered.
	 *	\tparam Args
	 *		The types of the arguments to forward
	 *		through to the generator.
	 *
	 *	\param [in] octaves
	 *		The number of octaves which shall be
	 *		applied.
	 *	\param [in] persistence
	 *		The persistence of the noise from each
	 *		octave.
	 *	\param [in] frequency
	 *		The starting sampling frequency.
	 *	\param [in] func
	 *		The generator.
	 *	\param [in] args
	 *		The arguments to forward through to
	 *		\em generator.
	 *
	 *	\return
	 *		A filtered value from \em func.
	 */
	template <typename T, typename... Args>
	Double Octave (Word octaves, Double persistence, Double frequency, T && func, Args &&...args) noexcept(
		noexcept(func(std::forward<Args>(args)...))
	) {

		Double total=0;
		Double amplitude=1;
		Double max_amp=0;

		for (Word i=0;i<octaves;++i) {

			total=fma(
				func(
					octave_helper(
						std::forward<Args>(args),
						frequency
					)...
				),
				amplitude,
				total
			);

			frequency*=2;
			max_amp+=amplitude;
			amplitude*=persistence;

		}

		return total/max_amp;

	}

	/**
	 *	Applies a bias filter to a value.  Given a value
	 *	on the range [0,1], a bias filter pushes values
	 *	towards 1 for bias values greater than 0.5,
	 *	towards 0 for bias values less than 0.5, and
	 *	does nothing for bias values of exactly 0.5.
	 *
	 *	\param [in] bias
	 *		The bias value.
	 *	\param [in] input
	 *		Input on the range [0,1].
	 *
	 *	\return
	 *		A biased noise value.
	 */
	inline Double Bias (Double bias, Double input) noexcept {

		return pow(
			input,
			log(bias)/log(0.5)
		);

	}

	/**
	 *	Applies a gain filter to a value.  Given a value
	 *	on the range [0,1], a gain filter pushes values
	 *	towards 0 and 1 for gain values greater than 0.5,
	 *	towards 0.5 for gain values less than 0.5, and
	 *	does nothing for gain values of exactly 0.5.
	 *
	 *	\param [in] gain
	 *		The gain value.
	 *	\param [in] input
	 *		Input on the range [0,1].
	 *
	 *	\return
	 *		A filtered noise value.
	 */
	inline Double Gain (Double gain, Double input) noexcept {

		Double complement=1-gain;
		input*=2;

		return (
			(input<0.5)
				?
					(Bias(
						complement,
						input
					)/2)
				:	(1-(Bias(
						complement,
						2-input
					)/2))
		);

	}

	/**
	 *	Creates a ridged multifractal.
	 *
	 *	\param [in] input
	 *		A particular noise value.
	 *
	 *	\return
	 *		The corresponding value mapped to
	 *		a ridged multifractal.
	 */
	inline Double Ridged (Double input) noexcept {

		return 1-fabs(input);

	}

}

#pragma GCC reset_options
<commit_msg>Noise Includes<commit_after>/**
 *	\file
 */

#pragma once

#include <rleahylib/rleahylib.hpp>
#include <fma.hpp>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <functional>
#include <limits>
#include <unordered_map>
#include <utility>
#include <type_traits>

#pragma GCC optimize ("fast-math")

namespace MCPP {

	/**
	 *	Generates simplex noise.
	 */
	class Simplex {

		private:

			Byte permutation [512];

			template <typename T>
			inline Byte get_random (T & gen, Byte bound) noexcept(noexcept(gen())) {

				typedef typename T::result_type stype;
				typedef typename std::make_unsigned<stype>::type type;

				union {
					type r;
					stype r_in;
				};

				//	If the bound is the maximum integer
				//	for the unsigned result type, it cannot
				//	be affected by modulo bias, so we simply
				//	return the next integer generated
				if (bound==std::numeric_limits<type>::max()) {

					r_in=gen();

					return r;

				}

				type d=static_cast<type>(bound)+1;
				//	This is the maximum number the random
				//	number generator may yield, divided
				//	by the divisor.
				type q=std::numeric_limits<type>::max()/d;

				//	Loop until we retrieve a random
				//	number unaffected by modulo bias
				//	over the given range
				do r_in=gen();
				while(
					//	This eliminates modulo bias by
					//	asking:
					//
					//	If I restrict the inputs to
					//	modulus to the range [(r/d)*d,((r/d)+1)*d)
					//	could I obtain all values within
					//	the bound given the maximum output
					//	of the random number generator?
					//
					//	If the answer is no a new number is
					//	obtained.
					//
					//	Example:
					//
					//	The function is called with a generator
					//	which generates [-128,127] (i.e. the range
					//	of a signed byte), and a bound of 5 (i.e.
					//	the output range is [0,5].
					//
					//	The union of r and r_in will map this range
					//	to an output range of [0,255] (i.e. the range
					//	of an unsigned byte).
					//
					//	If the random number generates a number on
					//	the range [252,255], modulo bias would occur.
					//
					//	Consider the outputs that would be yielded
					//	by blindly applying modulus to this range:
					//
					//	252 = 0
					//	253 = 1
					//	254 = 2
					//	255 = 3
					//
					//	The numbers 4 and 5 from the desired output
					//	range are not present, increasing the likelihood
					//	of obtaining outputs in the range [0,3].
					//
					//	In this case:
					//
					//	d=6
					//	q=255/6=42
					//
					//	Consider the case r=252:
					//
					//	(r/d)+1=43
					//
					//	This means that in order for 252 not to
					//	produce modulo bias (if not discarded)
					//	the random number generator would have to
					//	be capable of generating numbers up to
					//	at least (43*d)-1=257 (which it is not).
					//
					//	But we see that ((r/d)+1)>q, which
					//	causes this result to be discarded.
					((r/d)+1)>q
				);

				//	Current result will not produce
				//	modulo bias, apply modulus and return
				return static_cast<Byte>(r%d);

			}

			template <typename T>
			inline void init (T & gen) noexcept(noexcept(gen())) {

				//	Populate and shuffle the first half
				//	of the table using Fisher-Yates-Knuth
				//	shuffle
				for (Word i=0;i<(sizeof(permutation)/2);++i) {

					permutation[i]=static_cast<Byte>(i);

					std::swap(
						permutation[i],
						permutation[
							get_random(
								gen,
								static_cast<Byte>(i)
							)
						]
					);

				}

				//	Copy the first half of the table
				//	into the last half
				memcpy(
					&permutation[sizeof(permutation)/2],
					permutation,
					sizeof(permutation)/2
				);

			}

		public:

			/**
			 *	Creates a new simplex noise generator
			 *	with a randomly-chosen seed.
			 */
			Simplex ();
			/**
			 *	Creates a new simplex noise generator
			 *	seeded with a certain seed.
			 *
			 *	\param [in] seed
			 *		The seed which shall be used to
			 *		seed the noise generator.
			 */
			explicit Simplex (UInt64 seed) noexcept;
			/**
			 *	Creates a new simplex noise generator
			 *	seeded by a provided random number
			 *	generator.
			 *
			 *	\param [in] gen
			 *		A random number generator which
			 *		shall be used to seed the noise
			 *		generator.
			 */
			template <typename T, typename=typename std::enable_if<!std::numeric_limits<T>::is_integer>::type>
			explicit Simplex (T & gen) noexcept(noexcept(std::declval<Simplex>().init(gen))) {

				init(gen);

			}

			/**
			 *	Retrieves raw 2D noise.
			 *
			 *	\param [in] x
			 *		The x value.
			 *	\param [i] y
			 *		The y value.
			 *
			 *	\return
			 *		The raw noise output.
			 */
			Double operator () (Double x, Double y) const noexcept;
			/**
			 *	Retrieves raw 3D noise.
			 *
			 *	\param [in] x
			 *		The x value.
			 *	\param [in] y
			 *		The y value.
			 *	param [in] z
			 *		The z value.
			 *
			 *	\return
			 *		The raw noise output.
			 */
			Double operator () (Double x, Double y, Double z) const noexcept;
			/**
			 *	Retrieves raw 4D noise.
			 *
			 *	\param [in] w
			 *		The w value.
			 *	\param [in] x
			 *		The x value.
			 *	\param [in] y
			 *		The y value.
			 *	\param [in] z
			 *		The z value.
			 *
			 *	\return
			 *		The raw noise output.
			 */
			Double operator () (Double w, Double x, Double y, Double z) const noexcept;

	};

	/**
	 *	Selects a value from a range based on
	 *	a multiplier between 0 and 1.
	 *
	 *	\param [in] lo
	 *		The low end of the range to choose
	 *		from.
	 *	\param [in] hi
	 *		The high end of the range to choose
	 *		from.
	 *	\param [in] val
	 *		A value between zero and one (inclusive).
	 *		Input values close to one will yield
	 *		results close to \em hi, input values
	 *		close to zero will yield results close
	 *		to \em lo.
	 *
	 *	\return
	 *		A result chosen between \em lo and \em hi
	 *		according to \em val.  The exact algorithm
	 *		used shall be equivalent to ((hi-lo)*val)+lo.
	 */
	inline Double Select (Double lo, Double hi, Double val) noexcept {

		return fma(
			hi-lo,
			val,
			lo
		);

	}

	/**
	 *	Normalizes a value, yielding a value between 0
	 *	and 1 which specifies how far between a maximum
	 *	and minimum it is.
	 *
	 *	\param [in] lo
	 *		The number a \em val of 0 shall yield.
	 *	\param [in] hi
	 *		The number a \em val of 1 shall yield.
	 *	\param [in] val
	 *		A number between 0 and 1.
	 *
	 *	\return
	 *		A result chosen between \em lo and \em hi
	 *		such that this result multiplied by the
	 *		range gives the distance from \em lo.
	 *		For values of \em hi, 1 is returned, for
	 *		values of \em lo, 0 is returned, and all
	 *		values beteween 0 and 1 are placed proportionally
	 *		there between.
	 */
	inline Double Normalize (Double lo, Double hi, Double val) noexcept {

		if (lo==hi) {

			if (val==lo) return 0.5;
			if (val>lo) return 1;
			return 0;

		}

		bool complement;
		if (lo>hi) {

			complement=true;
			std::swap(lo,hi);

		} else {

			complement=false;

		}

		Double difference=val-lo;
		Double range=hi-lo;

		if (difference<0) return complement ? 1 : 0;
		if (difference>range) return complement ? 0 : 1;

		Double result=difference/range;

		return complement ? (1-result) : result;

	}

	/**
	 *	Given an input on a range, adjusts the value
	 *	such that it is on a different range.
	 *
	 *	\param [in] lo
	 *		The low end of the desired range.
	 *	\param [in] hi
	 *		The high end of the desired range.
	 *	\param [in] in_lo
	 *		The low end of the range of the
	 *		input.
	 *	\param [in] in_hi
	 *		The high end of the range of the
	 *		input.
	 *	\param [in] in
	 *		The input.
	 *
	 *	\return
	 *		The value that \em in would have were
	 *		it on the range given by \em lo, \em hi,
	 *		as opposed to the range \em in_lo, \em in_hi.
	 */
	inline Double Scale (Double lo, Double hi, Double in_lo, Double in_hi, Double in) noexcept {

		return Select(
			lo,
			hi,
			Normalize(
				in_lo,
				in_hi,
				in
			)
		);

	}

	/**
	 *	Given a simplex noise generator and
	 *	arguments to forward through to it,
	 *	adjusts the output of the noise
	 *	generator to place it on some
	 *	arbitrary range.
	 *
	 *	\tparam Args
	 *		The types of the arguments which
	 *		shall be forwarded through to the
	 *		simplex noise generator.
	 *
	 *	\param [in] lo
	 *		The low end of the desired range.
	 *	\param [in] hi
	 *		The high end of the desired range.
	 *	\param [in] gen
	 *		A reference to a simplex noise
	 *		generator.
	 *	\param [in] args
	 *		The arguments which shall be forwarded
	 *		through to \em gen.
	 *
	 *	\return
	 *		A noise value adjusted to the range
	 *		\em lo, \em hi.
	 */
	template <typename... Args>
	Double Scale (Double lo, Double hi, const Simplex & gen, Args &&... args) noexcept {

		return fma(
			gen(std::forward<Args>(args)...),
			(hi-lo)/2,
			(hi+lo)/2
		);

	}

	/**
	 *	\cond
	 */

	inline Double octave_helper (Double arg, Double frequency) noexcept {

		return arg*frequency;

	}

	/**
	 *	\endcond
	 */

	/**
	 *	Applies an octave filter to the output
	 *	of a certain generator.
	 *
	 *	\tparam T
	 *		The type of generator whose output
	 *		shall be filtered.
	 *	\tparam Args
	 *		The types of the arguments to forward
	 *		through to the generator.
	 *
	 *	\param [in] octaves
	 *		The number of octaves which shall be
	 *		applied.
	 *	\param [in] persistence
	 *		The persistence of the noise from each
	 *		octave.
	 *	\param [in] frequency
	 *		The starting sampling frequency.
	 *	\param [in] func
	 *		The generator.
	 *	\param [in] args
	 *		The arguments to forward through to
	 *		\em generator.
	 *
	 *	\return
	 *		A filtered value from \em func.
	 */
	template <typename T, typename... Args>
	Double Octave (Word octaves, Double persistence, Double frequency, T && func, Args &&...args) noexcept(
		noexcept(func(std::forward<Args>(args)...))
	) {

		Double total=0;
		Double amplitude=1;
		Double max_amp=0;

		for (Word i=0;i<octaves;++i) {

			total=fma(
				func(
					octave_helper(
						std::forward<Args>(args),
						frequency
					)...
				),
				amplitude,
				total
			);

			frequency*=2;
			max_amp+=amplitude;
			amplitude*=persistence;

		}

		return total/max_amp;

	}

	/**
	 *	Applies a bias filter to a value.  Given a value
	 *	on the range [0,1], a bias filter pushes values
	 *	towards 1 for bias values greater than 0.5,
	 *	towards 0 for bias values less than 0.5, and
	 *	does nothing for bias values of exactly 0.5.
	 *
	 *	\param [in] bias
	 *		The bias value.
	 *	\param [in] input
	 *		Input on the range [0,1].
	 *
	 *	\return
	 *		A biased noise value.
	 */
	inline Double Bias (Double bias, Double input) noexcept {

		return pow(
			input,
			log(bias)/log(0.5)
		);

	}

	/**
	 *	Applies a gain filter to a value.  Given a value
	 *	on the range [0,1], a gain filter pushes values
	 *	towards 0 and 1 for gain values greater than 0.5,
	 *	towards 0.5 for gain values less than 0.5, and
	 *	does nothing for gain values of exactly 0.5.
	 *
	 *	\param [in] gain
	 *		The gain value.
	 *	\param [in] input
	 *		Input on the range [0,1].
	 *
	 *	\return
	 *		A filtered noise value.
	 */
	inline Double Gain (Double gain, Double input) noexcept {

		Double complement=1-gain;
		input*=2;

		return (
			(input<0.5)
				?
					(Bias(
						complement,
						input
					)/2)
				:	(1-(Bias(
						complement,
						2-input
					)/2))
		);

	}

	/**
	 *	Creates a ridged multifractal.
	 *
	 *	\param [in] input
	 *		A particular noise value.
	 *
	 *	\return
	 *		The corresponding value mapped to
	 *		a ridged multifractal.
	 */
	inline Double Ridged (Double input) noexcept {

		return 1-fabs(input);

	}

}

#pragma GCC reset_options
<|endoftext|>


<commit_before>///
/// @file  pmath.hpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <cmath>
#include <vector>
#include <limits>

inline int64_t isquare(int64_t x)
{
  return x * x;
}

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return static_cast<T2>(min);
  if (x > max)
    return static_cast<T2>(max);

  return x;
}

template <typename T>
inline T number_of_bits(T)
{
  return static_cast<T>(sizeof(T) * 8);
}

/// @brief  Check if an integer is a power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline bool is_power_of_2(T x)
{
  return (x != 0 && (x & (x - 1)) == 0);
}

/// @brief  Round up to the next power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline T next_power_of_2(T x)
{
  if (x == 0)
    return 1;

  x--;
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return ++x;
}

template <typename T>
inline int ilog(T x)
{
  return static_cast<int>(std::log(static_cast<double>(x)));
}

/// Raise to power
template <int N>
inline int64_t ipow(int64_t x)
{
  int64_t r = 1;
  for (int i = 0; i < N; i++)
    r *= x;

  return r;
}

/// Integer suare root
template <typename T>
inline T isqrt(T x)
{
  T r = static_cast<T>(std::sqrt(static_cast<double>(x)));
  // correct rounding error
  while (ipow<2>(r) > x)
    r--;
  while (ipow<2>(r + 1) <= x)
    r++;
  return r;
}

/// Integer nth root
template <int N, typename T>
inline T iroot(T x)
{
  T r = static_cast<T>(std::pow(static_cast<double>(x), 1.0 / N));
  // correct rounding error
  while (ipow<N>(r) > x)
    r--;
  while (ipow<N>(r + 1) <= x)
    r++;
  return r;
}

/// Generate a vector with Möbius function values.
/// This implementation is based on code by Rick Sladkey
/// posted here: http://mathoverflow.net/a/99545
///
inline std::vector<int32_t> make_moebius(int64_t max)
{
  std::vector<int32_t> mu(max + 1, 1);

  for (int32_t i = 2; i * i <= max; i++)
  {
    if (mu[i] == 1)
    {
      for (int32_t j = i; j <= max; j += i)
        mu[j] *= -i;
      for (int32_t j = i * i; j <= max; j += i * i)
        mu[j] = 0;
    }
  }
  for (int32_t i = 2; i <= max; i++)
  {
    if (mu[i] == i)
      mu[i] = 1;
    else if (mu[i] == -i)
      mu[i] = -1;
    else if (mu[i] < 0)
      mu[i] = 1;
    else if (mu[i] > 0)
      mu[i] = -1;
  }
  return mu;
}

/// Generate a vector with the least prime
/// factors of the integers <= max.
///
inline std::vector<int32_t> make_least_prime_factor(int64_t max)
{
  std::vector<int32_t> lpf(max + 1, 1);

  // phi(x / 1, c) contributes to the sum, thus
  // set lpf[1] = MAX in order to pass
  // if (lpf[1] > primes[c])
  if (lpf.size() > 1)
    lpf[1] = std::numeric_limits<int32_t>::max();

  for (int32_t i = 2; i * i <= max; i++)
    if (lpf[i] == 1)
      for (int32_t j = i * 2; j <= max; j += i)
        if (lpf[j] == 1)
          lpf[j] = i;

  for (int32_t i = 2; i <= max; i++)
    if (lpf[i] == 1)
      lpf[i] = i;

  return lpf;
}

/// Generate a vector with the prime counts below max
/// using the sieve of Eratosthenes.
///
inline std::vector<int32_t> make_pi(int64_t max)
{
  std::vector<char> is_prime(max + 1, 1);

  for (int64_t i = 2; i * i <= max; i++)
    if (is_prime[i])
      for (int64_t j = i * i; j <= max; j += i)
        is_prime[j] = 0;

  std::vector<int32_t> pi(max + 1, 0);
  int32_t pix = 0;

  for (int64_t x = 2; x <= max; x++)
  {
    pix += is_prime[x];
    pi[x] = pix;
  }

  return pi;
}

/// Generate vectors containing n values which satisfy:
/// is_square_free(n) && && !is_prime(n) && primes[i] < least_prime_factor[n].
///
inline std::vector<std::vector<int32_t> >
generate_square_free_candidates(int64_t c,
                                int64_t y,
                                std::vector<int32_t>& lpf,
                                std::vector<int32_t>& mu,
                                std::vector<int32_t>& pi,
                                std::vector<int32_t>& primes)
{
  int64_t sqrty = isqrt(y);
  std::vector<std::vector<int32_t> > square_free_candidates(pi[sqrty], std::vector<int32_t>(1, 0));

  for (int32_t n = primes[c + 1]; n <= y; n++)
    if (mu[n] != 0 && n != primes[pi[n]] && lpf[n] < sqrty)
      for (int32_t i = pi[lpf[n]] - 1; i > c; i--)
        square_free_candidates[i].push_back(n);

  return square_free_candidates;
}

#endif
<commit_msg>Fix segmentation fault<commit_after>///
/// @file  pmath.hpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <limits>

inline int64_t isquare(int64_t x)
{
  return x * x;
}

template <typename T1, typename T2, typename T3>
inline T2 in_between(T1 min, T2 x, T3 max)
{
  if (x < min)
    return static_cast<T2>(min);
  if (x > max)
    return static_cast<T2>(max);

  return x;
}

template <typename T>
inline T number_of_bits(T)
{
  return static_cast<T>(sizeof(T) * 8);
}

/// @brief  Check if an integer is a power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline bool is_power_of_2(T x)
{
  return (x != 0 && (x & (x - 1)) == 0);
}

/// @brief  Round up to the next power of 2.
/// @see    Book "Hacker's Delight".
///
template <typename T>
inline T next_power_of_2(T x)
{
  if (x == 0)
    return 1;

  x--;
  for (T i = 1; i < number_of_bits(x); i += i)
    x |= (x >> i);

  return ++x;
}

template <typename T>
inline int ilog(T x)
{
  return static_cast<int>(std::log(static_cast<double>(x)));
}

/// Raise to power
template <int N>
inline int64_t ipow(int64_t x)
{
  int64_t r = 1;
  for (int i = 0; i < N; i++)
    r *= x;

  return r;
}

/// Integer suare root
template <typename T>
inline T isqrt(T x)
{
  T r = static_cast<T>(std::sqrt(static_cast<double>(x)));
  // correct rounding error
  while (ipow<2>(r) > x)
    r--;
  while (ipow<2>(r + 1) <= x)
    r++;
  return r;
}

/// Integer nth root
template <int N, typename T>
inline T iroot(T x)
{
  T r = static_cast<T>(std::pow(static_cast<double>(x), 1.0 / N));
  // correct rounding error
  while (ipow<N>(r) > x)
    r--;
  while (ipow<N>(r + 1) <= x)
    r++;
  return r;
}

/// Generate a vector with Möbius function values.
/// This implementation is based on code by Rick Sladkey
/// posted here: http://mathoverflow.net/a/99545
///
inline std::vector<int32_t> make_moebius(int64_t max)
{
  std::vector<int32_t> mu(max + 1, 1);

  for (int32_t i = 2; i * i <= max; i++)
  {
    if (mu[i] == 1)
    {
      for (int32_t j = i; j <= max; j += i)
        mu[j] *= -i;
      for (int32_t j = i * i; j <= max; j += i * i)
        mu[j] = 0;
    }
  }
  for (int32_t i = 2; i <= max; i++)
  {
    if (mu[i] == i)
      mu[i] = 1;
    else if (mu[i] == -i)
      mu[i] = -1;
    else if (mu[i] < 0)
      mu[i] = 1;
    else if (mu[i] > 0)
      mu[i] = -1;
  }
  return mu;
}

/// Generate a vector with the least prime
/// factors of the integers <= max.
///
inline std::vector<int32_t> make_least_prime_factor(int64_t max)
{
  std::vector<int32_t> lpf(max + 1, 1);

  // phi(x / 1, c) contributes to the sum, thus
  // set lpf[1] = MAX in order to pass
  // if (lpf[1] > primes[c])
  if (lpf.size() > 1)
    lpf[1] = std::numeric_limits<int32_t>::max();

  for (int32_t i = 2; i * i <= max; i++)
    if (lpf[i] == 1)
      for (int32_t j = i * 2; j <= max; j += i)
        if (lpf[j] == 1)
          lpf[j] = i;

  for (int32_t i = 2; i <= max; i++)
    if (lpf[i] == 1)
      lpf[i] = i;

  return lpf;
}

/// Generate a vector with the prime counts below max
/// using the sieve of Eratosthenes.
///
inline std::vector<int32_t> make_pi(int64_t max)
{
  std::vector<char> is_prime(max + 1, 1);

  for (int64_t i = 2; i * i <= max; i++)
    if (is_prime[i])
      for (int64_t j = i * i; j <= max; j += i)
        is_prime[j] = 0;

  std::vector<int32_t> pi(max + 1, 0);
  int32_t pix = 0;

  for (int64_t x = 2; x <= max; x++)
  {
    pix += is_prime[x];
    pi[x] = pix;
  }

  return pi;
}

/// Generate vectors containing n values which satisfy:
/// is_square_free(n) && && !is_prime(n) && primes[i] < least_prime_factor[n].
///
inline std::vector<std::vector<int32_t> >
generate_square_free_candidates(int64_t c,
                                int64_t y,
                                std::vector<int32_t>& lpf,
                                std::vector<int32_t>& mu,
                                std::vector<int32_t>& pi,
                                std::vector<int32_t>& primes)
{
  int64_t sqrty = isqrt(y);
  int64_t start = primes[std::min<int64_t>(c + 1, primes.size() - 1)];
  std::vector<std::vector<int32_t> > square_free_candidates(pi[sqrty], std::vector<int32_t>(1, 0));

  for (int32_t n = start; n <= y; n++)
    if (mu[n] != 0 && n != primes[pi[n]] && lpf[n] < sqrty)
      for (int32_t i = pi[lpf[n]] - 1; i > c; i--)
        square_free_candidates[i].push_back(n);

  return square_free_candidates;
}

#endif
<|endoftext|>


<commit_before>//
// Copyright (c) 2011, Willow Garage, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Willow Garage, Inc. nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include <boost/python.hpp>

#include <ecto/tendril.hpp>

#include <boost/foreach.hpp>
#include <Python.h>

#include <ecto/serialization/tendril.hpp>

namespace bp = boost::python;

namespace ecto
{
namespace py
{

tendril_ptr tendril_ctr()
{
  return boost::shared_ptr<tendril>(new tendril(bp::object(),"A pythonic tendril."));
}

tendril_ptr tendril_ctr1(const bp::object & object)
{
  //allow the tendril to have no type...
#if BOOST_PYTHON_OBJECT_HAS_IS_NONE
  if(object.is_none()){
#else
  if(object.ptr() == Py_None){
#endif
    return boost::shared_ptr<tendril>(new tendril);
  }
  return boost::shared_ptr<tendril>(new tendril(object,"A pythonic tendril."));
}

// this is probably a terrible thing to do, but it is needed for pickle
// an alternative is to override __new__
tendril_ptr tendril_ctr2(std::string s, std::string useless)
{
  return boost::shared_ptr<tendril>(new tendril(registry::tendril::get(s)));
}

std::string tendril_type_name(tendril_ptr t)
{
  return t->type_name();
}

std::string tendril_doc(tendril_ptr t)
{
  return t->doc();
}

void tendril_set_doc(tendril_ptr t, const std::string& doc)
{
  return t->set_doc(doc);
}

bp::object tendril_get_val(tendril_ptr t)
{
  bp::object o;
  t >> o;
  return o;
}

void tendril_set_val(tendril_ptr t, bp::object val)
{
  t << val;
  t->dirty(true);
  t->user_supplied(true);
}
void tendril_copy_val(tendril_ptr t, tendril_ptr tv)
{
  t << *tv;
}
bool tendril_user_supplied(tendril_ptr t)
{
  return t->user_supplied();
}

bool tendril_has_default(tendril_ptr t)
{
  return t->has_default();
}

bool tendril_dirty(tendril_ptr t)
{
  return t->dirty();
}

bool tendril_required(tendril_ptr t)
{
  return t->required();
}

bp::object py_tendril_reg_list(){
  bp::list l;
  BOOST_FOREACH(const std::string& x, ecto::registry::tendril::type_names())
      l.append(bp::str(x));
  return l;
}
namespace io = boost::iostreams;

std::string py_tendril_save(const tendril& t)
{
  //todo allow python to pass in a buffer so copies don't need to be made.
  std::string buf;
  ecto::serialization::save(buf, t);
  return buf;
}

void py_tendril_load(tendril& t,const std::string& str){
  ecto::serialization::load(str, t);
}

void wrapConnection(){
  bp::class_<tendril,boost::shared_ptr<tendril> > Tendril_("Tendril",
      "The Tendril is the slendor winding organ of ecto.\n"
      "It is a type erasing holder with meta data that enable introspection.");
    Tendril_.def("__init__", bp::make_constructor(tendril_ctr));
    Tendril_.def("__init__", bp::make_constructor(tendril_ctr1));
    Tendril_.def("__init__", bp::make_constructor(tendril_ctr2));
    Tendril_.add_property("doc",tendril_doc,&tendril::set_doc, "A doc string that describes the purpose of this tendril.");
    Tendril_.add_property("type_name",tendril_type_name, "The type of the value held by the tendril." );
    Tendril_.add_property("val", tendril_get_val,tendril_set_val, "The value held by the tendril.\n"
        "It requires boost::python bindings to be accessible from python.\n"
        "If none are available it will be None.");
    Tendril_.add_property("user_supplied",tendril_user_supplied, "Has the value been set by the user?");
    Tendril_.add_property("has_default",tendril_has_default, "Does the tendril have an explicit default value?\n"
        "Remember that the implicit default is always the default constructed type.");
    Tendril_.add_property("required",tendril_required, "Is this tendril required to be connected?");
    Tendril_.add_property("dirty",tendril_dirty, "Has the tendril changed since the last time?");
    Tendril_.def("get",tendril_get_val, "Gets the python value of the object.\n"
    "May be None if python bindings for the type held do not have boost::python bindings available from the current scope."
    );
    Tendril_.def("set",tendril_set_val, "Assuming the value held by the tendril has boost::python bindings,\nthis will copy the value of the given python object into the value held by the tendril.");
    Tendril_.def("copy_value",tendril_copy_val, "Copy from one tendril to the other.");
    Tendril_.def("notify",&tendril::notify, "Force updates.");
    Tendril_.def("save",&py_tendril_save);
    Tendril_.def("load",&py_tendril_load);
    Tendril_.def("createT",&registry::tendril::get, "Create a tendril of the c++ type.", bp::return_value_policy<bp::return_by_value>());
    def("make_tendril",&registry::tendril::get, "Create a tendril of the c++ type.", bp::return_value_policy<bp::return_by_value>());
    Tendril_.staticmethod("createT");
    Tendril_.def("listT", &py_tendril_reg_list);
    Tendril_.staticmethod("listT");
    Tendril_.enable_pickling();

}
}
}

<commit_msg>fix compilation on old boost<commit_after>//
// Copyright (c) 2011, Willow Garage, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Willow Garage, Inc. nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include <boost/python.hpp>

#include <ecto/tendril.hpp>

#include <boost/foreach.hpp>
#include <Python.h>

#include <ecto/serialization/tendril.hpp>

namespace bp = boost::python;

namespace ecto
{
namespace py
{

tendril_ptr tendril_ctr()
{
  return boost::shared_ptr<tendril>(new tendril(bp::object(),"A pythonic tendril."));
}

tendril_ptr tendril_ctr1(const bp::object & object)
{
  //allow the tendril to have no type...
#ifdef BOOST_PYTHON_OBJECT_HAS_IS_NONE
  if(object.is_none()){
#else
  if(object.ptr() == Py_None){
#endif
    return boost::shared_ptr<tendril>(new tendril);
  }
  return boost::shared_ptr<tendril>(new tendril(object,"A pythonic tendril."));
}

// this is probably a terrible thing to do, but it is needed for pickle
// an alternative is to override __new__
tendril_ptr tendril_ctr2(std::string s, std::string useless)
{
  return boost::shared_ptr<tendril>(new tendril(registry::tendril::get(s)));
}

std::string tendril_type_name(tendril_ptr t)
{
  return t->type_name();
}

std::string tendril_doc(tendril_ptr t)
{
  return t->doc();
}

void tendril_set_doc(tendril_ptr t, const std::string& doc)
{
  return t->set_doc(doc);
}

bp::object tendril_get_val(tendril_ptr t)
{
  bp::object o;
  t >> o;
  return o;
}

void tendril_set_val(tendril_ptr t, bp::object val)
{
  t << val;
  t->dirty(true);
  t->user_supplied(true);
}
void tendril_copy_val(tendril_ptr t, tendril_ptr tv)
{
  t << *tv;
}
bool tendril_user_supplied(tendril_ptr t)
{
  return t->user_supplied();
}

bool tendril_has_default(tendril_ptr t)
{
  return t->has_default();
}

bool tendril_dirty(tendril_ptr t)
{
  return t->dirty();
}

bool tendril_required(tendril_ptr t)
{
  return t->required();
}

bp::object py_tendril_reg_list(){
  bp::list l;
  BOOST_FOREACH(const std::string& x, ecto::registry::tendril::type_names())
      l.append(bp::str(x));
  return l;
}
namespace io = boost::iostreams;

std::string py_tendril_save(const tendril& t)
{
  //todo allow python to pass in a buffer so copies don't need to be made.
  std::string buf;
  ecto::serialization::save(buf, t);
  return buf;
}

void py_tendril_load(tendril& t,const std::string& str){
  ecto::serialization::load(str, t);
}

void wrapConnection(){
  bp::class_<tendril,boost::shared_ptr<tendril> > Tendril_("Tendril",
      "The Tendril is the slendor winding organ of ecto.\n"
      "It is a type erasing holder with meta data that enable introspection.");
    Tendril_.def("__init__", bp::make_constructor(tendril_ctr));
    Tendril_.def("__init__", bp::make_constructor(tendril_ctr1));
    Tendril_.def("__init__", bp::make_constructor(tendril_ctr2));
    Tendril_.add_property("doc",tendril_doc,&tendril::set_doc, "A doc string that describes the purpose of this tendril.");
    Tendril_.add_property("type_name",tendril_type_name, "The type of the value held by the tendril." );
    Tendril_.add_property("val", tendril_get_val,tendril_set_val, "The value held by the tendril.\n"
        "It requires boost::python bindings to be accessible from python.\n"
        "If none are available it will be None.");
    Tendril_.add_property("user_supplied",tendril_user_supplied, "Has the value been set by the user?");
    Tendril_.add_property("has_default",tendril_has_default, "Does the tendril have an explicit default value?\n"
        "Remember that the implicit default is always the default constructed type.");
    Tendril_.add_property("required",tendril_required, "Is this tendril required to be connected?");
    Tendril_.add_property("dirty",tendril_dirty, "Has the tendril changed since the last time?");
    Tendril_.def("get",tendril_get_val, "Gets the python value of the object.\n"
    "May be None if python bindings for the type held do not have boost::python bindings available from the current scope."
    );
    Tendril_.def("set",tendril_set_val, "Assuming the value held by the tendril has boost::python bindings,\nthis will copy the value of the given python object into the value held by the tendril.");
    Tendril_.def("copy_value",tendril_copy_val, "Copy from one tendril to the other.");
    Tendril_.def("notify",&tendril::notify, "Force updates.");
    Tendril_.def("save",&py_tendril_save);
    Tendril_.def("load",&py_tendril_load);
    Tendril_.def("createT",&registry::tendril::get, "Create a tendril of the c++ type.", bp::return_value_policy<bp::return_by_value>());
    def("make_tendril",&registry::tendril::get, "Create a tendril of the c++ type.", bp::return_value_policy<bp::return_by_value>());
    Tendril_.staticmethod("createT");
    Tendril_.def("listT", &py_tendril_reg_list);
    Tendril_.staticmethod("listT");
    Tendril_.enable_pickling();

}
}
}

<|endoftext|>


<commit_before>#include <iostream>

using namespace std;

template <typename T>
class stack
{
public:
	stack();/*strong*/
	stack(const stack<T> &);
	size_t count() const; /*noexcept*/
	void print()const;
	void push(T const &); /*basic*/
	void swap(stack<T>&); /*noexcept*/
	void pop(); /*no safety*/
	T top(); /*strong*/
	bool empty() const; /*noexcept*/
	stack<T>& operator=(stack<T> &); /*basic*/
	~stack();/*noexcept*/
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() : count_(0), array_size_(0), array_{ nullptr }
{}

template<class T>
stack<T>::~stack()
{
	count_ = 0;
	array_size_ = 0;
	delete[] array_;
}

template <typename T>
stack<T>::stack(const stack<T>& copy)
{
	array_size_ = copy.array_size_;
	count_ = copy.count_;
	array_ = new T[count_];
	std::copy(copy.array_, copy.array_ + copy.count_, array_);
}

template<class T>
size_t stack<T>::count() const
{
	return count_;
}

template <typename T>
bool stack<T>::empty() const
{
	return (count_ == 0);
}

template<typename T>
void stack<T>::swap(stack& x)
{
	std::swap(x.array_size_, array_size_);
	std::swap(count_, x.count_);
	std::swap(x.array_, array_);
}

template <typename T>
T stack<T>::top()
{
	if (empty())
	{
		std::cout << "Stack is empty!";
	}
	return array_[count_ - 1];
}

template <typename T>
void stack<T>::push(T const &value)
{
	if (array_size_ == 0)
	{
		array_size_ = 1;
		array_ = new T[array_size_];
	}
	else if (array_size_ == count_)
	{
		array_size_ = array_size_ * 2;
		T *s1 = new T[array_size_];
		std::copy(array_, array_ + count_, s1);
		//for (int i = 0; i < count_; i++)
		//std::copy(int i = 0; i < count; i++)
		//	s1[i] = array_[i];
		delete[] array_;
		array_ = s1;
	}
	array_[count_] = value;
	count_++;
}

template <typename T>
void stack<T>::pop()
{
	if (count_ == 0)
		throw "Stack is empty" ;
	count_--;
}

template <typename T>
void stack<T>::print() const
{
	for (int i = 0; i < array_size_; i++)
		cout << array_[i];
}

template<typename T>
stack<T>& stack<T>::operator=(stack<T> & tmp)
{
	if (this != &tmp)
	{
		stack(tmp).swap(*this);
	}
	return *this;
}
<commit_msg>Update stack.hpp<commit_after>#include <iostream>

using namespace std;

template <typename T>
class stack
{
public:
	stack();/*noexept*/
	stack(const stack<T> &);/*no safety*/
	size_t count() const; /*noexcept*/
	void print()const;/*strong*/
	void push(T const &); /*no safety*/
	void swap(stack<T>&); /*noexcept*/
	void pop(); /*no safety*/
	T top(); /*strong*/
	bool empty() const; /*noexcept*/
	stack<T>& operator=(stack<T> &); /*basic*/
	~stack();/*noexcept*/
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() : count_(0), array_size_(0), array_{ nullptr }
{}

template<class T>
stack<T>::~stack()
{
	count_ = 0;
	array_size_ = 0;
	delete[] array_;
}

template <typename T>
stack<T>::stack(const stack<T>& copy)
{
	array_size_ = copy.array_size_;
	count_ = copy.count_;
	array_ = new T[count_];
	std::copy(copy.array_, copy.array_ + copy.count_, array_);
}

template<class T>
size_t stack<T>::count() const
{
	return count_;
}

template <typename T>
bool stack<T>::empty() const
{
	return (count_ == 0);
}

template<typename T>
void stack<T>::swap(stack& x)
{
	std::swap(x.array_size_, array_size_);
	std::swap(count_, x.count_);
	std::swap(x.array_, array_);
}

template <typename T>
T stack<T>::top()
{
	if (empty())
	{
		std::cout << "Stack is empty!";
	}
	return array_[count_ - 1];
}

template <typename T>
void stack<T>::push(T const &value)
{
	if (array_size_ == 0)
	{
		array_size_ = 1;
		array_ = new T[array_size_];
	}
	else if (array_size_ == count_)
	{
		array_size_ = array_size_ * 2;
		T *s1 = new T[array_size_];
		std::copy(array_, array_ + count_, s1);
		//for (int i = 0; i < count_; i++)
		//std::copy(int i = 0; i < count; i++)
		//	s1[i] = array_[i];
		delete[] array_;
		array_ = s1;
	}
	array_[count_] = value;
	count_++;
}

template <typename T>
void stack<T>::pop()
{
	if (count_ == 0)
		throw "Stack is empty" ;
	count_--;
}

template <typename T>
void stack<T>::print() const
{
	for (int i = 0; i < array_size_; i++)
		cout << array_[i];
}

template<typename T>
stack<T>& stack<T>::operator=(stack<T> & tmp)
{
	if (this != &tmp)
	{
		stack(tmp).swap(*this);
	}
	return *this;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <mutex>
#include <thread>
#include <memory>

using namespace std;

template <typename T>
class stack
{
public:
	stack();/*noexept*/
	stack(const stack<T> &);/*strong*/
	size_t count() const; /*noexcept*/
	void print()const;/*noexcept*/
	void push(T const &); /*strong*/
	void swap(stack<T>&); /*noexcept*/
	auto pop()->std::shared_ptr<T>; /*strong*/
	T top(); /*strong*/
	bool empty() const; /*noexcept*/
	stack<T>& operator=(stack<T> &); /*noexcept*/
	~stack();/*noexcept*/
private:
	T * array_;
	mutable std::mutex mutex_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() : count_(0), array_size_(0), array_{ nullptr }
{}

template<class T>
stack<T>::~stack()
{
	count_ = 0;
	array_size_ = 0;
	delete[] array_;
}

template <typename T>
stack<T>::stack(const stack<T>& copy)
{
	std::lock_guard<std::mutex> lock(mutex_);
	T *tmp = new T[copy.array_size_];
	count_ = copy.count_;
	array_size_ = copy.array_size_;
	array_ = tmp;
	if(array_ == nullptr){
		throw "error";
		delete[] array_;
	}
	std::copy(copy.array_, copy.array_ + count_, array_);
}

template<class T>
size_t stack<T>::count() const
{
	std::lock_guard<std::mutex> lock(mutex_);
	return count_;
}

template <typename T>
bool stack<T>::empty() const
{
	return (count_ == 0);
}

template<typename T>
void stack<T>::swap(stack& x)
{
	x.mutex_.lock();
	std::swap(x.array_size_, array_size_);
	std::swap(count_, x.count_);
	std::swap(x.array_, array_);
	x.mutex_.unlock();
}

template <typename T>
T stack<T>::top()
{
	if (empty())
	{
		throw "Stack is empty!";
	}
	return array_[count_ - 1];
}

template <typename T>
void stack<T>::push(T const &value)
{
	mutex_.lock();
	if (array_size_ == count_)
	{
		array_size_ *= 2;
		stack<T> temp(*this);
		swap(temp);
	}
	array_[count_] = value;
	++count_;
	mutex_.unlock();
}

template <typename T>
auto stack<T>::pop() -> std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (empty())
		throw "Stack is empty" ;
	count_--;
}

template <typename T>
void stack<T>::print() const
{
	for (int i = 0; i < array_size_; i++)
		cout << array_[i];
}

template<typename T>
stack<T>& stack<T>::operator=(stack<T> & other)
{
	std::lock_guard<std::mutex> lock(other.mutex_);
	if (this != &other)
	{
		stack<T> tmp(other);
		tmp.swap(*this);
	}
	return *this;
}
<commit_msg>Update stack.hpp<commit_after>#include <iostream>
#include <mutex>
#include <thread>
#include <memory>

using namespace std;

template <typename T>
class stack
{
public:
	stack();/*noexept*/
	stack(const stack<T> &);/*strong*/
	size_t count() const; /*noexcept*/
	void print()const;/*noexcept*/
	void push(T const &); /*strong*/
	void swap(stack<T>&); /*noexcept*/
	auto pop()->std::shared_ptr<T>; /*strong*/
	T top(); /*strong*/
	bool empty() const; /*noexcept*/
	stack<T>& operator=(stack<T> &); /*noexcept*/
	~stack();/*noexcept*/
private:
	T * array_;
	mutable std::mutex mutex_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() : count_(0), array_size_(0), array_{ nullptr }
{}

template<class T>
stack<T>::~stack()
{
	count_ = 0;
	array_size_ = 0;
	delete[] array_;
}

template <typename T>
stack<T>::stack(const stack<T>& copy)
{
	std::lock_guard<std::mutex> lock(mutex_);
	T *tmp = new T[copy.array_size_];
	count_ = copy.count_;
	array_size_ = copy.array_size_;
	array_ = tmp;
	if(array_ == nullptr){
		throw "error";
		delete[] array_;
	}
	std::copy(copy.array_, copy.array_ + count_, array_);
}

template<class T>
size_t stack<T>::count() const
{
	std::lock_guard<std::mutex> lock(mutex_);
	return count_;
}

template <typename T>
bool stack<T>::empty() const
{
	return (count_ == 0);
}

template<typename T>
void stack<T>::swap(stack& x)
{
	x.mutex_.lock();
	std::swap(x.array_size_, array_size_);
	std::swap(count_, x.count_);
	std::swap(x.array_, array_);
	x.mutex_.unlock();
}

template <typename T>
T stack<T>::top()
{
	if (empty())
	{
		throw "Stack is empty!";
	}
	return array_[count_ - 1];
}

template <typename T>
void stack<T>::push(T const &value)
{
	mutex_.lock();
	if (array_size_ == count_)
	{
		array_size_ *= 2;
		stack<T> temp(*this);
		swap(temp);
	}
	array_[count_] = value;
	++count_;
	mutex_.unlock();
}

template <typename T>
auto stack<T>::pop() -> std::shared_ptr<T>
{
	std::lock_guard<std::mutex> lock(mutex_);
	if (empty())
		throw "Stack is empty" ;
	count_--;
	auto top = std::make_shared<T>(*array_);
	return top;
}

template <typename T>
void stack<T>::print() const
{
	for (int i = 0; i < array_size_; i++)
		cout << array_[i];
}

template<typename T>
stack<T>& stack<T>::operator=(stack<T> & other)
{
	std::lock_guard<std::mutex> lock(other.mutex_);
	if (this != &other)
	{
		stack<T> tmp(other);
		tmp.swap(*this);
	}
	return *this;
}
<|endoftext|>


<commit_before>#include "transactionview.h"

#include "transactionfilterproxy.h"
#include "transactionrecord.h"
#include "walletmodel.h"
#include "addresstablemodel.h"
#include "transactiontablemodel.h"
#include "bitcoinunits.h"
#include "csvmodelwriter.h"
#include "transactiondescdialog.h"
#include "editaddressdialog.h"
#include "optionsmodel.h"
#include "guiutil.h"

#include <QScrollBar>
#include <QComboBox>
#include <QDoubleValidator>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QTableView>
#include <QHeaderView>
#include <QPushButton>
#include <QMessageBox>
#include <QPoint>
#include <QMenu>
#include <QApplication>
#include <QClipboard>
#include <QLabel>
#include <QDateTimeEdit>

TransactionView::TransactionView(QWidget *parent) :
    QWidget(parent), model(0), transactionProxyModel(0),
    transactionView(0)
{
    // Build filter row
    setContentsMargins(0,0,0,0);

    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(0,0,0,0);
#ifdef Q_OS_MAC
    hlayout->setSpacing(5);
    hlayout->addSpacing(26);
#else
    hlayout->setSpacing(0);
    hlayout->addSpacing(23);
#endif

    dateWidget = new QComboBox(this);
#ifdef Q_OS_MAC
    dateWidget->setFixedWidth(121);
#else
    dateWidget->setFixedWidth(120);
#endif
    dateWidget->addItem(tr("All"), All);
    dateWidget->addItem(tr("Today"), Today);
    dateWidget->addItem(tr("This week"), ThisWeek);
    dateWidget->addItem(tr("This month"), ThisMonth);
    dateWidget->addItem(tr("Last month"), LastMonth);
    dateWidget->addItem(tr("This year"), ThisYear);
    dateWidget->addItem(tr("Range..."), Range);
    hlayout->addWidget(dateWidget);

    typeWidget = new QComboBox(this);
#ifdef Q_OS_MAC
    typeWidget->setFixedWidth(121);
#else
    typeWidget->setFixedWidth(120);
#endif

    typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
    typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
                                        TransactionFilterProxy::TYPE(TransactionRecord::RecvFromOther));
    typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
                                  TransactionFilterProxy::TYPE(TransactionRecord::SendToOther));
    typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf));
    typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::StakeMint));
    typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
    typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));

    hlayout->addWidget(typeWidget);

    addressWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    addressWidget->setPlaceholderText(tr("Enter address or label to search"));
#endif
    hlayout->addWidget(addressWidget);

    amountWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    amountWidget->setPlaceholderText(tr("Min amount"));
#endif
#ifdef Q_OS_MAC
    amountWidget->setFixedWidth(97);
#else
    amountWidget->setFixedWidth(100);
#endif
    amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
    hlayout->addWidget(amountWidget);

    QVBoxLayout *vlayout = new QVBoxLayout(this);
    vlayout->setContentsMargins(0,0,0,0);
    vlayout->setSpacing(0);

    QTableView *view = new QTableView(this);
    vlayout->addLayout(hlayout);
    vlayout->addWidget(createDateRangeWidget());
    vlayout->addWidget(view);
    vlayout->setSpacing(0);
    int width = view->verticalScrollBar()->sizeHint().width();
    // Cover scroll bar width with spacing
#ifdef Q_OS_MAC
    hlayout->addSpacing(width+2);
#else
    hlayout->addSpacing(width);
#endif
    // Always show scroll bar
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    view->setTabKeyNavigation(false);
    view->setContextMenuPolicy(Qt::CustomContextMenu);

    transactionView = view;

    // Actions
    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy label"), this);
    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
    QAction *editLabelAction = new QAction(tr("Edit label"), this);
    QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);

    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(copyAmountAction);
    contextMenu->addAction(editLabelAction);
    contextMenu->addAction(showDetailsAction);

    // Connect actions
    connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
    connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
    connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
    connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString)));

    connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
    connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
    connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
    connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
}

void TransactionView::setModel(WalletModel *model)
{
    this->model = model;
    if(model)
    {
        transactionProxyModel = new TransactionFilterProxy(this);
        transactionProxyModel->setSourceModel(model->getTransactionTableModel());
        transactionProxyModel->setDynamicSortFilter(true);
        transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
        transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

        transactionProxyModel->setSortRole(Qt::EditRole);

        transactionView->setModel(transactionProxyModel);
        transactionView->setAlternatingRowColors(true);
        transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
        transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        transactionView->setSortingEnabled(true);
        transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
        transactionView->verticalHeader()->hide();

        transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Status, 23);
        transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Date, 120);
        transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Type, 120);
#if QT_VERSION < 0x050000
        transactionView->horizontalHeader()->setResizeMode(TransactionTableModel::ToAddress, QHeaderView::ResizeToContents);
#else
        transactionView->horizontalHeader()->setSectionResizeMode(TransactionTableModel::ToAddress, QHeaderView::ResizeToContents);
#endif
        transactionView->horizontalHeader()->resizeSection( TransactionTableModel::Amount, 100);
    }
}

void TransactionView::chooseDate(int idx)
{
    if(!transactionProxyModel)
        return;
    QDate current = QDate::currentDate();
    dateRangeWidget->setVisible(false);
    switch(dateWidget->itemData(idx).toInt())
    {
    case All:
        transactionProxyModel->setDateRange(
                TransactionFilterProxy::MIN_DATE,
                TransactionFilterProxy::MAX_DATE);
        break;
    case Today:
        transactionProxyModel->setDateRange(
                QDateTime(current),
                TransactionFilterProxy::MAX_DATE);
        break;
    case ThisWeek: {
        // Find last Monday
        QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
        transactionProxyModel->setDateRange(
                QDateTime(startOfWeek),
                TransactionFilterProxy::MAX_DATE);

        } break;
    case ThisMonth:
        transactionProxyModel->setDateRange(
                QDateTime(QDate(current.year(), current.month(), 1)),
                TransactionFilterProxy::MAX_DATE);
        break;
    case LastMonth:
        transactionProxyModel->setDateRange(
                QDateTime(QDate(current.year(), current.month()-1, 1)),
                QDateTime(QDate(current.year(), current.month(), 1)));
        break;
    case ThisYear:
        transactionProxyModel->setDateRange(
                QDateTime(QDate(current.year(), 1, 1)),
                TransactionFilterProxy::MAX_DATE);
        break;
    case Range:
        dateRangeWidget->setVisible(true);
        dateRangeChanged();
        break;
    }
}

void TransactionView::chooseType(int idx)
{
    if(!transactionProxyModel)
        return;
    transactionProxyModel->setTypeFilter(
        typeWidget->itemData(idx).toInt());
}

void TransactionView::changedPrefix(const QString &prefix)
{
    if(!transactionProxyModel)
        return;
    transactionProxyModel->setAddressPrefix(prefix);
}

void TransactionView::changedAmount(const QString &amount)
{
    if(!transactionProxyModel)
        return;
    qint64 amount_parsed = 0;
    if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed))
    {
        transactionProxyModel->setMinAmount(amount_parsed);
    }
    else
    {
        transactionProxyModel->setMinAmount(0);
    }
}

void TransactionView::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Transaction Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(transactionProxyModel);
    writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
    writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
    writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
    writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole);
    writer.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole);
    writer.addColumn(tr("Amount"), 0, TransactionTableModel::FormattedAmountRole);
    writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void TransactionView::contextualMenu(const QPoint &point)
{
    QModelIndex index = transactionView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void TransactionView::copyAddress()
{
    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole);
}

void TransactionView::copyLabel()
{
    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::LabelRole);
}

void TransactionView::copyAmount()
{
    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::FormattedAmountRole);
}

void TransactionView::editLabel()
{
    if(!transactionView->selectionModel() ||!model)
        return;
    QModelIndexList selection = transactionView->selectionModel()->selectedRows();
    if(!selection.isEmpty())
    {
        AddressTableModel *addressBook = model->getAddressTableModel();
        if(!addressBook)
            return;
        QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
        if(address.isEmpty())
        {
            // If this transaction has no associated address, exit
            return;
        }
        // Is address in address book? Address book can miss address when a transaction is
        // sent from outside the UI.
        int idx = addressBook->lookupAddress(address);
        if(idx != -1)
        {
            // Edit sending / receiving address
            QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex());
            // Determine type of address, launch appropriate editor dialog type
            QString type = modelIdx.data(AddressTableModel::TypeRole).toString();

            EditAddressDialog dlg(type==AddressTableModel::Receive
                                         ? EditAddressDialog::EditReceivingAddress
                                         : EditAddressDialog::EditSendingAddress,
                                  this);
            dlg.setModel(addressBook);
            dlg.loadRow(idx);
            dlg.exec();
        }
        else
        {
            // Add sending address
            EditAddressDialog dlg(EditAddressDialog::NewSendingAddress,
                                  this);
            dlg.setModel(addressBook);
            dlg.setAddress(address);
            dlg.exec();
        }
    }
}

void TransactionView::showDetails()
{
    if(!transactionView->selectionModel())
        return;
    QModelIndexList selection = transactionView->selectionModel()->selectedRows();
    if(!selection.isEmpty())
    {
        TransactionDescDialog dlg(selection.at(0));
        dlg.exec();
    }
}

QWidget *TransactionView::createDateRangeWidget()
{
    dateRangeWidget = new QFrame();
    dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
    dateRangeWidget->setContentsMargins(1,1,1,1);
    QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
    layout->setContentsMargins(0,0,0,0);
    layout->addSpacing(23);
    layout->addWidget(new QLabel(tr("Range:")));

    dateFrom = new QDateTimeEdit(this);
    dateFrom->setDisplayFormat("dd/MM/yy");
    dateFrom->setCalendarPopup(true);
    dateFrom->setMinimumWidth(100);
    dateFrom->setDate(QDate::currentDate().addDays(-7));
    layout->addWidget(dateFrom);
    layout->addWidget(new QLabel(tr("to")));

    dateTo = new QDateTimeEdit(this);
    dateTo->setDisplayFormat("dd/MM/yy");
    dateTo->setCalendarPopup(true);
    dateTo->setMinimumWidth(100);
    dateTo->setDate(QDate::currentDate());
    layout->addWidget(dateTo);
    layout->addStretch();

    // Hide by default
    dateRangeWidget->setVisible(false);

    // Notify on change
    connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
    connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));

    return dateRangeWidget;
}

void TransactionView::dateRangeChanged()
{
    if(!transactionProxyModel)
        return;
    transactionProxyModel->setDateRange(
            QDateTime(dateFrom->date()),
            QDateTime(dateTo->date()).addDays(1));
}

void TransactionView::focusTransaction(const QModelIndex &idx)
{
    if(!transactionProxyModel)
        return;
    QModelIndex targetIdx = transactionProxyModel->mapFromSource(idx);
    transactionView->scrollTo(targetIdx);
    transactionView->setCurrentIndex(targetIdx);
    transactionView->setFocus();
}
<commit_msg>FIXED: display problem in transaction list view<commit_after>#include "transactionview.h"

#include "transactionfilterproxy.h"
#include "transactionrecord.h"
#include "walletmodel.h"
#include "addresstablemodel.h"
#include "transactiontablemodel.h"
#include "bitcoinunits.h"
#include "csvmodelwriter.h"
#include "transactiondescdialog.h"
#include "editaddressdialog.h"
#include "optionsmodel.h"
#include "guiutil.h"

#include <QScrollBar>
#include <QComboBox>
#include <QDoubleValidator>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QTableView>
#include <QHeaderView>
#include <QPushButton>
#include <QMessageBox>
#include <QPoint>
#include <QMenu>
#include <QApplication>
#include <QClipboard>
#include <QLabel>
#include <QDateTimeEdit>

TransactionView::TransactionView(QWidget *parent) :
    QWidget(parent), model(0), transactionProxyModel(0),
    transactionView(0)
{
    // Build filter row
    setContentsMargins(0,0,0,0);

    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(0,0,0,0);
#ifdef Q_OS_MAC
    hlayout->setSpacing(5);
    hlayout->addSpacing(26);
#else
    hlayout->setSpacing(0);
    hlayout->addSpacing(23);
#endif

    dateWidget = new QComboBox(this);
#ifdef Q_OS_MAC
    dateWidget->setFixedWidth(121);
#else
    dateWidget->setFixedWidth(120);
#endif
    dateWidget->addItem(tr("All"), All);
    dateWidget->addItem(tr("Today"), Today);
    dateWidget->addItem(tr("This week"), ThisWeek);
    dateWidget->addItem(tr("This month"), ThisMonth);
    dateWidget->addItem(tr("Last month"), LastMonth);
    dateWidget->addItem(tr("This year"), ThisYear);
    dateWidget->addItem(tr("Range..."), Range);
    hlayout->addWidget(dateWidget);

    typeWidget = new QComboBox(this);
#ifdef Q_OS_MAC
    typeWidget->setFixedWidth(121);
#else
    typeWidget->setFixedWidth(120);
#endif

    typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
    typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
                                        TransactionFilterProxy::TYPE(TransactionRecord::RecvFromOther));
    typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
                                  TransactionFilterProxy::TYPE(TransactionRecord::SendToOther));
    typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf));
    typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::StakeMint));
    typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
    typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));

    hlayout->addWidget(typeWidget);

    addressWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    addressWidget->setPlaceholderText(tr("Enter address or label to search"));
#endif
    hlayout->addWidget(addressWidget);

    amountWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    amountWidget->setPlaceholderText(tr("Min amount"));
#endif
#ifdef Q_OS_MAC
    amountWidget->setFixedWidth(97);
#else
    amountWidget->setFixedWidth(100);
#endif
    amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
    hlayout->addWidget(amountWidget);

    QVBoxLayout *vlayout = new QVBoxLayout(this);
    vlayout->setContentsMargins(0,0,0,0);
    vlayout->setSpacing(0);

    QTableView *view = new QTableView(this);
    vlayout->addLayout(hlayout);
    vlayout->addWidget(createDateRangeWidget());
    vlayout->addWidget(view);
    vlayout->setSpacing(0);
    int width = view->verticalScrollBar()->sizeHint().width();
    // Cover scroll bar width with spacing
#ifdef Q_OS_MAC
    hlayout->addSpacing(width+2);
#else
    hlayout->addSpacing(width);
#endif
    // Always show scroll bar
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    view->setTabKeyNavigation(false);
    view->setContextMenuPolicy(Qt::CustomContextMenu);

    transactionView = view;

    // Actions
    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
    QAction *copyLabelAction = new QAction(tr("Copy label"), this);
    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
    QAction *editLabelAction = new QAction(tr("Edit label"), this);
    QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);

    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(copyAmountAction);
    contextMenu->addAction(editLabelAction);
    contextMenu->addAction(showDetailsAction);

    // Connect actions
    connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
    connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
    connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
    connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString)));

    connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
    connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
    connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
    connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
}

void TransactionView::setModel(WalletModel *model)
{
    this->model = model;
    if(model)
    {
        transactionProxyModel = new TransactionFilterProxy(this);
        transactionProxyModel->setSourceModel(model->getTransactionTableModel());
        transactionProxyModel->setDynamicSortFilter(true);
        transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
        transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

        transactionProxyModel->setSortRole(Qt::EditRole);

        transactionView->setModel(transactionProxyModel);
        transactionView->setAlternatingRowColors(true);
        transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
        transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        transactionView->setSortingEnabled(true);
        transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
        transactionView->verticalHeader()->hide();

        transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Status, 23);
        transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Date, 120);
        transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Type, 120);
#if QT_VERSION < 0x050000
        transactionView->horizontalHeader()->setResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
#else
        transactionView->horizontalHeader()->setSectionResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
#endif
        transactionView->horizontalHeader()->resizeSection( TransactionTableModel::Amount, 100);
    }
}

void TransactionView::chooseDate(int idx)
{
    if(!transactionProxyModel)
        return;
    QDate current = QDate::currentDate();
    dateRangeWidget->setVisible(false);
    switch(dateWidget->itemData(idx).toInt())
    {
    case All:
        transactionProxyModel->setDateRange(
                TransactionFilterProxy::MIN_DATE,
                TransactionFilterProxy::MAX_DATE);
        break;
    case Today:
        transactionProxyModel->setDateRange(
                QDateTime(current),
                TransactionFilterProxy::MAX_DATE);
        break;
    case ThisWeek: {
        // Find last Monday
        QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
        transactionProxyModel->setDateRange(
                QDateTime(startOfWeek),
                TransactionFilterProxy::MAX_DATE);

        } break;
    case ThisMonth:
        transactionProxyModel->setDateRange(
                QDateTime(QDate(current.year(), current.month(), 1)),
                TransactionFilterProxy::MAX_DATE);
        break;
    case LastMonth:
        transactionProxyModel->setDateRange(
                QDateTime(QDate(current.year(), current.month()-1, 1)),
                QDateTime(QDate(current.year(), current.month(), 1)));
        break;
    case ThisYear:
        transactionProxyModel->setDateRange(
                QDateTime(QDate(current.year(), 1, 1)),
                TransactionFilterProxy::MAX_DATE);
        break;
    case Range:
        dateRangeWidget->setVisible(true);
        dateRangeChanged();
        break;
    }
}

void TransactionView::chooseType(int idx)
{
    if(!transactionProxyModel)
        return;
    transactionProxyModel->setTypeFilter(
        typeWidget->itemData(idx).toInt());
}

void TransactionView::changedPrefix(const QString &prefix)
{
    if(!transactionProxyModel)
        return;
    transactionProxyModel->setAddressPrefix(prefix);
}

void TransactionView::changedAmount(const QString &amount)
{
    if(!transactionProxyModel)
        return;
    qint64 amount_parsed = 0;
    if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed))
    {
        transactionProxyModel->setMinAmount(amount_parsed);
    }
    else
    {
        transactionProxyModel->setMinAmount(0);
    }
}

void TransactionView::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Transaction Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(transactionProxyModel);
    writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
    writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
    writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
    writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole);
    writer.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole);
    writer.addColumn(tr("Amount"), 0, TransactionTableModel::FormattedAmountRole);
    writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void TransactionView::contextualMenu(const QPoint &point)
{
    QModelIndex index = transactionView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void TransactionView::copyAddress()
{
    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole);
}

void TransactionView::copyLabel()
{
    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::LabelRole);
}

void TransactionView::copyAmount()
{
    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::FormattedAmountRole);
}

void TransactionView::editLabel()
{
    if(!transactionView->selectionModel() ||!model)
        return;
    QModelIndexList selection = transactionView->selectionModel()->selectedRows();
    if(!selection.isEmpty())
    {
        AddressTableModel *addressBook = model->getAddressTableModel();
        if(!addressBook)
            return;
        QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
        if(address.isEmpty())
        {
            // If this transaction has no associated address, exit
            return;
        }
        // Is address in address book? Address book can miss address when a transaction is
        // sent from outside the UI.
        int idx = addressBook->lookupAddress(address);
        if(idx != -1)
        {
            // Edit sending / receiving address
            QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex());
            // Determine type of address, launch appropriate editor dialog type
            QString type = modelIdx.data(AddressTableModel::TypeRole).toString();

            EditAddressDialog dlg(type==AddressTableModel::Receive
                                         ? EditAddressDialog::EditReceivingAddress
                                         : EditAddressDialog::EditSendingAddress,
                                  this);
            dlg.setModel(addressBook);
            dlg.loadRow(idx);
            dlg.exec();
        }
        else
        {
            // Add sending address
            EditAddressDialog dlg(EditAddressDialog::NewSendingAddress,
                                  this);
            dlg.setModel(addressBook);
            dlg.setAddress(address);
            dlg.exec();
        }
    }
}

void TransactionView::showDetails()
{
    if(!transactionView->selectionModel())
        return;
    QModelIndexList selection = transactionView->selectionModel()->selectedRows();
    if(!selection.isEmpty())
    {
        TransactionDescDialog dlg(selection.at(0));
        dlg.exec();
    }
}

QWidget *TransactionView::createDateRangeWidget()
{
    dateRangeWidget = new QFrame();
    dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
    dateRangeWidget->setContentsMargins(1,1,1,1);
    QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
    layout->setContentsMargins(0,0,0,0);
    layout->addSpacing(23);
    layout->addWidget(new QLabel(tr("Range:")));

    dateFrom = new QDateTimeEdit(this);
    dateFrom->setDisplayFormat("dd/MM/yy");
    dateFrom->setCalendarPopup(true);
    dateFrom->setMinimumWidth(100);
    dateFrom->setDate(QDate::currentDate().addDays(-7));
    layout->addWidget(dateFrom);
    layout->addWidget(new QLabel(tr("to")));

    dateTo = new QDateTimeEdit(this);
    dateTo->setDisplayFormat("dd/MM/yy");
    dateTo->setCalendarPopup(true);
    dateTo->setMinimumWidth(100);
    dateTo->setDate(QDate::currentDate());
    layout->addWidget(dateTo);
    layout->addStretch();

    // Hide by default
    dateRangeWidget->setVisible(false);

    // Notify on change
    connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
    connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));

    return dateRangeWidget;
}

void TransactionView::dateRangeChanged()
{
    if(!transactionProxyModel)
        return;
    transactionProxyModel->setDateRange(
            QDateTime(dateFrom->date()),
            QDateTime(dateTo->date()).addDays(1));
}

void TransactionView::focusTransaction(const QModelIndex &idx)
{
    if(!transactionProxyModel)
        return;
    QModelIndex targetIdx = transactionProxyModel->mapFromSource(idx);
    transactionView->scrollTo(targetIdx);
    transactionView->setCurrentIndex(targetIdx);
    transactionView->setFocus();
}
<|endoftext|>


<commit_before>#include "rdb_protocol/parser.hpp"

namespace rdb_protocol {

query_http_app_t::query_http_app_t(namespace_interface_t<rdb_protocol_t> * _namespace_if)
    : namespace_if(_namespace_if)
{ }

http_res_t query_http_app_t::handle(const http_req_t &req) {
    try {
        switch (req.method) {
        case GET:
            {
                rdb_protocol_t::read_t read;

                http_req_t::resource_t::iterator it = req.resource.begin();
                rassert(it != req.resource.end());

                store_key_t key(*it);
                read.read = rdb_protocol_t::point_read_t(key);
                cond_t cond;
                rdb_protocol_t::read_response_t read_res = namespace_if->read(read, order_source.check_in("dummy parser"), &cond);

                http_res_t res;

                rdb_protocol_t::point_read_response_t response = boost::get<rdb_protocol_t::point_read_response_t>(read_res.response);
                if (response.data) {
                    boost::scoped_ptr<char> json(cJSON_Print(response.data.get()->get()));
                    res.code = 200;
                    res.set_body("application/json", json.get());
                } else {
                    res.code = 404;
                }
                return res;
            }
            break;
        case PUT:
        case POST:
            {
                rdb_protocol_t::write_t write;

                rassert(req.resource.begin() == req.resource.end());

                cJSON *doc = cJSON_Parse(req.body.c_str());

                if (doc == NULL) {
                    return http_res_t(400);
                }

                cJSON *id = cJSON_GetObjectItem(doc, "id");

                if (id == NULL || id->type != cJSON_String) {
                    cJSON_Delete(doc);
                    return http_res_t(400);
                }

                store_key_t key(id->valuestring);
                write.write = rdb_protocol_t::point_write_t(key, boost::make_shared<scoped_cJSON_t>(doc));

                cond_t cond;
                rdb_protocol_t::write_response_t write_res = namespace_if->write(write, order_source.check_in("dummy parser"), &cond);

                return http_res_t(204);
            }
            break;
        default:
            return http_res_t(400);
        }
        crash("Unreachable\n");
    } catch(cannot_perform_query_exc_t e) {
        http_res_t res;
        res.set_body("text/plain", e.what());
        return http_res_t(500);
    }
}

} //namespace mock
<commit_msg>Made master build under gcc warnings.<commit_after>#include "rdb_protocol/parser.hpp"

namespace rdb_protocol {

query_http_app_t::query_http_app_t(namespace_interface_t<rdb_protocol_t> * _namespace_if)
    : namespace_if(_namespace_if)
{ }

http_res_t query_http_app_t::handle(const http_req_t &req) {
    try {
        switch (req.method) {
        case GET:
            {
                rdb_protocol_t::read_t read;

                http_req_t::resource_t::iterator it = req.resource.begin();
                rassert(it != req.resource.end());

                store_key_t key(*it);
                read.read = rdb_protocol_t::point_read_t(key);
                cond_t cond;
                rdb_protocol_t::read_response_t read_res = namespace_if->read(read, order_source.check_in("dummy parser"), &cond);

                http_res_t res;

                rdb_protocol_t::point_read_response_t response = boost::get<rdb_protocol_t::point_read_response_t>(read_res.response);
                if (response.data) {
                    boost::scoped_ptr<char> json(cJSON_Print(response.data.get()->get()));
                    res.code = 200;
                    res.set_body("application/json", json.get());
                } else {
                    res.code = 404;
                }
                return res;
            }
            break;
        case PUT:
        case POST:
            {
                rdb_protocol_t::write_t write;

                rassert(req.resource.begin() == req.resource.end());

                cJSON *doc = cJSON_Parse(req.body.c_str());

                if (doc == NULL) {
                    return http_res_t(400);
                }

                cJSON *id = cJSON_GetObjectItem(doc, "id");

                if (id == NULL || id->type != cJSON_String) {
                    cJSON_Delete(doc);
                    return http_res_t(400);
                }

                store_key_t key(id->valuestring);
                write.write = rdb_protocol_t::point_write_t(key, boost::make_shared<scoped_cJSON_t>(doc));

                cond_t cond;
                rdb_protocol_t::write_response_t write_res = namespace_if->write(write, order_source.check_in("dummy parser"), &cond);

                return http_res_t(204);
            }
            break;

        case HEAD:
        case DELETE:
        case TRACE:
        case OPTIONS:
        case CONNECT:
        case PATCH:
        default:
            return http_res_t(400);
        }
        crash("Unreachable\n");
    } catch(cannot_perform_query_exc_t e) {
        http_res_t res;
        res.set_body("text/plain", e.what());
        return http_res_t(500);
    }
}

} //namespace mock
<|endoftext|>