<commit_before>// Copyright (c) 2017 Alexander Gallego. All rights reserved.
//

#include <chrono>
#include <iostream>

#include <seastar/core/app-template.hh>
#include <seastar/core/distributed.hh>
#include <seastar/core/reactor.hh>
#include <seastar/net/api.hh>

#include "smf/histogram_seastar_utils.h"
#include "smf/log.h"
#include "smf/rpc_filter.h"
#include "smf/rpc_server.h"
#include "smf/unique_histogram_adder.h"
#include "smf/zstd_filter.h"

#include "demo_service.smf.fb.h"

class storage_service final : public smf_gen::demo::SmfStorage {
  virtual seastar::future<smf::rpc_typed_envelope<smf_gen::demo::Response>>
  Get(smf::rpc_recv_typed_context<smf_gen::demo::Request> &&rec) final {
    smf::rpc_typed_envelope<smf_gen::demo::Response> data;
    // return the same payload
    if (rec) { data.data->name = rec->name()->c_str(); }
    data.envelope.set_status(200);
    return seastar::make_ready_future<
      smf::rpc_typed_envelope<smf_gen::demo::Response>>(std::move(data));
  }
};

void
cli_opts(boost::program_options::options_description_easy_init o) {
  namespace po = boost::program_options;
  o("ip", po::value<std::string>()->default_value("127.0.0.1"),
    "ip to connect to");
  o("port", po::value<uint16_t>()->default_value(20776), "port for service");
  o("httpport", po::value<uint16_t>()->default_value(20777),
    "port for http stats service");
  o("key",
    po::value<std::string>()->default_value(""),
    "key for TLS seccured connection");
  o("cert", po::value<std::string>()->default_value(""),
    "cert for TLS seccured connection");
}

int
main(int args, char **argv, char **env) {
  std::setvbuf(stdout, nullptr, _IOLBF, 1024);
  seastar::distributed<smf::rpc_server> rpc;
  seastar::app_template app;
  cli_opts(app.add_options());

  return app.run_deprecated(args, argv, [&] {
    seastar::engine().at_exit([&] {
      return rpc
        .map_reduce(smf::unique_histogram_adder(),
                    &smf::rpc_server::copy_histogram)
        .then([](auto h) {
          LOG_INFO("Writing server histograms");
          return smf::histogram_seastar_utils::write("server_latency.hgrm",
                                                     std::move(h));
        })
        .then([&rpc] { return rpc.stop(); });
    });

    auto &cfg = app.configuration();

    smf::rpc_server_args args;
    args.ip = cfg["ip"].as<std::string>().c_str();
    args.rpc_port = cfg["port"].as<uint16_t>();
    args.http_port = cfg["httpport"].as<uint16_t>();

    auto key = cfg["key"].as<std::string>();
    auto cert = cfg["cert"].as<std::string>();
    if (key != "" && cert != "") {
        auto builder = seastar::tls::credentials_builder();
        builder.set_dh_level(seastar::tls::dh_params::level::MEDIUM);
        builder
          .set_x509_key_file(cert, key, seastar::tls::x509_crt_format::PEM)
          .get();
        args.credentials
          = builder.build_reloadable_server_credentials().get0();
    }

    args.memory_avail_per_core =
      static_cast<uint64_t>(0.9 * seastar::memory::stats().total_memory());

    return rpc.start(args)
      .then([&rpc] {
        LOG_INFO("Registering smf_gen::demo::storage_service");
        return rpc.invoke_on_all(
          &smf::rpc_server::register_service<storage_service>);
      })
      .then([&rpc] {
        return rpc.invoke_on_all(&smf::rpc_server::register_incoming_filter<
                                 smf::zstd_decompression_filter>);
      })
      .then([&rpc] {
        LOG_INFO("Invoking rpc start on all cores");
        return rpc.invoke_on_all(&smf::rpc_server::start);
      });
  });
}
<commit_msg>tls: fix promises<commit_after>// Copyright (c) 2017 Alexander Gallego. All rights reserved.
//

#include <chrono>
#include <iostream>

#include <seastar/core/app-template.hh>
#include <seastar/core/distributed.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/thread.hh>
#include <seastar/net/api.hh>

#include "smf/histogram_seastar_utils.h"
#include "smf/log.h"
#include "smf/rpc_filter.h"
#include "smf/rpc_server.h"
#include "smf/unique_histogram_adder.h"
#include "smf/zstd_filter.h"

#include "demo_service.smf.fb.h"

class storage_service final : public smf_gen::demo::SmfStorage {
  virtual seastar::future<smf::rpc_typed_envelope<smf_gen::demo::Response>>
  Get(smf::rpc_recv_typed_context<smf_gen::demo::Request> &&rec) final {
    smf::rpc_typed_envelope<smf_gen::demo::Response> data;
    // return the same payload
    if (rec) { data.data->name = rec->name()->c_str(); }
    data.envelope.set_status(200);
    return seastar::make_ready_future<
      smf::rpc_typed_envelope<smf_gen::demo::Response>>(std::move(data));
  }
};

void
cli_opts(boost::program_options::options_description_easy_init o) {
  namespace po = boost::program_options;
  o("ip", po::value<std::string>()->default_value("127.0.0.1"),
    "ip to connect to");
  o("port", po::value<uint16_t>()->default_value(20776), "port for service");
  o("httpport", po::value<uint16_t>()->default_value(20777),
    "port for http stats service");
  o("key", po::value<std::string>()->default_value(""),
    "key for TLS seccured connection");
  o("cert", po::value<std::string>()->default_value(""),
    "cert for TLS seccured connection");
}

int
main(int args, char **argv, char **env) {
  std::setvbuf(stdout, nullptr, _IOLBF, 1024);
  seastar::distributed<smf::rpc_server> rpc;
  seastar::app_template app;
  cli_opts(app.add_options());
  return app.run_deprecated(args, argv, [&] {
    seastar::engine().at_exit([&] {
      return rpc
        .map_reduce(smf::unique_histogram_adder(),
                    &smf::rpc_server::copy_histogram)
        .then([](auto h) {
          LOG_INFO("Writing server histograms");
          return smf::histogram_seastar_utils::write("server_latency.hgrm",
                                                     std::move(h));
        })
        .then([&rpc] { return rpc.stop(); });
    });

    auto &cfg = app.configuration();
    return seastar::async([&] {
      smf::rpc_server_args args;
      args.ip = cfg["ip"].as<std::string>().c_str();
      args.rpc_port = cfg["port"].as<uint16_t>();
      args.http_port = cfg["httpport"].as<uint16_t>();
      args.memory_avail_per_core =
        static_cast<uint64_t>(0.9 * seastar::memory::stats().total_memory());
      auto key = cfg["key"].as<std::string>();
      auto cert = cfg["cert"].as<std::string>();

      if (key != "" && cert != "") {
        LOG_INFO("Setting tls credentials");
        auto builder = seastar::tls::credentials_builder();
        builder.set_dh_level(seastar::tls::dh_params::level::MEDIUM);
        builder.set_x509_key_file(cert, key, seastar::tls::x509_crt_format::PEM)
          .get();
        args.credentials = builder.build_reloadable_server_credentials().get0();
      }

      rpc.start(args).get();
      LOG_INFO("Registering smf_gen::demo::storage_service");
      rpc.invoke_on_all(&smf::rpc_server::register_service<storage_service>)
        .get();
      rpc
        .invoke_on_all(&smf::rpc_server::register_incoming_filter<
                       smf::zstd_decompression_filter>)
        .get();
      LOG_INFO("Invoking rpc start on all cores");
      rpc.invoke_on_all(&smf::rpc_server::start).get();
    });
  });
}
<|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_mc
/// Macro to compare masses in ROOT data base to the values from pdg
/// (http://pdg.lbl.gov/2009/mcdata/mass_width_2008.mc)[pdg]
///
/// The ROOT values are read in by TDatabasePDG from `$ROOTSYS/etc/pdg_table.txt`
///
/// \macro_output
/// \macro_code
///
/// \author Christian.Klein-Boesing

#include "TDatabasePDG.h"
#include "TParticlePDG.h"

void CompareMasses()
{
   TString massWidthFile = gSystem->UnixPathName(__FILE__);
   massWidthFile.ReplaceAll("CompareMasses.C","mass_width_2008.mc.txt");

   FILE* file = fopen(massWidthFile.Data(),"r");

   if (!file){
      Printf("Could not open PDG particle file %s", massWidthFile.Data());
      return;
   }

   char      c[200];
   char      cempty;
   Int_t     pdg[4];
   Float_t   mass, err1, err2, err;
   Int_t     ndiff = 0;

   while (fgets(c, 200, file)) {
      if (c[0] != '*' &&  c[0] !='W') {
         //printf("%s",c);
         sscanf(&c[1], "%8d", &pdg[0]);

         // check emptiness
         pdg[1] = 0;
         for(int i = 0;i<8;i++){
            sscanf(&c[9+i],"%c",&cempty);
            if(cempty != ' ')sscanf(&c[9],"%8d",&pdg[1]);
         }

         pdg[2] = 0;
         for(int i = 0;i<8;i++){
            sscanf(&c[17+i],"%c",&cempty);
            if(cempty != ' ')sscanf(&c[17],"%8d",&pdg[2]);
         }

         pdg[3] = 0;
         for(int i = 0;i<8;i++){
            sscanf(&c[25+i],"%c",&cempty);
            if(cempty != ' ')sscanf(&c[25],"%8d",&pdg[3]);
         }

         sscanf(&c[35],"%14f",&mass);
         sscanf(&c[50],"%8f",&err1);
         sscanf(&c[50],"%8f",&err2);
         err = TMath::Max((Double_t)err1,(Double_t)-1.*err2);
         for(int ipdg = 0;ipdg  < 4;ipdg++){
            if(pdg[ipdg]==0)continue;
            TParticlePDG *partRoot = TDatabasePDG::Instance()->GetParticle(pdg[ipdg]);
            if(partRoot){
               Float_t massRoot = partRoot->Mass();
               Float_t deltaM = TMath::Abs(massRoot - mass);
               //      if(deltaM > err){
               if (mass != 0.0 && deltaM/mass>1E-05){
                  ndiff++;
                  Printf("%10s %8d pdg mass %E pdg err %E root Mass %E >> deltaM %E = %3.3f%%",partRoot->GetName(),pdg[ipdg],mass,err,massRoot,deltaM,100.*deltaM/mass);
               }
            }
         }
      }
   }// while
   fclose(file);
   if (ndiff == 0) Printf("Crongratulations !! All particles in ROOT and PDG have identical masses");

}
<commit_msg>Fix markdown<commit_after>/// \file
/// \ingroup tutorial_mc
/// Macro to compare masses in ROOT data base to the values from pdg
/// [pdg](http://pdg.lbl.gov/2009/mcdata/mass_width_2008.mc).
///
/// The ROOT values are read in by TDatabasePDG from `$ROOTSYS/etc/pdg_table.txt`
///
/// \macro_output
/// \macro_code
///
/// \author Christian.Klein-Boesing

#include "TDatabasePDG.h"
#include "TParticlePDG.h"

void CompareMasses()
{
   TString massWidthFile = gSystem->UnixPathName(__FILE__);
   massWidthFile.ReplaceAll("CompareMasses.C","mass_width_2008.mc.txt");

   FILE* file = fopen(massWidthFile.Data(),"r");

   if (!file){
      Printf("Could not open PDG particle file %s", massWidthFile.Data());
      return;
   }

   char      c[200];
   char      cempty;
   Int_t     pdg[4];
   Float_t   mass, err1, err2, err;
   Int_t     ndiff = 0;

   while (fgets(c, 200, file)) {
      if (c[0] != '*' &&  c[0] !='W') {
         //printf("%s",c);
         sscanf(&c[1], "%8d", &pdg[0]);

         // check emptiness
         pdg[1] = 0;
         for(int i = 0;i<8;i++){
            sscanf(&c[9+i],"%c",&cempty);
            if(cempty != ' ')sscanf(&c[9],"%8d",&pdg[1]);
         }

         pdg[2] = 0;
         for(int i = 0;i<8;i++){
            sscanf(&c[17+i],"%c",&cempty);
            if(cempty != ' ')sscanf(&c[17],"%8d",&pdg[2]);
         }

         pdg[3] = 0;
         for(int i = 0;i<8;i++){
            sscanf(&c[25+i],"%c",&cempty);
            if(cempty != ' ')sscanf(&c[25],"%8d",&pdg[3]);
         }

         sscanf(&c[35],"%14f",&mass);
         sscanf(&c[50],"%8f",&err1);
         sscanf(&c[50],"%8f",&err2);
         err = TMath::Max((Double_t)err1,(Double_t)-1.*err2);
         for(int ipdg = 0;ipdg  < 4;ipdg++){
            if(pdg[ipdg]==0)continue;
            TParticlePDG *partRoot = TDatabasePDG::Instance()->GetParticle(pdg[ipdg]);
            if(partRoot){
               Float_t massRoot = partRoot->Mass();
               Float_t deltaM = TMath::Abs(massRoot - mass);
               //      if(deltaM > err){
               if (mass != 0.0 && deltaM/mass>1E-05){
                  ndiff++;
                  Printf("%10s %8d pdg mass %E pdg err %E root Mass %E >> deltaM %E = %3.3f%%",partRoot->GetName(),pdg[ipdg],mass,err,massRoot,deltaM,100.*deltaM/mass);
               }
            }
         }
      }
   }// while
   fclose(file);
   if (ndiff == 0) Printf("Crongratulations !! All particles in ROOT and PDG have identical masses");

}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <deque>

#include "dll_test.hpp"

#include "dll/neural/conv_layer.hpp"
#include "dll/neural/dense_layer.hpp"
#include "dll/dbn.hpp"
#include "dll/datasets.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE("unit/conv/sgd/1", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<6 * 24 * 24, 10, dll::activation<dll::function::SIGMOID>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::updater<dll::updater_type::MOMENTUM>, dll::batch_size<10>>::dbn_t dbn_t;

    // Load the dataset
    auto dataset = dll::make_mnist_dataset_sub(500, 0, dll::batch_size<10>{});

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK_DATASET(25, 5e-2);
    TEST_CHECK_DATASET(0.25);
}

TEST_CASE("unit/conv/sgd/2", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::TANH>>::layer_t,
            dll::dense_desc<6 * 24 * 24, 10, dll::activation<dll::function::TANH>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<10>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    dll_test::mnist_scale(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.4);
}

TEST_CASE("unit/conv/sgd/3", "[unit][conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 4, 5, 5, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<4 * 24 * 24, 10, dll::activation<dll::function::TANH>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::updater<dll::updater_type::SGD>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(800);
    REQUIRE(!dataset.training_images.empty());

    dll_test::mnist_scale(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK(75, 6e-2);
    TEST_CHECK(0.25);
}

TEST_CASE("unit/conv/sgd/4", "[unit][conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::conv_desc<6, 24, 24, 4, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<4 * 20 * 20, 10, dll::activation<dll::function::SIGMOID>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>, dll::scale_pre<255>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(800);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.1;

    FT_CHECK(35, 0.2);
    TEST_CHECK(0.25);
}

TEST_CASE("unit/conv/sgd/5", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::RELU>>::layer_t,
            dll::conv_desc<6, 24, 24, 4, 5, 5, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<4 * 20 * 20, 200, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<200, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    dll_test::mnist_scale(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK(25, 6e-2);
    TEST_CHECK(0.2);
}

// Test custom training
TEST_CASE("unit/conv/sgd/partial/1", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<6 * 24 * 24, 10, dll::activation<dll::function::SIGMOID>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<10>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    using generator_t = dll::inmemory_data_generator_desc<dll::batch_size<10>, dll::categorical>;

    auto generator = dll::make_generator(dataset.training_images, dataset.training_labels, 10, generator_t{});

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.07;

    auto trainer = dbn->get_trainer();

    trainer.start_training(*dbn, 30);

    // Train for 25 epochs
    for(size_t epoch = 0; epoch < 30; ++epoch){
        trainer.start_epoch(*dbn, epoch);

        generator->reset();

        double error;
        double loss;

        // Train for one epoch
        std::tie(loss, error) = trainer.train_epoch(*dbn, *generator, epoch);

        if(trainer.stop_epoch(*dbn, epoch, error, loss)){
            break;
        }
    }

    auto ft_error = trainer.stop_training(*dbn);

    REQUIRE(ft_error < 5e-2);

    TEST_CHECK(0.25);
}
<commit_msg>Test He initialization<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <deque>

#include "dll_test.hpp"

#include "dll/neural/conv_layer.hpp"
#include "dll/neural/dense_layer.hpp"
#include "dll/dbn.hpp"
#include "dll/datasets.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE("unit/conv/sgd/1", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<6 * 24 * 24, 10, dll::activation<dll::function::SIGMOID>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::updater<dll::updater_type::MOMENTUM>, dll::batch_size<10>>::dbn_t dbn_t;

    // Load the dataset
    auto dataset = dll::make_mnist_dataset_sub(500, 0, dll::batch_size<10>{});

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK_DATASET(25, 5e-2);
    TEST_CHECK_DATASET(0.25);
}

TEST_CASE("unit/conv/sgd/2", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::TANH>>::layer_t,
            dll::dense_desc<6 * 24 * 24, 10, dll::activation<dll::function::TANH>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<10>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    dll_test::mnist_scale(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.4);
}

TEST_CASE("unit/conv/sgd/3", "[unit][conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 4, 5, 5, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<4 * 24 * 24, 10, dll::activation<dll::function::TANH>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::updater<dll::updater_type::SGD>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(800);
    REQUIRE(!dataset.training_images.empty());

    dll_test::mnist_scale(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK(75, 6e-2);
    TEST_CHECK(0.25);
}

TEST_CASE("unit/conv/sgd/4", "[unit][conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::conv_desc<6, 24, 24, 4, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<4 * 20 * 20, 10, dll::activation<dll::function::SIGMOID>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>, dll::scale_pre<255>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(800);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.1;

    FT_CHECK(35, 0.2);
    TEST_CHECK(0.25);
}

TEST_CASE("unit/conv/sgd/5", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::RELU>, dll::initializer<dll::initializer_type::HE>>::layer_t,
            dll::conv_desc<6, 24, 24, 4, 5, 5, dll::activation<dll::function::RELU>, dll::initializer<dll::initializer_type::HE>>::layer_t,
            dll::dense_desc<4 * 20 * 20, 200, dll::activation<dll::function::RELU>, dll::initializer<dll::initializer_type::HE>>::layer_t,
            dll::dense_desc<200, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(1000);
    REQUIRE(!dataset.training_images.empty());

    dll_test::mnist_scale(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    FT_CHECK(25, 6e-2);
    TEST_CHECK(0.2);
}

// Test custom training
TEST_CASE("unit/conv/sgd/partial/1", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_desc<1, 28, 28, 6, 5, 5, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<6 * 24 * 24, 10, dll::activation<dll::function::SIGMOID>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<10>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    using generator_t = dll::inmemory_data_generator_desc<dll::batch_size<10>, dll::categorical>;

    auto generator = dll::make_generator(dataset.training_images, dataset.training_labels, 10, generator_t{});

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.07;

    auto trainer = dbn->get_trainer();

    trainer.start_training(*dbn, 30);

    // Train for 25 epochs
    for(size_t epoch = 0; epoch < 30; ++epoch){
        trainer.start_epoch(*dbn, epoch);

        generator->reset();

        double error;
        double loss;

        // Train for one epoch
        std::tie(loss, error) = trainer.train_epoch(*dbn, *generator, epoch);

        if(trainer.stop_epoch(*dbn, epoch, error, loss)){
            break;
        }
    }

    auto ft_error = trainer.stop_training(*dbn);

    REQUIRE(ft_error < 5e-2);

    TEST_CHECK(0.25);
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "packetqueue.h"
#include "packet.h"
#include <vespa/fastos/time.h>
#include <cassert>
#include <chrono>

void
FNET_PacketQueue_NoLock::ExpandBuf(uint32_t needentries)
{
    uint32_t oldsize = _bufsize;
    if (_bufsize < 8)
        _bufsize = 8;
    while (_bufsize < _bufused + needentries)
        _bufsize *= 2;
    _QElem *newbuf = static_cast<_QElem *>(malloc(sizeof(_QElem) * _bufsize));
    assert(newbuf != nullptr);
    if (_bufused == 0) {          // EMPTY
        // BUFFER: |....................|
        // USED:   |....................|

    } else if (_in_pos > _out_pos) { // NON-WRAPPED
        // BUFFER: |....................|
        // USED:   |....############....|
        //            rOfs   rLen

        uint32_t rOfs = _out_pos;
        uint32_t rLen = (_in_pos - _out_pos);
//TODO Rewrite to pure C++
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
        memcpy(newbuf + rOfs, _buf + rOfs, rLen * sizeof(_QElem));
#pragma GCC diagnostic pop
    } else {                      // WRAPPED
        // BUFFER: |....................|
        // USED:   |######........######|
        //          r1Len          r2Len

        uint32_t r1Len = _in_pos;
        uint32_t r2Len = (oldsize - _out_pos);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
        memcpy(newbuf, _buf, r1Len * sizeof(_QElem));
        memcpy(newbuf + _bufsize - r2Len, _buf + oldsize - r2Len, r2Len * sizeof(_QElem));
#pragma GCC diagnostic pop
        _out_pos += _bufsize - oldsize;
    }
    free(_buf);
    _buf = newbuf;
}

FNET_PacketQueue_NoLock::FNET_PacketQueue_NoLock(uint32_t len,
                                                 HP_RetCode hpRetCode)
    : _buf(nullptr),
      _bufsize(len),
      _bufused(0),
      _in_pos(0),
      _out_pos(0),
      _hpRetCode(hpRetCode)
{
    _buf = static_cast<_QElem *>(malloc(sizeof(_QElem) * len));
    assert(_buf != nullptr);
}

FNET_PacketQueue_NoLock::~FNET_PacketQueue_NoLock()
{
    DiscardPackets_NoLock();
    free(_buf);
}

FNET_IPacketHandler::HP_RetCode
FNET_PacketQueue_NoLock::HandlePacket(FNET_Packet  *packet,
                                      FNET_Context  context)
{
    QueuePacket_NoLock(packet, context);
    return _hpRetCode;
}

void
FNET_PacketQueue_NoLock::QueuePacket_NoLock(FNET_Packet *packet,
                                            FNET_Context context)
{
    if (packet == nullptr)
        return;
    EnsureFree();
    _buf[_in_pos]._packet = packet;
    _buf[_in_pos]._context = context;
    if (++_in_pos == _bufsize)
        _in_pos = 0;                 // wrap around.
    _bufused++;
}

FNET_Packet*
FNET_PacketQueue_NoLock::DequeuePacket_NoLock(FNET_Context *context)
{
    assert(context != nullptr);
    FNET_Packet *packet = nullptr;
    if (_bufused > 0) {
        packet = _buf[_out_pos]._packet;
        __builtin_prefetch(packet, 0);
        *context = _buf[_out_pos]._context;
        if (++_out_pos == _bufsize)
            _out_pos = 0;              // wrap around
        _bufused--;
    }
    return packet;
}

uint32_t
FNET_PacketQueue_NoLock::FlushPackets_NoLock(FNET_PacketQueue_NoLock *target)
{
    uint32_t cnt = _bufused;

    target->EnsureFree(cnt);
    for (; _bufused > 0; _bufused--, target->_bufused++) {
        target->_buf[target->_in_pos]._packet  = _buf[_out_pos]._packet;
        target->_buf[target->_in_pos]._context = _buf[_out_pos]._context;

        if (++target->_in_pos == target->_bufsize)
            target->_in_pos = 0;         // wrap around.
        if (++_out_pos == _bufsize)
            _out_pos = 0;                // wrap around.
    }
    assert(_out_pos == _in_pos);

    return cnt;
}

void
FNET_PacketQueue_NoLock::DiscardPackets_NoLock()
{
    for (; _bufused > 0; _bufused--) {
        _buf[_out_pos]._packet->Free();   // discard packet
        if (++_out_pos == _bufsize)
            _out_pos = 0;                   // wrap around
    }
    assert(_out_pos == _in_pos);
}

void
FNET_PacketQueue_NoLock::Print(uint32_t indent)
{
    uint32_t i   = _out_pos;
    uint32_t cnt = _bufused;

    printf("%*sFNET_PacketQueue_NoLock {\n", indent, "");
    printf("%*s  bufsize : %d\n", indent, "", _bufsize);
    printf("%*s  bufused : %d\n", indent, "", _bufused);
    printf("%*s  in_pos  : %d\n", indent, "", _in_pos);
    printf("%*s  out_pos : %d\n", indent, "", _out_pos);
    for (; cnt > 0; i++, cnt--) {
        if (i == _bufsize)
            i = 0;           // wrap around
        _buf[i]._packet->Print(indent + 2);
        _buf[i]._context.Print(indent + 2);
    }
    printf("%*s}\n", indent, "");
}

//------------------------------------------------------------------

FNET_PacketQueue::FNET_PacketQueue(uint32_t len,
                                   HP_RetCode hpRetCode)
    : FNET_PacketQueue_NoLock(len, hpRetCode),
      _lock(),
      _cond(),
      _waitCnt(0)
{
}

FNET_PacketQueue::~FNET_PacketQueue()
{
}

FNET_IPacketHandler::HP_RetCode
FNET_PacketQueue::HandlePacket(FNET_Packet  *packet,
                               FNET_Context  context)
{
    QueuePacket(packet, context);
    return _hpRetCode;
}

void
FNET_PacketQueue::QueuePacket(FNET_Packet *packet, FNET_Context context)
{
    assert(packet != nullptr);
    std::lock_guard<std::mutex> guard(_lock);
    EnsureFree();
    _buf[_in_pos]._packet = packet;  // insert packet ref.
    _buf[_in_pos]._context = context;
    if (++_in_pos == _bufsize)
        _in_pos = 0;                   // wrap around.
    _bufused++;
    if (_waitCnt >= _bufused) {        // signal waiting thread(s)
        _cond.notify_one();
    }
}

FNET_Packet*
FNET_PacketQueue::DequeuePacket(FNET_Context *context)
{
    FNET_Packet *packet = nullptr;
    std::unique_lock<std::mutex> guard(_lock);
    _waitCnt++;
    while (_bufused == 0) {
        _cond.wait(guard);
    }
    _waitCnt--;
    packet = _buf[_out_pos]._packet;
    *context = _buf[_out_pos]._context;
    if (++_out_pos == _bufsize)
        _out_pos = 0;                   // wrap around
    _bufused--;
    return packet;
}

FNET_Packet*
FNET_PacketQueue::DequeuePacket(uint32_t maxwait, FNET_Context *context)
{
    FNET_Packet *packet = nullptr;
    FastOS_Time  startTime;
    int          waitTime;

    if (maxwait > 0)
        startTime.SetNow();
    std::unique_lock<std::mutex> guard(_lock);
    if (maxwait > 0) {
        bool timeout = false;

        _waitCnt++;
        while ((_bufused == 0) && !timeout && (waitTime = (int)(maxwait - startTime.MilliSecsToNow())) > 0) {
            timeout = _cond.wait_for(guard, std::chrono::milliseconds(waitTime)) == std::cv_status::timeout;
        }
        _waitCnt--;
    }
    if (_bufused > 0) {
        packet = _buf[_out_pos]._packet;
        *context = _buf[_out_pos]._context;
        if (++_out_pos == _bufsize)
            _out_pos = 0;                   // wrap around
        _bufused--;
    }
    return packet;
}

void
FNET_PacketQueue::Print(uint32_t indent)
{
    std::lock_guard<std::mutex> guard(_lock);
    uint32_t i   = _out_pos;
    uint32_t cnt = _bufused;

    printf("%*sFNET_PacketQueue {\n", indent, "");
    printf("%*s  bufsize : %d\n", indent, "", _bufsize);
    printf("%*s  bufused : %d\n", indent, "", _bufused);
    printf("%*s  in_pos  : %d\n", indent, "", _in_pos);
    printf("%*s  out_pos : %d\n", indent, "", _out_pos);
    printf("%*s  waitCnt : %d\n", indent, "", _waitCnt);
    for (; cnt > 0; i++, cnt--) {
        if (i == _bufsize)
            i = 0;           // wrap around
        _buf[i]._packet->Print(indent + 2);
        _buf[i]._context.Print(indent + 2);
    }
    printf("%*s}\n", indent, "");
}
<commit_msg>Only ignore warning on gcc 8<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "packetqueue.h"
#include "packet.h"
#include <vespa/fastos/time.h>
#include <cassert>
#include <chrono>

void
FNET_PacketQueue_NoLock::ExpandBuf(uint32_t needentries)
{
    uint32_t oldsize = _bufsize;
    if (_bufsize < 8)
        _bufsize = 8;
    while (_bufsize < _bufused + needentries)
        _bufsize *= 2;
    _QElem *newbuf = static_cast<_QElem *>(malloc(sizeof(_QElem) * _bufsize));
    assert(newbuf != nullptr);
    if (_bufused == 0) {          // EMPTY
        // BUFFER: |....................|
        // USED:   |....................|

    } else if (_in_pos > _out_pos) { // NON-WRAPPED
        // BUFFER: |....................|
        // USED:   |....############....|
        //            rOfs   rLen

        uint32_t rOfs = _out_pos;
        uint32_t rLen = (_in_pos - _out_pos);
//TODO Rewrite to pure C++
#pragma GCC diagnostic push
#if __GNUC__ >= 8
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
        memcpy(newbuf + rOfs, _buf + rOfs, rLen * sizeof(_QElem));
#pragma GCC diagnostic pop
    } else {                      // WRAPPED
        // BUFFER: |....................|
        // USED:   |######........######|
        //          r1Len          r2Len

        uint32_t r1Len = _in_pos;
        uint32_t r2Len = (oldsize - _out_pos);
#pragma GCC diagnostic push
#if __GNUC__ >= 8
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
        memcpy(newbuf, _buf, r1Len * sizeof(_QElem));
        memcpy(newbuf + _bufsize - r2Len, _buf + oldsize - r2Len, r2Len * sizeof(_QElem));
#pragma GCC diagnostic pop
        _out_pos += _bufsize - oldsize;
    }
    free(_buf);
    _buf = newbuf;
}

FNET_PacketQueue_NoLock::FNET_PacketQueue_NoLock(uint32_t len,
                                                 HP_RetCode hpRetCode)
    : _buf(nullptr),
      _bufsize(len),
      _bufused(0),
      _in_pos(0),
      _out_pos(0),
      _hpRetCode(hpRetCode)
{
    _buf = static_cast<_QElem *>(malloc(sizeof(_QElem) * len));
    assert(_buf != nullptr);
}

FNET_PacketQueue_NoLock::~FNET_PacketQueue_NoLock()
{
    DiscardPackets_NoLock();
    free(_buf);
}

FNET_IPacketHandler::HP_RetCode
FNET_PacketQueue_NoLock::HandlePacket(FNET_Packet  *packet,
                                      FNET_Context  context)
{
    QueuePacket_NoLock(packet, context);
    return _hpRetCode;
}

void
FNET_PacketQueue_NoLock::QueuePacket_NoLock(FNET_Packet *packet,
                                            FNET_Context context)
{
    if (packet == nullptr)
        return;
    EnsureFree();
    _buf[_in_pos]._packet = packet;
    _buf[_in_pos]._context = context;
    if (++_in_pos == _bufsize)
        _in_pos = 0;                 // wrap around.
    _bufused++;
}

FNET_Packet*
FNET_PacketQueue_NoLock::DequeuePacket_NoLock(FNET_Context *context)
{
    assert(context != nullptr);
    FNET_Packet *packet = nullptr;
    if (_bufused > 0) {
        packet = _buf[_out_pos]._packet;
        __builtin_prefetch(packet, 0);
        *context = _buf[_out_pos]._context;
        if (++_out_pos == _bufsize)
            _out_pos = 0;              // wrap around
        _bufused--;
    }
    return packet;
}

uint32_t
FNET_PacketQueue_NoLock::FlushPackets_NoLock(FNET_PacketQueue_NoLock *target)
{
    uint32_t cnt = _bufused;

    target->EnsureFree(cnt);
    for (; _bufused > 0; _bufused--, target->_bufused++) {
        target->_buf[target->_in_pos]._packet  = _buf[_out_pos]._packet;
        target->_buf[target->_in_pos]._context = _buf[_out_pos]._context;

        if (++target->_in_pos == target->_bufsize)
            target->_in_pos = 0;         // wrap around.
        if (++_out_pos == _bufsize)
            _out_pos = 0;                // wrap around.
    }
    assert(_out_pos == _in_pos);

    return cnt;
}

void
FNET_PacketQueue_NoLock::DiscardPackets_NoLock()
{
    for (; _bufused > 0; _bufused--) {
        _buf[_out_pos]._packet->Free();   // discard packet
        if (++_out_pos == _bufsize)
            _out_pos = 0;                   // wrap around
    }
    assert(_out_pos == _in_pos);
}

void
FNET_PacketQueue_NoLock::Print(uint32_t indent)
{
    uint32_t i   = _out_pos;
    uint32_t cnt = _bufused;

    printf("%*sFNET_PacketQueue_NoLock {\n", indent, "");
    printf("%*s  bufsize : %d\n", indent, "", _bufsize);
    printf("%*s  bufused : %d\n", indent, "", _bufused);
    printf("%*s  in_pos  : %d\n", indent, "", _in_pos);
    printf("%*s  out_pos : %d\n", indent, "", _out_pos);
    for (; cnt > 0; i++, cnt--) {
        if (i == _bufsize)
            i = 0;           // wrap around
        _buf[i]._packet->Print(indent + 2);
        _buf[i]._context.Print(indent + 2);
    }
    printf("%*s}\n", indent, "");
}

//------------------------------------------------------------------

FNET_PacketQueue::FNET_PacketQueue(uint32_t len,
                                   HP_RetCode hpRetCode)
    : FNET_PacketQueue_NoLock(len, hpRetCode),
      _lock(),
      _cond(),
      _waitCnt(0)
{
}

FNET_PacketQueue::~FNET_PacketQueue()
{
}

FNET_IPacketHandler::HP_RetCode
FNET_PacketQueue::HandlePacket(FNET_Packet  *packet,
                               FNET_Context  context)
{
    QueuePacket(packet, context);
    return _hpRetCode;
}

void
FNET_PacketQueue::QueuePacket(FNET_Packet *packet, FNET_Context context)
{
    assert(packet != nullptr);
    std::lock_guard<std::mutex> guard(_lock);
    EnsureFree();
    _buf[_in_pos]._packet = packet;  // insert packet ref.
    _buf[_in_pos]._context = context;
    if (++_in_pos == _bufsize)
        _in_pos = 0;                   // wrap around.
    _bufused++;
    if (_waitCnt >= _bufused) {        // signal waiting thread(s)
        _cond.notify_one();
    }
}

FNET_Packet*
FNET_PacketQueue::DequeuePacket(FNET_Context *context)
{
    FNET_Packet *packet = nullptr;
    std::unique_lock<std::mutex> guard(_lock);
    _waitCnt++;
    while (_bufused == 0) {
        _cond.wait(guard);
    }
    _waitCnt--;
    packet = _buf[_out_pos]._packet;
    *context = _buf[_out_pos]._context;
    if (++_out_pos == _bufsize)
        _out_pos = 0;                   // wrap around
    _bufused--;
    return packet;
}

FNET_Packet*
FNET_PacketQueue::DequeuePacket(uint32_t maxwait, FNET_Context *context)
{
    FNET_Packet *packet = nullptr;
    FastOS_Time  startTime;
    int          waitTime;

    if (maxwait > 0)
        startTime.SetNow();
    std::unique_lock<std::mutex> guard(_lock);
    if (maxwait > 0) {
        bool timeout = false;

        _waitCnt++;
        while ((_bufused == 0) && !timeout && (waitTime = (int)(maxwait - startTime.MilliSecsToNow())) > 0) {
            timeout = _cond.wait_for(guard, std::chrono::milliseconds(waitTime)) == std::cv_status::timeout;
        }
        _waitCnt--;
    }
    if (_bufused > 0) {
        packet = _buf[_out_pos]._packet;
        *context = _buf[_out_pos]._context;
        if (++_out_pos == _bufsize)
            _out_pos = 0;                   // wrap around
        _bufused--;
    }
    return packet;
}

void
FNET_PacketQueue::Print(uint32_t indent)
{
    std::lock_guard<std::mutex> guard(_lock);
    uint32_t i   = _out_pos;
    uint32_t cnt = _bufused;

    printf("%*sFNET_PacketQueue {\n", indent, "");
    printf("%*s  bufsize : %d\n", indent, "", _bufsize);
    printf("%*s  bufused : %d\n", indent, "", _bufused);
    printf("%*s  in_pos  : %d\n", indent, "", _in_pos);
    printf("%*s  out_pos : %d\n", indent, "", _out_pos);
    printf("%*s  waitCnt : %d\n", indent, "", _waitCnt);
    for (; cnt > 0; i++, cnt--) {
        if (i == _bufsize)
            i = 0;           // wrap around
        _buf[i]._packet->Print(indent + 2);
        _buf[i]._context.Print(indent + 2);
    }
    printf("%*s}\n", indent, "");
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include "astutil.h"
#include "bb.h"
#include "expr.h"
#include "stmt.h"
#include "view.h"

BasicBlock::BasicBlock(int init_id) : id(init_id) {}

#define BB_START()                              \
  basicBlock = new BasicBlock(id++)

#define BB_ADD(expr)                            \
  basicBlock->exprs.add(expr)

#define BB_ADD_LS(exprls)                       \
  for_alist(expr, exprls) {               \
    BB_ADD(expr);                               \
  }

#define BB_STOP()                               \
  fn->basicBlocks->add(basicBlock);             \
  basicBlock = NULL

#define BB_RESTART()                            \
  BB_STOP();                                    \
  BB_START()

#define BBB(stmt)                               \
  if (stmt) {                                   \
    buildBasicBlocks(fn, stmt);                 \
  }

#define BB_THREAD(in, out) \
  out->ins.add(in); \
  in->outs.add(out)

void buildBasicBlocks(FnSymbol* fn, Expr* stmt) {
  static BasicBlock* basicBlock;
  static Map<LabelSymbol*,Vec<BasicBlock*>*> gotoMaps;
  static Map<LabelSymbol*,BasicBlock*> labelMaps;
  static int id;
  if (!stmt) {
    if (fn->basicBlocks) {
      forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
        delete bb;
      }
      delete fn->basicBlocks;
    }
    fn->basicBlocks = new Vec<BasicBlock*>();
    gotoMaps.clear();
    labelMaps.clear();
    id = 0;
    BB_START();
    BBB(fn->body);
    BB_STOP();
  } else {
    if (BlockStmt* s = toBlockStmt(stmt)) {
      if (s->loopInfo) {
        BasicBlock* top = basicBlock;
        BB_RESTART();
        BB_ADD(s->loopInfo);
        BasicBlock* loopTop = basicBlock;
        for_alist(stmt, s->body) {
          BBB(stmt);
        }
        BasicBlock* loopBottom = basicBlock;
        BB_RESTART();
        BasicBlock* bottom = basicBlock;
        BB_THREAD(top, loopTop);
        BB_THREAD(loopBottom, bottom);
        BB_THREAD(loopBottom, loopTop);
        BB_THREAD(top, bottom);
      } else {
        for_alist(stmt, s->body) {
          BBB(stmt);
        }
      }
    } else if (CondStmt* s = toCondStmt(stmt)) {
      BB_ADD(s->condExpr);
      BasicBlock* top = basicBlock;
      BB_RESTART();
      BasicBlock* thenTop = basicBlock;
      BBB(s->thenStmt);
      BasicBlock* thenBottom = basicBlock;
      BB_RESTART();
      BasicBlock* elseTop = basicBlock;
      BBB(s->elseStmt);
      BasicBlock* elseBottom = basicBlock;
      BB_RESTART();
      BasicBlock* bottom = basicBlock;
      BB_THREAD(top, thenTop);
      BB_THREAD(top, elseTop);
      BB_THREAD(thenBottom, bottom);
      BB_THREAD(elseBottom, bottom);
    } else if (GotoStmt* s = toGotoStmt(stmt)) {
      LabelSymbol* label = toLabelSymbol(s->label);
      if (BasicBlock* bb = labelMaps.get(label)) {
        BB_THREAD(basicBlock, bb);
      } else {
        Vec<BasicBlock*>* vbb = gotoMaps.get(label);
        if (!vbb)
          vbb = new Vec<BasicBlock*>();
        vbb->add(basicBlock);
        gotoMaps.put(label, vbb);
      }
      BB_RESTART();
    } else {
      DefExpr* def = toDefExpr(stmt);
      if (def && toLabelSymbol(def->sym)) {
        BasicBlock* top = basicBlock;
        BB_RESTART();
        BasicBlock* bottom = basicBlock;
        BB_THREAD(top, bottom);
        LabelSymbol* label = toLabelSymbol(def->sym);
        if (Vec<BasicBlock*>* vbb = gotoMaps.get(label)) {
          forv_Vec(BasicBlock, basicBlock, *vbb) {
            BB_THREAD(basicBlock, bottom);
          }
        }
        labelMaps.put(label, bottom);
      } else
        BB_ADD(stmt);
    }
  }
}

void buildLocalsVectorMap(FnSymbol* fn,
                          Vec<Symbol*>& locals,
                          Map<Symbol*,int>& localMap) {
  int i = 0;
  forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
    forv_Vec(Expr, expr, bb->exprs) {
      if (DefExpr* def = toDefExpr(expr)) {
        if (toVarSymbol(def->sym)) {
          locals.add(def->sym);
          localMap.put(def->sym, i++);
        }
      }
    }
  }
}

void buildDefsVectorMap(FnSymbol* fn,
                        Vec<Symbol*>& locals,
                        Vec<SymExpr*>& defs,
                        Map<SymExpr*,int>& defMap) {
  int i = 0;
  forv_Vec(Symbol, local, locals) {
    forv_Vec(SymExpr, se, local->defs) {
      defs.add(se);
      defMap.put(se, i++);
    }
  }
}

void buildDefUseSets(FnSymbol* fn,
                     Vec<Symbol*>& locals,
                     Vec<SymExpr*>& useSet,
                     Vec<SymExpr*>& defSet) {
  compute_sym_uses(fn);
  forv_Vec(Symbol, local, locals) {
    forv_Vec(SymExpr, se, local->defs) {
      defSet.set_add(se);
    }
    forv_Vec(SymExpr, se, local->uses) {
      useSet.set_add(se);
    }
  }
}

//#define DEBUG_FLOW

void backwardFlowAnalysis(FnSymbol* fn,
                          Vec<Vec<bool>*>& GEN,
                          Vec<Vec<bool>*>& KILL,
                          Vec<Vec<bool>*>& IN,
                          Vec<Vec<bool>*>& OUT) {
  bool iterate = true;
  while (iterate) {
    iterate = false;
    int i = 0;
    forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
      for (int j = 0; j < IN.v[i]->n; j++) {
        bool new_in = (OUT.v[i]->v[j] & !KILL.v[i]->v[j]) | GEN.v[i]->v[j];
        if (new_in != IN.v[i]->v[j]) {
          IN.v[i]->v[j] = new_in;
          iterate = true;
        }
        bool new_out = false;
        forv_Vec(BasicBlock, bbout, bb->outs) {
          new_out = new_out | IN.v[bbout->id]->v[j];
        }
        if (new_out != OUT.v[i]->v[j]) {
          OUT.v[i]->v[j] = new_out;
          iterate = true;
        }
      }
      i++;
    }
#ifdef DEBUG_FLOW
    printf("IN\n"); printBitVectorSets(IN);
    printf("OUT\n"); printBitVectorSets(OUT);
#endif
  }
}

void forwardFlowAnalysis(FnSymbol* fn,
                         Vec<Vec<bool>*>& GEN,
                         Vec<Vec<bool>*>& KILL,
                         Vec<Vec<bool>*>& IN,
                         Vec<Vec<bool>*>& OUT,
                         bool intersect) {
  int nbbq = fn->basicBlocks->n; // size of bb queue
  int* bbq = (int*)malloc(nbbq*sizeof(int));    // bb queue
  bool* bbs = (bool*)malloc(nbbq*sizeof(bool)); // bb set (bbs[i]: is ith bb in bbq?)
  int iq = -1, nq = nbbq-1;      // index to first and last bb in bbq
  for (int i = 0; i < fn->basicBlocks->n; i++) {
    bbq[i] = i;
    bbs[i] = true;
  }
  while (iq != nq) {
    iq = (iq + 1) % nbbq;
    int i = bbq[iq];
    bbs[i] = false;
#ifdef DEBUG_FLOW
    if (iq == 0) {
      printf("IN\n"); debug_flow_print_set(IN);
      printf("OUT\n"); debug_flow_print_set(OUT);
    }
#endif
    BasicBlock* bb = fn->basicBlocks->v[i];
    bool change = false;
    for (int j = 0; j < IN.v[i]->n; j++) {
      if (bb->ins.n > 0) {
        bool new_in = intersect;
        forv_Vec(BasicBlock, bbin, bb->ins) {
          if (intersect)
            new_in = new_in & OUT.v[bbin->id]->v[j];
          else
            new_in = new_in | OUT.v[bbin->id]->v[j];
        }
        if (new_in != IN.v[i]->v[j]) {
          IN.v[i]->v[j] = new_in;
          change = true;
        }
      }
      bool new_out = (IN.v[i]->v[j] & !KILL.v[i]->v[j]) | GEN.v[i]->v[j];
      if (new_out != OUT.v[i]->v[j]) {
        OUT.v[i]->v[j] = new_out;
        change = true;
      }
    }
    if (change) {
      forv_Vec(BasicBlock, bbout, bb->outs) {
        if (!bbs[bbout->id]) {
          nq = (nq + 1) % nbbq;
          bbs[bbout->id] = true;
          bbq[nq] = bbout->id;
        }
      }
    }
  }
  free(bbq);
  free(bbs);
}

void printBasicBlocks(FnSymbol* fn) {
  forv_Vec(BasicBlock, b, *fn->basicBlocks) {
    printf("%2d:  ", b->id);
    forv_Vec(BasicBlock, bb, b->ins) {
      printf("%d ", bb->id);
    }
    printf(" >  ");
    forv_Vec(BasicBlock, bb, b->outs) {
      printf("%d ", bb->id);
    }
    printf("\n");
    forv_Vec(Expr, expr, b->exprs) {
      list_view_noline(expr);
    }
    printf("\n");
  }
}

void printLocalsVector(Vec<Symbol*> locals, Map<Symbol*,int>& localMap) {
  printf("Local Variables\n");
  forv_Vec(Symbol, local, locals) {
    printf("%2d: %s[%d]\n", localMap.get(local), local->name, local->id);
  }
  printf("\n");
}

void printDefsVector(Vec<SymExpr*> defs, Map<SymExpr*,int>& defMap) {
  printf("Variable Definitions\n");
  forv_Vec(SymExpr, def, defs) {
    printf("%2d: %s[%d] in %d\n", defMap.get(def), def->var->name,
           def->var->id, def->getStmtExpr()->id);
  }
  printf("\n");
}

void printLocalsVectorSets(Vec<Vec<bool>*>& sets, Vec<Symbol*> locals) {
  int i = 0;
  forv_Vec(Vec<bool>, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->n; j++) {
      if (set->v[j])
        printf("%s[%d] ", locals.v[j]->name, locals.v[j]->id);
    }
    printf("\n");
    i++;
  }
  printf("\n");
}

void printBitVectorSets(Vec<Vec<bool>*>& sets) {
  int i = 0;
  forv_Vec(Vec<bool>, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->n; j++) {
      printf("%d", (set->v[j]) ? 1 : 0);
      if ((j+1) % 10 == 0) printf(" ");
    }
    printf("\n");
    i++;
  }
  printf("\n");
}
<commit_msg><commit_after>#include <stdlib.h>
#include "astutil.h"
#include "bb.h"
#include "expr.h"
#include "stmt.h"
#include "view.h"

BasicBlock::BasicBlock(int init_id) : id(init_id) {}

#define BB_START()                              \
  basicBlock = new BasicBlock(id++)

#define BB_ADD(expr)                            \
  basicBlock->exprs.add(expr)

#define BB_ADD_LS(exprls)                       \
  for_alist(expr, exprls) {               \
    BB_ADD(expr);                               \
  }

#define BB_STOP()                               \
  fn->basicBlocks->add(basicBlock);             \
  basicBlock = NULL

#define BB_RESTART()                            \
  BB_STOP();                                    \
  BB_START()

#define BBB(stmt)                               \
  if (stmt) {                                   \
    buildBasicBlocks(fn, stmt);                 \
  }

#define BB_THREAD(in, out) \
  out->ins.add(in); \
  in->outs.add(out)

void buildBasicBlocks(FnSymbol* fn, Expr* stmt) {
  static BasicBlock* basicBlock;
  static Map<LabelSymbol*,Vec<BasicBlock*>*> gotoMaps;
  static Map<LabelSymbol*,BasicBlock*> labelMaps;
  static int id;
  if (!stmt) {
    if (fn->basicBlocks) {
      forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
        delete bb;
      }
      delete fn->basicBlocks;
    }
    fn->basicBlocks = new Vec<BasicBlock*>();
    gotoMaps.clear();
    labelMaps.clear();
    id = 0;
    BB_START();
    BBB(fn->body);
    BB_STOP();
  } else {
    if (BlockStmt* s = toBlockStmt(stmt)) {
      if (s->loopInfo) {
        BasicBlock* top = basicBlock;
        BB_RESTART();
        BB_ADD(s->loopInfo);
        BasicBlock* loopTop = basicBlock;
        for_alist(stmt, s->body) {
          BBB(stmt);
        }
        BasicBlock* loopBottom = basicBlock;
        BB_RESTART();
        BasicBlock* bottom = basicBlock;
        BB_THREAD(top, loopTop);
        BB_THREAD(loopBottom, bottom);
        BB_THREAD(loopBottom, loopTop);
        BB_THREAD(top, bottom);
      } else {
        for_alist(stmt, s->body) {
          BBB(stmt);
        }
      }
    } else if (CondStmt* s = toCondStmt(stmt)) {
      BB_ADD(s->condExpr);
      BasicBlock* top = basicBlock;
      BB_RESTART();
      BasicBlock* thenTop = basicBlock;
      BBB(s->thenStmt);
      BasicBlock* thenBottom = basicBlock;
      BB_RESTART();
      BasicBlock* elseTop = basicBlock;
      BBB(s->elseStmt);
      BasicBlock* elseBottom = basicBlock;
      BB_RESTART();
      BasicBlock* bottom = basicBlock;
      BB_THREAD(top, thenTop);
      BB_THREAD(top, elseTop);
      BB_THREAD(thenBottom, bottom);
      BB_THREAD(elseBottom, bottom);
    } else if (GotoStmt* s = toGotoStmt(stmt)) {
      LabelSymbol* label = toLabelSymbol(s->label);
      if (BasicBlock* bb = labelMaps.get(label)) {
        BB_THREAD(basicBlock, bb);
      } else {
        Vec<BasicBlock*>* vbb = gotoMaps.get(label);
        if (!vbb)
          vbb = new Vec<BasicBlock*>();
        vbb->add(basicBlock);
        gotoMaps.put(label, vbb);
      }
      BB_RESTART();
    } else {
      DefExpr* def = toDefExpr(stmt);
      if (def && toLabelSymbol(def->sym)) {
        BasicBlock* top = basicBlock;
        BB_RESTART();
        BasicBlock* bottom = basicBlock;
        BB_THREAD(top, bottom);
        LabelSymbol* label = toLabelSymbol(def->sym);
        if (Vec<BasicBlock*>* vbb = gotoMaps.get(label)) {
          forv_Vec(BasicBlock, basicBlock, *vbb) {
            BB_THREAD(basicBlock, bottom);
          }
        }
        labelMaps.put(label, bottom);
      } else
        BB_ADD(stmt);
    }
  }
}

void buildLocalsVectorMap(FnSymbol* fn,
                          Vec<Symbol*>& locals,
                          Map<Symbol*,int>& localMap) {
  int i = 0;
  forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
    forv_Vec(Expr, expr, bb->exprs) {
      if (DefExpr* def = toDefExpr(expr)) {
        if (toVarSymbol(def->sym)) {
          locals.add(def->sym);
          localMap.put(def->sym, i++);
        }
      }
    }
  }
}

void buildDefsVectorMap(FnSymbol* fn,
                        Vec<Symbol*>& locals,
                        Vec<SymExpr*>& defs,
                        Map<SymExpr*,int>& defMap) {
  int i = 0;
  forv_Vec(Symbol, local, locals) {
    forv_Vec(SymExpr, se, local->defs) {
      defs.add(se);
      defMap.put(se, i++);
    }
  }
}

void buildDefUseSets(FnSymbol* fn,
                     Vec<Symbol*>& locals,
                     Vec<SymExpr*>& useSet,
                     Vec<SymExpr*>& defSet) {
  compute_sym_uses(fn);
  forv_Vec(Symbol, local, locals) {
    forv_Vec(SymExpr, se, local->defs) {
      defSet.set_add(se);
    }
    forv_Vec(SymExpr, se, local->uses) {
      useSet.set_add(se);
    }
  }
}

//#define DEBUG_FLOW

void backwardFlowAnalysis(FnSymbol* fn,
                          Vec<Vec<bool>*>& GEN,
                          Vec<Vec<bool>*>& KILL,
                          Vec<Vec<bool>*>& IN,
                          Vec<Vec<bool>*>& OUT) {
  bool iterate = true;
  while (iterate) {
    iterate = false;
    int i = 0;
    forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
      for (int j = 0; j < IN.v[i]->n; j++) {
        bool new_in = (OUT.v[i]->v[j] & !KILL.v[i]->v[j]) | GEN.v[i]->v[j];
        if (new_in != IN.v[i]->v[j]) {
          IN.v[i]->v[j] = new_in;
          iterate = true;
        }
        bool new_out = false;
        forv_Vec(BasicBlock, bbout, bb->outs) {
          new_out = new_out | IN.v[bbout->id]->v[j];
        }
        if (new_out != OUT.v[i]->v[j]) {
          OUT.v[i]->v[j] = new_out;
          iterate = true;
        }
      }
      i++;
    }
#ifdef DEBUG_FLOW
    printf("IN\n"); printBitVectorSets(IN);
    printf("OUT\n"); printBitVectorSets(OUT);
#endif
  }
}

void forwardFlowAnalysis(FnSymbol* fn,
                         Vec<Vec<bool>*>& GEN,
                         Vec<Vec<bool>*>& KILL,
                         Vec<Vec<bool>*>& IN,
                         Vec<Vec<bool>*>& OUT,
                         bool intersect) {
  int nbbq = fn->basicBlocks->n; // size of bb queue
  Vec<int> bbq;
  Vec<bool> bbs;
  int iq = -1, nq = nbbq-1;      // index to first and last bb in bbq
  for (int i = 0; i < fn->basicBlocks->n; i++) {
    bbq.add(i);
    bbs.add(true);
  }
  while (iq != nq) {
    iq = (iq + 1) % nbbq;
    int i = bbq.v[iq];
    bbs.v[i] = false;
#ifdef DEBUG_FLOW
    if (iq == 0) {
      printf("IN\n"); debug_flow_print_set(IN);
      printf("OUT\n"); debug_flow_print_set(OUT);
    }
#endif
    BasicBlock* bb = fn->basicBlocks->v[i];
    bool change = false;
    for (int j = 0; j < IN.v[i]->n; j++) {
      if (bb->ins.n > 0) {
        bool new_in = intersect;
        forv_Vec(BasicBlock, bbin, bb->ins) {
          if (intersect)
            new_in = new_in & OUT.v[bbin->id]->v[j];
          else
            new_in = new_in | OUT.v[bbin->id]->v[j];
        }
        if (new_in != IN.v[i]->v[j]) {
          IN.v[i]->v[j] = new_in;
          change = true;
        }
      }
      bool new_out = (IN.v[i]->v[j] & !KILL.v[i]->v[j]) | GEN.v[i]->v[j];
      if (new_out != OUT.v[i]->v[j]) {
        OUT.v[i]->v[j] = new_out;
        change = true;
      }
    }
    if (change) {
      forv_Vec(BasicBlock, bbout, bb->outs) {
        if (!bbs.v[bbout->id]) {
          nq = (nq + 1) % nbbq;
          bbs.v[bbout->id] = true;
          bbq.v[nq] = bbout->id;
        }
      }
    }
  }
}

void printBasicBlocks(FnSymbol* fn) {
  forv_Vec(BasicBlock, b, *fn->basicBlocks) {
    printf("%2d:  ", b->id);
    forv_Vec(BasicBlock, bb, b->ins) {
      printf("%d ", bb->id);
    }
    printf(" >  ");
    forv_Vec(BasicBlock, bb, b->outs) {
      printf("%d ", bb->id);
    }
    printf("\n");
    forv_Vec(Expr, expr, b->exprs) {
      list_view_noline(expr);
    }
    printf("\n");
  }
}

void printLocalsVector(Vec<Symbol*> locals, Map<Symbol*,int>& localMap) {
  printf("Local Variables\n");
  forv_Vec(Symbol, local, locals) {
    printf("%2d: %s[%d]\n", localMap.get(local), local->name, local->id);
  }
  printf("\n");
}

void printDefsVector(Vec<SymExpr*> defs, Map<SymExpr*,int>& defMap) {
  printf("Variable Definitions\n");
  forv_Vec(SymExpr, def, defs) {
    printf("%2d: %s[%d] in %d\n", defMap.get(def), def->var->name,
           def->var->id, def->getStmtExpr()->id);
  }
  printf("\n");
}

void printLocalsVectorSets(Vec<Vec<bool>*>& sets, Vec<Symbol*> locals) {
  int i = 0;
  forv_Vec(Vec<bool>, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->n; j++) {
      if (set->v[j])
        printf("%s[%d] ", locals.v[j]->name, locals.v[j]->id);
    }
    printf("\n");
    i++;
  }
  printf("\n");
}

void printBitVectorSets(Vec<Vec<bool>*>& sets) {
  int i = 0;
  forv_Vec(Vec<bool>, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->n; j++) {
      printf("%d", (set->v[j]) ? 1 : 0);
      if ((j+1) % 10 == 0) printf(" ");
    }
    printf("\n");
    i++;
  }
  printf("\n");
}
<|endoftext|>


<commit_before>// Copyright (c) 2019-2020 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "mfx_common.h"
#if defined(MFX_ENABLE_H265_VIDEO_ENCODE) && (MFX_VERSION >= 1031)

#include "hevcehw_g12_rext.h"
#include "hevcehw_g9_legacy.h"

using namespace HEVCEHW;
using namespace HEVCEHW::Gen12;

const GUID RExt::DXVA2_Intel_Encode_HEVC_Main12 =
{ 0xd6d6bc4f, 0xd51a, 0x4712,{ 0x97, 0xe8, 0x75, 0x9, 0x17, 0xc8, 0x60, 0xfd } };
const GUID RExt::DXVA2_Intel_Encode_HEVC_Main422_12 =
{ 0x7fef652d, 0x3233, 0x44df,{ 0xac, 0xf7, 0xec, 0xfb, 0x58, 0x4d, 0xab, 0x35 } };
const GUID RExt::DXVA2_Intel_Encode_HEVC_Main444_12 =
{ 0xf8fa34b7, 0x93f5, 0x45a4,{ 0xbf, 0xc0, 0x38, 0x17, 0xce, 0xe6, 0xbb, 0x93 } };

void RExt::InitInternal(const FeatureBlocks& /*blocks*/, TPushII Push)
{
    Push(BLK_SetRecInfo
        , [](StorageRW& strg, StorageRW& local) -> mfxStatus
    {
        MFX_CHECK(!local.Contains(Gen9::Tmp::RecInfo::Key), MFX_ERR_NONE);

        auto& par = Gen9::Glob::VideoParam::Get(strg);
        mfxExtCodingOption3& CO3 = ExtBuffer::Get(par);

        bool bG12SpecificRec =
            CO3.TargetBitDepthLuma == 12
            || (CO3.TargetBitDepthLuma == 10
                && (CO3.TargetChromaFormatPlus1 == (1 + MFX_CHROMAFORMAT_YUV420)
                    || CO3.TargetChromaFormatPlus1 == (1 + MFX_CHROMAFORMAT_YUV422)));

        MFX_CHECK(bG12SpecificRec, MFX_ERR_NONE);

        const std::map<mfxU16, std::function<void(mfxFrameInfo&, mfxU16&)>> mUpdateRecInfo =
        {
            {
                mfxU16(1 + MFX_CHROMAFORMAT_YUV444)
                , [](mfxFrameInfo& rec, mfxU16& type)
                {
                    rec.FourCC = MFX_FOURCC_Y416;
                    rec.Width  = mfx::align2_value<mfxU16>(rec.Width, 256 / 4);
                    rec.Height = mfx::align2_value<mfxU16>(rec.Height * 3 / 2, 8);

                    type = (
                        MFX_MEMTYPE_FROM_ENCODE
                        | MFX_MEMTYPE_DXVA2_DECODER_TARGET
                        | MFX_MEMTYPE_INTERNAL_FRAME);
                }
            }
            , {
                mfxU16(1 + MFX_CHROMAFORMAT_YUV422)
                , [](mfxFrameInfo& rec, mfxU16& type)
                {
                    rec.FourCC = MFX_FOURCC_Y216;
                    rec.Width /= 2;
                    rec.Height *= 2;

                    type = (
                        MFX_MEMTYPE_FROM_ENCODE
                        | MFX_MEMTYPE_DXVA2_DECODER_TARGET
                        | MFX_MEMTYPE_INTERNAL_FRAME);
                }
            }
            , {
                mfxU16(1 + MFX_CHROMAFORMAT_YUV420)
                , [](mfxFrameInfo& rec, mfxU16&)
                {
                    rec.FourCC = MFX_FOURCC_NV12;
                    rec.Width = mfx::align2_value(rec.Width, 32) * 2;
                }
            }
        };

        MFX_CHECK(mUpdateRecInfo.count(CO3.TargetChromaFormatPlus1), MFX_ERR_NONE);

        auto pRI = make_storable<mfxFrameAllocRequest>(mfxFrameAllocRequest{});
        auto& rec = pRI->Info;

        rec = par.mfx.FrameInfo;

        mUpdateRecInfo.at(CO3.TargetChromaFormatPlus1)(rec, pRI->Type);

        rec.ChromaFormat   = CO3.TargetChromaFormatPlus1 - 1;
        rec.BitDepthLuma   = CO3.TargetBitDepthLuma;
        rec.BitDepthChroma = CO3.TargetBitDepthChroma;

        local.Insert(Gen9::Tmp::RecInfo::Key, std::move(pRI));

        return MFX_ERR_NONE;
    });
}

mfxStatus RExt::SetGuid(mfxVideoParam& par, StorageRW& strg)
{
    auto& fi = par.mfx.FrameInfo;
    const GUID* pGUID = nullptr;
    const mfxExtCodingOption3* pCO3 = ExtBuffer::Get(par);

    MFX_CHECK(fi.BitDepthLuma <= 12, MFX_ERR_NONE);
    MFX_CHECK(fi.BitDepthChroma <= 12, MFX_ERR_NONE);
    MFX_CHECK(!pCO3 || pCO3->TargetBitDepthLuma <= 12, MFX_ERR_NONE);
    MFX_CHECK(!pCO3 || pCO3->TargetBitDepthChroma <= 12, MFX_ERR_NONE);
    MFX_CHECK(!IsOn(par.mfx.LowPower), MFX_ERR_NONE);

    SetIf(pGUID, fi.FourCC == MFX_FOURCC_P016, &DXVA2_Intel_Encode_HEVC_Main12);
    SetIf(pGUID, fi.FourCC == MFX_FOURCC_Y216, &DXVA2_Intel_Encode_HEVC_Main422_12);
    SetIf(pGUID, fi.FourCC == MFX_FOURCC_Y416, &DXVA2_Intel_Encode_HEVC_Main444_12);

    MFX_CHECK(pGUID, MFX_ERR_NONE);

    Gen9::Glob::GUID::GetOrConstruct(strg) = *pGUID;

    return MFX_ERR_NONE;
}

void RExt::Query1NoCaps(const FeatureBlocks& /*blocks*/, TPushQ1 Push)
{
    Push(BLK_SetDefaultsCallChain
        , [this](const mfxVideoParam&, mfxVideoParam&, StorageRW& strg) -> mfxStatus
    {
        auto& defaults = Glob::Defaults::GetOrConstruct(strg);
        auto& bSet = defaults.SetForFeature[GetID()];
        MFX_CHECK(!bSet, MFX_ERR_NONE);

        defaults.CheckFourCC.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));
            return MFX_ERR_NONE;
        });

        defaults.CheckInputFormatByFourCC.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            auto&  fi      = par.mfx.FrameInfo;
            mfxU32 invalid = 0;

            invalid += CheckOrZero<mfxU16, 12, 0>(fi.BitDepthLuma);
            invalid += CheckOrZero<mfxU16, 12, 0>(fi.BitDepthChroma);
            invalid += (fi.FourCC == MFX_FOURCC_P016) && CheckOrZero<mfxU16, MFX_CHROMAFORMAT_YUV420>(fi.ChromaFormat);
            invalid += (fi.FourCC == MFX_FOURCC_Y216) && CheckOrZero<mfxU16, MFX_CHROMAFORMAT_YUV422>(fi.ChromaFormat);
            invalid += (fi.FourCC == MFX_FOURCC_Y416) && CheckOrZero<mfxU16, MFX_CHROMAFORMAT_YUV444>(fi.ChromaFormat);

            MFX_CHECK(!invalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.CheckTargetBitDepth.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            mfxExtCodingOption3* pCO3 = ExtBuffer::Get(par);

            MFX_CHECK(pCO3 && IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            mfxU32 invalid = 0;

            invalid += CheckOrZero<mfxU16, 12, 0>(pCO3->TargetBitDepthLuma);
            invalid += CheckOrZero<mfxU16, 12, 0>(pCO3->TargetBitDepthChroma);

            MFX_CHECK(!invalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.CheckFourCCByTargetFormat.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            auto   tcf = dpar.base.GetTargetChromaFormat(dpar);
            auto&  fi = par.mfx.FrameInfo;
            mfxU32 invalid = 0;

            invalid +=
                (tcf == MFX_CHROMAFORMAT_YUV444 + 1)
                && Check<mfxU32, MFX_FOURCC_Y416>(fi.FourCC);

            invalid +=
                (tcf == MFX_CHROMAFORMAT_YUV422 + 1)
                && Check<mfxU32, MFX_FOURCC_Y216, MFX_FOURCC_Y416>(fi.FourCC);

            MFX_CHECK(!invalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.CheckProfile.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            bool bInvalid = CheckOrZero<mfxU16, 0, MFX_PROFILE_HEVC_REXT>(par.mfx.CodecProfile);

            MFX_CHECK(!bInvalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.GetMaxChromaByFourCC.Push(
            [](Gen9::Defaults::TChain<mfxU16>::TExt prev
                , const Gen9::Defaults::Param& dpar)
        {
            MFX_CHECK(IsRextFourCC(dpar.mvp.mfx.FrameInfo.FourCC), prev(dpar));
            auto fcc = dpar.mvp.mfx.FrameInfo.FourCC;
            return mfxU16(
                  (fcc == MFX_FOURCC_P016) * MFX_CHROMAFORMAT_YUV420
                + (fcc == MFX_FOURCC_Y216) * MFX_CHROMAFORMAT_YUV422
                + (fcc == MFX_FOURCC_Y416) * MFX_CHROMAFORMAT_YUV444);
        });

        defaults.GetMaxBitDepthByFourCC.Push(
            [](Gen9::Defaults::TChain<mfxU16>::TExt prev
                , const Gen9::Defaults::Param& dpar)
        {
            MFX_CHECK(IsRextFourCC(dpar.mvp.mfx.FrameInfo.FourCC), prev(dpar));
            return mfxU16(12);
        });

        defaults.RunFastCopyWrapper.Push(
            [](Gen9::Defaults::TRunFastCopyWrapper::TExt prev
                , mfxFrameSurface1 &surfDst
                , mfxU16 dstMemType
                , mfxFrameSurface1 &surfSrc
                , mfxU16 srcMemType)
            {
                // convert to native shift in core.CopyFrame() if required
                surfDst.Info.Shift |=
                    surfDst.Info.FourCC == MFX_FOURCC_P016
                    || surfDst.Info.FourCC == MFX_FOURCC_Y216;

                return prev(
                     surfDst
                    , dstMemType
                    , surfSrc
                    , srcMemType);
            });

        bSet = true;

        return MFX_ERR_NONE;

    });
    Push(BLK_SetGUID
        , [this](const mfxVideoParam&, mfxVideoParam& par, StorageRW& strg) -> mfxStatus
    {
        //don't change GUID in Reset
        MFX_CHECK(!strg.Contains(Glob::RealState::Key), MFX_ERR_NONE);
        return SetGuid(par, strg);
    });
}

void RExt::Query1WithCaps(const FeatureBlocks& /*blocks*/, TPushQ1 Push)
{
    Push(BLK_CheckShift
        , [](const mfxVideoParam&, mfxVideoParam& out, StorageW&) -> mfxStatus
    {
        auto& fi = out.mfx.FrameInfo;
        bool bVideoMem = Gen9::Legacy::IsInVideoMem(out, ExtBuffer::Get(out));

        bool bNeedShift =
            (bVideoMem && !fi.Shift)
            && (   fi.FourCC == MFX_FOURCC_P016
                || fi.FourCC == MFX_FOURCC_Y216
                || fi.FourCC == MFX_FOURCC_Y416);

        SetIf(fi.Shift, bNeedShift, 1);
        MFX_CHECK(!bNeedShift, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);

        return MFX_ERR_NONE;
    });

    Push(BLK_HardcodeCaps
        , [](const mfxVideoParam&, mfxVideoParam&, StorageRW& strg) -> mfxStatus
    {
        Gen9::Glob::EncodeCaps::Get(strg).MaxEncodedBitDepth = 2;
        return MFX_ERR_NONE;
    });
}

#endif //defined(MFX_ENABLE_H265_VIDEO_ENCODE)
<commit_msg>[HEVCe] Fixed recon surface creation for P010<commit_after>// Copyright (c) 2019-2020 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "mfx_common.h"
#if defined(MFX_ENABLE_H265_VIDEO_ENCODE) && (MFX_VERSION >= 1031)

#include "hevcehw_g12_rext.h"
#include "hevcehw_g9_legacy.h"

using namespace HEVCEHW;
using namespace HEVCEHW::Gen12;

const GUID RExt::DXVA2_Intel_Encode_HEVC_Main12 =
{ 0xd6d6bc4f, 0xd51a, 0x4712,{ 0x97, 0xe8, 0x75, 0x9, 0x17, 0xc8, 0x60, 0xfd } };
const GUID RExt::DXVA2_Intel_Encode_HEVC_Main422_12 =
{ 0x7fef652d, 0x3233, 0x44df,{ 0xac, 0xf7, 0xec, 0xfb, 0x58, 0x4d, 0xab, 0x35 } };
const GUID RExt::DXVA2_Intel_Encode_HEVC_Main444_12 =
{ 0xf8fa34b7, 0x93f5, 0x45a4,{ 0xbf, 0xc0, 0x38, 0x17, 0xce, 0xe6, 0xbb, 0x93 } };

void RExt::InitInternal(const FeatureBlocks& /*blocks*/, TPushII Push)
{
    Push(BLK_SetRecInfo
        , [](StorageRW& strg, StorageRW& local) -> mfxStatus
    {
        auto& par = Gen9::Glob::VideoParam::Get(strg);
        mfxExtCodingOption3& CO3 = ExtBuffer::Get(par);

        bool bG12SpecificRec =
            CO3.TargetBitDepthLuma == 12
            || (CO3.TargetBitDepthLuma == 10
                && (CO3.TargetChromaFormatPlus1 == (1 + MFX_CHROMAFORMAT_YUV420)
                    || CO3.TargetChromaFormatPlus1 == (1 + MFX_CHROMAFORMAT_YUV422)));

        MFX_CHECK(bG12SpecificRec, MFX_ERR_NONE);

        local.Erase(Gen9::Tmp::RecInfo::Key);

        const std::map<mfxU16, std::function<void(mfxFrameInfo&, mfxU16&)>> mUpdateRecInfo =
        {
            {
                mfxU16(1 + MFX_CHROMAFORMAT_YUV444)
                , [](mfxFrameInfo& rec, mfxU16& type)
                {
                    rec.FourCC = MFX_FOURCC_Y416;
                    rec.Width  = mfx::align2_value<mfxU16>(rec.Width, 256 / 4);
                    rec.Height = mfx::align2_value<mfxU16>(rec.Height * 3 / 2, 8);

                    type = (
                        MFX_MEMTYPE_FROM_ENCODE
                        | MFX_MEMTYPE_DXVA2_DECODER_TARGET
                        | MFX_MEMTYPE_INTERNAL_FRAME);
                }
            }
            , {
                mfxU16(1 + MFX_CHROMAFORMAT_YUV422)
                , [](mfxFrameInfo& rec, mfxU16& type)
                {
                    rec.FourCC = MFX_FOURCC_Y216;
                    rec.Width /= 2;
                    rec.Height *= 2;

                    type = (
                        MFX_MEMTYPE_FROM_ENCODE
                        | MFX_MEMTYPE_DXVA2_DECODER_TARGET
                        | MFX_MEMTYPE_INTERNAL_FRAME);
                }
            }
            , {
                mfxU16(1 + MFX_CHROMAFORMAT_YUV420)
                , [](mfxFrameInfo& rec, mfxU16&)
                {
                    rec.FourCC = MFX_FOURCC_NV12;
                    rec.Width = mfx::align2_value(rec.Width, 32) * 2;
                }
            }
        };

        MFX_CHECK(mUpdateRecInfo.count(CO3.TargetChromaFormatPlus1), MFX_ERR_NONE);

        auto pRI = make_storable<mfxFrameAllocRequest>(mfxFrameAllocRequest{});
        auto& rec = pRI->Info;

        rec = par.mfx.FrameInfo;

        mUpdateRecInfo.at(CO3.TargetChromaFormatPlus1)(rec, pRI->Type);

        rec.ChromaFormat   = CO3.TargetChromaFormatPlus1 - 1;
        rec.BitDepthLuma   = CO3.TargetBitDepthLuma;
        rec.BitDepthChroma = CO3.TargetBitDepthChroma;

        local.Insert(Gen9::Tmp::RecInfo::Key, std::move(pRI));

        return MFX_ERR_NONE;
    });
}

mfxStatus RExt::SetGuid(mfxVideoParam& par, StorageRW& strg)
{
    auto& fi = par.mfx.FrameInfo;
    const GUID* pGUID = nullptr;
    const mfxExtCodingOption3* pCO3 = ExtBuffer::Get(par);

    MFX_CHECK(fi.BitDepthLuma <= 12, MFX_ERR_NONE);
    MFX_CHECK(fi.BitDepthChroma <= 12, MFX_ERR_NONE);
    MFX_CHECK(!pCO3 || pCO3->TargetBitDepthLuma <= 12, MFX_ERR_NONE);
    MFX_CHECK(!pCO3 || pCO3->TargetBitDepthChroma <= 12, MFX_ERR_NONE);
    MFX_CHECK(!IsOn(par.mfx.LowPower), MFX_ERR_NONE);

    SetIf(pGUID, fi.FourCC == MFX_FOURCC_P016, &DXVA2_Intel_Encode_HEVC_Main12);
    SetIf(pGUID, fi.FourCC == MFX_FOURCC_Y216, &DXVA2_Intel_Encode_HEVC_Main422_12);
    SetIf(pGUID, fi.FourCC == MFX_FOURCC_Y416, &DXVA2_Intel_Encode_HEVC_Main444_12);

    MFX_CHECK(pGUID, MFX_ERR_NONE);

    Gen9::Glob::GUID::GetOrConstruct(strg) = *pGUID;

    return MFX_ERR_NONE;
}

void RExt::Query1NoCaps(const FeatureBlocks& /*blocks*/, TPushQ1 Push)
{
    Push(BLK_SetDefaultsCallChain
        , [this](const mfxVideoParam&, mfxVideoParam&, StorageRW& strg) -> mfxStatus
    {
        auto& defaults = Glob::Defaults::GetOrConstruct(strg);
        auto& bSet = defaults.SetForFeature[GetID()];
        MFX_CHECK(!bSet, MFX_ERR_NONE);

        defaults.CheckFourCC.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));
            return MFX_ERR_NONE;
        });

        defaults.CheckInputFormatByFourCC.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            auto&  fi      = par.mfx.FrameInfo;
            mfxU32 invalid = 0;

            invalid += CheckOrZero<mfxU16, 12, 0>(fi.BitDepthLuma);
            invalid += CheckOrZero<mfxU16, 12, 0>(fi.BitDepthChroma);
            invalid += (fi.FourCC == MFX_FOURCC_P016) && CheckOrZero<mfxU16, MFX_CHROMAFORMAT_YUV420>(fi.ChromaFormat);
            invalid += (fi.FourCC == MFX_FOURCC_Y216) && CheckOrZero<mfxU16, MFX_CHROMAFORMAT_YUV422>(fi.ChromaFormat);
            invalid += (fi.FourCC == MFX_FOURCC_Y416) && CheckOrZero<mfxU16, MFX_CHROMAFORMAT_YUV444>(fi.ChromaFormat);

            MFX_CHECK(!invalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.CheckTargetBitDepth.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            mfxExtCodingOption3* pCO3 = ExtBuffer::Get(par);

            MFX_CHECK(pCO3 && IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            mfxU32 invalid = 0;

            invalid += CheckOrZero<mfxU16, 12, 0>(pCO3->TargetBitDepthLuma);
            invalid += CheckOrZero<mfxU16, 12, 0>(pCO3->TargetBitDepthChroma);

            MFX_CHECK(!invalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.CheckFourCCByTargetFormat.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            auto   tcf = dpar.base.GetTargetChromaFormat(dpar);
            auto&  fi = par.mfx.FrameInfo;
            mfxU32 invalid = 0;

            invalid +=
                (tcf == MFX_CHROMAFORMAT_YUV444 + 1)
                && Check<mfxU32, MFX_FOURCC_Y416>(fi.FourCC);

            invalid +=
                (tcf == MFX_CHROMAFORMAT_YUV422 + 1)
                && Check<mfxU32, MFX_FOURCC_Y216, MFX_FOURCC_Y416>(fi.FourCC);

            MFX_CHECK(!invalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.CheckProfile.Push(
            [](Gen9::Defaults::TCheckAndFix::TExt prev
                , const Gen9::Defaults::Param& dpar
                , mfxVideoParam& par)
        {
            MFX_CHECK(IsRextFourCC(par.mfx.FrameInfo.FourCC), prev(dpar, par));

            bool bInvalid = CheckOrZero<mfxU16, 0, MFX_PROFILE_HEVC_REXT>(par.mfx.CodecProfile);

            MFX_CHECK(!bInvalid, MFX_ERR_UNSUPPORTED);
            return MFX_ERR_NONE;
        });

        defaults.GetMaxChromaByFourCC.Push(
            [](Gen9::Defaults::TChain<mfxU16>::TExt prev
                , const Gen9::Defaults::Param& dpar)
        {
            MFX_CHECK(IsRextFourCC(dpar.mvp.mfx.FrameInfo.FourCC), prev(dpar));
            auto fcc = dpar.mvp.mfx.FrameInfo.FourCC;
            return mfxU16(
                  (fcc == MFX_FOURCC_P016) * MFX_CHROMAFORMAT_YUV420
                + (fcc == MFX_FOURCC_Y216) * MFX_CHROMAFORMAT_YUV422
                + (fcc == MFX_FOURCC_Y416) * MFX_CHROMAFORMAT_YUV444);
        });

        defaults.GetMaxBitDepthByFourCC.Push(
            [](Gen9::Defaults::TChain<mfxU16>::TExt prev
                , const Gen9::Defaults::Param& dpar)
        {
            MFX_CHECK(IsRextFourCC(dpar.mvp.mfx.FrameInfo.FourCC), prev(dpar));
            return mfxU16(12);
        });

        defaults.RunFastCopyWrapper.Push(
            [](Gen9::Defaults::TRunFastCopyWrapper::TExt prev
                , mfxFrameSurface1 &surfDst
                , mfxU16 dstMemType
                , mfxFrameSurface1 &surfSrc
                , mfxU16 srcMemType)
            {
                // convert to native shift in core.CopyFrame() if required
                surfDst.Info.Shift |=
                    surfDst.Info.FourCC == MFX_FOURCC_P016
                    || surfDst.Info.FourCC == MFX_FOURCC_Y216;

                return prev(
                     surfDst
                    , dstMemType
                    , surfSrc
                    , srcMemType);
            });

        bSet = true;

        return MFX_ERR_NONE;

    });
    Push(BLK_SetGUID
        , [this](const mfxVideoParam&, mfxVideoParam& par, StorageRW& strg) -> mfxStatus
    {
        //don't change GUID in Reset
        MFX_CHECK(!strg.Contains(Glob::RealState::Key), MFX_ERR_NONE);
        return SetGuid(par, strg);
    });
}

void RExt::Query1WithCaps(const FeatureBlocks& /*blocks*/, TPushQ1 Push)
{
    Push(BLK_CheckShift
        , [](const mfxVideoParam&, mfxVideoParam& out, StorageW&) -> mfxStatus
    {
        auto& fi = out.mfx.FrameInfo;
        bool bVideoMem = Gen9::Legacy::IsInVideoMem(out, ExtBuffer::Get(out));

        bool bNeedShift =
            (bVideoMem && !fi.Shift)
            && (   fi.FourCC == MFX_FOURCC_P016
                || fi.FourCC == MFX_FOURCC_Y216
                || fi.FourCC == MFX_FOURCC_Y416);

        SetIf(fi.Shift, bNeedShift, 1);
        MFX_CHECK(!bNeedShift, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);

        return MFX_ERR_NONE;
    });

    Push(BLK_HardcodeCaps
        , [](const mfxVideoParam&, mfxVideoParam&, StorageRW& strg) -> mfxStatus
    {
        Gen9::Glob::EncodeCaps::Get(strg).MaxEncodedBitDepth = 2;
        return MFX_ERR_NONE;
    });
}

#endif //defined(MFX_ENABLE_H265_VIDEO_ENCODE)
<|endoftext|>


<commit_before>#include "demo-common.h"
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h> //For Glib::build_filename().
#include <iostream>

#ifdef GLIBMM_WIN32

#undef DEMOCODEDIR

// TODO: Apply scorched earth tactics on code below.
static char *
get_democodedir(void)
{
  static char *result = NULL;

  if (result == NULL)
    {
      result = g_win32_get_package_installation_directory_of_module(0);
      if (result == NULL)
	result = "unknown-location";

      result = g_strconcat (result, "\\share\\gtkmm-2.4\\demo", NULL);
    }

  return result;
}

#define DEMOCODEDIR get_democodedir()

#endif // GLIBMM_WIN32

/**
 * demo_find_file:
 * @base: base filename
 *
 * Looks for @base first in the current directory, then in the
 * location where gtkmm will be installed on make install,
 * returns the first file found.
 *
 * Return value: the filename, if found, else throws a Glib::FileError.
 **/
std::string demo_find_file(const std::string& base)
{
  if(Glib::file_test("gtk-logo-rgb.gif", Glib::FILE_TEST_EXISTS) &&
      Glib::file_test (base, Glib::FILE_TEST_EXISTS))
  {
    return base;
  }
  else
  {
    std::string filename = Glib::build_filename(DEMOCODEDIR, base);
    if(!Glib::file_test(filename, Glib::FILE_TEST_EXISTS))
    {
      Glib::ustring msg = "Cannot find demo data file " + base;

      throw Glib::FileError(Glib::FileError::NO_SUCH_ENTITY, msg);
      return Glib::ustring();
    }

    return filename;
  }
}

<commit_msg>Demos: Fix Demo Data Path on Windows<commit_after>#include "demo-common.h"
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h> //For Glib::build_filename().
#include <iostream>

#ifdef GLIBMM_WIN32

#undef DEMOCODEDIR

// TODO: Apply scorched earth tactics on code below.
static char *
get_democodedir(void)
{
  static char *result = NULL;

  if (result == NULL)
    {
      result = g_win32_get_package_installation_directory_of_module(0);
      if (result == NULL)
	result = "unknown-location";

      result = g_strconcat (result, "\\share\\gtkmm-3.0\\demo", NULL);
    }

  return result;
}

#define DEMOCODEDIR get_democodedir()

#endif // GLIBMM_WIN32

/**
 * demo_find_file:
 * @base: base filename
 *
 * Looks for @base first in the current directory, then in the
 * location where gtkmm will be installed on make install,
 * returns the first file found.
 *
 * Return value: the filename, if found, else throws a Glib::FileError.
 **/
std::string demo_find_file(const std::string& base)
{
  if(Glib::file_test("gtk-logo-rgb.gif", Glib::FILE_TEST_EXISTS) &&
      Glib::file_test (base, Glib::FILE_TEST_EXISTS))
  {
    return base;
  }
  else
  {
    std::string filename = Glib::build_filename(DEMOCODEDIR, base);
    if(!Glib::file_test(filename, Glib::FILE_TEST_EXISTS))
    {
      Glib::ustring msg = "Cannot find demo data file " + base;

      throw Glib::FileError(Glib::FileError::NO_SUCH_ENTITY, msg);
      return Glib::ustring();
    }

    return filename;
  }
}

<|endoftext|>