<commit_before>#include <iostream>
#include <memory>
#include <fstream>

#include <openssl/sha.h>

#include <ecdsa/base58.h>
#include <ecdsa/key.h>

#include "args.h"
#include "btcaddr.h"

#define BUFF_SIZE 1024

/**
 * Show help document.
 *
 * @param args The argument manager
 */
void ShowHelp(const Args &args) {
  std::cout << "BTCAddrGen version 0.1" << std::endl;
  std::cout << "Usage:" << std::endl;
  std::cout << "  ./btcaddrgen" << std::endl << std::endl;
  std::cout << "Arguments:" << std::endl;
  std::cout << args.GetArgsHelpString() << std::endl;
}

std::tuple<std::vector<uint8_t>, bool> HashFile(const std::string &path) {
  std::vector<uint8_t> md;

  std::ifstream input(path, std::ios::binary);
  if (!input.is_open()) {
    std::cerr << "Cannot open file " << path << std::endl;
    return std::make_tuple(md, false);
  }

  // Hash file contents
  SHA512_CTX ctx;
  SHA512_Init(&ctx);

  // Reading...
  char buff[BUFF_SIZE];
  while (!input.eof()) {
    input.read(buff, BUFF_SIZE);
    size_t buff_size = input.gcount();
    SHA512_Update(&ctx, buff, buff_size);
  }

  // Get md buffer.
  md.resize(SHA512_DIGEST_LENGTH);
  SHA512_Final(md.data(), &ctx);

  return std::make_tuple(md, true);
}

std::tuple<std::vector<uint8_t>, bool> Signing(std::shared_ptr<ecdsa::Key> pkey,
    const std::string &path) {
  std::vector<uint8_t> signature;

  std::vector<uint8_t> md;
  bool succ;
  std::tie(md, succ) = HashFile(path);
  if (!succ) {
    return std::make_tuple(signature, false);
  }

  std::tie(signature, succ) = pkey->Sign(md);
  if (!succ) {
    std::cerr << "Cannot signing file!" << std::endl;
    return std::make_tuple(signature, false);
  }

  return std::make_tuple(signature, true);
}

bool Verifying(const ecdsa::PubKey &pub_key,
    const std::string &path, const std::vector<uint8_t> &signature) {
  std::vector<uint8_t> md;
  bool succ;
  std::tie(md, succ) = HashFile(path);
  if (succ) {
    return pub_key.Verify(md, signature);
  }
  return false;
}

void ShowKeyInfo(std::shared_ptr<ecdsa::Key> pkey) {
  auto pub_key = pkey->CreatePubKey();
  auto addr = btc::Address::FromPublicKey(pub_key.get_pub_key_data());
  std::cout << "Address: " << addr.ToString() << std::endl;
  std::cout << "Public key: "
    << base58::EncodeBase58(pkey->get_pub_key_data()) << std::endl;
  std::cout << "Private key: "
    << base58::EncodeBase58(pkey->get_priv_key_data()) << std::endl;
}

/// Main program.
int main(int argc, const char *argv[]) {
  try {
    Args args(argc, argv);
    if (args.is_help()) {
      ShowHelp(args);
      return 0;
    }

    if (args.is_generate_new_key()) {
      ShowKeyInfo(std::make_shared<ecdsa::Key>());
      return 0;
    }

    // Import key.
    std::shared_ptr<ecdsa::Key> pkey;
    std::string priv_key_b58 = args.get_import_priv_key();
    if (!priv_key_b58.empty()) {
      std::vector<uint8_t> priv_key;
      bool succ = base58::DecodeBase58(priv_key_b58.c_str(), priv_key);
      if (!succ) {
        std::cerr << "Failed to decode base58!" << std::endl;
        return 1;
      }
      pkey = std::make_shared<ecdsa::Key>(priv_key);
      ShowKeyInfo(pkey);
    }

    // Signing file?
    if (!args.get_signing_file().empty()) {
      if (pkey == nullptr) {
        pkey = std::make_shared<ecdsa::Key>();
        ShowKeyInfo(pkey);
      }
      std::vector<uint8_t> signature;
      bool succ;
      std::tie(signature, succ) = Signing(pkey, args.get_signing_file());
      if (succ) {
        std::string signature_b58 = base58::EncodeBase58(signature);
        std::cout << "Signature: " << signature_b58 << std::endl;
        return 0;
      }
      return 1;
    }

    // Verifying
    if (!args.get_import_pub_key().empty() && !args.get_verifying_file().empty()
        && !args.get_signature().empty()) {
      // Verifying
      std::vector<uint8_t> pub_key_data;
      bool succ = base58::DecodeBase58(args.get_import_pub_key(), pub_key_data);
      if (!succ) {
        std::cerr << "Cannot decode public key from base58 string."
          << std::endl;
        return 1;
      }
      std::vector<uint8_t> signature;
      succ = base58::DecodeBase58(args.get_signature(), signature);
      if (!succ) {
        std::cerr << "Cannot decode signature from base58 string." << std::endl;
        return 1;
      }
      ecdsa::PubKey pub_key(pub_key_data);
      succ = Verifying(pub_key, args.get_verifying_file(), signature);
      if (succ) {
        std::cout << "Verified OK." << std::endl;
        return 0;
      }
      return 1;
    }
  } catch (std::exception &e) {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}
<commit_msg>-h to show help.<commit_after>#include <iostream>
#include <memory>
#include <fstream>

#include <openssl/sha.h>

#include <ecdsa/base58.h>
#include <ecdsa/key.h>

#include "args.h"
#include "btcaddr.h"

#define BUFF_SIZE 1024

/**
 * Show help document.
 *
 * @param args The argument manager
 */
void ShowHelp(const Args &args) {
  std::cout << "BTCAddrGen version 0.1" << std::endl;
  std::cout << "Usage:" << std::endl;
  std::cout << "  ./btcaddrgen" << std::endl << std::endl;
  std::cout << "Arguments:" << std::endl;
  std::cout << args.GetArgsHelpString() << std::endl;
}

std::tuple<std::vector<uint8_t>, bool> HashFile(const std::string &path) {
  std::vector<uint8_t> md;

  std::ifstream input(path, std::ios::binary);
  if (!input.is_open()) {
    std::cerr << "Cannot open file " << path << std::endl;
    return std::make_tuple(md, false);
  }

  // Hash file contents
  SHA512_CTX ctx;
  SHA512_Init(&ctx);

  // Reading...
  char buff[BUFF_SIZE];
  while (!input.eof()) {
    input.read(buff, BUFF_SIZE);
    size_t buff_size = input.gcount();
    SHA512_Update(&ctx, buff, buff_size);
  }

  // Get md buffer.
  md.resize(SHA512_DIGEST_LENGTH);
  SHA512_Final(md.data(), &ctx);

  return std::make_tuple(md, true);
}

std::tuple<std::vector<uint8_t>, bool> Signing(std::shared_ptr<ecdsa::Key> pkey,
    const std::string &path) {
  std::vector<uint8_t> signature;

  std::vector<uint8_t> md;
  bool succ;
  std::tie(md, succ) = HashFile(path);
  if (!succ) {
    return std::make_tuple(signature, false);
  }

  std::tie(signature, succ) = pkey->Sign(md);
  if (!succ) {
    std::cerr << "Cannot signing file!" << std::endl;
    return std::make_tuple(signature, false);
  }

  return std::make_tuple(signature, true);
}

bool Verifying(const ecdsa::PubKey &pub_key,
    const std::string &path, const std::vector<uint8_t> &signature) {
  std::vector<uint8_t> md;
  bool succ;
  std::tie(md, succ) = HashFile(path);
  if (succ) {
    return pub_key.Verify(md, signature);
  }
  return false;
}

void ShowKeyInfo(std::shared_ptr<ecdsa::Key> pkey) {
  auto pub_key = pkey->CreatePubKey();
  auto addr = btc::Address::FromPublicKey(pub_key.get_pub_key_data());
  std::cout << "Address: " << addr.ToString() << std::endl;
  std::cout << "Public key: "
    << base58::EncodeBase58(pkey->get_pub_key_data()) << std::endl;
  std::cout << "Private key: "
    << base58::EncodeBase58(pkey->get_priv_key_data()) << std::endl;
}

/// Main program.
int main(int argc, const char *argv[]) {
  try {
    Args args(argc, argv);
    if (args.is_help()) {
      ShowHelp(args);
      return 0;
    }

    if (args.is_generate_new_key()) {
      ShowKeyInfo(std::make_shared<ecdsa::Key>());
      return 0;
    }

    // Import key.
    std::shared_ptr<ecdsa::Key> pkey;
    std::string priv_key_b58 = args.get_import_priv_key();
    if (!priv_key_b58.empty()) {
      std::vector<uint8_t> priv_key;
      bool succ = base58::DecodeBase58(priv_key_b58.c_str(), priv_key);
      if (!succ) {
        std::cerr << "Failed to decode base58!" << std::endl;
        return 1;
      }
      pkey = std::make_shared<ecdsa::Key>(priv_key);
      ShowKeyInfo(pkey);
    }

    // Signing file?
    if (!args.get_signing_file().empty()) {
      if (pkey == nullptr) {
        pkey = std::make_shared<ecdsa::Key>();
        ShowKeyInfo(pkey);
      }
      std::vector<uint8_t> signature;
      bool succ;
      std::tie(signature, succ) = Signing(pkey, args.get_signing_file());
      if (succ) {
        std::string signature_b58 = base58::EncodeBase58(signature);
        std::cout << "Signature: " << signature_b58 << std::endl;
        return 0;
      }
      return 1;
    }

    // Verifying
    if (!args.get_import_pub_key().empty() && !args.get_verifying_file().empty()
        && !args.get_signature().empty()) {
      // Verifying
      std::vector<uint8_t> pub_key_data;
      bool succ = base58::DecodeBase58(args.get_import_pub_key(), pub_key_data);
      if (!succ) {
        std::cerr << "Cannot decode public key from base58 string."
          << std::endl;
        return 1;
      }
      std::vector<uint8_t> signature;
      succ = base58::DecodeBase58(args.get_signature(), signature);
      if (!succ) {
        std::cerr << "Cannot decode signature from base58 string." << std::endl;
        return 1;
      }
      ecdsa::PubKey pub_key(pub_key_data);
      succ = Verifying(pub_key, args.get_verifying_file(), signature);
      if (succ) {
        std::cout << "Verified OK." << std::endl;
        return 0;
      }
      return 1;
    }

    std::cerr << "No argument, -h to show help." << std::endl;
    return 1;
  } catch (std::exception &e) {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include "NTClient.h"
using namespace std;

void initBot() {
	NTClient nclient = NTClient(120, 0.98);
	nclient.login("utpp_bot1", "123asd123"); // Throw-away account
	nclient.connect();
}
int main(int argc, char** argv) {
	srand(static_cast<unsigned int>(time(0)));
	initBot();
	return 0;
}<commit_msg>Longer typing interval<commit_after>#include <iostream>
#include <cstdlib>
#include "NTClient.h"
using namespace std;

void initBot() {
	NTClient nclient = NTClient(220, 0.98);
	nclient.login("utpp_bot1", "123asd123"); // Throw-away account
	nclient.connect();
}
int main(int argc, char** argv) {
	srand(static_cast<unsigned int>(time(0)));
	initBot();
	return 0;
}<|endoftext|>


<commit_before>/*!
 * \cond FILEINFO
 ******************************************************************************
 * \file main.cpp
 ******************************************************************************
 *
 * Copyright (C) ATS Advanced Telematic Systems GmbH GmbH, 2016
 *
 * \author Moritz Klinger
 *
 ******************************************************************************
 *
 * \brief  The main file of the project.
 *
 *
 ******************************************************************************
 *
 * \endcond
 */

/*****************************************************************************/
#include <openssl/ssl.h>
#include <sys/stat.h>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <iostream>

#include "aktualizr.h"
#include "config.h"
#include "logging.h"
#include "utils.h"

/*****************************************************************************/

namespace bpo = boost::program_options;

void check_info_options(const bpo::options_description &description, const bpo::variables_map &vm) {
  if (vm.count("help") != 0) {
    std::cout << description << '\n';
    exit(EXIT_SUCCESS);
  }
  if (vm.count("version") != 0) {
    std::cout << "Current aktualizr version is: " << AKTUALIZR_VERSION << "\n";
    exit(EXIT_SUCCESS);
  }
}

bpo::variables_map parse_options(int argc, char *argv[]) {
  bpo::options_description description("aktualizr command line options");
  // clang-format off
  description.add_options()
      ("help,h", "print usage")
      ("version,v", "Current aktualizr version")
      ("loglevel", bpo::value<int>(), "set log level 0-4 (trace, debug, warning, info, error)")
      ("config,c", bpo::value<std::string>()->required(), "toml configuration file")
      ("gateway-http", bpo::value<bool>(), "enable the http gateway")
      ("gateway-socket", bpo::value<bool>(), "enable the socket gateway")
      ("tls-server", bpo::value<std::string>(), "url, used for auto provisioning")
      ("repo-server", bpo::value<std::string>(), "url of the uptane repo repository")
      ("director-server", bpo::value<std::string>(), "url of the uptane director repository")
      ("ostree-server", bpo::value<std::string>(), "url of the ostree repository")
      ("primary-ecu-serial", bpo::value<std::string>(), "serial number of primary ecu")
      ("primary-ecu-hardware-id", bpo::value<std::string>(), "hardware id of primary ecu")
      ("poll-once", "Check for updates only once and exit")
      ("secondary-config", bpo::value<std::vector<boost::filesystem::path> >()->composing(), "secondary ECU json configuration file")
      ("legacy-interface", bpo::value<boost::filesystem::path>(), "path to legacy secondary ECU interface program")
      ("disable-keyid-validation", "deprecated");
  // clang-format on

  bpo::variables_map vm;
  std::vector<std::string> unregistered_options;
  try {
    bpo::basic_parsed_options<char> parsed_options =
        bpo::command_line_parser(argc, argv).options(description).allow_unregistered().run();
    bpo::store(parsed_options, vm);
    check_info_options(description, vm);
    bpo::notify(vm);
    unregistered_options = bpo::collect_unrecognized(parsed_options.options, bpo::include_positional);
    if (vm.count("help") == 0 && !unregistered_options.empty()) {
      std::cout << description << "\n";
      exit(EXIT_FAILURE);
    }
  } catch (const bpo::required_option &ex) {
    if (ex.get_option_name() == "--config") {
      std::cout << ex.get_option_name() << " is missing.\nYou have to provide a valid configuration "
                                           "file using toml format. See the example configuration file "
                                           "in config/config.toml.example"
                << std::endl;
      exit(EXIT_FAILURE);
    } else {
      // print the error and append the default commandline option description
      std::cout << ex.what() << std::endl << description;
      exit(EXIT_SUCCESS);
    }
  } catch (const bpo::error &ex) {
    check_info_options(description, vm);

    // log boost error
    LOG_WARNING << "boost command line option error: " << ex.what();

    // print the error message to the standard output too, as the user provided
    // a non-supported commandline option
    std::cout << ex.what() << '\n';

    // set the returnValue, thereby ctest will recognize
    // that something went wrong
    exit(EXIT_FAILURE);
  }

  return vm;
}

/*****************************************************************************/
int main(int argc, char *argv[]) {
  logger_init();

  bpo::variables_map commandline_map = parse_options(argc, argv);

  // check for loglevel
  if (commandline_map.count("loglevel") != 0) {
    // set the log level from command line option
    boost::log::trivial::severity_level severity =
        static_cast<boost::log::trivial::severity_level>(commandline_map["loglevel"].as<int>());
    if (severity < boost::log::trivial::trace) {
      LOG_DEBUG << "Invalid log level";
      severity = boost::log::trivial::trace;
    }
    if (boost::log::trivial::fatal < severity) {
      LOG_WARNING << "Invalid log level";
      severity = boost::log::trivial::fatal;
    }
    if (severity <= boost::log::trivial::debug) {
      SSL_load_error_strings();
    }
    logger_set_threshold(severity);
  }

  LOG_INFO << "Aktualizr version " AKTUALIZR_VERSION " starting";
  LOG_DEBUG << "Current directory: " << boost::filesystem::current_path().string();
  // Initialize config with default values, the update with config, then with cmd
  std::string sota_config_file = commandline_map["config"].as<std::string>();
  boost::filesystem::path sota_config_path(sota_config_file);
  if (false == boost::filesystem::exists(sota_config_path)) {
    std::cout << "aktualizr: configuration file " << boost::filesystem::absolute(sota_config_path)
              << " not found. Exiting." << std::endl;
    exit(EXIT_FAILURE);
  }

  try {
    Config config(sota_config_path, commandline_map);
    boost::filesystem::path saved_config_path = "/tmp/aktualizr_config_path";
    if (boost::filesystem::exists(saved_config_path)) {
      struct stat info;
      stat(saved_config_path.c_str(), &info);
      if (geteuid() != info.st_uid) {
        LOG_WARNING
            << "\n\nAktualizr may not work properly because it runs within other user than it was run before!!!\n\n";
      }
    }
    Utils::writeFile(saved_config_path, boost::filesystem::absolute(sota_config_path).string());
    Aktualizr aktualizr(config);
    return aktualizr.run();
  } catch (const std::exception &ex) {
    LOG_ERROR << ex.what();
    return -1;
  }
}
<commit_msg>Warn if aktualizr runs as non-root user<commit_after>/*!
 * \cond FILEINFO
 ******************************************************************************
 * \file main.cpp
 ******************************************************************************
 *
 * Copyright (C) ATS Advanced Telematic Systems GmbH GmbH, 2016
 *
 * \author Moritz Klinger
 *
 ******************************************************************************
 *
 * \brief  The main file of the project.
 *
 *
 ******************************************************************************
 *
 * \endcond
 */

/*****************************************************************************/
#include <openssl/ssl.h>
#include <sys/stat.h>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <iostream>

#include "aktualizr.h"
#include "config.h"
#include "logging.h"
#include "utils.h"

/*****************************************************************************/

namespace bpo = boost::program_options;

void check_info_options(const bpo::options_description &description, const bpo::variables_map &vm) {
  if (vm.count("help") != 0) {
    std::cout << description << '\n';
    exit(EXIT_SUCCESS);
  }
  if (vm.count("version") != 0) {
    std::cout << "Current aktualizr version is: " << AKTUALIZR_VERSION << "\n";
    exit(EXIT_SUCCESS);
  }
}

bpo::variables_map parse_options(int argc, char *argv[]) {
  bpo::options_description description("aktualizr command line options");
  // clang-format off
  description.add_options()
      ("help,h", "print usage")
      ("version,v", "Current aktualizr version")
      ("loglevel", bpo::value<int>(), "set log level 0-4 (trace, debug, warning, info, error)")
      ("config,c", bpo::value<std::string>()->required(), "toml configuration file")
      ("gateway-http", bpo::value<bool>(), "enable the http gateway")
      ("gateway-socket", bpo::value<bool>(), "enable the socket gateway")
      ("tls-server", bpo::value<std::string>(), "url, used for auto provisioning")
      ("repo-server", bpo::value<std::string>(), "url of the uptane repo repository")
      ("director-server", bpo::value<std::string>(), "url of the uptane director repository")
      ("ostree-server", bpo::value<std::string>(), "url of the ostree repository")
      ("primary-ecu-serial", bpo::value<std::string>(), "serial number of primary ecu")
      ("primary-ecu-hardware-id", bpo::value<std::string>(), "hardware id of primary ecu")
      ("poll-once", "Check for updates only once and exit")
      ("secondary-config", bpo::value<std::vector<boost::filesystem::path> >()->composing(), "secondary ECU json configuration file")
      ("legacy-interface", bpo::value<boost::filesystem::path>(), "path to legacy secondary ECU interface program")
      ("disable-keyid-validation", "deprecated");
  // clang-format on

  bpo::variables_map vm;
  std::vector<std::string> unregistered_options;
  try {
    bpo::basic_parsed_options<char> parsed_options =
        bpo::command_line_parser(argc, argv).options(description).allow_unregistered().run();
    bpo::store(parsed_options, vm);
    check_info_options(description, vm);
    bpo::notify(vm);
    unregistered_options = bpo::collect_unrecognized(parsed_options.options, bpo::include_positional);
    if (vm.count("help") == 0 && !unregistered_options.empty()) {
      std::cout << description << "\n";
      exit(EXIT_FAILURE);
    }
  } catch (const bpo::required_option &ex) {
    if (ex.get_option_name() == "--config") {
      std::cout << ex.get_option_name() << " is missing.\nYou have to provide a valid configuration "
                                           "file using toml format. See the example configuration file "
                                           "in config/config.toml.example"
                << std::endl;
      exit(EXIT_FAILURE);
    } else {
      // print the error and append the default commandline option description
      std::cout << ex.what() << std::endl << description;
      exit(EXIT_SUCCESS);
    }
  } catch (const bpo::error &ex) {
    check_info_options(description, vm);

    // log boost error
    LOG_WARNING << "boost command line option error: " << ex.what();

    // print the error message to the standard output too, as the user provided
    // a non-supported commandline option
    std::cout << ex.what() << '\n';

    // set the returnValue, thereby ctest will recognize
    // that something went wrong
    exit(EXIT_FAILURE);
  }

  return vm;
}

/*****************************************************************************/
int main(int argc, char *argv[]) {
  logger_init();

  bpo::variables_map commandline_map = parse_options(argc, argv);

  // check for loglevel
  if (commandline_map.count("loglevel") != 0) {
    // set the log level from command line option
    boost::log::trivial::severity_level severity =
        static_cast<boost::log::trivial::severity_level>(commandline_map["loglevel"].as<int>());
    if (severity < boost::log::trivial::trace) {
      LOG_DEBUG << "Invalid log level";
      severity = boost::log::trivial::trace;
    }
    if (boost::log::trivial::fatal < severity) {
      LOG_WARNING << "Invalid log level";
      severity = boost::log::trivial::fatal;
    }
    if (severity <= boost::log::trivial::debug) {
      SSL_load_error_strings();
    }
    logger_set_threshold(severity);
  }

  LOG_INFO << "Aktualizr version " AKTUALIZR_VERSION " starting";
  LOG_DEBUG << "Current directory: " << boost::filesystem::current_path().string();
  // Initialize config with default values, the update with config, then with cmd
  std::string sota_config_file = commandline_map["config"].as<std::string>();
  boost::filesystem::path sota_config_path(sota_config_file);
  if (false == boost::filesystem::exists(sota_config_path)) {
    std::cout << "aktualizr: configuration file " << boost::filesystem::absolute(sota_config_path)
              << " not found. Exiting." << std::endl;
    exit(EXIT_FAILURE);
  }

  try {
    Config config(sota_config_path, commandline_map);
    if (geteuid() != 0) {
      LOG_WARNING << "\033[31mAktualizr is currently running as non-root and may not work as expected! Aktualizr "
                     "should be ran as root for proper functionality.\033[0m\n";
    }
    boost::filesystem::path saved_config_path = "/tmp/aktualizr_config_path";
    Utils::writeFile(saved_config_path, boost::filesystem::absolute(sota_config_path).string());
    Aktualizr aktualizr(config);
    return aktualizr.run();
  } catch (const std::exception &ex) {
    LOG_ERROR << ex.what();
    return -1;
  }
}
<|endoftext|>


<commit_before>//g++-5 --std=c++11 -Wall -g -o algo_dc_equal_range algo_dc_equal_range.cc

/**
 * @file  Equal Range
 * @brief Find start/end of a given target value (in sorted array).
 */

// https://leetcode.com/problems/search-for-a-range/

#include <iostream>          /* std::cout                    */
#include <iomanip>           /* std::setw                    */
#include <cmath>             /* pow                          */
#include <cassert>           /* assert                       */
#include <algorithm>         /* std::max                     */
#include <vector>            /* std:vector                   */
#include <string>            /* std::string,                 */
#include <cstring>           /* std::strtok                  */
#include <unordered_map>     /* std::unordered_map container */
using namespace std;

/**
 * Given a sorted array of integers, find the starting and ending
 * position of a given target value.
 * Your algorithm's runtime complexity must be in the order
 * of O(log n).
 * If the target is not found in the array, return [-1, -1].
 * For example,
 * Given [5, 7, 7, 8, 8, 10] and target value 8,
 * return [3, 4].
 */

/**
 * @brief: Use Equal Range to calculate lb and ub            *
 * Time Complexity = O(lg n).   Space Complexity = O(1)      */
vector<int> searchRangeSTL(vector<int>& nums, int target) {
   auto eq = std::equal_range(nums.begin(), nums.end(), target);
   /* If lower_bound is in end or does not point to target   */
   if(eq.first == nums.end() || *eq.first != target)
      return std::vector<int> {-1, -1};
   /* If upper_bound points to element after tgt, come back  */
   else if(eq.second != nums.begin() && *std::prev(eq.second) == target)
      eq.second--;
   return std::vector<int> { (int)(eq.first  - nums.begin()),
                             (int)(eq.second - nums.begin()) };
}

/**
 * @brief: Use Binary Search to calculate lb and ub          *
 * Time Complexity = O(lg n).   Space Complexity = O(1)      */
vector<int> searchRangeBS(vector<int>& num, int t) {
   vector<int> v = {-1, -1};
   int b, e, N = num.size();
   if(num.size() == 0)            return v;

   /* First find the lower bound (almost equivalent to BS)   */
   for(b = 0, e = N - 1; b <= e; ) {
      int mid = b + (e - b) / 2;
      if(num[mid] < t)            b = mid + 1;
      else                        e = mid - 1;
   }
   /* If no LB, there can be no UB                           */
   if(num[b] == t)                v[0] = b;
   else                           return v;

   /* Second, find the UB                                    */
   for(e = N - 1; b <= e; ) {
      int mid = b + (e - b) / 2;
      if(num[mid] > t)            e = mid - 1;
      else                        b = mid + 1;
   }
   v[1] = e;
   return v;
}

struct test_vector {
   std::vector<int> num;
   int target;
   std::vector<int> exp;
};

const struct test_vector test[11] =  {
   {{},                       2,  {-1, -1}},
   {{1},                      0,  {-1, -1}},
   {{3},                      3,  {0, 0}  },
   {{0, 1},                   2,  {-1, -1}},
   {{5, 7},                   4,  {-1, -1}},
   {{5, 7},                   6,  {-1, -1}},
   {{5, 7, 7, 8, 8, 10},      8,  {3, 4}},
   {{5, 7, 7, 8, 8, 10},      5,  {0, 0}},
   {{5, 5, 7, 7, 8, 8, 10},   5,  {0, 1}},
   {{5, 5, 7, 7, 8, 8, 10},  10,  {6, 6}},
   {{5, 7, 7, 8, 8, 10, 10}, 10,  {5, 6}},
};

int main()
{
   for(auto tst : test) {
      auto ans = searchRangeSTL(tst.num, tst.target);
      if(ans != tst.exp) {
         cout << "Error:searchRangeSTL failed. Input ";
         for(auto val : tst.num) cout << val << ",";
         cout << "  Target = " << tst.target << endl << "Exp: ";
         for(auto val : tst.exp) cout << val << ",";
         cout << endl << "Got: ";
         for(auto val : ans) cout << val << ",";
         cout << endl;
         return -1;
      }

      ans = searchRangeBS(tst.num, tst.target);
      if(ans != tst.exp) {
         cout << "Error:searchRangeBS failed. Input ";
         for(auto val : tst.num) cout << val << ",";
         cout << "  Target = " << tst.target << endl << "Exp: ";
         for(auto val : tst.exp) cout << val << ",";
         cout << endl << "Got: ";
         for(auto val : ans) cout << val << ",";
         cout << endl;
         return -1;
      }
   }
   cout << "Info: All manual test-cases passed." << endl;
   return 0;
}
<commit_msg>Fix corner case in equal range<commit_after>//g++-5 --std=c++11 -Wall -g -o algo_dc_equal_range algo_dc_equal_range.cc

/**
 * @file  Equal Range
 * @brief Find start/end of a given target value (in sorted array).
 */

// https://leetcode.com/problems/search-for-a-range/

#include <iostream>          /* std::cout                    */
#include <iomanip>           /* std::setw                    */
#include <cmath>             /* pow                          */
#include <cassert>           /* assert                       */
#include <algorithm>         /* std::max                     */
#include <vector>            /* std:vector                   */
#include <string>            /* std::string,                 */
#include <cstring>           /* std::strtok                  */
#include <unordered_map>     /* std::unordered_map container */
using namespace std;

/**
 * Given a sorted array of integers, find the starting and ending
 * position of a given target value.
 * Your algorithm's runtime complexity must be in the order
 * of O(log n).
 * If the target is not found in the array, return [-1, -1].
 * For example,
 * Given [5, 7, 7, 8, 8, 10] and target value 8,
 * return [3, 4].
 */

/**
 * @brief: Use Equal Range to calculate lb and ub            *
 * Time Complexity = O(lg n).   Space Complexity = O(1)      */
vector<int> searchRangeSTL(vector<int>& nums, int target) {
   auto eq = std::equal_range(nums.begin(), nums.end(), target);
   /* If lower_bound is in end or does not point to target   */
   if(eq.first == nums.end() || *eq.first != target)
      return std::vector<int> {-1, -1};
   /* If upper_bound points to element after tgt, come back  */
   else if(eq.second != nums.begin() && *std::prev(eq.second) == target)
      eq.second--;
   return std::vector<int> { (int)(eq.first  - nums.begin()),
                             (int)(eq.second - nums.begin()) };
}

/**
 * @brief: Use Binary Search to calculate lb and ub          *
 * Time Complexity = O(lg n).   Space Complexity = O(1)      */
vector<int> searchRangeBS(vector<int>& num, int t) {
   vector<int> v = {-1, -1};
   int b, e, N = num.size();
   if(num.size() == 0)            return v;

   /* First find the lower bound (almost equivalent to BS)   */
   for(b = 0, e = N - 1; b <= e; ) {
      int mid = b + (e - b) / 2;
      if(num[mid] < t)            b = mid + 1;
      else                        e = mid - 1;
   }
   /* If no LB, there can be no UB                           */
   if(b < N && num[b] == t)       v[0] = b;
   else                           return v;

   /* Second, find the UB                                    */
   for(e = N - 1; b <= e; ) {
      int mid = b + (e - b) / 2;
      if(num[mid] > t)            e = mid - 1;
      else                        b = mid + 1;
   }
   v[1] = e;
   return v;
}

struct test_vector {
   std::vector<int> num;
   int target;
   std::vector<int> exp;
};

const struct test_vector test[12] =  {
   {{},                       2,  {-1, -1}},
   {{1},                      0,  {-1, -1}},
   {{0},                      1,  {-1, -1}},
   {{3},                      3,  {0, 0}  },
   {{0, 1},                   2,  {-1, -1}},
   {{5, 7},                   4,  {-1, -1}},
   {{5, 7},                   6,  {-1, -1}},
   {{5, 7, 7, 8, 8, 10},      8,  {3, 4}},
   {{5, 7, 7, 8, 8, 10},      5,  {0, 0}},
   {{5, 5, 7, 7, 8, 8, 10},   5,  {0, 1}},
   {{5, 5, 7, 7, 8, 8, 10},  10,  {6, 6}},
   {{5, 7, 7, 8, 8, 10, 10}, 10,  {5, 6}},
};

int main()
{
   for(auto tst : test) {
      auto ans = searchRangeSTL(tst.num, tst.target);
      if(ans != tst.exp) {
         cout << "Error:searchRangeSTL failed. Input ";
         for(auto val : tst.num) cout << val << ",";
         cout << "  Target = " << tst.target << endl << "Exp: ";
         for(auto val : tst.exp) cout << val << ",";
         cout << endl << "Got: ";
         for(auto val : ans) cout << val << ",";
         cout << endl;
         return -1;
      }

      ans = searchRangeBS(tst.num, tst.target);
      if(ans != tst.exp) {
         cout << "Error:searchRangeBS failed. Input ";
         for(auto val : tst.num) cout << val << ",";
         cout << "  Target = " << tst.target << endl << "Exp: ";
         for(auto val : tst.exp) cout << val << ",";
         cout << endl << "Got: ";
         for(auto val : ans) cout << val << ",";
         cout << endl;
         return -1;
      }
   }
   cout << "Info: All manual test-cases passed." << endl;
   return 0;
}
<|endoftext|>


<commit_before>//===- DbgInfoPrinter.cpp - Print debug info in a human readable form ------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass that prints instructions, and associated debug
// info:
//
//   - source/line/col information
//   - original variable name
//   - original type name
//
//===----------------------------------------------------------------------===//

#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool>
PrintDirectory("print-fullpath",
               cl::desc("Print fullpath when printing debug info"),
               cl::Hidden);

namespace {
  class VISIBILITY_HIDDEN PrintDbgInfo : public FunctionPass {
    raw_ostream &Out;
    void printStopPoint(const DbgStopPointInst *DSI);
    void printFuncStart(const DbgFuncStartInst *FS);
    void printVariableDeclaration(const Value *V);
  public:
    static char ID; // Pass identification
    PrintDbgInfo() : FunctionPass(&ID), Out(outs()) {}

    virtual bool runOnFunction(Function &F);
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };
  char PrintDbgInfo::ID = 0;
  static RegisterPass<PrintDbgInfo> X("print-dbginfo",
                                     "Print debug info in human readable form");
}

FunctionPass *llvm::createDbgInfoPrinterPass() { return new PrintDbgInfo(); }

void PrintDbgInfo::printVariableDeclaration(const Value *V) {
  std::string DisplayName, File, Directory, Type;
  unsigned LineNo;

  if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory))
    return;

  Out << "; ";
  WriteAsOperand(Out, V, false, 0);
  Out << " is variable " << DisplayName
      << " of type " << Type << " declared at ";

  if (PrintDirectory)
    Out << Directory << "/";

  Out << File << ":" << LineNo << "\n";
}

void PrintDbgInfo::printStopPoint(const DbgStopPointInst *DSI) {
  if (PrintDirectory) {
    std::string dir;
    GetConstantStringInfo(DSI->getDirectory(), dir);
    Out << dir << "/";
  }

  std::string file;
  GetConstantStringInfo(DSI->getFileName(), file);
  Out << file << ":" << DSI->getLine();

  if (unsigned Col = DSI->getColumn())
    Out << ":" << Col;
}

void PrintDbgInfo::printFuncStart(const DbgFuncStartInst *FS) {
  DISubprogram Subprogram(cast<GlobalVariable>(FS->getSubprogram()));
  std::string Res1, Res2;
  Out << "; fully qualified function name: " << Subprogram.getDisplayName(Res1)
      << " return type: " << Subprogram.getType().getName(Res2)
      << " at line " << Subprogram.getLineNumber()
      << "\n\n";
}

bool PrintDbgInfo::runOnFunction(Function &F) {
  if (F.isDeclaration())
    return false;

  Out << "function " << F.getName() << "\n\n";

  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    BasicBlock *BB = I;

    if (I != F.begin() && (pred_begin(BB) == pred_end(BB)))
      // Skip dead blocks.
      continue;

    const DbgStopPointInst *DSI = findBBStopPoint(BB);
    Out << BB->getName();
    Out << ":";

    if (DSI) {
      Out << "; (";
      printStopPoint(DSI);
      Out << ")";
    }

    Out << "\n";

    // A dbgstoppoint's information is valid until we encounter a new one.
    const DbgStopPointInst *LastDSP = DSI;
    bool Printed = DSI != 0;
    for (BasicBlock::const_iterator i = BB->begin(), e = BB->end();
         i != e; ++i) {
      if (isa<DbgInfoIntrinsic>(i)) {
        if ((DSI = dyn_cast<DbgStopPointInst>(i))) {
          if (DSI->getContext() == LastDSP->getContext() &&
              DSI->getLineValue() == LastDSP->getLineValue() &&
              DSI->getColumnValue() == LastDSP->getColumnValue())
            // Don't print same location twice.
            continue;

          LastDSP = cast<DbgStopPointInst>(i);

          // Don't print consecutive stoppoints, use a flag to know which one we
          // printed.
          Printed = false;
        } else if (const DbgFuncStartInst *FS = dyn_cast<DbgFuncStartInst>(i)) {
          printFuncStart(FS);
        }
      } else {
        if (!Printed && LastDSP) {
          Out << "; ";
          printStopPoint(LastDSP);
          Out << "\n";
          Printed = true;
        }

        Out << *i;
        printVariableDeclaration(i);

        if (const User *U = dyn_cast<User>(i)) {
          for(unsigned i=0;i<U->getNumOperands();i++)
            printVariableDeclaration(U->getOperand(i));
        }
      }
    }
  }

  return false;
}
<commit_msg>Use getReturnTypeName() to print return type.<commit_after>//===- DbgInfoPrinter.cpp - Print debug info in a human readable form ------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass that prints instructions, and associated debug
// info:
//
//   - source/line/col information
//   - original variable name
//   - original type name
//
//===----------------------------------------------------------------------===//

#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool>
PrintDirectory("print-fullpath",
               cl::desc("Print fullpath when printing debug info"),
               cl::Hidden);

namespace {
  class VISIBILITY_HIDDEN PrintDbgInfo : public FunctionPass {
    raw_ostream &Out;
    void printStopPoint(const DbgStopPointInst *DSI);
    void printFuncStart(const DbgFuncStartInst *FS);
    void printVariableDeclaration(const Value *V);
  public:
    static char ID; // Pass identification
    PrintDbgInfo() : FunctionPass(&ID), Out(outs()) {}

    virtual bool runOnFunction(Function &F);
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };
  char PrintDbgInfo::ID = 0;
  static RegisterPass<PrintDbgInfo> X("print-dbginfo",
                                     "Print debug info in human readable form");
}

FunctionPass *llvm::createDbgInfoPrinterPass() { return new PrintDbgInfo(); }

void PrintDbgInfo::printVariableDeclaration(const Value *V) {
  std::string DisplayName, File, Directory, Type;
  unsigned LineNo;

  if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory))
    return;

  Out << "; ";
  WriteAsOperand(Out, V, false, 0);
  Out << " is variable " << DisplayName
      << " of type " << Type << " declared at ";

  if (PrintDirectory)
    Out << Directory << "/";

  Out << File << ":" << LineNo << "\n";
}

void PrintDbgInfo::printStopPoint(const DbgStopPointInst *DSI) {
  if (PrintDirectory) {
    std::string dir;
    GetConstantStringInfo(DSI->getDirectory(), dir);
    Out << dir << "/";
  }

  std::string file;
  GetConstantStringInfo(DSI->getFileName(), file);
  Out << file << ":" << DSI->getLine();

  if (unsigned Col = DSI->getColumn())
    Out << ":" << Col;
}

void PrintDbgInfo::printFuncStart(const DbgFuncStartInst *FS) {
  DISubprogram Subprogram(cast<GlobalVariable>(FS->getSubprogram()));
  std::string Res1, Res2;
  Out << "; fully qualified function name: " << Subprogram.getDisplayName(Res1)
      << " return type: " << Subprogram.getReturnTypeName(Res2)
      << " at line " << Subprogram.getLineNumber()
      << "\n\n";
}

bool PrintDbgInfo::runOnFunction(Function &F) {
  if (F.isDeclaration())
    return false;

  Out << "function " << F.getName() << "\n\n";

  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    BasicBlock *BB = I;

    if (I != F.begin() && (pred_begin(BB) == pred_end(BB)))
      // Skip dead blocks.
      continue;

    const DbgStopPointInst *DSI = findBBStopPoint(BB);
    Out << BB->getName();
    Out << ":";

    if (DSI) {
      Out << "; (";
      printStopPoint(DSI);
      Out << ")";
    }

    Out << "\n";

    // A dbgstoppoint's information is valid until we encounter a new one.
    const DbgStopPointInst *LastDSP = DSI;
    bool Printed = DSI != 0;
    for (BasicBlock::const_iterator i = BB->begin(), e = BB->end();
         i != e; ++i) {
      if (isa<DbgInfoIntrinsic>(i)) {
        if ((DSI = dyn_cast<DbgStopPointInst>(i))) {
          if (DSI->getContext() == LastDSP->getContext() &&
              DSI->getLineValue() == LastDSP->getLineValue() &&
              DSI->getColumnValue() == LastDSP->getColumnValue())
            // Don't print same location twice.
            continue;

          LastDSP = cast<DbgStopPointInst>(i);

          // Don't print consecutive stoppoints, use a flag to know which one we
          // printed.
          Printed = false;
        } else if (const DbgFuncStartInst *FS = dyn_cast<DbgFuncStartInst>(i)) {
          printFuncStart(FS);
        }
      } else {
        if (!Printed && LastDSP) {
          Out << "; ";
          printStopPoint(LastDSP);
          Out << "\n";
          Printed = true;
        }

        Out << *i;
        printVariableDeclaration(i);

        if (const User *U = dyn_cast<User>(i)) {
          for(unsigned i=0;i<U->getNumOperands();i++)
            printVariableDeclaration(U->getOperand(i));
        }
      }
    }
  }

  return false;
}
<|endoftext|>


<commit_before>// Copyright (c) 2019, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <unistd.h>
#include <cmath>
#include <future>
#include <iostream>
#include <string>
#include "src/clients/c++/library/request_grpc.h"
#include "src/clients/c++/library/request_http.h"

namespace ni = nvidia::inferenceserver;
namespace nic = nvidia::inferenceserver::client;

constexpr uint64_t NANOS_PER_SECOND = 1000000000;
#define TIMESPEC_TO_NANOS(TS) ((TS).tv_sec * NANOS_PER_SECOND + (TS).tv_nsec)

#define FAIL_IF_ERR(X, MSG)                                        \
  {                                                                \
    nic::Error err = (X);                                          \
    if (!err.IsOk()) {                                             \
      std::cerr << "error: " << (MSG) << ": " << err << std::endl; \
      exit(1);                                                     \
    }                                                              \
  }

#define FAIL_IF(X, MSG)                             \
  {                                                 \
    if (X) {                                        \
      std::cerr << "error: " << (MSG) << std::endl; \
      exit(1);                                      \
    }                                               \
  }

namespace {

void
RunSyncSerial(
    nic::InferContext* ctx, const uint32_t iters,
    std::vector<uint64_t>* duration_ns)
{
  if (duration_ns != nullptr) {
    duration_ns->clear();
  }

  for (uint32_t iter = 0; iter < iters; iter++) {
    std::map<std::string, std::unique_ptr<nic::InferContext::Result>> results;

    struct timespec start;
    clock_gettime(CLOCK_MONOTONIC, &start);

    FAIL_IF_ERR(ctx->Run(&results), "unable to run");

    struct timespec end;
    clock_gettime(CLOCK_MONOTONIC, &end);

    // We expect there to be 1 result.
    FAIL_IF(
        results.size() != 1,
        "expected 1 result, got " + std::to_string(results.size()));

    if (duration_ns != nullptr) {
      uint64_t start_ns = TIMESPEC_TO_NANOS(start);
      uint64_t end_ns = TIMESPEC_TO_NANOS(end);
      duration_ns->push_back(end_ns - start_ns);
    }
  }
}

void
RunAsyncComplete(
    nic::InferContext* ctx, std::shared_ptr<nic::InferContext::Request> request,
    std::promise<uint64_t>* p)
{
  // We include getting the results in the timing since that is
  // included in the sync case as well.
  bool is_ready = false;
  std::map<std::string, std::unique_ptr<nic::InferContext::Result>> results;
  ctx->GetAsyncRunResults(&results, &is_ready, request, false);
  FAIL_IF(!is_ready, "callback invoked when request is not ready");

  FAIL_IF(
      results.size() != 1,
      "expected 1 result, got " + std::to_string(results.size()));

  struct timespec end;
  clock_gettime(CLOCK_MONOTONIC, &end);
  uint64_t end_ns = TIMESPEC_TO_NANOS(end);

  p->set_value(end_ns);
  delete p;
}

void
RunAsyncSerial(
    nic::InferContext* ctx, const uint32_t iters,
    std::vector<uint64_t>* duration_ns)
{
  if (duration_ns != nullptr) {
    duration_ns->clear();
  }

  for (uint32_t iter = 0; iter < iters; iter++) {
    auto p = new std::promise<uint64_t>();
    std::future<uint64_t> completed = p->get_future();

    struct timespec start;
    clock_gettime(CLOCK_MONOTONIC, &start);

    FAIL_IF_ERR(
        ctx->AsyncRun([p](nic::InferContext* ctx,
                          std::shared_ptr<nic::InferContext::Request> request) {
          RunAsyncComplete(ctx, request, p);
        }),
        "unable to async run");

    uint64_t end_ns = completed.get();
    if (duration_ns != nullptr) {
      uint64_t start_ns = TIMESPEC_TO_NANOS(start);
      duration_ns->push_back(end_ns - start_ns);
    }
  }
}

void
ShowResults(
    const std::vector<uint64_t>& duration_ns, const std::string& name,
    const std::string& protocol, const bool verbose)
{
  uint64_t sum_ns = 0;
  for (const auto ns : duration_ns) {
    if (verbose) {
      std::cout << ((ns / 1000) / 1000.0) << " ms" << std::endl;
    }

    sum_ns += ns;
  }

  const uint64_t sum_us = sum_ns / 1000;
  const uint64_t mean_us = sum_us / duration_ns.size();
  uint64_t var_us = 0;
  for (size_t n = 0; n < duration_ns.size(); n++) {
    uint64_t diff_us = (duration_ns[n] / 1000) - mean_us;
    var_us += diff_us * diff_us;
  }

  var_us /= duration_ns.size();
  uint64_t stddev_us = std::sqrt(var_us);

  std::cout << name << " (" << protocol << ")" << std::endl;
  std::cout << "Total time: " << (sum_us / 1000.0) << " ms" << std::endl;
  std::cout << "Mean time: " << (mean_us / 1000.0) << " ms" << std::endl;
  std::cout << "Stddev: " << (stddev_us / 1000.0) << " ms" << std::endl;
}

void
Usage(char** argv, const std::string& msg = std::string())
{
  if (!msg.empty()) {
    std::cerr << "error: " << msg << std::endl;
  }

  std::cerr << "Usage: " << argv[0] << " [options]" << std::endl;
  std::cerr << "\t-v" << std::endl;
  std::cerr << "\t-i <Protocol used to communicate with inference service>"
            << std::endl;
  std::cerr << "\t-u <URL for inference service>" << std::endl;
  std::cerr << "\t-m <model name>" << std::endl;
  std::cerr << "\t-b <batch size>" << std::endl;
  std::cerr << "\t-s <inference size>" << std::endl;
  std::cerr << "\t-w <warmup iterations>" << std::endl;
  std::cerr << "\t-n <measurement iterations>" << std::endl;
  std::cerr << std::endl;
  std::cerr
      << "For -i, available protocols are 'grpc' and 'http'. Default is 'http."
      << std::endl;
  std::cerr
      << "For -s, specify the input size in fp32 elements. So a value of 8 "
         "indicates that input will be a tensor of 8 fp32 elements. Output "
         "tensor size equals input tensor size. Default is 1."
      << std::endl;

  exit(1);
}

}  // namespace

int
main(int argc, char** argv)
{
  bool verbose = false;
  std::string url("localhost:8000");
  std::string protocol = "http";
  std::string model_name;
  uint32_t batch_size = 1;
  uint32_t tensor_size = 1;
  uint32_t warmup_iters = 10;
  uint32_t measure_iters = 10;

  // Parse commandline...
  int opt;
  while ((opt = getopt(argc, argv, "vi:u:m:b:s:w:n:")) != -1) {
    switch (opt) {
      case 'v':
        verbose = true;
        break;
      case 'i':
        protocol = optarg;
        break;
      case 'u':
        url = optarg;
        break;
      case 'm':
        model_name = optarg;
        break;
      case 'b':
        batch_size = std::stoul(optarg);
        break;
      case 's':
        tensor_size = std::stoul(optarg);
        break;
      case 'w':
        warmup_iters = std::stoul(optarg);
        break;
      case 'n':
        measure_iters = std::stoul(optarg);
        break;
      case '?':
        Usage(argv);
        break;
    }
  }

  nic::Error err;

  if (model_name.empty()) {
    Usage(argv, "-m <model name> must be specified");
  }

  // Create the inference context for the model.
  std::unique_ptr<nic::InferContext> ctx;
  if (protocol == "http") {
    err = nic::InferHttpContext::Create(
        &ctx, url, model_name, -1 /* model_version */, verbose);
  } else if (protocol == "grpc") {
    err = nic::InferGrpcContext::Create(
        &ctx, url, model_name, -1 /* model_version */, verbose);
  } else {
    Usage(argv, "unknown protocol '" + protocol + "'");
  }

  if (!err.IsOk()) {
    std::cerr << "error: unable to create inference context: " << err
              << std::endl;
    exit(1);
  }

  // Set the context options to specified batch-size and request
  // size. Request that all output tensors be returned.
  std::unique_ptr<nic::InferContext::Options> options;
  FAIL_IF_ERR(
      nic::InferContext::Options::Create(&options),
      "unable to create inference options");

  options->SetBatchSize(batch_size);
  for (const auto& output : ctx->Outputs()) {
    options->AddRawResult(output);
  }

  FAIL_IF_ERR(ctx->SetRunOptions(*options), "unable to set inference options");

  // Create a memory block for the input data. We don't bother to
  // initialize it. Set the input tensor to use that data.
  std::vector<float> input_data(tensor_size);

  const std::vector<std::shared_ptr<nic::InferContext::Input>>& inputs =
      ctx->Inputs();
  FAIL_IF(inputs.size() != 1, "expected 1 model input");
  std::shared_ptr<nic::InferContext::Input> input = inputs[0];
  FAIL_IF_ERR(input->Reset(), "unable to reset INPUT0");

  std::vector<int64_t> input_shape{tensor_size};
  FAIL_IF_ERR(input->SetShape(input_shape), "unable to set shape for input");
  FAIL_IF_ERR(
      input->SetRaw(
          reinterpret_cast<uint8_t*>(&input_data[0]),
          input_data.size() * sizeof(float)),
      "unable to set data for input");

  std::vector<uint64_t> duration_ns;

  // Warmup
  RunSyncSerial(ctx.get(), warmup_iters, nullptr /* duration_ns */);

  // Test sync serial
  RunSyncSerial(ctx.get(), measure_iters, &duration_ns);
  ShowResults(duration_ns, "Sync Serial Run", protocol, verbose);

  // Test async serial
  RunAsyncSerial(ctx.get(), measure_iters, &duration_ns);
  ShowResults(duration_ns, "Async Serial Run", protocol, verbose);

  return 0;
}
<commit_msg>L0_perf -> L0_simple_perf (#747)<commit_after>// Copyright (c) 2019, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <unistd.h>
#include <cmath>
#include <future>
#include <iostream>
#include <string>
#include "src/clients/c++/library/request_grpc.h"
#include "src/clients/c++/library/request_http.h"

namespace ni = nvidia::inferenceserver;
namespace nic = nvidia::inferenceserver::client;

constexpr uint64_t NANOS_PER_SECOND = 1000000000;
#define TIMESPEC_TO_NANOS(TS) ((TS).tv_sec * NANOS_PER_SECOND + (TS).tv_nsec)

#define FAIL_IF_ERR(X, MSG)                                        \
  {                                                                \
    nic::Error err = (X);                                          \
    if (!err.IsOk()) {                                             \
      std::cerr << "error: " << (MSG) << ": " << err << std::endl; \
      exit(1);                                                     \
    }                                                              \
  }

#define FAIL_IF(X, MSG)                             \
  {                                                 \
    if (X) {                                        \
      std::cerr << "error: " << (MSG) << std::endl; \
      exit(1);                                      \
    }                                               \
  }

namespace {

void
RunSyncSerial(
    nic::InferContext* ctx, const uint32_t iters,
    std::vector<uint64_t>* duration_ns)
{
  if (duration_ns != nullptr) {
    duration_ns->clear();
  }

  for (uint32_t iter = 0; iter < iters; iter++) {
    std::map<std::string, std::unique_ptr<nic::InferContext::Result>> results;

    struct timespec start;
    clock_gettime(CLOCK_MONOTONIC, &start);

    FAIL_IF_ERR(ctx->Run(&results), "unable to run");

    struct timespec end;
    clock_gettime(CLOCK_MONOTONIC, &end);

    // We expect there to be 1 result.
    FAIL_IF(
        results.size() != 1,
        "expected 1 result, got " + std::to_string(results.size()));

    if (duration_ns != nullptr) {
      uint64_t start_ns = TIMESPEC_TO_NANOS(start);
      uint64_t end_ns = TIMESPEC_TO_NANOS(end);
      duration_ns->push_back(end_ns - start_ns);
    }
  }
}

void
RunAsyncComplete(
    nic::InferContext* ctx, std::shared_ptr<nic::InferContext::Request> request,
    std::promise<uint64_t>* p)
{
  // We include getting the results in the timing since that is
  // included in the sync case as well.
  bool is_ready = false;
  std::map<std::string, std::unique_ptr<nic::InferContext::Result>> results;
  ctx->GetAsyncRunResults(&results, &is_ready, request, false);
  FAIL_IF(!is_ready, "callback invoked when request is not ready");

  FAIL_IF(
      results.size() != 1,
      "expected 1 result, got " + std::to_string(results.size()));

  struct timespec end;
  clock_gettime(CLOCK_MONOTONIC, &end);
  uint64_t end_ns = TIMESPEC_TO_NANOS(end);

  p->set_value(end_ns);
  delete p;
}

void
RunAsyncSerial(
    nic::InferContext* ctx, const uint32_t iters,
    std::vector<uint64_t>* duration_ns)
{
  if (duration_ns != nullptr) {
    duration_ns->clear();
  }

  for (uint32_t iter = 0; iter < iters; iter++) {
    auto p = new std::promise<uint64_t>();
    std::future<uint64_t> completed = p->get_future();

    struct timespec start;
    clock_gettime(CLOCK_MONOTONIC, &start);

    FAIL_IF_ERR(
        ctx->AsyncRun([p](nic::InferContext* ctx,
                          std::shared_ptr<nic::InferContext::Request> request) {
          RunAsyncComplete(ctx, request, p);
        }),
        "unable to async run");

    uint64_t end_ns = completed.get();
    if (duration_ns != nullptr) {
      uint64_t start_ns = TIMESPEC_TO_NANOS(start);
      duration_ns->push_back(end_ns - start_ns);
    }
  }
}

void
ShowResults(
    const std::vector<uint64_t>& duration_ns, const std::string& name,
    const std::string& framework, const std::string& model_name,
    const std::string& protocol, const uint32_t batch_size,
    const uint32_t tensor_size, const bool json, const bool verbose)
{
  uint64_t sum_ns = 0;
  for (const auto ns : duration_ns) {
    if (verbose) {
      std::cout << ((ns / 1000) / 1000.0) << " ms" << std::endl;
    }

    sum_ns += ns;
  }

  const uint64_t sum_us = sum_ns / 1000;
  const uint64_t mean_us = sum_us / duration_ns.size();
  uint64_t var_us = 0;
  for (size_t n = 0; n < duration_ns.size(); n++) {
    uint64_t diff_us = (duration_ns[n] / 1000) - mean_us;
    var_us += diff_us * diff_us;
  }

  var_us /= duration_ns.size();
  uint64_t stddev_us = std::sqrt(var_us);

  if (json) {
    std::cout << "{\"s_benchmark_kind\":\"simple_perf\",";
    std::cout << "\"s_benchmark_name\":\"" << name << "\",";
    std::cout << "\"s_protocol\":\"" << protocol << "\",";
    std::cout << "\"s_framework\":\"" << framework << "\",";
    std::cout << "\"s_model\":\"" << model_name << "\",";
    std::cout << "\"l_batch_size\":" << batch_size << ",";
    std::cout << "\"l_size\":" << tensor_size << ",";
    std::cout << "\"d_latency_avg_ms\":" << (mean_us / 1000.0) << ",";
    std::cout << "\"d_latency_avg_stddev_ms\":" << (stddev_us / 1000.0) << "}";
  } else {
    std::cout << name << " (" << protocol << ")" << std::endl;
    std::cout << "Total time: " << (sum_us / 1000.0) << " ms" << std::endl;
    std::cout << "Mean time: " << (mean_us / 1000.0) << " ms" << std::endl;
    std::cout << "Stddev: " << (stddev_us / 1000.0) << " ms" << std::endl;
  }
}

void
Usage(char** argv, const std::string& msg = std::string())
{
  if (!msg.empty()) {
    std::cerr << "error: " << msg << std::endl;
  }

  std::cerr << "Usage: " << argv[0] << " [options]" << std::endl;
  std::cerr << "\t-v" << std::endl;
  std::cerr << "\t-i <Protocol used to communicate with inference service>"
            << std::endl;
  std::cerr << "\t-u <URL for inference service>" << std::endl;
  std::cerr << "\t-f <model framework>" << std::endl;
  std::cerr << "\t-m <model name>" << std::endl;
  std::cerr << "\t-b <batch size>" << std::endl;
  std::cerr << "\t-s <inference size>" << std::endl;
  std::cerr << "\t-w <warmup iterations>" << std::endl;
  std::cerr << "\t-n <measurement iterations>" << std::endl;
  std::cerr << std::endl;
  std::cerr
      << "For -i, available protocols are 'grpc' and 'http'. Default is 'http."
      << std::endl;
  std::cerr
      << "For -s, specify the input size in fp32 elements. So a value of 8 "
         "indicates that input will be a tensor of 8 fp32 elements. Output "
         "tensor size equals input tensor size. Default is 1."
      << std::endl;

  exit(1);
}

}  // namespace

int
main(int argc, char** argv)
{
  bool verbose = false;
  bool json = false;
  std::string url("localhost:8000");
  std::string protocol = "http";
  std::string model_name;
  std::string framework;
  uint32_t batch_size = 1;
  uint32_t tensor_size = 1;
  uint32_t warmup_iters = 10;
  uint32_t measure_iters = 10;

  // Parse commandline...
  int opt;
  while ((opt = getopt(argc, argv, "vji:u:m:f:b:s:w:n:")) != -1) {
    switch (opt) {
      case 'v':
        verbose = true;
        break;
      case 'j':
        json = true;
        break;
      case 'i':
        protocol = optarg;
        break;
      case 'u':
        url = optarg;
        break;
      case 'm':
        model_name = optarg;
        break;
      case 'f':
        framework = optarg;
        break;
      case 'b':
        batch_size = std::stoul(optarg);
        break;
      case 's':
        tensor_size = std::stoul(optarg);
        break;
      case 'w':
        warmup_iters = std::stoul(optarg);
        break;
      case 'n':
        measure_iters = std::stoul(optarg);
        break;
      case '?':
        Usage(argv);
        break;
    }
  }

  nic::Error err;

  if (model_name.empty()) {
    Usage(argv, "-m <model name> must be specified");
  }

  // Create the inference context for the model.
  std::unique_ptr<nic::InferContext> ctx;
  if (protocol == "http") {
    err = nic::InferHttpContext::Create(
        &ctx, url, model_name, -1 /* model_version */, verbose);
  } else if (protocol == "grpc") {
    err = nic::InferGrpcContext::Create(
        &ctx, url, model_name, -1 /* model_version */, verbose);
  } else {
    Usage(argv, "unknown protocol '" + protocol + "'");
  }

  if (!err.IsOk()) {
    std::cerr << "error: unable to create inference context: " << err
              << std::endl;
    exit(1);
  }

  // Set the context options to specified batch-size and request
  // size. Request that all output tensors be returned.
  std::unique_ptr<nic::InferContext::Options> options;
  FAIL_IF_ERR(
      nic::InferContext::Options::Create(&options),
      "unable to create inference options");

  options->SetBatchSize(batch_size);
  for (const auto& output : ctx->Outputs()) {
    options->AddRawResult(output);
  }

  FAIL_IF_ERR(ctx->SetRunOptions(*options), "unable to set inference options");

  // Create a memory block for the input data. We don't bother to
  // initialize it. Set the input tensor to use that data.
  std::vector<float> input_data(tensor_size);

  const std::vector<std::shared_ptr<nic::InferContext::Input>>& inputs =
      ctx->Inputs();
  FAIL_IF(inputs.size() != 1, "expected 1 model input");
  std::shared_ptr<nic::InferContext::Input> input = inputs[0];
  FAIL_IF_ERR(input->Reset(), "unable to reset INPUT0");

  std::vector<int64_t> input_shape{tensor_size};
  FAIL_IF_ERR(input->SetShape(input_shape), "unable to set shape for input");
  for (uint32_t b = 0; b < batch_size; ++b) {
    FAIL_IF_ERR(
        input->SetRaw(
            reinterpret_cast<uint8_t*>(&input_data[0]),
            input_data.size() * sizeof(float)),
        "unable to set data for input");
  }

  std::vector<uint64_t> duration_ns;

  // Warmup
  RunSyncSerial(ctx.get(), warmup_iters, nullptr /* duration_ns */);

  // Test sync serial
  RunSyncSerial(ctx.get(), measure_iters, &duration_ns);
  ShowResults(
      duration_ns, "sync_serial", framework, model_name, protocol, batch_size,
      tensor_size, json, verbose);

  if (json) {
    std::cout << ",";
  }

  // Test async serial
  RunAsyncSerial(ctx.get(), measure_iters, &duration_ns);
  ShowResults(
      duration_ns, "async_serial", framework, model_name, protocol, batch_size,
      tensor_size, json, verbose);

  return 0;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 "paddle/memory/memory.h"
#include "paddle/memory/detail/memory_block.h"
#include "paddle/memory/detail/meta_data.h"

#include "paddle/platform/cpu_info.h"
#include "paddle/platform/gpu_info.h"
#include "paddle/platform/place.h"

#include <gtest/gtest.h>
#include <unordered_map>

inline bool is_aligned(void const *p, const size_t n) {
  return 0 == (reinterpret_cast<uintptr_t>(p) % n);
}

size_t align(size_t size, paddle::platform::CPUPlace place) {
  size += sizeof(paddle::memory::detail::Metadata);
  size_t alignment = paddle::platform::CpuMinChunkSize();
  size_t remaining = size % alignment;
  return remaining == 0 ? size : size + (alignment - remaining);
}

size_t align(size_t size, paddle::platform::GPUPlace place) {
  size += sizeof(paddle::memory::detail::Metadata);
  size_t alignment = paddle::platform::GpuMinChunkSize();
  size_t remaining = size % alignment;
  return remaining == 0 ? size : size + (alignment - remaining);
}

void update_size(size_t &total_size, const size_t size) {}

TEST(BuddyAllocator, CPUAllocation) {
  void *p = nullptr;

  EXPECT_EQ(p, nullptr);

  paddle::platform::CPUPlace cpu;
  p = paddle::memory::Alloc(cpu, 4096);

  EXPECT_NE(p, nullptr);

  paddle::memory::Free(cpu, p);
}

TEST(BuddyAllocator, CPUMultAlloc) {
  paddle::platform::CPUPlace cpu;

  std::unordered_map<void *, size_t> ps;

  size_t total_size = paddle::memory::Used(cpu);
  EXPECT_EQ(total_size, 0UL);

  for (auto size :
       {128, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304}) {
    ps[paddle::memory::Alloc(cpu, size)] = size;

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(cpu) == total_size) continue;

    size_t aligned_size = align(size, cpu);
    total_size += aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(cpu));
  }

  for (auto p : ps) {
    EXPECT_EQ(is_aligned(p.first, 32), true);
    paddle::memory::Free(cpu, p.first);

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(cpu) == total_size) continue;

    size_t aligned_size = align(p.second, cpu);
    total_size -= aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(cpu));
  }
}

#ifndef PADDLE_ONLY_CPU

TEST(BuddyAllocator, GPUAllocation) {
  void *p = nullptr;

  EXPECT_EQ(p, nullptr);

  paddle::platform::GPUPlace gpu(0);
  p = paddle::memory::Alloc(gpu, 4096);

  EXPECT_NE(p, nullptr);

  paddle::memory::Free(gpu, p);
}

TEST(BuddyAllocator, GPUMultAlloc) {
  paddle::platform::GPUPlace gpu;

  std::unordered_map<void *, size_t> ps;

  size_t total_size = paddle::memory::Used(gpu);
  EXPECT_EQ(total_size, 0UL);

  for (auto size :
       {128, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304}) {
    ps[paddle::memory::Alloc(gpu, size)] = size;

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(gpu) == total_size) continue;

    size_t aligned_size = align(size, gpu);
    total_size += aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(gpu));
  }

  for (auto p : ps) {
    EXPECT_EQ(is_aligned(p.first, 32), true);
    paddle::memory::Free(gpu, p.first);

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(gpu) == total_size) continue;

    size_t aligned_size = align(p.second, gpu);
    total_size -= aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(gpu));
  }
}

#endif  // PADDLE_ONLY_CPU
<commit_msg>Fix condition compile<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 "paddle/memory/memory.h"
#include "paddle/memory/detail/memory_block.h"
#include "paddle/memory/detail/meta_data.h"

#include "paddle/platform/cpu_info.h"
#include "paddle/platform/gpu_info.h"
#include "paddle/platform/place.h"

#include <gtest/gtest.h>
#include <unordered_map>

inline bool is_aligned(void const *p, const size_t n) {
  return 0 == (reinterpret_cast<uintptr_t>(p) % n);
}

size_t align(size_t size, paddle::platform::CPUPlace place) {
  size += sizeof(paddle::memory::detail::Metadata);
  size_t alignment = paddle::platform::CpuMinChunkSize();
  size_t remaining = size % alignment;
  return remaining == 0 ? size : size + (alignment - remaining);
}

void update_size(size_t &total_size, const size_t size) {}

TEST(BuddyAllocator, CPUAllocation) {
  void *p = nullptr;

  EXPECT_EQ(p, nullptr);

  paddle::platform::CPUPlace cpu;
  p = paddle::memory::Alloc(cpu, 4096);

  EXPECT_NE(p, nullptr);

  paddle::memory::Free(cpu, p);
}

TEST(BuddyAllocator, CPUMultAlloc) {
  paddle::platform::CPUPlace cpu;

  std::unordered_map<void *, size_t> ps;

  size_t total_size = paddle::memory::Used(cpu);
  EXPECT_EQ(total_size, 0UL);

  for (auto size :
       {128, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304}) {
    ps[paddle::memory::Alloc(cpu, size)] = size;

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(cpu) == total_size) continue;

    size_t aligned_size = align(size, cpu);
    total_size += aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(cpu));
  }

  for (auto p : ps) {
    EXPECT_EQ(is_aligned(p.first, 32), true);
    paddle::memory::Free(cpu, p.first);

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(cpu) == total_size) continue;

    size_t aligned_size = align(p.second, cpu);
    total_size -= aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(cpu));
  }
}

#ifndef PADDLE_ONLY_CPU

size_t align(size_t size, paddle::platform::GPUPlace place) {
  size += sizeof(paddle::memory::detail::Metadata);
  size_t alignment = paddle::platform::GpuMinChunkSize();
  size_t remaining = size % alignment;
  return remaining == 0 ? size : size + (alignment - remaining);
}

TEST(BuddyAllocator, GPUAllocation) {
  void *p = nullptr;

  EXPECT_EQ(p, nullptr);

  paddle::platform::GPUPlace gpu(0);
  p = paddle::memory::Alloc(gpu, 4096);

  EXPECT_NE(p, nullptr);

  paddle::memory::Free(gpu, p);
}

TEST(BuddyAllocator, GPUMultAlloc) {
  paddle::platform::GPUPlace gpu;

  std::unordered_map<void *, size_t> ps;

  size_t total_size = paddle::memory::Used(gpu);
  EXPECT_EQ(total_size, 0UL);

  for (auto size :
       {128, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304}) {
    ps[paddle::memory::Alloc(gpu, size)] = size;

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(gpu) == total_size) continue;

    size_t aligned_size = align(size, gpu);
    total_size += aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(gpu));
  }

  for (auto p : ps) {
    EXPECT_EQ(is_aligned(p.first, 32), true);
    paddle::memory::Free(gpu, p.first);

    // Buddy Allocator doesn't manage too large memory chunk
    if (paddle::memory::Used(gpu) == total_size) continue;

    size_t aligned_size = align(p.second, gpu);
    total_size -= aligned_size;
    EXPECT_EQ(total_size, paddle::memory::Used(gpu));
  }
}

#endif  // PADDLE_ONLY_CPU
<|endoftext|>


<commit_before>//===-- MakefileDepsParser.cpp --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "llbuild/Core/MakefileDepsParser.h"

using namespace llbuild;
using namespace llbuild::core;

MakefileDepsParser::ParseActions::~ParseActions() {}

#pragma mark - MakefileDepsParser Implementation

static bool IsWordChar(int Char) {
  switch (Char) {
  case '\0':
  case '\t':
  case '\n':
  case ' ':
  case '$':
  case ':':
  case ';':
  case '=':
  case '|':
  case '%':
    return false;
  default:
    return true;
  }
}

static void SkipWhitespaceAndComments(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    // Skip comments.
    if (Char == '#') {
      // Skip to the next newline.
      while (Cur + 1 != End && Cur[1] == '\n')
        ++Cur;
      continue;
    }

    if (Char == ' ' || Char == '\t' || Char == '\n')
      continue;

    break;
  }
}

static void SkipNonNewlineWhitespace(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    // Skip regular whitespace.
    if (Char == ' ' || Char == '\t')
      continue;

    // If this is an escaped newline, also skip it.
    if (Char == '\\' && Cur + 1 != End && Cur[1] == '\n') {
      ++Cur;
      continue;
    }

    // Otherwise, stop scanning.
    break;
  }
}

static void SkipToEndOfLine(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    if (Char == '\n') {
      ++Cur;
      break;
    }
  }
}

static void LexWord(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    // Check if this is an escape sequence.
    if (Char == '\\') {
      // If this is a line continuation, it ends the word.
      if (Cur + 1 != End && Cur[1] == '\n')
        break;
>
      // Otherwise, skip the escaped character.
      ++Cur;
      continue;
    }

    // Otherwise, if this is not a valid word character then skip it.
    if (!IsWordChar(*Cur))
      break;
  }
}

void MakefileDepsParser::parse() {
  const char* Cur = Data;
  const char* End = Data + Length;

  // While we have input data...
  while (Cur != End) {
    // Skip leading whitespace and comments.
    SkipWhitespaceAndComments(Cur, End);

    // The next token should be a word.
    const char* WordStart = Cur;
    LexWord(Cur, End);
    if (Cur == WordStart) {
      Actions.error("unexpected character in file", Cur - Data);
      SkipToEndOfLine(Cur, End);
      continue;
    }
    Actions.actOnRuleStart(WordStart, Cur - WordStart);

    // The next token should be a colon.
    SkipNonNewlineWhitespace(Cur, End);
    if (Cur == End || *Cur != ':') {
      Actions.error("missing ':' following rule", Cur - Data);
      Actions.actOnRuleEnd();
      SkipToEndOfLine(Cur, End);
      continue;
    }

    // Skip the colon.
    ++Cur;

    // Consume dependency words until we reach the end of a line.
    while (Cur != End) {
      // Skip forward and check for EOL.
      SkipNonNewlineWhitespace(Cur, End);
      if (Cur == End || *Cur == '\n')
        break;

      // Otherwise, we should have a word.
      const char* WordStart = Cur;
      LexWord(Cur, End);
      if (Cur == WordStart) {
        Actions.error("unexpected character in prerequisites", Cur - Data);
        SkipToEndOfLine(Cur, End);
        continue;
      }
      Actions.actOnRuleDependency(WordStart, Cur - WordStart);
    }
    Actions.actOnRuleEnd();
  }
}
<commit_msg>[Core/MakefileDepsParser] Fix a typo that got committed by mistake.<commit_after>//===-- MakefileDepsParser.cpp --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "llbuild/Core/MakefileDepsParser.h"

using namespace llbuild;
using namespace llbuild::core;

MakefileDepsParser::ParseActions::~ParseActions() {}

#pragma mark - MakefileDepsParser Implementation

static bool IsWordChar(int Char) {
  switch (Char) {
  case '\0':
  case '\t':
  case '\n':
  case ' ':
  case '$':
  case ':':
  case ';':
  case '=':
  case '|':
  case '%':
    return false;
  default:
    return true;
  }
}

static void SkipWhitespaceAndComments(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    // Skip comments.
    if (Char == '#') {
      // Skip to the next newline.
      while (Cur + 1 != End && Cur[1] == '\n')
        ++Cur;
      continue;
    }

    if (Char == ' ' || Char == '\t' || Char == '\n')
      continue;

    break;
  }
}

static void SkipNonNewlineWhitespace(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    // Skip regular whitespace.
    if (Char == ' ' || Char == '\t')
      continue;

    // If this is an escaped newline, also skip it.
    if (Char == '\\' && Cur + 1 != End && Cur[1] == '\n') {
      ++Cur;
      continue;
    }

    // Otherwise, stop scanning.
    break;
  }
}

static void SkipToEndOfLine(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    if (Char == '\n') {
      ++Cur;
      break;
    }
  }
}

static void LexWord(const char*& Cur, const char* End) {
  for (; Cur != End; ++Cur) {
    int Char = *Cur;

    // Check if this is an escape sequence.
    if (Char == '\\') {
      // If this is a line continuation, it ends the word.
      if (Cur + 1 != End && Cur[1] == '\n')
        break;

      // Otherwise, skip the escaped character.
      ++Cur;
      continue;
    }

    // Otherwise, if this is not a valid word character then skip it.
    if (!IsWordChar(*Cur))
      break;
  }
}

void MakefileDepsParser::parse() {
  const char* Cur = Data;
  const char* End = Data + Length;

  // While we have input data...
  while (Cur != End) {
    // Skip leading whitespace and comments.
    SkipWhitespaceAndComments(Cur, End);

    // The next token should be a word.
    const char* WordStart = Cur;
    LexWord(Cur, End);
    if (Cur == WordStart) {
      Actions.error("unexpected character in file", Cur - Data);
      SkipToEndOfLine(Cur, End);
      continue;
    }
    Actions.actOnRuleStart(WordStart, Cur - WordStart);

    // The next token should be a colon.
    SkipNonNewlineWhitespace(Cur, End);
    if (Cur == End || *Cur != ':') {
      Actions.error("missing ':' following rule", Cur - Data);
      Actions.actOnRuleEnd();
      SkipToEndOfLine(Cur, End);
      continue;
    }

    // Skip the colon.
    ++Cur;

    // Consume dependency words until we reach the end of a line.
    while (Cur != End) {
      // Skip forward and check for EOL.
      SkipNonNewlineWhitespace(Cur, End);
      if (Cur == End || *Cur == '\n')
        break;

      // Otherwise, we should have a word.
      const char* WordStart = Cur;
      LexWord(Cur, End);
      if (Cur == WordStart) {
        Actions.error("unexpected character in prerequisites", Cur - Data);
        SkipToEndOfLine(Cur, End);
        continue;
      }
      Actions.actOnRuleDependency(WordStart, Cur - WordStart);
    }
    Actions.actOnRuleEnd();
  }
}
<|endoftext|>


<commit_before>/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France       *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include <gtest/gtest.h>
#include <string>
#include <cgogn/io/map_import.h>

#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH)

using namespace cgogn::numerics;
using Vec3 = Eigen::Vector3d;
using Map2 = cgogn::CMap2;
using Map3 = cgogn::CMap3;

const std::string mesh_path(DEFAULT_MESH_PATH);

TEST(ImportTest, obj_surface_import)
{
	Map2 map2;
	testing::internal::CaptureStderr();
	cgogn::io::import_surface<Vec3>(map2, mesh_path + "obj/hand_remeshed.obj");
	const std::string expected_empty_error_output = testing::internal::GetCapturedStderr();

	auto pos = map2.get_attribute<Vec3, Map2::Vertex>("position");
	const uint32 nbv = map2.nb_cells<Map2::Vertex::ORBIT>();
	const uint32 nbf = map2.nb_cells<Map2::Face::ORBIT>();

	EXPECT_TRUE(pos.is_valid());
	EXPECT_TRUE(map2.check_map_integrity());
	EXPECT_EQ(nbv, 2500u);
	EXPECT_EQ(nbf, 4996u);
	EXPECT_TRUE(expected_empty_error_output.empty());
}

TEST(ImportTest, obj_normal_surface_import)
{
	Map2 map2;
	testing::internal::CaptureStderr();
	cgogn::io::import_surface<Vec3>(map2, mesh_path + "obj/salad_bowl.obj");
	const std::string expected_empty_error_output = testing::internal::GetCapturedStderr();

	auto pos = map2.get_attribute<Vec3, Map2::Vertex>("position");
	auto normal = map2.get_attribute<Vec3, Map2::Vertex>("normal");
	const uint32 nbv = map2.nb_cells<Map2::Vertex::ORBIT>();
	const uint32 nbf = map2.nb_cells<Map2::Face::ORBIT>();

	EXPECT_TRUE(pos.is_valid());
	EXPECT_TRUE(normal.is_valid());
	EXPECT_TRUE(map2.check_map_integrity());
	EXPECT_EQ(nbv, 706u);
	EXPECT_EQ(nbf, 1408u);
	EXPECT_TRUE(expected_empty_error_output.empty());
}
<commit_msg>wrong io obj test<commit_after>/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France       *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include <gtest/gtest.h>
#include <string>
#include <cgogn/io/map_import.h>

#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH)

using namespace cgogn::numerics;
using Vec3 = Eigen::Vector3d;
using Map2 = cgogn::CMap2;
using Map3 = cgogn::CMap3;

const std::string mesh_path(DEFAULT_MESH_PATH);

TEST(ImportTest, obj_surface_import)
{
	Map2 map2;
	testing::internal::CaptureStderr();
	cgogn::io::import_surface<Vec3>(map2, mesh_path + "obj/hand_remeshed.obj");
	const std::string expected_empty_error_output = testing::internal::GetCapturedStderr();

	auto pos = map2.get_attribute<Vec3, Map2::Vertex>("position");
	const uint32 nbv = map2.nb_cells<Map2::Vertex::ORBIT>();
	const uint32 nbf = map2.nb_cells<Map2::Face::ORBIT>();

	EXPECT_TRUE(pos.is_valid());
	EXPECT_TRUE(map2.check_map_integrity());
	EXPECT_EQ(nbv, 2500u);
	EXPECT_EQ(nbf, 4996u);
	EXPECT_TRUE(expected_empty_error_output.empty());
}

TEST(ImportTest, obj_normal_surface_import)
{
	Map2 map2;
	testing::internal::CaptureStderr();
	cgogn::io::import_surface<Vec3>(map2, mesh_path + "obj/salad_bowl.obj");
	const std::string expected_empty_error_output = testing::internal::GetCapturedStderr();

	auto pos = map2.get_attribute<Vec3, Map2::Vertex>("position");
	const uint32 nbv = map2.nb_cells<Map2::Vertex::ORBIT>();
	const uint32 nbf = map2.nb_cells<Map2::Face::ORBIT>();

	EXPECT_TRUE(pos.is_valid());
	EXPECT_TRUE(map2.check_map_integrity());
	EXPECT_EQ(nbv, 706u);
	EXPECT_EQ(nbf, 1408u);
	EXPECT_TRUE(expected_empty_error_output.empty());
}
<|endoftext|>


<commit_before>/* exception_handler.cc
   Jeremy Barnes, 26 February 2008
   Copyright (c) 2009 Jeremy Barnes.  All rights reserved.

*/

#include "exception.h"
#include "exception_hook.h"
#include "demangle.h"
#include <cxxabi.h>
#include "backtrace.h"
#include "jml/compiler/compiler.h"
#include "jml/utils/environment.h"

using namespace std;

namespace ML {

void (*exception_tracer) (void *, const std::type_info *) JML_WEAK_FN = 0;

Env_Option<bool> TRACE_EXCEPTIONS("JML_TRACE_EXCEPTIONS", true);

__thread bool trace_exceptions = false;
__thread bool trace_exceptions_initialized = false;

void set_default_trace_exceptions(bool val)
{
    TRACE_EXCEPTIONS.set(val);
}

bool get_default_trace_exceptions()
{
    return TRACE_EXCEPTIONS;
}

void set_trace_exceptions(bool trace)
{
    //cerr << "set_trace_exceptions to " << trace << " at " << &trace_exceptions
    //     << endl;
    trace_exceptions = trace;
    trace_exceptions_initialized = true;
}

bool get_trace_exceptions()
{
    if (!trace_exceptions_initialized) {
        //cerr << "trace_exceptions initialized to = "
        //     << trace_exceptions << " at " << &trace_exceptions << endl;
        set_trace_exceptions(TRACE_EXCEPTIONS);
        trace_exceptions_initialized = true;
    }

    //cerr << "get_trace_exceptions returned " << trace_exceptions
    //     << " at " << &trace_exceptions << endl;

    return trace_exceptions;
}

static const std::exception *
to_std_exception(void* object, const std::type_info * tinfo)
{
    /* Check if its a class.  If not, we can't see if it's a std::exception.
       The abi::__class_type_info is the base class of all types of type
       info for types that are classes (of which std::exception is one).
    */
    const abi::__class_type_info * ctinfo
        = dynamic_cast<const abi::__class_type_info *>(tinfo);

    if (!ctinfo) return 0;

    /* The thing thrown was an object.  Now, check if it is derived from
    std::exception. */
    const std::type_info * etinfo = &typeid(std::exception);

    /* See if the exception could catch this.  This is the mechanism
    used internally by the compiler in catch {} blocks to see if
    the exception matches the catch type.

    In the case of success, the object will be adjusted to point to
    the start of the std::exception object.
    */
    void * obj_ptr = object;
    bool can_catch = etinfo->__do_catch(tinfo, &obj_ptr, 0);

    if (!can_catch) return 0;

    /* obj_ptr points to a std::exception; extract it and get the
    exception message.
    */
    return (const std::exception *)obj_ptr;
}

/** We install this handler for when an exception is thrown. */

void trace_exception(void * object, const std::type_info * tinfo)
{
    //cerr << "trace_exception: trace_exceptions = " << get_trace_exceptions()
    //     << " at " << &trace_exceptions << endl;

    if (!get_trace_exceptions()) return;

    const std::exception * exc = to_std_exception(object, tinfo);

    // We don't want these exceptions to be printed out.
    if (dynamic_cast<const ML::SilentException *>(exc)) return;

    cerr << endl;
    cerr << "----------------- Exception thrown ------------------------"
         << endl;
    cerr << "type:   " << demangle(tinfo->name()) << endl;
    if (exc) cerr << "what:   " << exc->what() << endl;

    cerr << "stack:" << endl;
    backtrace(cerr, 3);
    cerr << endl;
}

namespace {
struct Install_Handler {
    Install_Handler()
    {
        //cerr << "installing exception tracer" << endl;
        exception_tracer = trace_exception;
    }
    ~Install_Handler()
    {
        if (exception_tracer == trace_exception)
            exception_tracer = 0;
    }
} install_handler;

} // file scope

} // namespace ML
<commit_msg>output the pid and kernel thread-id of the thread/process where the exception occurs<commit_after>/* exception_handler.cc
   Jeremy Barnes, 26 February 2008
   Copyright (c) 2009 Jeremy Barnes.  All rights reserved.

*/

#include <sys/syscall.h>
#include "exception.h"
#include "exception_hook.h"
#include "demangle.h"
#include <cxxabi.h>
#include "backtrace.h"
#include "jml/compiler/compiler.h"
#include "jml/utils/environment.h"

using namespace std;

namespace ML {

void (*exception_tracer) (void *, const std::type_info *) JML_WEAK_FN = 0;

Env_Option<bool> TRACE_EXCEPTIONS("JML_TRACE_EXCEPTIONS", true);

__thread bool trace_exceptions = false;
__thread bool trace_exceptions_initialized = false;

void set_default_trace_exceptions(bool val)
{
    TRACE_EXCEPTIONS.set(val);
}

bool get_default_trace_exceptions()
{
    return TRACE_EXCEPTIONS;
}

void set_trace_exceptions(bool trace)
{
    //cerr << "set_trace_exceptions to " << trace << " at " << &trace_exceptions
    //     << endl;
    trace_exceptions = trace;
    trace_exceptions_initialized = true;
}

bool get_trace_exceptions()
{
    if (!trace_exceptions_initialized) {
        //cerr << "trace_exceptions initialized to = "
        //     << trace_exceptions << " at " << &trace_exceptions << endl;
        set_trace_exceptions(TRACE_EXCEPTIONS);
        trace_exceptions_initialized = true;
    }

    //cerr << "get_trace_exceptions returned " << trace_exceptions
    //     << " at " << &trace_exceptions << endl;

    return trace_exceptions;
}

static const std::exception *
to_std_exception(void* object, const std::type_info * tinfo)
{
    /* Check if its a class.  If not, we can't see if it's a std::exception.
       The abi::__class_type_info is the base class of all types of type
       info for types that are classes (of which std::exception is one).
    */
    const abi::__class_type_info * ctinfo
        = dynamic_cast<const abi::__class_type_info *>(tinfo);

    if (!ctinfo) return 0;

    /* The thing thrown was an object.  Now, check if it is derived from
    std::exception. */
    const std::type_info * etinfo = &typeid(std::exception);

    /* See if the exception could catch this.  This is the mechanism
    used internally by the compiler in catch {} blocks to see if
    the exception matches the catch type.

    In the case of success, the object will be adjusted to point to
    the start of the std::exception object.
    */
    void * obj_ptr = object;
    bool can_catch = etinfo->__do_catch(tinfo, &obj_ptr, 0);

    if (!can_catch) return 0;

    /* obj_ptr points to a std::exception; extract it and get the
    exception message.
    */
    return (const std::exception *)obj_ptr;
}

/** We install this handler for when an exception is thrown. */

void trace_exception(void * object, const std::type_info * tinfo)
{
    //cerr << "trace_exception: trace_exceptions = " << get_trace_exceptions()
    //     << " at " << &trace_exceptions << endl;

    if (!get_trace_exceptions()) return;

    const std::exception * exc = to_std_exception(object, tinfo);

    // We don't want these exceptions to be printed out.
    if (dynamic_cast<const ML::SilentException *>(exc)) return;

    cerr << endl;
    cerr << "----------------- Exception thrown ------------------------"
         << endl;
    cerr << "type:   " << demangle(tinfo->name()) << endl
         << "pid:    " << getpid() << "; tid: " << (long) syscall(SYS_gettid) << endl;
    if (exc) cerr << "what:   " << exc->what() << endl;

    cerr << "stack:" << endl;
    backtrace(cerr, 3);
    cerr << endl;
}

namespace {
struct Install_Handler {
    Install_Handler()
    {
        //cerr << "installing exception tracer" << endl;
        exception_tracer = trace_exception;
    }
    ~Install_Handler()
    {
        if (exception_tracer == trace_exception)
            exception_tracer = 0;
    }
} install_handler;

} // file scope

} // namespace ML
<|endoftext|>