<commit_before>#include <iostream>
#include <vector>
#include <sys/stat.h>

#include "Network.h"

// Returns the path to the default weights directory
std::string getWeightsDir(char* argvZero) {
  std::string executablePath = realpath(argvZero, NULL);
  size_t index = executablePath.rfind('/', executablePath.rfind('/') - 1);
  return executablePath.substr(0, index) + "/files/weights";
}

// Print options and usage
void printHelp() {
  std::cout << "  Usage: trainer <training_file> [options]\n\n"
    "  Options:\n"
    "  -i, --input-nodes\t Set number of input nodes\n"
    "  -h, --hidden-nodes\t Set number of hidden nodes\n"
    "  -o, --output-nodes\t Set number of output nodes\n"
    "  -l, --hidden-layers\t Set number of hidden layers\n"
    "      --help\t\t Print this message\n\n"
    "  Example:\n"
    "  ./bin/trainer training_set.tra -h 5 -l 1\n\n";
}

// Validate option is an integer
void isValInt(char* opt, char* val) {
  std::string valStr = val;
  try {
    std::stoi(valStr);
  }
  catch (std::invalid_argument ia) {
    std::cerr << "  ERROR: Invalid value '" << val << "' for option '"
      << opt << "' (Value is not an Int)\n";
   }
}

// Print errors and return exit code 1
void error(int errorCode, std::string info = "") {
  switch (errorCode) {
    case ERRFILE :
      std::cerr << "  ERROR: Training file " << info << " is "
        "unreadable or does not exist\n";
      break;
    case ERRDIR :
      std::cerr << " ERROR: Train class does not currently support "
        "directories for training file argument\n";
      break;
    case ERRNODE :
      std::cerr << "  ERROR: Must have at least one " << info << " node.\n";
      break;
    default:
      std::cerr << " ERROR: Unknown error.\n";
      break;
  }
  exit(1);
}

// Check parameters
void checkParams(std::vector< std::string > options) {
  if (std::stoi(options[0]) <= 0) {
    error(ERRNODE, "input");
  }
  if (std::stoi(options[2]) <= 0) {
    error(ERRNODE, "output");
  }
  if (std::stoi(options[1]) > 0 && std::stoi(options[3]) <= 0) {
    std::cerr << "  ERROR: Hidden layers are set to one or greater"
      " but hidden nodes are set to zero.\n";
    exit(1);
  }
  if (std::stoi(options[1]) <= 0 && std::stoi(options[3]) > 0) {
    std::cerr << "  ERROR: Hidden nodes are set to one or greater"
      " but hidden layers are set to zero.\n";
    exit(1);
  }
  // TODO: Confirm number of inputs matches (first line - 1) of .tra file
  // Get number of output nodes if unspecified
}

// Parse options
std::vector<std::string> parseOptions(int argc, char* argv[]) {

  std::string trainingFile = "NULL";
  std::string inputNodes = "0";
  std::string hiddenNodes = "0";
  std::string outputNodes = "0";
  std::string hiddenLayers = "0";

  std::vector<std::string> options;
  options.push_back(inputNodes);
  options.push_back(hiddenNodes);
  options.push_back(outputNodes);
  options.push_back(hiddenLayers);
  options.push_back(trainingFile);

  for (int i = 1; i < argc; i++) {
    std::string arg = argv[i];
    if (arg == "--help") {
      printHelp();
      exit(0);
    }
    else if (arg == "-i" || arg == "--input-nodes") {
      isValInt(argv[i], argv[i+1]);
      options[0] = argv[i+1];
      i++;
    }
    else if (arg == "-h" || arg == "--hidden-nodes") {
      isValInt(argv[i], argv[i+1]);
      options[1] = argv[i+1];
      i++;
    }
    else if (arg == "-o" || arg == "--output-nodes") {
      isValInt(argv[i], argv[i+1]);
      options[2] = argv[i+1];
      i++;
    }
    else if (arg == "-l" || arg == "--hidden-layers") {
      isValInt(argv[i], argv[i+1]);
      options[3] = argv[i+1];
      i++;
    }
    else if (trainingFile == "NULL") {
      trainingFile = argv[i];
      struct stat s;
      if (stat(argv[i], &s) == 0) {
        if (s.st_mode & S_IFREG) {
          std::ifstream tFile(trainingFile);
          if (tFile.good()) {
            options[4] = argv[i];
          }
          else {
            error(ERRFILE, trainingFile);
          }
        }
        else if (s.st_mode & S_IFDIR) {
          // TODO: Support directories as training file argument
          error(ERRDIR);
        }
        else {
          error(ERRFILE, trainingFile);
        }
      }
      else {
        error(ERRFILE, trainingFile);
      }
    }
    else {
      std::cerr << "  ERROR: Invalid option \"" << argv[i] << "\"\n\n";
      printHelp();
      exit(1);
    }
  }

  if (trainingFile == "NULL") {
   std::cerr << "  ERROR: Training file was not provided.\n\n";
   printHelp();
   exit(1);
  }

  checkParams(options);
  return options;
}

// Main method
int main(int argc, char* argv[]) {

  std::vector< std::string > options = parseOptions(argc, argv);

  // Initialize network
  Network myNeuralNet = Network(std::stoi(options[0]),
                                std::stoi(options[1]),
                                std::stoi(options[2]),
                                std::stoi(options[3]));

  // Variables
  int numInputs = std::stoi(options[0]);
  int numOutputs = std::stoi(options[2]);
  std::ifstream tFile(options[4]);
  std::string val;

  float totalError = 1.0;
/*
  // Iterate through training file
  while (!tFile.eof()) {
    std::vector<float> inputVec;
    std::vector<float> outputVec(numOutputs, 0.01);
    // Set input and output vectors
    for (int i = 0; i < numInputs; i++) {
      std::getline(tFile, val, ',');
      inputVec.push_back(std::stof(val));
    }
    std::getline(tFile, val, ',');
    outputVec[std::stoi(val)] = 0.99;

    totalError = myNeuralNet.train(inputVec, outputVec);
  }
  myNeuralNet.writeWeightFile(getWeightsDir(argv[0]));
*/  return 0;
}
<commit_msg>removing commented out blocks for debugging<commit_after>#include <iostream>
#include <vector>
#include <sys/stat.h>

#include "Network.h"

// Returns the path to the default weights directory
std::string getWeightsDir(char* argvZero) {
  std::string executablePath = realpath(argvZero, NULL);
  size_t index = executablePath.rfind('/', executablePath.rfind('/') - 1);
  return executablePath.substr(0, index) + "/files/weights";
}

// Print options and usage
void printHelp() {
  std::cout << "  Usage: trainer <training_file> [options]\n\n"
    "  Options:\n"
    "  -i, --input-nodes\t Set number of input nodes\n"
    "  -h, --hidden-nodes\t Set number of hidden nodes\n"
    "  -o, --output-nodes\t Set number of output nodes\n"
    "  -l, --hidden-layers\t Set number of hidden layers\n"
    "      --help\t\t Print this message\n\n"
    "  Example:\n"
    "  ./bin/trainer training_set.tra -h 5 -l 1\n\n";
}

// Validate option is an integer
void isValInt(char* opt, char* val) {
  std::string valStr = val;
  try {
    std::stoi(valStr);
  }
  catch (std::invalid_argument ia) {
    std::cerr << "  ERROR: Invalid value '" << val << "' for option '"
      << opt << "' (Value is not an Int)\n";
   }
}

// Print errors and return exit code 1
void error(int errorCode, std::string info = "") {
  switch (errorCode) {
    case ERRFILE :
      std::cerr << "  ERROR: Training file " << info << " is "
        "unreadable or does not exist\n";
      break;
    case ERRDIR :
      std::cerr << " ERROR: Train class does not currently support "
        "directories for training file argument\n";
      break;
    case ERRNODE :
      std::cerr << "  ERROR: Must have at least one " << info << " node.\n";
      break;
    default:
      std::cerr << " ERROR: Unknown error.\n";
      break;
  }
  exit(1);
}

// Check parameters
void checkParams(std::vector< std::string > options) {
  if (std::stoi(options[0]) <= 0) {
    error(ERRNODE, "input");
  }
  if (std::stoi(options[2]) <= 0) {
    error(ERRNODE, "output");
  }
  if (std::stoi(options[1]) > 0 && std::stoi(options[3]) <= 0) {
    std::cerr << "  ERROR: Hidden layers are set to one or greater"
      " but hidden nodes are set to zero.\n";
    exit(1);
  }
  if (std::stoi(options[1]) <= 0 && std::stoi(options[3]) > 0) {
    std::cerr << "  ERROR: Hidden nodes are set to one or greater"
      " but hidden layers are set to zero.\n";
    exit(1);
  }
  // TODO: Confirm number of inputs matches (first line - 1) of .tra file
  // Get number of output nodes if unspecified
}

// Parse options
std::vector<std::string> parseOptions(int argc, char* argv[]) {

  std::string trainingFile = "NULL";
  std::string inputNodes = "0";
  std::string hiddenNodes = "0";
  std::string outputNodes = "0";
  std::string hiddenLayers = "0";

  std::vector<std::string> options;
  options.push_back(inputNodes);
  options.push_back(hiddenNodes);
  options.push_back(outputNodes);
  options.push_back(hiddenLayers);
  options.push_back(trainingFile);

  for (int i = 1; i < argc; i++) {
    std::string arg = argv[i];
    if (arg == "--help") {
      printHelp();
      exit(0);
    }
    else if (arg == "-i" || arg == "--input-nodes") {
      isValInt(argv[i], argv[i+1]);
      options[0] = argv[i+1];
      i++;
    }
    else if (arg == "-h" || arg == "--hidden-nodes") {
      isValInt(argv[i], argv[i+1]);
      options[1] = argv[i+1];
      i++;
    }
    else if (arg == "-o" || arg == "--output-nodes") {
      isValInt(argv[i], argv[i+1]);
      options[2] = argv[i+1];
      i++;
    }
    else if (arg == "-l" || arg == "--hidden-layers") {
      isValInt(argv[i], argv[i+1]);
      options[3] = argv[i+1];
      i++;
    }
    else if (trainingFile == "NULL") {
      trainingFile = argv[i];
      struct stat s;
      if (stat(argv[i], &s) == 0) {
        if (s.st_mode & S_IFREG) {
          std::ifstream tFile(trainingFile);
          if (tFile.good()) {
            options[4] = argv[i];
          }
          else {
            error(ERRFILE, trainingFile);
          }
        }
        else if (s.st_mode & S_IFDIR) {
          // TODO: Support directories as training file argument
          error(ERRDIR);
        }
        else {
          error(ERRFILE, trainingFile);
        }
      }
      else {
        error(ERRFILE, trainingFile);
      }
    }
    else {
      std::cerr << "  ERROR: Invalid option \"" << argv[i] << "\"\n\n";
      printHelp();
      exit(1);
    }
  }

  if (trainingFile == "NULL") {
   std::cerr << "  ERROR: Training file was not provided.\n\n";
   printHelp();
   exit(1);
  }

  checkParams(options);
  return options;
}

// Main method
int main(int argc, char* argv[]) {

  std::vector< std::string > options = parseOptions(argc, argv);

  // Initialize network
  Network myNeuralNet = Network(std::stoi(options[0]),
                                std::stoi(options[1]),
                                std::stoi(options[2]),
                                std::stoi(options[3]));

  // Variables
  int numInputs = std::stoi(options[0]);
  int numOutputs = std::stoi(options[2]);
  std::ifstream tFile(options[4]);
  std::string val;

  float totalError = 1.0;
  // Iterate through training file
  while (!tFile.eof()) {
    std::vector<float> inputVec;
    std::vector<float> outputVec(numOutputs, 0.01);
    // Set input and output vectors
    for (int i = 0; i < numInputs; i++) {
      std::getline(tFile, val, ',');
      inputVec.push_back(std::stof(val));
    }
    std::getline(tFile, val, ',');
    outputVec[std::stoi(val)] = 0.99;

    totalError = myNeuralNet.train(inputVec, outputVec);
  }
  myNeuralNet.writeWeightFile(getWeightsDir(argv[0]));
  return 0;
}
<|endoftext|>


<commit_before>/* Copyright 2018 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 <gtest/gtest.h>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/kernels/test_util.h"
#include "tensorflow/lite/model.h"

namespace tflite {
namespace {

using ::testing::ElementsAreArray;

template <typename input_type, typename index_type>
class SliceOpModel : public SingleOpModel {
 public:
  SliceOpModel(std::initializer_list<int> input_shape,
               std::initializer_list<int> begin_shape,
               std::initializer_list<int> size_shape,
               TensorType tensor_index_type, TensorType tensor_input_type) {
    input_ = AddInput(tensor_input_type);
    begin_ = AddInput(tensor_index_type);
    size_ = AddInput(tensor_index_type);
    output_ = AddOutput(tensor_input_type);
    SetBuiltinOp(BuiltinOperator_SLICE, BuiltinOptions_SliceOptions,
                 CreateSliceOptions(builder_).Union());
    BuildInterpreter({input_shape, begin_shape, size_shape});
  }

  void SetInput(std::initializer_list<input_type> data) {
    PopulateTensor<input_type>(input_, data);
  }
  void SetBegin(std::initializer_list<index_type> data) {
    PopulateTensor<index_type>(begin_, data);
  }
  void SetSize(std::initializer_list<index_type> data) {
    PopulateTensor<index_type>(size_, data);
  }

  std::vector<input_type> GetOutput() {
    return ExtractVector<input_type>(output_);
  }
  std::vector<int> GetOutputShape() { return GetTensorShape(output_); }

 private:
  int input_;
  int begin_;
  int size_;
  int output_;
};

TEST(SliceOpTest, In1D) {
  SliceOpModel<float, int32_t> m({4}, {1}, {1}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4});
  m.SetBegin({1});
  m.SetSize({2});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 3}));
}

TEST(SliceOpTest, In2D) {
  SliceOpModel<float, int32_t> m({2, 3}, {2}, {2}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4, 5, 6});
  m.SetBegin({1, 0});
  m.SetSize({1, 2});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 2}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({4, 5}));
}

TEST(SliceOpTest, In3D) {
  SliceOpModel<float, int32_t> m({2, 3, 2}, {3}, {4}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
  m.SetBegin({0, 0, 0});
  m.SetSize({2, 3, 2});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 3, 2}));
  EXPECT_THAT(m.GetOutput(),
              ElementsAreArray({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}));
}

TEST(SliceOpTest, InputFloat) {
  SliceOpModel<float, int32_t> m({4, 1, 1, 1}, {4}, {4}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({3, 1, 1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({3, 1, 1, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 3, 4}));
}

TEST(SliceOpTest, IndexInt64) {
  SliceOpModel<float, int64_t> m({4, 1, 1, 1}, {4}, {4}, TensorType_INT64,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({3, 1, 1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({3, 1, 1, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 3, 4}));
}

// See these test cases under:
// https://www.tensorflow.org/versions/master/api_docs/python/tf/slice
TEST(SliceOpTest, InputInteger1) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({1, 1, 3, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3}));
}

TEST(SliceOpTest, InputInteger2) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({1, 2, 3, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 2, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 4, 4, 4}));
}

TEST(SliceOpTest, InputInteger3) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, 3, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

TEST(SliceOpTest, SizeMinus1) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

TEST(SliceOpTest, BeginNonZeroSizeMinus1Dim2) {
  SliceOpModel<int32_t, int32_t> m({3, 3, 2, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9});
  m.SetBegin({1, 1, 0, 0});
  m.SetSize({2, -1, 1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 2, 1, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 6, 8, 9}));
}

TEST(SliceOpTest, BeginNonZeroSizeMinus1Dim3) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 1, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 2, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 5, 5}));
}

TEST(SliceOpTest, BeginNonZeroSizeMinus1Dim4) {
  SliceOpModel<int32_t, int32_t> m({3, 1, 2, 3}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 1});
  m.SetSize({2, 1, 1, -1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 1, 2}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 5, 5}));
}

TEST(SliceOpTest, SliceUint8) {
  SliceOpModel<uint8_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_UINT8);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

TEST(SliceOpTest, SliceInt8) {
  SliceOpModel<int8_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                  TensorType_INT8);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

}  // namespace
}  // namespace tflite

int main(int argc, char** argv) {
  ::tflite::LogToStderr();
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Changed dimension name to axis<commit_after>/* Copyright 2018 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 <gtest/gtest.h>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/kernels/test_util.h"
#include "tensorflow/lite/model.h"

namespace tflite {
namespace {

using ::testing::ElementsAreArray;

template <typename input_type, typename index_type>
class SliceOpModel : public SingleOpModel {
 public:
  SliceOpModel(std::initializer_list<int> input_shape,
               std::initializer_list<int> begin_shape,
               std::initializer_list<int> size_shape,
               TensorType tensor_index_type, TensorType tensor_input_type) {
    input_ = AddInput(tensor_input_type);
    begin_ = AddInput(tensor_index_type);
    size_ = AddInput(tensor_index_type);
    output_ = AddOutput(tensor_input_type);
    SetBuiltinOp(BuiltinOperator_SLICE, BuiltinOptions_SliceOptions,
                 CreateSliceOptions(builder_).Union());
    BuildInterpreter({input_shape, begin_shape, size_shape});
  }

  void SetInput(std::initializer_list<input_type> data) {
    PopulateTensor<input_type>(input_, data);
  }
  void SetBegin(std::initializer_list<index_type> data) {
    PopulateTensor<index_type>(begin_, data);
  }
  void SetSize(std::initializer_list<index_type> data) {
    PopulateTensor<index_type>(size_, data);
  }

  std::vector<input_type> GetOutput() {
    return ExtractVector<input_type>(output_);
  }
  std::vector<int> GetOutputShape() { return GetTensorShape(output_); }

 private:
  int input_;
  int begin_;
  int size_;
  int output_;
};

TEST(SliceOpTest, In1D) {
  SliceOpModel<float, int32_t> m({4}, {1}, {1}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4});
  m.SetBegin({1});
  m.SetSize({2});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 3}));
}

TEST(SliceOpTest, In2D) {
  SliceOpModel<float, int32_t> m({2, 3}, {2}, {2}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4, 5, 6});
  m.SetBegin({1, 0});
  m.SetSize({1, 2});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 2}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({4, 5}));
}

TEST(SliceOpTest, In3D) {
  SliceOpModel<float, int32_t> m({2, 3, 2}, {3}, {4}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
  m.SetBegin({0, 0, 0});
  m.SetSize({2, 3, 2});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 3, 2}));
  EXPECT_THAT(m.GetOutput(),
              ElementsAreArray({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}));
}

TEST(SliceOpTest, InputFloat) {
  SliceOpModel<float, int32_t> m({4, 1, 1, 1}, {4}, {4}, TensorType_INT32,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({3, 1, 1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({3, 1, 1, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 3, 4}));
}

TEST(SliceOpTest, IndexInt64) {
  SliceOpModel<float, int64_t> m({4, 1, 1, 1}, {4}, {4}, TensorType_INT64,
                                 TensorType_FLOAT32);
  m.SetInput({1, 2, 3, 4});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({3, 1, 1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({3, 1, 1, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 3, 4}));
}

// See these test cases under:
// https://www.tensorflow.org/versions/master/api_docs/python/tf/slice
TEST(SliceOpTest, InputInteger1) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({1, 1, 3, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3}));
}

TEST(SliceOpTest, InputInteger2) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({1, 2, 3, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 2, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 4, 4, 4}));
}

TEST(SliceOpTest, InputInteger3) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, 3, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

TEST(SliceOpTest, SizeMinus1) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

TEST(SliceOpTest, BeginNonZeroSizeMinus1Axis1) {
  SliceOpModel<int32_t, int32_t> m({3, 3, 2, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9});
  m.SetBegin({1, 1, 0, 0});
  m.SetSize({2, -1, 1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 2, 1, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 6, 8, 9}));
}

TEST(SliceOpTest, BeginNonZeroSizeMinus1Axis2) {
  SliceOpModel<int32_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 1, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 2, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 5, 5}));
}

TEST(SliceOpTest, BeginNonZeroSizeMinus1Axis3) {
  SliceOpModel<int32_t, int32_t> m({3, 1, 2, 3}, {4}, {4}, TensorType_INT32,
                                   TensorType_INT32);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 1});
  m.SetSize({2, 1, 1, -1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 1, 2}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 5, 5}));
}

TEST(SliceOpTest, SliceUint8) {
  SliceOpModel<uint8_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                   TensorType_UINT8);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

TEST(SliceOpTest, SliceInt8) {
  SliceOpModel<int8_t, int32_t> m({3, 2, 3, 1}, {4}, {4}, TensorType_INT32,
                                  TensorType_INT8);
  m.SetInput({1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6});
  m.SetBegin({1, 0, 0, 0});
  m.SetSize({2, 1, -1, 1});
  m.Invoke();
  EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 3, 1}));
  EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 3, 3, 5, 5, 5}));
}

}  // namespace
}  // namespace tflite

int main(int argc, char** argv) {
  ::tflite::LogToStderr();
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2004.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : contains workarounds and works as a central place for configurable types
// ***************************************************************************

#ifndef BOOST_UNIT_TEST_CONFIG_HPP_071894GER
#define BOOST_UNIT_TEST_CONFIG_HPP_071894GER

// BOOST
#include <boost/config.hpp> // compilers workarounds and std::ptrdiff_t
#include <boost/detail/workaround.hpp>

#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
#define BOOST_CLASSIC_IOSTREAMS
#else
#define BOOST_STANDARD_IOSTREAMS
#endif

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))     || \
    (defined __sgi && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(730)))
#define BOOST_TEST_SHIFTED_LINE
#endif

// Boost.Test
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#define BOOST_TEST_STRING_LITERAL( s ) boost::unit_test::literal_string( s, sizeof( s ) - 1 )
#define BOOST_TEST_EMPTY_STRING BOOST_TEST_STRING_LITERAL( "" )

#if defined(BOOST_HAS_SIGACTION)
#define BOOST_TEST_SUPPORT_TIMEOUT
#endif

#if BOOST_WORKAROUND(__BORLANDC__, <= 0x570)           || \
    BOOST_WORKAROUND( __COMO__, <= 0x433 )             || \
    BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 )       || \
    BOOST_WORKAROUND(__GNUC__, < 3)                    || \
    defined(__sgi) && _COMPILER_VERSION <= 730         || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
    defined(__DECCXX)
#define BOOST_TEST_NO_PROTECTED_USING
#endif

// STL
#include <iterator>     // for std::distance
#include <cstddef>      // for std::ptrdiff_t

namespace boost {

namespace unit_test {

typedef unsigned long   unit_test_counter;

namespace ut_detail {

#ifdef BOOST_NO_STD_DISTANCE
template <class T>
std::ptrdiff_t distance( T const& x_, T const& y_ )
{
    std::ptrdiff_t res = 0;

    std::distance( x_, y_, res );

    return res;
}
#else
using std::distance;
#endif

#define BOOST_TEST_L( s ) const_string( s, sizeof(s) )

} // namespace ut_detail

} // namespace unit_test

namespace unit_test_framework = unit_test;

} // namespace boost

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.25  2005/01/22 19:22:12  rogeeff
//  implementation moved into headers section to eliminate dependency of included/minimal component on src directory
//
//  Revision 1.24  2005/01/21 07:33:20  rogeeff
//  BOOST_TEST_SUPPORT_TIMEOUT flag introduced to be used by used to switch code by timeout support
//
//  Revision 1.23  2004/10/01 10:52:11  rogeeff
//  shared some workaround detection
//
//  Revision 1.22  2004/09/19 09:22:12  rogeeff
//  ios fix for classic iostreams
//
//  Revision 1.21  2004/07/19 12:23:28  rogeeff
//  guard rename
//
//  Revision 1.20  2004/06/07 07:33:49  rogeeff
//  detail namespace renamed
//
//  Revision 1.19  2004/05/27 06:36:26  rogeeff
//  eliminate c_string_literal typedef
//
//  Revision 1.18  2004/05/21 06:19:35  rogeeff
//  licence update
//
//  Revision 1.17  2004/05/11 11:00:53  rogeeff
//  basic_cstring introduced and used everywhere
//  class properties reworked
//
//  Revision 1.16  2003/12/01 00:41:56  rogeeff
//  prerelease cleaning
//
// ***************************************************************************

#endif // BOOST_UNIT_TEST_CONFIG_HPP_071894GER
<commit_msg>BOOST_TEST_STRINGIZE introduced counter type renamed<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2004.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : contains workarounds and works as a central place for configurable types
// ***************************************************************************

#ifndef BOOST_UNIT_TEST_CONFIG_HPP_071894GER
#define BOOST_UNIT_TEST_CONFIG_HPP_071894GER

// BOOST
#include <boost/config.hpp> // compilers workarounds and std::ptrdiff_t
#include <boost/detail/workaround.hpp>

#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
#define BOOST_CLASSIC_IOSTREAMS
#else
#define BOOST_STANDARD_IOSTREAMS
#endif

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))     || \
    (defined __sgi && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(730)))
#define BOOST_TEST_SHIFTED_LINE
#endif

// Boost.Test
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#define BOOST_TEST_STRING_LITERAL( s ) boost::unit_test::literal_string( s, sizeof( s ) - 1 )
#define BOOST_TEST_STRINGIZE( s ) BOOST_TEST_STRING_LITERAL( BOOST_STRINGIZE( s ) )
#define BOOST_TEST_EMPTY_STRING BOOST_TEST_STRING_LITERAL( "" )

#if defined(BOOST_HAS_SIGACTION)
#define BOOST_TEST_SUPPORT_TIMEOUT
#endif

#if BOOST_WORKAROUND(__BORLANDC__, <= 0x570)           || \
    BOOST_WORKAROUND( __COMO__, <= 0x433 )             || \
    BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 )       || \
    BOOST_WORKAROUND(__GNUC__, < 3)                    || \
    defined(__sgi) && _COMPILER_VERSION <= 730         || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
    defined(__DECCXX)
#define BOOST_TEST_NO_PROTECTED_USING
#endif

// STL
#include <iterator>     // for std::distance
#include <cstddef>      // for std::ptrdiff_t

namespace boost {

namespace unit_test {

typedef unsigned long   counter_t;

namespace ut_detail {

#ifdef BOOST_NO_STD_DISTANCE
template <class T>
std::ptrdiff_t distance( T const& x_, T const& y_ )
{
    std::ptrdiff_t res = 0;

    std::distance( x_, y_, res );

    return res;
}
#else
using std::distance;
#endif

#define BOOST_TEST_L( s ) const_string( s, sizeof(s) )

} // namespace ut_detail

} // namespace unit_test

namespace unit_test_framework = unit_test;

} // namespace boost

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.26  2005/01/30 01:48:24  rogeeff
//  BOOST_TEST_STRINGIZE introduced
//  counter type renamed
//
//  Revision 1.25  2005/01/22 19:22:12  rogeeff
//  implementation moved into headers section to eliminate dependency of included/minimal component on src directory
//
//  Revision 1.24  2005/01/21 07:33:20  rogeeff
//  BOOST_TEST_SUPPORT_TIMEOUT flag introduced to be used by used to switch code by timeout support
//
//  Revision 1.23  2004/10/01 10:52:11  rogeeff
//  shared some workaround detection
//
//  Revision 1.22  2004/09/19 09:22:12  rogeeff
//  ios fix for classic iostreams
//
//  Revision 1.21  2004/07/19 12:23:28  rogeeff
//  guard rename
//
//  Revision 1.20  2004/06/07 07:33:49  rogeeff
//  detail namespace renamed
//
//  Revision 1.19  2004/05/27 06:36:26  rogeeff
//  eliminate c_string_literal typedef
//
//  Revision 1.18  2004/05/21 06:19:35  rogeeff
//  licence update
//
//  Revision 1.17  2004/05/11 11:00:53  rogeeff
//  basic_cstring introduced and used everywhere
//  class properties reworked
//
//  Revision 1.16  2003/12/01 00:41:56  rogeeff
//  prerelease cleaning
//
// ***************************************************************************

#endif // BOOST_UNIT_TEST_CONFIG_HPP_071894GER
<|endoftext|>


<commit_before>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v4.0.0

  Copyright(c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>

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

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

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

#ifndef CONTINUABLE_PRIMITIVES_HPP_INCLUDED
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED

#include <continuable/detail/core/types.hpp>
#include <continuable/detail/utility/identity.hpp>

namespace cti {
/// \defgroup Primitives Primitives
/// provides basic tag types for creating a customized callbacks
/// and continuations.
/// For the callback and the continuation `Args...` represents the
/// asynchronous results:
/// ```cpp
/// template<typename... Args>
/// struct continuation {
///   void operator() (callback<Args...>);
///   bool operator() (cti::is_ready_arg_t) const;
///   std::tuple<Args...> operator() (cti::query_arg_t);
/// };
/// ```
/// ```cpp
/// template<typename... Args>
/// struct callback {
///   void operator() (Args...) &&;
///   void operator() (cti::exception_arg_t, cti::exception_t) &&;
/// };
/// ```
/// \{

/// Represents the tag type that is used to specify the signature hint
/// of a continuable_base or promise_base.
///
/// \since 4.0.0
template <typename... Args>
using signature_arg_t = detail::identity<Args...>;

/// Represents the tag type that is used to query the continuation
/// for whether it resolves the callback instantly with its arguments
/// without having side effects.
///
/// \since 4.0.0
struct is_ready_arg_t {};

/// Represents the tag type that is used to query the continuation
/// for its arguments when resolves the callback instantly
/// without having side effects.
/// It's required that the query of is_ready_arg_t returns true.
///
/// \since 4.0.0
struct query_arg_t { };

/// Represents the tag type that is used to disambiguate the
/// callback operator() in order to take the exception asynchronous chain.
///
/// \note see continuable::next for details.
///
/// \since 4.0.0
struct exception_arg_t {};

/// \copydoc exception_arg_t
///
/// \deprecated The exception_arg_t was deprecated in order to move closer
///             to the types specified in the "A Unified Future" proposal
///             especially regarding naming types similar.
///
[[deprecated("The dispatch_error_tag was replaced by exception_arg_t and will "
             "be removed in a later major version!")]] //
    typedef exception_arg_t dispatch_error_tag;

/// Represents the type that is used as exception type
///
/// By default this type deduces to `std::exception_ptr`.
/// If `CONTINUABLE_WITH_NO_EXCEPTIONS` is defined the type
/// will be a `std::error_condition`.
/// A custom error type may be set through
/// defining `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE`.
///
/// \since 4.0.0
using exception_t = detail::types::exception_t;

/// \copydoc exception_t
///
/// \deprecated The exception_t was deprecated in order to move closer
///             to the types specified in the "A Unified Future" proposal
///             especially regarding naming types similar.
///
[[deprecated("The error_type was replaced by exception_t and will "
             "be removed in a later major version!")]] //
    typedef exception_t error_type;
/// \}
} // namespace cti

#endif // CONTINUABLE_PRIMITIVES_HPP_INCLUDED
<commit_msg>Doc improvement<commit_after>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v4.0.0

  Copyright(c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>

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

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

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

#ifndef CONTINUABLE_PRIMITIVES_HPP_INCLUDED
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED

#include <continuable/detail/core/types.hpp>
#include <continuable/detail/utility/identity.hpp>

namespace cti {
/// \defgroup Primitives Primitives
/// provides basic tag types for creating a customized callbacks
/// and continuations.
///
/// For the callback and the continuation `Args...` represents the
/// asynchronous results:
/// ```cpp
/// template<typename... Args>
/// struct continuation {
///   void operator() (callback<Args...>);
///   bool operator() (cti::is_ready_arg_t) const;
///   std::tuple<Args...> operator() (cti::query_arg_t);
/// };
/// ```
/// ```cpp
/// template<typename... Args>
/// struct callback {
///   void operator() (Args...) &&;
///   void operator() (cti::exception_arg_t, cti::exception_t) &&;
/// };
/// ```
/// \{

/// Represents the tag type that is used to specify the signature hint
/// of a continuable_base or promise_base.
///
/// \since 4.0.0
template <typename... Args>
using signature_arg_t = detail::identity<Args...>;

/// Represents the tag type that is used to query the continuation
/// for whether it resolves the callback instantly with its arguments
/// without having side effects.
///
/// \since 4.0.0
struct is_ready_arg_t {};

/// Represents the tag type that is used to query the continuation
/// for its arguments when resolves the callback instantly
/// without having side effects.
/// It's required that the query of is_ready_arg_t returns true.
///
/// \since 4.0.0
struct query_arg_t {};

/// Represents the tag type that is used to disambiguate the
/// callback operator() in order to take the exception asynchronous chain.
///
/// \note see continuable::next for details.
///
/// \since 4.0.0
struct exception_arg_t {};

/// \copydoc exception_arg_t
///
/// \deprecated The exception_arg_t was deprecated in order to move closer
///             to the types specified in the "A Unified Future" proposal
///             especially regarding naming types similar.
///
[[deprecated("The dispatch_error_tag was replaced by exception_arg_t and will "
             "be removed in a later major version!")]] //
    typedef exception_arg_t dispatch_error_tag;

/// Represents the type that is used as exception type
///
/// By default this type deduces to `std::exception_ptr`.
/// If `CONTINUABLE_WITH_NO_EXCEPTIONS` is defined the type
/// will be a `std::error_condition`.
/// A custom error type may be set through
/// defining `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE`.
///
/// \since 4.0.0
using exception_t = detail::types::exception_t;

/// \copydoc exception_t
///
/// \deprecated The exception_t was deprecated in order to move closer
///             to the types specified in the "A Unified Future" proposal
///             especially regarding naming types similar.
///
[[deprecated("The error_type was replaced by exception_t and will "
             "be removed in a later major version!")]] //
    typedef exception_t error_type;
/// \}
} // namespace cti

#endif // CONTINUABLE_PRIMITIVES_HPP_INCLUDED
<|endoftext|>


<commit_before>#pragma once

#include <crest/basis/homogenized_basis.hpp>

#include <Eigen/Sparse>
#include <Eigen/IterativeLinearSolvers>

#include <memory>

namespace crest
{
    namespace detail
    {

        template <
                typename _Scalar,
                typename StiffnessSolver,
                typename StiffnessMatrixType = Eigen::SparseMatrix<_Scalar>,
                typename InterpolatorMatrixType = Eigen::SparseMatrix<_Scalar> >
        class SchurComplement
                : public Eigen::EigenBase<SchurComplement<_Scalar, StiffnessSolver, InterpolatorMatrixType>>
        {
        public:
            typedef _Scalar Scalar;
            typedef Scalar RealScalar;
            typedef int StorageIndex;

            enum
            {
                ColsAtCompileTime = Eigen::Dynamic,
                MaxColsAtCompileTime = Eigen::Dynamic,
                IsRowMajor = false
            };

            SchurComplement() : _stiffness_solver(nullptr), _A(nullptr), _I_H(nullptr) {}

            Eigen::Index rows() const { return _I_H->rows(); }
            Eigen::Index cols() const { return _I_H->rows(); }

            template <typename Rhs>
            Eigen::Product<SchurComplement<Scalar, StiffnessSolver>, Rhs, Eigen::AliasFreeProduct>
            operator*(const Eigen::MatrixBase<Rhs> & x) const
            {
                return Eigen::Product<
                        SchurComplement<Scalar, StiffnessSolver>,
                        Rhs,
                        Eigen::AliasFreeProduct>(*this, x.derived());
            }

            const InterpolatorMatrixType &  quasiInterpolator() const { return *_I_H; }
            const StiffnessMatrixType    &  stiffnessMatrix() const { return *_A; }
            const StiffnessSolver        &  stiffnessSolver() const { return *_stiffness_solver; }

            SchurComplement & withQuasiInterpolator(const InterpolatorMatrixType & I_H)
            {
                _I_H = &I_H;
                return *this;
            }

            SchurComplement & withStiffness(const StiffnessMatrixType & stiffness_matrix,
                                            const StiffnessSolver & stiffness_solver)
            {
                _A = &stiffness_matrix;
                _stiffness_solver = &stiffness_solver;
                return *this;
            }

            bool isInitialized() const
            {
                return _stiffness_solver != nullptr && _I_H != nullptr && _A != nullptr;
            }

        private:
            const StiffnessSolver           * _stiffness_solver;
            const StiffnessMatrixType       * _A;
            const InterpolatorMatrixType    * _I_H;
        };

        /**
         * Preconditioner for the Schur complement problem S y = b,
         * where S = I_H A^-1 I_H^T,
         * where I_H is a quasi-interpolation operator and A is an SPD stiffness matrix.
         *
         * The preconditioner is defined by the approximation
         * S_diag = I_H diag(A)^{-1} I_H^T.
         */
        template <typename Scalar>
        class DiagonalizedSchurComplementPreconditioner
        {
        public:
            DiagonalizedSchurComplementPreconditioner() {}

            template<typename MatrixType>
            DiagonalizedSchurComplementPreconditioner& analyzePattern(const MatrixType& ) { return *this; }

            template <
                    typename StiffnessSolver,
                    typename StiffnessMatrixType,
                    typename InterpolatorMatrixType>
            DiagonalizedSchurComplementPreconditioner& compute(
                    const SchurComplement<
                            Scalar,
                            StiffnessSolver,
                            StiffnessMatrixType,
                            InterpolatorMatrixType> & schur_complement)
            {
                _approx_stiffness_solver.compute(schur_complement.stiffnessMatrix());
                _diagonalized_schur.withStiffness(schur_complement.stiffnessMatrix(), _approx_stiffness_solver);
                _diagonalized_schur.withQuasiInterpolator(schur_complement.quasiInterpolator());
                _outer_solver.compute(_diagonalized_schur);
                return *this;
            }

            template<typename MatrixType>
            DiagonalizedSchurComplementPreconditioner& factorize(const MatrixType & mat) { return *this; }

            // Note: this copies the output, so it's not currently optimal. Can maybe use the Solve<> struct
            // instead? TODO
            template<typename Rhs>
            inline const Rhs solve(const Rhs& b) const
            {
                return _outer_solver.solve(b);
            }

            Eigen::ComputationInfo info() { return Eigen::Success; }

        private:
            Eigen::DiagonalPreconditioner<Scalar> _approx_stiffness_solver;
            SchurComplement<Scalar, Eigen::DiagonalPreconditioner<Scalar>> _diagonalized_schur;
            Eigen::ConjugateGradient<
                    SchurComplement<Scalar, Eigen::DiagonalPreconditioner<Scalar>>,
                    Eigen::Lower|Eigen::Upper,
                    Eigen::IdentityPreconditioner> _outer_solver;
        };

        template <typename Scalar>
        class SchurComplementCoarseStiffnessPreconditioner
        {
        public:
            SchurComplementCoarseStiffnessPreconditioner() {}

            template<typename MatrixType>
            SchurComplementCoarseStiffnessPreconditioner& analyzePattern(const MatrixType& ) { return *this; }

            template<typename MatrixType>
            SchurComplementCoarseStiffnessPreconditioner& factorize(const MatrixType&) { return *this; }

            template<typename MatrixType>
            SchurComplementCoarseStiffnessPreconditioner& compute(const MatrixType&) { return *this; }

            // Note: this copies the output, so it's not currently optimal. Can maybe use the Solve<> struct
            // instead? TODO
            template<typename Rhs>
            inline const Rhs solve(const Rhs& b) const
            {
                return _A_H * b;
            }

            Eigen::ComputationInfo info() { return Eigen::Success; }

            template <typename MatrixType>
            void setCoarseStiffnessMatrix(const MatrixType & A)
            {
                _A_H = A;
            }

        private:
            Eigen::SparseMatrix<Scalar> _A_H;
        };
    }

    template <typename Scalar>
    class SchurCorrectorSolver : public CorrectorSolver<Scalar>
    {
    public:
        virtual std::vector<Eigen::Triplet<Scalar>> resolve_element_correctors_for_patch(
                const BiscaleMesh<Scalar, int> & mesh,
                const std::vector<int> & coarse_patch_interior,
                const std::vector<int> & fine_patch_interior,
                const Eigen::SparseMatrix<Scalar> & global_coarse_stiffness,
                const Eigen::SparseMatrix<Scalar> & global_fine_stiffness,
                const Eigen::SparseMatrix<Scalar> & global_quasi_interpolator,
                int coarse_element) const override
        {
            const auto I_H = sparse_submatrix(global_quasi_interpolator,
                                              coarse_patch_interior,
                                              fine_patch_interior);
            const auto A_h = sparse_submatrix(global_fine_stiffness,
                                              fine_patch_interior,
                                              fine_patch_interior);
            const auto A_H = sparse_submatrix(global_coarse_stiffness,
                                              coarse_patch_interior,
                                              coarse_patch_interior);

            assert(A_h.rows() > 0);

            using Eigen::SparseMatrix;
            using Eigen::ConjugateGradient;
            using Eigen::SimplicialLDLT;
            using detail::SchurComplementCoarseStiffnessPreconditioner;

            // Define the type of the solver used to solve the "stiffness problem" Ax = b.
            typedef ConjugateGradient<
                    SparseMatrix<Scalar>,
                    Eigen::Lower|Eigen::Upper,
                    SimplicialLDLT<SparseMatrix<Scalar>>> StiffnessSolver;

            // The SchurComplement uses the StiffnessSolver internally
            typedef detail::SchurComplement<Scalar, StiffnessSolver> SchurComplement;

            // Finally we define the type of solver used for the Schur complement
            typedef ConjugateGradient<
                    SchurComplement,
                    Eigen::Lower|Eigen::Upper,
                    SchurComplementCoarseStiffnessPreconditioner<Scalar>> SchurComplementSolver;

            std::vector<Eigen::Triplet<Scalar>> triplets;

            StiffnessSolver stiffness_solver(A_h);
            const auto schur_operator = SchurComplement()
                    .withQuasiInterpolator(I_H)
                    .withStiffness(A_h, stiffness_solver);
            SchurComplementSolver schur_solver;
            schur_solver.preconditioner().setCoarseStiffnessMatrix(A_H);
            schur_solver.compute(schur_operator);

            for (int i = 0; i < 3; ++i)
            {
                const auto b = this->local_rhs(mesh, fine_patch_interior, coarse_element, i);
                VectorX<Scalar> corrector(A_h.rows());

                if (I_H.rows() == 0)
                {
                    corrector = stiffness_solver.solve(b);
                } else
                {
                    const VectorX<Scalar> y = stiffness_solver.solve(b);
                    const VectorX<Scalar> kappa = schur_solver.solve(I_H * y);
                    corrector = stiffness_solver.solve(b - I_H.transpose() * kappa);
                }

                assert(static_cast<size_t>(corrector.rows()) == fine_patch_interior.size());
                const auto global_index = mesh.coarse_mesh().elements()[coarse_element].vertex_indices[i];
                for (size_t k = 0; k < fine_patch_interior.size(); ++k)
                {
                    const auto component = corrector(k);
                    // Due to rounding issues, some components that should perhaps be zero in exact arithmetic
                    // may be non-zero, and as such we might end up with a denser matrix than we should actually
                    // have. To prevent this, we introduce a threshold which determines whether to keep the entry.
                    // TODO: Make this threshold configurable?
                    if (std::abs(component) > 1e-12)
                    {
                        triplets.emplace_back(Eigen::Triplet<Scalar>(global_index, fine_patch_interior[k], component));
                    }
                }
            }

            return triplets;
        }
    };

}

/**
 * The code below is necessary for matrix-free iterative solvers in Eigen.
 * See https://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html
 */
namespace Eigen {
    namespace internal {
        // MatrixReplacement looks- a SparseMatrix, so let's inherits its traits:
        template <typename _Scalar, typename _StiffnessSolver>
        struct traits<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>>
        {
            typedef _Scalar Scalar;
            typedef int StorageIndex;
            typedef Eigen::Sparse StorageKind;
            typedef Eigen::MatrixXpr XprKind;
            enum {
                RowsAtCompileTime = Dynamic,
                ColsAtCompileTime = Dynamic,
                MaxRowsAtCompileTime = Dynamic,
                MaxColsAtCompileTime = Dynamic,
                Flags = 0
            };
        };

        template<typename _Scalar, typename _StiffnessSolver, typename Rhs>
        struct generic_product_impl<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>, Rhs, SparseShape, DenseShape, GemvProduct> // GEMV stands for matrix-vector
                : generic_product_impl_base<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>,
                        Rhs,
                        generic_product_impl<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>, Rhs> >
        {
            typedef typename Product<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>, Rhs>::Scalar Scalar;
            template<typename Dest>
            static void scaleAndAddTo(Dest& dst,
                                      const crest::detail::SchurComplement<_Scalar, _StiffnessSolver>& lhs,
                                      const Rhs& rhs,
                                      const Scalar& alpha)
            {
                // Apply the Schur complement S = I_H A^-1 I_H^T
                // to the vector x.

                // First solve
                // Ay = I_H^T x
                // such that y = A^1 I_H^T x,
                // then multiply by I_H
                assert(lhs.isInitialized() && "Must initialize SchurComplement stiffness solver "
                        "and quasi interpolator before using.");

                const auto & A = lhs.stiffnessSolver();
                const auto & I_H = lhs.quasiInterpolator();
                dst = alpha * I_H * A.solve(I_H.transpose() * rhs);
            }
        };
    }
}
<commit_msg>Simplify Schur inner iteration<commit_after>#pragma once

#include <crest/basis/homogenized_basis.hpp>

#include <Eigen/Sparse>
#include <Eigen/IterativeLinearSolvers>

#include <memory>

namespace crest
{
    namespace detail
    {

        template <
                typename _Scalar,
                typename StiffnessSolver,
                typename StiffnessMatrixType = Eigen::SparseMatrix<_Scalar>,
                typename InterpolatorMatrixType = Eigen::SparseMatrix<_Scalar> >
        class SchurComplement
                : public Eigen::EigenBase<SchurComplement<_Scalar, StiffnessSolver, InterpolatorMatrixType>>
        {
        public:
            typedef _Scalar Scalar;
            typedef Scalar RealScalar;
            typedef int StorageIndex;

            enum
            {
                ColsAtCompileTime = Eigen::Dynamic,
                MaxColsAtCompileTime = Eigen::Dynamic,
                IsRowMajor = false
            };

            SchurComplement() : _stiffness_solver(nullptr), _A(nullptr), _I_H(nullptr) {}

            Eigen::Index rows() const { return _I_H->rows(); }
            Eigen::Index cols() const { return _I_H->rows(); }

            template <typename Rhs>
            Eigen::Product<SchurComplement<Scalar, StiffnessSolver>, Rhs, Eigen::AliasFreeProduct>
            operator*(const Eigen::MatrixBase<Rhs> & x) const
            {
                return Eigen::Product<
                        SchurComplement<Scalar, StiffnessSolver>,
                        Rhs,
                        Eigen::AliasFreeProduct>(*this, x.derived());
            }

            const InterpolatorMatrixType &  quasiInterpolator() const { return *_I_H; }
            const StiffnessMatrixType    &  stiffnessMatrix() const { return *_A; }
            const StiffnessSolver        &  stiffnessSolver() const { return *_stiffness_solver; }

            SchurComplement & withQuasiInterpolator(const InterpolatorMatrixType & I_H)
            {
                _I_H = &I_H;
                return *this;
            }

            SchurComplement & withStiffness(const StiffnessMatrixType & stiffness_matrix,
                                            const StiffnessSolver & stiffness_solver)
            {
                _A = &stiffness_matrix;
                _stiffness_solver = &stiffness_solver;
                return *this;
            }

            bool isInitialized() const
            {
                return _stiffness_solver != nullptr && _I_H != nullptr && _A != nullptr;
            }

        private:
            const StiffnessSolver           * _stiffness_solver;
            const StiffnessMatrixType       * _A;
            const InterpolatorMatrixType    * _I_H;
        };

        /**
         * Preconditioner for the Schur complement problem S y = b,
         * where S = I_H A^-1 I_H^T,
         * where I_H is a quasi-interpolation operator and A is an SPD stiffness matrix.
         *
         * The preconditioner is defined by the approximation
         * S_diag = I_H diag(A)^{-1} I_H^T.
         */
        template <typename Scalar>
        class DiagonalizedSchurComplementPreconditioner
        {
        public:
            DiagonalizedSchurComplementPreconditioner() {}

            template<typename MatrixType>
            DiagonalizedSchurComplementPreconditioner& analyzePattern(const MatrixType& ) { return *this; }

            template <
                    typename StiffnessSolver,
                    typename StiffnessMatrixType,
                    typename InterpolatorMatrixType>
            DiagonalizedSchurComplementPreconditioner& compute(
                    const SchurComplement<
                            Scalar,
                            StiffnessSolver,
                            StiffnessMatrixType,
                            InterpolatorMatrixType> & schur_complement)
            {
                _approx_stiffness_solver.compute(schur_complement.stiffnessMatrix());
                _diagonalized_schur.withStiffness(schur_complement.stiffnessMatrix(), _approx_stiffness_solver);
                _diagonalized_schur.withQuasiInterpolator(schur_complement.quasiInterpolator());
                _outer_solver.compute(_diagonalized_schur);
                return *this;
            }

            template<typename MatrixType>
            DiagonalizedSchurComplementPreconditioner& factorize(const MatrixType & mat) { return *this; }

            // Note: this copies the output, so it's not currently optimal. Can maybe use the Solve<> struct
            // instead? TODO
            template<typename Rhs>
            inline const Rhs solve(const Rhs& b) const
            {
                return _outer_solver.solve(b);
            }

            Eigen::ComputationInfo info() { return Eigen::Success; }

        private:
            Eigen::DiagonalPreconditioner<Scalar> _approx_stiffness_solver;
            SchurComplement<Scalar, Eigen::DiagonalPreconditioner<Scalar>> _diagonalized_schur;
            Eigen::ConjugateGradient<
                    SchurComplement<Scalar, Eigen::DiagonalPreconditioner<Scalar>>,
                    Eigen::Lower|Eigen::Upper,
                    Eigen::IdentityPreconditioner> _outer_solver;
        };

        template <typename Scalar>
        class SchurComplementCoarseStiffnessPreconditioner
        {
        public:
            SchurComplementCoarseStiffnessPreconditioner() {}

            template<typename MatrixType>
            SchurComplementCoarseStiffnessPreconditioner& analyzePattern(const MatrixType& ) { return *this; }

            template<typename MatrixType>
            SchurComplementCoarseStiffnessPreconditioner& factorize(const MatrixType&) { return *this; }

            template<typename MatrixType>
            SchurComplementCoarseStiffnessPreconditioner& compute(const MatrixType&) { return *this; }

            // Note: this copies the output, so it's not currently optimal. Can maybe use the Solve<> struct
            // instead? TODO
            template<typename Rhs>
            inline const Rhs solve(const Rhs& b) const
            {
                return _A_H * b;
            }

            Eigen::ComputationInfo info() { return Eigen::Success; }

            template <typename MatrixType>
            void setCoarseStiffnessMatrix(const MatrixType & A)
            {
                _A_H = A;
            }

        private:
            Eigen::SparseMatrix<Scalar> _A_H;
        };
    }

    template <typename Scalar>
    class SchurCorrectorSolver : public CorrectorSolver<Scalar>
    {
    public:
        virtual std::vector<Eigen::Triplet<Scalar>> resolve_element_correctors_for_patch(
                const BiscaleMesh<Scalar, int> & mesh,
                const std::vector<int> & coarse_patch_interior,
                const std::vector<int> & fine_patch_interior,
                const Eigen::SparseMatrix<Scalar> & global_coarse_stiffness,
                const Eigen::SparseMatrix<Scalar> & global_fine_stiffness,
                const Eigen::SparseMatrix<Scalar> & global_quasi_interpolator,
                int coarse_element) const override
        {
            const auto I_H = sparse_submatrix(global_quasi_interpolator,
                                              coarse_patch_interior,
                                              fine_patch_interior);
            const auto A_h = sparse_submatrix(global_fine_stiffness,
                                              fine_patch_interior,
                                              fine_patch_interior);
            const auto A_H = sparse_submatrix(global_coarse_stiffness,
                                              coarse_patch_interior,
                                              coarse_patch_interior);

            assert(A_h.rows() > 0);

            using Eigen::SparseMatrix;
            using Eigen::ConjugateGradient;
            using Eigen::SimplicialLDLT;
            using detail::SchurComplementCoarseStiffnessPreconditioner;

            // Define the type of the solver used to solve the "stiffness problem" Ax = b.
            typedef SimplicialLDLT<SparseMatrix<Scalar>> StiffnessSolver;

            // The SchurComplement uses the StiffnessSolver internally
            typedef detail::SchurComplement<Scalar, StiffnessSolver> SchurComplement;

            // Finally we define the type of solver used for the Schur complement
            typedef ConjugateGradient<
                    SchurComplement,
                    Eigen::Lower|Eigen::Upper,
                    SchurComplementCoarseStiffnessPreconditioner<Scalar>> SchurComplementSolver;

            std::vector<Eigen::Triplet<Scalar>> triplets;

            StiffnessSolver stiffness_solver(A_h);
            const auto schur_operator = SchurComplement()
                    .withQuasiInterpolator(I_H)
                    .withStiffness(A_h, stiffness_solver);
            SchurComplementSolver schur_solver;
            schur_solver.preconditioner().setCoarseStiffnessMatrix(A_H);
            schur_solver.compute(schur_operator);

            for (int i = 0; i < 3; ++i)
            {
                const auto b = this->local_rhs(mesh, fine_patch_interior, coarse_element, i);
                VectorX<Scalar> corrector(A_h.rows());

                if (I_H.rows() == 0)
                {
                    corrector = stiffness_solver.solve(b);
                } else
                {
                    const VectorX<Scalar> y = stiffness_solver.solve(b);
                    const VectorX<Scalar> kappa = schur_solver.solve(I_H * y);
                    corrector = stiffness_solver.solve(b - I_H.transpose() * kappa);
                }

                assert(static_cast<size_t>(corrector.rows()) == fine_patch_interior.size());
                const auto global_index = mesh.coarse_mesh().elements()[coarse_element].vertex_indices[i];
                for (size_t k = 0; k < fine_patch_interior.size(); ++k)
                {
                    const auto component = corrector(k);
                    // Due to rounding issues, some components that should perhaps be zero in exact arithmetic
                    // may be non-zero, and as such we might end up with a denser matrix than we should actually
                    // have. To prevent this, we introduce a threshold which determines whether to keep the entry.
                    // TODO: Make this threshold configurable?
                    if (std::abs(component) > 1e-12)
                    {
                        triplets.emplace_back(Eigen::Triplet<Scalar>(global_index, fine_patch_interior[k], component));
                    }
                }
            }

            return triplets;
        }
    };

}

/**
 * The code below is necessary for matrix-free iterative solvers in Eigen.
 * See https://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html
 */
namespace Eigen {
    namespace internal {
        // MatrixReplacement looks- a SparseMatrix, so let's inherits its traits:
        template <typename _Scalar, typename _StiffnessSolver>
        struct traits<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>>
        {
            typedef _Scalar Scalar;
            typedef int StorageIndex;
            typedef Eigen::Sparse StorageKind;
            typedef Eigen::MatrixXpr XprKind;
            enum {
                RowsAtCompileTime = Dynamic,
                ColsAtCompileTime = Dynamic,
                MaxRowsAtCompileTime = Dynamic,
                MaxColsAtCompileTime = Dynamic,
                Flags = 0
            };
        };

        template<typename _Scalar, typename _StiffnessSolver, typename Rhs>
        struct generic_product_impl<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>, Rhs, SparseShape, DenseShape, GemvProduct> // GEMV stands for matrix-vector
                : generic_product_impl_base<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>,
                        Rhs,
                        generic_product_impl<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>, Rhs> >
        {
            typedef typename Product<crest::detail::SchurComplement<_Scalar, _StiffnessSolver>, Rhs>::Scalar Scalar;
            template<typename Dest>
            static void scaleAndAddTo(Dest& dst,
                                      const crest::detail::SchurComplement<_Scalar, _StiffnessSolver>& lhs,
                                      const Rhs& rhs,
                                      const Scalar& alpha)
            {
                // Apply the Schur complement S = I_H A^-1 I_H^T
                // to the vector x.

                // First solve
                // Ay = I_H^T x
                // such that y = A^1 I_H^T x,
                // then multiply by I_H
                assert(lhs.isInitialized() && "Must initialize SchurComplement stiffness solver "
                        "and quasi interpolator before using.");

                const auto & A = lhs.stiffnessSolver();
                const auto & I_H = lhs.quasiInterpolator();
                dst = alpha * I_H * A.solve(I_H.transpose() * rhs);
            }
        };
    }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

#include <string>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/shared_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp"

namespace libtorrent
{

	class http_connection;
	class entry;
	class http_parser;
	class connection_queue;
	class session_settings;

	class TORRENT_EXPORT http_tracker_connection
		: public tracker_connection
	{
	friend class tracker_manager;
	public:

		http_tracker_connection(
			io_service& ios
			, connection_queue& cc
			, tracker_manager& man
			, tracker_request const& req
			, address bind_infc
			, boost::weak_ptr<request_callback> c
			, session_settings const& stn
			, proxy_settings const& ps
			, std::string const& password = "");

		void close();

	private:

		boost::intrusive_ptr<http_tracker_connection> self()
		{ return boost::intrusive_ptr<http_tracker_connection>(this); }

		void on_response(asio::error_code const& ec, http_parser const& parser
			, char const* data, int size);

		virtual void on_timeout() {}

		void parse(int status_code, const entry& e);
		bool extract_peer_info(const entry& e, peer_entry& ret);

		tracker_manager& m_man;
		boost::shared_ptr<http_connection> m_tracker_connection;
	};

}

#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

<commit_msg>silence msvc warning<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

#include <string>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/shared_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp"

namespace libtorrent
{

	struct http_connection;
	class entry;
	class http_parser;
	class connection_queue;
	class session_settings;

	class TORRENT_EXPORT http_tracker_connection
		: public tracker_connection
	{
	friend class tracker_manager;
	public:

		http_tracker_connection(
			io_service& ios
			, connection_queue& cc
			, tracker_manager& man
			, tracker_request const& req
			, address bind_infc
			, boost::weak_ptr<request_callback> c
			, session_settings const& stn
			, proxy_settings const& ps
			, std::string const& password = "");

		void close();

	private:

		boost::intrusive_ptr<http_tracker_connection> self()
		{ return boost::intrusive_ptr<http_tracker_connection>(this); }

		void on_response(asio::error_code const& ec, http_parser const& parser
			, char const* data, int size);

		virtual void on_timeout() {}

		void parse(int status_code, const entry& e);
		bool extract_peer_info(const entry& e, peer_entry& ret);

		tracker_manager& m_man;
		boost::shared_ptr<http_connection> m_tracker_connection;
	};

}

#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

#include <string>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/shared_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp"

namespace libtorrent
{

	struct http_connection;
	class entry;
	class http_parser;
	class connection_queue;
	class session_settings;

	class TORRENT_EXPORT http_tracker_connection
		: public tracker_connection
	{
	friend class tracker_manager;
	public:

		http_tracker_connection(
			io_service& ios
			, connection_queue& cc
			, tracker_manager& man
			, tracker_request const& req
			, address bind_infc
			, boost::weak_ptr<request_callback> c
			, session_settings const& stn
			, proxy_settings const& ps
			, std::string const& password = "");

		void close();

	private:

		boost::intrusive_ptr<http_tracker_connection> self()
		{ return boost::intrusive_ptr<http_tracker_connection>(this); }

		void on_response(asio::error_code const& ec, http_parser const& parser
			, char const* data, int size);

		virtual void on_timeout() {}

		void parse(int status_code, const entry& e);
		bool extract_peer_info(const entry& e, peer_entry& ret);

		tracker_manager& m_man;
		boost::shared_ptr<http_connection> m_tracker_connection;
	};

}

#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

<commit_msg>silence msvc warning<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

#include <string>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/shared_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp"

namespace libtorrent
{

	struct http_connection;
	class entry;
	class http_parser;
	class connection_queue;
	struct session_settings;

	class TORRENT_EXPORT http_tracker_connection
		: public tracker_connection
	{
	friend class tracker_manager;
	public:

		http_tracker_connection(
			io_service& ios
			, connection_queue& cc
			, tracker_manager& man
			, tracker_request const& req
			, address bind_infc
			, boost::weak_ptr<request_callback> c
			, session_settings const& stn
			, proxy_settings const& ps
			, std::string const& password = "");

		void close();

	private:

		boost::intrusive_ptr<http_tracker_connection> self()
		{ return boost::intrusive_ptr<http_tracker_connection>(this); }

		void on_response(asio::error_code const& ec, http_parser const& parser
			, char const* data, int size);

		virtual void on_timeout() {}

		void parse(int status_code, const entry& e);
		bool extract_peer_info(const entry& e, peer_entry& ret);

		tracker_manager& m_man;
		boost::shared_ptr<http_connection> m_tracker_connection;
	};

}

#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

<|endoftext|>


<commit_before>// Copyright (c) 2017 Sony Corporation. 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.

#ifndef NBLA_FUNCTION_MAX_POOLING_BACKWARD_HPP
#define NBLA_FUNCTION_MAX_POOLING_BACKWARD_HPP

#include <nbla/cpu.hpp>
#include <nbla/function.hpp>
#include <nbla/function_registry.hpp>

namespace nbla {

NBLA_REGISTER_FUNCTION_HEADER(MaxPoolingBackward, const vector<int> &,
                              const vector<int> &, bool, const vector<int> &,
                              bool);

/**
    @todo Write doc.

Inputs:

Outputs:

\ingroup FunctionImplGrp
 */
template <typename T>
class MaxPoolingBackward
    : public BaseFunction<const vector<int> &, const vector<int> &, bool,
                          const vector<int> &, bool> {
protected:
  const vector<int> kernel_;
  const vector<int> stride_;
  bool ignore_border_;
  const vector<int> pad_;
  bool channel_last_;

public:
  MaxPoolingBackward(const Context &ctx, const vector<int> &kernel,
                     const vector<int> &stride, bool ignore_border,
                     const vector<int> &pad, bool channel_last)
      : BaseFunction(ctx, kernel, stride, ignore_border, pad, channel_last),
        kernel_(kernel), stride_(stride), ignore_border_(ignore_border),
        pad_(pad), channel_last_(channel_last) {}
  virtual ~MaxPoolingBackward() {}
  virtual shared_ptr<Function> copy() const {
    return create_MaxPoolingBackward(ctx_, kernel_, stride_, ignore_border_,
                                     pad_, channel_last_);
  }
  virtual int min_inputs() { return 2; }
  virtual int min_outputs() { return 1; }
  virtual vector<dtypes> in_types() {
    return vector<dtypes>{get_dtype<T>(), get_dtype<T>()};
  }
  virtual vector<dtypes> out_types() { return vector<dtypes>{get_dtype<T>()}; }
  virtual vector<string> allowed_array_classes() {
    return SingletonManager::get<Cpu>()->array_classes();
  }
  virtual string name() { return "MaxPoolingBackward"; }
  virtual bool grad_depends_output_data(int i, int o) const { return false; }

protected:
  NBLA_API virtual void setup_impl(const Variables &inputs,
                                   const Variables &outputs);
  NBLA_API virtual void forward_impl(const Variables &inputs,
                                     const Variables &outputs);
  NBLA_API virtual void backward_impl(const Variables &inputs,
                                      const Variables &outputs,
                                      const vector<bool> &propagate_down,
                                      const vector<bool> &accum);
  virtual bool grad_depends_input_data_impl(int i, int j) const {
    return false;
  }
};
}
#endif
<commit_msg>Fix MaxPoolingBackward grad_depends_input_data_impl<commit_after>// Copyright (c) 2017 Sony Corporation. 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.

#ifndef NBLA_FUNCTION_MAX_POOLING_BACKWARD_HPP
#define NBLA_FUNCTION_MAX_POOLING_BACKWARD_HPP

#include <nbla/cpu.hpp>
#include <nbla/function.hpp>
#include <nbla/function_registry.hpp>

namespace nbla {

NBLA_REGISTER_FUNCTION_HEADER(MaxPoolingBackward, const vector<int> &,
                              const vector<int> &, bool, const vector<int> &,
                              bool);

/**
    @todo Write doc.

Inputs:

Outputs:

\ingroup FunctionImplGrp
 */
template <typename T>
class MaxPoolingBackward
    : public BaseFunction<const vector<int> &, const vector<int> &, bool,
                          const vector<int> &, bool> {
protected:
  const vector<int> kernel_;
  const vector<int> stride_;
  bool ignore_border_;
  const vector<int> pad_;
  bool channel_last_;

public:
  MaxPoolingBackward(const Context &ctx, const vector<int> &kernel,
                     const vector<int> &stride, bool ignore_border,
                     const vector<int> &pad, bool channel_last)
      : BaseFunction(ctx, kernel, stride, ignore_border, pad, channel_last),
        kernel_(kernel), stride_(stride), ignore_border_(ignore_border),
        pad_(pad), channel_last_(channel_last) {}
  virtual ~MaxPoolingBackward() {}
  virtual shared_ptr<Function> copy() const {
    return create_MaxPoolingBackward(ctx_, kernel_, stride_, ignore_border_,
                                     pad_, channel_last_);
  }
  virtual int min_inputs() { return 2; }
  virtual int min_outputs() { return 1; }
  virtual vector<dtypes> in_types() {
    return vector<dtypes>{get_dtype<T>(), get_dtype<T>()};
  }
  virtual vector<dtypes> out_types() { return vector<dtypes>{get_dtype<T>()}; }
  virtual vector<string> allowed_array_classes() {
    return SingletonManager::get<Cpu>()->array_classes();
  }
  virtual string name() { return "MaxPoolingBackward"; }
  virtual bool grad_depends_output_data(int i, int o) const { return false; }

protected:
  NBLA_API virtual void setup_impl(const Variables &inputs,
                                   const Variables &outputs);
  NBLA_API virtual void forward_impl(const Variables &inputs,
                                     const Variables &outputs);
  NBLA_API virtual void backward_impl(const Variables &inputs,
                                      const Variables &outputs,
                                      const vector<bool> &propagate_down,
                                      const vector<bool> &accum);
  virtual bool grad_depends_input_data_impl(int i, int j) const { return true; }
};
}
#endif
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2017 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_MAIN_MENU_SITE_PLAY_HPP
#define RJ_GAME_MAIN_MENU_SITE_PLAY_HPP

#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>
#include <rectojump/ui/level_widget.hpp>
#include <rectojump/ui/stacked_widget.hpp>

namespace rj
{
	template<typename Overlay>
	class site_play
	{
		Overlay& m_overlay;
		level_manager& m_lvmgr;

		ui::stacked_widget& m_sites;

	public:
		site_play(Overlay& ov) :
			m_overlay{ov},
			m_lvmgr{ov.mainmenu().gamehandler().levelmgr()},
			m_sites{ov.sites()}
		{ }

		void construct()
		{
			auto& site_play{m_sites.get("play")};
			auto& font{m_overlay.mainmenu().gamehandler().datastore().template get<sf::Font>
					   (settings::text_font())};

			// create level_widget
			auto level_widget{m_sites.add_object<ui::level_widget>(
								  "play", m_overlay.mainmenu().gamehandler().gamewindow(),
								  m_sites.size(), m_sites.pos())};

			// add levels
			for(const auto& a : m_lvmgr.get_levels())
				level_widget->add_item(a.second, font, []{/*TODO:implement(button play)*/},
				[this, &a]
				{
					// button edit
					m_overlay.mainmenu().gamehandler().switch_to_editor();
					m_overlay.mainmenu().gamehandler().editor().
							handle_load(a.second.info.level_name);
				});

			// set camera on render
			site_play.on_render = [level_widget]{level_widget->activate_cam();};

			// add input
			m_overlay.mainmenu().gamehandler().template add_input<state::main_menu>
					([this, level_widget](const vec2f&)
			{
				if(m_sites.active("play"))
					level_widget->scroll_up();
			}, wheel::up);

			m_overlay.mainmenu().gamehandler().template add_input<state::main_menu>
					([this, level_widget](const vec2f&)
			{
				if(m_sites.active("play"))
					level_widget->scroll_down();
			}, wheel::down);
		}
	};
}

#endif // RJ_GAME_MAIN_MENU_SITE_PLAY_HPP

<commit_msg>level_widget_item: impl button play<commit_after>//
// Copyright (c) 2013-2017 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_MAIN_MENU_SITE_PLAY_HPP
#define RJ_GAME_MAIN_MENU_SITE_PLAY_HPP

#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>
#include <rectojump/ui/level_widget.hpp>
#include <rectojump/ui/stacked_widget.hpp>

namespace rj
{
	template<typename Overlay>
	class site_play
	{
		Overlay& m_overlay;
		level_manager& m_lvmgr;

		ui::stacked_widget& m_sites;

	public:
		site_play(Overlay& ov) :
			m_overlay{ov},
			m_lvmgr{ov.mainmenu().gamehandler().levelmgr()},
			m_sites{ov.sites()}
		{ }

		void construct()
		{
			auto& site_play{m_sites.get("play")};
			auto& font{m_overlay.mainmenu().gamehandler().datastore().template get<sf::Font>
					   (settings::text_font())};

			// create level_widget
			auto level_widget{m_sites.add_object<ui::level_widget>(
								  "play", m_overlay.mainmenu().gamehandler().gamewindow(),
								  m_sites.size(), m_sites.pos())};

			// add levels
			for(const auto& a : m_lvmgr.get_levels())
				level_widget->add_item(a.second, font,
				[this, &a]
				{
					//button play
					m_overlay.mainmenu().gamehandler().load_level(a.second.info.level_name);
				},
				[this, &a]
				{
					// button edit
					m_overlay.mainmenu().gamehandler().switch_to_editor();
					m_overlay.mainmenu().gamehandler().editor().
							handle_load(a.second.info.level_name);
				});

			// set camera on render
			site_play.on_render = [level_widget]{level_widget->activate_cam();};

			// add input
			m_overlay.mainmenu().gamehandler().template add_input<state::main_menu>
					([this, level_widget](const vec2f&)
			{
				if(m_sites.active("play"))
					level_widget->scroll_up();
			}, wheel::up);

			m_overlay.mainmenu().gamehandler().template add_input<state::main_menu>
					([this, level_widget](const vec2f&)
			{
				if(m_sites.active("play"))
					level_widget->scroll_down();
			}, wheel::down);
		}
	};
}

#endif // RJ_GAME_MAIN_MENU_SITE_PLAY_HPP

<|endoftext|>