diff --git a/sprout/compost.hpp b/sprout/compost.hpp new file mode 100644 index 00000000..684da66c --- /dev/null +++ b/sprout/compost.hpp @@ -0,0 +1,10 @@ +#ifndef SPROUT_COMPOST_HPP +#define SPROUT_COMPOST_HPP + +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_COMPOST_HPP diff --git a/sprout/compost/effects.hpp b/sprout/compost/effects.hpp new file mode 100644 index 00000000..ddb451f8 --- /dev/null +++ b/sprout/compost/effects.hpp @@ -0,0 +1,10 @@ +#ifndef SPROUT_COMPOST_EFFECTS_HPP +#define SPROUT_COMPOST_EFFECTS_HPP + +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_COMPOST_EFFECTS_HPP diff --git a/sprout/compost/effects/change_volume.hpp b/sprout/compost/effects/change_volume.hpp new file mode 100644 index 00000000..d13863dd --- /dev/null +++ b/sprout/compost/effects/change_volume.hpp @@ -0,0 +1,71 @@ +#ifndef SPROUT_COMPOST_EFFECTS_CHANGE_VOLUME_HPP +#define SPROUT_COMPOST_EFFECTS_CHANGE_VOLUME_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace compost { + namespace effects { + // + // change_volume_holder + // + template + class change_volume_holder { + public: + typedef T value_type; + private: + value_type value_; + public: + change_volume_holder() = default; + change_volume_holder(change_volume_holder const&) = default; + explicit SPROUT_CONSTEXPR change_volume_holder(value_type const& value) + : value_(value) + {} + SPROUT_CONSTEXPR value_type const& value() const { + return value_; + } + }; + + // + // changed_volume_forwarder + // + class changed_volume_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::compost::effects::change_volume_holder + operator()(T const& value) { + return sprout::compost::effects::change_volume_holder(value); + } + }; + + // + // changed_volume + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::effects::changed_volume_forwarder changed_volume{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::effects::change_volume_holder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::adaptors::transformed(sprout::bind2nd(sprout::multiplies<>(), rhs.value())) + ) + { + return sprout::forward(lhs) + | sprout::adaptors::transformed(sprout::bind2nd(sprout::multiplies<>(), rhs.value())) + ; + } + } // namespace effects + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_EFFECTS_CHANGE_VOLUME_HPP diff --git a/sprout/compost/effects/clip.hpp b/sprout/compost/effects/clip.hpp new file mode 100644 index 00000000..37e6b38f --- /dev/null +++ b/sprout/compost/effects/clip.hpp @@ -0,0 +1,85 @@ +#ifndef SPROUT_COMPOST_EFFECTS_CLIP_HPP +#define SPROUT_COMPOST_EFFECTS_CLIP_HPP + +#include +#include +#include + +namespace sprout { + namespace compost { + namespace effects { + // + // clip_holder + // + template + class clip_holder { + public: + typedef T value_type; + private: + value_type low_; + value_type up_; + public: + clip_holder() = default; + clip_holder(clip_holder const&) = default; + explicit SPROUT_CONSTEXPR clip_holder(value_type const& low = -1, value_type const& up = 1) + : low_(low), up_(up) + {} + SPROUT_CONSTEXPR value_type const& lower() const { + return low_; + } + SPROUT_CONSTEXPR value_type const& upper() const { + return up_; + } + }; + + // + // clipped_forwarder + // + class clipped_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::compost::effects::clip_holder + operator()(T const& low = -1, T const& up = 1) { + return sprout::compost::effects::clip_holder(low, up); + } + }; + + // + // clipped + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::effects::clipped_forwarder clipped{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::effects::clip_holder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::adaptors::clamped(rhs.lower(), rhs.upper()) + ) + { + return sprout::forward(lhs) + | sprout::adaptors::clamped(rhs.lower(), rhs.upper()) + ; + } + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::effects::clipped_forwarder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::adaptors::clamped(-1., 1.) + ) + { + return sprout::forward(lhs) + | sprout::adaptors::clamped(-1., 1.) + ; + } + } // namespace effects + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_EFFECTS_CLIP_HPP diff --git a/sprout/compost/effects/distort.hpp b/sprout/compost/effects/distort.hpp new file mode 100644 index 00000000..f6977655 --- /dev/null +++ b/sprout/compost/effects/distort.hpp @@ -0,0 +1,78 @@ +#ifndef SPROUT_COMPOST_EFFECTS_DISTORT_HPP +#define SPROUT_COMPOST_EFFECTS_DISTORT_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace compost { + namespace effects { + // + // distort_holder + // + template + class distort_holder { + public: + typedef T value_type; + private: + value_type gain_; + value_type level_; + public: + distort_holder() = default; + distort_holder(distort_holder const&) = default; + SPROUT_CONSTEXPR distort_holder(value_type const& gain, value_type const& level) + : gain_(gain) , level_(level) + {} + SPROUT_CONSTEXPR value_type const& gain() const { + return gain_; + } + SPROUT_CONSTEXPR value_type const& level() const { + return level_; + } + }; + + // + // distorted_forwarder + // + class distorted_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::compost::effects::distort_holder + operator()(T const& gain, T const& level) { + return sprout::compost::effects::distort_holder(gain, level); + } + }; + + // + // distorted + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::effects::distorted_forwarder distorted{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::effects::distort_holder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::compost::effects::changed_volume(rhs.gain()) + | sprout::compost::effects::clipped() + | sprout::compost::effects::changed_volume(rhs.level()) + ) + { + return sprout::forward(lhs) + | sprout::compost::effects::changed_volume(rhs.gain()) + | sprout::compost::effects::clipped() + | sprout::compost::effects::changed_volume(rhs.level()) + ; + } + } // namespace effects + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_EFFECTS_DISTORT_HPP diff --git a/sprout/compost/effects/synthesize.hpp b/sprout/compost/effects/synthesize.hpp new file mode 100644 index 00000000..27e748ef --- /dev/null +++ b/sprout/compost/effects/synthesize.hpp @@ -0,0 +1,77 @@ +#ifndef SPROUT_COMPOST_EFFECTS_SYNTHESIZED_HPP +#define SPROUT_COMPOST_EFFECTS_SYNTHESIZED_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace compost { + namespace effects { + // + // synthesize_holder + // + template + class synthesize_holder { + public: + typedef RRange range2_type; + private: + sprout::value_holder range_; + public: + synthesize_holder() = default; + synthesize_holder(synthesize_holder const&) = default; + explicit SPROUT_CONSTEXPR synthesize_holder(range2_type& range) + : range_(range) + {} + SPROUT_CONSTEXPR range2_type& range() const { + return range_; + } + }; + + // + // synthesized_forwarder + // + class synthesized_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::compost::effects::synthesize_holder< + typename std::remove_reference::type>::type + > + operator()(RRange&& range) { + return sprout::compost::effects::synthesize_holder< + typename std::remove_reference::type>::type + >( + sprout::lvalue_forward(range) + ); + } + }; + + // + // synthesized + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::effects::synthesized_forwarder synthesized{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::effects::synthesize_holder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::adaptors::transformed(rhs.range(), sprout::plus<>()) + ) + { + return sprout::forward(lhs) + | sprout::adaptors::transformed(rhs.range(), sprout::plus<>()) + ; + } + } // namespace effects + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_EFFECTS_SYNTHESIZED_HPP diff --git a/sprout/compost/formats.hpp b/sprout/compost/formats.hpp new file mode 100644 index 00000000..ae2a9fbe --- /dev/null +++ b/sprout/compost/formats.hpp @@ -0,0 +1,7 @@ +#ifndef SPROUT_COMPOST_FORMATS_HPP +#define SPROUT_COMPOST_FORMATS_HPP + +#include +#include + +#endif // #ifndef SPROUT_COMPOST_FORMATS_HPP diff --git a/sprout/compost/formats/as_pcm_wave.hpp b/sprout/compost/formats/as_pcm_wave.hpp new file mode 100644 index 00000000..0a0a6aba --- /dev/null +++ b/sprout/compost/formats/as_pcm_wave.hpp @@ -0,0 +1,92 @@ +#ifndef SPROUT_COMPOST_FORMATS_AS_PCM_WAVE_HPP +#define SPROUT_COMPOST_FORMATS_AS_PCM_WAVE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace compost { + namespace formats { + // + // normalized_to_pcm_wave + // + template + struct normalized_to_pcm_wave; + template + struct normalized_to_pcm_wave< + IntType, + typename std::enable_if::value>::type + > { + public: + typedef IntType result_type; + public: + template + SPROUT_CONSTEXPR result_type operator()(T const& x) const { + return static_cast(sprout::clamp(x, -1, 1) * std::numeric_limits::max()); + } + }; + template + struct normalized_to_pcm_wave< + IntType, + typename std::enable_if::value>::type + > { + public: + typedef IntType result_type; + public: + template + SPROUT_CONSTEXPR result_type operator()(T const& x) const { + return static_cast(sprout::clamp((x + 1) / 2, 0, 1) * std::numeric_limits::max()); + } + }; + + // + // as_pcm_wave_forwarder + // + template + class as_pcm_wave_forwarder {}; + + // + // as_pcm_wave + // + template + inline SPROUT_CONSTEXPR sprout::compost::formats::as_pcm_wave_forwarder + as_pcm_wave() { + return sprout::compost::formats::as_pcm_wave_forwarder(); + } + + // + // operator| + // + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::formats::as_pcm_wave_forwarder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::adaptors::transformed(sprout::compost::formats::normalized_to_pcm_wave()) + ) + { + return sprout::forward(lhs) + | sprout::adaptors::transformed(sprout::compost::formats::normalized_to_pcm_wave()) + ; + } + + // + // as_pcm_wave8 + // as_pcm_wave16 + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::formats::as_pcm_wave_forwarder as_pcm_wave8{}; + SPROUT_STATIC_CONSTEXPR sprout::compost::formats::as_pcm_wave_forwarder as_pcm_wave16{}; + } // anonymous-namespace + } // namespace formats + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_FORMATS_AS_PCM_WAVE_HPP diff --git a/sprout/compost/load/source.hpp b/sprout/compost/load/source.hpp new file mode 100644 index 00000000..5f38b06c --- /dev/null +++ b/sprout/compost/load/source.hpp @@ -0,0 +1,68 @@ + +#ifndef COMPOST_DEF_LOAD_SOURCE_IDENTIFIER +# error should define COMPOST_DEF_LOAD_SOURCE_IDENTIFIER. +#endif + +#ifndef COMPOST_DEF_LOAD_SOURCE_FILE +# error should define COMPOST_DEF_LOAD_SOURCE_FILE. +#endif + +#ifndef COMPOST_DEF_LOAD_SOURCE_DATA_INDEX +# define COMPOST_DEF_LOAD_SOURCE_DATA_INDEX -1 +#endif + +#define COMPOST_LOAD_IDENTIFIER_DETAIL_CAT(id, suffix) COMPOST_LOAD_IDENTIFIER_DETAIL_CAT_I(id, suffix) +#define COMPOST_LOAD_IDENTIFIER_DETAIL_CAT_I(id, suffix) COMPOST_LOAD_IDENTIFIER_DETAIL_CAT_II(id ## suffix) +#define COMPOST_LOAD_IDENTIFIER_DETAIL_CAT_II(res) res + +#define COMPOST_LOAD_DETAIL_IDENTIFIER(id) COMPOST_LOAD_IDENTIFIER_DETAIL_CAT( \ + COMPOST_LOAD_IDENTIFIER_DETAIL_CAT(COMPOST_DEF_LOAD_SOURCE_IDENTIFIER, id), \ + _compost_load_source_detail \ + ) + +#define COMPOST_LOAD_IDENTIFIER COMPOST_DEF_LOAD_SOURCE_IDENTIFIER +#ifdef COMPOST_DEF_LOAD_INFO_IDENTIFIER +# define COMPOST_LOAD_INFO_IDENTIFIER COMPOST_DEF_LOAD_INFO_IDENTIFIER +#else +# define COMPOST_LOAD_INFO_IDENTIFIER COMPOST_LOAD_DETAIL_IDENTIFIER(info) +#endif + +SPROUT_STATIC_CONSTEXPR sprout::compost::sources::version_type COMPOST_LOAD_DETAIL_IDENTIFIER(version) = +# define COMPOST_LOADING_SOURCE_VERSION +# include COMPOST_DEF_LOAD_SOURCE_FILE +# undef COMPOST_LOADING_SOURCE_VERSION + ; + +static_assert(COMPOST_LOAD_DETAIL_IDENTIFIER(version) <= 0, "Unsupported compost src version"); + +SPROUT_STATIC_CONSTEXPR sprout::compost::sources::info_type COMPOST_LOAD_INFO_IDENTIFIER = { +# define COMPOST_LOADING_SOURCE_INFO +# include COMPOST_DEF_LOAD_SOURCE_FILE +# undef COMPOST_LOADING_SOURCE_INFO + }; + +SPROUT_STATIC_CONSTEXPR sprout::compost::sources::sound_type< + COMPOST_LOAD_INFO_IDENTIFIER.size +> COMPOST_LOAD_IDENTIFIER( + COMPOST_LOAD_INFO_IDENTIFIER, +# define COMPOST_LOADING_SOURCE_DATA +# define COMPOST_LOADING_SOURCE_DATA_INDEX COMPOST_DEF_LOAD_SOURCE_DATA_INDEX +# include COMPOST_DEF_LOAD_SOURCE_FILE +# undef COMPOST_LOADING_SOURCE_DATA_INDEX +# undef COMPOST_LOADING_SOURCE_DATA + ); + +#undef COMPOST_LOAD_IDENTIFIER +#undef COMPOST_LOAD_INFO_IDENTIFIER + +#undef COMPOST_LOAD_DETAIL_IDENTIFIER + +#undef COMPOST_LOAD_IDENTIFIER_DETAIL_CAT +#undef COMPOST_LOAD_IDENTIFIER_DETAIL_CAT_I +#undef COMPOST_LOAD_IDENTIFIER_DETAIL_CAT_II + +#undef COMPOST_DEF_LOAD_SOURCE_IDENTIFIER +#undef COMPOST_DEF_LOAD_SOURCE_FILE +#ifdef COMPOST_DEF_LOAD_INFO_IDENTIFIER +# undef COMPOST_DEF_LOAD_INFO_IDENTIFIER +#endif diff --git a/sprout/compost/sources.hpp b/sprout/compost/sources.hpp new file mode 100644 index 00000000..b1039539 --- /dev/null +++ b/sprout/compost/sources.hpp @@ -0,0 +1,7 @@ +#ifndef SPROUT_COMPOST_SOURCES_HPP +#define SPROUT_COMPOST_SOURCES_HPP + +#include +#include + +#endif // #ifndef SPROUT_COMPOST_SOURCES_HPP diff --git a/sprout/compost/sources/source.hpp b/sprout/compost/sources/source.hpp new file mode 100644 index 00000000..5a8c0aeb --- /dev/null +++ b/sprout/compost/sources/source.hpp @@ -0,0 +1,80 @@ +#ifndef SPROUT_COMPOST_SOURCES_SOURCE_HPP +#define SPROUT_COMPOST_SOURCES_SOURCE_HPP + +#include +#include +#include + +// +// COMPOST_LOAD_SOURCE +// +#define COMPOST_LOAD_SOURCE + +// +// COMPOST_SRC_VERSION +// +#define COMPOST_SRC_VERSION(NUM) NUM + +namespace sprout { + namespace compost { + namespace sources { + // + // version_type + // + typedef unsigned long version_type; + // + // info_type + // + struct info_type { + public: + std::uint16_t format_tag; // フォーマットID + std::uint16_t channels; // チャンネル数 + std::uint32_t samples_per_sec; // サンプリングレート + std::uint32_t bytes_per_sec; // データ速度 (Byte/sec) + std::uint16_t block_size; // ブロックサイズ (Byte/sample*チャンネル数) + std::uint16_t bits_per_sample; // サンプルあたりのビット数 (bit/sample) + std::size_t size; // 要素数 + }; + // + // sound_type + // + template + struct sound_type { + public: + typedef Elem element_type; + typedef element_type value_type; + typedef std::size_t size_type; + SPROUT_STATIC_CONSTEXPR size_type static_size = Size; + typedef sprout::array elements_type; + private: + elements_type elements_; + public: + template + SPROUT_CONSTEXPR sound_type(info_type const& info, Elems const&... elems) + : elements_{{ + (static_cast::type>(elems) / static_cast(32768.0))... + }} + { + static_assert(sizeof...(Elems) == static_size, "sound_type<>: unmatch source size"); + } + SPROUT_CONSTEXPR value_type const& + operator()(size_type x) const { + return elements_[x]; + } + SPROUT_CONSTEXPR size_type + size() const { + return static_size; + } + SPROUT_CONSTEXPR elements_type const& + elements() const { + return elements_; + } + }; + template + SPROUT_CONSTEXPR_OR_CONST typename sprout::compost::sources::sound_type::size_type + sprout::compost::sources::sound_type::static_size; + } // namespace sources + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_SOURCES_SOURCE_HPP diff --git a/sprout/compost/waves.hpp b/sprout/compost/waves.hpp new file mode 100644 index 00000000..d47e16ec --- /dev/null +++ b/sprout/compost/waves.hpp @@ -0,0 +1,11 @@ +#ifndef SPROUT_COMPOST_WAVES_HPP +#define SPROUT_COMPOST_WAVES_HPP + +#include +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_COMPOST_WAVES_HPP diff --git a/sprout/compost/waves/sawtooth_wave.hpp b/sprout/compost/waves/sawtooth_wave.hpp new file mode 100644 index 00000000..f3df661d --- /dev/null +++ b/sprout/compost/waves/sawtooth_wave.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_COMPOST_WAVES_SAWTOOTH_WAVE_HPP +#define SPROUT_COMPOST_WAVES_SAWTOOTH_WAVE_HPP + +#include +#include + +namespace sprout { + namespace compost { + namespace waves { + // + // sawtooth_wave + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::adaptors::sawtooth_wave_forwarder sawtooth_wave{}; + } // anonymous-namespace + } // namespace waves + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_WAVES_SAWTOOTH_WAVE_HPP diff --git a/sprout/compost/waves/sinusoidal.hpp b/sprout/compost/waves/sinusoidal.hpp new file mode 100644 index 00000000..914483aa --- /dev/null +++ b/sprout/compost/waves/sinusoidal.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_COMPOST_WAVES_SINUSOIDAL_HPP +#define SPROUT_COMPOST_WAVES_SINUSOIDAL_HPP + +#include +#include + +namespace sprout { + namespace compost { + namespace waves { + // + // sinusoidal + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::adaptors::sinusoidal_forwarder sinusoidal{}; + } // anonymous-namespace + } // namespace waves + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_WAVES_SINUSOIDAL_HPP diff --git a/sprout/compost/waves/square_wave.hpp b/sprout/compost/waves/square_wave.hpp new file mode 100644 index 00000000..7cfec18a --- /dev/null +++ b/sprout/compost/waves/square_wave.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_COMPOST_WAVES_SQUARE_WAVE_HPP +#define SPROUT_COMPOST_WAVES_SQUARE_WAVE_HPP + +#include +#include + +namespace sprout { + namespace compost { + namespace waves { + // + // square_wave + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::adaptors::square_wave_forwarder square_wave{}; + } // anonymous-namespace + } // namespace waves + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_WAVES_SQUARE_WAVE_HPP diff --git a/sprout/compost/waves/triangle_wave.hpp b/sprout/compost/waves/triangle_wave.hpp new file mode 100644 index 00000000..9cc1117a --- /dev/null +++ b/sprout/compost/waves/triangle_wave.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_COMPOST_WAVES_TRIANGLE_WAVE_HPP +#define SPROUT_COMPOST_WAVES_TRIANGLE_WAVE_HPP + +#include +#include + +namespace sprout { + namespace compost { + namespace waves { + // + // triangle_wave + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::adaptors::triangle_wave_forwarder triangle_wave{}; + } // anonymous-namespace + } // namespace waves + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_WAVES_TRIANGLE_WAVE_HPP diff --git a/sprout/compost/waves/white_noise.hpp b/sprout/compost/waves/white_noise.hpp new file mode 100644 index 00000000..ab59866b --- /dev/null +++ b/sprout/compost/waves/white_noise.hpp @@ -0,0 +1,179 @@ +#ifndef SPROUT_COMPOST_WAVES_WHITE_NOISE_HPP +#define SPROUT_COMPOST_WAVES_WHITE_NOISE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace compost { + namespace waves { + // + // white_noise_range + // + template + class white_noise_range + : public sprout::range::range_container< + sprout::generator_iterator< + sprout::random::random_result > + > + > + , public sprout::detail::container_nosy_static_size + , public sprout::detail::container_nosy_fixed_size + { + public: + typedef Range range_type; + typedef sprout::range::range_container< + sprout::generator_iterator< + sprout::random::random_result > + > + > base_type; + typedef typename base_type::iterator iterator; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename iterator::generator_type generator_type; + typedef typename generator_type::engine_type engine_type; + typedef typename generator_type::distribution_type distribution_type; + public: + white_noise_range() = default; + white_noise_range(white_noise_range const&) = default; + explicit SPROUT_CONSTEXPR white_noise_range( + range_type& range, + engine_type const& gen, + value_type const& sigma = 1 + ) + : base_type( + iterator(distribution_type(0, sigma)(gen), sprout::size(range)), + iterator() + ) + {} + SPROUT_CONSTEXPR engine_type const& engine() const { + return base_type::begin().generator().engine(); + } + SPROUT_CONSTEXPR value_type const& sigma() const { + return base_type::begin().generator().distribution().sigma(); + } + }; + + template + class white_noise_range + : public sprout::range::range_container< + sprout::generator_iterator< + sprout::random::random_result > + > + > + { + public: + typedef sprout::range::range_container< + sprout::generator_iterator< + sprout::random::random_result > + > + > base_type; + typedef typename base_type::iterator iterator; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename iterator::generator_type generator_type; + typedef typename generator_type::engine_type engine_type; + typedef typename generator_type::distribution_type distribution_type; + public: + white_noise_range() = default; + white_noise_range(white_noise_range const&) = default; + explicit SPROUT_CONSTEXPR white_noise_range( + engine_type const& gen, + value_type const& sigma = 1 + ) + : base_type( + iterator(distribution_type(0, sigma)(gen)), + iterator() + ) + {} + SPROUT_CONSTEXPR engine_type const& engine() const { + return base_type::begin().generator().engine(); + } + SPROUT_CONSTEXPR value_type const& sigma() const { + return base_type::begin().generator().distribution().sigma(); + } + }; + + // + // white_noise_forwarder + // + class white_noise_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::compost::waves::white_noise_range + operator()( + UniformRandomNumberGenerator const& gen, + Value const& sigma = 1 + ) const + { + return sprout::compost::waves::white_noise_range(gen, sigma); + } + }; + + // + // white_noise + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::waves::white_noise_forwarder white_noise{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR sprout::compost::waves::white_noise_range< + Value, UniformRandomNumberGenerator, + typename std::remove_reference::type>::type + > + operator|(Range&& lhs, sprout::compost::waves::white_noise_range const& rhs) { + return sprout::compost::waves::white_noise_range< + Value, UniformRandomNumberGenerator, + typename std::remove_reference::type>::type + >( + sprout::lvalue_forward(lhs), + rhs.engine(), rhs.sigma() + ); + } + } // namespace waves + } // namespace compost + + // + // container_construct_traits + // + template + struct container_construct_traits > { + public: + typedef typename sprout::container_construct_traits::copied_type copied_type; + public: + template + static SPROUT_CONSTEXPR copied_type deep_copy(Cont&& cont) { + return sprout::range::fixed::copy(sprout::forward(cont), sprout::pit()); + } + template + static SPROUT_CONSTEXPR copied_type make(Args&&... args) { + return sprout::make(sprout::forward(args)...); + } + template + static SPROUT_CONSTEXPR copied_type remake( + Cont&& cont, + typename sprout::container_traits >::difference_type size, + Args&&... args + ) + { + return sprout::remake(sprout::forward(cont), size, sprout::forward(args)...); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_WAVES_WHITE_NOISE_HPP diff --git a/sprout/darkroom/load/texture.hpp b/sprout/darkroom/load/texture.hpp index ddaf3c59..ca8996c9 100644 --- a/sprout/darkroom/load/texture.hpp +++ b/sprout/darkroom/load/texture.hpp @@ -11,12 +11,18 @@ #define DARKROOM_LOAD_IDENTIFIER_DETAIL_CAT_I(id, suffix) DARKROOM_LOAD_IDENTIFIER_DETAIL_CAT_II(id ## suffix) #define DARKROOM_LOAD_IDENTIFIER_DETAIL_CAT_II(res) res -#define DARKROOM_LOAD_IDENTIFIER DARKROOM_DEF_LOAD_TEXTURE_IDENTIFIER #define DARKROOM_LOAD_DETAIL_IDENTIFIER(id) DARKROOM_LOAD_IDENTIFIER_DETAIL_CAT( \ DARKROOM_LOAD_IDENTIFIER_DETAIL_CAT(DARKROOM_DEF_LOAD_TEXTURE_IDENTIFIER, id), \ _darkroom_load_texture_detail \ ) +#define DARKROOM_LOAD_IDENTIFIER DARKROOM_DEF_LOAD_TEXTURE_IDENTIFIER +#ifdef DARKROOM_DEF_LOAD_INFO_IDENTIFIER +# define DARKROOM_LOAD_INFO_IDENTIFIER DARKROOM_DEF_LOAD_INFO_IDENTIFIER +#else +# define DARKROOM_LOAD_INFO_IDENTIFIER DARKROOM_LOAD_DETAIL_IDENTIFIER(info) +#endif + SPROUT_STATIC_CONSTEXPR sprout::darkroom::textures::version_type DARKROOM_LOAD_DETAIL_IDENTIFIER(version) = # define DARKROOM_LOADING_TEXTURE_VERSION # include DARKROOM_DEF_LOAD_TEXTURE_FILE @@ -25,24 +31,25 @@ SPROUT_STATIC_CONSTEXPR sprout::darkroom::textures::version_type DARKROOM_LOAD_D static_assert(DARKROOM_LOAD_DETAIL_IDENTIFIER(version) <= 0, "Unsupported darkroom tex version"); -SPROUT_STATIC_CONSTEXPR sprout::darkroom::textures::info_type DARKROOM_LOAD_DETAIL_IDENTIFIER(info) = { +SPROUT_STATIC_CONSTEXPR sprout::darkroom::textures::info_type DARKROOM_LOAD_INFO_IDENTIFIER = { # define DARKROOM_LOADING_TEXTURE_INFO # include DARKROOM_DEF_LOAD_TEXTURE_FILE # undef DARKROOM_LOADING_TEXTURE_INFO }; SPROUT_STATIC_CONSTEXPR sprout::darkroom::textures::image_type< - DARKROOM_LOAD_DETAIL_IDENTIFIER(info).width, - DARKROOM_LOAD_DETAIL_IDENTIFIER(info).height + DARKROOM_LOAD_INFO_IDENTIFIER.width, + DARKROOM_LOAD_INFO_IDENTIFIER.height > DARKROOM_LOAD_IDENTIFIER( - DARKROOM_LOAD_DETAIL_IDENTIFIER(info).image_format, - DARKROOM_LOAD_DETAIL_IDENTIFIER(info).pixel_format, + DARKROOM_LOAD_INFO_IDENTIFIER, # define DARKROOM_LOADING_TEXTURE_PIXEL # include DARKROOM_DEF_LOAD_TEXTURE_FILE # undef DARKROOM_LOADING_TEXTURE_PIXEL ); #undef DARKROOM_LOAD_IDENTIFIER +#undef DARKROOM_LOAD_INFO_IDENTIFIER + #undef DARKROOM_LOAD_DETAIL_IDENTIFIER #undef DARKROOM_LOAD_IDENTIFIER_DETAIL_CAT @@ -51,3 +58,6 @@ SPROUT_STATIC_CONSTEXPR sprout::darkroom::textures::image_type< #undef DARKROOM_DEF_LOAD_TEXTURE_IDENTIFIER #undef DARKROOM_DEF_LOAD_TEXTURE_FILE +#ifdef DARKROOM_DEF_LOAD_INFO_IDENTIFIER +# undef DARKROOM_DEF_LOAD_INFO_IDENTIFIER +#endif diff --git a/sprout/darkroom/textures/texture.hpp b/sprout/darkroom/textures/texture.hpp index a1653f8b..607c3d07 100644 --- a/sprout/darkroom/textures/texture.hpp +++ b/sprout/darkroom/textures/texture.hpp @@ -61,7 +61,7 @@ namespace sprout { pixels_type pixels_; public: template - SPROUT_CONSTEXPR image_type(unsigned long image_format, unsigned long pixel_format, Elems const&... elems) + SPROUT_CONSTEXPR image_type(info_type const& info, Elems const&... elems) : pixels_{{ color_type( static_cast((elems >> 16) & 0xFF) / 0xFF, @@ -89,6 +89,12 @@ namespace sprout { return pixels_; } }; + template + SPROUT_CONSTEXPR_OR_CONST typename sprout::darkroom::textures::image_type::size_type + sprout::darkroom::textures::image_type::static_width; + template + SPROUT_CONSTEXPR_OR_CONST typename sprout::darkroom::textures::image_type::size_type + sprout::darkroom::textures::image_type::static_height; } // namespace textures } // namespace darkroom } // namespace sprout diff --git a/sprout/functional.hpp b/sprout/functional.hpp index 4b3cb19a..4c11fcb0 100644 --- a/sprout/functional.hpp +++ b/sprout/functional.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #endif // #ifndef SPROUT_FUNCTIONAL_HPP diff --git a/sprout/functional/bind1st.hpp b/sprout/functional/bind1st.hpp index daae7ba4..fbc06fcd 100644 --- a/sprout/functional/bind1st.hpp +++ b/sprout/functional/bind1st.hpp @@ -1,34 +1,68 @@ #ifndef SPROUT_FUNCTIONAL_BIND1ST_HPP #define SPROUT_FUNCTIONAL_BIND1ST_HPP +#include #include #include +#include namespace sprout { // Copyright (C) 2011 RiSK (sscrisk) // D.9.1 Class template binder1st - template - class binder1st + template + class binder1st; + template + class binder1st< + Fn, T, + typename std::enable_if::value>::type + > : public sprout::unary_function { + public: + typedef typename std::conditional< + std::is_void::value, + typename Fn::first_argument_type, + T + >::type value_type; protected: Fn op; - typename Fn::first_argument_type value; + value_type value; public: - SPROUT_CONSTEXPR binder1st(Fn const& x, typename Fn::first_argument_type const& y) + SPROUT_CONSTEXPR binder1st(Fn const& x, value_type const& y) : op(x), value(y) {} - SPROUT_CONSTEXPR typename Fn::result_type operator()(typename Fn::second_argument_type const& x) const { + SPROUT_CONSTEXPR typename Fn::result_type + operator()(typename Fn::second_argument_type const& x) const { + return op(value, x); + } + }; + template + class binder1st< + Fn, T, + typename std::enable_if::value>::type + > { + public: + typedef T value_type; + protected: + Fn op; + value_type value; + public: + SPROUT_CONSTEXPR binder1st(Fn const& x, value_type const& y) + : op(x), value(y) + {} + template + SPROUT_CONSTEXPR decltype(op(value, std::declval())) + operator()(U const& x) const { return op(value, x); } }; // D.9.2 bind1st template - inline SPROUT_CONSTEXPR sprout::binder1st + inline SPROUT_CONSTEXPR sprout::binder1st bind1st(Fn const& fn, T const& x) { - return sprout::binder1st(fn, typename Fn::first_argument_type(x)); + return sprout::binder1st(fn, typename sprout::binder1st::value_type(x)); } } // namespace sprout diff --git a/sprout/functional/bind2nd.hpp b/sprout/functional/bind2nd.hpp index 722c1466..b6abc12a 100644 --- a/sprout/functional/bind2nd.hpp +++ b/sprout/functional/bind2nd.hpp @@ -8,27 +8,59 @@ namespace sprout { // Copyright (C) 2011 RiSK (sscrisk) // D.9.3 Class template binder2nd - template - class binder2nd + template + class binder2nd; + template + class binder2nd< + Fn, T, + typename std::enable_if::value>::type + > : public sprout::unary_function { + public: + typedef typename std::conditional< + std::is_void::value, + typename Fn::second_argument_type, + T + >::type value_type; protected: Fn op; - typename Fn::second_argument_type value; + value_type value; public: - SPROUT_CONSTEXPR binder2nd(Fn const& x, typename Fn::second_argument_type const& y) + SPROUT_CONSTEXPR binder2nd(Fn const& x, value_type const& y) : op(x), value(y) {} - SPROUT_CONSTEXPR typename Fn::result_type operator()(typename Fn::first_argument_type const& x) const { + SPROUT_CONSTEXPR typename Fn::result_type + operator()(typename Fn::first_argument_type const& x) const { + return op(x, value); + } + }; + template + class binder2nd< + Fn, T, + typename std::enable_if::value>::type + > { + public: + typedef T value_type; + protected: + Fn op; + value_type value; + public: + SPROUT_CONSTEXPR binder2nd(Fn const& x, value_type const& y) + : op(x), value(y) + {} + template + SPROUT_CONSTEXPR decltype(op(std::declval(), value)) + operator()(U const& x) const { return op(x, value); } }; - // D.9.4 bind2nd + // D.9.3 bind2nd template - inline SPROUT_CONSTEXPR sprout::binder2nd - bind2nd(Fn const& op, T const& x) { - return sprout::binder2nd(op, typename Fn::second_argument_type(x)); + inline SPROUT_CONSTEXPR sprout::binder2nd + bind2nd(Fn const& fn, T const& x) { + return sprout::binder2nd(fn, typename sprout::binder2nd::value_type(x)); } } // namespace sprout diff --git a/sprout/functional/type_traits.hpp b/sprout/functional/type_traits.hpp new file mode 100644 index 00000000..66af3271 --- /dev/null +++ b/sprout/functional/type_traits.hpp @@ -0,0 +1,57 @@ +#ifndef SPROUT_FUNCTIONAL_TYPE_TRAITS_HPP +#define SPROUT_FUNCTIONAL_TYPE_TRAITS_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // has_result_type + // has_argument_type + // has_first_argument_type + // has_second_argument_type + // + SPROUT_HAS_XXX_TYPE_DEF_LAZY(result_type); + SPROUT_HAS_XXX_TYPE_DEF_LAZY(argument_type); + SPROUT_HAS_XXX_TYPE_DEF_LAZY(first_argument_type); + SPROUT_HAS_XXX_TYPE_DEF_LAZY(second_argument_type); + + // + // inhert_if_result_type + // inhert_if_argument_type + // inhert_if_first_argument_type + // inhert_if_second_argument_type + // + SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(result_type); + SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(argument_type); + SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(first_argument_type); + SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(second_argument_type); + + // + // is_strict_unary_function + // + template + struct is_strict_unary_function + : public std::integral_constant< + bool, + sprout::has_result_type::value + && sprout::has_argument_type::value + > + {}; + // + // is_strict_binary_function + // + template + struct is_strict_binary_function + : public std::integral_constant< + bool, + sprout::has_result_type::value + && sprout::has_first_argument_type::value + && sprout::has_second_argument_type::value + > + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_FUNCTIONAL_TYPE_TRAITS_HPP diff --git a/sprout/iterator/clamp_iterator.hpp b/sprout/iterator/clamp_iterator.hpp new file mode 100644 index 00000000..ee2f31dc --- /dev/null +++ b/sprout/iterator/clamp_iterator.hpp @@ -0,0 +1,264 @@ +#ifndef SPROUT_ITERATOR_CLAMP_ITERATOR_HPP +#define SPROUT_ITERATOR_CLAMP_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT + +namespace sprout { + // + // clamp_iterator + // + template::value_type> > + class clamp_iterator + : public std::iterator< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::value_type, + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + > + { + public: + typedef Iterator iterator_type; + typedef Compare compare_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + protected: + iterator_type current; + compare_type comp; + value_type low; + value_type up; + private: + public: + clamp_iterator() = default; + clamp_iterator(clamp_iterator const&) = default; + SPROUT_CONSTEXPR clamp_iterator(iterator_type it, value_type const& low, value_type const& up, compare_type comp = compare_type()) + : current(it), comp(comp), low(low), up(up) + {} + template + SPROUT_CONSTEXPR clamp_iterator(clamp_iterator const& it) + : current(it.current), comp(it.comp), low(it.low), up(it.up) + {} + template + clamp_iterator& operator=(clamp_iterator const& it) { + clamp_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type const& base() const { + return current; + } + SPROUT_CONSTEXPR compare_type const& compare() const { + return comp; + } + SPROUT_CONSTEXPR value_type const& lower() const { + return low; + } + SPROUT_CONSTEXPR value_type const& upper() const { + return up; + } + SPROUT_CONSTEXPR reference operator*() const { + return sprout::clamp(*current, low, up, comp); + } + SPROUT_CONSTEXPR pointer operator->() const { + return &sprout::clamp(*current, low, up, comp); + } + + clamp_iterator& operator++() { + ++current; + return *this; + } + clamp_iterator operator++(int) { + clamp_iterator result(*this); + ++current; + return result; + } + clamp_iterator& operator--() { + --current; + return *this; + } + clamp_iterator operator--(int) { + clamp_iterator temp(*this); + --current; + return temp; + } + SPROUT_CONSTEXPR clamp_iterator operator+(difference_type n) const { + return clamp_iterator(sprout::next(current, n), low, up, comp); + } + SPROUT_CONSTEXPR clamp_iterator operator-(difference_type n) const { + return clamp_iterator(sprout::prev(current, n), low, up, comp); + } + clamp_iterator& operator+=(difference_type n) { + clamp_iterator temp(sprout::next(current, n), low, up, comp); + temp.swap(*this); + return *this; + } + clamp_iterator& operator-=(difference_type n) { + clamp_iterator temp(sprout::prev(current, n), low, up, comp); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR reference operator[](difference_type n) const { + return sprout::clamp(*sprout::next(current, n), low, up, comp); + } + SPROUT_CONSTEXPR clamp_iterator next() const { + return clamp_iterator(sprout::next(current), low, up, comp); + } + SPROUT_CONSTEXPR clamp_iterator prev() const { + return clamp_iterator(sprout::prev(current), low, up, comp); + } + void swap(clamp_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(low, other.low)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(up, other.up)) + ) + { + sprout::swap(current, other.current); + sprout::swap(comp, other.comp); + sprout::swap(low, other.low); + sprout::swap(up, other.up); + } + }; + + template + inline SPROUT_CONSTEXPR bool operator==( + sprout::clamp_iterator const& lhs, + sprout::clamp_iterator const& rhs + ) + { + return lhs.base() == rhs.base(); + } + template + inline SPROUT_CONSTEXPR bool + operator!=(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { + return !(lhs == rhs); + } + template + inline SPROUT_CONSTEXPR bool + operator<(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { + return lhs.base() < rhs.base(); + } + template + inline SPROUT_CONSTEXPR bool + operator>(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { + return rhs < lhs; + } + template + inline SPROUT_CONSTEXPR bool + operator<=(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { + return !(rhs < lhs); + } + template + inline SPROUT_CONSTEXPR bool + operator>=(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { + return !(lhs < rhs); + } + template + inline SPROUT_CONSTEXPR decltype(std::declval() - std::declval()) + operator-(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { + return lhs.base() - rhs.base(); + } + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + operator+( + typename sprout::clamp_iterator::difference_type n, + sprout::clamp_iterator const& it + ) + { + return it + n; + } + + // + // make_clamp_iterator + // + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + make_clamp_iterator( + Iterator it, + typename std::iterator_traits::value_type const& low, + typename std::iterator_traits::value_type const& up, + Compare comp + ) + { + return sprout::clamp_iterator(it, low, up, comp); + } + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + make_clamp_iterator( + Iterator it, + typename std::iterator_traits::value_type const& low, + typename std::iterator_traits::value_type const& up + ) + { + return sprout::clamp_iterator(it, low, up); + } + + // + // swap + // + template + inline void + swap(sprout::clamp_iterator& lhs, sprout::clamp_iterator& rhs) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_distance + // + template + inline SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type + iterator_distance(sprout::clamp_iterator first, sprout::clamp_iterator last) { + return last - first; + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + iterator_next(sprout::clamp_iterator const& it) { + return it.next(); + } + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + iterator_next( + sprout::clamp_iterator const& it, + typename sprout::clamp_iterator::difference_type n + ) + { + return it + n; + } + + // + // iterator_prev + // + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + iterator_prev(sprout::clamp_iterator const& it) { + return it.prev(); + } + template + inline SPROUT_CONSTEXPR sprout::clamp_iterator + iterator_prev( + sprout::clamp_iterator const& it, + typename sprout::clamp_iterator::difference_type n + ) + { + return it - n; + } +} // namespace sprout + +#endif // SPROUT_ITERATOR_CLAMP_ITERATOR_HPP diff --git a/sprout/iterator/filter_iterator.hpp b/sprout/iterator/filter_iterator.hpp index 9f269f15..71ce73ed 100644 --- a/sprout/iterator/filter_iterator.hpp +++ b/sprout/iterator/filter_iterator.hpp @@ -71,7 +71,7 @@ namespace sprout { , last(last) , pred(pred) {} - public: + public: filter_iterator() = default; filter_iterator(filter_iterator const&) = default; SPROUT_CONSTEXPR filter_iterator(predicate_type pred, iterator_type it, iterator_type last = iterator_type()) diff --git a/sprout/iterator/traits.hpp b/sprout/iterator/traits.hpp index 2227d856..1707214b 100644 --- a/sprout/iterator/traits.hpp +++ b/sprout/iterator/traits.hpp @@ -19,124 +19,139 @@ namespace sprout { : sprout::detail::has_iterator_category > {}; - namespace detail { - template - struct is_input_iterator_impl - : std::false_type - {}; - template - struct is_input_iterator_impl< - Iterator, - typename std::enable_if::value>::type - > - : std::is_convertible< - typename std::iterator_traits::iterator_category, - std::input_iterator_tag - > - {}; - } // namespace detail + // + // is_input_iterator_category + // + template + struct is_input_iterator_category + : public std::is_convertible + {}; + // + // is_output_iterator_category + // + template + struct is_output_iterator_category + : public std::is_convertible + {}; + // + // is_forward_iterator_category + // + template + struct is_forward_iterator_category + : public std::is_convertible + {}; + // + // is_bidirectional_iterator_category + // + template + struct is_bidirectional_iterator_category + : public std::is_convertible + {}; + // + // is_random_access_iterator_category + // + template + struct is_random_access_iterator_category + : public std::is_convertible + {}; + // // is_input_iterator // template struct is_input_iterator - : sprout::detail::is_input_iterator_impl + : public sprout::is_input_iterator_category::iterator_category> {}; - - namespace detail { - template - struct is_output_iterator_impl - : std::false_type - {}; - template - struct is_output_iterator_impl< - Iterator, - typename std::enable_if::value>::type - > - : std::is_convertible< - typename std::iterator_traits::iterator_category, - std::output_iterator_tag - > - {}; - } // namespace detail // // is_output_iterator // template struct is_output_iterator - : sprout::detail::is_output_iterator_impl + : public sprout::is_output_iterator_category::iterator_category> {}; - - namespace detail { - template - struct is_forward_iterator_impl - : std::false_type - {}; - template - struct is_forward_iterator_impl< - Iterator, - typename std::enable_if::value>::type - > - : std::is_convertible< - typename std::iterator_traits::iterator_category, - std::forward_iterator_tag - > - {}; - } // namespace detail // // is_forward_iterator // template struct is_forward_iterator - : sprout::detail::is_forward_iterator_impl + : public sprout::is_forward_iterator_category::iterator_category> {}; - - namespace detail { - template - struct is_bidirectional_iterator_impl - : std::false_type - {}; - template - struct is_bidirectional_iterator_impl< - Iterator, - typename std::enable_if::value>::type - > - : std::is_convertible< - typename std::iterator_traits::iterator_category, - std::bidirectional_iterator_tag - > - {}; - } // namespace detail // // is_bidirectional_iterator // template struct is_bidirectional_iterator - : sprout::detail::is_bidirectional_iterator_impl + : public sprout::is_bidirectional_iterator_category::iterator_category> {}; - - namespace detail { - template - struct is_random_access_iterator_impl - : std::false_type - {}; - template - struct is_random_access_iterator_impl< - Iterator, - typename std::enable_if::value>::type - > - : std::is_convertible< - typename std::iterator_traits::iterator_category, - std::random_access_iterator_tag - > - {}; - } // namespace detail // // is_random_access_iterator // template struct is_random_access_iterator - : sprout::detail::is_random_access_iterator_impl + : public sprout::is_random_access_iterator_category::iterator_category> + {}; + + namespace detail { + template + struct iterator_category_hierarchy_impl; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + + template + struct iterator_category_hierarchy + : public sprout::detail::iterator_category_hierarchy_impl< + Category, + sprout::is_random_access_iterator_category::value, + sprout::is_bidirectional_iterator_category::value, + sprout::is_forward_iterator_category::value, + sprout::is_input_iterator_category::value || sprout::is_output_iterator_category::value + > + {}; + + template + struct iterator_category_less + : public std::integral_constant< + bool, + (sprout::detail::iterator_category_hierarchy::value < sprout::detail::iterator_category_hierarchy::value) + > + {}; + } // namespace detail + // + // min_iterator_category + // + template + struct min_iterator_category; + template + struct min_iterator_category + : public std::common_type + {}; + template + struct min_iterator_category + : public std::conditional< + sprout::detail::iterator_category_less::value, + Category1, Category2 + > + {}; + template + struct min_iterator_category + : public sprout::min_iterator_category< + Head, + typename sprout::min_iterator_category::type + > {}; } // namespace sprout diff --git a/sprout/iterator/transform_iterator.hpp b/sprout/iterator/transform_iterator.hpp index cfce8e59..f03abb45 100644 --- a/sprout/iterator/transform_iterator.hpp +++ b/sprout/iterator/transform_iterator.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace sprout { @@ -17,7 +18,10 @@ namespace sprout { template class transform_iterator : public std::iterator< - typename std::iterator_traits::iterator_category, + typename sprout::min_iterator_category< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::iterator_category + >::type, typename std::remove_reference< typename std::result_of< BinaryFunction ( @@ -47,7 +51,10 @@ namespace sprout { typedef BinaryFunction functor_type; typedef LIterator iterator_type; typedef RIterator iterator2_type; - typedef typename std::iterator_traits::iterator_category iterator_category; + typedef typename sprout::min_iterator_category< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::iterator_category + >::type iterator_category; typedef typename std::result_of< BinaryFunction ( typename std::iterator_traits::reference, diff --git a/sprout/random/variate_generator.hpp b/sprout/random/variate_generator.hpp index 208d21b2..c1971263 100644 --- a/sprout/random/variate_generator.hpp +++ b/sprout/random/variate_generator.hpp @@ -29,6 +29,7 @@ namespace sprout { typedef Engine engine_type; typedef Distribution distribution_type; typedef typename distribution_value_type::result_type result_type; + typedef sprout::random::random_result random_result_type; private: engine_type engine_; distribution_type distribution_; @@ -40,7 +41,7 @@ namespace sprout { : engine_(engine) , distribution_(distribution) {} - SPROUT_CONSTEXPR sprout::random::random_result operator()() const { + SPROUT_CONSTEXPR random_result_type operator()() const { return distribution_(engine_); } engine_reference_type engine() { diff --git a/sprout/range/adaptor/clamped.hpp b/sprout/range/adaptor/clamped.hpp new file mode 100644 index 00000000..90023aad --- /dev/null +++ b/sprout/range/adaptor/clamped.hpp @@ -0,0 +1,164 @@ +#ifndef SPROUT_RANGE_ADAPTOR_CLAMPED_HPP +#define SPROUT_RANGE_ADAPTOR_CLAMPED_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT + +namespace sprout { + namespace adaptors { + // + // clamped_range + // + template< + typename Range, + typename Compare = NS_SSCRISK_CEL_OR_SPROUT::less::value_type> + > + class clamped_range + : public sprout::range::range_container< + sprout::clamp_iterator::iterator, Compare> + > + , public sprout::detail::container_nosy_static_size + , public sprout::detail::container_nosy_fixed_size + { + public: + typedef Range range_type; + typedef sprout::range::range_container< + sprout::clamp_iterator::iterator, Compare> + > base_type; + typedef typename base_type::iterator iterator; + typedef typename base_type::value_type value_type; + typedef typename iterator::compare_type compare_type; + public: + clamped_range() = default; + clamped_range(clamped_range const&) = default; + explicit SPROUT_CONSTEXPR clamped_range( + range_type& range, + value_type const& low, + value_type const& up, + compare_type comp = compare_type() + ) + : base_type( + iterator(sprout::begin(range), low, up, comp), + iterator(sprout::end(range), low, up, comp) + ) + {} + SPROUT_CONSTEXPR compare_type const& compare() const { + return base_type::begin().compare(); + } + SPROUT_CONSTEXPR value_type const& lower() const { + return base_type::begin().lower(); + } + SPROUT_CONSTEXPR value_type const& upper() const { + return base_type::begin().upper(); + } + }; + + // + // clamp_holder + // + template > + class clamp_holder { + public: + typedef Value value_type; + typedef Compare compare_type; + private: + compare_type comp_; + value_type low_; + value_type up_; + public: + SPROUT_CONSTEXPR clamp_holder(value_type const& low, value_type const& up, compare_type comp = compare_type()) + : comp_(comp), low_(low), up_(up) + {} + SPROUT_CONSTEXPR compare_type const& compare() const { + return comp_; + } + SPROUT_CONSTEXPR value_type const& lower() const { + return low_; + } + SPROUT_CONSTEXPR value_type const& upper() const { + return up_; + } + }; + + // + // clamped_forwarder + // + class clamped_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::adaptors::clamp_holder + operator()(Value const& low, Value const& up, Compare comp) { + return sprout::adaptors::clamp_holder(low, up, comp); + } + template + SPROUT_CONSTEXPR sprout::adaptors::clamp_holder + operator()(Value const& low, Value const& up) { + return sprout::adaptors::clamp_holder(low, up); + } + }; + + // + // clamped + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::adaptors::clamped_forwarder clamped{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR sprout::adaptors::clamped_range< + typename std::remove_reference::type>::type, + Compare + > + operator|(Range&& lhs, sprout::adaptors::clamp_holder const& rhs) { + return sprout::adaptors::clamped_range< + typename std::remove_reference::type>::type, + Compare + >( + sprout::lvalue_forward(lhs), + rhs.lower(), rhs.upper(), rhs.compare() + ); + } + } // namespace adaptors + + // + // container_construct_traits + // + template + struct container_construct_traits > { + public: + typedef typename sprout::container_construct_traits::copied_type copied_type; + public: + template + static SPROUT_CONSTEXPR copied_type deep_copy(Cont&& cont) { + return sprout::range::fixed::copy(sprout::forward(cont), sprout::pit()); + } + template + static SPROUT_CONSTEXPR copied_type make(Args&&... args) { + return sprout::make(sprout::forward(args)...); + } + template + static SPROUT_CONSTEXPR copied_type remake( + Cont&& cont, + typename sprout::container_traits >::difference_type size, + Args&&... args + ) + { + return sprout::remake(sprout::forward(cont), size, sprout::forward(args)...); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_RANGE_ADAPTOR_CLAMPED_HPP diff --git a/sprout/range/adaptor/copied.hpp b/sprout/range/adaptor/copied.hpp index c36342c0..ac36810b 100644 --- a/sprout/range/adaptor/copied.hpp +++ b/sprout/range/adaptor/copied.hpp @@ -62,7 +62,7 @@ namespace sprout { explicit SPROUT_CONSTEXPR copy_holder(result_type& result) : result_(result) {} - SPROUT_CONSTEXPR result_type result() const { + SPROUT_CONSTEXPR result_type const& result() const { return result_; } }; @@ -90,9 +90,9 @@ namespace sprout { // operator| // template - inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm >::type + inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type operator|(Range&& lhs, sprout::adaptors::copy_holder const& rhs) { - return sprout::range::fixed::copy(sprout::lvalue_forward(lhs), sprout::pit()); + return sprout::range::fixed::copy(sprout::lvalue_forward(lhs), rhs.result()); } template inline SPROUT_CONSTEXPR sprout::adaptors::copied_range< diff --git a/sprout/range/adaptor/transformed.hpp b/sprout/range/adaptor/transformed.hpp index cddfc138..30a943df 100644 --- a/sprout/range/adaptor/transformed.hpp +++ b/sprout/range/adaptor/transformed.hpp @@ -143,7 +143,7 @@ namespace sprout { return sprout::adaptors::transform_holder< BinaryFunction, typename std::remove_reference::type>::type - > ( + >( func, sprout::lvalue_forward(range) );