<commit_before>// Copyright 2018 The Amber Authors.
//
// 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 <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <set>
#include <utility>
#include <vector>

#include "amber/amber.h"
#include "amber/recipe.h"
#include "samples/config_helper.h"
#include "samples/ppm.h"
#include "src/build-versions.h"
#include "src/make_unique.h"

namespace {

struct Options {
  std::vector<std::string> input_filenames;

  std::string image_filename;
  std::string buffer_filename;
  int64_t buffer_binding_index = 0;
  uint32_t engine_major = 1;
  uint32_t engine_minor = 0;
  bool parse_only = false;
  bool disable_validation_layer = false;
  bool show_summary = false;
  bool show_help = false;
  bool show_version_info = false;
  amber::EngineType engine = amber::kEngineTypeVulkan;
  std::string spv_env;
};

const char kUsage[] = R"(Usage: amber [options] SCRIPT [SCRIPTS...]

 options:
  -p                  -- Parse input files only; Don't execute.
  -s                  -- Print summary of pass/failure.
  -d                  -- Disable validation layers.
  -t <spirv_env> -- The target SPIR-V environment. Defaults to SPV_ENV_UNIVERSAL_1_0.
  -i <filename>       -- Write rendering to <filename> as a PPM image.
  -b <filename>       -- Write contents of a UBO or SSBO to <filename>.
  -B <buffer>         -- Index of buffer to write. Defaults buffer 0.
  -e <engine>         -- Specify graphics engine: vulkan, dawn. Default is vulkan.
  -v <engine version> -- Engine version (eg, 1.1 for Vulkan). Default 1.0.
  -V, --version       -- Output version information for Amber and libraries.
  -h                  -- This help text.
)";

bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
  for (size_t i = 1; i < args.size(); ++i) {
    const std::string& arg = args[i];
    if (arg == "-i") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -i argument." << std::endl;
        return false;
      }
      opts->image_filename = args[i];

    } else if (arg == "-b") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -b argument." << std::endl;
        return false;
      }
      opts->buffer_filename = args[i];

    } else if (arg == "-B") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -B argument." << std::endl;
        return false;
      }
      opts->buffer_binding_index =
          static_cast<int64_t>(strtol(args[i].c_str(), nullptr, 10));

      if (opts->buffer_binding_index < 0U) {
        std::cerr << "Invalid value for -B, must be 0 or greater." << std::endl;
        return false;
      }

    } else if (arg == "-e") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -e argument." << std::endl;
        return false;
      }
      const std::string& engine = args[i];
      if (engine == "vulkan") {
        opts->engine = amber::kEngineTypeVulkan;
      } else if (engine == "dawn") {
        opts->engine = amber::kEngineTypeDawn;
      } else {
        std::cerr
            << "Invalid value for -e argument. Must be one of: vulkan dawn"
            << std::endl;
        return false;
      }
    } else if (arg == "-t") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -t argument." << std::endl;
        return false;
      }
      opts->spv_env = args[i];
    } else if (arg == "-h" || arg == "--help") {
      opts->show_help = true;
    } else if (arg == "-v") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -v argument." << std::endl;
        return false;
      }
      const std::string& ver = args[i];

      size_t dot_pos = 0;
      int32_t val = std::stoi(ver, &dot_pos);
      if (val < 0) {
        std::cerr << "Version major must be non-negative" << std::endl;
        return false;
      }

      opts->engine_major = static_cast<uint32_t>(val);
      if (dot_pos != std::string::npos && (dot_pos + 1) < ver.size()) {
        val = std::stoi(ver.substr(dot_pos + 1));
        if (val < 0) {
          std::cerr << "Version minor must be non-negative" << std::endl;
          return false;
        }
        opts->engine_minor = static_cast<uint32_t>(val);
      }
    } else if (arg == "-V" || arg == "--version") {
      opts->show_version_info = true;
    } else if (arg == "-p") {
      opts->parse_only = true;
    } else if (arg == "-d") {
      opts->disable_validation_layer = true;
    } else if (arg == "-s") {
      opts->show_summary = true;
    } else if (arg.size() > 0 && arg[0] == '-') {
      std::cerr << "Unrecognized option " << arg << std::endl;
      return false;
    } else if (!arg.empty()) {
      opts->input_filenames.push_back(arg);
    }
  }

  return true;
}

std::string ReadFile(const std::string& input_file) {
  FILE* file = nullptr;
#if defined(_MSC_VER)
  fopen_s(&file, input_file.c_str(), "rb");
#else
  file = fopen(input_file.c_str(), "rb");
#endif
  if (!file) {
    std::cerr << "Failed to open " << input_file << std::endl;
    return {};
  }

  fseek(file, 0, SEEK_END);
  uint64_t tell_file_size = static_cast<uint64_t>(ftell(file));
  if (tell_file_size <= 0) {
    std::cerr << "Input file of incorrect size: " << input_file << std::endl;
    return {};
  }
  fseek(file, 0, SEEK_SET);

  size_t file_size = static_cast<size_t>(tell_file_size);

  std::vector<char> data;
  data.resize(file_size);

  size_t bytes_read = fread(data.data(), sizeof(char), file_size, file);
  fclose(file);
  if (bytes_read != file_size) {
    std::cerr << "Failed to read " << input_file << std::endl;
    return {};
  }

  return std::string(data.begin(), data.end());
}

}  // namespace

int main(int argc, const char** argv) {
  std::vector<std::string> args(argv, argv + argc);
  Options options;

  if (!ParseArgs(args, &options)) {
    std::cerr << "Failed to parse arguments." << std::endl;
    return 1;
  }

  if (options.show_version_info) {
    std::cout << "Amber        : " << AMBER_VERSION << std::endl;
#if AMBER_ENABLE_SPIRV_TOOLS
    std::cout << "SPIRV-Tools  : " << SPIRV_TOOLS_VERSION << std::endl;
    std::cout << "SPIRV-Headers: " << SPIRV_HEADERS_VERSION << std::endl;
#endif  // AMBER_ENABLE_SPIRV_TOOLS
#if AMBER_ENABLE_SHADERC
    std::cout << "GLSLang      : " << GLSLANG_VERSION << std::endl;
    std::cout << "Shaderc      : " << SHADERC_VERSION << std::endl;
#endif  // AMBER_ENABLE_SHADERC
  }

  if (options.show_help) {
    std::cout << kUsage << std::endl;
    return 0;
  }

  if (options.input_filenames.empty()) {
    std::cerr << "Input file must be provided." << std::endl;
    return 2;
  }

  amber::Result result;
  std::vector<std::string> failures;
  struct RecipeData {
    std::string file;
    std::unique_ptr<amber::Recipe> recipe;
  };
  std::vector<RecipeData> recipe_data;
  for (const auto& file : options.input_filenames) {
    auto data = ReadFile(file);
    if (data.empty()) {
      std::cerr << file << " is empty." << std::endl;
      failures.push_back(file);
      continue;
    }

    amber::Amber am;
    std::unique_ptr<amber::Recipe> recipe = amber::MakeUnique<amber::Recipe>();

    result = am.Parse(data, recipe.get());
    if (!result.IsSuccess()) {
      std::cerr << file << ": " << result.Error() << std::endl;
      failures.push_back(file);
      continue;
    }

    recipe_data.emplace_back();
    recipe_data.back().file = file;
    recipe_data.back().recipe = std::move(recipe);
  }

  if (options.parse_only)
    return 0;

  amber::Options amber_options;
  amber_options.engine = options.engine;
  amber_options.spv_env = options.spv_env;

  std::set<std::string> required_features;
  std::set<std::string> required_extensions;
  for (const auto& recipe_data_elem : recipe_data) {
    const auto features = recipe_data_elem.recipe->GetRequiredFeatures();
    required_features.insert(features.begin(), features.end());

    const auto extensions = recipe_data_elem.recipe->GetRequiredExtensions();
    required_extensions.insert(extensions.begin(), extensions.end());
  }

  sample::ConfigHelper config_helper;
  std::unique_ptr<amber::EngineConfig> config;

  amber::Result r = config_helper.CreateConfig(
      amber_options.engine, options.engine_major, options.engine_minor,
      std::vector<std::string>(required_features.begin(),
                               required_features.end()),
      std::vector<std::string>(required_extensions.begin(),
                               required_extensions.end()),
      options.disable_validation_layer, &config);

  if (!r.IsSuccess()) {
    std::cout << r.Error() << std::endl;
    return 1;
  }

  amber_options.config = config.get();

  if (!options.buffer_filename.empty()) {
    // TODO(dsinclair): Write buffer file
    assert(false);
  }

  if (!options.image_filename.empty()) {
    amber::BufferInfo buffer_info;
    buffer_info.buffer_name = "framebuffer";
    amber_options.extractions.push_back(buffer_info);
  }

  for (const auto& recipe_data_elem : recipe_data) {
    const auto* recipe = recipe_data_elem.recipe.get();
    const auto& file = recipe_data_elem.file;

    amber::Amber am;
    result = am.Execute(recipe, &amber_options);
    if (!result.IsSuccess()) {
      std::cerr << file << ": " << result.Error() << std::endl;
      failures.push_back(file);
      continue;
    }

    if (!options.image_filename.empty()) {
      std::string image;
      for (amber::BufferInfo buffer_info : amber_options.extractions) {
        if (buffer_info.buffer_name == "framebuffer") {
          std::tie(result, image) = ppm::ConvertToPPM(
              buffer_info.width, buffer_info.height, buffer_info.values);
          break;
        }
      }
      if (!result.IsSuccess()) {
        std::cerr << result.Error() << std::endl;
        continue;
      }
      std::ofstream image_file;
      image_file.open(options.image_filename, std::ios::out | std::ios::binary);
      if (!image_file.is_open()) {
        std::cerr << "Cannot open file for image dump: ";
        std::cerr << options.image_filename << std::endl;
        continue;
      }
      image_file << image;
      image_file.close();
    }
  }

  if (options.show_summary) {
    if (!failures.empty()) {
      std::cout << "\nSummary of Failures:" << std::endl;

      for (const auto& failure : failures)
        std::cout << "  " << failure << std::endl;
    }

    std::cout << "\nSummary: "
              << (options.input_filenames.size() - failures.size()) << " pass, "
              << failures.size() << " fail" << std::endl;

    config_helper.Shutdown();
  }

  return !failures.empty();
}
<commit_msg>Sample app shutdown always (#274)<commit_after>// Copyright 2018 The Amber Authors.
//
// 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 <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <set>
#include <utility>
#include <vector>

#include "amber/amber.h"
#include "amber/recipe.h"
#include "samples/config_helper.h"
#include "samples/ppm.h"
#include "src/build-versions.h"
#include "src/make_unique.h"

namespace {

struct Options {
  std::vector<std::string> input_filenames;

  std::string image_filename;
  std::string buffer_filename;
  int64_t buffer_binding_index = 0;
  uint32_t engine_major = 1;
  uint32_t engine_minor = 0;
  bool parse_only = false;
  bool disable_validation_layer = false;
  bool show_summary = false;
  bool show_help = false;
  bool show_version_info = false;
  amber::EngineType engine = amber::kEngineTypeVulkan;
  std::string spv_env;
};

const char kUsage[] = R"(Usage: amber [options] SCRIPT [SCRIPTS...]

 options:
  -p                  -- Parse input files only; Don't execute.
  -s                  -- Print summary of pass/failure.
  -d                  -- Disable validation layers.
  -t <spirv_env> -- The target SPIR-V environment. Defaults to SPV_ENV_UNIVERSAL_1_0.
  -i <filename>       -- Write rendering to <filename> as a PPM image.
  -b <filename>       -- Write contents of a UBO or SSBO to <filename>.
  -B <buffer>         -- Index of buffer to write. Defaults buffer 0.
  -e <engine>         -- Specify graphics engine: vulkan, dawn. Default is vulkan.
  -v <engine version> -- Engine version (eg, 1.1 for Vulkan). Default 1.0.
  -V, --version       -- Output version information for Amber and libraries.
  -h                  -- This help text.
)";

bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
  for (size_t i = 1; i < args.size(); ++i) {
    const std::string& arg = args[i];
    if (arg == "-i") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -i argument." << std::endl;
        return false;
      }
      opts->image_filename = args[i];

    } else if (arg == "-b") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -b argument." << std::endl;
        return false;
      }
      opts->buffer_filename = args[i];

    } else if (arg == "-B") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -B argument." << std::endl;
        return false;
      }
      opts->buffer_binding_index =
          static_cast<int64_t>(strtol(args[i].c_str(), nullptr, 10));

      if (opts->buffer_binding_index < 0U) {
        std::cerr << "Invalid value for -B, must be 0 or greater." << std::endl;
        return false;
      }

    } else if (arg == "-e") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -e argument." << std::endl;
        return false;
      }
      const std::string& engine = args[i];
      if (engine == "vulkan") {
        opts->engine = amber::kEngineTypeVulkan;
      } else if (engine == "dawn") {
        opts->engine = amber::kEngineTypeDawn;
      } else {
        std::cerr
            << "Invalid value for -e argument. Must be one of: vulkan dawn"
            << std::endl;
        return false;
      }
    } else if (arg == "-t") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -t argument." << std::endl;
        return false;
      }
      opts->spv_env = args[i];
    } else if (arg == "-h" || arg == "--help") {
      opts->show_help = true;
    } else if (arg == "-v") {
      ++i;
      if (i >= args.size()) {
        std::cerr << "Missing value for -v argument." << std::endl;
        return false;
      }
      const std::string& ver = args[i];

      size_t dot_pos = 0;
      int32_t val = std::stoi(ver, &dot_pos);
      if (val < 0) {
        std::cerr << "Version major must be non-negative" << std::endl;
        return false;
      }

      opts->engine_major = static_cast<uint32_t>(val);
      if (dot_pos != std::string::npos && (dot_pos + 1) < ver.size()) {
        val = std::stoi(ver.substr(dot_pos + 1));
        if (val < 0) {
          std::cerr << "Version minor must be non-negative" << std::endl;
          return false;
        }
        opts->engine_minor = static_cast<uint32_t>(val);
      }
    } else if (arg == "-V" || arg == "--version") {
      opts->show_version_info = true;
    } else if (arg == "-p") {
      opts->parse_only = true;
    } else if (arg == "-d") {
      opts->disable_validation_layer = true;
    } else if (arg == "-s") {
      opts->show_summary = true;
    } else if (arg.size() > 0 && arg[0] == '-') {
      std::cerr << "Unrecognized option " << arg << std::endl;
      return false;
    } else if (!arg.empty()) {
      opts->input_filenames.push_back(arg);
    }
  }

  return true;
}

std::string ReadFile(const std::string& input_file) {
  FILE* file = nullptr;
#if defined(_MSC_VER)
  fopen_s(&file, input_file.c_str(), "rb");
#else
  file = fopen(input_file.c_str(), "rb");
#endif
  if (!file) {
    std::cerr << "Failed to open " << input_file << std::endl;
    return {};
  }

  fseek(file, 0, SEEK_END);
  uint64_t tell_file_size = static_cast<uint64_t>(ftell(file));
  if (tell_file_size <= 0) {
    std::cerr << "Input file of incorrect size: " << input_file << std::endl;
    return {};
  }
  fseek(file, 0, SEEK_SET);

  size_t file_size = static_cast<size_t>(tell_file_size);

  std::vector<char> data;
  data.resize(file_size);

  size_t bytes_read = fread(data.data(), sizeof(char), file_size, file);
  fclose(file);
  if (bytes_read != file_size) {
    std::cerr << "Failed to read " << input_file << std::endl;
    return {};
  }

  return std::string(data.begin(), data.end());
}

}  // namespace

int main(int argc, const char** argv) {
  std::vector<std::string> args(argv, argv + argc);
  Options options;

  if (!ParseArgs(args, &options)) {
    std::cerr << "Failed to parse arguments." << std::endl;
    return 1;
  }

  if (options.show_version_info) {
    std::cout << "Amber        : " << AMBER_VERSION << std::endl;
#if AMBER_ENABLE_SPIRV_TOOLS
    std::cout << "SPIRV-Tools  : " << SPIRV_TOOLS_VERSION << std::endl;
    std::cout << "SPIRV-Headers: " << SPIRV_HEADERS_VERSION << std::endl;
#endif  // AMBER_ENABLE_SPIRV_TOOLS
#if AMBER_ENABLE_SHADERC
    std::cout << "GLSLang      : " << GLSLANG_VERSION << std::endl;
    std::cout << "Shaderc      : " << SHADERC_VERSION << std::endl;
#endif  // AMBER_ENABLE_SHADERC
  }

  if (options.show_help) {
    std::cout << kUsage << std::endl;
    return 0;
  }

  if (options.input_filenames.empty()) {
    std::cerr << "Input file must be provided." << std::endl;
    return 2;
  }

  amber::Result result;
  std::vector<std::string> failures;
  struct RecipeData {
    std::string file;
    std::unique_ptr<amber::Recipe> recipe;
  };
  std::vector<RecipeData> recipe_data;
  for (const auto& file : options.input_filenames) {
    auto data = ReadFile(file);
    if (data.empty()) {
      std::cerr << file << " is empty." << std::endl;
      failures.push_back(file);
      continue;
    }

    amber::Amber am;
    std::unique_ptr<amber::Recipe> recipe = amber::MakeUnique<amber::Recipe>();

    result = am.Parse(data, recipe.get());
    if (!result.IsSuccess()) {
      std::cerr << file << ": " << result.Error() << std::endl;
      failures.push_back(file);
      continue;
    }

    recipe_data.emplace_back();
    recipe_data.back().file = file;
    recipe_data.back().recipe = std::move(recipe);
  }

  if (options.parse_only)
    return 0;

  amber::Options amber_options;
  amber_options.engine = options.engine;
  amber_options.spv_env = options.spv_env;

  std::set<std::string> required_features;
  std::set<std::string> required_extensions;
  for (const auto& recipe_data_elem : recipe_data) {
    const auto features = recipe_data_elem.recipe->GetRequiredFeatures();
    required_features.insert(features.begin(), features.end());

    const auto extensions = recipe_data_elem.recipe->GetRequiredExtensions();
    required_extensions.insert(extensions.begin(), extensions.end());
  }

  sample::ConfigHelper config_helper;
  std::unique_ptr<amber::EngineConfig> config;

  amber::Result r = config_helper.CreateConfig(
      amber_options.engine, options.engine_major, options.engine_minor,
      std::vector<std::string>(required_features.begin(),
                               required_features.end()),
      std::vector<std::string>(required_extensions.begin(),
                               required_extensions.end()),
      options.disable_validation_layer, &config);

  if (!r.IsSuccess()) {
    std::cout << r.Error() << std::endl;
    return 1;
  }

  amber_options.config = config.get();

  if (!options.buffer_filename.empty()) {
    // TODO(dsinclair): Write buffer file
    assert(false);
  }

  if (!options.image_filename.empty()) {
    amber::BufferInfo buffer_info;
    buffer_info.buffer_name = "framebuffer";
    amber_options.extractions.push_back(buffer_info);
  }

  for (const auto& recipe_data_elem : recipe_data) {
    const auto* recipe = recipe_data_elem.recipe.get();
    const auto& file = recipe_data_elem.file;

    amber::Amber am;
    result = am.Execute(recipe, &amber_options);
    if (!result.IsSuccess()) {
      std::cerr << file << ": " << result.Error() << std::endl;
      failures.push_back(file);
      continue;
    }

    if (!options.image_filename.empty()) {
      std::string image;
      for (amber::BufferInfo buffer_info : amber_options.extractions) {
        if (buffer_info.buffer_name == "framebuffer") {
          std::tie(result, image) = ppm::ConvertToPPM(
              buffer_info.width, buffer_info.height, buffer_info.values);
          break;
        }
      }
      if (!result.IsSuccess()) {
        std::cerr << result.Error() << std::endl;
        continue;
      }
      std::ofstream image_file;
      image_file.open(options.image_filename, std::ios::out | std::ios::binary);
      if (!image_file.is_open()) {
        std::cerr << "Cannot open file for image dump: ";
        std::cerr << options.image_filename << std::endl;
        continue;
      }
      image_file << image;
      image_file.close();
    }
  }

  if (options.show_summary) {
    if (!failures.empty()) {
      std::cout << "\nSummary of Failures:" << std::endl;

      for (const auto& failure : failures)
        std::cout << "  " << failure << std::endl;
    }

    std::cout << "\nSummary: "
              << (options.input_filenames.size() - failures.size()) << " pass, "
              << failures.size() << " fail" << std::endl;
  }

  config_helper.Shutdown();

  return !failures.empty();
}
<|endoftext|>


<commit_before>/* js_utils.cc
   Jeremy Barnes, 21 July 2010
   Copyright (c) 2010 Datacratic.  All rights reserved.

   Implementation of Javascript utility functions.
*/

#include "js_utils.h"
#include "js_value.h"
#include <cxxabi.h>
#include "jml/arch/demangle.h"
#include "jml/arch/exception_internals.h"
#include "jml/arch/backtrace.h"
#include "jml/utils/string_functions.h"

using namespace std;
using namespace v8;
using namespace ML;

namespace ML {

extern __thread BacktraceInfo * current_backtrace;

} // namespace ML

namespace Datacratic {
namespace JS {

/*****************************************************************************/
/* UTILITIES                                                                 */
/*****************************************************************************/

std::string cstr(const std::string & str)
{
    return str;
}

std::string cstr(const JSValue & val)
{
    return from_js(val, (string *)0);
}

v8::Handle<v8::Value>
injectBacktrace(v8::Handle<v8::Value> value)
{
    if (value.IsEmpty())
        throw ML::Exception("no object passed for backtrace injection");

    v8::Handle<v8::Object> obj(v8::Object::Cast(*value));

    if (obj.IsEmpty())
        throw ML::Exception("can't inject backtrace");

    v8::Handle<v8::Value> js_trace = obj->Get(v8::String::NewSymbol("stack"));

    vector<string> js_trace_elements = split(cstr(js_trace), '\n');

    // Frames to skip:
    // at [C++] ML::backtrace(int)
    // at [C++] Datacratic::JS::injectBacktrace(v8::Handle<v8::Value>)
    // at [C++] Datacratic::JS::mapException(ML::Exception const&)
    // at [C++] Datacratic::JS::translateCurrentException()
    int num_frames_to_skip = 0;

    vector<ML::BacktraceFrame> backtrace;
    if (current_backtrace && abi::__cxa_current_exception_type()) {
        // Skip:
        backtrace = ML::backtrace(*current_backtrace, num_frames_to_skip);
        delete current_backtrace;
        current_backtrace = 0;
    }
    else backtrace = ML::backtrace(num_frames_to_skip);

    string cpp_trace_str = js_trace_elements.at(0) + "\n";

    v8::Handle<v8::Array> cpp_trace(v8::Array::New(backtrace.size() + 1));
    for (unsigned i = 0;  i < backtrace.size();  ++i) {
        cpp_trace_str += "    at [C++] " + backtrace[i].print_for_trace() + "\n";
        cpp_trace->Set(v8::Uint32::New(i),
                       v8::String::New(backtrace[i].print().c_str()));
    }

    for (unsigned i = 1;  i < js_trace_elements.size();  ++i)
        cpp_trace_str += js_trace_elements[i] + "\n";

    cpp_trace->Set(v8::Uint32::New(backtrace.size()), js_trace);

    obj->Set(v8::String::NewSymbol("cpp_trace"), cpp_trace);
    obj->Set(v8::String::NewSymbol("js_trace"), js_trace);
    obj->Set(v8::String::NewSymbol("stack"), v8::String::New(cpp_trace_str.c_str()));

    return obj;
}

v8::Handle<Value>
mapException(const std::exception & exc)
{
    return v8::ThrowException
        (injectBacktrace
         (v8::Exception::Error(v8::String::New((type_name(exc)
                                                + ": " + exc.what()).c_str()))));
}

v8::Handle<Value>
mapException(const ML::Exception & exc)
{
    //cerr << "mapping ML::Exception " << exc.what() << endl;

    return v8::ThrowException
        (injectBacktrace
         (v8::Exception::Error(v8::String::New(exc.what()))));
}

v8::Handle<v8::Value>
translateCurrentException()
{
    if (!std::current_exception()) {
        throw ML::Exception("no exception");
    }

    try {
        throw;
    }
    catch(const JSPassException&) {
        return v8::Handle<v8::Value>();
    }
    catch(const ML::Exception& ex) {
        return mapException(ex);
    }
    catch(const std::exception& ex) {
        return mapException(ex);
    }
    catch(...) {
        std::string msg = "unknown exception type";
        auto error = v8::Exception::Error(v8::String::New(msg.c_str()));
        return v8::ThrowException(injectBacktrace(error));
    }
}

void passJsException(const v8::TryCatch & tc);

struct NullHandle NULL_HANDLE;

ValuePromise getArg(const JSArgs & args, int argnum,
                    const std::string & name)
{
    if (args.Length() <= argnum)
        throw ML::Exception("argument %d (%s) must be present",
                            argnum, name.c_str());

    ValuePromise arg;
    arg.value  = args[argnum];

    if (arg.value->IsUndefined() || arg.value->IsNull())
        throw ML::Exception("argument %d (%s) was %s",
                            argnum, name.c_str(), cstr(arg.value).c_str());

    arg.argnum = argnum;
    arg.name   = name;

    return arg;
}

string getArg(const JSArgs & args, int argnum, const string & defvalue,
         const std::string & name)
{

    return getArg<string>(args, argnum, defvalue, name);
}

/** Convert the given value into a persistent v8 function. */
v8::Persistent<v8::Function>
from_js(const JSValue & val, v8::Persistent<v8::Function> *)
{
    v8::Handle<v8::Function> fn(v8::Function::Cast(*val));
    if (fn.IsEmpty() || !fn->IsFunction()) {
        //cerr << "fn = " << cstr(fn) << endl;
        //cerr << "fn.IsEmpty() = " << fn.IsEmpty() << endl;
        //cerr << "val->IsFunction() = " << val->IsFunction() << endl;
        throw ML::Exception("expected a function; instead we got " + cstr(val));
    }

    return v8::Persistent<v8::Function>::New(fn);
}

v8::Local<v8::Function>
from_js(const JSValue & val, v8::Local<v8::Function> *)
{
    v8::Local<v8::Function> fn(v8::Function::Cast(*val));
    if (fn.IsEmpty() || !fn->IsFunction()) {
        //cerr << "fn = " << cstr(fn) << endl;
        //cerr << "fn.IsEmpty() = " << fn.IsEmpty() << endl;
        //cerr << "val->IsFunction() = " << val->IsFunction() << endl;
        throw ML::Exception("expected a function; instead we got " + cstr(val));
    }

    return fn;
}

v8::Handle<v8::Function>
from_js(const JSValue & val, v8::Handle<v8::Function> *)
{
    v8::Handle<v8::Function> fn(v8::Function::Cast(*val));
    if (fn.IsEmpty() || !fn->IsFunction()) {
        //cerr << "fn = " << cstr(fn) << endl;
        //cerr << "fn.IsEmpty() = " << fn.IsEmpty() << endl;
        //cerr << "val->IsFunction() = " << val->IsFunction() << endl;
        throw ML::Exception("expected a function; instead we got " + cstr(val));
    }

    return fn;
}

v8::Handle<v8::Array>
from_js(const JSValue & val, v8::Handle<v8::Array> *)
{
    v8::Handle<v8::Array> arr(v8::Array::Cast(*val));
    if (arr.IsEmpty() || !arr->IsArray())
        throw ML::Exception("expected an array; instead we got " + cstr(val));

    return arr;
}

v8::Handle<v8::Function>
getFunction(const std::string & script_source)
{
    using namespace v8;

    HandleScope scope;
    Handle<String> source = String::New(script_source.c_str());

    TryCatch tc;

    // Compile the source code.
    Handle<Script> script = Script::Compile(source);

    if (script.IsEmpty() && tc.HasCaught())
        throw ML::Exception("got exception compiling: "
                            + JS::cstr(tc.Exception()));
    if (script.IsEmpty())
        throw ML::Exception("compilation returned nothing");

    // Run the script to get the result (which should be a function)
    Handle<Value> result = script->Run();

    if (result.IsEmpty() && tc.HasCaught())
        throw ML::Exception("got exception compiling: "
                            + JS::cstr(tc.Exception()));
    if (result.IsEmpty())
        throw ML::Exception("compilation returned nothing");
    if (!result->IsFunction())
        throw ML::Exception("result of script isn't a function");

    v8::Local<v8::Function> fnresult(v8::Function::Cast(*result));

    return scope.Close(fnresult);
}

v8::Handle<v8::Array>
getIndexArray(size_t sz)
{
    v8::Handle<v8::Array> result(v8::Array::New(sz));

    for (unsigned i = 0;  i < sz;  ++i) {
        result->Set(v8::Uint32::New(i),
                    v8::Uint32::New(i));
    }

    return result;
}

/** Call a getter function that's in the data field of the given object. */
v8::Handle<v8::Value>
callGetterFn(v8::Local<v8::String> property,
             const v8::AccessorInfo & info)
{
    try {
        HandleScope scope;
        if (!info.Data()->IsFunction())
            throw ML::Exception("isn't a function");
        v8::Local<v8::Function> fn(v8::Function::Cast(*info.Data()));
        if (fn.IsEmpty())
            throw JSPassException();
        const int argc = 1;
        v8::Local<v8::Value> argv[argc] = { property };
        return scope.Close(fn->Call(info.This(), argc, argv));
    } HANDLE_JS_EXCEPTIONS;
}

void printObj(const v8::Handle<v8::Value> & val,
              std::ostream & stream,
              int nesting)
{
    string s(nesting * 4, ' ');
    stream << s << cstr(val) << endl;
    if (val->IsObject()) {
        auto objPtr = v8::Object::Cast(*val);
        if (!objPtr)
            return;

        v8::Local<v8::Array> properties = objPtr->GetPropertyNames();

        for(int i=0; i<properties->Length(); ++i) {
            v8::Local<v8::Value> key = properties->Get(i);
            v8::Local<v8::Value> val = objPtr->Get(key);

            stream << s << "  " << cstr(key) << ": " << cstr(val) << endl;
        }

        v8::Local<v8::Value> proto = objPtr->Get(v8::String::New("prototype"));
        stream << s << "  prototype " << cstr(proto) << endl;
        if (proto->IsObject())
            printObj(proto, stream, nesting + 1);

        v8::Local<v8::Value> proto2 = objPtr->GetPrototype();
        stream << s << "  .__proto__ " << cstr(proto2) << endl;
        if (proto2->IsObject())
            printObj(proto2, stream, nesting + 1);
    }
}

} // namespace JS
} // namespace Datacratic
<commit_msg>replaced catch(...) by JML_CATCH_ALL.<commit_after>/* js_utils.cc
   Jeremy Barnes, 21 July 2010
   Copyright (c) 2010 Datacratic.  All rights reserved.

   Implementation of Javascript utility functions.
*/

#include "js_utils.h"
#include "js_value.h"
#include <cxxabi.h>
#include "jml/arch/demangle.h"
#include "jml/arch/exception_internals.h"
#include "jml/arch/backtrace.h"
#include "jml/utils/string_functions.h"
#include "jml/compiler/compiler.h"

using namespace std;
using namespace v8;
using namespace ML;

namespace ML {

extern __thread BacktraceInfo * current_backtrace;

} // namespace ML

namespace Datacratic {
namespace JS {

/*****************************************************************************/
/* UTILITIES                                                                 */
/*****************************************************************************/

std::string cstr(const std::string & str)
{
    return str;
}

std::string cstr(const JSValue & val)
{
    return from_js(val, (string *)0);
}

v8::Handle<v8::Value>
injectBacktrace(v8::Handle<v8::Value> value)
{
    if (value.IsEmpty())
        throw ML::Exception("no object passed for backtrace injection");

    v8::Handle<v8::Object> obj(v8::Object::Cast(*value));

    if (obj.IsEmpty())
        throw ML::Exception("can't inject backtrace");

    v8::Handle<v8::Value> js_trace = obj->Get(v8::String::NewSymbol("stack"));

    vector<string> js_trace_elements = split(cstr(js_trace), '\n');

    // Frames to skip:
    // at [C++] ML::backtrace(int)
    // at [C++] Datacratic::JS::injectBacktrace(v8::Handle<v8::Value>)
    // at [C++] Datacratic::JS::mapException(ML::Exception const&)
    // at [C++] Datacratic::JS::translateCurrentException()
    int num_frames_to_skip = 0;

    vector<ML::BacktraceFrame> backtrace;
    if (current_backtrace && abi::__cxa_current_exception_type()) {
        // Skip:
        backtrace = ML::backtrace(*current_backtrace, num_frames_to_skip);
        delete current_backtrace;
        current_backtrace = 0;
    }
    else backtrace = ML::backtrace(num_frames_to_skip);

    string cpp_trace_str = js_trace_elements.at(0) + "\n";

    v8::Handle<v8::Array> cpp_trace(v8::Array::New(backtrace.size() + 1));
    for (unsigned i = 0;  i < backtrace.size();  ++i) {
        cpp_trace_str += "    at [C++] " + backtrace[i].print_for_trace() + "\n";
        cpp_trace->Set(v8::Uint32::New(i),
                       v8::String::New(backtrace[i].print().c_str()));
    }

    for (unsigned i = 1;  i < js_trace_elements.size();  ++i)
        cpp_trace_str += js_trace_elements[i] + "\n";

    cpp_trace->Set(v8::Uint32::New(backtrace.size()), js_trace);

    obj->Set(v8::String::NewSymbol("cpp_trace"), cpp_trace);
    obj->Set(v8::String::NewSymbol("js_trace"), js_trace);
    obj->Set(v8::String::NewSymbol("stack"), v8::String::New(cpp_trace_str.c_str()));

    return obj;
}

v8::Handle<Value>
mapException(const std::exception & exc)
{
    return v8::ThrowException
        (injectBacktrace
         (v8::Exception::Error(v8::String::New((type_name(exc)
                                                + ": " + exc.what()).c_str()))));
}

v8::Handle<Value>
mapException(const ML::Exception & exc)
{
    //cerr << "mapping ML::Exception " << exc.what() << endl;

    return v8::ThrowException
        (injectBacktrace
         (v8::Exception::Error(v8::String::New(exc.what()))));
}

v8::Handle<v8::Value>
translateCurrentException()
{
    if (!std::current_exception()) {
        throw ML::Exception("no exception");
    }

    try {
        throw;
    }
    catch(const JSPassException&) {
        return v8::Handle<v8::Value>();
    }
    catch(const ML::Exception& ex) {
        return mapException(ex);
    }
    catch(const std::exception& ex) {
        return mapException(ex);
    }
    JML_CATCH_ALL {
        std::string msg = "unknown exception type";
        auto error = v8::Exception::Error(v8::String::New(msg.c_str()));
        return v8::ThrowException(injectBacktrace(error));
    }
}

void passJsException(const v8::TryCatch & tc);

struct NullHandle NULL_HANDLE;

ValuePromise getArg(const JSArgs & args, int argnum,
                    const std::string & name)
{
    if (args.Length() <= argnum)
        throw ML::Exception("argument %d (%s) must be present",
                            argnum, name.c_str());

    ValuePromise arg;
    arg.value  = args[argnum];

    if (arg.value->IsUndefined() || arg.value->IsNull())
        throw ML::Exception("argument %d (%s) was %s",
                            argnum, name.c_str(), cstr(arg.value).c_str());

    arg.argnum = argnum;
    arg.name   = name;

    return arg;
}

string getArg(const JSArgs & args, int argnum, const string & defvalue,
         const std::string & name)
{

    return getArg<string>(args, argnum, defvalue, name);
}

/** Convert the given value into a persistent v8 function. */
v8::Persistent<v8::Function>
from_js(const JSValue & val, v8::Persistent<v8::Function> *)
{
    v8::Handle<v8::Function> fn(v8::Function::Cast(*val));
    if (fn.IsEmpty() || !fn->IsFunction()) {
        //cerr << "fn = " << cstr(fn) << endl;
        //cerr << "fn.IsEmpty() = " << fn.IsEmpty() << endl;
        //cerr << "val->IsFunction() = " << val->IsFunction() << endl;
        throw ML::Exception("expected a function; instead we got " + cstr(val));
    }

    return v8::Persistent<v8::Function>::New(fn);
}

v8::Local<v8::Function>
from_js(const JSValue & val, v8::Local<v8::Function> *)
{
    v8::Local<v8::Function> fn(v8::Function::Cast(*val));
    if (fn.IsEmpty() || !fn->IsFunction()) {
        //cerr << "fn = " << cstr(fn) << endl;
        //cerr << "fn.IsEmpty() = " << fn.IsEmpty() << endl;
        //cerr << "val->IsFunction() = " << val->IsFunction() << endl;
        throw ML::Exception("expected a function; instead we got " + cstr(val));
    }

    return fn;
}

v8::Handle<v8::Function>
from_js(const JSValue & val, v8::Handle<v8::Function> *)
{
    v8::Handle<v8::Function> fn(v8::Function::Cast(*val));
    if (fn.IsEmpty() || !fn->IsFunction()) {
        //cerr << "fn = " << cstr(fn) << endl;
        //cerr << "fn.IsEmpty() = " << fn.IsEmpty() << endl;
        //cerr << "val->IsFunction() = " << val->IsFunction() << endl;
        throw ML::Exception("expected a function; instead we got " + cstr(val));
    }

    return fn;
}

v8::Handle<v8::Array>
from_js(const JSValue & val, v8::Handle<v8::Array> *)
{
    v8::Handle<v8::Array> arr(v8::Array::Cast(*val));
    if (arr.IsEmpty() || !arr->IsArray())
        throw ML::Exception("expected an array; instead we got " + cstr(val));

    return arr;
}

v8::Handle<v8::Function>
getFunction(const std::string & script_source)
{
    using namespace v8;

    HandleScope scope;
    Handle<String> source = String::New(script_source.c_str());

    TryCatch tc;

    // Compile the source code.
    Handle<Script> script = Script::Compile(source);

    if (script.IsEmpty() && tc.HasCaught())
        throw ML::Exception("got exception compiling: "
                            + JS::cstr(tc.Exception()));
    if (script.IsEmpty())
        throw ML::Exception("compilation returned nothing");

    // Run the script to get the result (which should be a function)
    Handle<Value> result = script->Run();

    if (result.IsEmpty() && tc.HasCaught())
        throw ML::Exception("got exception compiling: "
                            + JS::cstr(tc.Exception()));
    if (result.IsEmpty())
        throw ML::Exception("compilation returned nothing");
    if (!result->IsFunction())
        throw ML::Exception("result of script isn't a function");

    v8::Local<v8::Function> fnresult(v8::Function::Cast(*result));

    return scope.Close(fnresult);
}

v8::Handle<v8::Array>
getIndexArray(size_t sz)
{
    v8::Handle<v8::Array> result(v8::Array::New(sz));

    for (unsigned i = 0;  i < sz;  ++i) {
        result->Set(v8::Uint32::New(i),
                    v8::Uint32::New(i));
    }

    return result;
}

/** Call a getter function that's in the data field of the given object. */
v8::Handle<v8::Value>
callGetterFn(v8::Local<v8::String> property,
             const v8::AccessorInfo & info)
{
    try {
        HandleScope scope;
        if (!info.Data()->IsFunction())
            throw ML::Exception("isn't a function");
        v8::Local<v8::Function> fn(v8::Function::Cast(*info.Data()));
        if (fn.IsEmpty())
            throw JSPassException();
        const int argc = 1;
        v8::Local<v8::Value> argv[argc] = { property };
        return scope.Close(fn->Call(info.This(), argc, argv));
    } HANDLE_JS_EXCEPTIONS;
}

void printObj(const v8::Handle<v8::Value> & val,
              std::ostream & stream,
              int nesting)
{
    string s(nesting * 4, ' ');
    stream << s << cstr(val) << endl;
    if (val->IsObject()) {
        auto objPtr = v8::Object::Cast(*val);
        if (!objPtr)
            return;

        v8::Local<v8::Array> properties = objPtr->GetPropertyNames();

        for(int i=0; i<properties->Length(); ++i) {
            v8::Local<v8::Value> key = properties->Get(i);
            v8::Local<v8::Value> val = objPtr->Get(key);

            stream << s << "  " << cstr(key) << ": " << cstr(val) << endl;
        }

        v8::Local<v8::Value> proto = objPtr->Get(v8::String::New("prototype"));
        stream << s << "  prototype " << cstr(proto) << endl;
        if (proto->IsObject())
            printObj(proto, stream, nesting + 1);

        v8::Local<v8::Value> proto2 = objPtr->GetPrototype();
        stream << s << "  .__proto__ " << cstr(proto2) << endl;
        if (proto2->IsObject())
            printObj(proto2, stream, nesting + 1);
    }
}

} // namespace JS
} // namespace Datacratic
<|endoftext|>


<commit_before>#include <FImage.h>
#include <stdint.h>

using namespace FImage;

Var x, y, c;

Func hot_pixel_suppression(Func input) {
    Expr max = Max(Max(input(x-2, y), input(x+2, y)),
                   Max(input(x, y-2), input(x, y+2)));
    Expr min = Min(Min(input(x-2, y), input(x+2, y)),
                   Min(input(x, y-2), input(x, y+2)));

    Func denoised("denoised");
    denoised(x, y) = Clamp(input(x, y), min, max);

    return denoised;
}

Expr abs(Expr e) {
    return Select(e < Cast(e.type(), 0), -e, e);
}

Func interleave_x(Func a, Func b) {
    Func out;
    out(x, y) = Select((x%2)==0, a(x/2, y), b(x/2, y));
    return out;
}

Func interleave_y(Func a, Func b) {
    Func out;
    out(x, y) = Select((y%2)==0, a(x, y/2), b(x, y/2));
    return out;
}

Func demosaic(Func raw) {
    // These are the values we already know from the input
    // x_y = the value of channel x at a site in the input of channel y
    // gb refers to green sites in the blue rows
    // gr refers to green sites in the red rows
    Func r_r("r_r"), g_gr("g_gr"), g_gb("g_gb"), b_b("b_b");
    g_gr(x, y) = raw(2*x, 2*y);
    r_r(x, y)  = raw(2*x+1, 2*y);
    b_b(x, y)  = raw(2*x, 2*y+1);
    g_gb(x, y) = raw(2*x+1, 2*y+1);

    // These are the ones we need to interpolate
    Func b_r("b_r"), g_r("g_r");
    Func b_gr("b_gr"), r_gr("r_gr");
    Func b_gb("b_gb"), r_gb("r_gb");
    Func r_b("r_b"), g_b("g_b");

    // First calculate green at the red and blue sites

    // Try interpolating vertically and horizontally. Also compute
    // differences vertically and horizontally. Use interpolation in
    // whichever direction had the smallest difference.
    Expr gv_r  =    (g_gb(x, y-1) + g_gb(x, y))/2;
    Expr gvd_r = abs(g_gb(x, y-1) - g_gb(x, y));
    Expr gh_r  =    (g_gr(x+1, y) + g_gr(x, y))/2;
    Expr ghd_r = abs(g_gr(x+1, y) - g_gr(x, y));

    g_r(x, y)  = Select(ghd_r < gvd_r, gh_r, gv_r);

    Expr gv_b  =    (g_gr(x, y+1) + g_gr(x, y))/2;
    Expr gvd_b = abs(g_gr(x, y+1) - g_gr(x, y));
    Expr gh_b  =    (g_gb(x-1, y) + g_gb(x, y))/2;
    Expr ghd_b = abs(g_gb(x-1, y) - g_gb(x, y));

    g_b(x, y)  = Select(ghd_b < gvd_b, gh_b, gv_b);

    // Next interpolate red at gr by first interpolating, then
    // correcting using the error green would have had if we had
    // interpolated it in the same way (i.e. add the second derivative
    // of the green channel at the same place).
    Expr correction;
    correction = g_gr(x, y) - (g_r(x, y) + g_r(x-1, y))/2;
    r_gr(x, y) = correction + (r_r(x-1, y) + r_r(x, y))/2;

    // Do the same for other reds and blues at green sites
    correction = g_gr(x, y) - (g_b(x, y) + g_b(x, y-1))/2;
    b_gr(x, y) = correction + (b_b(x, y) + b_b(x, y-1))/2;

    correction = g_gb(x, y) - (g_r(x, y) + g_r(x, y+1))/2;
    r_gb(x, y) = correction + (r_r(x, y) + r_r(x, y+1))/2;

    correction = g_gb(x, y) - (g_b(x, y) + g_b(x+1, y))/2;
    b_gb(x, y) = correction + (b_b(x, y) + b_b(x+1, y))/2;

    // Now interpolate diagonally to get red at blue and blue at
    // red. Hold onto your hats; this gets really fancy. We do the
    // same thing as for interpolating green where we try both
    // directions (in this case the positive and negative diagonals),
    // and use the one with the lowest absolute difference. But we
    // also use the same trick as interpolating red and blue at green
    // sites - we correct our interpolations using the second
    // derivative of green at the same sites.

    correction = g_b(x, y)  - (g_r(x, y) + g_r(x-1, y+1))/2;
    Expr rp_b  = correction + (r_r(x, y) + r_r(x-1, y+1))/2;
    Expr rpd_b = abs(r_r(x, y) - r_r(x-1, y+1));

    correction = g_b(x, y)  - (g_r(x-1, y) + g_r(x, y+1))/2;
    Expr rn_b  = correction + (r_r(x-1, y) + r_r(x, y+1))/2;
    Expr rnd_b = abs(r_r(x-1, y) - r_r(x, y+1));

    r_b(x, y)  = Select(rpd_b < rnd_b, rp_b, rn_b);

    // Same thing for blue at red
    correction = g_r(x, y)  - (g_b(x, y) + g_b(x+1, y-1))/2;
    Expr bp_r  = correction + (b_b(x, y) + b_b(x+1, y-1))/2;
    Expr bpd_r = abs(b_b(x, y) - b_b(x+1, y-1));

    correction = g_r(x, y)  - (g_b(x+1, y) + g_b(x, y-1))/2;
    Expr bn_r  = correction + (b_b(x+1, y) + b_b(x, y-1))/2;
    Expr bnd_r = abs(b_b(x+1, y) - b_b(x, y-1));

    b_r(x, y)  =  Select(bpd_r < bnd_r, bp_r, bn_r);

    // Interleave the resulting channels
    Func r = interleave_y(interleave_x(r_gr, r_r),
                          interleave_x(r_b, r_gb));
    Func g = interleave_y(interleave_x(g_gr, g_r),
                          interleave_x(g_b, g_gb));
    Func b = interleave_y(interleave_x(b_gr, b_r),
                          interleave_x(b_b, b_gb));

    Func output("dem");
    output(x, y) = (r(x, y), g(x, y), b(x, y));

    return output;
}

Func color_correct(Func input, UniformImage matrix_3200, UniformImage matrix_7000, Uniform<float> kelvin) {
    // Get a color matrix by linearly interpolating between two
    // calibrated matrices using inverse kelvin.

    Func matrix;
    Expr alpha = (1.0f/kelvin - 1.0f/3200) / (1.0f/7000 - 1.0f/3200);
    matrix(x, y) = (matrix_3200(x, y) * alpha +
                    matrix_7000(x, y) * (1 - alpha));

    Func corrected;
    RVar j(0, 3);
    corrected(x, y, c) = Cast<int16_t>(Sum(matrix(j, c)*Cast<float>(input(x, y, j))) + matrix(3, c));
    return corrected;
}

Func apply_curve(Func input, Uniform<float> gamma, Uniform<float> contrast) {
    // copied from FCam
    Func curve("curve");

    Expr xf = Cast<float>(x)/1024.0f;
    Expr g = pow(xf, 1.0f/gamma);
    Expr b = 2.0f - pow(2.0f, contrast/100.0f);
    Expr a = 2.0f - 2.0f*b;
    Expr z = Select(g > 0.5f,
                    1.0f - (a*(1.0f-g)*(1.0f-g) + b*(1.0f-g)),
                    a*g*g + b*g);
    Expr val = Cast<uint8_t>(Clamp(z*256.0f, 0.0f, 255.0f));
    curve(x) = val; //Debug(val, "curve ", x, xf, g, z, val);

    Func curved("curved");
    // This is after the color transform, so the input could be
    // negative or very large. Clamp it back to 10 bits before applying the curve.
    curved(x, y, c) = curve(Clamp(Cast<int32_t>(input(x, y, c)), 0, 1023));
    return curved;
}

/*
Func rgb_to_yuv422(Func rgb) {
    Func Y;
    Func U;
    Func V;
    Func UV;
    Func YUV;
}
*/

Func process(Func raw,
             UniformImage matrix_3200, UniformImage matrix_7000, Uniform<float> color_temp,
             Uniform<float> gamma, Uniform<float> contrast) {
    Func im = raw;
    im = hot_pixel_suppression(im);
    im = demosaic(im);
    im = color_correct(im, matrix_3200, matrix_7000, color_temp);
    im = apply_curve(im, gamma, contrast);

    /*
    Func check;
    Var x, y, c;
    check(x, y, c) = Debug(im(x, y, c), "after curve ", x, y, c, im(x, y, c));
    im = check;
    */

    //im = rgb_to_yuv422(im);
    return im;
}

int main(int argc, char **argv) {
    UniformImage input(UInt(16), 2, "raw");
    UniformImage matrix_3200(Float(32), 2, "m3200"), matrix_7000(Float(32), 2, "m7000");
    Uniform<float> color_temp("color_temp", 3200.0f);
    Uniform<float> gamma("gamma", 1.8f);
    Uniform<float> contrast("contrast", 10.0f);

    // add a boundary condition and treat things as signed ints
    // (demosaic might introduce negative values)
    Func clamped("in");
    clamped(x, y) = Cast<int16_t>(input(Clamp(x, 0, input.width()-1),
                                        Clamp(y, 0, input.height()-1)));

    // Run the pipeline
    Func processed = process(clamped, matrix_3200, matrix_7000, color_temp, gamma, contrast);

    // Pick a schedule

    if (argc > 1)
        srand(atoi(argv[1]));
    else
        srand(0);

    Var xo("xo"), yo("yo"), c("c"), xi("xi"), yi("yi");
    Func output;
    output(xo, yo, c) = processed(xo, yo, c);
    output.root().tile(xo, yo, xi, yi, 32, 16).transpose(yo, c).transpose(xo, c);

    std::vector<Func> funcs = output.rhs().funcs();

    for (size_t i = 0; i < funcs.size(); i++) {
      if (funcs[i].name() == "curve") funcs[i].root();
      else funcs[i].chunk(xo);
      //if (funcs[i].returnType() == UInt(8)) funcs[i].vectorize(x, 16);
      //if (funcs[i].returnType() == Int(16)) funcs[i].vectorize(x, 8);
      //if (funcs[i].returnType() == Float(32)) funcs[i].vectorize(x, 4);
    }

    output.compileToFile("curved");

    return 0;
}

<commit_msg>Updated camera_pipe example<commit_after>#include <FImage.h>
#include <stdint.h>

using namespace FImage;

Var x, y, c;

Func hot_pixel_suppression(Func input) {
    Expr max = Max(Max(input(x-2, y), input(x+2, y)),
                   Max(input(x, y-2), input(x, y+2)));
    Expr min = Min(Min(input(x-2, y), input(x+2, y)),
                   Min(input(x, y-2), input(x, y+2)));

    Func denoised("denoised");
    denoised(x, y) = Clamp(input(x, y), min, max);

    return denoised;
}

Expr abs(Expr e) {
    return Select(e < Cast(e.type(), 0), -e, e);
}

Func interleave_x(Func a, Func b) {
    Func out;
    out(x, y) = Select((x%2)==0, a(x/2, y), b(x/2, y));
    return out;
}

Func interleave_y(Func a, Func b) {
    Func out;
    out(x, y) = Select((y%2)==0, a(x, y/2), b(x, y/2));
    return out;
}

Func demosaic(Func raw) {
    // These are the values we already know from the input
    // x_y = the value of channel x at a site in the input of channel y
    // gb refers to green sites in the blue rows
    // gr refers to green sites in the red rows
    Func r_r("r_r"), g_gr("g_gr"), g_gb("g_gb"), b_b("b_b");
    g_gr(x, y) = raw(2*x, 2*y);
    r_r(x, y)  = raw(2*x+1, 2*y);
    b_b(x, y)  = raw(2*x, 2*y+1);
    g_gb(x, y) = raw(2*x+1, 2*y+1);

    // These are the ones we need to interpolate
    Func b_r("b_r"), g_r("g_r");
    Func b_gr("b_gr"), r_gr("r_gr");
    Func b_gb("b_gb"), r_gb("r_gb");
    Func r_b("r_b"), g_b("g_b");

    // First calculate green at the red and blue sites

    // Try interpolating vertically and horizontally. Also compute
    // differences vertically and horizontally. Use interpolation in
    // whichever direction had the smallest difference.
    Expr gv_r  =    (g_gb(x, y-1) + g_gb(x, y))/2;
    Expr gvd_r = abs(g_gb(x, y-1) - g_gb(x, y));
    Expr gh_r  =    (g_gr(x+1, y) + g_gr(x, y))/2;
    Expr ghd_r = abs(g_gr(x+1, y) - g_gr(x, y));

    g_r(x, y)  = Select(ghd_r < gvd_r, gh_r, gv_r);

    Expr gv_b  =    (g_gr(x, y+1) + g_gr(x, y))/2;
    Expr gvd_b = abs(g_gr(x, y+1) - g_gr(x, y));
    Expr gh_b  =    (g_gb(x-1, y) + g_gb(x, y))/2;
    Expr ghd_b = abs(g_gb(x-1, y) - g_gb(x, y));

    g_b(x, y)  = Select(ghd_b < gvd_b, gh_b, gv_b);

    // Next interpolate red at gr by first interpolating, then
    // correcting using the error green would have had if we had
    // interpolated it in the same way (i.e. add the second derivative
    // of the green channel at the same place).
    Expr correction;
    correction = g_gr(x, y) - (g_r(x, y) + g_r(x-1, y))/2;
    r_gr(x, y) = correction + (r_r(x-1, y) + r_r(x, y))/2;

    // Do the same for other reds and blues at green sites
    correction = g_gr(x, y) - (g_b(x, y) + g_b(x, y-1))/2;
    b_gr(x, y) = correction + (b_b(x, y) + b_b(x, y-1))/2;

    correction = g_gb(x, y) - (g_r(x, y) + g_r(x, y+1))/2;
    r_gb(x, y) = correction + (r_r(x, y) + r_r(x, y+1))/2;

    correction = g_gb(x, y) - (g_b(x, y) + g_b(x+1, y))/2;
    b_gb(x, y) = correction + (b_b(x, y) + b_b(x+1, y))/2;

    // Now interpolate diagonally to get red at blue and blue at
    // red. Hold onto your hats; this gets really fancy. We do the
    // same thing as for interpolating green where we try both
    // directions (in this case the positive and negative diagonals),
    // and use the one with the lowest absolute difference. But we
    // also use the same trick as interpolating red and blue at green
    // sites - we correct our interpolations using the second
    // derivative of green at the same sites.

    correction = g_b(x, y)  - (g_r(x, y) + g_r(x-1, y+1))/2;
    Expr rp_b  = correction + (r_r(x, y) + r_r(x-1, y+1))/2;
    Expr rpd_b = abs(r_r(x, y) - r_r(x-1, y+1));

    correction = g_b(x, y)  - (g_r(x-1, y) + g_r(x, y+1))/2;
    Expr rn_b  = correction + (r_r(x-1, y) + r_r(x, y+1))/2;
    Expr rnd_b = abs(r_r(x-1, y) - r_r(x, y+1));

    r_b(x, y)  = Select(rpd_b < rnd_b, rp_b, rn_b);

    // Same thing for blue at red
    correction = g_r(x, y)  - (g_b(x, y) + g_b(x+1, y-1))/2;
    Expr bp_r  = correction + (b_b(x, y) + b_b(x+1, y-1))/2;
    Expr bpd_r = abs(b_b(x, y) - b_b(x+1, y-1));

    correction = g_r(x, y)  - (g_b(x+1, y) + g_b(x, y-1))/2;
    Expr bn_r  = correction + (b_b(x+1, y) + b_b(x, y-1))/2;
    Expr bnd_r = abs(b_b(x+1, y) - b_b(x, y-1));

    b_r(x, y)  =  Select(bpd_r < bnd_r, bp_r, bn_r);

    // Interleave the resulting channels
    Func r = interleave_y(interleave_x(r_gr, r_r),
                          interleave_x(r_b, r_gb));
    Func g = interleave_y(interleave_x(g_gr, g_r),
                          interleave_x(g_b, g_gb));
    Func b = interleave_y(interleave_x(b_gr, b_r),
                          interleave_x(b_b, b_gb));

    Func output("dem");
    output(x, y) = (r(x, y), g(x, y), b(x, y));

    return output;
}

Func color_correct(Func input, UniformImage matrix_3200, UniformImage matrix_7000, Uniform<float> kelvin) {
    // Get a color matrix by linearly interpolating between two
    // calibrated matrices using inverse kelvin.

    Func matrix("matrix");
    Expr alpha = (1.0f/kelvin - 1.0f/3200) / (1.0f/7000 - 1.0f/3200);
    matrix(x, y) = (matrix_3200(x, y) * alpha +
                    matrix_7000(x, y) * (1 - alpha));

    Func corrected("corrected");
    RVar j(0, 3);
    corrected(x, y, c) = Cast<int16_t>(Sum(matrix(j, c)*Cast<float>(input(x, y, j))) + matrix(3, c));
    return corrected;
}

Func apply_curve(Func input, Uniform<float> gamma, Uniform<float> contrast) {
    // copied from FCam
    Func curve("curve");

    Expr xf = Cast<float>(x)/1024.0f;
    Expr g = pow(xf, 1.0f/gamma);
    Expr b = 2.0f - pow(2.0f, contrast/100.0f);
    Expr a = 2.0f - 2.0f*b;
    Expr z = Select(g > 0.5f,
                    1.0f - (a*(1.0f-g)*(1.0f-g) + b*(1.0f-g)),
                    a*g*g + b*g);
    Expr val = Cast<uint8_t>(Clamp(z*256.0f, 0.0f, 255.0f));
    curve(x) = val; //Debug(val, "curve ", x, xf, g, z, val);

    Func curved("curved");
    // This is after the color transform, so the input could be
    // negative or very large. Clamp it back to 10 bits before applying the curve.
    curved(x, y, c) = curve(Clamp(Cast<int32_t>(input(x, y, c)), 0, 1023));
    return curved;
}

/*
Func rgb_to_yuv422(Func rgb) {
    Func Y;
    Func U;
    Func V;
    Func UV;
    Func YUV;
}
*/

Func process(Func raw,
             UniformImage matrix_3200, UniformImage matrix_7000, Uniform<float> color_temp,
             Uniform<float> gamma, Uniform<float> contrast) {
    Func im = raw;
    im = hot_pixel_suppression(im);
    im = demosaic(im);
    im = color_correct(im, matrix_3200, matrix_7000, color_temp);
    im = apply_curve(im, gamma, contrast);

    /*
    Func check;
    Var x, y, c;
    check(x, y, c) = Debug(im(x, y, c), "after curve ", x, y, c, im(x, y, c));
    im = check;
    */

    //im = rgb_to_yuv422(im);
    return im;
}

int main(int argc, char **argv) {
    UniformImage input(UInt(16), 2, "raw");
    UniformImage matrix_3200(Float(32), 2, "m3200"), matrix_7000(Float(32), 2, "m7000");
    Uniform<float> color_temp("color_temp", 3200.0f);
    Uniform<float> gamma("gamma", 1.8f);
    Uniform<float> contrast("contrast", 10.0f);

    // add a boundary condition and treat things as signed ints
    // (demosaic might introduce negative values)
    Func clamped("in");
    clamped(x, y) = Cast<int16_t>(input(Clamp(x, 0, input.width()-1),
                                        Clamp(y, 0, input.height()-1)));

    // Run the pipeline
    Func processed = process(clamped, matrix_3200, matrix_7000, color_temp, gamma, contrast);

    // Pick a schedule

    if (argc > 1)
        srand(atoi(argv[1]));
    else
        srand(0);

    Var xo("xo"), yo("yo"), c("c"), xi("xi"), yi("yi");
    Func output;
    output(xo, yo, c) = processed(xo, yo, c);
    output.root().tile(xo, yo, xi, yi, 32, 16).transpose(yo, c).transpose(xo, c);

    std::vector<Func> funcs = output.rhs().funcs();

    for (size_t i = 0; i < funcs.size(); i++) {
      if (funcs[i] == processed) {} // inline
      else if (funcs[i].name() == "curve") funcs[i].root();
      else funcs[i].chunk(xo);
      //if (funcs[i].returnType() == UInt(8)) funcs[i].vectorize(x, 16);
      //if (funcs[i].returnType() == Int(16)) funcs[i].vectorize(x, 8);
      //if (funcs[i].returnType() == Float(32)) funcs[i].vectorize(x, 4);
    }

    output.compileToFile("curved");

    return 0;
}

<|endoftext|>


<commit_before>#include <omp.h>
#include <stdlib.h>
#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <condition_variable>

using namespace std;

const int SCALE = 1500;

const int W = SCALE*2;
const int H = SCALE;
const int T = SCALE*2;

double field[H][W];
double field1[H][W];

const int OBS_N = 19;

double obs_seq[OBS_N];
double seq_max, seq_mid, seq_min;

double obs_omp[OBS_N];
double omp_max, omp_mid, omp_min;

double obs_tet[OBS_N];
double tet_max, tet_mid, tet_min;

void shufle()
{
	srand(0);
	for(int i=0;i<H;i++)
	for(int j=0;j<W;j++) field[i][j]=rand();
}

void shufle1()
{
	srand(0);
	for(int i=0;i<H;i++)
	for(int j=0;j<W;j++) field1[i][j]=rand();
}

void op(int i)
{
	for (int j=1; j<W-1; j++)
		field[i][j]=(field[i][j-1]+field[i][j+1]+
			field[i-1][j]+field[i+1][j])*0.25;
}

void op1(int i)
{
	for (int j = 1; j<W - 1; j++)
		field1[i][j] = (field1[i][j - 1] + field1[i][j + 1] +
		field1[i - 1][j] + field1[i + 1][j])*0.25;
}

double seq_alg()
{
	double time=omp_get_wtime();

	for (int t=1;t<=T;t++)
	for (int i=1;i<H-1;i++) op1(i);

	return omp_get_wtime() - time;
}

double par_omp()
{
	double time = omp_get_wtime();

#pragma omp parallel shared(H,T)
{
	for (int t = 1; t <= (2 * T - 1) + (H - 3); t++){

		if (t % 2 == 1){
#pragma omp for schedule(dynamic,1)
			for (int i = 1; i<H - 1; i += 2)
				if (i <= t && i>t - 2 * T)	op(i);
		}
		if (t % 2 == 0){
#pragma omp for schedule(dynamic,1)
			for (int i = 2; i<H - 1; i += 2)
				if (i <= t && i>t - 2 * T)	op(i);
		}
	}
}
	return omp_get_wtime() - time;
}

bool compare()
{
	for(int i=0; i<H; i++)
	for(int j=0; j<W; j++) if(field1[i][j]!=field[i][j])return false;
	return true;
}

void min_max()
{
	seq_max = seq_min = obs_seq[0];
	omp_max = omp_min = obs_omp[0];
	tet_max = tet_min = obs_tet[0];

	for (int i = 1; i < OBS_N; i++){
		seq_max = obs_seq[i] > seq_max ? obs_seq[i] : seq_max;
		seq_min = obs_seq[i] < seq_min ? obs_seq[i] : seq_min;

		omp_max = obs_omp[i] > omp_max ? obs_omp[i] : omp_max;
		omp_min = obs_omp[i] < omp_min ? obs_omp[i] : omp_min;

		tet_max = obs_tet[i] > tet_max ? obs_tet[i] : tet_max;
		tet_min = obs_tet[i] < tet_min ? obs_tet[i] : tet_min;
	}
	seq_mid = (seq_min + seq_max) / 2;
	omp_mid = (omp_min + omp_max) / 2;
	tet_mid = (tet_min + tet_max) / 2;
}

struct message;
struct actor;

struct engine{
	volatile int active;
	std::mutex mtx;
	std::condition_variable cv;
	std::queue<message*> ready;
};

struct actor{
	std::mutex mtx;
	void(*recv)(message*, actor*);
};

struct message{
	actor*a;
	bool sending;
};

inline void send(engine*e, message*m, actor*a)
{
	if (m->sending) return;
	m->sending = true;	m->a = a;
	std::unique_lock<std::mutex> lck(e->mtx);
	e->ready.push(m);	e->cv.notify_one();
}

inline bool access(message*m, actor*a)
{
	return m->a == a && !m->sending;
}

void tfunc(engine*e)
{
	message*m; actor*a;

	for (;;){
		{
			std::unique_lock<std::mutex> lck(e->mtx);
			while (e->ready.empty()){
				e->active--;
				if (!e->active){ e->cv.notify_one(); return; }
				e->cv.wait(lck);
				e->active++;
			}
			m = e->ready.front();
			e->ready.pop();
		}
		a = m->a;
		{
			std::unique_lock<std::mutex> lck(a->mtx);
			m->sending = false;
			a->recv(m, a);
		}
	}
}

double run(engine*e, int n = 1)
{
	std::vector<std::thread> threads(n);
	e->active = n;
	for (int i = 0; i<n; i++) threads[i] = std::thread(tfunc, e);
	double start = omp_get_wtime();
	for (auto& th : threads) th.join();
	return omp_get_wtime() - start;
}

const int N = H - 2;

engine e;
actor  as[N];
message ms[N - 1];
int  ts[N];

void recv(message* , actor* a)
{
	int id = (int)(a - as);

	if ((id == 0 || access(&ms[id - 1], a)) &&
		(id == N - 1 || access(&ms[id], a)) &&
		(ts[id] <= T)){

		op(id+1);	ts[id]++;

		if (id != 0)	send(&e, &ms[id - 1], &as[id - 1]);
		if (id != N - 1)	send(&e, &ms[id], &as[id + 1]);
	}
}

double par_tet()
{
	for (int i = 0; i < N; i++)
	{
		as[i].recv = recv; ts[i] = 1;
	}
	for (int i = 0; i < N - 1; i++)
	{
		ms[i].a = &as[i]; ms[i].sending = false;
	}
	send(&e, &ms[0], &as[0]);

	return run(&e, omp_get_max_threads());
}

void main()
{
	for (int i = 0; i < OBS_N; i++){
		shufle1();	obs_seq[i] = seq_alg();
		shufle();	obs_omp[i] = par_omp(); cout << (compare() ? "OMP Ok " : "something wrong in OMP ");
		shufle();	obs_tet[i] = par_tet(); cout << (compare() ? "Templet Ok " : "something wrong in Templet ");
		cout << (int)((float)(i+1)/OBS_N*100) << "% done" << endl;
	}

	min_max();

	cout << "\nTest results for H = " << H << "; W = " << W << "; T = " << T << "; OMP max threads  = " << omp_get_max_threads() << "\n";

	cout << "\nseq_min  = " << seq_min << " sec; " << "\nseq_mid  = " << seq_mid <<" sec; \nseq_max  = " << seq_max << " sec\n";
	cout << "\nomp_min  = " << omp_min << " sec; " << "\nomp_mid  = " << omp_mid << " sec; \nomp_max  = " << omp_max << " sec\n";
	cout << "\ntet_min  = " << tet_min << " sec; " << "\ntet_mid  = " << tet_mid << " sec; \ntet_max  = " << tet_max << " sec\n";
}

/*
public class MyActor extends UntypedActor{
	public int id;

	public bool access_ms_id_minus_1 = false;
	public bool access_ms_id = false;

	public ActorRef id_minus_1 = null;
	public ActorRef id_plus_1 = null;

	public void onRecieve(Object m){ // Akka analog of void recv(message* , actor* a)
		access_ms_id_1 = ((Integer)m.intValue() == id - 1);
		access_ms_id = ((Integer)m.intValue == id);

		if ((id == 0 || access_ms_id_minus_1) &&
			(id == N - 1 || access_ms_id)) &&
			(ts[id] <= T)){

			op(id + 1);	ts[id]++;

			if (id != 0)	 id_minus_1.sendOneWay(Integer(id - 1));
			if (id != N - 1) id_plus_1.sendOneWay(Integer(id));
		}
	}
}
*/<commit_msg>renaming<commit_after>#include <omp.h>
#include <stdlib.h>
#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <condition_variable>

using namespace std;

const int SCALE = 1500;

const int W = SCALE*2;
const int H = SCALE;
const int T = SCALE*2;

double field[H][W];
double field1[H][W];

const int OBS_N = 19;

double obs_seq[OBS_N];
double seq_max, seq_mid, seq_min;

double obs_omp[OBS_N];
double omp_max, omp_mid, omp_min;

double obs_tet[OBS_N];
double tet_max, tet_mid, tet_min;

void shufle()
{
	srand(0);
	for(int i=0;i<H;i++)
	for(int j=0;j<W;j++) field[i][j]=rand();
}

void shufle1()
{
	srand(0);
	for(int i=0;i<H;i++)
	for(int j=0;j<W;j++) field1[i][j]=rand();
}

void op(int i)
{
	for (int j=1; j<W-1; j++)
		field[i][j]=(field[i][j-1]+field[i][j+1]+
			field[i-1][j]+field[i+1][j])*0.25;
}

void op1(int i)
{
	for (int j = 1; j<W - 1; j++)
		field1[i][j] = (field1[i][j - 1] + field1[i][j + 1] +
		field1[i - 1][j] + field1[i + 1][j])*0.25;
}

double seq_alg()
{
	double time=omp_get_wtime();

	for (int t=1;t<=T;t++)
	for (int i=1;i<H-1;i++) op1(i);

	return omp_get_wtime() - time;
}

double par_omp()
{
	double time = omp_get_wtime();

#pragma omp parallel shared(H,T)
{
	for (int t = 1; t <= (2 * T - 1) + (H - 3); t++){

		if (t % 2 == 1){
#pragma omp for schedule(dynamic,1)
			for (int i = 1; i<H - 1; i += 2)
				if (i <= t && i>t - 2 * T)	op(i);
		}
		if (t % 2 == 0){
#pragma omp for schedule(dynamic,1)
			for (int i = 2; i<H - 1; i += 2)
				if (i <= t && i>t - 2 * T)	op(i);
		}
	}
}
	return omp_get_wtime() - time;
}

bool compare()
{
	for(int i=0; i<H; i++)
	for(int j=0; j<W; j++) if(field1[i][j]!=field[i][j])return false;
	return true;
}

void min_max()
{
	seq_max = seq_min = obs_seq[0];
	omp_max = omp_min = obs_omp[0];
	tet_max = tet_min = obs_tet[0];

	for (int i = 1; i < OBS_N; i++){
		seq_max = obs_seq[i] > seq_max ? obs_seq[i] : seq_max;
		seq_min = obs_seq[i] < seq_min ? obs_seq[i] : seq_min;

		omp_max = obs_omp[i] > omp_max ? obs_omp[i] : omp_max;
		omp_min = obs_omp[i] < omp_min ? obs_omp[i] : omp_min;

		tet_max = obs_tet[i] > tet_max ? obs_tet[i] : tet_max;
		tet_min = obs_tet[i] < tet_min ? obs_tet[i] : tet_min;
	}
	seq_mid = (seq_min + seq_max) / 2;
	omp_mid = (omp_min + omp_max) / 2;
	tet_mid = (tet_min + tet_max) / 2;
}

struct message;
struct actor;

struct engine{
	volatile int active;
	std::mutex mtx;
	std::condition_variable cv;
	std::queue<message*> ready;
};

struct actor{
	std::mutex mtx;
	void(*recv)(message*, actor*);
};

struct message{
	actor*a;
	bool sending;
};

inline void send(engine*e, message*m, actor*a)
{
	if (m->sending) return;
	m->sending = true;	m->a = a;
	std::unique_lock<std::mutex> lck(e->mtx);
	e->ready.push(m);	e->cv.notify_one();
}

inline bool access(message*m, actor*a)
{
	return m->a == a && !m->sending;
}

void tfunc(engine*e)
{
	message*m; actor*a;

	for (;;){
		{
			std::unique_lock<std::mutex> lck(e->mtx);
			while (e->ready.empty()){
				e->active--;
				if (!e->active){ e->cv.notify_one(); return; }
				e->cv.wait(lck);
				e->active++;
			}
			m = e->ready.front();
			e->ready.pop();
		}
		a = m->a;
		{
			std::unique_lock<std::mutex> lck(a->mtx);
			m->sending = false;
			a->recv(m, a);
		}
	}
}

double run(engine*e, int n = 1)
{
	std::vector<std::thread> threads(n);
	e->active = n;
	for (int i = 0; i<n; i++) threads[i] = std::thread(tfunc, e);
	double start = omp_get_wtime();
	for (auto& th : threads) th.join();
	return omp_get_wtime() - start;
}

const int N = H - 2;

engine e;
actor  as[N];
message ms[N - 1];
int  ts[N];

void recv(message* , actor* a)
{
	int id = (int)(a - as);

	if ((id == 0 || access(&ms[id - 1], a)) &&
		(id == N - 1 || access(&ms[id], a)) &&
		(ts[id] <= T)){

		op(id+1);	ts[id]++;

		if (id != 0)	send(&e, &ms[id - 1], &as[id - 1]);
		if (id != N - 1)	send(&e, &ms[id], &as[id + 1]);
	}
}

double par_tet()
{
	for (int i = 0; i < N; i++)
	{
		as[i].recv = recv; ts[i] = 1;
	}
	for (int i = 0; i < N - 1; i++)
	{
		ms[i].a = &as[i]; ms[i].sending = false;
	}
	send(&e, &ms[0], &as[0]);

	return run(&e, omp_get_max_threads());
}

void main()
{
	for (int i = 0; i < OBS_N; i++){
		shufle1();	obs_seq[i] = seq_alg();
		shufle();	obs_omp[i] = par_omp(); cout << (compare() ? "OMP Ok " : "something wrong in OMP ");
		shufle();	obs_tet[i] = par_tet(); cout << (compare() ? "Templet Ok " : "something wrong in Templet ");
		cout << (int)((float)(i+1)/OBS_N*100) << "% done" << endl;
	}

	min_max();

	cout << "\nTest results for H = " << H << "; W = " << W << "; T = " << T << "; OMP max threads  = " << omp_get_max_threads() << "\n";

	cout << "\nseq_min  = " << seq_min << " sec; " << "\nseq_mid  = " << seq_mid <<" sec; \nseq_max  = " << seq_max << " sec\n";
	cout << "\nomp_min  = " << omp_min << " sec; " << "\nomp_mid  = " << omp_mid << " sec; \nomp_max  = " << omp_max << " sec\n";
	cout << "\ntet_min  = " << tet_min << " sec; " << "\ntet_mid  = " << tet_mid << " sec; \ntet_max  = " << tet_max << " sec\n";
}

/*
public class MyActor extends UntypedActor{
	public int id;

	public bool access_ms_id_minus_1 = false;
	public bool access_ms_id = false;

	public ActorRef id_minus_1 = null;
	public ActorRef id_plus_1 = null;

	public void onRecieve(Object m){ // Akka analog of void recv(message* , actor* a)
		if ((Integer)m.intValue() == id - 1) access_ms_id_minus_1 = true;
		if((Integer)m.intValue == id) access_ms_id = true;

		if ((id == 0 || access_ms_id_minus_1) &&
			(id == N - 1 || access_ms_id)) &&
			(ts[id] <= T)){

			op(id + 1);	ts[id]++;

			if (id != 0){id_minus_1.sendOneWay(Integer(id - 1));access_ms_id_minus_1 = false;}
			if (id != N - 1){id_plus_1.sendOneWay(Integer(id));access_ms_id = false;}
		}
	}
}
*/<|endoftext|>


<commit_before>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/
#include "CPPlasticEnergyMaterial.h"
// #include "CrystalPlasticityStateVariable.h"

template <>
InputParameters
validParams<CPPlasticEnergyMaterial>()
{
  InputParameters params = validParams<DerivativeFunctionMaterialBase>();
  params.addClassDescription("Free energy material for the plastic energy contributions. Based on Mellbin 2017");
  params.addRequiredParam<std::string>("uo_state_var_name",
                               "Name of state variable property: Same as "
                               "state variable user object specified in input "
                               "file.");
  params.addRequiredCoupledVar("args", "Arguments of F() - use vector coupling");
  params.addParam<Real>("Q", 1, "Hardening parameter SHOULD BE ALREADY USED SOMEWHERE...");
  params.addParam<Real>("q", 1.4, "Cross-hardening parameter");
  // params.addParam<Real>("s0", 0, "Initial value of slip resistance"); //Should make a vector
  params.addRequiredParam<unsigned int>("variable_size", "Number of slip systems.");
  params.addParam<std::vector<unsigned int>>("groups",
                                             "To group the initial values on different "
                                             "slip systems 'format: [start end)', i.e.'0 "
                                             "4 8 11' groups 0-3, 4-7 and 8-11 ");
  params.addParam<std::vector<Real>>("group_values",
                                     "The initial values correspoinding to each "
                                     "group, i.e. '0.0 1.0 2.0' means 0-4 = 0.0, "
                                     "4-8 = 1.0 and 8-12 = 2.0 ");
  return params;
}

CPPlasticEnergyMaterial::CPPlasticEnergyMaterial(const InputParameters & parameters)
  : DerivativeFunctionMaterialBase(parameters),
  _variable_size(getParam<unsigned int>("variable_size")),
  _mat_prop_state_var(
    getMaterialProperty<std::vector<Real>>(parameters.get<std::string>("uo_state_var_name"))),
  _Q(getParam<Real>("Q")),
  _q(getParam<Real>("q")),
  // _s0(getParam<Real>("s0")),
  _groups(getParam<std::vector<unsigned int>>("groups")),
  _group_values(getParam<std::vector<Real>>("group_values"))
{

}
Real
CPPlasticEnergyMaterial::computeF()
{
  std::vector<Real> s0;
  s0.resize(_variable_size);
  for (unsigned int i = 0; i < _groups.size() - 1; ++i)
  {
    unsigned int is, ie;

    is = _groups[i];
    ie = _groups[i + 1] - 1;

    if (is > ie)
      mooseError("CPPlasticEnergyMaterial: Start index is = ",
                 is,
                 " should be greater than end index ie = ",
                 ie,
                 " in state variable read");

    for (unsigned int j = is; j <= ie; ++j)
      s0[j] = _group_values[i];
  }

  Real sum, qab;
  sum = 0;
  // Loop over all slip systems
  for (unsigned int i = 0; i < _variable_size; ++i)
  {
    for (unsigned int j = 0; j < _variable_size; ++j)
    {
      // unsigned int iplane, jplane;
      // iplane = i / 2;
      // jplane = j / 2;
      //
      // // Not sure why not if i==j
      // if (iplane == jplane) // Kalidindi
      if (i == j)
        qab = 1.0;
      // else
      //   qab = _q;
      else if ( i >=20 || j >=20)
        qab = _q;

      else if ((i == 0||i==4)||(i==14||i==15))
        if ((j == 0||j==4)||(j==14||j==15))
          qab = 1.0;
      else if ((i == 1||i==5)||(i==12||i==13))
        if ((j == 1||j==5)||(j==12||j==13))
          qab = 1.0;
      else if ((i==2||i==6)||(i==7||i==10))
        if ((j==2||j==6)||(j==7||j==10))
          qab = 1.0;

      else if ((i==3||i==8)||(i==9||i==11))
        if ((j==3||j==8)||(j==9||j==11))
          qab = 1.0;

      else if (i>=16&&i<=19)
        if (i>=16&&i<=19)
          qab = 1.0;

      else
        qab = _q;

      sum += qab * _mat_prop_state_var[_qp][i] * _mat_prop_state_var[_qp][j];
      // This will not give sum = 0 for purely elastic so must subtract initial value of _mat_prop_state_var
      // sum -= qab * s0[i] * s0[j];

    }
  }

  return 0.5 * _Q * sum;
}

/// Do not know which derivatives I must calculate so just return 0
Real
CPPlasticEnergyMaterial::computeDF(unsigned int i_var)
{
  return 0;
}

Real
CPPlasticEnergyMaterial::computeD2F(unsigned int i_var, unsigned int j_var)
{
  return 0;
}
<commit_msg>subtract initial state variable value<commit_after>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/
#include "CPPlasticEnergyMaterial.h"
// #include "CrystalPlasticityStateVariable.h"

template <>
InputParameters
validParams<CPPlasticEnergyMaterial>()
{
  InputParameters params = validParams<DerivativeFunctionMaterialBase>();
  params.addClassDescription("Free energy material for the plastic energy contributions. Based on Mellbin 2017");
  params.addRequiredParam<std::string>("uo_state_var_name",
                               "Name of state variable property: Same as "
                               "state variable user object specified in input "
                               "file.");
  params.addRequiredCoupledVar("args", "Arguments of F() - use vector coupling");
  params.addParam<Real>("Q", 1, "Hardening parameter SHOULD BE ALREADY USED SOMEWHERE...");
  params.addParam<Real>("q", 1.4, "Cross-hardening parameter");
  // params.addParam<Real>("s0", 0, "Initial value of slip resistance"); //Should make a vector
  params.addRequiredParam<unsigned int>("variable_size", "Number of slip systems.");
  params.addParam<std::vector<unsigned int>>("groups",
                                             "To group the initial values on different "
                                             "slip systems 'format: [start end)', i.e.'0 "
                                             "4 8 11' groups 0-3, 4-7 and 8-11 ");
  params.addParam<std::vector<Real>>("group_values",
                                     "The initial values correspoinding to each "
                                     "group, i.e. '0.0 1.0 2.0' means 0-4 = 0.0, "
                                     "4-8 = 1.0 and 8-12 = 2.0 ");
  return params;
}

CPPlasticEnergyMaterial::CPPlasticEnergyMaterial(const InputParameters & parameters)
  : DerivativeFunctionMaterialBase(parameters),
  _variable_size(getParam<unsigned int>("variable_size")),
  _mat_prop_state_var(
    getMaterialProperty<std::vector<Real>>(parameters.get<std::string>("uo_state_var_name"))),
  _Q(getParam<Real>("Q")),
  _q(getParam<Real>("q")),
  // _s0(getParam<Real>("s0")),
  _groups(getParam<std::vector<unsigned int>>("groups")),
  _group_values(getParam<std::vector<Real>>("group_values"))
{

}
Real
CPPlasticEnergyMaterial::computeF()
{
  std::vector<Real> s0;
  s0.resize(_variable_size);
  for (unsigned int i = 0; i < _groups.size() - 1; ++i)
  {
    unsigned int is, ie;

    is = _groups[i];
    ie = _groups[i + 1] - 1;

    if (is > ie)
      mooseError("CPPlasticEnergyMaterial: Start index is = ",
                 is,
                 " should be greater than end index ie = ",
                 ie,
                 " in state variable read");

    for (unsigned int j = is; j <= ie; ++j)
      s0[j] = _group_values[i];
  }

  Real sum, qab;
  sum = 0;
  // Loop over all slip systems
  for (unsigned int i = 0; i < _variable_size; ++i)
  {
    for (unsigned int j = 0; j < _variable_size; ++j)
    {
      // unsigned int iplane, jplane;
      // iplane = i / 2;
      // jplane = j / 2;
      //
      // // Not sure why not if i==j
      // if (iplane == jplane) // Kalidindi
      if (i == j)
        qab = 1.0;
      // else
      //   qab = _q;
      else if ( i >=20 || j >=20)
        qab = _q;

      else if ((i == 0||i==4)||(i==14||i==15))
        if ((j == 0||j==4)||(j==14||j==15))
          qab = 1.0;
      else if ((i == 1||i==5)||(i==12||i==13))
        if ((j == 1||j==5)||(j==12||j==13))
          qab = 1.0;
      else if ((i==2||i==6)||(i==7||i==10))
        if ((j==2||j==6)||(j==7||j==10))
          qab = 1.0;

      else if ((i==3||i==8)||(i==9||i==11))
        if ((j==3||j==8)||(j==9||j==11))
          qab = 1.0;

      else if (i>=16&&i<=19)
        if (i>=16&&i<=19)
          qab = 1.0;

      else
        qab = _q;

      sum += qab * _mat_prop_state_var[_qp][i] * _mat_prop_state_var[_qp][j];
      // This will not give sum = 0 for purely elastic so must subtract initial value of _mat_prop_state_var
      sum -= qab * s0[i] * s0[j];

    }
  }

  return 0.5 * _Q * sum;
}

/// Do not know which derivatives I must calculate so just return 0
Real
CPPlasticEnergyMaterial::computeDF(unsigned int i_var)
{
  return 0;
}

Real
CPPlasticEnergyMaterial::computeD2F(unsigned int i_var, unsigned int j_var)
{
  return 0;
}
<|endoftext|>