<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow_lite_support/c/task/audio/audio_classifier.h"

#include <string.h>

#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
#include "tensorflow_lite_support/c/common.h"
#include "tensorflow_lite_support/c/task/audio/core/audio_buffer.h"
#include "tensorflow_lite_support/c/task/processor/classification_result.h"
#include "tensorflow_lite_support/cc/port/gmock.h"
#include "tensorflow_lite_support/cc/port/gtest.h"
#include "tensorflow_lite_support/cc/port/status_matchers.h"
#include "tensorflow_lite_support/cc/port/statusor.h"
#include "tensorflow_lite_support/cc/task/audio/utils/wav_io.h"
#include "tensorflow_lite_support/cc/test/test_utils.h"

namespace tflite {
namespace task {
namespace audio {
namespace {

using ::testing::HasSubstr;
using ::tflite::support::StatusOr;
using ::tflite::task::JoinPath;

constexpr char kTestDataDirectory[] =
    "/tensorflow_lite_support/cc/test/testdata/task/"
    "audio/";
// Quantized model.
constexpr char kYamNetAudioClassifierWithMetadata[] =
    "yamnet_audio_classifier_with_metadata.tflite";

StatusOr<TfLiteAudioBuffer> LoadAudioBufferFromFileNamed(
    const std::string wav_file, int buffer_size) {
  std::string contents = ReadFile(
      JoinPath("./" /*test src dir*/, kTestDataDirectory, wav_file));

  int offset = 0;
  uint32_t decoded_sample_count;
  uint16_t decoded_channel_count;
  uint32_t decoded_sample_rate;
  std::vector<float> wav_data;

  absl::Status read_audio_file_status = DecodeLin16WaveAsFloatVector(
      contents, &wav_data, offset, &decoded_sample_count, &decoded_channel_count,
      &decoded_sample_rate);

  if (decoded_sample_count > buffer_size) {
    decoded_sample_count = buffer_size;
  }

  if (!read_audio_file_status.ok()) {
    return read_audio_file_status;
  }

  float* c_wav_data = (float*)malloc(sizeof(float) * wav_data.size());
  if (!c_wav_data) {
    exit(-1);
  }

  memcpy(c_wav_data, wav_data.data(), sizeof(float) * wav_data.size());

  TfLiteAudioBuffer audio_buffer = {
      .format = {.channels = decoded_channel_count,
                 .sample_rate = static_cast<int>(decoded_sample_rate)},
      .data = c_wav_data,
      .size = static_cast<int>(decoded_sample_count)};

  return audio_buffer;
}

void Verify(TfLiteClassificationResult* classification_result,
            int expected_classifications_size) {
  EXPECT_NE(classification_result, nullptr);
  EXPECT_EQ(classification_result->size, expected_classifications_size);
  EXPECT_NE(classification_result->classifications, nullptr);
}

void Verify(TfLiteClassifications& classifications,
            int expected_categories_size, int expected_head_index,
            char const* expected_head_name) {
  EXPECT_EQ(classifications.size, expected_categories_size);
  EXPECT_EQ(classifications.head_index, expected_head_index);
  ASSERT_NE(classifications.head_name, nullptr);
  if (expected_head_name) {
    EXPECT_EQ(strcmp(classifications.head_name, expected_head_name), 0);
  }
  EXPECT_NE(classifications.categories, nullptr);
}

void Verify(TfLiteCategory& category, int expected_index,
            char const* expected_label, float expected_score) {
  const float kPrecision = 1e-6;
  EXPECT_EQ(category.index, expected_index);
  EXPECT_NE(category.label, nullptr);

  if (category.label && expected_label) {
    EXPECT_EQ(strcmp(category.label, expected_label), 0);
  }

  EXPECT_EQ(category.display_name, nullptr);
  EXPECT_NEAR(category.score, expected_score, kPrecision);
}

void Verify(TfLiteSupportError* error, TfLiteSupportErrorCode error_code,
            char const* message) {
  ASSERT_NE(error, nullptr);
  EXPECT_EQ(error->code, kInvalidArgumentError);
  EXPECT_NE(error->message, nullptr);
  EXPECT_THAT(error->message, HasSubstr(message));
}

class AudioClassifierFromOptionsTest : public tflite_shims::testing::Test {};

TEST_F(AudioClassifierFromOptionsTest, FailsWithMissingModelPathAndError) {
  TfLiteAudioClassifierOptions options = TfLiteAudioClassifierOptionsCreate();

  TfLiteSupportError* error = nullptr;
  TfLiteAudioClassifier* audio_classifier =
      TfLiteAudioClassifierFromOptions(&options, &error);

  EXPECT_EQ(audio_classifier, nullptr);
  if (audio_classifier) TfLiteAudioClassifierDelete(audio_classifier);

  Verify(error, kInvalidArgumentError,
         "INVALID_ARGUMENT: Missing mandatory `model_file` field in "
         "`base_options`");

  TfLiteSupportErrorDelete(error);
}

TEST_F(AudioClassifierFromOptionsTest, SucceedsWithModelPath) {
  std::string model_path =
      JoinPath("./" /*test src dir*/, kTestDataDirectory,
               kYamNetAudioClassifierWithMetadata);
  TfLiteAudioClassifierOptions options = TfLiteAudioClassifierOptionsCreate();
  options.base_options.model_file.file_path = model_path.data();
  TfLiteAudioClassifier* audio_classifier =
      TfLiteAudioClassifierFromOptions(&options, nullptr);

  EXPECT_NE(audio_classifier, nullptr);
  TfLiteAudioClassifierDelete(audio_classifier);
}

class AudioClassifierClassifyTest : public tflite_shims::testing::Test {
 protected:
  void SetUp() override {
    std::string model_path =
        JoinPath("./" /*test src dir*/, kTestDataDirectory,
                 kYamNetAudioClassifierWithMetadata);

    TfLiteAudioClassifierOptions options = TfLiteAudioClassifierOptionsCreate();
    options.base_options.model_file.file_path = model_path.data();
    audio_classifier = TfLiteAudioClassifierFromOptions(&options, nullptr);
    ASSERT_NE(audio_classifier, nullptr);
  }

  void TearDown() override { TfLiteAudioClassifierDelete(audio_classifier); }
  TfLiteAudioClassifier* audio_classifier;
};

TEST_F(AudioClassifierClassifyTest, SucceedsWithAudioFile) {
  int input_buffer_size = TfLiteAudioClassifierGetRequiredInputBufferSize(
      audio_classifier, nullptr);
  ASSERT_NE(input_buffer_size, -1);

  SUPPORT_ASSERT_OK_AND_ASSIGN(
      TfLiteAudioBuffer audio_buffer,
      LoadAudioBufferFromFileNamed("speech.wav", input_buffer_size));

  TfLiteSupportError* classifyError = NULL;
  TfLiteClassificationResult* classification_result =
      TfLiteAudioClassifierClassify(audio_classifier, &audio_buffer,
                                    &classifyError);

  TfLiteAudioBufferDeleteData(audio_buffer);

  Verify(classification_result, 1);
  Verify(classification_result->classifications[0], 521, 0, "scores");
  Verify(classification_result->classifications[0].categories[0], 0, "Speech",
         0.917969);
  Verify(classification_result->classifications[0].categories[1], 500,
         "Inside, small room", 0.058594);
  Verify(classification_result->classifications[0].categories[2], 494,
         "Silence", 0.011719);

  TfLiteClassificationResultDelete(classification_result);
}

}  // namespace
}  // namespace audio
}  // namespace task
}  // namespace tflite
<commit_msg>Updated C audio classifier test to account for changes<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow_lite_support/c/task/audio/audio_classifier.h"

#include <string.h>

#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
#include "tensorflow_lite_support/c/common.h"
#include "tensorflow_lite_support/c/task/audio/core/audio_buffer.h"
#include "tensorflow_lite_support/c/task/processor/classification_result.h"
#include "tensorflow_lite_support/cc/port/gmock.h"
#include "tensorflow_lite_support/cc/port/gtest.h"
#include "tensorflow_lite_support/cc/port/status_matchers.h"
#include "tensorflow_lite_support/cc/port/statusor.h"
#include "tensorflow_lite_support/cc/task/audio/utils/wav_io.h"
#include "tensorflow_lite_support/cc/test/test_utils.h"

namespace tflite {
namespace task {
namespace audio {
namespace {

using ::testing::HasSubstr;
using ::tflite::support::StatusOr;
using ::tflite::task::JoinPath;

constexpr char kTestDataDirectory[] =
    "/tensorflow_lite_support/cc/test/testdata/task/"
    "audio/";
// Quantized model.
constexpr char kYamNetAudioClassifierWithMetadata[] =
    "yamnet_audio_classifier_with_metadata.tflite";

StatusOr<TfLiteAudioBuffer> LoadAudioBufferFromFileNamed(
    const std::string wav_file, int buffer_size) {
  std::string contents = ReadFile(
      JoinPath("./" /*test src dir*/, kTestDataDirectory, wav_file));

  uint32_t offset = 0;
  uint32_t decoded_sample_count;
  uint16_t decoded_channel_count;
  uint32_t decoded_sample_rate;
  std::vector<float> wav_data;

  absl::Status read_audio_file_status = DecodeLin16WaveAsFloatVector(
      contents, &wav_data, &offset, &decoded_sample_count, &decoded_channel_count,
      &decoded_sample_rate);

  if (decoded_sample_count > buffer_size) {
    decoded_sample_count = buffer_size;
  }

  if (!read_audio_file_status.ok()) {
    return read_audio_file_status;
  }

  float* c_wav_data = (float*)malloc(sizeof(float) * wav_data.size());
  if (!c_wav_data) {
    exit(-1);
  }

  memcpy(c_wav_data, wav_data.data(), sizeof(float) * wav_data.size());

  TfLiteAudioBuffer audio_buffer = {
      .format = {.channels = decoded_channel_count,
                 .sample_rate = static_cast<int>(decoded_sample_rate)},
      .data = c_wav_data,
      .size = static_cast<int>(decoded_sample_count)};

  return audio_buffer;
}

void Verify(TfLiteClassificationResult* classification_result,
            int expected_classifications_size) {
  EXPECT_NE(classification_result, nullptr);
  EXPECT_EQ(classification_result->size, expected_classifications_size);
  EXPECT_NE(classification_result->classifications, nullptr);
}

void Verify(TfLiteClassifications& classifications,
            int expected_categories_size, int expected_head_index,
            char const* expected_head_name) {
  EXPECT_EQ(classifications.size, expected_categories_size);
  EXPECT_EQ(classifications.head_index, expected_head_index);
  ASSERT_NE(classifications.head_name, nullptr);
  if (expected_head_name) {
    EXPECT_EQ(strcmp(classifications.head_name, expected_head_name), 0);
  }
  EXPECT_NE(classifications.categories, nullptr);
}

void Verify(TfLiteCategory& category, int expected_index,
            char const* expected_label, float expected_score) {
  const float kPrecision = 1e-6;
  EXPECT_EQ(category.index, expected_index);
  EXPECT_NE(category.label, nullptr);

  if (category.label && expected_label) {
    EXPECT_EQ(strcmp(category.label, expected_label), 0);
  }

  EXPECT_EQ(category.display_name, nullptr);
  EXPECT_NEAR(category.score, expected_score, kPrecision);
}

void Verify(TfLiteSupportError* error, TfLiteSupportErrorCode error_code,
            char const* message) {
  ASSERT_NE(error, nullptr);
  EXPECT_EQ(error->code, kInvalidArgumentError);
  EXPECT_NE(error->message, nullptr);
  EXPECT_THAT(error->message, HasSubstr(message));
}

class AudioClassifierFromOptionsTest : public tflite_shims::testing::Test {};

TEST_F(AudioClassifierFromOptionsTest, FailsWithMissingModelPathAndError) {
  TfLiteAudioClassifierOptions options = TfLiteAudioClassifierOptionsCreate();

  TfLiteSupportError* error = nullptr;
  TfLiteAudioClassifier* audio_classifier =
      TfLiteAudioClassifierFromOptions(&options, &error);

  EXPECT_EQ(audio_classifier, nullptr);
  if (audio_classifier) TfLiteAudioClassifierDelete(audio_classifier);

  Verify(error, kInvalidArgumentError,
         "INVALID_ARGUMENT: Missing mandatory `model_file` field in "
         "`base_options`");

  TfLiteSupportErrorDelete(error);
}

TEST_F(AudioClassifierFromOptionsTest, SucceedsWithModelPath) {
  std::string model_path =
      JoinPath("./" /*test src dir*/, kTestDataDirectory,
               kYamNetAudioClassifierWithMetadata);
  TfLiteAudioClassifierOptions options = TfLiteAudioClassifierOptionsCreate();
  options.base_options.model_file.file_path = model_path.data();
  TfLiteAudioClassifier* audio_classifier =
      TfLiteAudioClassifierFromOptions(&options, nullptr);

  EXPECT_NE(audio_classifier, nullptr);
  TfLiteAudioClassifierDelete(audio_classifier);
}

class AudioClassifierClassifyTest : public tflite_shims::testing::Test {
 protected:
  void SetUp() override {
    std::string model_path =
        JoinPath("./" /*test src dir*/, kTestDataDirectory,
                 kYamNetAudioClassifierWithMetadata);

    TfLiteAudioClassifierOptions options = TfLiteAudioClassifierOptionsCreate();
    options.base_options.model_file.file_path = model_path.data();
    audio_classifier = TfLiteAudioClassifierFromOptions(&options, nullptr);
    ASSERT_NE(audio_classifier, nullptr);
  }

  void TearDown() override { TfLiteAudioClassifierDelete(audio_classifier); }
  TfLiteAudioClassifier* audio_classifier;
};

TEST_F(AudioClassifierClassifyTest, SucceedsWithAudioFile) {
  int input_buffer_size = TfLiteAudioClassifierGetRequiredInputBufferSize(
      audio_classifier, nullptr);
  ASSERT_NE(input_buffer_size, -1);

  SUPPORT_ASSERT_OK_AND_ASSIGN(
      TfLiteAudioBuffer audio_buffer,
      LoadAudioBufferFromFileNamed("speech.wav", input_buffer_size));

  TfLiteSupportError* classifyError = NULL;
  TfLiteClassificationResult* classification_result =
      TfLiteAudioClassifierClassify(audio_classifier, &audio_buffer,
                                    &classifyError);

  TfLiteAudioBufferDeleteData(audio_buffer);

  Verify(classification_result, 1);
  Verify(classification_result->classifications[0], 521, 0, "scores");
  Verify(classification_result->classifications[0].categories[0], 0, "Speech",
         0.917969);
  Verify(classification_result->classifications[0].categories[1], 500,
         "Inside, small room", 0.058594);
  Verify(classification_result->classifications[0].categories[2], 494,
         "Silence", 0.011719);

  TfLiteClassificationResultDelete(classification_result);
}

}  // namespace
}  // namespace audio
}  // namespace task
}  // namespace tflite
<|endoftext|>


<commit_before>#ifndef COMPASS_CT_MSVC_IMPL_H_

#include "detail/ct/detect_compiler.hpp"

#ifdef COMPASS_CT_COMP_MSVC

#define COMPASS_CT_MSVC_IMPL_H_

#include "intrin.h"

#include <array>
#include <bitset>
#include <cstdint>

#include "detail/tags.hpp"
#include "detail/definitions.hpp"

namespace compass {

  namespace runtime {

    static std::array<std::uint32_t, 4> cpuid(std::uint32_t level,
                                              std::uint32_t in_eax = 0,
                                              std::uint32_t in_ebx = 0,
                                              std::uint32_t in_ecx = 0,
                                              std::uint32_t in_edx = 0) {

	  std::array<std::uint32_t, 4> regs = { in_eax,in_ebx,in_ecx,in_edx };

	  std::int32_t* regs_ptr = reinterpret_cast<std::int32_t*>(regs.data());
      __cpuid(regs_ptr,
              (std::int32_t)level);

/*
      if (!(regs[ct::eax] || regs[ct::ebx] || regs[ct::ecx] || regs[ct::edx])) {

        return regs;
      }*/

      return regs;

    }

  };

};

#endif /* COMPASS_CT_COMP_MSVC */
#endif /* COMPASS_CT_MSVC_IMPL_H_ */
<commit_msg>fixed cpuid use with visual studio<commit_after>#ifndef COMPASS_CT_MSVC_IMPL_H_

#include "detail/ct/detect_compiler.hpp"

#ifdef COMPASS_CT_COMP_MSVC

#define COMPASS_CT_MSVC_IMPL_H_

#include "intrin.h"

#include <array>
#include <bitset>
#include <cstdint>

#include "detail/tags.hpp"
#include "detail/definitions.hpp"

namespace compass {

  namespace runtime {

    static std::array<std::uint32_t, 4> cpuid(std::uint32_t in_eax = 0,
                                              std::uint32_t in_ebx = 0,
                                              std::uint32_t in_ecx = 0,
                                              std::uint32_t in_edx = 0) {

	  std::array<std::uint32_t, 4> regs = { in_eax,in_ebx,in_ecx,in_edx };

	  std::int32_t* regs_ptr = reinterpret_cast<std::int32_t*>(regs.data());
      __cpuidex(regs_ptr,
				(std::int32_t)in_eax,
		  (std::int32_t)in_ecx
		  );

      return regs;

    }

  };

};

#endif /* COMPASS_CT_COMP_MSVC */
#endif /* COMPASS_CT_MSVC_IMPL_H_ */
<|endoftext|>


<commit_before>//
//  fiber_group.hpp
//  fibio
//
//  Created by Chen Xu on 14-3-20.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#ifndef fibio_fiber_group_hpp
#define fibio_fiber_group_hpp

#include <list>
#include <algorithm>
#include <fibio/fibers/fiber.hpp>
#include <fibio/fibers/shared_mutex.hpp>

namespace fibio { namespace fibers {
    /// fiber_group
    class fiber_group {
    private:
        /// fiber_group is non-copyable
        fiber_group(fiber_group const&)=delete;
        fiber_group& operator=(fiber_group const&)=delete;

    public:
        /// constructor
        fiber_group() {}

        /// destructor
        ~fiber_group() {
            for(std::list<fiber*>::iterator it=fibers_.begin(), end=fibers_.end(); it!=end; ++it) {
                delete *it;
            }
        }

        /**
         * check if the current fiber is in the fiber group
         */
        bool is_this_fiber_in() {
            fiber::id id = this_fiber::get_id();
            shared_lock<shared_timed_mutex> guard(m_);
            for(std::list<fiber*>::iterator it=fibers_.begin(),end=fibers_.end(); it!=end; ++it) {
                if ((*it)->get_id() == id)
                    return true;
            }
            return false;
        }

        /**
         * check if the given fiber is in the fiber group
         */
        bool is_fiber_in(fiber* thrd) {
            if(thrd) {
                fiber::id id = thrd->get_id();
                shared_lock<shared_timed_mutex> guard(m_);
                for(std::list<fiber*>::iterator it=fibers_.begin(),end=fibers_.end(); it!=end; ++it) {
                    if ((*it)->get_id() == id)
                        return true;
                }
                return false;
            } else {
                return false;
            }
        }

        /**
         * create a new fiber in the fiber group
         */
        template<typename Fn, typename... Args>
        fiber* create_fiber(Fn &&fn, Args&&... args)
        {
            lock_guard<shared_timed_mutex> guard(m_);
            std::unique_ptr<fiber> new_fiber(new fiber(std::forward<Fn>(fn), std::forward<Args>(args)...));
            fibers_.push_back(new_fiber.get());
            return new_fiber.release();
        }

        /**
         * add an existing fiber into the fiber group
         */
        void add_fiber(fiber* thrd) {
            if(thrd) {
                lock_guard<shared_timed_mutex> guard(m_);
                fibers_.push_back(thrd);
            }
        }

        /**
         * remove a fiber from the fiber group
         */
        void remove_fiber(fiber* thrd) {
            lock_guard<shared_timed_mutex> guard(m_);
            std::list<fiber*>::iterator const it=std::find(fibers_.begin(),fibers_.end(),thrd);
            if(it!=fibers_.end()) {
                fibers_.erase(it);
            }
        }

        /**
         * wait until all fibers exit
         */
        void join_all() {
            shared_lock<shared_timed_mutex> guard(m_);

            for(std::list<fiber*>::iterator it=fibers_.begin(),end=fibers_.end(); it!=end; ++it) {
                if ((*it)->joinable())
                    (*it)->join();
            }
        }

        /**
         * returns the number of fibers in the group
         */
        size_t size() const {
            shared_lock<shared_timed_mutex> guard(m_);
            return fibers_.size();
        }

    private:
        std::list<fiber*> fibers_;
        mutable shared_timed_mutex m_;
    };
}}  // End of namespace fibio::fibers

namespace fibio {
    using fibers::fiber_group;
}   // End of namespace fibio

#endif
<commit_msg>join_all before destruction<commit_after>//
//  fiber_group.hpp
//  fibio
//
//  Created by Chen Xu on 14-3-20.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#ifndef fibio_fiber_group_hpp
#define fibio_fiber_group_hpp

#include <list>
#include <algorithm>
#include <fibio/fibers/fiber.hpp>
#include <fibio/fibers/shared_mutex.hpp>

namespace fibio { namespace fibers {
    /// fiber_group
    class fiber_group {
    private:
        /// fiber_group is non-copyable
        fiber_group(fiber_group const&)=delete;
        fiber_group& operator=(fiber_group const&)=delete;

    public:
        /// constructor
        fiber_group() {}

        /// destructor
        ~fiber_group() {
            join_all();
            for(std::list<fiber*>::iterator it=fibers_.begin(), end=fibers_.end(); it!=end; ++it) {
                delete *it;
            }
        }

        /**
         * check if the current fiber is in the fiber group
         */
        bool is_this_fiber_in() {
            fiber::id id = this_fiber::get_id();
            shared_lock<shared_timed_mutex> guard(m_);
            for(std::list<fiber*>::iterator it=fibers_.begin(),end=fibers_.end(); it!=end; ++it) {
                if ((*it)->get_id() == id)
                    return true;
            }
            return false;
        }

        /**
         * check if the given fiber is in the fiber group
         */
        bool is_fiber_in(fiber* thrd) {
            if(thrd) {
                fiber::id id = thrd->get_id();
                shared_lock<shared_timed_mutex> guard(m_);
                for(std::list<fiber*>::iterator it=fibers_.begin(),end=fibers_.end(); it!=end; ++it) {
                    if ((*it)->get_id() == id)
                        return true;
                }
                return false;
            } else {
                return false;
            }
        }

        /**
         * create a new fiber in the fiber group
         */
        template<typename Fn, typename... Args>
        fiber* create_fiber(Fn &&fn, Args&&... args)
        {
            lock_guard<shared_timed_mutex> guard(m_);
            std::unique_ptr<fiber> new_fiber(new fiber(std::forward<Fn>(fn), std::forward<Args>(args)...));
            fibers_.push_back(new_fiber.get());
            return new_fiber.release();
        }

        /**
         * add an existing fiber into the fiber group
         */
        void add_fiber(fiber* thrd) {
            if(thrd) {
                lock_guard<shared_timed_mutex> guard(m_);
                fibers_.push_back(thrd);
            }
        }

        /**
         * remove a fiber from the fiber group
         */
        void remove_fiber(fiber* thrd) {
            lock_guard<shared_timed_mutex> guard(m_);
            std::list<fiber*>::iterator const it=std::find(fibers_.begin(),fibers_.end(),thrd);
            if(it!=fibers_.end()) {
                fibers_.erase(it);
            }
        }

        /**
         * wait until all fibers exit
         */
        void join_all() {
            shared_lock<shared_timed_mutex> guard(m_);

            for(std::list<fiber*>::iterator it=fibers_.begin(),end=fibers_.end(); it!=end; ++it) {
                if ((*it)->joinable())
                    (*it)->join();
            }
        }

        /**
         * returns the number of fibers in the group
         */
        size_t size() const {
            shared_lock<shared_timed_mutex> guard(m_);
            return fibers_.size();
        }

    private:
        std::list<fiber*> fibers_;
        mutable shared_timed_mutex m_;
    };
}}  // End of namespace fibio::fibers

namespace fibio {
    using fibers::fiber_group;
}   // End of namespace fibio

#endif
<|endoftext|>


<commit_before>
#include "Gameboy.hpp"

#include "OpenGLWindow.hpp"
#include "DbWindow.hpp"
#include "registerAddr.hpp"

#include "Cpu.hpp"
#include "Gpu.hpp"
#include "Memory.hpp"
#include "Timer.hpp"
#include "Audio.hpp"

void setLowBit(Memory *memory, uint16_t addr, uint8_t bit)
{
	memory->write_byte(addr, (uint8_t)((0x01 << bit) ^ memory->read_byte(addr)), true);
}

void setHightBit(Memory *memory, uint16_t addr, uint8_t bit)
{
	memory->write_byte(addr, (uint8_t)((0x01 << bit) | memory->read_byte(addr)), true);
}

Gameboy::Gameboy(const char *path) :
	_window(OpenGLWindow::Instance())
	, _windowDebug(nullptr)
	, _thread(nullptr)
	, _romPath(path)
{
	_stepMode.store(false);
	_willRun.store(false);

	connect(_window, &OpenGLWindow::openRomSign, this, &Gameboy::openRomSlot);
	connect(_window, &OpenGLWindow::gbDbSign, this, &Gameboy::gbDbSlot);
	connect(_window, &OpenGLWindow::keyPressSign, this, &Gameboy::KeyPress);
	connect(_window, &OpenGLWindow::keyReleaseSign, this, &Gameboy::KeyRelease);
	connect(_window, &OpenGLWindow::gbTypeSign, this, &Gameboy::gbTypeSlot);
	connect(_window, &OpenGLWindow::gbComPlay, this, &Gameboy::switchPlaySlot);
	connect(_window, &OpenGLWindow::gbComPause, this, &Gameboy::switchPauseSlot);
	connect(_window, &OpenGLWindow::gbComStop, this, &Gameboy::resetPressedSlot);
	connect(_window, &OpenGLWindow::gbSoundSign, this, &Gameboy::soundSlot);

	_window->show();
	_window->setWindowTitle("GBmu");
#ifdef DEBUG
	gbDbSlot(); // Open Debug window. WARNING: Peux generer SGFAULT random
	reset();
#endif
}

Gameboy::~Gameboy()
{
	this->_memory->saverom();
	delete this->_windowDebug;
	this->stopThread();
}

void	Gameboy::stopThread()
{
	_stepMode.store(true);
	_willRun.store(false);
	if (_thread)
	{
		_thread->join();
		delete _thread;
		_thread = nullptr;
	}
}

void	Gameboy::gstep()
{
	step();
	if (isBreakpoint(_cpu->_cpuRegister.PC))
		_stepMode.store(true);
}

void	Gameboy::run()
{
	while (_willRun.load())
	{
		if (!_stepMode.load())
		{
			gstep();
		}
	}
}

void	Gameboy::reset(void)
{
	if (_willRun.load())
	{
		stopThread();
	}

	if (_romPath.length())
	{
		this->_memory->reset();
		this->_memory->setAudio(_audio);
		this->_clock->reset();
		this->_audio->reset(_memory->getRomType() == GBC);
		this->_cyclesAcc = 0;
		if (_memory->loadRom(_romPath.c_str(), this->_hardware) == 0)
		{
			htype		hardRom;
			hardRom = (this->_hardware == AUTO) ? this->_memory->getRomType() : this->_hardware;
			this->_cpu->init(hardRom);
			this->_gpu->init(); // TODO pour passer hardware au gpu: this->_gpu->init(hardRom)
			_window->setWindowTitle(_memory->romTitle());
			_willRun.store(true);
			_thread = new std::thread(&Gameboy::run, this);
		}
	}
	else
		std::cerr << "Gameboy: No rom path defined" << std::endl;
}

void	Gameboy::gbTypeSlot(htype hardware)
{
	this->_hardware = hardware;
}

void	Gameboy::stepPressedSlot(unsigned int count)
{
	_stepMode.store(true);
	while (count--) {
		gstep();
		if (isBreakpoint(_cpu->_cpuRegister.PC))
			break ;
	}
}

#include "registerAddr.hpp"
void	Gameboy::framePressedSlot()
{
	_stepMode.store(true);
	bool			cte = true;

	uint16_t	start;
	start = _memory->read_byte(REGISTER_LY);
	while (start == _memory->read_byte(REGISTER_LY) && cte) {
		gstep();
		cte = !isBreakpoint(_cpu->_cpuRegister.PC);
	}
	while (start != _memory->read_byte(REGISTER_LY) && cte) {
		gstep();
		cte = !isBreakpoint(_cpu->_cpuRegister.PC);
	}
}

void	Gameboy::resetPressedSlot()
{
	_stepMode.store(true);
	reset();
}

void	Gameboy::openRomSlot(std::string path)
{
	_romPath = path;
	reset();
	_stepMode.store(false);
}

void	Gameboy::gbDbSlot()
{
	_windowDebug = new DbWindow(&_cpu->_cpuRegister, _memory, &_breakpoints);
	connect(_windowDebug, &DbWindow::stepPressedSign, this, &Gameboy::stepPressedSlot);
	connect(_windowDebug, &DbWindow::framePressedSign, this, &Gameboy::framePressedSlot);
	connect(_windowDebug, &DbWindow::runPressedSign, this, &Gameboy::switchStepModeSlot);
	connect(_windowDebug, &DbWindow::resetPressedSign, this, &Gameboy::resetPressedSlot);
	connect(_windowDebug, &DbWindow::openPressedSign, this, &Gameboy::openRomSlot);

	connect(_windowDebug, &DbWindow::bpAddSign, this, &Gameboy::addBreakpointSlot);
	connect(_windowDebug, &DbWindow::bpDelSign, this, &Gameboy::delBreakpointSlot);

	_windowDebug->show();
	_stepMode.store(true);
}

void	Gameboy::switchPlaySlot(void)
{
	_stepMode.store(false);
}

void	Gameboy::switchPauseSlot(void)
{
	_stepMode.store(true);
}

void	Gameboy::soundSlot(bool on)
{
	_audio->enable(on);
}

void	Gameboy::switchStepModeSlot(void)
{
	_stepMode.store(!_stepMode.load());
}

void	Gameboy::addBreakpointSlot(uint16_t addr)
{
	auto it = std::find(_breakpoints.begin(), _breakpoints.end(), addr);

	if (it == _breakpoints.end())
		_breakpoints.push_back(addr);
}

void	Gameboy::delBreakpointSlot(uint16_t addr)
{
	_breakpoints.remove(addr);
}

bool	Gameboy::isBreakpoint(uint16_t addr)
{
	auto it = std::find(_breakpoints.begin(), _breakpoints.end(), addr);

	return (it != _breakpoints.end());
}

void	Gameboy::KeyPress(int key)
{
	switch(key)
	{
		case RIGHT:
			_memory->key[0] &= 0x0e;
			setLowBit(_memory, REGISTER_INPUT, 0);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case A_BUTTON:
			_memory->key[1] &= 0x0e;
			setLowBit(_memory, REGISTER_INPUT, 0);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case LEFT:
			_memory->key[0] &= 0x0D;
			setLowBit(_memory, REGISTER_INPUT, 1);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case B_BUTTON:
			_memory->key[1] &= 0x0D;
			setLowBit(_memory, REGISTER_INPUT, 1);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case UP:
			_memory->key[0] &= 0x0B;
			setLowBit(_memory, REGISTER_INPUT, 2);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case SELECT:
			_memory->key[1] &= 0x0B;
			setLowBit(_memory, REGISTER_INPUT, 2);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case DOWN:
			_memory->key[0] &= 0x07;
			setLowBit(_memory, REGISTER_INPUT, 3);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case START:
			_memory->key[1] &= 0x07;
			setLowBit(_memory, REGISTER_INPUT, 3);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
	}
}

void	Gameboy::KeyRelease(int key)
{
	switch(key)
	{
		case RIGHT:
			_memory->key[0] |= 0x01;
			setHightBit(_memory, REGISTER_INPUT, 0);
			_cpu->setStop(false);
			break;
		case A_BUTTON:
			_memory->key[1] |= 0x01;
			setHightBit(_memory, REGISTER_INPUT, 0);
			_cpu->setStop(false);
			break;
		case LEFT:
			_memory->key[0] |= 0x02;
			setHightBit(_memory, REGISTER_INPUT, 1);
			_cpu->setStop(false);
			break;
		case B_BUTTON:
			_memory->key[1] |= 0x02;
			setHightBit(_memory, REGISTER_INPUT, 1);
			_cpu->setStop(false);
			break;
		case UP:
			_memory->key[0] |= 0x04;
			setHightBit(_memory, REGISTER_INPUT, 2);
			_cpu->setStop(false);
			break;
		case SELECT:
			_memory->key[1] |= 0x04;
			setHightBit(_memory, REGISTER_INPUT, 2);
			_cpu->setStop(false);
			break;
		case DOWN:
			_memory->key[0] |= 0x08;
			setHightBit(_memory, REGISTER_INPUT, 3);
			_cpu->setStop(false);
			break;
		case START:
			_memory->key[1] |= 0x08;
			setHightBit(_memory, REGISTER_INPUT, 3);
			_cpu->setStop(false);
			break;
	}
}

<commit_msg>reinitialisation affichage si bad ROM<commit_after>
#include "Gameboy.hpp"

#include "OpenGLWindow.hpp"
#include "DbWindow.hpp"
#include "registerAddr.hpp"

#include "Cpu.hpp"
#include "Gpu.hpp"
#include "Memory.hpp"
#include "Timer.hpp"
#include "Audio.hpp"

void setLowBit(Memory *memory, uint16_t addr, uint8_t bit)
{
	memory->write_byte(addr, (uint8_t)((0x01 << bit) ^ memory->read_byte(addr)), true);
}

void setHightBit(Memory *memory, uint16_t addr, uint8_t bit)
{
	memory->write_byte(addr, (uint8_t)((0x01 << bit) | memory->read_byte(addr)), true);
}

Gameboy::Gameboy(const char *path) :
	_window(OpenGLWindow::Instance())
	, _windowDebug(nullptr)
	, _thread(nullptr)
	, _romPath(path)
{
	_stepMode.store(false);
	_willRun.store(false);

	connect(_window, &OpenGLWindow::openRomSign, this, &Gameboy::openRomSlot);
	connect(_window, &OpenGLWindow::gbDbSign, this, &Gameboy::gbDbSlot);
	connect(_window, &OpenGLWindow::keyPressSign, this, &Gameboy::KeyPress);
	connect(_window, &OpenGLWindow::keyReleaseSign, this, &Gameboy::KeyRelease);
	connect(_window, &OpenGLWindow::gbTypeSign, this, &Gameboy::gbTypeSlot);
	connect(_window, &OpenGLWindow::gbComPlay, this, &Gameboy::switchPlaySlot);
	connect(_window, &OpenGLWindow::gbComPause, this, &Gameboy::switchPauseSlot);
	connect(_window, &OpenGLWindow::gbComStop, this, &Gameboy::resetPressedSlot);
	connect(_window, &OpenGLWindow::gbSoundSign, this, &Gameboy::soundSlot);

	_window->show();
	_window->setWindowTitle("GBmu");
#ifdef DEBUG
	gbDbSlot(); // Open Debug window. WARNING: Peux generer SGFAULT random
	reset();
#endif
}

Gameboy::~Gameboy()
{
	this->_memory->saverom();
	delete this->_windowDebug;
	this->stopThread();
}

void	Gameboy::stopThread()
{
	_stepMode.store(true);
	_willRun.store(false);
	if (_thread)
	{
		_thread->join();
		delete _thread;
		_thread = nullptr;
	}
}

void	Gameboy::gstep()
{
	step();
	if (isBreakpoint(_cpu->_cpuRegister.PC))
		_stepMode.store(true);
}

void	Gameboy::run()
{
	while (_willRun.load())
	{
		if (!_stepMode.load())
		{
			gstep();
		}
	}
}

void	Gameboy::reset(void)
{
	if (_willRun.load())
	{
		stopThread();
	}

	if (_romPath.length())
	{
		this->_memory->reset();
		this->_memory->setAudio(_audio);
		this->_clock->reset();
		this->_audio->reset(_memory->getRomType() == GBC);
		this->_cyclesAcc = 0;
		if (_memory->loadRom(_romPath.c_str(), this->_hardware) == 0)
		{
			htype		hardRom;
			hardRom = (this->_hardware == AUTO) ? this->_memory->getRomType() : this->_hardware;
			this->_cpu->init(hardRom);
			this->_gpu->init(); // TODO pour passer hardware au gpu: this->_gpu->init(hardRom)
			_window->setWindowTitle(_memory->romTitle());
			_willRun.store(true);
			_thread = new std::thread(&Gameboy::run, this);
		}
		else
			_window->initialize();
	}
	else
		std::cerr << "Gameboy: No rom path defined" << std::endl;
}

void	Gameboy::gbTypeSlot(htype hardware)
{
	this->_hardware = hardware;
}

void	Gameboy::stepPressedSlot(unsigned int count)
{
	_stepMode.store(true);
	while (count--) {
		gstep();
		if (isBreakpoint(_cpu->_cpuRegister.PC))
			break ;
	}
}

#include "registerAddr.hpp"
void	Gameboy::framePressedSlot()
{
	_stepMode.store(true);
	bool			cte = true;

	uint16_t	start;
	start = _memory->read_byte(REGISTER_LY);
	while (start == _memory->read_byte(REGISTER_LY) && cte) {
		gstep();
		cte = !isBreakpoint(_cpu->_cpuRegister.PC);
	}
	while (start != _memory->read_byte(REGISTER_LY) && cte) {
		gstep();
		cte = !isBreakpoint(_cpu->_cpuRegister.PC);
	}
}

void	Gameboy::resetPressedSlot()
{
	_stepMode.store(true);
	reset();
}

void	Gameboy::openRomSlot(std::string path)
{
	_romPath = path;
	reset();
	_stepMode.store(false);
}

void	Gameboy::gbDbSlot()
{
	_windowDebug = new DbWindow(&_cpu->_cpuRegister, _memory, &_breakpoints);
	connect(_windowDebug, &DbWindow::stepPressedSign, this, &Gameboy::stepPressedSlot);
	connect(_windowDebug, &DbWindow::framePressedSign, this, &Gameboy::framePressedSlot);
	connect(_windowDebug, &DbWindow::runPressedSign, this, &Gameboy::switchStepModeSlot);
	connect(_windowDebug, &DbWindow::resetPressedSign, this, &Gameboy::resetPressedSlot);
	connect(_windowDebug, &DbWindow::openPressedSign, this, &Gameboy::openRomSlot);

	connect(_windowDebug, &DbWindow::bpAddSign, this, &Gameboy::addBreakpointSlot);
	connect(_windowDebug, &DbWindow::bpDelSign, this, &Gameboy::delBreakpointSlot);

	_windowDebug->show();
	_stepMode.store(true);
}

void	Gameboy::switchPlaySlot(void)
{
	_stepMode.store(false);
}

void	Gameboy::switchPauseSlot(void)
{
	_stepMode.store(true);
}

void	Gameboy::soundSlot(bool on)
{
	_audio->enable(on);
}

void	Gameboy::switchStepModeSlot(void)
{
	_stepMode.store(!_stepMode.load());
}

void	Gameboy::addBreakpointSlot(uint16_t addr)
{
	auto it = std::find(_breakpoints.begin(), _breakpoints.end(), addr);

	if (it == _breakpoints.end())
		_breakpoints.push_back(addr);
}

void	Gameboy::delBreakpointSlot(uint16_t addr)
{
	_breakpoints.remove(addr);
}

bool	Gameboy::isBreakpoint(uint16_t addr)
{
	auto it = std::find(_breakpoints.begin(), _breakpoints.end(), addr);

	return (it != _breakpoints.end());
}

void	Gameboy::KeyPress(int key)
{
	switch(key)
	{
		case RIGHT:
			_memory->key[0] &= 0x0e;
			setLowBit(_memory, REGISTER_INPUT, 0);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case A_BUTTON:
			_memory->key[1] &= 0x0e;
			setLowBit(_memory, REGISTER_INPUT, 0);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case LEFT:
			_memory->key[0] &= 0x0D;
			setLowBit(_memory, REGISTER_INPUT, 1);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case B_BUTTON:
			_memory->key[1] &= 0x0D;
			setLowBit(_memory, REGISTER_INPUT, 1);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case UP:
			_memory->key[0] &= 0x0B;
			setLowBit(_memory, REGISTER_INPUT, 2);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case SELECT:
			_memory->key[1] &= 0x0B;
			setLowBit(_memory, REGISTER_INPUT, 2);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case DOWN:
			_memory->key[0] &= 0x07;
			setLowBit(_memory, REGISTER_INPUT, 3);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
		case START:
			_memory->key[1] &= 0x07;
			setLowBit(_memory, REGISTER_INPUT, 3);
			setHightBit(_memory, REGISTER_IF, 4);
			_cpu->setStop(false);
			break;
	}
}

void	Gameboy::KeyRelease(int key)
{
	switch(key)
	{
		case RIGHT:
			_memory->key[0] |= 0x01;
			setHightBit(_memory, REGISTER_INPUT, 0);
			_cpu->setStop(false);
			break;
		case A_BUTTON:
			_memory->key[1] |= 0x01;
			setHightBit(_memory, REGISTER_INPUT, 0);
			_cpu->setStop(false);
			break;
		case LEFT:
			_memory->key[0] |= 0x02;
			setHightBit(_memory, REGISTER_INPUT, 1);
			_cpu->setStop(false);
			break;
		case B_BUTTON:
			_memory->key[1] |= 0x02;
			setHightBit(_memory, REGISTER_INPUT, 1);
			_cpu->setStop(false);
			break;
		case UP:
			_memory->key[0] |= 0x04;
			setHightBit(_memory, REGISTER_INPUT, 2);
			_cpu->setStop(false);
			break;
		case SELECT:
			_memory->key[1] |= 0x04;
			setHightBit(_memory, REGISTER_INPUT, 2);
			_cpu->setStop(false);
			break;
		case DOWN:
			_memory->key[0] |= 0x08;
			setHightBit(_memory, REGISTER_INPUT, 3);
			_cpu->setStop(false);
			break;
		case START:
			_memory->key[1] |= 0x08;
			setHightBit(_memory, REGISTER_INPUT, 3);
			_cpu->setStop(false);
			break;
	}
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_MEMORY_FEATURESET_HPP
#define MAPNIK_MEMORY_FEATURESET_HPP

// mapnik
#include <mapnik/memory_datasource.hpp>

// boost
#include <boost/utility.hpp>

namespace mapnik {

class memory_featureset : public Featureset, private boost::noncopyable
{
public:
    memory_featureset(box2d<double> const& bbox, memory_datasource const& ds)
        : bbox_(bbox),
          pos_(ds.features_.begin()),
          end_(ds.features_.end())
    {}

    memory_featureset(box2d<double> const& bbox, std::vector<feature_ptr> const& features)
        : bbox_(bbox),
          pos_(features.begin()),
          end_(features.end())
    {}

    virtual ~memory_featureset() {}

    feature_ptr next()
    {
        while (pos_ != end_)
        {
            for  (unsigned i=0; i<(*pos_)->num_geometries();++i) {
                geometry_type & geom = (*pos_)->get_geometry(i);
#ifdef MAPNIK_DEBUG
                std::clog << "bbox_=" << bbox_ << ", geom.envelope=" << geom.envelope() << "\n";
#endif
                if (bbox_.intersects(geom.envelope()))
                {
                    return *pos_++;
                }
            }
            ++pos_;
        }

        return feature_ptr();
    }

private:
    box2d<double> bbox_;
    std::vector<feature_ptr>::const_iterator pos_;
    std::vector<feature_ptr>::const_iterator end_;
};
}

#endif // MAPNIK_MEMORY_FEATURESET_HPP
<commit_msg>+ base class already derived from boost::noncopyable<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_MEMORY_FEATURESET_HPP
#define MAPNIK_MEMORY_FEATURESET_HPP

// mapnik
#include <mapnik/memory_datasource.hpp>

// boost
#include <boost/utility.hpp>

namespace mapnik {

class memory_featureset : public Featureset
{
public:
    memory_featureset(box2d<double> const& bbox, memory_datasource const& ds)
        : bbox_(bbox),
          pos_(ds.features_.begin()),
          end_(ds.features_.end())
    {}

    memory_featureset(box2d<double> const& bbox, std::vector<feature_ptr> const& features)
        : bbox_(bbox),
          pos_(features.begin()),
          end_(features.end())
    {}

    virtual ~memory_featureset() {}

    feature_ptr next()
    {
        while (pos_ != end_)
        {
            for  (unsigned i=0; i<(*pos_)->num_geometries();++i) {
                geometry_type & geom = (*pos_)->get_geometry(i);
#ifdef MAPNIK_DEBUG
                std::clog << "bbox_=" << bbox_ << ", geom.envelope=" << geom.envelope() << "\n";
#endif
                if (bbox_.intersects(geom.envelope()))
                {
                    return *pos_++;
                }
            }
            ++pos_;
        }

        return feature_ptr();
    }

private:
    box2d<double> bbox_;
    std::vector<feature_ptr>::const_iterator pos_;
    std::vector<feature_ptr>::const_iterator end_;
};
}

#endif // MAPNIK_MEMORY_FEATURESET_HPP
<|endoftext|>


<commit_before>#ifndef PROTO_RPC_MESSAGE_CODING
#define PROTO_RPC_MESSAGE_CODING

#include <iostream>
#include <utility> // for pair

#include <boost/asio/read_until.hpp> // for is_match_condition
#include <boost/asio/streambuf.hpp>

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/message.h>

#include <proto_rpc/namespace.hpp>

namespace proto_rpc {

static inline void encode(const gp::Message &message, ba::streambuf &buffer) {
  // triple-wrapping of the buffer is required ...
  std::ostream os(&buffer);
  gp::io::OstreamOutputStream oos(&os);
  gp::io::CodedOutputStream output(&oos);

  // write the message length and then the message data to the buffer
  output.WriteVarint32(message.ByteSize());
  message.SerializeWithCachedSizes(&output);
}

class Decode {
public:
  Decode(gp::Message &message) : message_(message) {}

  virtual ~Decode() {}

  template < typename Iterator >
  std::pair< Iterator, bool > operator()(Iterator begin, Iterator end) const {
    // convert the given range to an input stream
    gp::io::CodedInputStream input(reinterpret_cast< const gp::uint8 * >(&(*begin)),
                                   static_cast< int >(end - begin));

    // read the message length
    gp::uint32 message_size;
    if (!input.ReadVarint32(&message_size)) {
      return std::pair< Iterator, bool >(begin, false);
    }

    // check if the buffer length is enough to be read message data
    {
      const void *data;
      int size;
      input.GetDirectBufferPointer(&data, &size);
      if (static_cast< int >(message_size) > size) {
        return std::pair< Iterator, bool >(begin, false);
      }
    }

    // read the message data
    input.PushLimit(message_size);
    message_.ParsePartialFromCodedStream(&input);
    return std::pair< Iterator, bool >(begin + input.CurrentPosition(), true);
  }

private:
  gp::Message &message_;
};
}

// export Decode to boost.asio
namespace boost {
namespace asio {
template <> struct is_match_condition< proto_rpc::Decode > : public boost::true_type {};
}
}

#endif // PROTO_RPC_MESSAGE_CODING<commit_msg>bugfix<commit_after>#ifndef PROTO_RPC_MESSAGE_CODING
#define PROTO_RPC_MESSAGE_CODING

#include <iostream>
#include <utility> // for pair

#include <boost/asio/read_until.hpp> // for is_match_condition
#include <boost/asio/streambuf.hpp>

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/message.h>

#include <proto_rpc/namespace.hpp>

namespace proto_rpc {

static inline void encode(const gp::Message &message, ba::streambuf &buffer) {
  // triple-wrapping of the buffer is required ...
  std::ostream os(&buffer);
  gp::io::OstreamOutputStream oos(&os);
  gp::io::CodedOutputStream output(&oos);

  // write the message length and then the message data to the buffer
  output.WriteVarint32(message.ByteSize());
  message.SerializeWithCachedSizes(&output);
}

class Decode {
public:
  Decode(gp::Message &message) : message_(message) {}

  virtual ~Decode() {}

  template < typename Iterator >
  std::pair< Iterator, bool > operator()(Iterator begin, Iterator end) const {
    // convert the given range to an input stream
    gp::io::CodedInputStream input(reinterpret_cast< const gp::uint8 * >(&(*begin)),
                                   static_cast< int >(end - begin));

    // read the message length
    gp::uint32 message_size;
    if (!input.ReadVarint32(&message_size)) {
      return std::pair< Iterator, bool >(begin, false);
    }

    // check if the buffer length is enough to be read message data
    {
      const void *data;
      int size;
      if (!input.GetDirectBufferPointer(&data, &size)) {
        size = 0;
      }
      if (static_cast< int >(message_size) > size) {
        return std::pair< Iterator, bool >(begin, false);
      }
    }

    // read the message data
    input.PushLimit(message_size);
    message_.ParsePartialFromCodedStream(&input);
    return std::pair< Iterator, bool >(begin + input.CurrentPosition(), true);
  }

private:
  gp::Message &message_;
};
}

// export Decode to boost.asio
namespace boost {
namespace asio {
template <> struct is_match_condition< proto_rpc::Decode > : public boost::true_type {};
}
}

#endif // PROTO_RPC_MESSAGE_CODING<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <string.h>
#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.h"
#include "tensorflow/contrib/lite/toco/model.h"
#include "tensorflow/contrib/lite/toco/runtime/types.h"
#include "tensorflow/contrib/lite/toco/tooling_util.h"
#include "tensorflow/core/platform/logging.h"

namespace toco {

bool ResolveConstantUnaryOperator::Run(Model* model, std::size_t op_index) {
  const auto unary_it = model->operators.begin() + op_index;
  const auto* unary_op = unary_it->get();
  // Test for unary ops of types that we know how to resolve
  if (unary_op->type != OperatorType::kCast &&
      unary_op->type != OperatorType::kNeg &&
      unary_op->type != OperatorType::kTensorFlowRsqrt &&
      unary_op->type != OperatorType::kTensorFlowSqrt &&
      unary_op->type != OperatorType::kTensorFlowSquare &&
      unary_op->type != OperatorType::kTensorFlowSum &&
      unary_op->type != OperatorType::kTensorFlowMin &&
      unary_op->type != OperatorType::kTensorFlowMax &&
      unary_op->type != OperatorType::kTensorFlowReshape) {
    return false;
  }
  // Check if the input is a constant parameter.
  if (!IsConstantParameterArray(*model, unary_op->inputs[0])) {
    return false;
  }

  // if the unary op involves a tensor required by a rnn state, ignore it
  for (const auto& rnn_state : model->flags.rnn_states()) {
    if (unary_op->inputs[0] == rnn_state.back_edge_source_array()) {
      return false;
    }
    if (unary_op->inputs[0] == rnn_state.state_array()) {
      return false;
    }
  }

  auto& output_array = model->GetArray(unary_op->outputs[0]);
  if (!output_array.has_shape()) {
    // Yield until the output array dims have been resolved.
    return false;
  }

  // At the moment we don't want to care about fused activation functions.
  // The idea is that we should do the present constants-propagation before
  // activation functions get fused.
  if (unary_op->fused_activation_function !=
      FusedActivationFunctionType::kNone) {
    AddMessageF(
        "Not resolving constant %s "
        " because it has a fused activation function",
        LogName(*unary_op));
    return false;
  }

  const auto& input_array = model->GetArray(unary_op->inputs[0]);
  // We have already tested above for existence of buffers (synonymous to being
  // a constant param).
  CHECK(input_array.buffer);
  std::vector<DataType<ArrayDataType::kFloat>> const* input_float_data;
  if (unary_op->type == OperatorType::kCast) {
    CastOperator const* cast_op = static_cast<CastOperator const*>(unary_op);
    if (cast_op->dst_data_type != ArrayDataType::kFloat) {
      AddMessageF(
          "Not resolving constant %s because we currently only support casting "
          "to float",
          LogName(*unary_op));
      return false;
    }
    if (cast_op->src_data_type != input_array.buffer->type) {
      AddMessageF(
          "Not resolving constant %s because cast op source type does not "
          "match input type",
          LogName(*unary_op));
    }
  } else {
    if (input_array.buffer->type != ArrayDataType::kFloat) {
      return false;
    }
    input_float_data = &(input_array.GetBuffer<ArrayDataType::kFloat>().data);
  }

  // Create a float buffer on the output array, which are always constant.
  const Shape& output_shape = output_array.shape();
  const int output_dims_count = output_shape.dimensions_count();
  const int output_buffer_size = RequiredBufferSizeForShape(output_shape);
  auto& output_float_data =
      output_array.GetMutableBuffer<ArrayDataType::kFloat>().data;
  output_float_data.resize(output_buffer_size);

  const Shape& input_shape = input_array.shape();
  const int input_buffer_size = RequiredBufferSizeForShape(input_shape);
  if (unary_op->type == OperatorType::kCast) {
    for (int i = 0; i < output_buffer_size; i++) {
      float outval = 0.0f;
      if (input_array.buffer->type == ArrayDataType::kFloat) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kFloat>().data[i]);
      } else if (input_array.buffer->type == ArrayDataType::kUint8) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kUint8>().data[i]);
      } else if (input_array.buffer->type == ArrayDataType::kInt32) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kInt32>().data[i]);
      } else if (input_array.buffer->type == ArrayDataType::kInt64) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kInt64>().data[i]);
      } else {
        LOG(FATAL) << "Unsupported cast op input type";
      }
      output_float_data[i] = outval;
    }
  } else if (unary_op->type == OperatorType::kTensorFlowReshape) {
    CHECK(input_buffer_size == output_buffer_size);
    memcpy(output_float_data.data(), (*input_float_data).data(),
           output_buffer_size * sizeof(output_float_data[0]));
  } else if (unary_op->type == OperatorType::kTensorFlowSum) {
    // At the moment only full reduction across all dimensions is supported.
    float sum = 0.f;
    for (int i = 0; i < input_buffer_size; i++) {
      sum += (*input_float_data)[i];
    }
    for (int i = 0; i < output_buffer_size; ++i) {
      output_float_data[i] = sum;
    }
  } else if (unary_op->type == OperatorType::kTensorFlowMin) {
    // At the moment only full reduction across all dimensions is supported.
    // TODO(starka): Output should not be padded.
    for (int i = 0; i < output_dims_count; i++) {
      CHECK_EQ(output_shape.dims(i), 1);
    }
    float min = (*input_float_data)[0];
    for (int i = 0; i < input_buffer_size; i++) {
      min = std::min(min, (*input_float_data)[i]);
    }
    output_float_data[0] = min;
  } else if (unary_op->type == OperatorType::kTensorFlowMax) {
    // At the moment only full reduction across all dimensions is supported.
    // TODO(starka): Output should not be padded.
    for (int i = 0; i < output_dims_count; i++) {
      CHECK_EQ(output_shape.dims(i), 1);
    }
    float max = (*input_float_data)[0];
    for (int i = 0; i < input_buffer_size; i++) {
      max = std::max(max, (*input_float_data)[i]);
    }
    output_float_data[0] = max;
  } else if (unary_op->type == OperatorType::kNeg ||
             unary_op->type == OperatorType::kTensorFlowRsqrt ||
             unary_op->type == OperatorType::kTensorFlowSqrt ||
             unary_op->type == OperatorType::kTensorFlowSquare) {
    // Element-wise ops. Should have perfectly matching sizes here.
    for (int i = 0; i < output_dims_count; i++) {
      CHECK_EQ(output_shape.dims(i), input_shape.dims(i));
    }

    for (int i = 0; i < output_buffer_size; i++) {
      const float val = (*input_float_data)[i];
      float outval = 0.f;
      if (unary_op->type == OperatorType::kNeg) {
        outval = -val;
      } else if (unary_op->type == OperatorType::kTensorFlowRsqrt) {
        outval = 1.0f / std::sqrt(val);
      } else if (unary_op->type == OperatorType::kTensorFlowSqrt) {
        outval = std::sqrt(val);
      } else if (unary_op->type == OperatorType::kTensorFlowSquare) {
        outval = val * val;
      } else {
        LOG(FATAL) << "should not get here.";
      }
      output_float_data[i] = outval;
    }
  } else {
    LOG(FATAL) << "should not get here.";
  }
  for (const auto& input : unary_op->inputs) {
    if (CountOpsWithInput(*model, input) == 1) {
      model->EraseArray(input);
    }
  }
  AddMessageF("Resolved constant %s to the equivalent constant array",
              LogName(*unary_op));
  model->operators.erase(unary_it);
  return true;
}

}  // namespace toco
<commit_msg>Fixed tf.reduce_sum usage on 2-D tensors.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <string.h>
#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.h"
#include "tensorflow/contrib/lite/toco/model.h"
#include "tensorflow/contrib/lite/toco/runtime/types.h"
#include "tensorflow/contrib/lite/toco/tooling_util.h"
#include "tensorflow/core/platform/logging.h"

namespace toco {

bool ResolveConstantUnaryOperator::Run(Model* model, std::size_t op_index) {
  const auto unary_it = model->operators.begin() + op_index;
  const auto* unary_op = unary_it->get();
  // Test for unary ops of types that we know how to resolve
  if (unary_op->type != OperatorType::kCast &&
      unary_op->type != OperatorType::kNeg &&
      unary_op->type != OperatorType::kTensorFlowRsqrt &&
      unary_op->type != OperatorType::kTensorFlowSqrt &&
      unary_op->type != OperatorType::kTensorFlowSquare &&
      unary_op->type != OperatorType::kTensorFlowSum &&
      unary_op->type != OperatorType::kTensorFlowMin &&
      unary_op->type != OperatorType::kTensorFlowMax &&
      unary_op->type != OperatorType::kTensorFlowReshape) {
    return false;
  }
  // Check if the input is a constant parameter.
  if (!IsConstantParameterArray(*model, unary_op->inputs[0])) {
    return false;
  }

  // if the unary op involves a tensor required by a rnn state, ignore it
  for (const auto& rnn_state : model->flags.rnn_states()) {
    if (unary_op->inputs[0] == rnn_state.back_edge_source_array()) {
      return false;
    }
    if (unary_op->inputs[0] == rnn_state.state_array()) {
      return false;
    }
  }

  auto& output_array = model->GetArray(unary_op->outputs[0]);
  if (!output_array.has_shape()) {
    // Yield until the output array dims have been resolved.
    return false;
  }

  // At the moment we don't want to care about fused activation functions.
  // The idea is that we should do the present constants-propagation before
  // activation functions get fused.
  if (unary_op->fused_activation_function !=
      FusedActivationFunctionType::kNone) {
    AddMessageF(
        "Not resolving constant %s "
        " because it has a fused activation function",
        LogName(*unary_op));
    return false;
  }

  const auto& input_array = model->GetArray(unary_op->inputs[0]);
  // We have already tested above for existence of buffers (synonymous to being
  // a constant param).
  CHECK(input_array.buffer);
  std::vector<DataType<ArrayDataType::kFloat>> const* input_float_data;
  if (unary_op->type == OperatorType::kCast) {
    CastOperator const* cast_op = static_cast<CastOperator const*>(unary_op);
    if (cast_op->dst_data_type != ArrayDataType::kFloat) {
      AddMessageF(
          "Not resolving constant %s because we currently only support casting "
          "to float",
          LogName(*unary_op));
      return false;
    }
    if (cast_op->src_data_type != input_array.buffer->type) {
      AddMessageF(
          "Not resolving constant %s because cast op source type does not "
          "match input type",
          LogName(*unary_op));
    }
  } else {
    if (input_array.buffer->type != ArrayDataType::kFloat) {
      return false;
    }
    input_float_data = &(input_array.GetBuffer<ArrayDataType::kFloat>().data);
  }

  // Create a float buffer on the output array, which are always constant.
  const Shape& output_shape = output_array.shape();
  const int output_dims_count = output_shape.dimensions_count();
  const int output_buffer_size = RequiredBufferSizeForShape(output_shape);
  auto& output_float_data =
      output_array.GetMutableBuffer<ArrayDataType::kFloat>().data;
  output_float_data.resize(output_buffer_size);

  const Shape& input_shape = input_array.shape();
  const int input_buffer_size = RequiredBufferSizeForShape(input_shape);
  if (unary_op->type == OperatorType::kCast) {
    for (int i = 0; i < output_buffer_size; i++) {
      float outval = 0.0f;
      if (input_array.buffer->type == ArrayDataType::kFloat) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kFloat>().data[i]);
      } else if (input_array.buffer->type == ArrayDataType::kUint8) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kUint8>().data[i]);
      } else if (input_array.buffer->type == ArrayDataType::kInt32) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kInt32>().data[i]);
      } else if (input_array.buffer->type == ArrayDataType::kInt64) {
        outval = static_cast<float>(
            input_array.GetBuffer<ArrayDataType::kInt64>().data[i]);
      } else {
        LOG(FATAL) << "Unsupported cast op input type";
      }
      output_float_data[i] = outval;
    }
  } else if (unary_op->type == OperatorType::kTensorFlowReshape) {
    CHECK(input_buffer_size == output_buffer_size);
    memcpy(output_float_data.data(), (*input_float_data).data(),
           output_buffer_size * sizeof(output_float_data[0]));
  } else if (unary_op->type == OperatorType::kTensorFlowSum) {
    CHECK_EQ(unary_op->inputs.size(), 2) << "Sum needs 2 inputs";
    if (!IsConstantParameterArray(*model, unary_op->inputs[1])) {
      AddMessageF("Axis input is non-constant");
      return false;
    }
    auto& axis_array = model->GetArray(unary_op->inputs[1]);
    CHECK(axis_array.data_type == ArrayDataType::kInt32);
    int axis = axis_array.GetBuffer<ArrayDataType::kInt32>().data[0];
    CHECK_LT(axis, input_shape.dimensions_count()) << "Axis out of bounds";

    // We currently only handle reduction on axis 0.
    CHECK_EQ(axis, 0) << "Only reduction along axis 0 is supported";
    // We currently only handle 1-D and 2-D input tensors.
    CHECK_LE(input_shape.dimensions_count(), 2) << "Rank >2 not yet supported";
    // We only support keep_dims=true; shape prop will need to change otherwise.
    auto sum_op = static_cast<const TensorFlowSumOperator*>(unary_op);
    CHECK(sum_op->keep_dims) << "Only keep_dims=true is supported";

    std::vector<int> indices(input_shape.dimensions_count());
    for (int i = 0; i < input_shape.dims(1); ++i) {
      indices[1] = i;
      float sum = 0.f;
      for (int j = 0; j < input_shape.dims(0); ++j) {
        indices[0] = j;
        sum += (*input_float_data)[Offset(input_shape, indices)];
      }
      output_float_data[i] = sum;
    }
  } else if (unary_op->type == OperatorType::kTensorFlowMin) {
    // At the moment only full reduction across all dimensions is supported.
    // TODO(starka): Output should not be padded.
    for (int i = 0; i < output_dims_count; i++) {
      CHECK_EQ(output_shape.dims(i), 1);
    }
    float min = (*input_float_data)[0];
    for (int i = 0; i < input_buffer_size; i++) {
      min = std::min(min, (*input_float_data)[i]);
    }
    output_float_data[0] = min;
  } else if (unary_op->type == OperatorType::kTensorFlowMax) {
    // At the moment only full reduction across all dimensions is supported.
    // TODO(starka): Output should not be padded.
    for (int i = 0; i < output_dims_count; i++) {
      CHECK_EQ(output_shape.dims(i), 1);
    }
    float max = (*input_float_data)[0];
    for (int i = 0; i < input_buffer_size; i++) {
      max = std::max(max, (*input_float_data)[i]);
    }
    output_float_data[0] = max;
  } else if (unary_op->type == OperatorType::kNeg ||
             unary_op->type == OperatorType::kTensorFlowRsqrt ||
             unary_op->type == OperatorType::kTensorFlowSqrt ||
             unary_op->type == OperatorType::kTensorFlowSquare) {
    // Element-wise ops. Should have perfectly matching sizes here.
    for (int i = 0; i < output_dims_count; i++) {
      CHECK_EQ(output_shape.dims(i), input_shape.dims(i));
    }

    for (int i = 0; i < output_buffer_size; i++) {
      const float val = (*input_float_data)[i];
      float outval = 0.f;
      if (unary_op->type == OperatorType::kNeg) {
        outval = -val;
      } else if (unary_op->type == OperatorType::kTensorFlowRsqrt) {
        outval = 1.0f / std::sqrt(val);
      } else if (unary_op->type == OperatorType::kTensorFlowSqrt) {
        outval = std::sqrt(val);
      } else if (unary_op->type == OperatorType::kTensorFlowSquare) {
        outval = val * val;
      } else {
        LOG(FATAL) << "should not get here.";
      }
      output_float_data[i] = outval;
    }
  } else {
    LOG(FATAL) << "should not get here.";
  }
  for (const auto& input : unary_op->inputs) {
    if (CountOpsWithInput(*model, input) == 1) {
      model->EraseArray(input);
    }
  }
  AddMessageF("Resolved constant %s to the equivalent constant array",
              LogName(*unary_op));
  model->operators.erase(unary_it);
  return true;
}

}  // namespace toco
<|endoftext|>


<commit_before>#pragma once

#include "rapidcheck/detail/ApplyTuple.h"
#include "rapidcheck/seq/Create.h"

namespace rc {
namespace seq {
namespace detail {

template <typename T>
class DropSeq {
public:
  DropSeq(std::size_t n, Seq<T> seq)
      : m_drop(n)
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    while (m_drop > 0) {
      if (!m_seq.next()) {
        m_seq = Seq<T>();
        m_drop = 0;
        return Nothing;
      }
      m_drop--;
    }

    return m_seq.next();
  }

private:
  std::size_t m_drop;
  Seq<T> m_seq;
};

template <typename T>
class TakeSeq {
public:
  TakeSeq(std::size_t n, Seq<T> seq)
      : m_take(n)
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    if (m_take == 0) {
      return Nothing;
    }

    m_take--;
    return m_seq.next();
  }

private:
  std::size_t m_take;
  Seq<T> m_seq;
};

template <typename Predicate, typename T>
class DropWhileSeq {
public:
  template <typename PredArg>
  DropWhileSeq(Seq<T> seq, PredArg &&pred)
      : m_pred(std::forward<PredArg>(pred))
      , m_dropped(false)
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    while (!m_dropped) {
      auto value = m_seq.next();

      if (!value) {
        m_dropped = true;
        m_seq = Seq<T>();
        return Nothing;
      }

      if (!m_pred(*value)) {
        m_dropped = true;
        return value;
      }
    }

    return m_seq.next();
  }

private:
  Predicate m_pred;
  bool m_dropped;
  Seq<T> m_seq;
};

template <typename Predicate, typename T>
class TakeWhileSeq {
public:
  template <typename PredArg>
  TakeWhileSeq(Seq<T> seq, PredArg &&pred)
      : m_pred(std::forward<PredArg>(pred))
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    auto value = m_seq.next();
    if (!value) {
      return Nothing;
    }

    if (!m_pred(*value)) {
      m_seq = Seq<T>();
      return Nothing;
    }

    return value;
  }

private:
  Predicate m_pred;
  Seq<T> m_seq;
};

template <typename Mapper, typename T>
class MapSeq {
public:
  using U = Decay<typename std::result_of<Mapper(T)>::type>;

  template <typename MapperArg>
  MapSeq(Seq<T> seq, MapperArg &&mapper)
      : m_mapper(std::forward<MapperArg>(mapper))
      , m_seq(std::move(seq)) {}

  Maybe<U> operator()() {
    auto value = m_seq.next();
    if (!value) {
      m_seq = Seq<T>();
      return Nothing;
    }

    return m_mapper(std::move(*value));
  }

private:
  Mapper m_mapper;
  Seq<T> m_seq;
};

template <typename Zipper, typename... Ts>
class ZipWithSeq {
public:
  using U = Decay<typename std::result_of<Zipper(Ts...)>::type>;

  template <typename ZipperArg>
  ZipWithSeq(ZipperArg &&zipper, Seq<Ts>... seqs)
      : m_zipper(std::forward<ZipperArg>(zipper))
      , m_seqs(std::move(seqs)...) {}

  Maybe<U> operator()() {
    return rc::detail::applyTuple(
        m_seqs,
        [this](Seq<Ts> &... seqs) { return mapMaybes(seqs.next()...); });
  }

private:
  Maybe<U> mapMaybes(Maybe<Ts> &&... maybes) {
    if (!allTrue(maybes...)) {
      m_seqs = std::tuple<Seq<Ts>...>();
      return Nothing;
    }

    return m_zipper(std::move(*maybes)...);
  }

  static bool allTrue() { return true; }

  template <typename MaybeT, typename... MaybeTs>
  static bool allTrue(const MaybeT &arg, const MaybeTs &... args) {
    return arg && allTrue(args...);
  }

  Zipper m_zipper;
  std::tuple<Seq<Ts>...> m_seqs;
};

template <typename Predicate, typename T>
class FilterSeq {
public:
  template <typename PredArg>
  FilterSeq(Seq<T> seq, PredArg predicate)
      : m_predicate(std::forward<PredArg>(predicate))
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    while (true) {
      auto value = m_seq.next();

      if (!value) {
        m_seq = Seq<T>();
        return Nothing;
      }

      if (m_predicate(*value)) {
        return value;
      }
    }
  }

private:
  Predicate m_predicate;
  Seq<T> m_seq;
};

template <typename T>
class JoinSeq {
public:
  JoinSeq(Seq<Seq<T>> seqs)
      : m_seqs(std::move(seqs)) {}

  Maybe<T> operator()() {
    while (true) {
      auto value = m_seq.next();
      if (value) {
        return value;
      }

      // Otherwise, next Seq
      auto seq = m_seqs.next();
      if (!seq) {
        m_seq = Seq<T>();
        m_seqs = Seq<Seq<T>>();
        return Nothing;
      }

      m_seq = std::move(*seq);
    }
  }

private:
  Seq<T> m_seq;
  Seq<Seq<T>> m_seqs;
};

template <typename T, std::size_t N>
class ConcatSeq {
public:
  template <typename... Ts>
  ConcatSeq(Seq<Ts>... seqs)
      : m_seqs{std::move(seqs)...} {}

  Maybe<T> operator()() {
    while (m_i < N) {
      auto value = m_seqs[m_i].next();
      if (value) {
        return value;
      }

      m_i++;
    }

    return Nothing;
  }

private:
  Seq<T> m_seqs[N];
  std::size_t m_i;
};

template <typename Mapper, typename T>
class MapcatSeq {
public:
  using U = typename std::result_of<Mapper(T)>::type::ValueType;

  template <typename MapperArg>
  MapcatSeq(Seq<T> seq, MapperArg &&mapper)
      : m_mapper(std::forward<MapperArg>(mapper))
      , m_seqT(std::move(seq)) {}

  Maybe<U> operator()() {
    while (true) {
      auto valueU = m_seqU.next();
      if (valueU) {
        return valueU;
      }

      auto valueT = m_seqT.next();
      if (!valueT) {
        m_seqT = Seq<T>();
        m_seqU = Seq<U>();
        return Nothing;
      }

      m_seqU = m_mapper(std::move(*valueT));
    }
  }

private:
  Mapper m_mapper;
  Seq<T> m_seqT;
  Seq<U> m_seqU;
};

} // namespace detail

template <typename T>
Seq<T> drop(std::size_t n, Seq<T> seq) {
  if (n == 0) {
    return seq;
  }
  return makeSeq<detail::DropSeq<T>>(n, std::move(seq));
}

template <typename T>
Seq<T> take(std::size_t n, Seq<T> seq) {
  if (n == 0) {
    return Seq<T>();
  }
  return makeSeq<detail::TakeSeq<T>>(n, std::move(seq));
}

template <typename T, typename Predicate>
Seq<T> dropWhile(Seq<T> seq, Predicate &&pred) {
  return makeSeq<detail::DropWhileSeq<Decay<Predicate>, T>>(
      std::move(seq), std::forward<Predicate>(pred));
}

template <typename T, typename Predicate>
Seq<T> takeWhile(Seq<T> seq, Predicate &&pred) {
  return makeSeq<detail::TakeWhileSeq<Decay<Predicate>, T>>(
      std::move(seq), std::forward<Predicate>(pred));
}

template <typename T, typename Mapper>
Seq<Decay<typename std::result_of<Mapper(T)>::type>> map(Seq<T> seq,
                                                         Mapper &&mapper) {
  return makeSeq<detail::MapSeq<Decay<Mapper>, T>>(
      std::move(seq), std::forward<Mapper>(mapper));
}

template <typename... Ts, typename Zipper>
Seq<Decay<typename std::result_of<Zipper(Ts...)>::type>>
zipWith(Zipper &&zipper, Seq<Ts>... seqs) {
  return makeSeq<detail::ZipWithSeq<Decay<Zipper>, Ts...>>(
      std::forward<Zipper>(zipper), std::move(seqs)...);
}

template <typename T, typename Predicate>
Seq<T> filter(Seq<T> seq, Predicate &&pred) {
  return makeSeq<detail::FilterSeq<Decay<Predicate>, T>>(
      std::move(seq), std::forward<Predicate>(pred));
}

template <typename T>
Seq<T> join(Seq<Seq<T>> seqs) {
  return makeSeq<detail::JoinSeq<T>>(std::move(seqs));
}

template <typename T, typename... Ts>
Seq<T> concat(Seq<T> seq, Seq<Ts>... seqs) {
  return makeSeq<detail::ConcatSeq<T, sizeof...(Ts) + 1>>(std::move(seq),
                                                          std::move(seqs)...);
}

template <typename T, typename Mapper>
Seq<typename std::result_of<Mapper(T)>::type::ValueType>
mapcat(Seq<T> seq, Mapper &&mapper) {
  return makeSeq<detail::MapcatSeq<Decay<Mapper>, T>>(
      std::move(seq), std::forward<Mapper>(mapper));
}

template <typename T, typename Mapper>
Seq<typename std::result_of<Mapper(T)>::type::ValueType>
mapMaybe(Seq<T> seq, Mapper &&mapper) {
  using U = typename std::result_of<Mapper(T)>::type::ValueType;
  return seq::map(
      seq::filter(seq::map(std::move(seq), std::forward<Mapper>(mapper)),
                  [](const Maybe<U> &x) { return !!x; }),
      [](Maybe<U> &&x) { return std::move(*x); });
}

template <typename T>
Seq<T> cycle(Seq<T> seq) {
  return seq::join(seq::repeat(std::move(seq)));
}

template <typename T, typename U>
Seq<T> cast(Seq<U> seq) {
  return seq::map(std::move(seq),
                  [](U &&x) { return static_cast<T>(std::move(x)); });
}

} // namespace seq
} // namespace rc
<commit_msg>Fix uninitialized value in seq::concat<commit_after>#pragma once

#include "rapidcheck/detail/ApplyTuple.h"
#include "rapidcheck/seq/Create.h"

namespace rc {
namespace seq {
namespace detail {

template <typename T>
class DropSeq {
public:
  DropSeq(std::size_t n, Seq<T> seq)
      : m_drop(n)
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    while (m_drop > 0) {
      if (!m_seq.next()) {
        m_seq = Seq<T>();
        m_drop = 0;
        return Nothing;
      }
      m_drop--;
    }

    return m_seq.next();
  }

private:
  std::size_t m_drop;
  Seq<T> m_seq;
};

template <typename T>
class TakeSeq {
public:
  TakeSeq(std::size_t n, Seq<T> seq)
      : m_take(n)
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    if (m_take == 0) {
      return Nothing;
    }

    m_take--;
    return m_seq.next();
  }

private:
  std::size_t m_take;
  Seq<T> m_seq;
};

template <typename Predicate, typename T>
class DropWhileSeq {
public:
  template <typename PredArg>
  DropWhileSeq(Seq<T> seq, PredArg &&pred)
      : m_pred(std::forward<PredArg>(pred))
      , m_dropped(false)
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    while (!m_dropped) {
      auto value = m_seq.next();

      if (!value) {
        m_dropped = true;
        m_seq = Seq<T>();
        return Nothing;
      }

      if (!m_pred(*value)) {
        m_dropped = true;
        return value;
      }
    }

    return m_seq.next();
  }

private:
  Predicate m_pred;
  bool m_dropped;
  Seq<T> m_seq;
};

template <typename Predicate, typename T>
class TakeWhileSeq {
public:
  template <typename PredArg>
  TakeWhileSeq(Seq<T> seq, PredArg &&pred)
      : m_pred(std::forward<PredArg>(pred))
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    auto value = m_seq.next();
    if (!value) {
      return Nothing;
    }

    if (!m_pred(*value)) {
      m_seq = Seq<T>();
      return Nothing;
    }

    return value;
  }

private:
  Predicate m_pred;
  Seq<T> m_seq;
};

template <typename Mapper, typename T>
class MapSeq {
public:
  using U = Decay<typename std::result_of<Mapper(T)>::type>;

  template <typename MapperArg>
  MapSeq(Seq<T> seq, MapperArg &&mapper)
      : m_mapper(std::forward<MapperArg>(mapper))
      , m_seq(std::move(seq)) {}

  Maybe<U> operator()() {
    auto value = m_seq.next();
    if (!value) {
      m_seq = Seq<T>();
      return Nothing;
    }

    return m_mapper(std::move(*value));
  }

private:
  Mapper m_mapper;
  Seq<T> m_seq;
};

template <typename Zipper, typename... Ts>
class ZipWithSeq {
public:
  using U = Decay<typename std::result_of<Zipper(Ts...)>::type>;

  template <typename ZipperArg>
  ZipWithSeq(ZipperArg &&zipper, Seq<Ts>... seqs)
      : m_zipper(std::forward<ZipperArg>(zipper))
      , m_seqs(std::move(seqs)...) {}

  Maybe<U> operator()() {
    return rc::detail::applyTuple(
        m_seqs,
        [this](Seq<Ts> &... seqs) { return mapMaybes(seqs.next()...); });
  }

private:
  Maybe<U> mapMaybes(Maybe<Ts> &&... maybes) {
    if (!allTrue(maybes...)) {
      m_seqs = std::tuple<Seq<Ts>...>();
      return Nothing;
    }

    return m_zipper(std::move(*maybes)...);
  }

  static bool allTrue() { return true; }

  template <typename MaybeT, typename... MaybeTs>
  static bool allTrue(const MaybeT &arg, const MaybeTs &... args) {
    return arg && allTrue(args...);
  }

  Zipper m_zipper;
  std::tuple<Seq<Ts>...> m_seqs;
};

template <typename Predicate, typename T>
class FilterSeq {
public:
  template <typename PredArg>
  FilterSeq(Seq<T> seq, PredArg predicate)
      : m_predicate(std::forward<PredArg>(predicate))
      , m_seq(std::move(seq)) {}

  Maybe<T> operator()() {
    while (true) {
      auto value = m_seq.next();

      if (!value) {
        m_seq = Seq<T>();
        return Nothing;
      }

      if (m_predicate(*value)) {
        return value;
      }
    }
  }

private:
  Predicate m_predicate;
  Seq<T> m_seq;
};

template <typename T>
class JoinSeq {
public:
  JoinSeq(Seq<Seq<T>> seqs)
      : m_seqs(std::move(seqs)) {}

  Maybe<T> operator()() {
    while (true) {
      auto value = m_seq.next();
      if (value) {
        return value;
      }

      // Otherwise, next Seq
      auto seq = m_seqs.next();
      if (!seq) {
        m_seq = Seq<T>();
        m_seqs = Seq<Seq<T>>();
        return Nothing;
      }

      m_seq = std::move(*seq);
    }
  }

private:
  Seq<T> m_seq;
  Seq<Seq<T>> m_seqs;
};

template <typename T, std::size_t N>
class ConcatSeq {
public:
  template <typename... Ts>
  ConcatSeq(Seq<Ts>... seqs)
      : m_seqs{std::move(seqs)...}
      , m_i(0) {}

  Maybe<T> operator()() {
    while (m_i < N) {
      auto value = m_seqs[m_i].next();
      if (value) {
        return value;
      }

      m_i++;
    }

    return Nothing;
  }

private:
  Seq<T> m_seqs[N];
  std::size_t m_i;
};

template <typename Mapper, typename T>
class MapcatSeq {
public:
  using U = typename std::result_of<Mapper(T)>::type::ValueType;

  template <typename MapperArg>
  MapcatSeq(Seq<T> seq, MapperArg &&mapper)
      : m_mapper(std::forward<MapperArg>(mapper))
      , m_seqT(std::move(seq)) {}

  Maybe<U> operator()() {
    while (true) {
      auto valueU = m_seqU.next();
      if (valueU) {
        return valueU;
      }

      auto valueT = m_seqT.next();
      if (!valueT) {
        m_seqT = Seq<T>();
        m_seqU = Seq<U>();
        return Nothing;
      }

      m_seqU = m_mapper(std::move(*valueT));
    }
  }

private:
  Mapper m_mapper;
  Seq<T> m_seqT;
  Seq<U> m_seqU;
};

} // namespace detail

template <typename T>
Seq<T> drop(std::size_t n, Seq<T> seq) {
  if (n == 0) {
    return seq;
  }
  return makeSeq<detail::DropSeq<T>>(n, std::move(seq));
}

template <typename T>
Seq<T> take(std::size_t n, Seq<T> seq) {
  if (n == 0) {
    return Seq<T>();
  }
  return makeSeq<detail::TakeSeq<T>>(n, std::move(seq));
}

template <typename T, typename Predicate>
Seq<T> dropWhile(Seq<T> seq, Predicate &&pred) {
  return makeSeq<detail::DropWhileSeq<Decay<Predicate>, T>>(
      std::move(seq), std::forward<Predicate>(pred));
}

template <typename T, typename Predicate>
Seq<T> takeWhile(Seq<T> seq, Predicate &&pred) {
  return makeSeq<detail::TakeWhileSeq<Decay<Predicate>, T>>(
      std::move(seq), std::forward<Predicate>(pred));
}

template <typename T, typename Mapper>
Seq<Decay<typename std::result_of<Mapper(T)>::type>> map(Seq<T> seq,
                                                         Mapper &&mapper) {
  return makeSeq<detail::MapSeq<Decay<Mapper>, T>>(
      std::move(seq), std::forward<Mapper>(mapper));
}

template <typename... Ts, typename Zipper>
Seq<Decay<typename std::result_of<Zipper(Ts...)>::type>>
zipWith(Zipper &&zipper, Seq<Ts>... seqs) {
  return makeSeq<detail::ZipWithSeq<Decay<Zipper>, Ts...>>(
      std::forward<Zipper>(zipper), std::move(seqs)...);
}

template <typename T, typename Predicate>
Seq<T> filter(Seq<T> seq, Predicate &&pred) {
  return makeSeq<detail::FilterSeq<Decay<Predicate>, T>>(
      std::move(seq), std::forward<Predicate>(pred));
}

template <typename T>
Seq<T> join(Seq<Seq<T>> seqs) {
  return makeSeq<detail::JoinSeq<T>>(std::move(seqs));
}

template <typename T, typename... Ts>
Seq<T> concat(Seq<T> seq, Seq<Ts>... seqs) {
  return makeSeq<detail::ConcatSeq<T, sizeof...(Ts) + 1>>(std::move(seq),
                                                          std::move(seqs)...);
}

template <typename T, typename Mapper>
Seq<typename std::result_of<Mapper(T)>::type::ValueType>
mapcat(Seq<T> seq, Mapper &&mapper) {
  return makeSeq<detail::MapcatSeq<Decay<Mapper>, T>>(
      std::move(seq), std::forward<Mapper>(mapper));
}

template <typename T, typename Mapper>
Seq<typename std::result_of<Mapper(T)>::type::ValueType>
mapMaybe(Seq<T> seq, Mapper &&mapper) {
  using U = typename std::result_of<Mapper(T)>::type::ValueType;
  return seq::map(
      seq::filter(seq::map(std::move(seq), std::forward<Mapper>(mapper)),
                  [](const Maybe<U> &x) { return !!x; }),
      [](Maybe<U> &&x) { return std::move(*x); });
}

template <typename T>
Seq<T> cycle(Seq<T> seq) {
  return seq::join(seq::repeat(std::move(seq)));
}

template <typename T, typename U>
Seq<T> cast(Seq<U> seq) {
  return seq::map(std::move(seq),
                  [](U &&x) { return static_cast<T>(std::move(x)); });
}

} // namespace seq
} // namespace rc
<|endoftext|>