<commit_before>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/

#include "otbVectorImage.h"
#include "itkMacro.h"
#include <iostream>
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiChannelExtractROI.h"

int otbImageFileWriterWithExtendedOptionBox(int argc, char* argv[])
{
  // Verify the number of parameters in the command line
  const std::string inputFilename = argv[1];
  const std::string outputFilename = argv[2];

  const unsigned int startx = atoi(argv[3]);
  const unsigned int starty = atoi(argv[4]);
  const unsigned int sizex = atoi(argv[5]);
  const unsigned int sizey = atoi(argv[6]);
  const std::string separator = ":";

  typedef float InputPixelType;
  typedef float OutputPixelType;

  typedef otb::VectorImage<InputPixelType, 2> InputImageType;

  typedef typename InputImageType::PixelType   PixelType;

  typedef otb::MultiChannelExtractROI<InputImageType::InternalPixelType,
                                      InputImageType::InternalPixelType> ExtractROIFilterType;

  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::ImageFileWriter<InputImageType> WriterType;

  typedef itk::ImageRegionIterator< InputImageType >       IteratorType;
  typedef itk::ImageRegionConstIterator< InputImageType >  ConstIteratorType;

  ReaderType::Pointer reader = ReaderType::New();
  ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(inputFilename);

  //Build output filename with extended box
  std::ostringstream outputFilenameExtended;
  outputFilenameExtended
                         << outputFilename
                         << "?&box=" << startx << separator
                         << starty << separator
                         << sizex << separator
                         << sizey
                         ;

  std::cout << "Output image with user defined path " << outputFilenameExtended.str() << std::endl;

  writer->SetFileName(outputFilenameExtended.str());
  writer->SetInput(reader->GetOutput());

  extractROIFilter->SetStartX(startx);
  extractROIFilter->SetStartY(starty);
  extractROIFilter->SetSizeX(sizex);
  extractROIFilter->SetSizeY(sizey);
  extractROIFilter->SetInput(reader->GetOutput());

  writer->Update();
  extractROIFilter->Update();

  ReaderType::Pointer reader2 = ReaderType::New();
  reader2->SetFileName(outputFilename);

  reader2->Update();

  typename InputImageType::ConstPointer readImage = reader2->GetOutput();
  typename InputImageType::ConstPointer extractImage = extractROIFilter->GetOutput();

  ConstIteratorType ritr( readImage, readImage->GetLargestPossibleRegion() );
  ConstIteratorType extractitr( extractImage, extractImage->GetLargestPossibleRegion() );

  ritr.GoToBegin();
  extractitr.GoToBegin();

  std::cout << "Comparing the pixel values.. :" << std::endl;

  while( !ritr.IsAtEnd() &&  !extractitr.IsAtEnd() )
    {
    if( ritr.Get() != extractitr.Get() )
      {
      std::cerr << "Pixel comparison failed at index = " << ritr.GetIndex() << std::endl;
      std::cerr << "Expected pixel value " << extractitr.Get() << std::endl;
      std::cerr << "Read Image pixel value " << ritr.Get() << std::endl;
      return EXIT_FAILURE;
      }
    ++extractitr;
    ++ritr;
    }

  std::cout << std::endl;
  std::cout << "Test PASSED !" << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>STYLE<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/

#include "otbVectorImage.h"
#include "itkMacro.h"
#include <iostream>
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiChannelExtractROI.h"

int otbImageFileWriterWithExtendedOptionBox(int argc, char* argv[])
{
  // Verify the number of parameters in the command line
  const std::string inputFilename = argv[1];
  const std::string outputFilename = argv[2];

  const unsigned int startx = atoi(argv[3]);
  const unsigned int starty = atoi(argv[4]);
  const unsigned int sizex = atoi(argv[5]);
  const unsigned int sizey = atoi(argv[6]);
  const std::string separator = ":";

  typedef float InputPixelType;
  typedef float OutputPixelType;

  typedef otb::VectorImage<InputPixelType, 2> InputImageType;

  typedef typename InputImageType::PixelType   PixelType;

  typedef otb::MultiChannelExtractROI<InputImageType::InternalPixelType,
                                      InputImageType::InternalPixelType> ExtractROIFilterType;

  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::ImageFileWriter<InputImageType> WriterType;

  typedef itk::ImageRegionIterator< InputImageType >       IteratorType;
  typedef itk::ImageRegionConstIterator< InputImageType >  ConstIteratorType;

  ReaderType::Pointer reader = ReaderType::New();
  ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(inputFilename);

  //Build output filename with extended box
  std::ostringstream outputFilenameExtended;
  outputFilenameExtended
                         << outputFilename
                         << "?&box=" << startx << separator
                         << starty << separator
                         << sizex << separator
                         << sizey
                        ;

  std::cout << "Output image with user defined path " << outputFilenameExtended.str() << std::endl;

  writer->SetFileName(outputFilenameExtended.str());
  writer->SetInput(reader->GetOutput());

  extractROIFilter->SetStartX(startx);
  extractROIFilter->SetStartY(starty);
  extractROIFilter->SetSizeX(sizex);
  extractROIFilter->SetSizeY(sizey);
  extractROIFilter->SetInput(reader->GetOutput());

  writer->Update();
  extractROIFilter->Update();

  ReaderType::Pointer reader2 = ReaderType::New();
  reader2->SetFileName(outputFilename);

  reader2->Update();

  typename InputImageType::ConstPointer readImage = reader2->GetOutput();
  typename InputImageType::ConstPointer extractImage = extractROIFilter->GetOutput();

  ConstIteratorType ritr( readImage, readImage->GetLargestPossibleRegion() );
  ConstIteratorType extractitr( extractImage, extractImage->GetLargestPossibleRegion() );

  ritr.GoToBegin();
  extractitr.GoToBegin();

  std::cout << "Comparing the pixel values.. :" << std::endl;

  while( !ritr.IsAtEnd() &&  !extractitr.IsAtEnd() )
    {
    if( ritr.Get() != extractitr.Get() )
      {
      std::cerr << "Pixel comparison failed at index = " << ritr.GetIndex() << std::endl;
      std::cerr << "Expected pixel value " << extractitr.Get() << std::endl;
      std::cerr << "Read Image pixel value " << ritr.Get() << std::endl;
      return EXIT_FAILURE;
      }
    ++extractitr;
    ++ritr;
    }

  std::cout << std::endl;
  std::cout << "Test PASSED !" << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "gibbs_sampling.h"
#include "single_node_sampler.h"
#include "binary_format.h"
#include "common.h"
#include "timer.h"
#include <fstream>
#include <memory>
#include <unistd.h>

namespace dd {

GibbsSampling::GibbsSampling(std::unique_ptr<CompiledFactorGraph> p_cfg,
                             const Weight weights[], const CmdParser &opts)
    : weights(weights), opts(opts) {
  // the highest node number available
  n_numa_nodes = numa_max_node();

  // if n_datacopy is valid, use it, otherwise, use numa_max_node
  if (opts.n_datacopy >= 1 && opts.n_datacopy <= n_numa_nodes + 1) {
    n_numa_nodes = opts.n_datacopy - 1;
  }

  // max possible threads per NUMA node
  n_thread_per_numa = (sysconf(_SC_NPROCESSORS_CONF)) / (n_numa_nodes + 1);
  // n_thread_per_numa = 1;

  // copy factor graphs
  for (int i = 0; i <= n_numa_nodes; ++i) {
    numa_run_on_node(i);
    numa_set_localalloc();

    std::cout << "CREATE CFG ON NODE ..." << i << std::endl;
    sampler.push_back(SingleNodeSampler(
        std::unique_ptr<CompiledFactorGraph>(
            i == 0 ? p_cfg.release() : new CompiledFactorGraph(*p_cfg)),
        weights, n_thread_per_numa /* TODO fold this into opts */, i, opts));
  }
};

void GibbsSampling::inference(const int &n_epoch, const bool is_quiet) {
  Timer t_total;

  Timer t;
  int nvar = sampler[0].fg.size.num_variables;
  int nnode = n_numa_nodes + 1;

  // inference epochs
  for (int i_epoch = 0; i_epoch < n_epoch; i_epoch++) {
    if (!is_quiet) {
      std::cout << std::setprecision(2) << "INFERENCE EPOCH " << i_epoch * nnode
                << "~" << ((i_epoch + 1) * nnode) << "...." << std::flush;
    }

    // restart timer
    t.restart();

    // sample
    for (int i = 0; i < nnode; i++) {
      sampler[i].sample(i_epoch);
    }

    // wait for samplers to finish
    for (int i = 0; i < nnode; i++) {
      sampler[i].wait();
    }

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << "" << elapsed << " sec.";
      std::cout << "," << (nvar * nnode) / elapsed << " vars/sec" << std::endl;
    }
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL INFERENCE TIME: " << elapsed << " sec." << std::endl;
}

void GibbsSampling::learn(const int &n_epoch, const int &n_sample_per_epoch,
                          const double &stepsize, const double &decay,
                          const double reg_param, const bool is_quiet,
                          const regularization reg) {
  Timer t_total;

  double current_stepsize = stepsize;
  std::cerr << sampler[0].fg.size << std::endl;

  Timer t;
  int nvar = sampler[0].fg.size.num_variables;
  int nnode = n_numa_nodes + 1;
  int nweight = sampler[0].fg.size.num_weights;

  std::cerr << sampler[0].fg.size << std::endl;

  std::unique_ptr<double[]> ori_weights(new double[nweight]);
  memcpy(ori_weights.get(), sampler[0].infrs.weight_values.get(),
         sizeof(*ori_weights.get()) * nweight);
  std::cerr << sampler[0].fg.size << std::endl;

  // learning epochs
  for (int i_epoch = 0; i_epoch < n_epoch; i_epoch++) {
    if (!is_quiet) {
      std::cout << std::setprecision(2) << "LEARNING EPOCH " << i_epoch * nnode
                << "~" << ((i_epoch + 1) * nnode) << "...." << std::flush;
    }

    t.restart();

    // performs stochastic gradient descent with sampling
    for (int i = 0; i < nnode; i++) {
      sampler[i].sample_sgd(current_stepsize);
    }

    // wait the samplers to finish
    for (int i = 0; i < nnode; i++) {
      sampler[i].wait_sgd();
    }

    // sum the weights and store in the first factor graph
    // the average weights will be calculated and assigned to all factor graphs
    for (int i = 1; i <= n_numa_nodes; i++) {
      auto &sampler_other = sampler[i];
      for (int j = 0; j < nweight; j++) {
        sampler[0].infrs.weight_values[j] +=
            sampler_other.infrs.weight_values[j];
      }
    }

    // calculate average weights and regularize weights
    for (int j = 0; j < nweight; j++) {
      sampler[0].infrs.weight_values[j] /= nnode;
      if (!sampler[0].infrs.weights_isfixed[j]) {
        if (reg == REG_L2)
          sampler[0].infrs.weight_values[j] *=
              (1.0 / (1.0 + reg_param * current_stepsize));
        else  // l1
          sampler[0].infrs.weight_values[j] +=
              reg_param * (sampler[0].infrs.weight_values[j] < 0);
      }
    }

    // set weights for other factor graph to be the same as the first factor
    // graph
    for (int i = 1; i <= n_numa_nodes; i++) {
      auto &sampler_other = sampler[i];
      for (int j = 0; j < nweight; j++) {
        if (!sampler[0].infrs.weights_isfixed[j]) {
          sampler_other.infrs.weight_values[j] =
              sampler[0].infrs.weight_values[j];
        }
      }
    }

    // calculate the norms of the difference of weights from the current epoch
    // and last epoch
    double lmax = -1000000;
    double l2 = 0.0;
    for (int i = 0; i < nweight; i++) {
      double diff = fabs(ori_weights[i] - sampler[0].infrs.weight_values[i]);
      ori_weights[i] = sampler[0].infrs.weight_values[i];
      l2 += diff * diff;
      if (lmax < diff) {
        lmax = diff;
      }
    }
    lmax = lmax / current_stepsize;

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << "" << elapsed << " sec.";
      std::cout << "," << (nvar * nnode) / elapsed << " vars/sec."
                << ",stepsize=" << current_stepsize << ",lmax=" << lmax
                << ",l2=" << sqrt(l2) / current_stepsize << std::endl;
    }

    current_stepsize = current_stepsize * decay;
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL LEARNING TIME: " << elapsed << " sec." << std::endl;
}

void GibbsSampling::dump_weights(const bool is_quiet) {
  // learning weights snippets
  if (!is_quiet) {
    std::cout << "LEARNING SNIPPETS (QUERY WEIGHTS):" << std::endl;
    int ct = 0;
    for (long i = 0; i < sampler[0].infrs.nweights; i++) {
      ct++;
      std::cout << "   " << i << " " << sampler[0].infrs.weight_values[i]
                << std::endl;
      if (ct % 10 == 0) {
        break;
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump learned weights
  std::string filename_text;
  filename_text = opts.output_folder + "/inference_result.out.weights.text";

  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;

  std::ofstream fout_text(filename_text.c_str());
  for (long i = 0; i < sampler[0].infrs.nweights; i++) {
    fout_text << i << " " << sampler[0].infrs.weight_values[i] << std::endl;
  }
  fout_text.close();
}

void GibbsSampling::aggregate_results_and_dump(const bool is_quiet) {
  // sum of variable assignments
  std::unique_ptr<double[]> agg_means(
      new double[sampler[0].fg.size.num_variables]);
  // number of samples
  std::unique_ptr<double[]> agg_nsamples(
      new double[sampler[0].fg.size.num_variables]);
  std::unique_ptr<int[]> multinomial_tallies(
      new int[sampler[0].infrs.ntallies]);

  for (long i = 0; i < sampler[0].fg.size.num_variables; i++) {
    agg_means[i] = 0;
    agg_nsamples[i] = 0;
  }

  for (long i = 0; i < sampler[0].infrs.ntallies; i++) {
    multinomial_tallies[i] = 0;
  }

  // sum variable assignments over all NUMA nodes
  for (int i = 0; i <= n_numa_nodes; i++) {
    const InferenceResult &infrs = sampler[i].infrs;
    for (long j = 0; j < sampler[i].fg.size.num_variables; ++j) {
      const Variable &variable = sampler[i].fg.variables[j];
      agg_means[variable.id] += infrs.agg_means[variable.id];
      agg_nsamples[variable.id] += infrs.agg_nsamples[variable.id];
    }
    for (long j = 0; j < infrs.ntallies; ++j) {
      multinomial_tallies[j] += infrs.multinomial_tallies[j];
    }
  }

  // inference snippets
  if (!is_quiet) {
    std::cout << "INFERENCE SNIPPETS (QUERY VARIABLES):" << std::endl;
    int ct = 0;
    for (long i = 0; i < sampler[0].fg.size.num_variables; i++) {
      const Variable &variable = sampler[0].fg.variables[i];
      if (!variable.is_evid || opts.should_sample_evidence) {
        ct++;
        std::cout << "   " << variable.id
                  << "  NSAMPLE=" << agg_nsamples[variable.id] << std::endl;
        switch (variable.domain_type) {
          case DTYPE_BOOLEAN:
            std::cout << "        @ 1 -> EXP="
                      << agg_means[variable.id] / agg_nsamples[variable.id]
                      << std::endl;
            break;

          case DTYPE_MULTINOMIAL: {
            const auto &print_snippet = [&multinomial_tallies, &agg_nsamples,
                                         variable](int domain_value,
                                                   int domain_index) {
              std::cout << "        @ " << domain_value << " -> EXP="
                        << 1.0 * multinomial_tallies[variable.n_start_i_tally +
                                                     domain_index] /
                               agg_nsamples[variable.id]
                        << std::endl;
            };
            if (variable.domain_map) {  // sparse
              for (const auto &entry : *variable.domain_map)
                print_snippet(entry.first, entry.second);
            } else {  // dense case
              for (size_t j = 0; j < variable.cardinality; j++)
                print_snippet(j, j);
            }
            break;
          }

          default:
            abort();
        }

        if (ct % 10 == 0) {
          break;
        }
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump inference results
  std::string filename_text;
  filename_text = opts.output_folder + "/inference_result.out.text";

  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;
  std::ofstream fout_text(filename_text.c_str());
  for (long i = 0; i < sampler[0].fg.size.num_variables; i++) {
    const Variable &variable = sampler[0].fg.variables[i];
    if (variable.is_evid && !opts.should_sample_evidence) {
      continue;
    }

    switch (variable.domain_type) {
      case DTYPE_BOOLEAN: {
        fout_text << variable.id << " " << 1 << " "
                  << (agg_means[variable.id] / agg_nsamples[variable.id])
                  << std::endl;
        break;
      }

      case DTYPE_MULTINOMIAL: {
        const auto &print_result = [&fout_text, &multinomial_tallies,
                                    &agg_nsamples, variable](int domain_value,
                                                             int domain_index) {
          fout_text
              << variable.id << " " << domain_value << " "
              << (1.0 *
                  multinomial_tallies[variable.n_start_i_tally + domain_index] /
                  agg_nsamples[variable.id])
              << std::endl;
        };
        if (variable.domain_map) {  // sparse
          for (const auto &entry : *variable.domain_map)
            print_result(entry.first, entry.second);
        } else {  // dense
          for (size_t j = 0; j < variable.cardinality; j++) print_result(j, j);
        }
        break;
      }

      default:
        abort();
    }
  }
  fout_text.close();

  if (!is_quiet) {
    // show a histogram of inference results
    std::cout << "INFERENCE CALIBRATION (QUERY BINS):" << std::endl;
    std::vector<int> abc;
    for (int i = 0; i <= 10; i++) {
      abc.push_back(0);
    }
    int bad = 0;
    for (long i = 0; i < sampler[0].fg.size.num_variables; i++) {
      const Variable &variable = sampler[0].fg.variables[i];
      if (variable.is_evid && !opts.should_sample_evidence) {
        continue;
      }
      int bin = (int)(agg_means[variable.id] / agg_nsamples[variable.id] * 10);
      if (bin >= 0 && bin <= 10) {
        abc[bin]++;
      } else {
        bad++;
      }
    }
    abc[9] += abc[10];
    for (int i = 0; i < 10; i++) {
      std::cout << "PROB BIN 0." << i << "~0." << (i + 1) << "  -->  # "
                << abc[i] << std::endl;
    }
  }
}

}  // namespace dd
<commit_msg>Aliases `sampler[0]`<commit_after>#include "gibbs_sampling.h"
#include "single_node_sampler.h"
#include "binary_format.h"
#include "common.h"
#include "timer.h"
#include <fstream>
#include <memory>
#include <unistd.h>

namespace dd {

GibbsSampling::GibbsSampling(std::unique_ptr<CompiledFactorGraph> p_cfg,
                             const Weight weights[], const CmdParser &opts)
    : weights(weights), opts(opts) {
  // the highest node number available
  n_numa_nodes = numa_max_node();

  // if n_datacopy is valid, use it, otherwise, use numa_max_node
  if (opts.n_datacopy >= 1 && opts.n_datacopy <= n_numa_nodes + 1) {
    n_numa_nodes = opts.n_datacopy - 1;
  }

  // max possible threads per NUMA node
  n_thread_per_numa = (sysconf(_SC_NPROCESSORS_CONF)) / (n_numa_nodes + 1);
  // n_thread_per_numa = 1;

  // copy factor graphs
  for (int i = 0; i <= n_numa_nodes; ++i) {
    numa_run_on_node(i);
    numa_set_localalloc();

    std::cout << "CREATE CFG ON NODE ..." << i << std::endl;
    sampler.push_back(SingleNodeSampler(
        std::unique_ptr<CompiledFactorGraph>(
            i == 0 ? p_cfg.release() : new CompiledFactorGraph(*p_cfg)),
        weights, n_thread_per_numa /* TODO fold this into opts */, i, opts));
  }
};

void GibbsSampling::inference(const int &n_epoch, const bool is_quiet) {
  Timer t_total;

  Timer t;
  int nvar = sampler[0].fg.size.num_variables;
  int nnode = n_numa_nodes + 1;

  for (auto &s : sampler)
      s.infrs.clear_variabletally();

  // inference epochs
  for (int i_epoch = 0; i_epoch < n_epoch; i_epoch++) {
    if (!is_quiet) {
      std::cout << std::setprecision(2) << "INFERENCE EPOCH " << i_epoch * nnode
                << "~" << ((i_epoch + 1) * nnode) << "...." << std::flush;
    }

    // restart timer
    t.restart();

    // sample
    for (int i = 0; i < nnode; i++) {
      sampler[i].sample(i_epoch);
    }

    // wait for samplers to finish
    for (int i = 0; i < nnode; i++) {
      sampler[i].wait();
    }

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << "" << elapsed << " sec.";
      std::cout << "," << (nvar * nnode) / elapsed << " vars/sec" << std::endl;
    }
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL INFERENCE TIME: " << elapsed << " sec." << std::endl;
}

void GibbsSampling::learn(const int &n_epoch, const int &n_sample_per_epoch,
                          const double &stepsize, const double &decay,
                          const double reg_param, const bool is_quiet,
                          const regularization reg) {
  Timer t_total;

  double current_stepsize = stepsize;
  std::cerr << sampler[0].fg.size << std::endl;

  Timer t;
  int nvar = sampler[0].fg.size.num_variables;
  int nnode = n_numa_nodes + 1;
  int nweight = sampler[0].fg.size.num_weights;

  std::cerr << sampler[0].fg.size << std::endl;

  InferenceResult &infrs = sampler[0].infrs;

  std::unique_ptr<double[]> ori_weights(new double[nweight]);
  memcpy(ori_weights.get(), infrs.weight_values.get(),
         sizeof(*ori_weights.get()) * nweight);
  std::cerr << sampler[0].fg.size << std::endl;

  // learning epochs
  for (int i_epoch = 0; i_epoch < n_epoch; i_epoch++) {
    if (!is_quiet) {
      std::cout << std::setprecision(2) << "LEARNING EPOCH " << i_epoch * nnode
                << "~" << ((i_epoch + 1) * nnode) << "...." << std::flush;
    }

    t.restart();

    // performs stochastic gradient descent with sampling
    for (int i = 0; i < nnode; i++) {
      sampler[i].sample_sgd(current_stepsize);
    }

    // wait the samplers to finish
    for (int i = 0; i < nnode; i++) {
      sampler[i].wait_sgd();
    }

    // sum the weights and store in the first factor graph
    // the average weights will be calculated and assigned to all factor graphs
    for (int i = 1; i <= n_numa_nodes; i++) {
      auto &sampler_other = sampler[i];
      for (int j = 0; j < nweight; j++) {
        infrs.weight_values[j] +=
            sampler_other.infrs.weight_values[j];
      }
    }

    // calculate average weights and regularize weights
    for (int j = 0; j < nweight; j++) {
      infrs.weight_values[j] /= nnode;
      if (!infrs.weights_isfixed[j]) {
        if (reg == REG_L2)
          infrs.weight_values[j] *=
              (1.0 / (1.0 + reg_param * current_stepsize));
        else  // l1
          infrs.weight_values[j] +=
              reg_param * (infrs.weight_values[j] < 0);
      }
    }

    // set weights for other factor graph to be the same as the first factor
    // graph
    for (int i = 1; i <= n_numa_nodes; i++) {
      auto &sampler_other = sampler[i];
      for (int j = 0; j < nweight; j++) {
        if (!infrs.weights_isfixed[j]) {
          sampler_other.infrs.weight_values[j] =
              infrs.weight_values[j];
        }
      }
    }

    // calculate the norms of the difference of weights from the current epoch
    // and last epoch
    double lmax = -1000000;
    double l2 = 0.0;
    for (int i = 0; i < nweight; i++) {
      double diff = fabs(ori_weights[i] - infrs.weight_values[i]);
      ori_weights[i] = infrs.weight_values[i];
      l2 += diff * diff;
      if (lmax < diff) {
        lmax = diff;
      }
    }
    lmax = lmax / current_stepsize;

    double elapsed = t.elapsed();
    if (!is_quiet) {
      std::cout << "" << elapsed << " sec.";
      std::cout << "," << (nvar * nnode) / elapsed << " vars/sec."
                << ",stepsize=" << current_stepsize << ",lmax=" << lmax
                << ",l2=" << sqrt(l2) / current_stepsize << std::endl;
    }

    current_stepsize = current_stepsize * decay;
  }

  double elapsed = t_total.elapsed();
  std::cout << "TOTAL LEARNING TIME: " << elapsed << " sec." << std::endl;
}

void GibbsSampling::dump_weights(const bool is_quiet) {
  // learning weights snippets
  InferenceResult &infrs = sampler[0].infrs;

  if (!is_quiet) {
    std::cout << "LEARNING SNIPPETS (QUERY WEIGHTS):" << std::endl;
    int ct = 0;
    for (long i = 0; i < infrs.nweights; i++) {
      ct++;
      std::cout << "   " << i << " " << infrs.weight_values[i]
                << std::endl;
      if (ct % 10 == 0) {
        break;
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump learned weights
  std::string filename_text;
  filename_text = opts.output_folder + "/inference_result.out.weights.text";

  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;

  std::ofstream fout_text(filename_text.c_str());
  for (long i = 0; i < infrs.nweights; i++) {
    fout_text << i << " " << infrs.weight_values[i] << std::endl;
  }
  fout_text.close();
}

void GibbsSampling::aggregate_results_and_dump(const bool is_quiet) {
InferenceResult &infrs = sampler[0].infrs;
  // sum of variable assignments
  std::unique_ptr<double[]> agg_means(
      new double[infrs.nvars]);
  // number of samples
  std::unique_ptr<double[]> agg_nsamples(
      new double[infrs.nvars]);
  std::unique_ptr<int[]> multinomial_tallies(
      new int[infrs.ntallies]);

  for (long i = 0; i < infrs.nvars; i++) {
    agg_means[i] = 0;
    agg_nsamples[i] = 0;
  }

  for (long i = 0; i < infrs.ntallies; i++) {
    multinomial_tallies[i] = 0;
  }

  // sum variable assignments over all NUMA nodes
  for (int i = 0; i <= n_numa_nodes; i++) {
    const InferenceResult &infrs_i = sampler[i].infrs;
    for (long j = 0; j < infrs_i.nvars; ++j) {
      const Variable &variable = sampler[i].fg.variables[j];
      agg_means[variable.id] += infrs_i.agg_means[variable.id];
      agg_nsamples[variable.id] += infrs_i.agg_nsamples[variable.id];
    }
    for (long j = 0; j < infrs_i.ntallies; ++j) {
      multinomial_tallies[j] += infrs_i.multinomial_tallies[j];
    }
  }

  // inference snippets
  if (!is_quiet) {
    std::cout << "INFERENCE SNIPPETS (QUERY VARIABLES):" << std::endl;
    int ct = 0;
    for (long i = 0; i < infrs.nvars; i++) {
      const Variable &variable = sampler[0].fg.variables[i];
      if (!variable.is_evid || opts.should_sample_evidence) {
        ct++;
        std::cout << "   " << variable.id
                  << "  NSAMPLE=" << agg_nsamples[variable.id] << std::endl;
        switch (variable.domain_type) {
          case DTYPE_BOOLEAN:
            std::cout << "        @ 1 -> EXP="
                      << agg_means[variable.id] / agg_nsamples[variable.id]
                      << std::endl;
            break;

          case DTYPE_MULTINOMIAL: {
            const auto &print_snippet = [&multinomial_tallies, &agg_nsamples,
                                         variable](int domain_value,
                                                   int domain_index) {
              std::cout << "        @ " << domain_value << " -> EXP="
                        << 1.0 * multinomial_tallies[variable.n_start_i_tally +
                                                     domain_index] /
                               agg_nsamples[variable.id]
                        << std::endl;
            };
            if (variable.domain_map) {  // sparse
              for (const auto &entry : *variable.domain_map)
                print_snippet(entry.first, entry.second);
            } else {  // dense case
              for (size_t j = 0; j < variable.cardinality; j++)
                print_snippet(j, j);
            }
            break;
          }

          default:
            abort();
        }

        if (ct % 10 == 0) {
          break;
        }
      }
    }
    std::cout << "   ..." << std::endl;
  }

  // dump inference results
  std::string filename_text;
  filename_text = opts.output_folder + "/inference_result.out.text";

  std::cout << "DUMPING... TEXT    : " << filename_text << std::endl;
  std::ofstream fout_text(filename_text.c_str());
  for (long i = 0; i < sampler[0].fg.size.num_variables; i++) {
    const Variable &variable = sampler[0].fg.variables[i];
    if (variable.is_evid && !opts.should_sample_evidence) {
      continue;
    }

    switch (variable.domain_type) {
      case DTYPE_BOOLEAN: {
        fout_text << variable.id << " " << 1 << " "
                  << (agg_means[variable.id] / agg_nsamples[variable.id])
                  << std::endl;
        break;
      }

      case DTYPE_MULTINOMIAL: {
        const auto &print_result = [&fout_text, &multinomial_tallies,
                                    &agg_nsamples, variable](int domain_value,
                                                             int domain_index) {
          fout_text
              << variable.id << " " << domain_value << " "
              << (1.0 *
                  multinomial_tallies[variable.n_start_i_tally + domain_index] /
                  agg_nsamples[variable.id])
              << std::endl;
        };
        if (variable.domain_map) {  // sparse
          for (const auto &entry : *variable.domain_map)
            print_result(entry.first, entry.second);
        } else {  // dense
          for (size_t j = 0; j < variable.cardinality; j++) print_result(j, j);
        }
        break;
      }

      default:
        abort();
    }
  }
  fout_text.close();

  if (!is_quiet) {
    // show a histogram of inference results
    std::cout << "INFERENCE CALIBRATION (QUERY BINS):" << std::endl;
    std::vector<int> abc;
    for (int i = 0; i <= 10; i++) {
      abc.push_back(0);
    }
    int bad = 0;
    for (long i = 0; i < sampler[0].fg.size.num_variables; i++) {
      const Variable &variable = sampler[0].fg.variables[i];
      if (variable.is_evid && !opts.should_sample_evidence) {
        continue;
      }
      int bin = (int)(agg_means[variable.id] / agg_nsamples[variable.id] * 10);
      if (bin >= 0 && bin <= 10) {
        abc[bin]++;
      } else {
        bad++;
      }
    }
    abc[9] += abc[10];
    for (int i = 0; i < 10; i++) {
      std::cout << "PROB BIN 0." << i << "~0." << (i + 1) << "  -->  # "
                << abc[i] << std::endl;
    }
  }
}

}  // namespace dd
<|endoftext|>


<commit_before>/*
 * Copyright 2011-2013 Branimir Karadzic. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include "bgfx_p.h"

#if (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL)
#	include "renderer_gl.h"

#	if BX_PLATFORM_LINUX

namespace bgfx
{
#	define GL_IMPORT(_optional, _proto, _func) _proto _func
#		include "glimports.h"
#	undef GL_IMPORT

	static ::Display* s_display;
	static ::Window s_window;

	void x11SetDisplayWindow(::Display* _display, ::Window _window)
	{
		s_display = _display;
		s_window = _window;
	}

	void GlContext::create(uint32_t _width, uint32_t _height)
	{
		XLockDisplay(s_display);

		int major, minor;
		bool version = glXQueryVersion(s_display, &major, &minor);
		BGFX_FATAL(version, Fatal::UnableToInitialize, "Failed to query GLX version");
		BGFX_FATAL( (major == 1 && minor >= 3) || major > 1
				, Fatal::UnableToInitialize
				, "GLX version is not >=1.3 (%d.%d)."
				, major
				, minor
				);

		const int attrsGlx[] =
		{
			GLX_RENDER_TYPE, GLX_RGBA_BIT,
			GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
			GLX_DOUBLEBUFFER, true,
			GLX_RED_SIZE, 8,
			GLX_BLUE_SIZE, 8,
			GLX_GREEN_SIZE, 8,
			GLX_ALPHA_SIZE, 8,
			GLX_DEPTH_SIZE, 24,
			GLX_STENCIL_SIZE, 8,
			None,
		};

		// Find suitable config
		GLXFBConfig bestConfig = NULL;

		int numConfigs;
		GLXFBConfig* configs = glXChooseFBConfig(s_display, DefaultScreen(s_display), attrsGlx, &numConfigs);

		BX_TRACE("glX num configs %d", numConfigs);

		XVisualInfo* visualInfo = 0;
		for (int ii = 0; ii < numConfigs; ++ii)
		{
			visualInfo = glXGetVisualFromFBConfig(s_display, configs[ii]);
			if (NULL != visualInfo)
			{
				BX_TRACE("---");
				bool valid = true;
				for (uint32_t attr = 6; attr < countof(attrsGlx)-1 && attrsGlx[attr] != None; attr += 2)
				{
					int value;
					glXGetFBConfigAttrib(s_display, configs[ii], attrsGlx[attr], &value);
					BX_TRACE("glX %d/%d %2d: %4x, %8x (%8x%s)"
							, ii
							, numConfigs
							, attr/2
							, attrsGlx[attr]
							, value
							, attrsGlx[attr + 1]
							, value < attrsGlx[attr + 1] ? " *" : ""
							);

					if (value < attrsGlx[attr + 1])
					{
						valid = false;
#if !BGFX_CONFIG_DEBUG
						break;
#endif // BGFX_CONFIG_DEBUG
					}
				}

				if (valid)
				{
					bestConfig = configs[ii];
					break;
				}
			}

			XFree(visualInfo);
			visualInfo = 0;
		}

		XFree(configs);
		BGFX_FATAL(visualInfo, Fatal::UnableToInitialize, "Failed to find a suitable X11 display configuration.");

		BX_TRACE("Create GL 2.1 context.");
		m_context = glXCreateContext(s_display, visualInfo, 0, GL_TRUE);
		BGFX_FATAL(NULL != m_context, Fatal::UnableToInitialize, "Failed to create GL 2.1 context.");

		XFree(visualInfo);

#if BGFX_CONFIG_RENDERER_OPENGL >= 31
		typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
		glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
		if (NULL != glXCreateContextAttribsARB)
		{
			BX_TRACE("Create GL 3.1 context.");
			const int contextAttrs[] =
			{
				GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
				GLX_CONTEXT_MINOR_VERSION_ARB, 1,
				GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
				0,
			};

			GLXContext context = glXCreateContextAttribsARB(s_display, bestConfig, 0, true, contextAttrs);

			if (NULL != context)
			{
				glXDestroyContext(s_display, m_context);
				m_context = context;
			}
		}
#else
		BX_UNUSED(bestConfig);
#endif // BGFX_CONFIG_RENDERER_OPENGL >= 31

		XUnlockDisplay(s_display);

		import();

		glXMakeCurrent(s_display, s_window, m_context);
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glXSwapBuffers(s_display, s_window);
	}

	void GlContext::destroy()
	{
		glXMakeCurrent(s_display, 0, 0);
		glXDestroyContext(s_display, m_context);
	}

	void GlContext::resize(uint32_t _width, uint32_t _height)
	{
	}

	void GlContext::swap()
	{
		glXMakeCurrent(s_display, s_window, m_context);
		glXSwapBuffers(s_display, s_window);
	}

	void GlContext::import()
	{
#	define GL_IMPORT(_optional, _proto, _func) \
	{ \
		_func = (_proto)glXGetProcAddress((const GLubyte*)#_func); \
		BGFX_FATAL(_optional || NULL != _func, Fatal::UnableToInitialize, "Failed to create OpenGL context. glXGetProcAddress %s", #_func); \
	}
#	include "glimports.h"
#	undef GL_IMPORT
	}

} // namespace bgfx

#	endif // BX_PLATFORM_LINUX
#endif // (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL)

<commit_msg>GLX: Removed alpha from backbuffer attributes. Fix for NV issue#23.<commit_after>/*
 * Copyright 2011-2013 Branimir Karadzic. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include "bgfx_p.h"

#if (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL)
#	include "renderer_gl.h"

#	if BX_PLATFORM_LINUX

namespace bgfx
{
#	define GL_IMPORT(_optional, _proto, _func) _proto _func
#		include "glimports.h"
#	undef GL_IMPORT

	static ::Display* s_display;
	static ::Window s_window;

	void x11SetDisplayWindow(::Display* _display, ::Window _window)
	{
		s_display = _display;
		s_window = _window;
	}

	void GlContext::create(uint32_t _width, uint32_t _height)
	{
		XLockDisplay(s_display);

		int major, minor;
		bool version = glXQueryVersion(s_display, &major, &minor);
		BGFX_FATAL(version, Fatal::UnableToInitialize, "Failed to query GLX version");
		BGFX_FATAL( (major == 1 && minor >= 3) || major > 1
				, Fatal::UnableToInitialize
				, "GLX version is not >=1.3 (%d.%d)."
				, major
				, minor
				);

		const int attrsGlx[] =
		{
			GLX_RENDER_TYPE, GLX_RGBA_BIT,
			GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
			GLX_DOUBLEBUFFER, true,
			GLX_RED_SIZE, 8,
			GLX_BLUE_SIZE, 8,
			GLX_GREEN_SIZE, 8,
//			GLX_ALPHA_SIZE, 8,
			GLX_DEPTH_SIZE, 24,
			GLX_STENCIL_SIZE, 8,
			0,
		};

		// Find suitable config
		GLXFBConfig bestConfig = NULL;

		int numConfigs;
		GLXFBConfig* configs = glXChooseFBConfig(s_display, DefaultScreen(s_display), attrsGlx, &numConfigs);

		BX_TRACE("glX num configs %d", numConfigs);

		XVisualInfo* visualInfo = 0;
		for (int ii = 0; ii < numConfigs; ++ii)
		{
			visualInfo = glXGetVisualFromFBConfig(s_display, configs[ii]);
			if (NULL != visualInfo)
			{
				BX_TRACE("---");
				bool valid = true;
				for (uint32_t attr = 6; attr < countof(attrsGlx)-1 && attrsGlx[attr] != None; attr += 2)
				{
					int value;
					glXGetFBConfigAttrib(s_display, configs[ii], attrsGlx[attr], &value);
					BX_TRACE("glX %d/%d %2d: %4x, %8x (%8x%s)"
							, ii
							, numConfigs
							, attr/2
							, attrsGlx[attr]
							, value
							, attrsGlx[attr + 1]
							, value < attrsGlx[attr + 1] ? " *" : ""
							);

					if (value < attrsGlx[attr + 1])
					{
						valid = false;
#if !BGFX_CONFIG_DEBUG
						break;
#endif // BGFX_CONFIG_DEBUG
					}
				}

				if (valid)
				{
					bestConfig = configs[ii];
					break;
				}
			}

			XFree(visualInfo);
			visualInfo = 0;
		}

		XFree(configs);
		BGFX_FATAL(visualInfo, Fatal::UnableToInitialize, "Failed to find a suitable X11 display configuration.");

		BX_TRACE("Create GL 2.1 context.");
		m_context = glXCreateContext(s_display, visualInfo, 0, GL_TRUE);
		BGFX_FATAL(NULL != m_context, Fatal::UnableToInitialize, "Failed to create GL 2.1 context.");

		XFree(visualInfo);

#if BGFX_CONFIG_RENDERER_OPENGL >= 31
		typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
		glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
		if (NULL != glXCreateContextAttribsARB)
		{
			BX_TRACE("Create GL 3.1 context.");
			const int contextAttrs[] =
			{
				GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
				GLX_CONTEXT_MINOR_VERSION_ARB, 1,
				GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
				0,
			};

			GLXContext context = glXCreateContextAttribsARB(s_display, bestConfig, 0, true, contextAttrs);

			if (NULL != context)
			{
				glXDestroyContext(s_display, m_context);
				m_context = context;
			}
		}
#else
		BX_UNUSED(bestConfig);
#endif // BGFX_CONFIG_RENDERER_OPENGL >= 31

		XUnlockDisplay(s_display);

		import();

		glXMakeCurrent(s_display, s_window, m_context);
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glXSwapBuffers(s_display, s_window);
	}

	void GlContext::destroy()
	{
		glXMakeCurrent(s_display, 0, 0);
		glXDestroyContext(s_display, m_context);
	}

	void GlContext::resize(uint32_t _width, uint32_t _height)
	{
	}

	void GlContext::swap()
	{
		glXMakeCurrent(s_display, s_window, m_context);
		glXSwapBuffers(s_display, s_window);
	}

	void GlContext::import()
	{
#	define GL_IMPORT(_optional, _proto, _func) \
	{ \
		_func = (_proto)glXGetProcAddress((const GLubyte*)#_func); \
		BGFX_FATAL(_optional || NULL != _func, Fatal::UnableToInitialize, "Failed to create OpenGL context. glXGetProcAddress %s", #_func); \
	}
#	include "glimports.h"
#	undef GL_IMPORT
	}

} // namespace bgfx

#	endif // BX_PLATFORM_LINUX
#endif // (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL)

<|endoftext|>


<commit_before>//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OptParserEmitter.h"
#include "Record.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;

static int StrCmpOptionName(const char *A, const char *B) {
  char a = *A, b = *B;
  while (a == b) {
    if (a == '\0')
      return 0;

    a = *++A;
    b = *++B;
  }

  if (a == '\0') // A is a prefix of B.
    return 1;
  if (b == '\0') // B is a prefix of A.
    return -1;

  // Otherwise lexicographic.
  return (a < b) ? -1 : 1;
}

static int CompareOptionRecords(const void *Av, const void *Bv) {
  const Record *A = *(Record**) Av;
  const Record *B = *(Record**) Bv;

  // Sentinel options preceed all others and are only ordered by precedence.
  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  if (ASent != BSent)
    return ASent ? -1 : 1;

  // Compare options by name, unless they are sentinels.
  if (!ASent)
    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
                                   B->getValueAsString("Name").c_str()))
    return Cmp;

  // Then by the kind precedence;
  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
  assert(APrec != BPrec && "Options are equivalent!");
  return APrec < BPrec ? -1 : 1;
}

static const std::string getOptionName(const Record &R) {
  // Use the record name unless EnumName is defined.
  if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
    return R.getName();

  return R.getValueAsString("EnumName");
}

static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
  OS << '"';
  OS.write_escaped(Str);
  OS << '"';
  return OS;
}

void OptParserEmitter::run(raw_ostream &OS) {
  // Get the option groups and options.
  const std::vector<Record*> &Groups =
    Records.getAllDerivedDefinitions("OptionGroup");
  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");

  if (GenDefs) {
    OS << "\
//=== TableGen'erated File - Option Parsing Definitions ---------*- C++ -*-===//\n \
//\n\
// Option Parsing Definitions\n\
//\n\
// Automatically generated file, do not edit!\n\
//\n\
//===----------------------------------------------------------------------===//\n";
  } else {
    OS << "\
//=== TableGen'erated File - Option Parsing Table ---------------*- C++ -*-===//\n \
//\n\
// Option Parsing Definitions\n\
//\n\
// Automatically generated file, do not edit!\n\
//\n\
//===----------------------------------------------------------------------===//\n";
  }
  OS << "\n";

  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
  if (GenDefs) {
    OS << "#ifndef OPTION\n";
    OS << "#error \"Define OPTION prior to including this file!\"\n";
    OS << "#endif\n\n";

    OS << "/////////\n";
    OS << "// Groups\n\n";
    for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
      const Record &R = *Groups[i];

      // Start a single option entry.
      OS << "OPTION(";

      // The option string.
      OS << '"' << R.getValueAsString("Name") << '"';

      // The option identifier name.
      OS  << ", "<< getOptionName(R);

      // The option kind.
      OS << ", Group";

      // The containing option group (if any).
      OS << ", ";
      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
        OS << getOptionName(*DI->getDef());
      else
        OS << "INVALID";

      // The other option arguments (unused for groups).
      OS << ", INVALID, 0, 0, 0, 0)\n";
    }
    OS << "\n";

    OS << "//////////\n";
    OS << "// Options\n\n";
    for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
      const Record &R = *Opts[i];

      // Start a single option entry.
      OS << "OPTION(";

      // The option string.
      write_cstring(OS, R.getValueAsString("Name"));

      // The option identifier name.
      OS  << ", "<< getOptionName(R);

      // The option kind.
      OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");

      // The containing option group (if any).
      OS << ", ";
      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
        OS << getOptionName(*DI->getDef());
      else
        OS << "INVALID";

      // The option alias (if any).
      OS << ", ";
      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
        OS << getOptionName(*DI->getDef());
      else
        OS << "INVALID";

      // The option flags.
      const ListInit *LI = R.getValueAsListInit("Flags");
      if (LI->empty()) {
        OS << ", 0";
      } else {
        OS << ", ";
        for (unsigned i = 0, e = LI->size(); i != e; ++i) {
          if (i)
            OS << " | ";
          OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
        }
      }

      // The option parameter field.
      OS << ", " << R.getValueAsInt("NumArgs");

      // The option help text.
      if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
        OS << ",\n";
        OS << "       ";
        write_cstring(OS, R.getValueAsString("HelpText"));
      } else
        OS << ", 0";

      // The option meta-variable name.
      OS << ", ";
      if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
        write_cstring(OS, R.getValueAsString("MetaVarName"));
      else
        OS << "0";

      OS << ")\n";
    }
  }
}
<commit_msg>OptParser: Emit HelpText field for option groups.<commit_after>//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OptParserEmitter.h"
#include "Record.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;

static int StrCmpOptionName(const char *A, const char *B) {
  char a = *A, b = *B;
  while (a == b) {
    if (a == '\0')
      return 0;

    a = *++A;
    b = *++B;
  }

  if (a == '\0') // A is a prefix of B.
    return 1;
  if (b == '\0') // B is a prefix of A.
    return -1;

  // Otherwise lexicographic.
  return (a < b) ? -1 : 1;
}

static int CompareOptionRecords(const void *Av, const void *Bv) {
  const Record *A = *(Record**) Av;
  const Record *B = *(Record**) Bv;

  // Sentinel options preceed all others and are only ordered by precedence.
  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
  if (ASent != BSent)
    return ASent ? -1 : 1;

  // Compare options by name, unless they are sentinels.
  if (!ASent)
    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
                                   B->getValueAsString("Name").c_str()))
    return Cmp;

  // Then by the kind precedence;
  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
  assert(APrec != BPrec && "Options are equivalent!");
  return APrec < BPrec ? -1 : 1;
}

static const std::string getOptionName(const Record &R) {
  // Use the record name unless EnumName is defined.
  if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
    return R.getName();

  return R.getValueAsString("EnumName");
}

static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
  OS << '"';
  OS.write_escaped(Str);
  OS << '"';
  return OS;
}

void OptParserEmitter::run(raw_ostream &OS) {
  // Get the option groups and options.
  const std::vector<Record*> &Groups =
    Records.getAllDerivedDefinitions("OptionGroup");
  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");

  if (GenDefs) {
    OS << "\
//=== TableGen'erated File - Option Parsing Definitions ---------*- C++ -*-===//\n \
//\n\
// Option Parsing Definitions\n\
//\n\
// Automatically generated file, do not edit!\n\
//\n\
//===----------------------------------------------------------------------===//\n";
  } else {
    OS << "\
//=== TableGen'erated File - Option Parsing Table ---------------*- C++ -*-===//\n \
//\n\
// Option Parsing Definitions\n\
//\n\
// Automatically generated file, do not edit!\n\
//\n\
//===----------------------------------------------------------------------===//\n";
  }
  OS << "\n";

  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
  if (GenDefs) {
    OS << "#ifndef OPTION\n";
    OS << "#error \"Define OPTION prior to including this file!\"\n";
    OS << "#endif\n\n";

    OS << "/////////\n";
    OS << "// Groups\n\n";
    for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
      const Record &R = *Groups[i];

      // Start a single option entry.
      OS << "OPTION(";

      // The option string.
      OS << '"' << R.getValueAsString("Name") << '"';

      // The option identifier name.
      OS  << ", "<< getOptionName(R);

      // The option kind.
      OS << ", Group";

      // The containing option group (if any).
      OS << ", ";
      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
        OS << getOptionName(*DI->getDef());
      else
        OS << "INVALID";

      // The other option arguments (unused for groups).
      OS << ", INVALID, 0, 0";

      // The option help text.
      if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
        OS << ",\n";
        OS << "       ";
        write_cstring(OS, R.getValueAsString("HelpText"));
      } else
        OS << ", 0";

      // The option meta-variable name (unused).
      OS << ", 0)\n";
    }
    OS << "\n";

    OS << "//////////\n";
    OS << "// Options\n\n";
    for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
      const Record &R = *Opts[i];

      // Start a single option entry.
      OS << "OPTION(";

      // The option string.
      write_cstring(OS, R.getValueAsString("Name"));

      // The option identifier name.
      OS  << ", "<< getOptionName(R);

      // The option kind.
      OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");

      // The containing option group (if any).
      OS << ", ";
      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
        OS << getOptionName(*DI->getDef());
      else
        OS << "INVALID";

      // The option alias (if any).
      OS << ", ";
      if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
        OS << getOptionName(*DI->getDef());
      else
        OS << "INVALID";

      // The option flags.
      const ListInit *LI = R.getValueAsListInit("Flags");
      if (LI->empty()) {
        OS << ", 0";
      } else {
        OS << ", ";
        for (unsigned i = 0, e = LI->size(); i != e; ++i) {
          if (i)
            OS << " | ";
          OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
        }
      }

      // The option parameter field.
      OS << ", " << R.getValueAsInt("NumArgs");

      // The option help text.
      if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
        OS << ",\n";
        OS << "       ";
        write_cstring(OS, R.getValueAsString("HelpText"));
      } else
        OS << ", 0";

      // The option meta-variable name.
      OS << ", ";
      if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
        write_cstring(OS, R.getValueAsString("MetaVarName"));
      else
        OS << "0";

      OS << ")\n";
    }
  }
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file data_validator_group.cpp
 *
 * A data validation group to identify anomalies in data streams
 *
 * @author Lorenz Meier <lorenz@px4.io>
 */

#include "data_validator_group.h"
#include <ecl.h>
#include <cfloat>

DataValidatorGroup::DataValidatorGroup(unsigned siblings)
{
	DataValidator *next = nullptr;
	DataValidator *prev = nullptr;

	for (unsigned i = 0; i < siblings; i++) {
		next = new DataValidator();

		if (i == 0) {
			_first = next;

		} else {
			prev->setSibling(next);
		}

		prev = next;
	}

	_last = next;

	if (_first) {
		_timeout_interval_us = _first->get_timeout();
	}
}

DataValidatorGroup::~DataValidatorGroup()
{
	while (_first) {
		DataValidator *next = _first->sibling();
		delete (_first);
		_first = next;
	}
}

DataValidator *DataValidatorGroup::add_new_validator()
{
	DataValidator *validator = new DataValidator();

	if (!validator) {
		return nullptr;
	}

	_last->setSibling(validator);
	_last = validator;
	_last->set_timeout(_timeout_interval_us);
	return _last;
}

void
DataValidatorGroup::set_timeout(uint32_t timeout_interval_us)
{
	DataValidator *next = _first;

	while (next != nullptr) {
		next->set_timeout(timeout_interval_us);
		next = next->sibling();
	}

	_timeout_interval_us = timeout_interval_us;
}

void
DataValidatorGroup::set_equal_value_threshold(uint32_t threshold)
{
	DataValidator *next = _first;

	while (next != nullptr) {
		next->set_equal_value_threshold(threshold);
		next = next->sibling();
	}
}

void
DataValidatorGroup::put(unsigned index, uint64_t timestamp, const float val[3], uint64_t error_count, int priority)
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (i == index) {
			next->put(timestamp, val, error_count, priority);
			break;
		}

		next = next->sibling();
		i++;
	}
}

float *
DataValidatorGroup::get_best(uint64_t timestamp, int *index)
{
	DataValidator *next = _first;

	// XXX This should eventually also include voting
	int pre_check_best = _curr_best;
	float pre_check_confidence = 1.0f;
	int pre_check_prio = -1;
	float max_confidence = -1.0f;
	int max_priority = -1000;
	int max_index = -1;
	DataValidator *best = nullptr;

	unsigned i = 0;

	while (next != nullptr) {
		float confidence = next->confidence(timestamp);

		if (static_cast<int>(i) == pre_check_best) {
			pre_check_prio = next->priority();
			pre_check_confidence = confidence;
		}

		/*
		 * Switch if:
		 * 1) the confidence is higher and priority is equal or higher
		 * 2) the confidence is no less than 1% different and the priority is higher
		 */
		if ((((max_confidence < MIN_REGULAR_CONFIDENCE) && (confidence >= MIN_REGULAR_CONFIDENCE)) ||
		     (confidence > max_confidence && (next->priority() >= max_priority)) ||
		     (fabsf(confidence - max_confidence) < 0.01f && (next->priority() > max_priority))
		    ) && (confidence > 0.0f)) {

			max_index = i;
			max_confidence = confidence;
			max_priority = next->priority();
			best = next;
		}

		next = next->sibling();
		i++;
	}

	/* the current best sensor is not matching the previous best sensor,
	 * or the only sensor went bad */
	if (max_index != _curr_best || ((max_confidence < FLT_EPSILON) && (_curr_best >= 0))) {

		bool true_failsafe = true;

		/* check whether the switch was a failsafe or preferring a higher priority sensor */
		if (pre_check_prio != -1 && pre_check_prio < max_priority &&
		    fabsf(pre_check_confidence - max_confidence) < 0.1f) {
			/* this is not a failover */
			true_failsafe = false;
			/* reset error flags, this is likely a hotplug sensor coming online late */
			best->reset_state();
		}

		/* if we're no initialized, initialize the bookkeeping but do not count a failsafe */
		if (_curr_best < 0) {
			_prev_best = max_index;

		} else {
			/* we were initialized before, this is a real failsafe */
			_prev_best = pre_check_best;

			if (true_failsafe) {
				_toggle_count++;

				/* if this is the first time, log when we failed */
				if (_first_failover_time == 0) {
					_first_failover_time = timestamp;
				}
			}
		}

		/* for all cases we want to keep a record of the best index */
		_curr_best = max_index;
	}

	*index = max_index;
	return (best) ? best->value() : nullptr;
}

float
DataValidatorGroup::get_vibration_factor(uint64_t timestamp)
{
	DataValidator *next = _first;

	float vibe = 0.0f;

	/* find the best RMS value of a non-timed out sensor */
	while (next != nullptr) {

		if (next->confidence(timestamp) > 0.5f) {
			float *rms = next->rms();

			for (unsigned j = 0; j < 3; j++) {
				if (rms[j] > vibe) {
					vibe = rms[j];
				}
			}
		}

		next = next->sibling();
	}

	return vibe;
}

float
DataValidatorGroup::get_vibration_offset(uint64_t timestamp, int axis)
{
	DataValidator *next = _first;

	float vibe = -1.0f;

	/* find the best vibration value of a non-timed out sensor */
	while (next != nullptr) {

		if (next->confidence(timestamp) > 0.5f) {
			float *vibration_offset = next->vibration_offset();

			if (vibe < 0.0f || vibration_offset[axis] < vibe) {
				vibe = vibration_offset[axis];
			}
		}

		next = next->sibling();
	}

	return vibe;
}

void
DataValidatorGroup::print()
{
	/* print the group's state */
	ECL_INFO("validator: best: %d, prev best: %d, failsafe: %s (%u events)",
		 _curr_best, _prev_best, (_toggle_count > 0) ? "YES" : "NO",
		 _toggle_count);

	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used()) {
			uint32_t flags = next->state();

			ECL_INFO("sensor #%u, prio: %d, state:%s%s%s%s%s%s", i, next->priority(),
				 ((flags & DataValidator::ERROR_FLAG_NO_DATA) ? " OFF" : ""),
				 ((flags & DataValidator::ERROR_FLAG_STALE_DATA) ? " STALE" : ""),
				 ((flags & DataValidator::ERROR_FLAG_TIMEOUT) ? " TOUT" : ""),
				 ((flags & DataValidator::ERROR_FLAG_HIGH_ERRCOUNT) ? " ECNT" : ""),
				 ((flags & DataValidator::ERROR_FLAG_HIGH_ERRDENSITY) ? " EDNST" : ""),
				 ((flags == DataValidator::ERROR_FLAG_NO_ERROR) ? " OK" : ""));

			next->print();
		}

		next = next->sibling();
		i++;
	}
}

int
DataValidatorGroup::failover_index()
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used() && (next->state() != DataValidator::ERROR_FLAG_NO_ERROR) && (i == (unsigned)_prev_best)) {
			return i;
		}

		next = next->sibling();
		i++;
	}

	return -1;
}

uint32_t
DataValidatorGroup::failover_state()
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used() && (next->state() != DataValidator::ERROR_FLAG_NO_ERROR) && (i == (unsigned)_prev_best)) {
			return next->state();
		}

		next = next->sibling();
		i++;
	}

	return DataValidator::ERROR_FLAG_NO_ERROR;
}
<commit_msg>validation DataValidatorGroup::get_best() nullptr check<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file data_validator_group.cpp
 *
 * A data validation group to identify anomalies in data streams
 *
 * @author Lorenz Meier <lorenz@px4.io>
 */

#include "data_validator_group.h"
#include <ecl.h>
#include <cfloat>

DataValidatorGroup::DataValidatorGroup(unsigned siblings)
{
	DataValidator *next = nullptr;
	DataValidator *prev = nullptr;

	for (unsigned i = 0; i < siblings; i++) {
		next = new DataValidator();

		if (i == 0) {
			_first = next;

		} else {
			prev->setSibling(next);
		}

		prev = next;
	}

	_last = next;

	if (_first) {
		_timeout_interval_us = _first->get_timeout();
	}
}

DataValidatorGroup::~DataValidatorGroup()
{
	while (_first) {
		DataValidator *next = _first->sibling();
		delete (_first);
		_first = next;
	}
}

DataValidator *DataValidatorGroup::add_new_validator()
{
	DataValidator *validator = new DataValidator();

	if (!validator) {
		return nullptr;
	}

	_last->setSibling(validator);
	_last = validator;
	_last->set_timeout(_timeout_interval_us);
	return _last;
}

void
DataValidatorGroup::set_timeout(uint32_t timeout_interval_us)
{
	DataValidator *next = _first;

	while (next != nullptr) {
		next->set_timeout(timeout_interval_us);
		next = next->sibling();
	}

	_timeout_interval_us = timeout_interval_us;
}

void
DataValidatorGroup::set_equal_value_threshold(uint32_t threshold)
{
	DataValidator *next = _first;

	while (next != nullptr) {
		next->set_equal_value_threshold(threshold);
		next = next->sibling();
	}
}

void
DataValidatorGroup::put(unsigned index, uint64_t timestamp, const float val[3], uint64_t error_count, int priority)
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (i == index) {
			next->put(timestamp, val, error_count, priority);
			break;
		}

		next = next->sibling();
		i++;
	}
}

float *
DataValidatorGroup::get_best(uint64_t timestamp, int *index)
{
	DataValidator *next = _first;

	// XXX This should eventually also include voting
	int pre_check_best = _curr_best;
	float pre_check_confidence = 1.0f;
	int pre_check_prio = -1;
	float max_confidence = -1.0f;
	int max_priority = -1000;
	int max_index = -1;
	DataValidator *best = nullptr;

	int i = 0;

	while (next != nullptr) {
		float confidence = next->confidence(timestamp);

		if (i == pre_check_best) {
			pre_check_prio = next->priority();
			pre_check_confidence = confidence;
		}

		/*
		 * Switch if:
		 * 1) the confidence is higher and priority is equal or higher
		 * 2) the confidence is no less than 1% different and the priority is higher
		 */
		if ((((max_confidence < MIN_REGULAR_CONFIDENCE) && (confidence >= MIN_REGULAR_CONFIDENCE)) ||
		     (confidence > max_confidence && (next->priority() >= max_priority)) ||
		     (fabsf(confidence - max_confidence) < 0.01f && (next->priority() > max_priority))
		    ) && (confidence > 0.0f)) {

			max_index = i;
			max_confidence = confidence;
			max_priority = next->priority();
			best = next;
		}

		next = next->sibling();
		i++;
	}

	/* the current best sensor is not matching the previous best sensor,
	 * or the only sensor went bad */
	if (max_index != _curr_best || ((max_confidence < FLT_EPSILON) && (_curr_best >= 0))) {

		bool true_failsafe = true;

		/* check whether the switch was a failsafe or preferring a higher priority sensor */
		if (pre_check_prio != -1 && pre_check_prio < max_priority &&
		    fabsf(pre_check_confidence - max_confidence) < 0.1f) {

			/* this is not a failover */
			true_failsafe = false;

			/* reset error flags, this is likely a hotplug sensor coming online late */
			if (best != nullptr) {
				best->reset_state();
			}
		}

		/* if we're no initialized, initialize the bookkeeping but do not count a failsafe */
		if (_curr_best < 0) {
			_prev_best = max_index;

		} else {
			/* we were initialized before, this is a real failsafe */
			_prev_best = pre_check_best;

			if (true_failsafe) {
				_toggle_count++;

				/* if this is the first time, log when we failed */
				if (_first_failover_time == 0) {
					_first_failover_time = timestamp;
				}
			}
		}

		/* for all cases we want to keep a record of the best index */
		_curr_best = max_index;
	}

	*index = max_index;
	return (best) ? best->value() : nullptr;
}

float
DataValidatorGroup::get_vibration_factor(uint64_t timestamp)
{
	DataValidator *next = _first;

	float vibe = 0.0f;

	/* find the best RMS value of a non-timed out sensor */
	while (next != nullptr) {

		if (next->confidence(timestamp) > 0.5f) {
			float *rms = next->rms();

			for (unsigned j = 0; j < 3; j++) {
				if (rms[j] > vibe) {
					vibe = rms[j];
				}
			}
		}

		next = next->sibling();
	}

	return vibe;
}

float
DataValidatorGroup::get_vibration_offset(uint64_t timestamp, int axis)
{
	DataValidator *next = _first;

	float vibe = -1.0f;

	/* find the best vibration value of a non-timed out sensor */
	while (next != nullptr) {

		if (next->confidence(timestamp) > 0.5f) {
			float *vibration_offset = next->vibration_offset();

			if (vibe < 0.0f || vibration_offset[axis] < vibe) {
				vibe = vibration_offset[axis];
			}
		}

		next = next->sibling();
	}

	return vibe;
}

void
DataValidatorGroup::print()
{
	/* print the group's state */
	ECL_INFO("validator: best: %d, prev best: %d, failsafe: %s (%u events)",
		 _curr_best, _prev_best, (_toggle_count > 0) ? "YES" : "NO",
		 _toggle_count);

	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used()) {
			uint32_t flags = next->state();

			ECL_INFO("sensor #%u, prio: %d, state:%s%s%s%s%s%s", i, next->priority(),
				 ((flags & DataValidator::ERROR_FLAG_NO_DATA) ? " OFF" : ""),
				 ((flags & DataValidator::ERROR_FLAG_STALE_DATA) ? " STALE" : ""),
				 ((flags & DataValidator::ERROR_FLAG_TIMEOUT) ? " TOUT" : ""),
				 ((flags & DataValidator::ERROR_FLAG_HIGH_ERRCOUNT) ? " ECNT" : ""),
				 ((flags & DataValidator::ERROR_FLAG_HIGH_ERRDENSITY) ? " EDNST" : ""),
				 ((flags == DataValidator::ERROR_FLAG_NO_ERROR) ? " OK" : ""));

			next->print();
		}

		next = next->sibling();
		i++;
	}
}

int
DataValidatorGroup::failover_index()
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used() && (next->state() != DataValidator::ERROR_FLAG_NO_ERROR) && (i == (unsigned)_prev_best)) {
			return i;
		}

		next = next->sibling();
		i++;
	}

	return -1;
}

uint32_t
DataValidatorGroup::failover_state()
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used() && (next->state() != DataValidator::ERROR_FLAG_NO_ERROR) && (i == (unsigned)_prev_best)) {
			return next->state();
		}

		next = next->sibling();
		i++;
	}

	return DataValidator::ERROR_FLAG_NO_ERROR;
}
<|endoftext|>


<commit_before>#ifndef SLIDING_WINDOW_HPP_
#define SLIDING_WINDOW_HPP_

#include "iterbase.hpp"

#include <vector>
#include <algorithm>
#include <functional>
#include <type_traits>
#include <utility>
#include <iterator>

namespace iter {
    template <typename Container>
    class SlidingWindow;

    template <typename Container>
    SlidingWindow<Container> sliding_window(Container&&, std::size_t);

    template <typename T>
    SlidingWindow<std::initializer_list<T>> sliding_window(
            std::initializer_list<T>, std::size_t);

    template <typename Container>
    class SlidingWindow {
        private:
            Container container;
            std::size_t window_size;

            friend SlidingWindow sliding_window<Container>(
                    Container&&, std::size_t);

            template <typename T>
            friend SlidingWindow<std::initializer_list<T>> sliding_window(
                    std::initializer_list<T>, std::size_t);

            SlidingWindow(Container container, std::size_t win_sz)
                : container(std::forward<Container>(container)),
                window_size{win_sz}
            { }

        public:

            class Iterator {
                private:
                    // confusing, but, just makes the type of the vector
                    // returned by operator*()
                    using OpDerefElemType =
                        std::reference_wrapper<
                            typename std::remove_reference<
                                iterator_deref<Container>>::type>;
                    using DerefVec = std::vector<OpDerefElemType>;

                    std::vector<iterator_type<Container>> section;
                    std::size_t section_size = 0;

                public:
                    Iterator(Container& container, std::size_t s)
                        : section_size{s}
                    {
                        auto iter = std::begin(container);
                        auto end = std::end(container);
                        for (std::size_t i = 0;
                                i < section_size && iter != end;
                                ++iter, ++i) {
                            section.push_back(iter);
                        }
                    }

                    // for the end iter
                    Iterator(Container& container)
                        : section{std::end(container)},
                        section_size{0}
                    { }

                    Iterator& operator++() {
                        for (auto&& iter : this->section) {
                            ++iter;
                        }
                        return *this;
                    }

                    bool operator!=(const Iterator& rhs) const {
                       return this->section.back() != rhs.section.back();
                    }

                    DerefVec operator*() {
                        DerefVec vec;
                        for (auto&& iter : this->section) {
                            vec.push_back(*iter);
                        }
                        return vec;
                    }
            };

            Iterator begin() {
                return {container, window_size};
            }

            Iterator end() {
                return {container};
            }
    };

    template <typename Container>
    SlidingWindow<Container> sliding_window(
            Container&& container, std::size_t window_size) {
        return {std::forward<Container>(container), window_size};
    }

    template <typename T>
    SlidingWindow<std::initializer_list<T>> sliding_window(
            std::initializer_list<T> il, std::size_t window_size) {
        return {il, window_size};
    }
}

#endif //SLIDING_WINDOW_HPP_
<commit_msg>sliding window lazily consumes iterable<commit_after>#ifndef ITER_SLIDING_WINDOW_HPP_
#define ITER_SLIDING_WINDOW_HPP_

#include "iterbase.hpp"

#include <deque>
#include <utility>
#include <iterator>

namespace iter {
    template <typename Container>
    class SlidingWindow;

    template <typename Container>
    SlidingWindow<Container> sliding_window(Container&&, std::size_t);

    template <typename T>
    SlidingWindow<std::initializer_list<T>> sliding_window(
            std::initializer_list<T>, std::size_t);

    template <typename Container>
    class SlidingWindow {
        private: Container container;
            std::size_t window_size;

            friend SlidingWindow sliding_window<Container>(
                    Container&&, std::size_t);

            template <typename T>
            friend SlidingWindow<std::initializer_list<T>> sliding_window(
                    std::initializer_list<T>, std::size_t);

            SlidingWindow(Container container, std::size_t win_sz)
                : container(std::forward<Container>(container)),
                window_size{win_sz}
            { }

        public:

            class Iterator {
                private:
                    // TODO move defs outside and subclass std::iterator
                    using OpDerefElemType = collection_item_type<Container>;
                    using DerefVec = std::deque<OpDerefElemType>;

                    iterator_type<Container> sub_iter;
                    DerefVec window;

                public:
                    Iterator(const iterator_type<Container>& in_iter,
                            const iterator_type<Container>& in_end,
                             std::size_t window_sz)
                        : sub_iter(in_iter)
                    {
                        std::size_t i{0};
                        while (i < window_sz && this->sub_iter != in_end) {
                            this->window.push_back(*this->sub_iter);
                            ++i;
                            if (i != window_sz) ++this->sub_iter;
                        }
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    DerefVec& operator*() {
                        return this->window;
                    }

                    Iterator& operator++() {
                        ++this->sub_iter;
                        this->window.pop_front();
                        this->window.push_back(*this->sub_iter);
                        return *this;
                    }
            };

            Iterator begin() {
                return {std::begin(container),
                    std::end(container),
                    window_size};
            }

            Iterator end() {
                return {std::end(container),
                    std::end(container),
                    window_size};
            }
    };

    template <typename Container>
    SlidingWindow<Container> sliding_window(
            Container&& container, std::size_t window_size) {
        return {std::forward<Container>(container), window_size};
    }

    template <typename T>
    SlidingWindow<std::initializer_list<T>> sliding_window(
            std::initializer_list<T> il, std::size_t window_size) {
        return {il, window_size};
    }
}

#endif
<|endoftext|>


<commit_before>#include "CauchyRand.h"

CauchyRand::CauchyRand(double location, double scale)
{
    setLocation(location);
    setScale(scale);
}

std::string CauchyRand::name()
{
    return "Cauchy(" + toStringWithPrecision(getLocation()) + ", " + toStringWithPrecision(getScale()) + ")";
}

void CauchyRand::setLocation(double location)
{
    x0 = location;
}

void CauchyRand::setScale(double scale)
{
    gamma = std::max(scale, MIN_POSITIVE);
    gammaInv = 1.0 / gamma;
}

double CauchyRand::f(double x) const
{
    double y = x - x0;
    y *= y;
    y *= gammaInv;
    y += gamma;
    return M_1_PI / y;
}

double CauchyRand::F(double x) const
{
    double y = x - x0;
    y *= gammaInv;
    y = std::atan(y);
    y *= M_1_PI;
    return y + .5;
}

double CauchyRand::variate() const
{
    return x0 + gamma * standardVariate();
}

double CauchyRand::variate(double location, double scale)
{
    return location + scale * standardVariate();
}

double CauchyRand::standardVariate()
{
    double x, y;
    do {
        x = UniformRand::variate(-1, 1);
        y = UniformRand::variate(-1, 1);
    } while (x * x + y * y > 1.0 || y == 0.0);
    return x / y;
}

double E() const
{
    return NAN;
}

double Var() const
{
    return INFINITY;
}

double quantile(double p) const
{
    if (p < 0 || p > 1)
         return NAN;
    if (p == 0)
        return -INFINITY;
    if (p == 1)
        return INFINITY;
    return x0 + gamma * std::tan(M_PI * (p - 0.5));
}

double Median() const
{
    return x0;
}

double Mode() const
{
    return x0;
}

double Skewness() const
{
    return NAN;
}

double ExcessKurtosis() const
{
    return NAN;
}

double CauchyRand::Entropy() const
{
     return std::log(4 * gamma * M_PI);
}
<commit_msg>Update CauchyRand.cpp<commit_after>#include "CauchyRand.h"

CauchyRand::CauchyRand(double location, double scale)
{
    setLocation(location);
    setScale(scale);
}

std::string CauchyRand::name()
{
    return "Cauchy(" + toStringWithPrecision(getLocation()) + ", " + toStringWithPrecision(getScale()) + ")";
}

void CauchyRand::setLocation(double location)
{
    x0 = location;
}

void CauchyRand::setScale(double scale)
{
    gamma = std::max(scale, MIN_POSITIVE);
    gammaInv = 1.0 / gamma;
}

double CauchyRand::f(double x) const
{
    double y = x - x0;
    y *= y;
    y *= gammaInv;
    y += gamma;
    return M_1_PI / y;
}

double CauchyRand::F(double x) const
{
    double y = x - x0;
    y *= gammaInv;
    y = std::atan(y);
    y *= M_1_PI;
    return y + .5;
}

double CauchyRand::variate() const
{
    return x0 + gamma * standardVariate();
}

double CauchyRand::variate(double location, double scale)
{
    return location + scale * standardVariate();
}

double CauchyRand::standardVariate()
{
    double x, y;
    do {
        x = UniformRand::variate(-1, 1);
        y = UniformRand::variate(-1, 1);
    } while (x * x + y * y > 1.0 || y == 0.0);
    return x / y;
}

double CauchyRand::E() const
{
    return NAN;
}

double CauchyRand::Var() const
{
    return INFINITY;
}

double CauchyRand::quantile(double p) const
{
    if (p < 0 || p > 1)
         return NAN;
    if (p == 0)
        return -INFINITY;
    if (p == 1)
        return INFINITY;
    return x0 + gamma * std::tan(M_PI * (p - 0.5));
}

double CauchyRand::Median() const
{
    return x0;
}

double CauchyRand::Mode() const
{
    return x0;
}

double CauchyRand::Skewness() const
{
    return NAN;
}

double CauchyRand::ExcessKurtosis() const
{
    return NAN;
}

double CauchyRand::Entropy() const
{
     return std::log(4 * gamma * M_PI);
}
<|endoftext|>


<commit_before>#ifndef UNIT_DATA_HPP_
#define UNIT_DATA_HPP_

#include "communication/communicator.hpp"
#include "estimator/dcm_attitude_estimator.hpp"
#include "motor/multirotor_quad_plus_motor_mapper.hpp"
#include "input/offboard_input_source.hpp"
#include "sensor/gyroscope.hpp"
#include "sensor/accelerometer.hpp"
#include "system/multirotor_vehicle_system.hpp"
#include "variant/platform.hpp"

static const float MOTOR_PWM_MIN = 0.53f;
static const float MOTOR_PWM_MAX = 0.93f;
static const float MOTOR_PWM_SAFE = 0.30f;

struct unit_data_t {
  PWMDeviceGroup<4> motors;
  MultirotorQuadPlusMotorMapper motorMapper;

  DCMAttitudeEstimator estimator;
  OffboardInputSource inputSource;

  MultirotorVehicleSystem system;

  unit_data_t(Platform& platform, Communicator& communicator)
    : motors(platform.get<PWMPlatform>(),
        { 0, 1, 2, 3 },                              // channels
        { 0.0f, 0.0f, 0.0f, 0.0f },                  // offsets
        0.0f, 1.0f,                                  // input range
        MOTOR_PWM_MIN, MOTOR_PWM_MAX, MOTOR_PWM_SAFE // output range
      ),
      motorMapper(motors, communicator),
      estimator(communicator),
      inputSource(communicator),
      system(platform.get<Gyroscope>(), platform.get<Accelerometer>(), std::experimental::nullopt, estimator, inputSource, motorMapper, communicator) {
  }
};

#endif
<commit_msg>Update other platforms again.<commit_after>#ifndef UNIT_DATA_HPP_
#define UNIT_DATA_HPP_

#include "communication/communicator.hpp"
#include "estimator/dcm_attitude_estimator.hpp"
#include "motor/multirotor_quad_plus_motor_mapper.hpp"
#include "input/offboard_input_source.hpp"
#include "sensor/gyroscope.hpp"
#include "sensor/accelerometer.hpp"
#include "system/multirotor_vehicle_system.hpp"
#include "util/optional.hpp"
#include "variant/platform.hpp"

static const float MOTOR_PWM_MIN = 0.53f;
static const float MOTOR_PWM_MAX = 0.93f;
static const float MOTOR_PWM_SAFE = 0.30f;

struct unit_data_t {
  PWMDeviceGroup<4> motors;
  MultirotorQuadPlusMotorMapper motorMapper;

  DCMAttitudeEstimator estimator;
  OffboardInputSource inputSource;

  MultirotorVehicleSystem system;

  unit_data_t(Platform& platform, Communicator& communicator)
    : motors(platform.get<PWMPlatform>(),
        { 0, 1, 2, 3 },                              // channels
        { 0.0f, 0.0f, 0.0f, 0.0f },                  // offsets
        0.0f, 1.0f,                                  // input range
        MOTOR_PWM_MIN, MOTOR_PWM_MAX, MOTOR_PWM_SAFE // output range
      ),
      motorMapper(motors, communicator),
      estimator(communicator),
      inputSource(communicator),
      system(platform.get<Gyroscope>(), platform.get<Accelerometer>(), std::experimental::nullopt, estimator, inputSource, motorMapper, communicator) {
  }
};

#endif
<|endoftext|>


<commit_before>#ifndef VIENNAGRID_MESH_OPERATIONS_HPP
#define VIENNAGRID_MESH_OPERATIONS_HPP

/* =======================================================================
   Copyright (c) 2011-2013, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include "viennagrid/mesh/mesh.hpp"
#include "viennagrid/mesh/element_creation.hpp"

namespace viennagrid
{

  template<typename SrcMeshT, typename SrcSegmentationT, typename DstMeshT, typename DstSegmentationT>
  void copy_cells(SrcMeshT const & src_mesh,  SrcSegmentationT const & src_segmentation,
                  DstMeshT & dst_mesh,        DstSegmentationT & dst_segmentation )
  {
  //     typedef typename src_segment_container_type::value_type src_segment_handle_type;
  //     typedef typename dst_segment_container_type::value_type dst_segment_handle_type;
      typedef typename viennagrid::result_of::segment<SrcSegmentationT>::type SrcSegmentHandleType;
      typedef typename viennagrid::result_of::segment<DstSegmentationT>::type DstSegmentHandleType;

      typedef typename viennagrid::result_of::cell_tag<SrcMeshT>::type  SrcCellTag;
      typedef typename viennagrid::result_of::cell<SrcMeshT>::type      SrcCellType;

      typedef typename viennagrid::result_of::const_vertex_range<SrcMeshT>::type    SrcVertexRangeType;
      typedef typename viennagrid::result_of::iterator<SrcVertexRangeType>::type      SrcVertexRangeIterator;

      typedef typename viennagrid::result_of::const_cell_range<SrcSegmentHandleType>::type  SrcCellRangeType;
      typedef typename viennagrid::result_of::iterator<SrcCellRangeType>::type        SrcCellRangeIterator;

      typedef typename viennagrid::result_of::const_vertex_handle<SrcMeshT>::type   SrcConstVertexHandle;
      typedef typename viennagrid::result_of::vertex_handle<DstMeshT>::type         DstVertexHandleType;

      if (&src_mesh == &dst_mesh)
          return;

      dst_mesh.clear();
      dst_segmentation.clear();

      std::map<SrcConstVertexHandle, DstVertexHandleType> vertex_handle_map;

      SrcVertexRangeType vertices = viennagrid::elements( src_mesh );
  //     std::cout << "Copy: vertex count = " << vertices.size() << std::endl;
      for (SrcVertexRangeIterator it = vertices.begin(); it != vertices.end(); ++it)
          vertex_handle_map[it.handle()] = viennagrid::make_vertex( dst_mesh, viennagrid::point(src_mesh, *it) );

      for (typename SrcSegmentationT::const_iterator seg_it = src_segmentation.begin(); seg_it != src_segmentation.end(); ++seg_it)
      {
  //         dst_segments.push_back( viennagrid::make_view<dst_segment_handle_type>(dst_mesh) );
          DstSegmentHandleType & dst_segment = dst_segmentation.get_make_segment( seg_it->id() );

          SrcCellRangeType cells = viennagrid::elements( *seg_it );
  //         std::cout << "Copy: cell count = " << cells.size() << std::endl;
          for (SrcCellRangeIterator it = cells.begin(); it != cells.end(); ++it)
          {
              SrcCellType const & cell = *it;

              std::deque<DstVertexHandleType> vertex_handles;

              typedef typename viennagrid::result_of::const_vertex_range<SrcCellType>::type SrcVertexOnSrcCellRangeType;
              typedef typename viennagrid::result_of::iterator<SrcVertexOnSrcCellRangeType>::type SrcVertexOnSrcCellRangeIterator;

              SrcVertexOnSrcCellRangeType cell_vertices = viennagrid::elements(cell);
              for (SrcVertexOnSrcCellRangeIterator jt = cell_vertices.begin(); jt != cell_vertices.end(); ++jt)
                  vertex_handles.push_back( vertex_handle_map[jt.handle()] );

              typedef typename viennagrid::result_of::cell<DstMeshT>::type DstCellType;
              viennagrid::make_element<DstCellType>( dst_segment, vertex_handles.begin(), vertex_handles.end() );
          }
      }
  }

}

#endif
<commit_msg>segment -> segment_handle<commit_after>#ifndef VIENNAGRID_MESH_OPERATIONS_HPP
#define VIENNAGRID_MESH_OPERATIONS_HPP

/* =======================================================================
   Copyright (c) 2011-2013, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include "viennagrid/mesh/mesh.hpp"
#include "viennagrid/mesh/element_creation.hpp"

namespace viennagrid
{

  template<typename SrcMeshT, typename SrcSegmentationT, typename DstMeshT, typename DstSegmentationT>
  void copy_cells(SrcMeshT const & src_mesh,  SrcSegmentationT const & src_segmentation,
                  DstMeshT & dst_mesh,        DstSegmentationT & dst_segmentation )
  {
  //     typedef typename src_segment_container_type::value_type src_segment_handle_type;
  //     typedef typename dst_segment_container_type::value_type dst_segment_handle_type;
      typedef typename viennagrid::result_of::segment_handle<SrcSegmentationT>::type SrcSegmentHandleType;
      typedef typename viennagrid::result_of::segment_handle<DstSegmentationT>::type DstSegmentHandleType;

      typedef typename viennagrid::result_of::cell_tag<SrcMeshT>::type  SrcCellTag;
      typedef typename viennagrid::result_of::cell<SrcMeshT>::type      SrcCellType;

      typedef typename viennagrid::result_of::const_vertex_range<SrcMeshT>::type    SrcVertexRangeType;
      typedef typename viennagrid::result_of::iterator<SrcVertexRangeType>::type      SrcVertexRangeIterator;

      typedef typename viennagrid::result_of::const_cell_range<SrcSegmentHandleType>::type  SrcCellRangeType;
      typedef typename viennagrid::result_of::iterator<SrcCellRangeType>::type        SrcCellRangeIterator;

      typedef typename viennagrid::result_of::const_vertex_handle<SrcMeshT>::type   SrcConstVertexHandle;
      typedef typename viennagrid::result_of::vertex_handle<DstMeshT>::type         DstVertexHandleType;

      if (&src_mesh == &dst_mesh)
          return;

      dst_mesh.clear();
      dst_segmentation.clear();

      std::map<SrcConstVertexHandle, DstVertexHandleType> vertex_handle_map;

      SrcVertexRangeType vertices = viennagrid::elements( src_mesh );
  //     std::cout << "Copy: vertex count = " << vertices.size() << std::endl;
      for (SrcVertexRangeIterator it = vertices.begin(); it != vertices.end(); ++it)
          vertex_handle_map[it.handle()] = viennagrid::make_vertex( dst_mesh, viennagrid::point(src_mesh, *it) );

      for (typename SrcSegmentationT::const_iterator seg_it = src_segmentation.begin(); seg_it != src_segmentation.end(); ++seg_it)
      {
  //         dst_segments.push_back( viennagrid::make_view<dst_segment_handle_type>(dst_mesh) );
          DstSegmentHandleType & dst_segment = dst_segmentation.get_make_segment( seg_it->id() );

          SrcCellRangeType cells = viennagrid::elements( *seg_it );
  //         std::cout << "Copy: cell count = " << cells.size() << std::endl;
          for (SrcCellRangeIterator it = cells.begin(); it != cells.end(); ++it)
          {
              SrcCellType const & cell = *it;

              std::deque<DstVertexHandleType> vertex_handles;

              typedef typename viennagrid::result_of::const_vertex_range<SrcCellType>::type SrcVertexOnSrcCellRangeType;
              typedef typename viennagrid::result_of::iterator<SrcVertexOnSrcCellRangeType>::type SrcVertexOnSrcCellRangeIterator;

              SrcVertexOnSrcCellRangeType cell_vertices = viennagrid::elements(cell);
              for (SrcVertexOnSrcCellRangeIterator jt = cell_vertices.begin(); jt != cell_vertices.end(); ++jt)
                  vertex_handles.push_back( vertex_handle_map[jt.handle()] );

              typedef typename viennagrid::result_of::cell<DstMeshT>::type DstCellType;
              viennagrid::make_element<DstCellType>( dst_segment, vertex_handles.begin(), vertex_handles.end() );
          }
      }
  }

}

#endif
<|endoftext|>