<commit_before>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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

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

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

#ifndef __RESEMBLA_REGRESSION_HPP__
#define __RESEMBLA_REGRESSION_HPP__

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <fstream>

#include "resembla_interface.hpp"
#include "regression/extractor/feature_extractor.hpp"
#include "reranker.hpp"

namespace resembla {

template<typename ScoreFunction>
class ResemblaRegression: public ResemblaInterface
{
public:
    ResemblaRegression(size_t max_candidate,
            std::shared_ptr<FeatureExtractor> extract, std::shared_ptr<ScoreFunction> score_func,
            std::string corpus_path = "", size_t feature_col = 2):
        max_candidate(max_candidate),
        extract(extract), score_func(score_func), reranker(), extract_corpus(!corpus_path.empty())
    {
        if(extract_corpus){
            loadCorpusFeatures(corpus_path, feature_col);
        }
    }

    void append(const std::string name, const std::shared_ptr<ResemblaInterface> resembla, bool is_primary = true)
    {
        resemblas[name] = resembla;
        if(is_primary && primary_resembla_name.empty()){
            primary_resembla_name = name;
        }
    }

    std::vector<response_type> getSimilarTexts(const string_type& input, size_t max_response, double threshold)
    {
        std::vector<string_type> candidate_texts;
        std::unordered_map<string_type, StringFeatureMap> candidate_features;

        // primary resembla
        for(auto r: resemblas[primary_resembla_name]->getSimilarTexts(input, max_candidate, threshold)){
            candidate_texts.push_back(r.text);
            candidate_features[r.text] = extract_corpus ? corpus_features[r.text] : (*extract)(r.text);
            candidate_features[r.text][primary_resembla_name] = Feature::toText(r.score);
        }

        // other resemblas
        for(auto p: resemblas){
            if(p.first == primary_resembla_name){
                continue;
            }
            for(auto r: p.second->getSimilarTexts(input, candidate_texts)){
                if(candidate_features.find(r.text) == candidate_features.end()){
                    candidate_features[r.text] = extract_corpus ?
                            corpus_features[r.text] : (*extract)(r.text);
                }
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        // prepare data for reranking
        std::vector<WorkData> candidates;
        for(auto c: candidate_features){
            candidates.push_back(std::make_pair(c.first, c.second));
        }
        WorkData input_data = std::make_pair(input, (*extract)(input));

        // rerank by its own metric
        std::vector<ResemblaInterface::response_type> results;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func)){
            if(r.second < threshold || results.size() >= max_response){
                break;
            }
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

    std::vector<response_type> getSimilarTexts(const string_type& query, const std::vector<string_type>& targets)
    {
        return resemblas[primary_resembla_name]->getSimilarTexts(query, targets);
        /*TODO
        std::vector<WorkData> candidates;
        auto original_results = resembla->getSimilarTexts(query, targets);
        for(const auto& r: original_results){
            candidates.push_back(std::make_pair(r.text, (*extract)(r,
                    extract_corpus ? corpus_features[r.text] : decltype((*extract)(r.text))())));
        }

        // rerank by its own metric
        WorkData query_data = std::make_pair(query, (*extract)(query));
        auto reranked = reranker.rerank(query_data, std::begin(candidates), std::end(candidates), *score_func);

        std::vector<ResemblaInterface::response_type> results;
        for(const auto& r: reranked){
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
        */
    }

protected:
    using WorkData = std::pair<string_type, typename FeatureExtractor::return_type>;

    std::unordered_map<std::string, std::shared_ptr<ResemblaInterface>> resemblas;
    std::string primary_resembla_name;
    const size_t max_candidate;

    const std::shared_ptr<FeatureExtractor> extract;
    const std::shared_ptr<ScoreFunction> score_func;
    const Reranker<string_type> reranker;

    const bool extract_corpus;
    std::unordered_map<string_type, typename FeatureExtractor::return_type> corpus_features;

    void loadCorpusFeatures(const std::string& corpus_path, size_t col)
    {
        std::ifstream ifs(corpus_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + corpus_path);
        }
        while(ifs.good()){
            std::string line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }
            auto columns = split(line, '\t');
            if(columns.size() + 1 < col){
                corpus_features[cast_string<string_type>(columns[0])] = (*extract)(columns[0], columns[1]);
            }
        }
    }
};

}
#endif
<commit_msg>implement ResemblaRegression::getSimilarTexts(string, strings)<commit_after>/*
Resembla: Word-based Japanese similar sentence search library
https://github.com/tuem/resembla

Copyright 2017 Takashi Uemura

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

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

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

#ifndef __RESEMBLA_REGRESSION_HPP__
#define __RESEMBLA_REGRESSION_HPP__

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <fstream>

#include "resembla_interface.hpp"
#include "regression/extractor/feature_extractor.hpp"
#include "reranker.hpp"

namespace resembla {

template<typename ScoreFunction>
class ResemblaRegression: public ResemblaInterface
{
public:
    ResemblaRegression(size_t max_candidate,
            std::shared_ptr<FeatureExtractor> extract, std::shared_ptr<ScoreFunction> score_func,
            std::string corpus_path = "", size_t feature_col = 2):
        max_candidate(max_candidate),
        extract(extract), score_func(score_func), reranker(), extract_corpus(!corpus_path.empty())
    {
        if(extract_corpus){
            loadCorpusFeatures(corpus_path, feature_col);
        }
    }

    void append(const std::string name, const std::shared_ptr<ResemblaInterface> resembla, bool is_primary = true)
    {
        resemblas[name] = resembla;
        if(is_primary && primary_resembla_name.empty()){
            primary_resembla_name = name;
        }
    }

    std::vector<response_type> getSimilarTexts(const string_type& input, size_t max_response, double threshold)
    {
        std::vector<string_type> candidate_texts;
        std::unordered_map<string_type, StringFeatureMap> candidate_features;

        // primary resembla
        for(const auto& r: resemblas[primary_resembla_name]->getSimilarTexts(input, max_candidate, threshold)){
            candidate_texts.push_back(r.text);
            candidate_features[r.text] = extract_corpus ? corpus_features[r.text] : (*extract)(r.text);
            candidate_features[r.text][primary_resembla_name] = Feature::toText(r.score);
        }

        // other resemblas
        for(const auto& p: resemblas){
            if(p.first == primary_resembla_name){
                continue;
            }
            for(auto r: p.second->getSimilarTexts(input, candidate_texts)){
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        // prepare data for reranking
        std::vector<WorkData> candidates;
        for(const auto& c: candidate_features){
            candidates.push_back(std::make_pair(c.first, c.second));
        }
        WorkData input_data = std::make_pair(input, (*extract)(input));

        // rerank by its own metric
        std::vector<ResemblaInterface::response_type> results;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func)){
            if(r.second < threshold || results.size() >= max_response){
                break;
            }
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

    std::vector<response_type> getSimilarTexts(const string_type& query, const std::vector<string_type>& targets)
    {
        std::unordered_map<string_type, StringFeatureMap> candidate_features;
        for(const auto& t: targets){
            candidate_features[t] = extract_corpus ? corpus_features[t] : (*extract)(t);
        }

        for(const auto& p: resemblas){
            for(const auto& r: p.second->getSimilarTexts(query, targets)){
                candidate_features[r.text][p.first] = Feature::toText(r.score);
            }
        }

        // prepare data for reranking
        std::vector<WorkData> candidates;
        for(const auto& c: candidate_features){
            candidates.push_back(std::make_pair(c.first, c.second));
        }
        WorkData input_data = std::make_pair(query, (*extract)(query));

        // rerank by its own metric
        std::vector<ResemblaInterface::response_type> results;
        for(const auto& r: reranker.rerank(input_data, std::begin(candidates), std::end(candidates), *score_func)){
            results.push_back({r.first, score_func->name, r.second});
        }
        return results;
    }

protected:
    using WorkData = std::pair<string_type, typename FeatureExtractor::return_type>;

    std::unordered_map<std::string, std::shared_ptr<ResemblaInterface>> resemblas;
    std::string primary_resembla_name;
    const size_t max_candidate;

    const std::shared_ptr<FeatureExtractor> extract;
    const std::shared_ptr<ScoreFunction> score_func;
    const Reranker<string_type> reranker;

    const bool extract_corpus;
    std::unordered_map<string_type, typename FeatureExtractor::return_type> corpus_features;

    void loadCorpusFeatures(const std::string& corpus_path, size_t col)
    {
        std::ifstream ifs(corpus_path);
        if(ifs.fail()){
            throw std::runtime_error("input file is not available: " + corpus_path);
        }
        while(ifs.good()){
            std::string line;
            std::getline(ifs, line);
            if(ifs.eof() || line.length() == 0){
                break;
            }
            auto columns = split(line, '\t');
            if(columns.size() + 1 < col){
                corpus_features[cast_string<string_type>(columns[0])] = (*extract)(columns[0], columns[1]);
            }
        }
    }
};

}
#endif
<|endoftext|>


<commit_before>
#ifndef RESOURCE_IDENTIFIERS_HPP
#define RESOURCE_IDENTIFIERS_HPP

#include <cstdlib>
#include <set>

namespace sf
{
    class Texture;
    class Font;
    class SoundBuffer;
}

namespace Textures
{
    enum ID
    {
    };
}

namespace Fonts
{
    enum ID
    {
    };
}

namespace Music
{
    enum ID
    {
    };
}

namespace Sound
{
    enum ID
    {
    };
}

namespace GameResources
{
    enum LoadingMode
    {
        DEFAULT,
        PACKFILE
    };
}

template<class Resource, class Identifier>
class ResourceHolder;

typedef ResourceHolder<sf::Texture, Textures::ID> TextureHolder;
typedef ResourceHolder<sf::Font, Fonts::ID> FontHolder;
typedef ResourceHolder<sf::SoundBuffer, Sound::ID> SoundBufferHolder;

typedef std::set<Textures::ID> TextureSet;
typedef std::set<Fonts::ID> FontSet;
typedef std::set<Sound::ID> SoundSet;

struct ResourcesSet
{
    ResourcesSet();

    ResourcesSet(TextureSet& tset, FontSet& fset, SoundSet& sset);

    TextureSet* tset;
    FontSet* fset;
    SoundSet* sset;
};
#endif
<commit_msg>Update resourceIdentifiers.hpp<commit_after>
#ifndef RESOURCE_IDENTIFIERS_HPP
#define RESOURCE_IDENTIFIERS_HPP

#include <cstdlib>
#include <set>

namespace sf
{
    class Texture;
    class Font;
    class SoundBuffer;
}

namespace Textures
{
    enum ID
    {
    };
}

namespace Fonts
{
    enum ID
    {
    };
}

/*
  Only use Music identifiers if you intend to use the MusicPlayer, which does not use a ResourcePacker.
  If you intend to use the ResourcePacker, load music files as SoundBuffers via the Sound enum values.
*/
namespace Music
{
    enum ID
    {
    };
}

namespace Sound
{
    enum ID
    {
    };
}

namespace GameResources
{
    enum LoadingMode
    {
        DEFAULT,
        PACKFILE
    };
}

template<class Resource, class Identifier>
class ResourceHolder;

typedef ResourceHolder<sf::Texture, Textures::ID> TextureHolder;
typedef ResourceHolder<sf::Font, Fonts::ID> FontHolder;
typedef ResourceHolder<sf::SoundBuffer, Sound::ID> SoundBufferHolder;

typedef std::set<Textures::ID> TextureSet;
typedef std::set<Fonts::ID> FontSet;
typedef std::set<Sound::ID> SoundSet;

struct ResourcesSet
{
    ResourcesSet();

    ResourcesSet(TextureSet& tset, FontSet& fset, SoundSet& sset);

    TextureSet* tset;
    FontSet* fset;
    SoundSet* sset;
};
#endif
<|endoftext|>


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

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

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

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

#include <errno.h>
#include <jni.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fstream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "tensorflow/lite/tools/benchmark/benchmark_tflite_model.h"

#ifdef __ANDROID__
#include <android/log.h>
#endif

namespace tflite {
namespace benchmark {
namespace {

const char kOutputDir[] = "/sdcard/benchmark_output";

class FirebaseReportingListener : public BenchmarkListener {
 public:
  explicit FirebaseReportingListener(std::string tag, int report_fd)
      : tag_(tag), report_fd_(report_fd) {
    if (report_fd < 0) {
#ifdef __ANDROID__
      __android_log_print(
          ANDROID_LOG_ERROR, "tflite",
          "Report would be streamed only to local log not to Firebase "
          "since the Firebase log file is not opened.");
#else
      fprintf(stderr,
              "Report would be streamed only to local log not to Firebase "
              "since the Firebase log file is not opened.");
#endif
    }
  }

  void OnBenchmarkEnd(const BenchmarkResults& results) override {
    ReportResult(results);
  }

  void ReportFailure(TfLiteStatus status) {
    std::string status_msg =
        status == kTfLiteError
            ? "TFLite error"
            : (status == kTfLiteDelegateError ? "TFLite delegate error"
                                              : "Unknown error code");
    Report(status_msg, std::vector<std::pair<std::string, std::string>>());
  }

 private:
  void Report(
      const std::string& status,
      const std::vector<std::pair<std::string, std::string>>& contents) {
    // The output format of Firebase Game Loop test is json.
    // https://firebase.google.com/docs/test-lab/android/game-loop#output-example
    std::stringstream report;
    report << "{\n"
           << "  \"name\": \"TFLite benchmark\",\n"
           << "  \"benchmark config\": \"" << tag_ << "\",\n"
           << "  \"status\": \"" << status << "\"";
    for (const auto& content : contents) {
      report << ",\n"
             << "  \"" << content.first << "\": \"" << content.second << "\"";
    }
    report << "\n}\n";

    auto report_str = report.str();
    if (report_fd_ >= 0) {
      write(report_fd_, report_str.c_str(), report_str.size());
    }

#ifdef __ANDROID__
    __android_log_print(ANDROID_LOG_ERROR, "tflite", "%s", report_str.c_str());
#else
    fprintf(stderr, "%s", report_str.c_str());
#endif
  }

  void ReportResult(const BenchmarkResults& results) {
    std::vector<std::pair<std::string, std::string>> contents;
    std::stringstream avg_time;
    avg_time << "init: " << results.startup_latency_us() << ", "
             << "warmup: " << results.warmup_time_us().avg() << ", "
             << "inference: " << results.inference_time_us().avg();
    contents.emplace_back("average time in us", avg_time.str());
    std::stringstream overall_mem_usage;
    overall_mem_usage << results.overall_mem_usage();
    contents.emplace_back("overall memory usage", overall_mem_usage.str());

    Report("OK", contents);
  }

  std::string tag_;
  int report_fd_;
};

class CsvExportingListener : public BenchmarkListener {
 public:
  explicit CsvExportingListener(std::string tag) : tag_(tag) {}

  void OnBenchmarkEnd(const BenchmarkResults& results) override {
    if (!CreateOutputDir()) {
#ifdef __ANDROID__
      __android_log_print(ANDROID_LOG_ERROR, "tflite",
                          "Failed to create output directory %s.", kOutputDir);
#else
      fprintf(stderr, "Failed to create output directory %s.", kOutputDir);
#endif
      return;
    }
    WriteBenchmarkResultCsv(results);
  }

 private:
  bool CreateOutputDir() {
    struct stat st;
    if (stat(kOutputDir, &st) != 0) {
      if (mkdir(kOutputDir, 0777) != 0 && errno != EEXIST) {
        return false;
      }
    } else if (!S_ISDIR(st.st_mode)) {
      errno = ENOTDIR;
      return false;
    }
    return true;
  }

  void WriteBenchmarkResultCsv(const BenchmarkResults& results) {
    auto init_us = results.startup_latency_us();
    auto warmup_us = results.warmup_time_us();
    auto inference_us = results.inference_time_us();
    auto init_mem_usage = results.init_mem_usage();
    auto overall_mem_usage = results.overall_mem_usage();

    std::stringstream file_name;
    file_name << kOutputDir << "/benchmark_result_" << tag_;

    std::ofstream file;
    file.open(file_name.str().c_str());
    file << "config_key,model_size,init_time,"
         << "warmup_avg,warmup_min,warmup_max,warmup_stddev,"
         << "inference_avg,inference_min,inference_max,inference_stddev,"
         << "init_max_rss,init_total_alloc,init_in_use_alloc,"
         << "overall_max_rss,overall_total_alloc,overall_in_use_alloc\n";
    file << tag_ << "," << results.model_size_mb() << "," << init_us << ","
         << warmup_us.avg() << "," << warmup_us.min() << "," << warmup_us.max()
         << "," << warmup_us.std_deviation() << "," << inference_us.avg() << ","
         << inference_us.min() << "," << inference_us.max() << ","
         << inference_us.std_deviation() << ","
         << (init_mem_usage.max_rss_kb / 1024.0) << ","
         << (init_mem_usage.total_allocated_bytes / 1024.0 / 1024.0) << ","
         << (init_mem_usage.in_use_allocated_bytes / 1024.0 / 1024.0) << ","
         << (overall_mem_usage.max_rss_kb / 1024.0) << ","
         << (overall_mem_usage.total_allocated_bytes / 1024.0 / 1024.0) << ","
         << (overall_mem_usage.in_use_allocated_bytes / 1024.0 / 1024.0)
         << "\n";
    file.close();
  }

  std::string tag_;
};

std::string GetScenarioConfig(const std::string& library_dir, int scenario,
                              std::vector<std::string>& args) {
  // The number of scenarios should equal to the value specified in
  // AndroidManifest.xml file.
  std::unordered_map<int, std::pair<std::string, std::vector<std::string>>>
      all_scenarios = {
          {1, {"cpu_1thread", {"--num_threads=1"}}},
          {2, {"cpu_2threads", {"--num_threads=2"}}},
          {3, {"cpu_4threads", {"--num_threads=4"}}},
          {4, {"xnnpack_1thread", {"--use_xnnpack=true", "--num_threads=1"}}},
          {5, {"xnnpack_2threads", {"--use_xnnpack=true", "--num_threads=2"}}},
          {6, {"xnnpack_4threads", {"--use_xnnpack=true", "--num_threads=4"}}},
          {7,
           {"gpu_default",
            {"--use_gpu=true", "--gpu_precision_loss_allowed=false"}}},
          {8,
           {"gpu_fp16",
            {"--use_gpu=true", "--gpu_precision_loss_allowed=true"}}},
          {9, {"dsp_hexagon", {"--use_hexagon=true"}}},
          {10, {"nnapi", {"--use_nnapi=true"}}},
      };

  std::string tag;
  args.emplace_back("(BenchmarkModelAndroid)");
  args.emplace_back("--graph=/data/local/tmp/graph");

  auto it = all_scenarios.find(scenario);
  if (it != all_scenarios.end()) {
    const auto& scenario_info = it->second;
    tag = scenario_info.first;
    for (const auto& arg : scenario_info.second) {
      args.push_back(arg);
    }
  }
  if (scenario == 9) {
    std::stringstream hexagon_lib_path;
    hexagon_lib_path << "--hexagon_lib_path=" << library_dir;
    args.push_back(hexagon_lib_path.str());
  }
  return tag;
}

void RunScenario(const std::string& library_dir, int scenario, int report_fd) {
  std::vector<std::string> args;
  std::string tag = GetScenarioConfig(library_dir, scenario, args);
  std::vector<char*> argv;
  argv.reserve(args.size());
  for (auto& arg : args) {
    argv.push_back(const_cast<char*>(arg.data()));
  }

  BenchmarkTfLiteModel benchmark;
  FirebaseReportingListener firebaseReporting(tag, report_fd);
  benchmark.AddListener(&firebaseReporting);
  CsvExportingListener csvExporting(tag);
  benchmark.AddListener(&csvExporting);
  auto status = benchmark.Run(static_cast<int>(argv.size()), argv.data());
  if (status != kTfLiteOk) {
    firebaseReporting.ReportFailure(status);
  }
}

}  // namespace
}  // namespace benchmark
}  // namespace tflite

extern "C" {

JNIEXPORT void JNICALL
Java_org_tensorflow_lite_benchmark_firebase_BenchmarkModel_nativeRun(
    JNIEnv* env, jclass clazz, jstring library_dir, jint scenario,
    jint report_fd) {
  const char* lib_dir = env->GetStringUTFChars(library_dir, nullptr);

  tflite::benchmark::RunScenario(lib_dir, static_cast<int>(scenario),
                                 static_cast<int>(report_fd));

  env->ReleaseStringUTFChars(library_dir, lib_dir);
}

}  // extern "C"
<commit_msg>Add GPU serialization option support in the FTL benchmark tool<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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

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

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

#include <errno.h>
#include <jni.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fstream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "tensorflow/lite/tools/benchmark/benchmark_tflite_model.h"

#ifdef __ANDROID__
#include <android/log.h>
#endif

namespace tflite {
namespace benchmark {
namespace {

const char kOutputDir[] = "/sdcard/benchmark_output";
const char kSerializeDir[] = "/sdcard/serialize";

bool CreateDir(const char* path) {
  struct stat st;
  if (stat(path, &st) != 0) {
    if (mkdir(path, 0777) != 0 && errno != EEXIST) {
      return false;
    }
  } else if (!S_ISDIR(st.st_mode)) {
    errno = ENOTDIR;
    return false;
  }
  return true;
}

class FirebaseReportingListener : public BenchmarkListener {
 public:
  explicit FirebaseReportingListener(std::string tag, int report_fd)
      : tag_(tag), report_fd_(report_fd) {
    if (report_fd < 0) {
#ifdef __ANDROID__
      __android_log_print(
          ANDROID_LOG_ERROR, "tflite",
          "Report would be streamed only to local log not to Firebase "
          "since the Firebase log file is not opened.");
#else
      fprintf(stderr,
              "Report would be streamed only to local log not to Firebase "
              "since the Firebase log file is not opened.");
#endif
    }
  }

  void OnBenchmarkEnd(const BenchmarkResults& results) override {
    ReportResult(results);
  }

  void ReportFailure(TfLiteStatus status) {
    std::string status_msg =
        status == kTfLiteError
            ? "TFLite error"
            : (status == kTfLiteDelegateError ? "TFLite delegate error"
                                              : "Unknown error code");
    Report(status_msg, std::vector<std::pair<std::string, std::string>>());
  }

 private:
  void Report(
      const std::string& status,
      const std::vector<std::pair<std::string, std::string>>& contents) {
    // The output format of Firebase Game Loop test is json.
    // https://firebase.google.com/docs/test-lab/android/game-loop#output-example
    std::stringstream report;
    report << "{\n"
           << "  \"name\": \"TFLite benchmark\",\n"
           << "  \"benchmark config\": \"" << tag_ << "\",\n"
           << "  \"status\": \"" << status << "\"";
    for (const auto& content : contents) {
      report << ",\n"
             << "  \"" << content.first << "\": \"" << content.second << "\"";
    }
    report << "\n}\n";

    auto report_str = report.str();
    if (report_fd_ >= 0) {
      write(report_fd_, report_str.c_str(), report_str.size());
    }

#ifdef __ANDROID__
    __android_log_print(ANDROID_LOG_ERROR, "tflite", "%s", report_str.c_str());
#else
    fprintf(stderr, "%s", report_str.c_str());
#endif
  }

  void ReportResult(const BenchmarkResults& results) {
    std::vector<std::pair<std::string, std::string>> contents;
    std::stringstream avg_time;
    avg_time << "init: " << results.startup_latency_us() << ", "
             << "warmup: " << results.warmup_time_us().avg() << ", "
             << "inference: " << results.inference_time_us().avg();
    contents.emplace_back("average time in us", avg_time.str());
    std::stringstream overall_mem_usage;
    overall_mem_usage << results.overall_mem_usage();
    contents.emplace_back("overall memory usage", overall_mem_usage.str());

    Report("OK", contents);
  }

  std::string tag_;
  int report_fd_;
};

class CsvExportingListener : public BenchmarkListener {
 public:
  explicit CsvExportingListener(std::string tag) : tag_(tag) {}

  void OnBenchmarkEnd(const BenchmarkResults& results) override {
    if (!CreateDir(kOutputDir)) {
#ifdef __ANDROID__
      __android_log_print(ANDROID_LOG_ERROR, "tflite",
                          "Failed to create output directory %s.", kOutputDir);
#else
      fprintf(stderr, "Failed to create output directory %s.", kOutputDir);
#endif
      return;
    }
    WriteBenchmarkResultCsv(results);
  }

 private:
  void WriteBenchmarkResultCsv(const BenchmarkResults& results) {
    auto init_us = results.startup_latency_us();
    auto warmup_us = results.warmup_time_us();
    auto inference_us = results.inference_time_us();
    auto init_mem_usage = results.init_mem_usage();
    auto overall_mem_usage = results.overall_mem_usage();

    std::stringstream file_name;
    file_name << kOutputDir << "/benchmark_result_" << tag_;

    std::ofstream file;
    file.open(file_name.str().c_str());
    file << "config_key,model_size,init_time,"
         << "warmup_avg,warmup_min,warmup_max,warmup_stddev,"
         << "inference_avg,inference_min,inference_max,inference_stddev,"
         << "init_max_rss,init_total_alloc,init_in_use_alloc,"
         << "overall_max_rss,overall_total_alloc,overall_in_use_alloc\n";
    file << tag_ << "," << results.model_size_mb() << "," << init_us << ","
         << warmup_us.avg() << "," << warmup_us.min() << "," << warmup_us.max()
         << "," << warmup_us.std_deviation() << "," << inference_us.avg() << ","
         << inference_us.min() << "," << inference_us.max() << ","
         << inference_us.std_deviation() << ","
         << (init_mem_usage.max_rss_kb / 1024.0) << ","
         << (init_mem_usage.total_allocated_bytes / 1024.0 / 1024.0) << ","
         << (init_mem_usage.in_use_allocated_bytes / 1024.0 / 1024.0) << ","
         << (overall_mem_usage.max_rss_kb / 1024.0) << ","
         << (overall_mem_usage.total_allocated_bytes / 1024.0 / 1024.0) << ","
         << (overall_mem_usage.in_use_allocated_bytes / 1024.0 / 1024.0)
         << "\n";
    file.close();
  }

  std::string tag_;
};

std::string GetScenarioConfig(const std::string& library_dir, int scenario,
                              std::vector<std::string>& args) {
  // The number of scenarios should equal to the value specified in
  // AndroidManifest.xml file.
  std::unordered_map<int, std::pair<std::string, std::vector<std::string>>>
      all_scenarios = {
          {1, {"cpu_1thread", {"--num_threads=1"}}},
          {2, {"cpu_2threads", {"--num_threads=2"}}},
          {3, {"cpu_4threads", {"--num_threads=4"}}},
          {4, {"xnnpack_1thread", {"--use_xnnpack=true", "--num_threads=1"}}},
          {5, {"xnnpack_2threads", {"--use_xnnpack=true", "--num_threads=2"}}},
          {6, {"xnnpack_4threads", {"--use_xnnpack=true", "--num_threads=4"}}},
          {7,
           {"gpu_default",
            {"--use_gpu=true", "--gpu_precision_loss_allowed=false"}}},
          {8,
           {"gpu_fp16",
            {"--use_gpu=true", "--gpu_precision_loss_allowed=true"}}},
          {9, {"dsp_hexagon", {"--use_hexagon=true"}}},
          {10, {"nnapi", {"--use_nnapi=true"}}},
          {11,
           {"gpu_default_with_serialization",
            {"--use_gpu=true", "--gpu_precision_loss_allowed=false",
             "--delegate_serialize_token=dummy_token"}}},
          {12,
           {"gpu_fp16_with_serialization",
            {"--use_gpu=true", "--gpu_precision_loss_allowed=true",
             "--delegate_serialize_token=dummy_token"}}},
      };

  std::string tag;
  args.emplace_back("(BenchmarkModelAndroid)");
  args.emplace_back("--graph=/data/local/tmp/graph");

  auto it = all_scenarios.find(scenario);
  if (it != all_scenarios.end()) {
    const auto& scenario_info = it->second;
    tag = scenario_info.first;
    for (const auto& arg : scenario_info.second) {
      args.push_back(arg);
    }
  }
  if (scenario == 9) {
    std::stringstream hexagon_lib_path;
    hexagon_lib_path << "--hexagon_lib_path=" << library_dir;
    args.push_back(hexagon_lib_path.str());
  }

  if (scenario == 11 || scenario == 12) {
    if (CreateDir(kSerializeDir)) {
      std::stringstream serialize_dir;
      serialize_dir << "--delegate_serialize_dir=" << kSerializeDir;
      args.push_back(serialize_dir.str());
    } else {
#ifdef __ANDROID__
      __android_log_print(ANDROID_LOG_ERROR, "tflite",
                          "Failed to create serialize directory %s.",
                          kSerializeDir);
#else
      fprintf(stderr, "Failed to create serialize directory %s.",
              kSerializeDir);
#endif
    }
  }
  return tag;
}

void RunScenario(const std::string& library_dir, int scenario, int report_fd) {
  std::vector<std::string> args;
  std::string tag = GetScenarioConfig(library_dir, scenario, args);
  std::vector<char*> argv;
  argv.reserve(args.size());
  for (auto& arg : args) {
    argv.push_back(const_cast<char*>(arg.data()));
  }

  BenchmarkTfLiteModel benchmark;
  FirebaseReportingListener firebaseReporting(tag, report_fd);
  benchmark.AddListener(&firebaseReporting);
  CsvExportingListener csvExporting(tag);
  benchmark.AddListener(&csvExporting);
  auto status = benchmark.Run(static_cast<int>(argv.size()), argv.data());
  if (status != kTfLiteOk) {
    firebaseReporting.ReportFailure(status);
  }
}

}  // namespace
}  // namespace benchmark
}  // namespace tflite

extern "C" {

JNIEXPORT void JNICALL
Java_org_tensorflow_lite_benchmark_firebase_BenchmarkModel_nativeRun(
    JNIEnv* env, jclass clazz, jstring library_dir, jint scenario,
    jint report_fd) {
  const char* lib_dir = env->GetStringUTFChars(library_dir, nullptr);

  tflite::benchmark::RunScenario(lib_dir, static_cast<int>(scenario),
                                 static_cast<int>(report_fd));

  env->ReleaseStringUTFChars(library_dir, lib_dir);
}

}  // extern "C"
<|endoftext|>


<commit_before><commit_msg>Fixed compile error.<commit_after><|endoftext|>


<commit_before><commit_msg>With an upcoming ICU 4.2 upgrade, the way 'search' works has changed and FiP doesn't make a hit for  a stand-alone dependent vowel sign of Indic scripts, which is OK according to a native Malayalam speaker.<commit_after><|endoftext|>


<commit_before>#include "journal.h"
#include "qif.h"
#include "datetime.h"
#include "error.h"
#include "util.h"

#include <cstring>
#include <memory>

namespace ledger {

#define MAX_LINE 1024

static char         line[MAX_LINE + 1];
static std::string  path;
static unsigned int src_idx;
static unsigned int linenum;

static inline char * get_line(std::istream& in) {
  in.getline(line, MAX_LINE);
  int len = std::strlen(line);
  if (line[len - 1] == '\r')
    line[len - 1] = '\0';
  linenum++;
  return line;
}

bool qif_parser_t::test(std::istream& in) const
{
  char magic[sizeof(unsigned int) + 1];
  in.read(magic, sizeof(unsigned int));
  magic[sizeof(unsigned int)] = '\0';
  in.seekg(0, std::ios::beg);

  return (std::strcmp(magic, "!Typ") == 0 ||
	  std::strcmp(magic, "\n!Ty") == 0 ||
	  std::strcmp(magic, "\r\n!T") == 0);
}

unsigned int qif_parser_t::parse(std::istream&	     in,
				 journal_t *	     journal,
				 account_t *	     master,
				 const std::string * original_file)
{
  std::auto_ptr<entry_t>  entry;
  std::auto_ptr<amount_t> amount;

  transaction_t * xact;
  unsigned int    count		= 0;
  account_t *     misc		= NULL;
  commodity_t *   def_commodity = NULL;
  bool            saw_splits    = false;
  bool            saw_category  = false;
  transaction_t * total         = NULL;

  entry.reset(new entry_t);
  xact = new transaction_t(master);
  entry->add_transaction(xact);

  path	  = journal->sources.back();
  src_idx = journal->sources.size() - 1;
  linenum = 1;

  istream_pos_type beg_pos  = 0;
  unsigned long    beg_line = 0;

#define SET_BEG_POS_AND_LINE()			\
  if (! beg_line) {				\
    beg_pos  = in.tellg();			\
    beg_line = linenum;				\
  }

  while (in.good() && ! in.eof()) {
    char c;
    in.get(c);
    switch (c) {
    case ' ':
    case '\t':
      if (peek_next_nonws(in) != '\n') {
	get_line(in);
	throw parse_error(path, linenum, "Line begins with whitespace");
      }
      // fall through...

    case '\n':
      linenum++;
    case '\r':                  // skip blank lines
      break;

    case '!':
      get_line(in);

      if (std::strcmp(line, "Type:Invst") == 0 ||
	  std::strcmp(line, "Account") == 0 ||
	  std::strcmp(line, "Type:Cat") == 0 ||
	  std::strcmp(line, "Type:Class") == 0 ||
	  std::strcmp(line, "Type:Memorized") == 0)
	throw parse_error(path, linenum,
			  std::string("QIF files of type ") + line +
			  " are not supported.");
      break;

    case 'D':
      SET_BEG_POS_AND_LINE();
      in >> line;
      if (! parse_date(line, &entry->date))
	throw parse_error(path, linenum, "Failed to parse date");
      break;

    case 'T':
    case '$': {
      SET_BEG_POS_AND_LINE();
      in >> line;
      xact->amount.parse(line);

      unsigned long  flags = xact->amount.commodity().flags;
      unsigned short prec  = xact->amount.commodity().precision;

      if (! def_commodity)
	def_commodity = commodity_t::find_commodity("$", true);
      xact->amount.set_commodity(*def_commodity);

      def_commodity->flags |= flags;
      if (prec > def_commodity->precision)
	def_commodity->precision = prec;

      if (c == '$') {
	saw_splits = true;
	xact->amount.negate();
      } else {
	total = xact;
      }
      break;
    }

    case 'C':
      SET_BEG_POS_AND_LINE();
      c = in.peek();
      if (c == '*' || c == 'X') {
	in.get(c);
	entry->state = entry_t::CLEARED;
      }
      break;

    case 'N':
      SET_BEG_POS_AND_LINE();
      if (std::isdigit(in.peek())) {
	in >> line;
	entry->code = line;
      } else {
	in >> line;
      }
      break;

    case 'P':
    case 'M':
    case 'L':
    case 'S':
    case 'E': {
      SET_BEG_POS_AND_LINE();
      get_line(in);

      switch (c) {
      case 'P':
	entry->payee = line;
	break;

      case 'S':
	xact = new transaction_t(NULL);
	entry->add_transaction(xact);
	// fall through...
      case 'L': {
	int len = std::strlen(line);
	if (line[len - 1] == ']')
	  line[len - 1] = '\0';
	xact->account = journal->find_account(line[0] == '[' ?
					      line + 1 : line);
	if (c == 'L')
	  saw_category = true;
	break;
      }

      case 'M':
      case 'E':
	xact->note = line;
	break;
      }
      break;
    }

    case 'A':
      SET_BEG_POS_AND_LINE();
      // jww (2004-08-19): these are ignored right now
      get_line(in);
      break;

    case '^': {
      account_t * other;
      if (xact->account == master) {
	if (! misc)
	  misc = journal->find_account("Miscellaneous");
	other = misc;
      } else {
	other = master;
      }

      if (total && saw_category) {
	if (! saw_splits)
	  total->amount.negate(); // negate, to show correct flow
	else
	  total->account = other;
      }

      if (! saw_splits) {
	transaction_t * nxact = new transaction_t(other);
	// The amount doesn't need to be set because the code below
	// will balance this transaction against the other.
	entry->add_transaction(nxact);
      }

      if (journal->add_entry(entry.get())) {
	entry->src_idx  = src_idx;
	entry->beg_pos  = beg_pos;
	entry->beg_line = beg_line;
	entry->end_pos  = in.tellg();
	entry->end_line = linenum;
	entry.release();
	count++;
      }

      entry.reset(new entry_t);
      xact = new transaction_t(master);
      entry->add_transaction(xact);

      beg_line = 0;		// reset for next entry
      break;
    }

    default:
      get_line(in);
      break;
    }
  }

  return count;
}

} // namespace ledger

#ifdef USE_BOOST_PYTHON

#include <boost/python.hpp>

using namespace boost::python;
using namespace ledger;

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(qif_parse_overloads,
				       qif_parser_t::parse, 2, 4)

void export_qif() {
  class_< qif_parser_t, bases<parser_t> > ("QifParser")
    .def("test", &qif_parser_t::test)
    .def("parse", &qif_parser_t::parse, qif_parse_overloads())
    ;
}

#endif // USE_BOOST_PYTHON
<commit_msg>*** empty log message ***<commit_after>#include "journal.h"
#include "qif.h"
#include "datetime.h"
#include "error.h"
#include "util.h"

#include <cstring>
#include <memory>

namespace ledger {

#define MAX_LINE 1024

static char         line[MAX_LINE + 1];
static std::string  path;
static unsigned int src_idx;
static unsigned int linenum;

static inline char * get_line(std::istream& in) {
  in.getline(line, MAX_LINE);
  int len = std::strlen(line);
  if (line[len - 1] == '\r')
    line[len - 1] = '\0';
  linenum++;
  return line;
}

bool qif_parser_t::test(std::istream& in) const
{
  char magic[sizeof(unsigned int) + 1];
  in.read(magic, sizeof(unsigned int));
  magic[sizeof(unsigned int)] = '\0';
  in.seekg(0, std::ios::beg);

  return (std::strcmp(magic, "!Typ") == 0 ||
	  std::strcmp(magic, "\n!Ty") == 0 ||
	  std::strcmp(magic, "\r\n!T") == 0);
}

unsigned int qif_parser_t::parse(std::istream&	     in,
				 journal_t *	     journal,
				 account_t *	     master,
				 const std::string * original_file)
{
  std::auto_ptr<entry_t>  entry;
  std::auto_ptr<amount_t> amount;

  transaction_t * xact;
  unsigned int    count		= 0;
  account_t *     misc		= NULL;
  commodity_t *   def_commodity = NULL;
  bool            saw_splits    = false;
  bool            saw_category  = false;
  transaction_t * total         = NULL;

  entry.reset(new entry_t);
  xact = new transaction_t(master);
  entry->add_transaction(xact);

  path	  = journal->sources.back();
  src_idx = journal->sources.size() - 1;
  linenum = 1;

  istream_pos_type beg_pos  = 0;
  unsigned long    beg_line = 0;

#define SET_BEG_POS_AND_LINE()			\
  if (! beg_line) {				\
    beg_pos  = in.tellg();			\
    beg_line = linenum;				\
  }

  while (in.good() && ! in.eof()) {
    char c;
    in.get(c);
    switch (c) {
    case ' ':
    case '\t':
      if (peek_next_nonws(in) != '\n') {
	get_line(in);
	throw parse_error(path, linenum, "Line begins with whitespace");
      }
      // fall through...

    case '\n':
      linenum++;
    case '\r':                  // skip blank lines
      break;

    case '!':
      get_line(in);

      if (std::strcmp(line, "Type:Invst") == 0 ||
	  std::strcmp(line, "Account") == 0 ||
	  std::strcmp(line, "Type:Cat") == 0 ||
	  std::strcmp(line, "Type:Class") == 0 ||
	  std::strcmp(line, "Type:Memorized") == 0)
	throw parse_error(path, linenum,
			  std::string("QIF files of type ") + line +
			  " are not supported.");
      break;

    case 'D':
      SET_BEG_POS_AND_LINE();
      in >> line;
      if (! parse_date(line, &entry->date))
	throw parse_error(path, linenum, "Failed to parse date");
      break;

    case 'T':
    case '$': {
      SET_BEG_POS_AND_LINE();
      in >> line;
      xact->amount.parse(line);

      unsigned long  flags = xact->amount.commodity().flags;
      unsigned short prec  = xact->amount.commodity().precision;

      if (! def_commodity)
	def_commodity = commodity_t::find_commodity("$", true);
      xact->amount.set_commodity(*def_commodity);

      def_commodity->flags |= flags;
      if (prec > def_commodity->precision)
	def_commodity->precision = prec;

      if (c == '$') {
	saw_splits = true;
	xact->amount.negate();
      } else {
	total = xact;
      }
      break;
    }

    case 'C':
      SET_BEG_POS_AND_LINE();
      c = in.peek();
      if (c == '*' || c == 'X') {
	in.get(c);
	entry->state = entry_t::CLEARED;
      }
      break;

    case 'N':
      SET_BEG_POS_AND_LINE();
      if (std::isdigit(in.peek())) {
	in >> line;
	entry->code = line;
      } else {
	in >> line;
      }
      break;

    case 'P':
    case 'M':
    case 'L':
    case 'S':
    case 'E': {
      SET_BEG_POS_AND_LINE();
      get_line(in);

      switch (c) {
      case 'P':
	entry->payee = line;
	break;

      case 'S':
	xact = new transaction_t(NULL);
	entry->add_transaction(xact);
	// fall through...
      case 'L': {
	int len = std::strlen(line);
	if (line[len - 1] == ']')
	  line[len - 1] = '\0';
	xact->account = journal->find_account(line[0] == '[' ?
					      line + 1 : line);
	if (c == 'L')
	  saw_category = true;
	break;
      }

      case 'M':
      case 'E':
	xact->note = line;
	break;
      }
      break;
    }

    case 'A':
      SET_BEG_POS_AND_LINE();
      // jww (2004-08-19): these are ignored right now
      get_line(in);
      break;

    case '^': {
      account_t * other;
      if (xact->account == master) {
	if (! misc)
	  misc = journal->find_account("Miscellaneous");
	other = misc;
      } else {
	other = master;
      }

      if (total && saw_category) {
	if (! saw_splits)
	  total->amount.negate(); // negate, to show correct flow
	else
	  total->account = other;
      }

      if (! saw_splits) {
	transaction_t * nxact = new transaction_t(other);
	// The amount doesn't need to be set because the code below
	// will balance this transaction against the other.
	entry->add_transaction(nxact);
      }

      if (journal->add_entry(entry.get())) {
	entry->src_idx  = src_idx;
	entry->beg_pos  = beg_pos;
	entry->beg_line = beg_line;
	entry->end_pos  = in.tellg();
	entry->end_line = linenum;
	entry.release();
	count++;
      }

      // reset things for the next entry
      entry.reset(new entry_t);
      xact = new transaction_t(master);
      entry->add_transaction(xact);

      saw_splits   = false;
      saw_category = false;
      total        = NULL;
      beg_line	   = 0;
      break;
    }

    default:
      get_line(in);
      break;
    }
  }

  return count;
}

} // namespace ledger

#ifdef USE_BOOST_PYTHON

#include <boost/python.hpp>

using namespace boost::python;
using namespace ledger;

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(qif_parse_overloads,
				       qif_parser_t::parse, 2, 4)

void export_qif() {
  class_< qif_parser_t, bases<parser_t> > ("QifParser")
    .def("test", &qif_parser_t::test)
    .def("parse", &qif_parser_t::parse, qif_parse_overloads())
    ;
}

#endif // USE_BOOST_PYTHON
<|endoftext|>


<commit_before>// Time:  O(nlogp), p is total pages.
// Space: O(1)

class Solution {
public:
    /**
     * @param pages: a vector of integers
     * @param k: an integer
     * @return: an integer
     */
    int copyBooks(vector<int> &pages, int k) {
        if (k >= pages.size()) {
            return *max_element(pages.cbegin(), pages.cend());
        }

        int sum = 0;
        for (const auto& page : pages) {
            sum += page;
        }
        int average = sum / k;   // Lower bound.
        return binarySearch(pages, k, average, sum);
    }

    int binarySearch(const vector<int> &pages,
                      const int k, int left, int right) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (valid(pages, k, mid)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

    // Check whether everyone copying at most x pages works or not.
    bool valid(const vector<int> &pages, const int k, const int x) {
        int sum = 0;
        int people = 0;
        for (int i = 0; i < pages.size() && people < k; ++i) {
            if (sum + pages[i] > x) {
                sum = 0;
                ++people;
            }
            sum += pages[i];
        }
        return  people < k && sum <= x;
    }
};
<commit_msg>Update copy-books.cpp<commit_after>// Time:  O(nlogp), p is total pages.
// Space: O(1)

class Solution {
public:
    /**
     * @param pages: a vector of integers
     * @param k: an integer
     * @return: an integer
     */
    int copyBooks(vector<int> &pages, int k) {
        if (k >= pages.size()) {
            return *max_element(pages.cbegin(), pages.cend());
        }

        int sum = 0;
        for (const auto& page : pages) {
            sum += page;
        }
        int average = sum / k;   // Lower bound.
        return binarySearch(pages, k, average, sum);
    }

    int binarySearch(const vector<int> &pages,
                     const int k, int left, int right) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (valid(pages, k, mid)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

    // Check whether everyone copying at most x pages works or not.
    bool valid(const vector<int> &pages, const int k, const int x) {
        int sum = 0;
        int people = 0;
        for (int i = 0; i < pages.size() && people < k; ++i) {
            if (sum + pages[i] > x) {
                sum = 0;
                ++people;
            }
            sum += pages[i];
        }
        return  people < k && sum <= x;
    }
};
<|endoftext|>


<commit_before>class Solution {
    public:
        void sortColors(int A[], int n) {
            int i0 = 0;
            int i2 = n-1;
            for(int i = 0; i < n && i0 <= i2 && i <= i2; i++) {
                while(A[i] != 1 && i0 <= i2 && i >= i0 && i<=i2) {
                    if(A[i] == 0) {
                        swap(A[i], A[i0++]);
                    }
                    else if(A[i] == 2) {
                        swap(A[i], A[i2--]);
                    }
                }
            }
        }
};
<commit_msg>update sortColors.cpp<commit_after>// Time Complexity: O(n)
// Space Complexity: O(1)
class Solution {
    public:
        void sortColors(int A[], int n) {
            int i0 = 0;
            int i2 = n-1;
            for(int i = 0; i < n && i0 <= i2 && i <= i2; i++) {
                while(A[i] != 1 && i0 <= i2 && i >= i0 && i<=i2) {
                    if(A[i] == 0) {
                        swap(A[i], A[i0++]);
                    }
                    else if(A[i] == 2) {
                        swap(A[i], A[i2--]);
                    }
                }
            }
        }
};
<|endoftext|>


<commit_before>/*
 * Promise2
 *
 * Copyright (c) 2015-2016 "0of" Magnus
 * Licensed under the MIT license.
 * https://github.com/0of/Promise2/blob/master/LICENSE
 */

#include <atomic>
#include <vector>

#include "entry.h"
#include "Promise.h"

class CurrentContext : public Promise2::ThreadContext {
public:
  static ThreadContext *New() {
    return new CurrentContext;
  }

public:
  virtual void scheduleToRun(std::function<void()>&& task) override {
    task();
  }
};

namespace RecursionAPIsBase {

 template<typename T>
  void init(T& spec) {
    using context = CurrentContext;

    spec
    /* ==> */
    .it("should run three times", [](const LTest::SharedCaseEndNotifier& notifier){
      std::vector<std::int32_t> values = {1, 2, 3};
      auto len = values.size();

      auto counter = std::make_shared<std::int32_t>(0);

        Promise2::RecursionPromise<std::int32_t>::Iterate(values.begin(), values.end(), new context()).
        then([=](std::int32_t ) { ++*counter; },
             [=](std::exception_ptr) { notifier->fail(std::make_exception_ptr(AssertionFailed())); return Promise2::RecursionPromise<void>(); },
             new context()).
        final([=]() { if (len == *counter) { notifier->done(); }
                      else notifier->fail(std::make_exception_ptr(AssertionFailed())); },
              [=](std::exception_ptr) { notifier->fail(std::make_exception_ptr(AssertionFailed())); return Promise2::Promise<void>(); },
              new context());
    });
  }

} // RecursionAPIsBase

TEST_ENTRY(CONTAINER_TYPE,
  SPEC_TFN(RecursionAPIsBase::init));
<commit_msg>UserIterator test cases<commit_after>/*
 * Promise2
 *
 * Copyright (c) 2015-2016 "0of" Magnus
 * Licensed under the MIT license.
 * https://github.com/0of/Promise2/blob/master/LICENSE
 */

#include <atomic>
#include <vector>

#include "entry.h"
#include "Promise.h"

class CurrentContext : public Promise2::ThreadContext {
public:
  static ThreadContext *New() {
    return new CurrentContext;
  }

public:
  virtual void scheduleToRun(std::function<void()>&& task) override {
    task();
  }
};

namespace RecursionAPIsBase {

  // IntputIterator
  class UserIterator {
  public:
    static constexpr const std::int32_t max = 3;

  private:
    std::int32_t _index;

  public:
    UserIterator(bool end)
      : _index { end? 3 : 0 }
    {}

  public:
    bool operator == (const UserIterator& i) { return i._index == _index; }
    // must
    bool operator != (const UserIterator& i) { return i._index != _index; }

    // must
    UserIterator& operator++ () {
      ++_index;
      return *this;
    }

    // must
    std::int32_t operator *() const {
      return _index;
    }
  };

  constexpr const std::int32_t UserIterator::max;

  template<typename T>
  void init(T& spec) {
    using context = CurrentContext;

    spec
    /* ==> */
    .it("should run three times", [](const LTest::SharedCaseEndNotifier& notifier){
      std::vector<std::int32_t> values = {1, 2, 3};
      auto len = values.size();

      auto counter = std::make_shared<std::int32_t>(0);

      Promise2::RecursionPromise<std::int32_t>::Iterate(values.begin(), values.end(), new context()).
      then([=](std::int32_t ) { ++*counter; },
           [=](std::exception_ptr) { notifier->fail(std::make_exception_ptr(AssertionFailed())); return Promise2::RecursionPromise<void>(); },
           new context()).
      final([=]() { if (len == *counter) { notifier->done(); }
                    else notifier->fail(std::make_exception_ptr(AssertionFailed())); },
            [=](std::exception_ptr) { notifier->fail(std::make_exception_ptr(AssertionFailed())); return Promise2::Promise<void>(); },
            new context());
    })
    /* ==> */
    .it("should run three times with customized iterator", [](const LTest::SharedCaseEndNotifier& notifier){
      auto counter = std::make_shared<std::int32_t>(0);

      Promise2::RecursionPromise<std::int32_t>::Iterate(UserIterator(false), UserIterator(true), new context()).
      then([=](std::int32_t ) { ++*counter; },
           [=](std::exception_ptr) { notifier->fail(std::make_exception_ptr(AssertionFailed())); return Promise2::RecursionPromise<void>(); },
           new context()).
      final([=]() { if (UserIterator::max == *counter) { notifier->done(); }
                    else notifier->fail(std::make_exception_ptr(AssertionFailed())); },
            [=](std::exception_ptr) { notifier->fail(std::make_exception_ptr(AssertionFailed())); return Promise2::Promise<void>(); },
            new context());
    });
  }

} // RecursionAPIsBase

TEST_ENTRY(CONTAINER_TYPE,
  SPEC_TFN(RecursionAPIsBase::init));
<|endoftext|>


<commit_before>#include <QtGui/QGuiApplication>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/QQuickWindow>
#include <QtCore/QUrl>
#include <QUrlQuery>
#include <QDateTime>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QMutex>
#include <QNetworkAccessManager>
#include <QTimer>

#include "chat/ConversationWindow.hpp"
#include "chat/ContactsWindow.hpp"
#include "chat/net/NetworkRequest.hpp"

using chat::ConversationWindow;
using chat::net::NetworkRequest;

ConversationWindow::ConversationWindow(QString conversationID, QObject *parent): QObject(parent), _conversationID(conversationID) {
    QQmlEngine *engine = new QQmlEngine(this);
    QQmlComponent *component = new QQmlComponent(engine, this);
    component->loadUrl(QUrl("qrc:/assets/ChatWindow.qml"));

    QObject *root;
    if (component->isReady()) {
        root = component->create();
        root->setProperty("title", "Conversation ID: " + conversationID);
    }
    else {
        qWarning() << component->errorString();
        return;
    }

    QObject *button = root->findChild<QObject*>("sendButton");
    if (button) {
        connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));
    }
    _chatText = root->findChild<QObject*>("chatText");
    _input = root->findChild<QObject*>("input");

    connect(_input, SIGNAL(accepted()), this, SLOT(onClicked()));

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
    timer->start(1000);

    connect(root, SIGNAL(visibleChanged(bool)), this, SLOT(deleteLater()));
}

void ConversationWindow::onTimeOut() {
    QUrl url("http://chatServer:8080/chatServer/getMessages");
    QUrlQuery query;
    query.addQueryItem("after", "1");
    url.setQuery(query);

    NetworkRequest *request = new NetworkRequest(url);
    request->get();

    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), this, SLOT(onMessages(chat::net::NetworkRequest*)));
    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), request, SLOT(deleteLater()));
}

void ConversationWindow::onMessages(NetworkRequest *reply) {

    QByteArray contents = reply->data();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(contents);
    QVariantList messages = jsonDoc.object()["msg"].toObject()["messages"].toArray().toVariantList();

    QString string;
    foreach (QVariant i, messages) {
        QVariantMap map = i.toMap();
        string += map["sender"].toString() + ": " + map["message"].toString() + "\n";
    }

    _chatText->setProperty("text", string);
}

void ConversationWindow::onClicked() {

    QUrl url("http://chatServer:8080/chatServer/postMessage");
    QUrlQuery query;
    query.addQueryItem("sender", chat::ContactsWindow::userName);
    query.addQueryItem("timeSent", QString::number(QDateTime::currentDateTime().toTime_t()));
    query.addQueryItem("conversation", _conversationID);
    url.setQuery(query);

    NetworkRequest *request = new NetworkRequest(url);
    request->post(_input->property("text").toByteArray());

    _input->setProperty("text", "");

    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), this, SLOT(onPostFinished(chat::net::NetworkRequest*)));
    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), request, SLOT(deleteLater()));
}

void ConversationWindow::onPostFinished(NetworkRequest *reply) {
    qDebug() << reply->data();
}
<commit_msg>added conversation to conversation request<commit_after>#include <QtGui/QGuiApplication>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/QQuickWindow>
#include <QtCore/QUrl>
#include <QUrlQuery>
#include <QDateTime>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QMutex>
#include <QNetworkAccessManager>
#include <QTimer>

#include "chat/ConversationWindow.hpp"
#include "chat/ContactsWindow.hpp"
#include "chat/net/NetworkRequest.hpp"

using chat::ConversationWindow;
using chat::net::NetworkRequest;

ConversationWindow::ConversationWindow(QString conversationID, QObject *parent): QObject(parent), _conversationID(conversationID) {
    QQmlEngine *engine = new QQmlEngine(this);
    QQmlComponent *component = new QQmlComponent(engine, this);
    component->loadUrl(QUrl("qrc:/assets/ChatWindow.qml"));

    QObject *root;
    if (component->isReady()) {
        root = component->create();
        root->setProperty("title", "Conversation ID: " + conversationID);
    }
    else {
        qWarning() << component->errorString();
        return;
    }

    QObject *button = root->findChild<QObject*>("sendButton");
    if (button) {
        connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));
    }
    _chatText = root->findChild<QObject*>("chatText");
    _input = root->findChild<QObject*>("input");

    connect(_input, SIGNAL(accepted()), this, SLOT(onClicked()));

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
    timer->start(1000);

    connect(root, SIGNAL(visibleChanged(bool)), this, SLOT(deleteLater()));
}

void ConversationWindow::onTimeOut() {
    QUrl url("http://chatServer:8080/chatServer/getMessages");
    QUrlQuery query;
    query.addQueryItem("after", "1");
    query.addQueryItem("conversation", _conversationID);
    url.setQuery(query);

    NetworkRequest *request = new NetworkRequest(url);
    request->get();

    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), this, SLOT(onMessages(chat::net::NetworkRequest*)));
    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), request, SLOT(deleteLater()));
}

void ConversationWindow::onMessages(NetworkRequest *reply) {

    QByteArray contents = reply->data();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(contents);
    QVariantList messages = jsonDoc.object()["msg"].toObject()["messages"].toArray().toVariantList();

    QString string;
    foreach (QVariant i, messages) {
        QVariantMap map = i.toMap();
        string += map["sender"].toString() + ": " + map["message"].toString() + "\n";
    }

    _chatText->setProperty("text", string);
}

void ConversationWindow::onClicked() {

    QUrl url("http://chatServer:8080/chatServer/postMessage");
    QUrlQuery query;
    query.addQueryItem("sender", chat::ContactsWindow::userName);
    query.addQueryItem("timeSent", QString::number(QDateTime::currentDateTime().toTime_t()));
    query.addQueryItem("conversation", _conversationID);
    url.setQuery(query);

    NetworkRequest *request = new NetworkRequest(url);
    request->post(_input->property("text").toByteArray());

    _input->setProperty("text", "");

    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), this, SLOT(onPostFinished(chat::net::NetworkRequest*)));
    connect(request, SIGNAL(finished(chat::net::NetworkRequest*)), request, SLOT(deleteLater()));
}

void ConversationWindow::onPostFinished(NetworkRequest *reply) {
    qDebug() << reply->data();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
#include "GrTexture.h"

// number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8;

// except FS outputs where we expect 2 at most.
static const int kMaxFSOutputs = 2;

// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;

typedef GrGLUniformManager::UniformHandle UniformHandle;
///////////////////////////////////////////////////////////////////////////////

static SkString build_sampler_string(GrGLShaderBuilder::SamplerMode samplerMode) {
    SkString sampler("texture2D");
    switch (samplerMode) {
      case GrGLShaderBuilder::kDefault_SamplerMode:
          break;
      case GrGLShaderBuilder::kProj_SamplerMode:
          sampler.append("Proj");
          break;
      case GrGLShaderBuilder::kExplicitDivide_SamplerMode:
          GrAssert(false);  // Not Implemented
          break;
    }

    return sampler;
}

static bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps,
                                                  const GrTextureAccess& access) {
    return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() &&
        access.referencesAlpha();
}

static SkString build_swizzle_string(const GrTextureAccess& textureAccess,
                                     const GrGLCaps& caps) {
    const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle();
    if (0 == swizzle[0]) {
        return SkString("");
    }

    SkString swizzleOut(".");
    bool alphaIsRed = texture_requires_alpha_to_red_swizzle(caps, textureAccess);
    for (int offset = 0; offset < 4 && swizzle[offset]; ++offset) {
        if (alphaIsRed && 'a' == swizzle[offset]) {
            swizzleOut.appendf("r");
        } else {
            swizzleOut.appendf("%c", swizzle[offset]);
        }
    }

    return swizzleOut;
}

///////////////////////////////////////////////////////////////////////////////

// Architectural assumption: always 2-d input coords.
// Likely to become non-constant and non-static, perhaps even
// varying by stage, if we use 1D textures for gradients!
//const int GrGLShaderBuilder::fCoordDims = 2;

GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx, GrGLUniformManager& uniformManager)
    : fUniforms(kVarsPerBlock)
    , fVSAttrs(kVarsPerBlock)
    , fVSOutputs(kVarsPerBlock)
    , fGSInputs(kVarsPerBlock)
    , fGSOutputs(kVarsPerBlock)
    , fFSInputs(kVarsPerBlock)
    , fFSOutputs(kMaxFSOutputs)
    , fUsesGS(false)
    , fVaryingDims(0)
    , fComplexCoord(false)
    , fContext(ctx)
    , fUniformManager(uniformManager)
    , fCurrentStage(kNonStageIdx) {
}

void GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
   static const uint32_t kMulByAlphaMask =
        (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
         GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);

    fSwizzle = "";
    if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) {
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
        fSwizzle = ".bgra";
    } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
        GrAssert(!(configFlags & kMulByAlphaMask));
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
        fSwizzle = ".aaaa";
    } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
        GrAssert(!(configFlags & kMulByAlphaMask));
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
        fSwizzle = ".rrrr";
    }
}

void GrGLShaderBuilder::computeModulate(const char* fsInColor) {
    if (NULL != fsInColor) {
        fModulate.printf(" * %s", fsInColor);
    } else {
        fModulate.reset();
    }
}

void GrGLShaderBuilder::setupTextureAccess(SamplerMode samplerMode,
                                           int stageNum) {
    SkString retval;

    fTexFunc = "texture2D";
    switch (samplerMode) {
        case kDefault_SamplerMode:
            GrAssert(fVaryingDims == fCoordDims);
            // Do nothing
            break;
        case kProj_SamplerMode:
            fTexFunc.append("Proj");
            break;
        case kExplicitDivide_SamplerMode:
            retval = "inCoord";
            retval.appendS32(stageNum);
            fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
                GrGLShaderVar::TypeString
                    (GrSLFloatVectorType(fCoordDims)),
                retval.c_str(),
                fSampleCoords.c_str(),
                GrGLSLVectorNonhomogCoords(fVaryingDims),
                fSampleCoords.c_str(),
                GrGLSLVectorHomogCoord(fVaryingDims));
            fSampleCoords = retval;
            break;
    }
    fComplexCoord = false;
}

void GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
                                          const char* coordName) {
    if (NULL == coordName) {
        coordName = fSampleCoords.c_str();
    }
    fFSCode.appendf("%s(%s, %s)", fTexFunc.c_str(), samplerName, coordName);
}

void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
                                         const char* samplerName) {
    fFSCode.appendf("\t%s = ", outColor);
    this->emitTextureLookup(samplerName);
    fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
}

void GrGLShaderBuilder::emitCustomTextureLookup(SamplerMode samplerMode,
                                                const GrTextureAccess& textureAccess,
                                                const char* samplerName,
                                                const char* coordName) {
    GrAssert(samplerName && coordName);
    SkString sampler = build_sampler_string(samplerMode);
    SkString swizzle = build_swizzle_string(textureAccess, fContext.caps());

    fFSCode.appendf("%s( %s, %s)%s;\n", sampler.c_str(), samplerName,
                    coordName, swizzle.c_str());
}

GrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
                                                               const GrGLCaps& caps) {
    GrCustomStage::StageKey key = 0;
    // Assume that swizzle support implies that we never have to modify a shader to adjust
    // for texture format/swizzle settings.
    if (caps.textureSwizzleSupport()) {
        return key;
    }

    if (texture_requires_alpha_to_red_swizzle(caps, access)) {
        key = 1;
    }

    return key;
}

GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
                                                                     GrSLType type,
                                                                     const char* name,
                                                                     int count,
                                                                     const char** outName) {
    GrAssert(name && strlen(name));
    static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType;
    GrAssert(0 == (~kVisibilityMask & visibility));
    GrAssert(0 != visibility);

    BuilderUniform& uni = fUniforms.push_back();
    UniformHandle h = index_to_handle(fUniforms.count() - 1);
    GR_DEBUGCODE(UniformHandle h2 =)
    fUniformManager.appendUniform(type, count);
    // We expect the uniform manager to initially have no uniforms and that all uniforms are added
    // by this function. Therefore, the handles should match.
    GrAssert(h2 == h);
    uni.fVariable.setType(type);
    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
    SkString* uniName = uni.fVariable.accessName();
    if (kNonStageIdx == fCurrentStage) {
        uniName->printf("u%s", name);
    } else {
        uniName->printf("u%s%d", name, fCurrentStage);
    }
    uni.fVariable.setArrayCount(count);
    uni.fVisibility = visibility;

    // If it is visible in both the VS and FS, the precision must match.
    // We declare a default FS precision, but not a default VS. So set the var
    // to use the default FS precision.
    if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
        // the fragment and vertex precisions must match
        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
    }

    if (NULL != outName) {
        *outName = uni.fVariable.c_str();
    }

    return h;
}

const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
    return fUniforms[handle_to_index(u)].fVariable;
}

void GrGLShaderBuilder::addVarying(GrSLType type,
                                   const char* name,
                                   const char** vsOutName,
                                   const char** fsInName) {
    fVSOutputs.push_back();
    fVSOutputs.back().setType(type);
    fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
    if (kNonStageIdx == fCurrentStage) {
        fVSOutputs.back().accessName()->printf("v%s", name);
    } else {
        fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStage);
    }
    if (vsOutName) {
        *vsOutName = fVSOutputs.back().getName().c_str();
    }
    // input to FS comes either from VS or GS
    const SkString* fsName;
    if (fUsesGS) {
        // if we have a GS take each varying in as an array
        // and output as non-array.
        fGSInputs.push_back();
        fGSInputs.back().setType(type);
        fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
        fGSInputs.back().setUnsizedArray();
        *fGSInputs.back().accessName() = fVSOutputs.back().getName();
        fGSOutputs.push_back();
        fGSOutputs.back().setType(type);
        fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
        fGSOutputs.back().accessName()->printf("g%s", name);
        fsName = fGSOutputs.back().accessName();
    } else {
        fsName = fVSOutputs.back().accessName();
    }
    fFSInputs.push_back();
    fFSInputs.back().setType(type);
    fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
    fFSInputs.back().setName(*fsName);
    if (fsInName) {
        *fsInName = fsName->c_str();
    }
}

namespace {

inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
                                               GrGLBinding binding,
                                               SkString* str) {
    // Desktop GLSL has added precision qualifiers but they don't do anything.
    if (kES2_GrGLBinding == binding) {
        switch (p) {
            case GrGLShaderVar::kHigh_Precision:
                str->append("precision highp float;\n");
                break;
            case GrGLShaderVar::kMedium_Precision:
                str->append("precision mediump float;\n");
                break;
            case GrGLShaderVar::kLow_Precision:
                str->append("precision lowp float;\n");
                break;
            case GrGLShaderVar::kDefault_Precision:
                GrCrash("Default precision now allowed.");
            default:
                GrCrash("Unknown precision value.");
        }
    }
}
}

void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
    for (int i = 0; i < vars.count(); ++i) {
        vars[i].appendDecl(fContext, out);
    }
}

void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
    for (int i = 0; i < fUniforms.count(); ++i) {
        if (fUniforms[i].fVisibility & stype) {
            fUniforms[i].fVariable.appendDecl(fContext, out);
        }
    }
}

void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
    switch (type) {
        case kVertex_ShaderType:
            *shaderStr = fHeader;
            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
            this->appendDecls(fVSAttrs, shaderStr);
            this->appendDecls(fVSOutputs, shaderStr);
            shaderStr->append(fVSCode);
            break;
        case kGeometry_ShaderType:
            if (fUsesGS) {
                *shaderStr = fHeader;
                shaderStr->append(fGSHeader);
                this->appendDecls(fGSInputs, shaderStr);
                this->appendDecls(fGSOutputs, shaderStr);
                shaderStr->append(fGSCode);
            } else {
                shaderStr->reset();
            }
            break;
        case kFragment_ShaderType:
            *shaderStr = fHeader;
            append_default_precision_qualifier(kDefaultFragmentPrecision,
                                               fContext.binding(),
                                               shaderStr);
            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
            this->appendDecls(fFSInputs, shaderStr);
            // We shouldn't have declared outputs on 1.10
            GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty());
            this->appendDecls(fFSOutputs, shaderStr);
            shaderStr->append(fFSFunctions);
            shaderStr->append(fFSCode);
            break;
    }
 }

void GrGLShaderBuilder::finished(GrGLuint programID) {
    fUniformManager.getUniformLocations(programID, fUniforms);
}
<commit_msg>Early out the texture key generation if there is no texture passed to the GrGLShaderBuilder::keyForTextureAccess.  <commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
#include "GrTexture.h"

// number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8;

// except FS outputs where we expect 2 at most.
static const int kMaxFSOutputs = 2;

// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;

typedef GrGLUniformManager::UniformHandle UniformHandle;
///////////////////////////////////////////////////////////////////////////////

static SkString build_sampler_string(GrGLShaderBuilder::SamplerMode samplerMode) {
    SkString sampler("texture2D");
    switch (samplerMode) {
      case GrGLShaderBuilder::kDefault_SamplerMode:
          break;
      case GrGLShaderBuilder::kProj_SamplerMode:
          sampler.append("Proj");
          break;
      case GrGLShaderBuilder::kExplicitDivide_SamplerMode:
          GrAssert(false);  // Not Implemented
          break;
    }

    return sampler;
}

static bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps,
                                                  const GrTextureAccess& access) {
    return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() &&
        access.referencesAlpha();
}

static SkString build_swizzle_string(const GrTextureAccess& textureAccess,
                                     const GrGLCaps& caps) {
    const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle();
    if (0 == swizzle[0]) {
        return SkString("");
    }

    SkString swizzleOut(".");
    bool alphaIsRed = texture_requires_alpha_to_red_swizzle(caps, textureAccess);
    for (int offset = 0; offset < 4 && swizzle[offset]; ++offset) {
        if (alphaIsRed && 'a' == swizzle[offset]) {
            swizzleOut.appendf("r");
        } else {
            swizzleOut.appendf("%c", swizzle[offset]);
        }
    }

    return swizzleOut;
}

///////////////////////////////////////////////////////////////////////////////

// Architectural assumption: always 2-d input coords.
// Likely to become non-constant and non-static, perhaps even
// varying by stage, if we use 1D textures for gradients!
//const int GrGLShaderBuilder::fCoordDims = 2;

GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx, GrGLUniformManager& uniformManager)
    : fUniforms(kVarsPerBlock)
    , fVSAttrs(kVarsPerBlock)
    , fVSOutputs(kVarsPerBlock)
    , fGSInputs(kVarsPerBlock)
    , fGSOutputs(kVarsPerBlock)
    , fFSInputs(kVarsPerBlock)
    , fFSOutputs(kMaxFSOutputs)
    , fUsesGS(false)
    , fVaryingDims(0)
    , fComplexCoord(false)
    , fContext(ctx)
    , fUniformManager(uniformManager)
    , fCurrentStage(kNonStageIdx) {
}

void GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
   static const uint32_t kMulByAlphaMask =
        (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
         GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);

    fSwizzle = "";
    if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) {
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
        fSwizzle = ".bgra";
    } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
        GrAssert(!(configFlags & kMulByAlphaMask));
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
        fSwizzle = ".aaaa";
    } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
        GrAssert(!(configFlags & kMulByAlphaMask));
        GrAssert(!(configFlags &
                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
        fSwizzle = ".rrrr";
    }
}

void GrGLShaderBuilder::computeModulate(const char* fsInColor) {
    if (NULL != fsInColor) {
        fModulate.printf(" * %s", fsInColor);
    } else {
        fModulate.reset();
    }
}

void GrGLShaderBuilder::setupTextureAccess(SamplerMode samplerMode,
                                           int stageNum) {
    SkString retval;

    fTexFunc = "texture2D";
    switch (samplerMode) {
        case kDefault_SamplerMode:
            GrAssert(fVaryingDims == fCoordDims);
            // Do nothing
            break;
        case kProj_SamplerMode:
            fTexFunc.append("Proj");
            break;
        case kExplicitDivide_SamplerMode:
            retval = "inCoord";
            retval.appendS32(stageNum);
            fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
                GrGLShaderVar::TypeString
                    (GrSLFloatVectorType(fCoordDims)),
                retval.c_str(),
                fSampleCoords.c_str(),
                GrGLSLVectorNonhomogCoords(fVaryingDims),
                fSampleCoords.c_str(),
                GrGLSLVectorHomogCoord(fVaryingDims));
            fSampleCoords = retval;
            break;
    }
    fComplexCoord = false;
}

void GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
                                          const char* coordName) {
    if (NULL == coordName) {
        coordName = fSampleCoords.c_str();
    }
    fFSCode.appendf("%s(%s, %s)", fTexFunc.c_str(), samplerName, coordName);
}

void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
                                         const char* samplerName) {
    fFSCode.appendf("\t%s = ", outColor);
    this->emitTextureLookup(samplerName);
    fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
}

void GrGLShaderBuilder::emitCustomTextureLookup(SamplerMode samplerMode,
                                                const GrTextureAccess& textureAccess,
                                                const char* samplerName,
                                                const char* coordName) {
    GrAssert(samplerName && coordName);
    SkString sampler = build_sampler_string(samplerMode);
    SkString swizzle = build_swizzle_string(textureAccess, fContext.caps());

    fFSCode.appendf("%s( %s, %s)%s;\n", sampler.c_str(), samplerName,
                    coordName, swizzle.c_str());
}

GrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
                                                               const GrGLCaps& caps) {
    GrCustomStage::StageKey key = 0;

    if (!access.getTexture()) {
        return key;
    }

    // Assume that swizzle support implies that we never have to modify a shader to adjust
    // for texture format/swizzle settings.
    if (caps.textureSwizzleSupport()) {
        return key;
    }

    if (texture_requires_alpha_to_red_swizzle(caps, access)) {
        key = 1;
    }

    return key;
}

GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
                                                                     GrSLType type,
                                                                     const char* name,
                                                                     int count,
                                                                     const char** outName) {
    GrAssert(name && strlen(name));
    static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType;
    GrAssert(0 == (~kVisibilityMask & visibility));
    GrAssert(0 != visibility);

    BuilderUniform& uni = fUniforms.push_back();
    UniformHandle h = index_to_handle(fUniforms.count() - 1);
    GR_DEBUGCODE(UniformHandle h2 =)
    fUniformManager.appendUniform(type, count);
    // We expect the uniform manager to initially have no uniforms and that all uniforms are added
    // by this function. Therefore, the handles should match.
    GrAssert(h2 == h);
    uni.fVariable.setType(type);
    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
    SkString* uniName = uni.fVariable.accessName();
    if (kNonStageIdx == fCurrentStage) {
        uniName->printf("u%s", name);
    } else {
        uniName->printf("u%s%d", name, fCurrentStage);
    }
    uni.fVariable.setArrayCount(count);
    uni.fVisibility = visibility;

    // If it is visible in both the VS and FS, the precision must match.
    // We declare a default FS precision, but not a default VS. So set the var
    // to use the default FS precision.
    if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
        // the fragment and vertex precisions must match
        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
    }

    if (NULL != outName) {
        *outName = uni.fVariable.c_str();
    }

    return h;
}

const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
    return fUniforms[handle_to_index(u)].fVariable;
}

void GrGLShaderBuilder::addVarying(GrSLType type,
                                   const char* name,
                                   const char** vsOutName,
                                   const char** fsInName) {
    fVSOutputs.push_back();
    fVSOutputs.back().setType(type);
    fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
    if (kNonStageIdx == fCurrentStage) {
        fVSOutputs.back().accessName()->printf("v%s", name);
    } else {
        fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStage);
    }
    if (vsOutName) {
        *vsOutName = fVSOutputs.back().getName().c_str();
    }
    // input to FS comes either from VS or GS
    const SkString* fsName;
    if (fUsesGS) {
        // if we have a GS take each varying in as an array
        // and output as non-array.
        fGSInputs.push_back();
        fGSInputs.back().setType(type);
        fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
        fGSInputs.back().setUnsizedArray();
        *fGSInputs.back().accessName() = fVSOutputs.back().getName();
        fGSOutputs.push_back();
        fGSOutputs.back().setType(type);
        fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
        fGSOutputs.back().accessName()->printf("g%s", name);
        fsName = fGSOutputs.back().accessName();
    } else {
        fsName = fVSOutputs.back().accessName();
    }
    fFSInputs.push_back();
    fFSInputs.back().setType(type);
    fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
    fFSInputs.back().setName(*fsName);
    if (fsInName) {
        *fsInName = fsName->c_str();
    }
}

namespace {

inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
                                               GrGLBinding binding,
                                               SkString* str) {
    // Desktop GLSL has added precision qualifiers but they don't do anything.
    if (kES2_GrGLBinding == binding) {
        switch (p) {
            case GrGLShaderVar::kHigh_Precision:
                str->append("precision highp float;\n");
                break;
            case GrGLShaderVar::kMedium_Precision:
                str->append("precision mediump float;\n");
                break;
            case GrGLShaderVar::kLow_Precision:
                str->append("precision lowp float;\n");
                break;
            case GrGLShaderVar::kDefault_Precision:
                GrCrash("Default precision now allowed.");
            default:
                GrCrash("Unknown precision value.");
        }
    }
}
}

void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
    for (int i = 0; i < vars.count(); ++i) {
        vars[i].appendDecl(fContext, out);
    }
}

void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
    for (int i = 0; i < fUniforms.count(); ++i) {
        if (fUniforms[i].fVisibility & stype) {
            fUniforms[i].fVariable.appendDecl(fContext, out);
        }
    }
}

void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
    switch (type) {
        case kVertex_ShaderType:
            *shaderStr = fHeader;
            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
            this->appendDecls(fVSAttrs, shaderStr);
            this->appendDecls(fVSOutputs, shaderStr);
            shaderStr->append(fVSCode);
            break;
        case kGeometry_ShaderType:
            if (fUsesGS) {
                *shaderStr = fHeader;
                shaderStr->append(fGSHeader);
                this->appendDecls(fGSInputs, shaderStr);
                this->appendDecls(fGSOutputs, shaderStr);
                shaderStr->append(fGSCode);
            } else {
                shaderStr->reset();
            }
            break;
        case kFragment_ShaderType:
            *shaderStr = fHeader;
            append_default_precision_qualifier(kDefaultFragmentPrecision,
                                               fContext.binding(),
                                               shaderStr);
            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
            this->appendDecls(fFSInputs, shaderStr);
            // We shouldn't have declared outputs on 1.10
            GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty());
            this->appendDecls(fFSOutputs, shaderStr);
            shaderStr->append(fFSFunctions);
            shaderStr->append(fFSCode);
            break;
    }
 }

void GrGLShaderBuilder::finished(GrGLuint programID) {
    fUniformManager.getUniformLocations(programID, fUniforms);
}
<|endoftext|>