<commit_before>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <QByteArray>
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/storage/exceptions/perfdata.hh"
#include "com/centreon/broker/storage/parser.hh"
#include "com/centreon/broker/storage/perfdata.hh"

using namespace com::centreon::broker::storage;

/**************************************
*                                     *
*            Local Objects            *
*                                     *
**************************************/

/**
 *  Extract a real value from a perfdata string.
 *
 *  @param[in,out] str  Pointer to a perfdata string.
 *  @param[in]     skip true to skip semicolon.
 *
 *  @return Extracted real value if successful, NaN otherwise.
 */
static inline double extract_double(
                       char const** str,
                       bool skip = true) {
  double retval;
  char* tmp;
  retval = strtod(*str, &tmp);
  *str = tmp;
  if (skip && (**str == ';'))
    ++*str;
  return (retval);
}

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
parser::parser() {}

/**
 *  @brief Copy constructor.
 *
 *  No data is stored within the parser class.
 *
 *  @param[in] pp Unused.
 */
parser::parser(parser const& pp) {
  (void)pp;
}

/**
 *  Destructor.
 */
parser::~parser() {}

/**
 *  @brief Assignment operator.
 *
 *  No data is stored within the parser class.
 *
 *  @param[in] pp Unused.
 *
 *  @return This object.
 */
parser& parser::operator=(parser const& pp) {
  (void)pp;
  return (*this);
}

/**
 *  Parse perfdata string as given by plugin.
 *
 *  @param[in]  str Raw perfdata string.
 *  @param[out] pd  List of parsed metrics.
 */
void parser::parse_perfdata(
               QString const& str,
               QList<perfdata>& pd) {
  // Extract metrics strings.
  QByteArray buf(qPrintable(str));
  buf.replace(',', '.');
  char const* ptr(buf.constData());

  // Skip initial whitespaces.
  while (isblank(*ptr))
    ++ptr;
  while (*ptr) {
    // Debug message.
    logging::debug(logging::medium)
      << "storage: parsing perfdata string '" << ptr << "'";

    // Perfdata object.
    perfdata p;

    // Get metric name.
    bool in_quote(false);
    unsigned int i(0);
    while (ptr[i] && (in_quote || (ptr[i] != '='))) {
      if ('\'' == ptr[i])
        in_quote = !in_quote;
      ++i;
    }
    std::string s(ptr, i);
    ptr += i;

    // Unquote metric name.
    size_t t;
    t = s.find_first_of('\'');
    while (t != std::string::npos) {
      s.erase(t, 1);
      t = s.find_first_of('\'', t + 1); // Skip one char, so '' becomes '.
    }
    if ((s.size() > 0) && (*s.rbegin() == ']')) {
      if (!s.compare(0, 2, "a[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::absolute);
      }
      else if (!s.compare(0, 2, "c[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::counter);
      }
      else if (!s.compare(0, 2, "d[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::derive);
      }
      else if (!s.compare(0, 2, "g[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::gauge);
      }
    }
    p.name(QString(s.c_str()).trimmed().toLower());

    // Check format.
    if (*ptr != '=')
      throw (exceptions::perfdata() << "storage: invalid perfdata " \
               "format: equal sign not present or misplaced");
    ++ptr;

    // Extract value.
    p.value(extract_double(&ptr, false));
    if (isnan(p.value()))
      p.value(0.0);

    // Extract unit.
    t = strcspn(ptr, " ;");
    p.unit(std::string(ptr, t).c_str());
    ptr += t;
    if (*ptr == ';')
      ++ptr;

    // Extract warning.
    p.warning(extract_double(&ptr));

    // Extract critical.
    p.critical(extract_double(&ptr));

    // Extract minimum.
    p.min(extract_double(&ptr));

    // Extract maximum.
    p.max(extract_double(&ptr));

    // Log new perfdata.
    logging::debug(logging::low) << "storage: got new perfdata (name="
      << p.name() << ", value=" << p.value() << ", unit=" << p.unit()
      << ", warning=" << p.warning() << ", critical=" << p.critical()
      << ", min=" << p.min() << ", max=" << p.max() << ")";

    // Append to list.
    pd.push_back(p);

    // Skip whitespaces.
    while (isblank(*ptr))
      ++ptr;
  }

  return ;
}
<commit_msg>Revert "storage: DS name must match metric_name in DB. This refs #3641."<commit_after>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <QByteArray>
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/storage/exceptions/perfdata.hh"
#include "com/centreon/broker/storage/parser.hh"
#include "com/centreon/broker/storage/perfdata.hh"

using namespace com::centreon::broker::storage;

/**************************************
*                                     *
*            Local Objects            *
*                                     *
**************************************/

/**
 *  Extract a real value from a perfdata string.
 *
 *  @param[in,out] str  Pointer to a perfdata string.
 *  @param[in]     skip true to skip semicolon.
 *
 *  @return Extracted real value if successful, NaN otherwise.
 */
static inline double extract_double(
                       char const** str,
                       bool skip = true) {
  double retval;
  char* tmp;
  retval = strtod(*str, &tmp);
  *str = tmp;
  if (skip && (**str == ';'))
    ++*str;
  return (retval);
}

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
parser::parser() {}

/**
 *  @brief Copy constructor.
 *
 *  No data is stored within the parser class.
 *
 *  @param[in] pp Unused.
 */
parser::parser(parser const& pp) {
  (void)pp;
}

/**
 *  Destructor.
 */
parser::~parser() {}

/**
 *  @brief Assignment operator.
 *
 *  No data is stored within the parser class.
 *
 *  @param[in] pp Unused.
 *
 *  @return This object.
 */
parser& parser::operator=(parser const& pp) {
  (void)pp;
  return (*this);
}

/**
 *  Parse perfdata string as given by plugin.
 *
 *  @param[in]  str Raw perfdata string.
 *  @param[out] pd  List of parsed metrics.
 */
void parser::parse_perfdata(
               QString const& str,
               QList<perfdata>& pd) {
  // Extract metrics strings.
  QByteArray buf(qPrintable(str));
  buf.replace(',', '.');
  char const* ptr(buf.constData());

  // Skip initial whitespaces.
  while (isblank(*ptr))
    ++ptr;
  while (*ptr) {
    // Debug message.
    logging::debug(logging::medium)
      << "storage: parsing perfdata string '" << ptr << "'";

    // Perfdata object.
    perfdata p;

    // Get metric name.
    bool in_quote(false);
    unsigned int i(0);
    while (ptr[i] && (in_quote || (ptr[i] != '='))) {
      if ('\'' == ptr[i])
        in_quote = !in_quote;
      ++i;
    }
    std::string s(ptr, i);
    ptr += i;

    // Unquote metric name.
    size_t t;
    t = s.find_first_of('\'');
    while (t != std::string::npos) {
      s.erase(t, 1);
      t = s.find_first_of('\'', t + 1); // Skip one char, so '' becomes '.
    }
    if ((s.size() > 0) && (*s.rbegin() == ']')) {
      if (!s.compare(0, 2, "a[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::absolute);
      }
      else if (!s.compare(0, 2, "c[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::counter);
      }
      else if (!s.compare(0, 2, "d[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::derive);
      }
      else if (!s.compare(0, 2, "g[")) {
        s = s.substr(2, s.size() - 3);
        p.value_type(perfdata::gauge);
      }
    }
    p.name(s.c_str());

    // Check format.
    if (*ptr != '=')
      throw (exceptions::perfdata() << "storage: invalid perfdata " \
               "format: equal sign not present or misplaced");
    ++ptr;

    // Extract value.
    p.value(extract_double(&ptr, false));
    if (isnan(p.value()))
      p.value(0.0);

    // Extract unit.
    t = strcspn(ptr, " ;");
    p.unit(std::string(ptr, t).c_str());
    ptr += t;
    if (*ptr == ';')
      ++ptr;

    // Extract warning.
    p.warning(extract_double(&ptr));

    // Extract critical.
    p.critical(extract_double(&ptr));

    // Extract minimum.
    p.min(extract_double(&ptr));

    // Extract maximum.
    p.max(extract_double(&ptr));

    // Log new perfdata.
    logging::debug(logging::low) << "storage: got new perfdata (name="
      << p.name() << ", value=" << p.value() << ", unit=" << p.unit()
      << ", warning=" << p.warning() << ", critical=" << p.critical()
      << ", min=" << p.min() << ", max=" << p.max() << ")";

    // Append to list.
    pd.push_back(p);

    // Skip whitespaces.
    while (isblank(*ptr))
      ++ptr;
  }

  return ;
}
<|endoftext|>


<commit_before>/*
 *  quadtree.cpp
 *  Implementation of a quadtree in two dimensions + Barnes-Hut algorithm for t-SNE.
 *
 *  Created by Laurens van der Maaten.
 *  Copyright 2012, Delft University of Technology. All rights reserved.
 *
 *  Multicore version by Dmitry Ulyanov, 2016. dmitry.ulyanov.msu@gmail.com
 */

#include <cmath>
#include <cfloat>
#include <cstdlib>
#include <cstdio>

#include "quadtree.h"

// Checks whether a point lies in a cell
bool Cell::containsPoint(double point[])
{
    for (int i = 0; i< n_dims; ++i) {
        if (abs_d(center[i] - point[i]) > width[i]) {
            return false;
        }
    }
    return true;
}

// Default constructor for quadtree -- build tree, too!
QuadTree::QuadTree(double* inp_data, int N, int no_dims)
{
    QT_NO_DIMS = no_dims;
    num_children = 1 << no_dims;

    // Compute mean, width, and height of current map (boundaries of quadtree)
    double* mean_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        mean_Y[d] = .0;
    }

    double*  min_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        min_Y[d] =  DBL_MAX;
    }
    double*  max_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        max_Y[d] = -DBL_MAX;
    }

    for (int n = 0; n < N; n++) {
        for (int d = 0; d < QT_NO_DIMS; d++) {
            mean_Y[d] += inp_data[n * QT_NO_DIMS + d];
            min_Y[d] = min(min_Y[d], inp_data[n * QT_NO_DIMS + d]);
            max_Y[d] = max(max_Y[d], inp_data[n * QT_NO_DIMS + d]);
        }

    }

    double* width_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        mean_Y[d] /= (double) N;
        width_Y[d] = max(max_Y[d] - mean_Y[d], mean_Y[d] - min_Y[d]) + 1e-5;
    }

    // Construct quadtree
    init(NULL, inp_data, mean_Y, width_Y);
    fill(N);
    delete[] max_Y; delete[] min_Y;
}

// Constructor for quadtree with particular size and parent (do not fill the tree)
QuadTree::QuadTree(QuadTree* inp_parent, double* inp_data, double* mean_Y, double* width_Y)
{
    QT_NO_DIMS = inp_parent->QT_NO_DIMS;
    num_children = 1 << QT_NO_DIMS;

    init(inp_parent, inp_data, mean_Y, width_Y);
}

// Main initialization function
void QuadTree::init(QuadTree* inp_parent, double* inp_data, double* mean_Y, double* width_Y)
{
    // parent = inp_parent;
    data = inp_data;
    is_leaf = true;
    size = 0;
    cum_size = 0;

    boundary.center = mean_Y;
    boundary.width  = width_Y;
    boundary.n_dims = QT_NO_DIMS;

    index[0] = 0;

    center_of_mass = new double[QT_NO_DIMS];
    for (int i = 0; i < QT_NO_DIMS; i++) {
        center_of_mass[i] = .0;
    }
}

// Destructor for quadtree
QuadTree::~QuadTree()
{
    for(uint i = 0; i != children.size(); i++) {
        delete children[i];
    }
    delete[] center_of_mass;
}

// Insert a point into the QuadTree
bool QuadTree::insert(int new_index)
{
    // Ignore objects which do not belong in this quad tree
    double* point = data + new_index * QT_NO_DIMS;
    if (!boundary.containsPoint(point)) {
        return false;
    }

    // Online update of cumulative size and center-of-mass
    cum_size++;
    double mult1 = (double) (cum_size - 1) / (double) cum_size;
    double mult2 = 1.0 / (double) cum_size;
    for (int d = 0; d < QT_NO_DIMS; d++) {
        center_of_mass[d] = center_of_mass[d] * mult1 + mult2 * point[d];
    }

    // If there is space in this quad tree and it is a leaf, add the object here
    if (is_leaf && size < QT_NODE_CAPACITY) {
        index[size] = new_index;
        size++;
        return true;
    }

    // Don't add duplicates for now (this is not very nice)
    bool any_duplicate = false;
    for (int n = 0; n < size; n++) {
        bool duplicate = true;
        for (int d = 0; d < QT_NO_DIMS; d++) {
            if (point[d] != data[index[n] * QT_NO_DIMS + d]) { duplicate = false; break; }
        }
        any_duplicate = any_duplicate | duplicate;
    }
    if (any_duplicate) {
        return true;
    }

    // Otherwise, we need to subdivide the current cell
    if (is_leaf) {
        subdivide();
    }

    // Find out where the point can be inserted
    for (int i = 0; i < num_children; ++i) {
        if (children[i]->insert(new_index)) {
            return true;
        }
    }

    // Otherwise, the point cannot be inserted (this should never happen)
    printf("%s\n", "No no, this should not happen");
    return false;
}

int *get_bits(int n, int bitswanted){
  int *bits = new int[bitswanted];

  int k;
  for(k=0; k<bitswanted; k++) {
    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;
    bits[k] = thebit;
  }

  return bits;
}

// Create four children which fully divide this cell into four quads of equal area
void QuadTree::subdivide() {

    // Create children
    double* new_centers = new double[2 * QT_NO_DIMS];
    for(int i = 0; i < QT_NO_DIMS; ++i) {
        new_centers[i*2]     = boundary.center[i] - .5 * boundary.width[i];
        new_centers[i*2 + 1] = boundary.center[i] + .5 * boundary.width[i];
    }

    for (int i = 0; i < num_children; ++i) {
        int *bits = get_bits(i, QT_NO_DIMS);

        double* mean_Y = new double[QT_NO_DIMS];
        double* width_Y = new double[QT_NO_DIMS];

        // fill the means and width
        for (int d = 0; d < QT_NO_DIMS; d++) {
            mean_Y[d] = new_centers[d*2 + bits[d]];
            width_Y[d] = .5*boundary.width[d];
        }

        QuadTree* qt = new QuadTree(this, data, mean_Y, width_Y);
        children.push_back(qt);
        delete[] bits;
    }
    delete[] new_centers;

    // Move existing points to correct children
    for (int i = 0; i < size; i++) {
        bool flag = false;
        for (int j = 0; j < num_children; j++) {
            if (children[j]->insert(index[i])) {
                flag = true;
                break;
            }
        }
        if (flag == false) {
            index[i] = -1;
        }
    }

    // This node is not leaf now
    // Empty it
    size = 0;
    is_leaf = false;
}

// Build quadtree on dataset
void QuadTree::fill(int N)
{
    for (int i = 0; i < N; i++) {
        insert(i);
    }
}

// Compute non-edge forces using Barnes-Hut algorithm
void QuadTree::computeNonEdgeForces(int point_index, double theta, double* neg_f, double* sum_Q)
{
    // Make sure that we spend no time on empty nodes or self-interactions
    if (cum_size == 0 || (is_leaf && size == 1 && index[0] == point_index)) return;

    // Compute distance between point and center-of-mass
    double D = .0;
    int ind = point_index * QT_NO_DIMS;
    double* buff = new double[QT_NO_DIMS];

    for (int d = 0; d < QT_NO_DIMS; d++) {
        buff[d]  = data[ind + d];
        buff[d] -= center_of_mass[d];
        D += buff[d] * buff[d];
    }

    // Check whether we can use this node as a "summary"
    double m = -1;
    for (int i = 0; i < QT_NO_DIMS; ++i) {
        m = max(m, boundary.width[i]);
    }
    if (is_leaf || m / sqrt(D) < theta) {

        // Compute and add t-SNE force between point and current node
        double Q = 1.0 / (1.0 + D);
        *sum_Q += cum_size * Q;
        double mult = cum_size * Q * Q;
        for (int d = 0; d < QT_NO_DIMS; d++)
            neg_f[d] += mult * buff[d];
    }
    else {
        // Recursively apply Barnes-Hut to children
        for (int i = 0; i < num_children; ++i) {
            children[i]->computeNonEdgeForces(point_index, theta, neg_f, sum_Q);
        }
    }
    delete[] buff;
}

// Computes edge forces
void QuadTree::computeEdgeForces(int* row_P, int* col_P, double* val_P, int N, double* pos_f)
{

    // Loop over all edges in the graph
    double D;
    double* buff = new double[QT_NO_DIMS];

    for (int n = 0; n < N; n++) {
        int ind1 = n * QT_NO_DIMS;
        for (int i = row_P[n]; i < row_P[n + 1]; i++) {

            // Compute pairwise distance and Q-value
            D = .0;
            int ind2 = col_P[i] * QT_NO_DIMS;
            for (int d = 0; d < QT_NO_DIMS; d++) {
                buff[d]  = data[ind1 + d];
                buff[d] -= data[ind2 + d];
                D += buff[d] * buff[d];

            }
            D = val_P[i] / (1.0 + D);

            // Sum positive force
            for (int d = 0; d < QT_NO_DIMS; d++) {
                pos_f[ind1 + d] += D * buff[d];
            }
        }
    }
}
<commit_msg>free memory<commit_after>/*
 *  quadtree.cpp
 *  Implementation of a quadtree in two dimensions + Barnes-Hut algorithm for t-SNE.
 *
 *  Created by Laurens van der Maaten.
 *  Copyright 2012, Delft University of Technology. All rights reserved.
 *
 *  Multicore version by Dmitry Ulyanov, 2016. dmitry.ulyanov.msu@gmail.com
 */

#include <cmath>
#include <cfloat>
#include <cstdlib>
#include <cstdio>

#include "quadtree.h"

// Checks whether a point lies in a cell
bool Cell::containsPoint(double point[])
{
    for (int i = 0; i< n_dims; ++i) {
        if (abs_d(center[i] - point[i]) > width[i]) {
            return false;
        }
    }
    return true;
}

// Default constructor for quadtree -- build tree, too!
QuadTree::QuadTree(double* inp_data, int N, int no_dims)
{
    QT_NO_DIMS = no_dims;
    num_children = 1 << no_dims;

    // Compute mean, width, and height of current map (boundaries of quadtree)
    double* mean_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        mean_Y[d] = .0;
    }

    double*  min_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        min_Y[d] =  DBL_MAX;
    }
    double*  max_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        max_Y[d] = -DBL_MAX;
    }

    for (int n = 0; n < N; n++) {
        for (int d = 0; d < QT_NO_DIMS; d++) {
            mean_Y[d] += inp_data[n * QT_NO_DIMS + d];
            min_Y[d] = min(min_Y[d], inp_data[n * QT_NO_DIMS + d]);
            max_Y[d] = max(max_Y[d], inp_data[n * QT_NO_DIMS + d]);
        }

    }

    double* width_Y = new double[QT_NO_DIMS];
    for (int d = 0; d < QT_NO_DIMS; d++) {
        mean_Y[d] /= (double) N;
        width_Y[d] = max(max_Y[d] - mean_Y[d], mean_Y[d] - min_Y[d]) + 1e-5;
    }

    // Construct quadtree
    init(NULL, inp_data, mean_Y, width_Y);
    fill(N);
    delete[] max_Y; delete[] min_Y;
}

// Constructor for quadtree with particular size and parent (do not fill the tree)
QuadTree::QuadTree(QuadTree* inp_parent, double* inp_data, double* mean_Y, double* width_Y)
{
    QT_NO_DIMS = inp_parent->QT_NO_DIMS;
    num_children = 1 << QT_NO_DIMS;

    init(inp_parent, inp_data, mean_Y, width_Y);
}

// Main initialization function
void QuadTree::init(QuadTree* inp_parent, double* inp_data, double* mean_Y, double* width_Y)
{
    // parent = inp_parent;
    data = inp_data;
    is_leaf = true;
    size = 0;
    cum_size = 0;

    boundary.center = mean_Y;
    boundary.width  = width_Y;
    boundary.n_dims = QT_NO_DIMS;

    index[0] = 0;

    center_of_mass = new double[QT_NO_DIMS];
    for (int i = 0; i < QT_NO_DIMS; i++) {
        center_of_mass[i] = .0;
    }
}

// Destructor for quadtree
QuadTree::~QuadTree()
{
    for(uint i = 0; i != children.size(); i++) {
        delete children[i];
    }
    delete[] center_of_mass;
}

// Insert a point into the QuadTree
bool QuadTree::insert(int new_index)
{
    // Ignore objects which do not belong in this quad tree
    double* point = data + new_index * QT_NO_DIMS;
    if (!boundary.containsPoint(point)) {
        return false;
    }

    // Online update of cumulative size and center-of-mass
    cum_size++;
    double mult1 = (double) (cum_size - 1) / (double) cum_size;
    double mult2 = 1.0 / (double) cum_size;
    for (int d = 0; d < QT_NO_DIMS; d++) {
        center_of_mass[d] = center_of_mass[d] * mult1 + mult2 * point[d];
    }

    // If there is space in this quad tree and it is a leaf, add the object here
    if (is_leaf && size < QT_NODE_CAPACITY) {
        index[size] = new_index;
        size++;
        return true;
    }

    // Don't add duplicates for now (this is not very nice)
    bool any_duplicate = false;
    for (int n = 0; n < size; n++) {
        bool duplicate = true;
        for (int d = 0; d < QT_NO_DIMS; d++) {
            if (point[d] != data[index[n] * QT_NO_DIMS + d]) { duplicate = false; break; }
        }
        any_duplicate = any_duplicate | duplicate;
    }
    if (any_duplicate) {
        return true;
    }

    // Otherwise, we need to subdivide the current cell
    if (is_leaf) {
        subdivide();
    }

    // Find out where the point can be inserted
    for (int i = 0; i < num_children; ++i) {
        if (children[i]->insert(new_index)) {
            return true;
        }
    }

    // Otherwise, the point cannot be inserted (this should never happen)
    printf("%s\n", "No no, this should not happen");
    return false;
}

int *get_bits(int n, int bitswanted){
  int *bits = new int[bitswanted];

  int k;
  for(k=0; k<bitswanted; k++) {
    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;
    bits[k] = thebit;
  }

  return bits;
}

// Create four children which fully divide this cell into four quads of equal area
void QuadTree::subdivide() {

    // Create children
    double* new_centers = new double[2 * QT_NO_DIMS];
    for(int i = 0; i < QT_NO_DIMS; ++i) {
        new_centers[i*2]     = boundary.center[i] - .5 * boundary.width[i];
        new_centers[i*2 + 1] = boundary.center[i] + .5 * boundary.width[i];
    }

    for (int i = 0; i < num_children; ++i) {
        int *bits = get_bits(i, QT_NO_DIMS);

        double* mean_Y = new double[QT_NO_DIMS];
        double* width_Y = new double[QT_NO_DIMS];

        // fill the means and width
        for (int d = 0; d < QT_NO_DIMS; d++) {
            mean_Y[d] = new_centers[d*2 + bits[d]];
            width_Y[d] = .5*boundary.width[d];
        }

        QuadTree* qt = new QuadTree(this, data, mean_Y, width_Y);
        children.push_back(qt);
        delete[] bits;
    }
    delete[] new_centers;

    // Move existing points to correct children
    for (int i = 0; i < size; i++) {
        bool flag = false;
        for (int j = 0; j < num_children; j++) {
            if (children[j]->insert(index[i])) {
                flag = true;
                break;
            }
        }
        if (flag == false) {
            index[i] = -1;
        }
    }

    // This node is not leaf now
    // Empty it
    size = 0;
    is_leaf = false;
}

// Build quadtree on dataset
void QuadTree::fill(int N)
{
    for (int i = 0; i < N; i++) {
        insert(i);
    }
}

// Compute non-edge forces using Barnes-Hut algorithm
void QuadTree::computeNonEdgeForces(int point_index, double theta, double* neg_f, double* sum_Q)
{
    // Make sure that we spend no time on empty nodes or self-interactions
    if (cum_size == 0 || (is_leaf && size == 1 && index[0] == point_index)) return;

    // Compute distance between point and center-of-mass
    double D = .0;
    int ind = point_index * QT_NO_DIMS;
    double* buff = new double[QT_NO_DIMS];

    for (int d = 0; d < QT_NO_DIMS; d++) {
        buff[d]  = data[ind + d];
        buff[d] -= center_of_mass[d];
        D += buff[d] * buff[d];
    }

    // Check whether we can use this node as a "summary"
    double m = -1;
    for (int i = 0; i < QT_NO_DIMS; ++i) {
        m = max(m, boundary.width[i]);
    }
    if (is_leaf || m / sqrt(D) < theta) {

        // Compute and add t-SNE force between point and current node
        double Q = 1.0 / (1.0 + D);
        *sum_Q += cum_size * Q;
        double mult = cum_size * Q * Q;
        for (int d = 0; d < QT_NO_DIMS; d++)
            neg_f[d] += mult * buff[d];
    }
    else {
        // Recursively apply Barnes-Hut to children
        for (int i = 0; i < num_children; ++i) {
            children[i]->computeNonEdgeForces(point_index, theta, neg_f, sum_Q);
        }
    }
    delete[] buff;
}

// Computes edge forces
void QuadTree::computeEdgeForces(int* row_P, int* col_P, double* val_P, int N, double* pos_f)
{

    // Loop over all edges in the graph
    double D;
    double* buff = new double[QT_NO_DIMS];

    for (int n = 0; n < N; n++) {
        int ind1 = n * QT_NO_DIMS;
        for (int i = row_P[n]; i < row_P[n + 1]; i++) {

            // Compute pairwise distance and Q-value
            D = .0;
            int ind2 = col_P[i] * QT_NO_DIMS;
            for (int d = 0; d < QT_NO_DIMS; d++) {
                buff[d]  = data[ind1 + d];
                buff[d] -= data[ind2 + d];
                D += buff[d] * buff[d];

            }
            D = val_P[i] / (1.0 + D);

            // Sum positive force
            for (int d = 0; d < QT_NO_DIMS; d++) {
                pos_f[ind1 + d] += D * buff[d];
            }
        }
    }
    delete[] buff;
}
<|endoftext|>


<commit_before>/*******************************************************************************
Program:   Wake Forest University - Virginia Tech CTC Software
Id:        $Id$
Language:  C++
*******************************************************************************/
#include <limits>

#include "ctcSegmentProjectionFilter.h"

#include "itkImageLinearIteratorWithIndex.h"
#include "itkImageSliceConstIteratorWithIndex.h"

namespace ctc
{

  SegmentProjectionFilter::SegmentProjectionFilter()
  {

  }

  void SegmentProjectionFilter::GenerateOutputInformation()
  {

    // get pointers to the input and output
    Superclass::OutputImagePointer      outputPtr = this->GetOutput();
    Superclass::InputImageConstPointer  inputPtr  = this->GetInput();

    if ( !outputPtr || !inputPtr)
      {
	return;
      }
    BinaryImageType::RegionType inputRegion =
      inputPtr->GetLargestPossibleRegion();

    ProjectionImageType::RegionType outputRegion;
    ProjectionImageType::RegionType::SizeType outputSize;
    ProjectionImageType::RegionType::IndexType outputIndex;
    outputIndex[0] = 0;
    outputIndex[1] = 0;
    outputSize[0] = inputRegion.GetSize()[1];
    outputSize[1] = inputRegion.GetSize()[2];
    outputRegion.SetSize( outputSize );
    outputRegion.SetIndex( outputIndex );
    outputPtr->SetLargestPossibleRegion( outputRegion );
    outputPtr->SetBufferedRegion( outputRegion );
    outputPtr->SetRequestedRegion( outputRegion );

    BinaryImageType::SpacingType inputSpacing = inputPtr->GetSpacing();
    ProjectionImageType::SpacingType outputSpacing;
    outputSpacing[0] = inputSpacing[1];
    outputSpacing[1] = inputSpacing[2];
    outputPtr->SetSpacing( outputSpacing );

    BinaryImageType::DirectionType inputDirection = inputPtr->GetDirection();
    ProjectionImageType::DirectionType outputDirection;
    outputDirection[0][0] = inputDirection[0][1];
    outputDirection[1][0] = inputDirection[1][1];
    outputDirection[2][0] = inputDirection[2][1];
    outputDirection[0][1] = inputDirection[0][2];
    outputDirection[1][1] = inputDirection[1][2];
    outputDirection[2][1] = inputDirection[2][2];
    outputPtr->SetDirection(outputDirection);

    BinaryImageType::PointType inputOrigin = inputPtr->GetOrigin();
    ProjectionImageType::PointType outputOrigin;
    outputOrigin[0] = inputOrigin[0];
    outputOrigin[1] = inputOrigin[1];
    outputOrigin[2] = inputOrigin[2];
    outputPtr->SetOrigin( outputOrigin );
    outputPtr->SetNumberOfComponentsPerPixel(1);
  }

  void SegmentProjectionFilter::GenerateData()
  {
    // get pointer to input image
    BinaryImageType::ConstPointer inputImage = this->GetInput();

    // allocate the output image
    ProjectionImageType::Pointer outputImage = this->GetOutput();
    outputImage->Allocate();

    // create the projection
    BinaryImageType::RegionType inputRegion =
      this->GetInput()->GetLargestPossibleRegion();
    typedef itk::ImageSliceConstIteratorWithIndex<BinaryImageType> BinaryIteratorType;
    BinaryIteratorType
      iit(this->GetInput(),
	 inputRegion);
    typedef itk::ImageLinearIteratorWithIndex< ProjectionImageType >
      ProjectionIteratorType;
    ProjectionIteratorType oit(outputImage, outputImage->GetBufferedRegion());

    // integrate in the sagital direction
    iit.SetFirstDirection(0);
    iit.SetSecondDirection(2);

    clog << "hi" << endl;

    oit.SetDirection(0);

    iit.GoToBegin();
    oit.GoToBegin();
    while ( ! iit.IsAtEnd() )
      {
	while ( ! iit.IsAtEndOfSlice() )
	  {
	    while ( ! iit.IsAtEndOfLine() )
	      {
		oit.Set( oit.Get() + iit.Get() );
		++iit;
		++oit;
	      }
	    iit.NextLine();
	    oit.NextLine();
	  }
	iit.NextSlice();
	oit.GoToBegin();
      }
  }

  void SegmentProjectionFilter::PrintSelf(
				     std::ostream& os,
				     itk::Indent indent ) const
  {
    Superclass::PrintSelf(os,indent);
  }

}

<commit_msg>CLW undoing last change.<commit_after>/*******************************************************************************
Program:   Wake Forest University - Virginia Tech CTC Software
Id:        $Id$
Language:  C++
*******************************************************************************/
#include <limits>

#include "ctcSegmentProjectionFilter.h"

#include "itkImageLinearIteratorWithIndex.h"
#include "itkImageSliceConstIteratorWithIndex.h"

namespace ctc
{

  SegmentProjectionFilter::SegmentProjectionFilter()
  {

  }

  void SegmentProjectionFilter::GenerateOutputInformation()
  {

    // get pointers to the input and output
    Superclass::OutputImagePointer      outputPtr = this->GetOutput();
    Superclass::InputImageConstPointer  inputPtr  = this->GetInput();

    if ( !outputPtr || !inputPtr)
      {
	return;
      }
    BinaryImageType::RegionType inputRegion =
      inputPtr->GetLargestPossibleRegion();

    ProjectionImageType::RegionType outputRegion;
    ProjectionImageType::RegionType::SizeType outputSize;
    ProjectionImageType::RegionType::IndexType outputIndex;
    outputIndex[0] = 0;
    outputIndex[1] = 0;
    outputSize[0] = inputRegion.GetSize()[1];
    outputSize[1] = inputRegion.GetSize()[2];
    outputRegion.SetSize( outputSize );
    outputRegion.SetIndex( outputIndex );
    outputPtr->SetLargestPossibleRegion( outputRegion );
    outputPtr->SetBufferedRegion( outputRegion );
    outputPtr->SetRequestedRegion( outputRegion );

    BinaryImageType::SpacingType inputSpacing = inputPtr->GetSpacing();
    ProjectionImageType::SpacingType outputSpacing;
    outputSpacing[0] = inputSpacing[1];
    outputSpacing[1] = inputSpacing[2];
    outputPtr->SetSpacing( outputSpacing );

    BinaryImageType::DirectionType inputDirection = inputPtr->GetDirection();
    ProjectionImageType::DirectionType outputDirection;
    outputDirection[0][0] = inputDirection[0][1];
    outputDirection[1][0] = inputDirection[1][1];
    outputDirection[2][0] = inputDirection[2][1];
    outputDirection[0][1] = inputDirection[0][2];
    outputDirection[1][1] = inputDirection[1][2];
    outputDirection[2][1] = inputDirection[2][2];
    outputPtr->SetDirection(outputDirection);

    BinaryImageType::PointType inputOrigin = inputPtr->GetOrigin();
    ProjectionImageType::PointType outputOrigin;
    outputOrigin[0] = inputOrigin[0];
    outputOrigin[1] = inputOrigin[1];
    outputOrigin[2] = inputOrigin[2];
    outputPtr->SetOrigin( outputOrigin );
    outputPtr->SetNumberOfComponentsPerPixel(1);
  }

  void SegmentProjectionFilter::GenerateData()
  {
    // get pointer to input image
    BinaryImageType::ConstPointer inputImage = this->GetInput();

    // allocate the output image
    ProjectionImageType::Pointer outputImage = this->GetOutput();
    outputImage->Allocate();

    // create the projection
    BinaryImageType::RegionType inputRegion =
      this->GetInput()->GetLargestPossibleRegion();
    typedef itk::ImageSliceConstIteratorWithIndex<BinaryImageType> BinaryIteratorType;
    BinaryIteratorType
      iit(this->GetInput(),
	 inputRegion);
    typedef itk::ImageLinearIteratorWithIndex< ProjectionImageType >
      ProjectionIteratorType;
    ProjectionIteratorType oit(outputImage, outputImage->GetBufferedRegion());

    // integrate in the sagital direction
    iit.SetFirstDirection(0);
    iit.SetSecondDirection(2);

    oit.SetDirection(0);

    iit.GoToBegin();
    oit.GoToBegin();
    while ( ! iit.IsAtEnd() )
      {
	while ( ! iit.IsAtEndOfSlice() )
	  {
	    while ( ! iit.IsAtEndOfLine() )
	      {
		oit.Set( oit.Get() + iit.Get() );
		++iit;
		++oit;
	      }
	    iit.NextLine();
	    oit.NextLine();
	  }
	iit.NextSlice();
	oit.GoToBegin();
      }
  }

  void SegmentProjectionFilter::PrintSelf(
				     std::ostream& os,
				     itk::Indent indent ) const
  {
    Superclass::PrintSelf(os,indent);
  }

}

<|endoftext|>


<commit_before>/*
   All permutation.

   Constructs all permutations of 1, 2, ..., n via backtracking.

   (c) 2015 Josef Ziegler (ippeb24@gmail.com)

*/

#include <cstdio>
#include <string>
#define MAXCANDIDATES 10000
#define MAXN          10000
using namespace std;

bool is_solution(int A[], int k, int n){
  return(k==n);
}

void process_solution(int A[], int k, int n){
  for(int i=1; i<=k; i++) printf(" %d",A[i]);
  printf("\n");
}

void construct_candidates(int A[], int k, int n, int C[], int *ncandidates){
  bool in_perm[MAXN];
  memset(in_perm,0,MAXN);
  for (int i=1; i<k; i++) in_perm[A[i]]=true;
  *ncandidates = 0;
  for (int i=1; i<=n; i++)
    if (in_perm[i] == false){
      C[*ncandidates]=i;
      *ncandidates=*ncandidates+1;
    }
}

void backtrack(int A[], int k, int n){
  int C[MAXCANDIDATES];
  int ncandidates;
  if (is_solution(A,k,n))
    process_solution(A,k,n);
  else{
    k++;
    construct_candidates(A,k,n,C,&ncandidates);
    for (int i=0; i<ncandidates; i++){
      A[k]=C[i];
      backtrack(A,k,n);
    }
  }
}

int main(){
  int A[MAXN];
  int n;
  scanf("%d",&n);
  backtrack(A,0,n);
}
<commit_msg>combinatorics: Improved header of all permutation (int).<commit_after>/*
   All permutation (int).

   Constructs all permutations of 1, 2, ..., n via backtracking.
   This program was meant to be kept extensible.
   Adapted parts from the book "Programming Challenges" by Steven S. Skiena
   and Miguel A. Revilla, 2003, Springer.

   (c) 2015 Josef Ziegler (ippeb24@gmail.com)

*/

#include <cstdio>
#include <string>
#define MAXCANDIDATES 10000
#define MAXN          10000
using namespace std;

bool is_solution(int A[], int k, int n){
  return(k==n);
}

void process_solution(int A[], int k, int n){
  for(int i=1; i<=k; i++) printf(" %d",A[i]);
  printf("\n");
}

void construct_candidates(int A[], int k, int n, int C[], int *ncandidates){
  bool in_perm[MAXN];
  memset(in_perm,0,MAXN);
  for (int i=1; i<k; i++) in_perm[A[i]]=true;
  *ncandidates = 0;
  for (int i=1; i<=n; i++)
    if (in_perm[i] == false){
      C[*ncandidates]=i;
      *ncandidates=*ncandidates+1;
    }
}

void backtrack(int A[], int k, int n){
  int C[MAXCANDIDATES];
  int ncandidates;
  if (is_solution(A,k,n))
    process_solution(A,k,n);
  else{
    k++;
    construct_candidates(A,k,n,C,&ncandidates);
    for (int i=0; i<ncandidates; i++){
      A[k]=C[i];
      backtrack(A,k,n);
    }
  }
}

int main(){
  int A[MAXN];
  int n;
  scanf("%d",&n);
  backtrack(A,0,n);
}
<|endoftext|>


<commit_before>/*
 * LexicalReordering.cpp
 *
 *  Created on: 15 Dec 2015
 *      Author: hieu
 */

#include "LexicalReordering.h"
#include "../System.h"
#include "../Search/Manager.h"
#include "../legacy/InputFileStream.h"

using namespace std;

namespace Moses2 {

struct LexicalReorderingState : public FFState
{
  const Range *range;

  LexicalReorderingState()
  {
	  // uninitialised
  }

  size_t hash() const {
    return (size_t) range;
  }
  virtual bool operator==(const FFState& other) const {
	  const LexicalReorderingState &stateCast = static_cast<const LexicalReorderingState&>(other);
	  return range == stateCast.range;
  }

  virtual std::string ToString() const
  {
	  return "";
  }

};

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

LexicalReordering::LexicalReordering(size_t startInd, const std::string &line)
:StatefulFeatureFunction(startInd, line)
{
	ReadParameters();
}

LexicalReordering::~LexicalReordering()
{
	// TODO Auto-generated destructor stub
}

void LexicalReordering::Load(System &system)
{
  InputFileStream file(m_path);
  string line;
  size_t lineNum = 0;

  while(getline(file, line)) {
	if (++lineNum % 1000000 == 0) {
		cerr << lineNum << " ";
	}

	std::vector<std::string> toks = TokenizeMultiCharSeparator(line, "|||");
	assert(toks.size() == 3);
	PhraseImpl *source = PhraseImpl::CreateFromString(system.systemPool, system.GetVocab(), system, toks[0]);
	PhraseImpl *target = PhraseImpl::CreateFromString(system.systemPool, system.GetVocab(), system, toks[1]);
	std::vector<SCORE> scores = Tokenize<SCORE>(toks[2]);
    std::transform(scores.begin(), scores.end(), scores.begin(), TransformScore);

	Key key(source, target);
	m_coll[key] = scores;
  }
}

void LexicalReordering::SetParameter(const std::string& key, const std::string& value)
{
  if (key == "path") {
	  m_path = value;
  }
  else if (key == "type") {

  }
  else if (key == "input-factor") {

  }
  else if (key == "output-factor") {

  }

  else {
	  StatefulFeatureFunction::SetParameter(key, value);
  }
}

FFState* LexicalReordering::BlankState(const Manager &mgr, const InputType &input) const
{
  MemPool &pool = mgr.GetPool();
  return new (pool.Allocate<LexicalReorderingState>()) LexicalReorderingState();
}

void LexicalReordering::EmptyHypothesisState(FFState &state,
		const Manager &mgr,
		const InputType &input,
		const Hypothesis &hypo) const
{
	LexicalReorderingState &stateCast = static_cast<LexicalReorderingState&>(state);
	stateCast.range = &hypo.GetInputPath().range;
}

void LexicalReordering::EvaluateWhenApplied(const Manager &mgr,
  const Hypothesis &hypo,
  const FFState &prevState,
  Scores &scores,
  FFState &state) const
{
  const LexicalReorderingState &prevStateCast = static_cast<const LexicalReorderingState&>(prevState);
  LexicalReorderingState &stateCast = static_cast<LexicalReorderingState&>(state);
cerr << "hypo=" << hypo << endl;
  const Range &currRange = hypo.GetInputPath().range;
  stateCast.range = &currRange;

  const Phrase &source = hypo.GetInputPath().subPhrase;
  const Phrase &target = hypo.GetTargetPhrase();

  const LexicalReordering::Values *values = GetValues(source, target);

  if (values) {
	  size_t orientation;
	  vector<SCORE> scoreVec(6, 0);

	  const Range *prevRange = prevStateCast.range;
	  assert(prevRange);

	  if (prevRange->GetStartPos() == NOT_FOUND) {
		  orientation = GetOrientation(currRange);
		  scoreVec[orientation] = (*values)[orientation];
	  }
	  else {
		  orientation = GetOrientation(*prevRange, currRange);
		  scoreVec[orientation] = (*values)[orientation];
		  scoreVec[2 + orientation] = (*values)[2 + orientation];
	  }

	  scores.PlusEquals(mgr.system, *this, scoreVec);
  }
}

const LexicalReordering::Values *LexicalReordering::GetValues(const Phrase &source, const Phrase &target) const
{
	Key key(&source, &target);
	Coll::const_iterator iter;
	iter = m_coll.find(key);
	if (iter == m_coll.end()) {
		return NULL;
	}
	else {
		return &iter->second;
	}
}

size_t LexicalReordering::GetOrientation(Range const& cur) const
{
  return (cur.GetStartPos() == 0) ? 0 : 1;
}

size_t LexicalReordering::GetOrientation(Range const& prev, Range const& cur) const
{
  if (cur.GetStartPos() == prev.GetEndPos() + 1) {
	  // monotone
	  return 0;
  }
  else if (prev.GetStartPos() ==  cur.GetEndPos() + 1) {
	  // swap
	  return 1;
  }
  else {
	  // discontinuous
	  return 2;
  }
}

} /* namespace Moses2 */
<commit_msg>correct offset<commit_after>/*
 * LexicalReordering.cpp
 *
 *  Created on: 15 Dec 2015
 *      Author: hieu
 */

#include "LexicalReordering.h"
#include "../System.h"
#include "../Search/Manager.h"
#include "../legacy/InputFileStream.h"

using namespace std;

namespace Moses2 {

struct LexicalReorderingState : public FFState
{
  const Range *range;

  LexicalReorderingState()
  {
	  // uninitialised
  }

  size_t hash() const {
    return (size_t) range;
  }
  virtual bool operator==(const FFState& other) const {
	  const LexicalReorderingState &stateCast = static_cast<const LexicalReorderingState&>(other);
	  return range == stateCast.range;
  }

  virtual std::string ToString() const
  {
	  return "";
  }

};

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

LexicalReordering::LexicalReordering(size_t startInd, const std::string &line)
:StatefulFeatureFunction(startInd, line)
{
	ReadParameters();
}

LexicalReordering::~LexicalReordering()
{
	// TODO Auto-generated destructor stub
}

void LexicalReordering::Load(System &system)
{
  InputFileStream file(m_path);
  string line;
  size_t lineNum = 0;

  while(getline(file, line)) {
	if (++lineNum % 1000000 == 0) {
		cerr << lineNum << " ";
	}

	std::vector<std::string> toks = TokenizeMultiCharSeparator(line, "|||");
	assert(toks.size() == 3);
	PhraseImpl *source = PhraseImpl::CreateFromString(system.systemPool, system.GetVocab(), system, toks[0]);
	PhraseImpl *target = PhraseImpl::CreateFromString(system.systemPool, system.GetVocab(), system, toks[1]);
	std::vector<SCORE> scores = Tokenize<SCORE>(toks[2]);
    std::transform(scores.begin(), scores.end(), scores.begin(), TransformScore);

	Key key(source, target);
	m_coll[key] = scores;
  }
}

void LexicalReordering::SetParameter(const std::string& key, const std::string& value)
{
  if (key == "path") {
	  m_path = value;
  }
  else if (key == "type") {

  }
  else if (key == "input-factor") {

  }
  else if (key == "output-factor") {

  }

  else {
	  StatefulFeatureFunction::SetParameter(key, value);
  }
}

FFState* LexicalReordering::BlankState(const Manager &mgr, const InputType &input) const
{
  MemPool &pool = mgr.GetPool();
  return new (pool.Allocate<LexicalReorderingState>()) LexicalReorderingState();
}

void LexicalReordering::EmptyHypothesisState(FFState &state,
		const Manager &mgr,
		const InputType &input,
		const Hypothesis &hypo) const
{
	LexicalReorderingState &stateCast = static_cast<LexicalReorderingState&>(state);
	stateCast.range = &hypo.GetInputPath().range;
}

void LexicalReordering::EvaluateWhenApplied(const Manager &mgr,
  const Hypothesis &hypo,
  const FFState &prevState,
  Scores &scores,
  FFState &state) const
{
  const LexicalReorderingState &prevStateCast = static_cast<const LexicalReorderingState&>(prevState);
  LexicalReorderingState &stateCast = static_cast<LexicalReorderingState&>(state);

  const Range &currRange = hypo.GetInputPath().range;
  stateCast.range = &currRange;

  const Phrase &source = hypo.GetInputPath().subPhrase;
  const Phrase &target = hypo.GetTargetPhrase();

  const LexicalReordering::Values *values = GetValues(source, target);

  if (values) {
	  size_t orientation;
	  vector<SCORE> scoreVec(6, 0);

	  const Range *prevRange = prevStateCast.range;
	  assert(prevRange);

	  if (prevRange->GetStartPos() == NOT_FOUND) {
		  orientation = GetOrientation(currRange);
		  scoreVec[orientation] = (*values)[orientation];
	  }
	  else {
		  orientation = GetOrientation(*prevRange, currRange);
		  scoreVec[orientation] = (*values)[orientation];
		  scoreVec[3 + orientation] = (*values)[3 + orientation];
	  }

	  scores.PlusEquals(mgr.system, *this, scoreVec);
  }
}

const LexicalReordering::Values *LexicalReordering::GetValues(const Phrase &source, const Phrase &target) const
{
	Key key(&source, &target);
	Coll::const_iterator iter;
	iter = m_coll.find(key);
	if (iter == m_coll.end()) {
		return NULL;
	}
	else {
		return &iter->second;
	}
}

size_t LexicalReordering::GetOrientation(Range const& cur) const
{
  return (cur.GetStartPos() == 0) ? 0 : 1;
}

size_t LexicalReordering::GetOrientation(Range const& prev, Range const& cur) const
{
  if (cur.GetStartPos() == prev.GetEndPos() + 1) {
	  // monotone
	  return 0;
  }
  else if (prev.GetStartPos() ==  cur.GetEndPos() + 1) {
	  // swap
	  return 1;
  }
  else {
	  // discontinuous
	  return 2;
  }
}

} /* namespace Moses2 */
<|endoftext|>


<commit_before>//CPPUnit includes
#include "cppunit/CompilerOutputter.h"
#include "cppunit/ui/text/TestRunner.h"
#include "cppunit/extensions/TestFactoryRegistry.h"

//libMesh includes
#include "perf_log.h"

//Moose includes
#include "ColumnMajorMatrixTest.h"
#include "Moose.h"

PerfLog Moose::perf_log("CppUnit");

int main(int argc, char **argv)
{
  CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();

  CppUnit::TextUi::TestRunner runner;
  runner.addTest(suite);

  runner.setOutputter ( new CppUnit::CompilerOutputter( &runner.result(), std::cerr ) );

  bool wasSucessful = runner.run();

  return wasSucessful ? 0 : 1;
}
<commit_msg>Changing output to XML<commit_after>//CPPUnit includes
#include "cppunit/XmlOutputter.h"
#include "cppunit/CompilerOutputter.h"
#include "cppunit/ui/text/TestRunner.h"
#include "cppunit/extensions/TestFactoryRegistry.h"

//libMesh includes
#include "perf_log.h"

//Moose includes
#include "ColumnMajorMatrixTest.h"
#include "Moose.h"

PerfLog Moose::perf_log("CppUnit");

int main(int argc, char **argv)
{
  CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();

  CppUnit::TextUi::TestRunner runner;
  runner.addTest(suite);

  /* Uncomment the following line for bitten testing */
  runner.setOutputter ( new CppUnit::XmlOutputter( &runner.result(), std::cerr ) );

  /* Uncomment the following line for CLI testing */
  //runner.setOutputter ( new CppUnit::CompilerOutputter( &runner.result(), std::cerr ) );

  bool wasSucessful = runner.run();

  return wasSucessful ? 0 : 1;
}
<|endoftext|>


<commit_before>#include <Unity.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

using namespace std;

#define MOCK_SIZE 513 // number of lines with mocked values

static double mockData[MOCK_SIZE];

Unity::Unity()
{
	this->buildPid = 0;
	cout << "Initiating Unity" << endl;
}

Unity::~Unity()
{
	if(this->buildPid > 0)
	{
		cout << "Killing unity process: " << this->buildPid << endl;
		kill(this->buildPid, SIGTERM);
	}

	if(!this->infoFile.is_open())
		this->infoFile.close();

	if(!this->altitudeFile.is_open())
		this->altitudeFile.close();

	if(!this->rotationFile.is_open())
		this->rotationFile.close();

	if(!this->positionFile.is_open())
		this->positionFile.close();

	cout << "Terminating Unity" << endl;
}

void Unity::initBuild()
{
	// Creates a whole new process
	this->buildPid = fork();
	if(this->buildPid == -1)
	{
		cout << "Problems while initiazing a new process!!!" << endl;
		perror("Reason");
		exit(-1);
	}

	// pid > 0 means this is still parent process
	if(this->buildPid > 0)
	{
		cout << "Initiating unity build with the process: " << this->buildPid << endl;
		return; // so we just keep doing our amazing job
	}

	// If we got here, from the line bellow until exit(0) means totaly the child process
	cout << "$ " << CURRENT_UNITY_BUILD << endl;
	int rc = execl(CURRENT_UNITY_BUILD, "currentBuild", NULL);
	if(rc == -1)
	{
		cout << "Error while initiating unity build" << endl;
		perror("Reason");
	}
	exit(0);
}

void Unity::init()
{
	// First forks this process do load the heavy unity application
	this->initBuild();

	// Now open some useful files
	this->altitudeFile.open(UNITY_ALTITUDE_FILE, std::ios::in | std::ios::binary | std::ios::ate);
	this->infoFile.open(UNITY_INFO_FILE);
	this->rotationFile.open(UNITY_ROTATION_FILE);
	this->positionFile.open(UNITY_POSITION_FILE);

	if(!this->infoFile.is_open() || !this->altitudeFile.is_open() ||
	   !this->rotationFile.is_open() || this->positionFile.is_open())
	{
		cout << "Couldn't open unity communication files";
	}
}

int Unity::getPlayerAltitude()
{
	static std::ifstream file;
	int returned = -1;

	#ifdef MOCK_DATA
		std::cout << "Mocaaaando" << std::endl;
		static int mockIndex = 0;

		// First time
		if(MOCK_SIZE == 0)
		{
			file.open("files/unity_altitude_mock.txt", std::ios::in | std::ios::binary | std::ios::ate);
			if(file.is_open())
			{
				for(int i = 0; i < MOCK_SIZE; i++)
					file >> mockData[i];
				file.close();
				std::cout << "Unity mockData loaded: " << MOCK_SIZE * sizeof(double) << " bytes long" << std::endl;
			}
			else
			{
				std::cout << "Failed to load unity mockData" << std::endl;
				mockData[0] = -1.0;
			}
		}

		if(mockIndex >= MOCK_SIZE)
			mockIndex = 0;

		returned = (int)mockData[mockIndex];
		mockIndex++;

	#else
		if(this->altitudeFile.is_open())
		{
			// Make sure to read new data
			this->altitudeFile.sync();

			this->altitudeFile >> returned;

			// Rewinds it, so next time it will read from the beginning again
			this->altitudeFile.seekg(0, ios_base::beg);
		}
		else
			std::cout << "Failed to load unity altitude" << std::endl;

	#endif

	return returned;
}

void Unity::setPlayerPosition(double speed)
{
	if(this->positionFile.is_open())
	{
		// Rewinds it, so it will write to the beginning again
		// TODO: how to come back to the beginning of the output file?
		// this->positionFile.seekg(0);

		this->positionFile << speed;

		// Make sure to write new data
		this->positionFile.flush();
	}
	else
		std::cout << "Failed to write unity position" << std::endl;
}

void Unity::setPlayerRotation(double rotation)
{
	if(this->rotationFile.is_open())
	{
		// Rewinds it, so it will write to the beginning again
		// TODO: how to come back to the beginning of the output file?
		//this->rotationFile.seekg(0);

		this->rotationFile << rotation;

		// Make sure to write new data
		this->rotationFile.flush();
	}
	else
		std::cout << "Failed to write unity rotation" << std::endl;
}

void Unity::setInfo(const char * info, int chars_written)
{
	if(this->infoFile.is_open())
	{
		// Rewinds it, so it will write to the beginning again
		// TODO: how to come back to the beginning of the output file?
		//this->infoFile.seekg(0);

		this->infoFile << info;

		// Make sure to write new data
		this->infoFile.flush();
	}
	else
		std::cout << "Failed to write unity information" << std::endl;
}

void Unity::render()
{
	// TODO: somehow tell unity to keep rendering the frames
}
<commit_msg>Writing on the first position on files unity_rotation.txt and unity_speed.txt<commit_after>#include <Unity.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

using namespace std;

#define MOCK_SIZE 513 // number of lines with mocked values

static double mockData[MOCK_SIZE];

Unity::Unity()
{
	this->buildPid = 0;
	cout << "Initiating Unity" << endl;
}

Unity::~Unity()
{
	if(this->buildPid > 0)
	{
		cout << "Killing unity process: " << this->buildPid << endl;
		kill(this->buildPid, SIGTERM);
	}

	if(!this->infoFile.is_open())
		this->infoFile.close();

	if(!this->altitudeFile.is_open())
		this->altitudeFile.close();

	if(!this->rotationFile.is_open())
		this->rotationFile.close();

	if(!this->positionFile.is_open())
		this->positionFile.close();

	cout << "Terminating Unity" << endl;
}

void Unity::initBuild()
{
	// Creates a whole new process
	this->buildPid = fork();
	if(this->buildPid == -1)
	{
		cout << "Problems while initiazing a new process!!!" << endl;
		perror("Reason");
		exit(-1);
	}

	// pid > 0 means this is still parent process
	if(this->buildPid > 0)
	{
		cout << "Initiating unity build with the process: " << this->buildPid << endl;
		return; // so we just keep doing our amazing job
	}

	// If we got here, from the line bellow until exit(0) means totaly the child process
	cout << "$ " << CURRENT_UNITY_BUILD << endl;
	int rc = execl(CURRENT_UNITY_BUILD, "currentBuild", NULL);
	if(rc == -1)
	{
		cout << "Error while initiating unity build" << endl;
		perror("Reason");
	}
	exit(0);
}

void Unity::init()
{
	// First forks this process do load the heavy unity application
	this->initBuild();

	// Now open some useful files
	this->altitudeFile.open(UNITY_ALTITUDE_FILE, std::ios::in | std::ios::binary | std::ios::ate);
	this->infoFile.open(UNITY_INFO_FILE);
	this->rotationFile.open(UNITY_ROTATION_FILE);
	this->positionFile.open(UNITY_POSITION_FILE);

	if(!this->infoFile.is_open() || !this->altitudeFile.is_open() ||
	   !this->rotationFile.is_open() || this->positionFile.is_open())
	{
		cout << "Couldn't open unity communication files";
	}
}

int Unity::getPlayerAltitude()
{
	static std::ifstream file;
	int returned = -1;

	#ifdef MOCK_DATA
		std::cout << "Mocaaaando" << std::endl;
		static int mockIndex = 0;

		// First time
		if(MOCK_SIZE == 0)
		{
			file.open("files/unity_altitude_mock.txt", std::ios::in | std::ios::binary | std::ios::ate);
			if(file.is_open())
			{
				for(int i = 0; i < MOCK_SIZE; i++)
					file >> mockData[i];
				file.close();
				std::cout << "Unity mockData loaded: " << MOCK_SIZE * sizeof(double) << " bytes long" << std::endl;
			}
			else
			{
				std::cout << "Failed to load unity mockData" << std::endl;
				mockData[0] = -1.0;
			}
		}

		if(mockIndex >= MOCK_SIZE)
			mockIndex = 0;

		returned = (int)mockData[mockIndex];
		mockIndex++;

	#else
		if(this->altitudeFile.is_open())
		{
			// Make sure to read new data
			this->altitudeFile.sync();

			this->altitudeFile >> returned;

			// Rewinds it, so next time it will read from the beginning again
			this->altitudeFile.seekg(0, ios_base::beg);
		}
		else
			std::cout << "Failed to load unity altitude" << std::endl;

	#endif

	return returned;
}

void Unity::setPlayerPosition(double speed)
{
	if(this->positionFile.is_open())
	{
		// Rewinds it, so it will write to the beginning again
		// TODO: how to come back to the beginning of the output file?
		// this->positionFile.seekg(0);

		this->positionFile << '\r' << speed;

		// Make sure to write new data
		this->positionFile.flush();
	}
	else
		std::cout << "Failed to write unity position" << std::endl;
}

void Unity::setPlayerRotation(double rotation)
{
	if(this->rotationFile.is_open())
	{
		// Rewinds it, so it will write to the beginning again
		// TODO: how to come back to the beginning of the output file?
		//this->rotationFile.seekg(0);

		this->rotationFile << '\r'  << rotation;

		// Make sure to write new data
		this->rotationFile.flush();
	}
	else
		std::cout << "Failed to write unity rotation" << std::endl;
}

void Unity::setInfo(const char * info, int chars_written)
{
	if(this->infoFile.is_open())
	{
		// Rewinds it, so it will write to the beginning again
		// TODO: how to come back to the beginning of the output file?
		//this->infoFile.seekg(0);

		this->infoFile << info;

		// Make sure to write new data
		this->infoFile.flush();
	}
	else
		std::cout << "Failed to write unity information" << std::endl;
}

void Unity::render()
{
	// TODO: somehow tell unity to keep rendering the frames
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2012-1015 Alex Zhondin <qtinuum.team@gmail.com>

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

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

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

#include "PropertyDelegateQFont.h"
#include "../../../Core/GUI/PropertyQFont.h"
#include "../../../Core/Core/PropertyQString.h"
#include "../../../Core/Core/PropertyUInt.h"
#include "../../../Core/Core/PropertyBool.h"
#include "../../../Core/Core/PropertyEnum.h"
#include "../PropertyDelegateFactory.h"
#include "../PropertyEditorHandler.h"
#include "../PropertyEditorAux.h"
#include "../Core/PropertySet.h"

#include <QFontDialog>
#include <QFontDatabase>

#include <memory>

static QString FontToStr(const QFont &font)
{
	int size = font.pointSize();
	bool pixels = (size < 0);
	if (pixels)
		size = font.pixelSize();

	return QString("[%1, %2 %3]").arg(font.family(), QString::number(size), QString(pixels ? "px" : "pt"));
}

class QtnPropertyQFontLineEditBttnHandler
		: public QtnPropertyEditorBttnHandler<QtnPropertyQFontBase, QtnLineEditBttn>
{
public:
	QtnPropertyQFontLineEditBttnHandler(QtnPropertyQFontBase& property, QtnLineEditBttn& editor)
		: QtnPropertyEditorHandlerType(property, editor)
	{
		editor.lineEdit->setReadOnly(true);

		if (!property.isEditableByUser())
		{
			editor.toolButton->setEnabled(false);
		}

		updateEditor();
		editor.lineEdit->installEventFilter(this);
		QObject::connect(editor.toolButton, &QToolButton::clicked,
						 this, &QtnPropertyQFontLineEditBttnHandler::onToolButtonClicked);
	}

protected:
	virtual void onToolButtonClick() override { onToolButtonClicked(false); }
	virtual void updateEditor() override
	{
		editor().lineEdit->setText(FontToStr(property()));
	}

private:
	void onToolButtonClicked(bool)
	{
		auto property = &this->property();
		volatile bool destroyed = false;
		auto connection = QObject::connect(property, &QObject::destroyed, [&destroyed]() mutable
		{
			destroyed = true;
		});
		QFontDialog dlg(property->value(), &editor());
		if (dlg.exec() == QDialog::Accepted && !destroyed)
		{
			auto font = property->value();
			auto style_strategy = font.styleStrategy();
			int pixel_size = font.pixelSize();
			font = dlg.currentFont();

			if (pixel_size > 0)
				font.setPixelSize(font.pointSize());

			font.setStyleStrategy(style_strategy);

			property->setValue(font);
			property->propertyDidChange(property, property, QtnPropertyChangeReasonChildren);
		}

		if (!destroyed)
			QObject::disconnect(connection);
	}
};

static bool regQFontDelegate = QtnPropertyDelegateFactory::staticInstance()
								.registerDelegateDefault(&QtnPropertyQFontBase::staticMetaObject
								, &qtnCreateDelegate<QtnPropertyDelegateQFont, QtnPropertyQFontBase>
								, "LineEditBttn");

static QtnEnumInfo* styleStrategyEnum()
{
	static QtnEnumInfo* enumInfo = nullptr;
	if (!enumInfo)
	{
		QVector<QtnEnumValueInfo> items;
		items.append(QtnEnumValueInfo(QFont::PreferDefault, QtnPropertyQFont::getPreferDefaultStr()));
		items.append(QtnEnumValueInfo(QFont::NoAntialias, QtnPropertyQFont::getNoAntialiasStr()));
		items.append(QtnEnumValueInfo(QFont::PreferAntialias, QtnPropertyQFont::getPreferAntialiasStr()));
		enumInfo = new QtnEnumInfo("FontStyleStrategy", items);
	}

	return enumInfo;
}

enum
{
	SizeUnitPixel,
	SizeUnitPoint
};

static QtnEnumInfo* sizeUnitEnum()
{
	static QtnEnumInfo* enumInfo = nullptr;
	if (!enumInfo)
	{
		QVector<QtnEnumValueInfo> items;
		items.append(QtnEnumValueInfo(SizeUnitPixel, QtnPropertyQFont::getPixelStr()));
		items.append(QtnEnumValueInfo(SizeUnitPoint, QtnPropertyQFont::getPointStr()));
		enumInfo = new QtnEnumInfo("FontSizeUnit", items);
	}

	return enumInfo;
}

QtnPropertyDelegateQFont::QtnPropertyDelegateQFont(QtnPropertyQFontBase& owner)
	: QtnPropertyDelegateTypedEx<QtnPropertyQFontBase>(owner)
{
	QtnPropertyQStringCallback* propertyStyle = new QtnPropertyQStringCallback(0);

	QtnPropertyQStringCallback* propertyFamily = new QtnPropertyQStringCallback(0);
	addSubProperty(propertyFamily);
	propertyFamily->setName(QtnPropertyQFont::getFamilyLabel());
	propertyFamily->setDescription(QtnPropertyQFont::getFamilyDescription(owner.name()));
	propertyFamily->setCallbackValueGet([&owner]()->QString {
		return owner.value().family();
	});
	propertyFamily->setCallbackValueSet([&owner, propertyStyle, propertyFamily](QString value) {
		QFont font = owner.value();
		font.setFamily(value);
		owner.setValue(font);

#ifdef Q_OS_MAC
		QtnPropertyDelegateInfo delegate;
		delegate.name = "List";
		QFontDatabase fDB;
		delegate.attributes["items"] = QStringList("") + fDB.styles(value);
		delegate.attributes["editable"] = true;
		propertyStyle->setDelegate(delegate);

		std::shared_ptr<QMetaObject::Connection> c(new QMetaObject::Connection);
		*c.get() = QObject::connect(propertyFamily, &QtnPropertyBase::propertyDidChange, [&owner, c]() mutable
		{
			QObject::disconnect(*c.get());
			c = nullptr;

			owner.propertyDidChange(&owner, &owner, QtnPropertyChangeReasonChildren);
		});
#endif
	});

	QtnPropertyDelegateInfo delegate;
	delegate.name = "List";
	QFontDatabase fDB;
	delegate.attributes["items"] = fDB.families();
	propertyFamily->setDelegate(delegate);

	propertyStyle->setName(QtnPropertyQFont::getStyleLabel());
	propertyStyle->setDescription(QtnPropertyQFont::getStyleDescription(owner.name()));
	propertyStyle->setCallbackValueGet([&owner]()->QString {
		return owner.value().styleName();
	});
	propertyStyle->setCallbackValueSet([&owner](QString value) {
		QFont font = owner.value();
		font.setStyleName(value);
		owner.setValue(font);
	});

#ifdef Q_OS_MAC
	delegate.name = "List";
	delegate.attributes["items"] = QStringList("") + fDB.styles(owner.value().family());
	delegate.attributes["editable"] = true;
#else
	delegate.name = "LineEdit";
	delegate.attributes["multiline_edit"] = false;
#endif
	propertyStyle->setDelegate(delegate);

	addSubProperty(propertyStyle);

	QtnPropertyUIntCallback* propertySize = new QtnPropertyUIntCallback(0);
	addSubProperty(propertySize);
	propertySize->setName(QtnPropertyQFont::getSizeLabel());
	propertySize->setDescription(QtnPropertyQFont::getSizeDescription(owner.name()));
	propertySize->setCallbackValueGet([&owner]() -> quint32
	{
		int ps = owner.value().pointSize();
		if (ps < 0)
			ps = owner.value().pixelSize();
		if (ps < 1)
			ps = 1;
		return ps;
	});
	propertySize->setCallbackValueSet([&owner](quint32 value)
	{
		if (value == 0)
			value = 1;

		QFont font = owner.value();
		if (font.pointSize() > 0)
		{
			if (value > 128)
				value = 128;

			font.setPointSize((int) value);
		} else
		{
			if (value > 256)
				value = 256;

			font.setPixelSize((int) value);
		}
		owner.setValue(font);
	});

	QtnPropertyEnumCallback* propertySizeUnit = new QtnPropertyEnumCallback(0);
	addSubProperty(propertySizeUnit);
	propertySizeUnit->setName(QtnPropertyQFont::getSizeUnitLabel());
	propertySizeUnit->setDescription(QtnPropertyQFont::getSizeUnitDescription(owner.name()));
	propertySizeUnit->setEnumInfo(sizeUnitEnum());
	propertySizeUnit->setCallbackValueGet([&owner]() -> QtnEnumValueType
	{
		if (owner.value().pointSize() < 0)
			return SizeUnitPixel;

		return SizeUnitPoint;
	});
	propertySizeUnit->setCallbackValueSet([&owner](QtnEnumValueType value)
	{
		QFont font = owner.value();

		int size = std::max(font.pointSize(), font.pixelSize());

		switch (value)
		{
			case SizeUnitPixel:
				font.setPixelSize(size);
				break;

			case SizeUnitPoint:
				font.setPointSize(size);
				break;

			default:
				break;
		}

		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyBold = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyBold);
	propertyBold->setName(QtnPropertyQFont::getBoldLabel());
	propertyBold->setDescription(QtnPropertyQFont::getBoldDescription(owner.name()));
	propertyBold->setCallbackValueGet([&owner]()->bool {
		return owner.value().bold();
	});
	propertyBold->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setBold(value);
		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyItalic = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyItalic);
	propertyItalic->setName(QtnPropertyQFont::getItalicLabel());
	propertyItalic->setDescription(QtnPropertyQFont::getItalicDescription(owner.name()));
	propertyItalic->setCallbackValueGet([&owner]()->bool {
		return owner.value().italic();
	});
	propertyItalic->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setItalic(value);
		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyUnderline = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyUnderline);
	propertyUnderline->setName(QtnPropertyQFont::getUnderlineLabel());
	propertyUnderline->setDescription(QtnPropertyQFont::getUnderlineDescription(owner.name()));
	propertyUnderline->setCallbackValueGet([&owner]()->bool {
		return owner.value().underline();
	});
	propertyUnderline->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setUnderline(value);
		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyStrikeout = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyStrikeout);
	propertyStrikeout->setName(QtnPropertyQFont::getStrikeoutLabel());
	propertyStrikeout->setDescription(QtnPropertyQFont::getStrikeoutDescription(owner.name()));
	propertyStrikeout->setCallbackValueGet([&owner]()->bool {
		return owner.value().strikeOut();
	});
	propertyStrikeout->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setStrikeOut(value);
		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyKerning = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyKerning);
	propertyKerning->setName(QtnPropertyQFont::getKerningLabel());
	propertyKerning->setDescription(QtnPropertyQFont::getKerningDescription(owner.name()));
	propertyKerning->setCallbackValueGet([&owner]()->bool {
		return owner.value().kerning();
	});
	propertyKerning->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setKerning(value);
		owner.setValue(font);
	});

	QtnPropertyEnumCallback* propertyAntialiasing = new QtnPropertyEnumCallback(0);
	addSubProperty(propertyAntialiasing);
	propertyAntialiasing->setName(QtnPropertyQFont::getAntialiasingLabel());
	propertyAntialiasing->setDescription(QtnPropertyQFont::getAntialiasingDescription(owner.name()));
	propertyAntialiasing->setEnumInfo(styleStrategyEnum());
	propertyAntialiasing->setCallbackValueGet([&owner]()->QtnEnumValueType {
		return owner.value().styleStrategy();
	});
	propertyAntialiasing->setCallbackValueSet([&owner](QtnEnumValueType value) {
		QFont font = owner.value();
		font.setStyleStrategy((QFont::StyleStrategy)value);
		owner.setValue(font);
	});
}

void QtnPropertyDelegateQFont::drawValueImpl(QStylePainter& painter, const QRect& rect, const QStyle::State& state, bool* needTooltip) const
{
	QFont value = owner().value();

	QRect textRect = rect;

	if (textRect.isValid())
	{
		QRect br;

		QFont oldFont = painter.font();
		QFont newFont(value);
		newFont.setPointSize(oldFont.pointSize());
		painter.setFont(newFont);
		painter.drawText(textRect, Qt::AlignLeading | Qt::AlignVCenter, "A", &br);
		painter.setFont(oldFont);

		textRect.setLeft(br.right() + 3);
	}

	if (textRect.isValid())
	{
		QtnPropertyDelegateTypedEx<QtnPropertyQFontBase>::drawValueImpl(painter, textRect, state, needTooltip);
	}
}

QWidget* QtnPropertyDelegateQFont::createValueEditorImpl(QWidget* parent, const QRect& rect, QtnInplaceInfo* inplaceInfo)
{
	QtnLineEditBttn* editor = new QtnLineEditBttn(parent);
	editor->setGeometry(rect);

	new QtnPropertyQFontLineEditBttnHandler(owner(), *editor);

	if (inplaceInfo)
	{
		editor->lineEdit->selectAll();
	}

	return editor;
}

bool QtnPropertyDelegateQFont::propertyValueToStr(QString& strValue) const
{
	strValue = FontToStr(owner().value());
	return true;
}
<commit_msg>QtnPropertyDelegateQFont style updates bold and italic flags<commit_after>/*
   Copyright (c) 2012-1015 Alex Zhondin <qtinuum.team@gmail.com>

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

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

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

#include "PropertyDelegateQFont.h"
#include "../../../Core/GUI/PropertyQFont.h"
#include "../../../Core/Core/PropertyQString.h"
#include "../../../Core/Core/PropertyUInt.h"
#include "../../../Core/Core/PropertyBool.h"
#include "../../../Core/Core/PropertyEnum.h"
#include "../PropertyDelegateFactory.h"
#include "../PropertyEditorHandler.h"
#include "../PropertyEditorAux.h"
#include "../Core/PropertySet.h"

#include <QFontDialog>
#include <QFontDatabase>

#include <memory>

static QString FontToStr(const QFont &font)
{
	int size = font.pointSize();
	bool pixels = (size < 0);
	if (pixels)
		size = font.pixelSize();

	return QString("[%1, %2 %3]").arg(font.family(), QString::number(size), QString(pixels ? "px" : "pt"));
}

class QtnPropertyQFontLineEditBttnHandler
		: public QtnPropertyEditorBttnHandler<QtnPropertyQFontBase, QtnLineEditBttn>
{
public:
	QtnPropertyQFontLineEditBttnHandler(QtnPropertyQFontBase& property, QtnLineEditBttn& editor)
		: QtnPropertyEditorHandlerType(property, editor)
	{
		editor.lineEdit->setReadOnly(true);

		if (!property.isEditableByUser())
		{
			editor.toolButton->setEnabled(false);
		}

		updateEditor();
		editor.lineEdit->installEventFilter(this);
		QObject::connect(editor.toolButton, &QToolButton::clicked,
						 this, &QtnPropertyQFontLineEditBttnHandler::onToolButtonClicked);
	}

protected:
	virtual void onToolButtonClick() override { onToolButtonClicked(false); }
	virtual void updateEditor() override
	{
		editor().lineEdit->setText(FontToStr(property()));
	}

private:
	void onToolButtonClicked(bool)
	{
		auto property = &this->property();
		volatile bool destroyed = false;
		auto connection = QObject::connect(property, &QObject::destroyed, [&destroyed]() mutable
		{
			destroyed = true;
		});
		QFontDialog dlg(property->value(), &editor());
		if (dlg.exec() == QDialog::Accepted && !destroyed)
		{
			auto font = property->value();
			auto style_strategy = font.styleStrategy();
			int pixel_size = font.pixelSize();
			font = dlg.currentFont();

			if (pixel_size > 0)
				font.setPixelSize(font.pointSize());

			font.setStyleStrategy(style_strategy);

			property->setValue(font);
			property->propertyDidChange(property, property, QtnPropertyChangeReasonChildren);
		}

		if (!destroyed)
			QObject::disconnect(connection);
	}
};

static bool regQFontDelegate = QtnPropertyDelegateFactory::staticInstance()
								.registerDelegateDefault(&QtnPropertyQFontBase::staticMetaObject
								, &qtnCreateDelegate<QtnPropertyDelegateQFont, QtnPropertyQFontBase>
								, "LineEditBttn");

static QtnEnumInfo* styleStrategyEnum()
{
	static QtnEnumInfo* enumInfo = nullptr;
	if (!enumInfo)
	{
		QVector<QtnEnumValueInfo> items;
		items.append(QtnEnumValueInfo(QFont::PreferDefault, QtnPropertyQFont::getPreferDefaultStr()));
		items.append(QtnEnumValueInfo(QFont::NoAntialias, QtnPropertyQFont::getNoAntialiasStr()));
		items.append(QtnEnumValueInfo(QFont::PreferAntialias, QtnPropertyQFont::getPreferAntialiasStr()));
		enumInfo = new QtnEnumInfo("FontStyleStrategy", items);
	}

	return enumInfo;
}

enum
{
	SizeUnitPixel,
	SizeUnitPoint
};

static QtnEnumInfo* sizeUnitEnum()
{
	static QtnEnumInfo* enumInfo = nullptr;
	if (!enumInfo)
	{
		QVector<QtnEnumValueInfo> items;
		items.append(QtnEnumValueInfo(SizeUnitPixel, QtnPropertyQFont::getPixelStr()));
		items.append(QtnEnumValueInfo(SizeUnitPoint, QtnPropertyQFont::getPointStr()));
		enumInfo = new QtnEnumInfo("FontSizeUnit", items);
	}

	return enumInfo;
}

static void applyFontStyle(QFont &font)
{
#ifdef Q_OS_MAC
		auto style = font.styleName();
		if (!style.isEmpty())
		{
			auto family = font.family();
			QFontDatabase db;
			for (auto &s : db.styles(family))
			{
				if (s == style)
				{
					font.setBold(db.bold(family, style));
					font.setItalic(db.italic(family, style));
					return;
				}
			}
		}
#else
	Q_UNUSED(font);
#endif
}

QtnPropertyDelegateQFont::QtnPropertyDelegateQFont(QtnPropertyQFontBase& owner)
	: QtnPropertyDelegateTypedEx<QtnPropertyQFontBase>(owner)
{
	QtnPropertyQStringCallback* propertyStyle = new QtnPropertyQStringCallback(0);

	QtnPropertyQStringCallback* propertyFamily = new QtnPropertyQStringCallback(0);
	addSubProperty(propertyFamily);
	propertyFamily->setName(QtnPropertyQFont::getFamilyLabel());
	propertyFamily->setDescription(QtnPropertyQFont::getFamilyDescription(owner.name()));
	propertyFamily->setCallbackValueGet([&owner]()->QString {
		return owner.value().family();
	});
	propertyFamily->setCallbackValueSet([&owner, propertyStyle, propertyFamily](QString value) {
		QFont font = owner.value();
		font.setFamily(value);
		applyFontStyle(font);
		owner.setValue(font);

#ifdef Q_OS_MAC
		QtnPropertyDelegateInfo delegate;
		delegate.name = "List";
		QFontDatabase fDB;
		delegate.attributes["items"] = QStringList("") + fDB.styles(value);
		delegate.attributes["editable"] = true;
		propertyStyle->setDelegate(delegate);

		std::shared_ptr<QMetaObject::Connection> c(new QMetaObject::Connection);
		*c.get() = QObject::connect(propertyFamily, &QtnPropertyBase::propertyDidChange, [&owner, c]() mutable
		{
			QObject::disconnect(*c.get());
			c = nullptr;

			owner.propertyDidChange(&owner, &owner, QtnPropertyChangeReasonChildren);
		});
#endif
	});

	QtnPropertyDelegateInfo delegate;
	delegate.name = "List";
	QFontDatabase fDB;
	delegate.attributes["items"] = fDB.families();
	propertyFamily->setDelegate(delegate);

	propertyStyle->setName(QtnPropertyQFont::getStyleLabel());
	propertyStyle->setDescription(QtnPropertyQFont::getStyleDescription(owner.name()));
	propertyStyle->setCallbackValueGet([&owner]()->QString {
		return owner.value().styleName();
	});
	propertyStyle->setCallbackValueSet([&owner](QString value) {
		QFont font = owner.value();
		font.setStyleName(value);
		applyFontStyle(font);
		owner.setValue(font);
	});

#ifdef Q_OS_MAC
	delegate.name = "List";
	delegate.attributes["items"] = QStringList("") + fDB.styles(owner.value().family());
	delegate.attributes["editable"] = true;
#else
	delegate.name = "LineEdit";
	delegate.attributes["multiline_edit"] = false;
#endif
	propertyStyle->setDelegate(delegate);

	addSubProperty(propertyStyle);

	QtnPropertyUIntCallback* propertySize = new QtnPropertyUIntCallback(0);
	addSubProperty(propertySize);
	propertySize->setName(QtnPropertyQFont::getSizeLabel());
	propertySize->setDescription(QtnPropertyQFont::getSizeDescription(owner.name()));
	propertySize->setCallbackValueGet([&owner]() -> quint32
	{
		int ps = owner.value().pointSize();
		if (ps < 0)
			ps = owner.value().pixelSize();
		if (ps < 1)
			ps = 1;
		return ps;
	});
	propertySize->setCallbackValueSet([&owner](quint32 value)
	{
		if (value == 0)
			value = 1;

		QFont font = owner.value();
		if (font.pointSize() > 0)
		{
			if (value > 128)
				value = 128;

			font.setPointSize((int) value);
		} else
		{
			if (value > 256)
				value = 256;

			font.setPixelSize((int) value);
		}
		owner.setValue(font);
	});

	QtnPropertyEnumCallback* propertySizeUnit = new QtnPropertyEnumCallback(0);
	addSubProperty(propertySizeUnit);
	propertySizeUnit->setName(QtnPropertyQFont::getSizeUnitLabel());
	propertySizeUnit->setDescription(QtnPropertyQFont::getSizeUnitDescription(owner.name()));
	propertySizeUnit->setEnumInfo(sizeUnitEnum());
	propertySizeUnit->setCallbackValueGet([&owner]() -> QtnEnumValueType
	{
		if (owner.value().pointSize() < 0)
			return SizeUnitPixel;

		return SizeUnitPoint;
	});
	propertySizeUnit->setCallbackValueSet([&owner](QtnEnumValueType value)
	{
		QFont font = owner.value();

		int size = std::max(font.pointSize(), font.pixelSize());

		switch (value)
		{
			case SizeUnitPixel:
				font.setPixelSize(size);
				break;

			case SizeUnitPoint:
				font.setPointSize(size);
				break;

			default:
				break;
		}

		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyBold = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyBold);
	propertyBold->setName(QtnPropertyQFont::getBoldLabel());
	propertyBold->setDescription(QtnPropertyQFont::getBoldDescription(owner.name()));
	propertyBold->setCallbackValueGet([&owner]()->bool {
		return owner.value().bold();
	});
	propertyBold->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		if (font.bold() != value)
		{
#ifdef Q_OS_MAC
			auto style = font.styleName();
			if (!style.isEmpty())
			{
				auto family = font.family();
				QFontDatabase db;
				for (auto &s : db.styles(family))
				{
					if (s == style)
					{
						if (value != db.bold(family, style))
							return;

						break;
					}
				}
			}
#endif
			font.setBold(value);
			owner.setValue(font);
		}
	});

	QtnPropertyBoolCallback* propertyItalic = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyItalic);
	propertyItalic->setName(QtnPropertyQFont::getItalicLabel());
	propertyItalic->setDescription(QtnPropertyQFont::getItalicDescription(owner.name()));
	propertyItalic->setCallbackValueGet([&owner]()->bool {
		return owner.value().italic();
	});
	propertyItalic->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		if (font.italic() != value)
		{
#ifdef Q_OS_MAC
			auto style = font.styleName();
			if (!style.isEmpty())
			{
				auto family = font.family();
				QFontDatabase db;
				for (auto &s : db.styles(family))
				{
					if (s == style)
					{
						if (value != db.italic(family, style))
							return;

						break;
					}
				}
			}
#endif
			font.setItalic(value);
			owner.setValue(font);
		}
	});

	QtnPropertyBoolCallback* propertyUnderline = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyUnderline);
	propertyUnderline->setName(QtnPropertyQFont::getUnderlineLabel());
	propertyUnderline->setDescription(QtnPropertyQFont::getUnderlineDescription(owner.name()));
	propertyUnderline->setCallbackValueGet([&owner]()->bool {
		return owner.value().underline();
	});
	propertyUnderline->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setUnderline(value);
		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyStrikeout = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyStrikeout);
	propertyStrikeout->setName(QtnPropertyQFont::getStrikeoutLabel());
	propertyStrikeout->setDescription(QtnPropertyQFont::getStrikeoutDescription(owner.name()));
	propertyStrikeout->setCallbackValueGet([&owner]()->bool {
		return owner.value().strikeOut();
	});
	propertyStrikeout->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setStrikeOut(value);
		owner.setValue(font);
	});

	QtnPropertyBoolCallback* propertyKerning = new QtnPropertyBoolCallback(0);
	addSubProperty(propertyKerning);
	propertyKerning->setName(QtnPropertyQFont::getKerningLabel());
	propertyKerning->setDescription(QtnPropertyQFont::getKerningDescription(owner.name()));
	propertyKerning->setCallbackValueGet([&owner]()->bool {
		return owner.value().kerning();
	});
	propertyKerning->setCallbackValueSet([&owner](bool value) {
		QFont font = owner.value();
		font.setKerning(value);
		owner.setValue(font);
	});

	QtnPropertyEnumCallback* propertyAntialiasing = new QtnPropertyEnumCallback(0);
	addSubProperty(propertyAntialiasing);
	propertyAntialiasing->setName(QtnPropertyQFont::getAntialiasingLabel());
	propertyAntialiasing->setDescription(QtnPropertyQFont::getAntialiasingDescription(owner.name()));
	propertyAntialiasing->setEnumInfo(styleStrategyEnum());
	propertyAntialiasing->setCallbackValueGet([&owner]()->QtnEnumValueType {
		return owner.value().styleStrategy();
	});
	propertyAntialiasing->setCallbackValueSet([&owner](QtnEnumValueType value) {
		QFont font = owner.value();
		font.setStyleStrategy((QFont::StyleStrategy)value);
		owner.setValue(font);
	});
}

void QtnPropertyDelegateQFont::drawValueImpl(QStylePainter& painter, const QRect& rect, const QStyle::State& state, bool* needTooltip) const
{
	QFont value = owner().value();

	QRect textRect = rect;

	if (textRect.isValid())
	{
		QRect br;

		QFont oldFont = painter.font();
		QFont newFont(value);
		newFont.setPointSize(oldFont.pointSize());
		painter.setFont(newFont);
		painter.drawText(textRect, Qt::AlignLeading | Qt::AlignVCenter, "A", &br);
		painter.setFont(oldFont);

		textRect.setLeft(br.right() + 3);
	}

	if (textRect.isValid())
	{
		QtnPropertyDelegateTypedEx<QtnPropertyQFontBase>::drawValueImpl(painter, textRect, state, needTooltip);
	}
}

QWidget* QtnPropertyDelegateQFont::createValueEditorImpl(QWidget* parent, const QRect& rect, QtnInplaceInfo* inplaceInfo)
{
	QtnLineEditBttn* editor = new QtnLineEditBttn(parent);
	editor->setGeometry(rect);

	new QtnPropertyQFontLineEditBttnHandler(owner(), *editor);

	if (inplaceInfo)
	{
		editor->lineEdit->selectAll();
	}

	return editor;
}

bool QtnPropertyDelegateQFont::propertyValueToStr(QString& strValue) const
{
	strValue = FontToStr(owner().value());
	return true;
}
<|endoftext|>


<commit_before>#ifndef ITER_GROUP_BY_HPP_
#define ITER_GROUP_BY_HPP_

// this is easily the most functionally complex itertool

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container, typename KeyFunc>
    class GroupProducer;

    struct Identity {
      template <typename T>
      const T& operator()(const T& t) const {
        return t;
      }
    };

    using GroupByFn = IterToolFnOptionalBindSecond<GroupProducer, Identity>;
  }
  constexpr impl::GroupByFn groupby{};
}

template <typename Container, typename KeyFunc>
class iter::impl::GroupProducer {
 private:
  Container container;
  KeyFunc key_func;

  friend GroupByFn;

  using key_func_ret = std::result_of_t<KeyFunc(iterator_deref<Container>)>;

  GroupProducer(Container&& in_container, KeyFunc in_key_func)
      : container(std::forward<Container>(in_container)),
        key_func(in_key_func) {}

 public:
  GroupProducer(GroupProducer&&) = default;

  class Iterator;
  class Group;

 private:
  using KeyGroupPair = std::pair<key_func_ret, Group>;
  using Holder = DerefHolder<iterator_deref<Container>>;

 public:
  class Iterator : public std::iterator<std::input_iterator_tag, KeyGroupPair> {
   private:
    IteratorWrapper<Container> sub_iter;
    IteratorWrapper<Container> sub_end;
    Holder item;
    KeyFunc* key_func;

    std::unique_ptr<KeyGroupPair> current_key_group_pair;

   public:
    Iterator(IteratorWrapper<Container>&& si, IteratorWrapper<Container>&& end,
        KeyFunc& in_key_func)
        : sub_iter{std::move(si)},
          sub_end{std::move(end)},
          key_func(&in_key_func) {
      if (this->sub_iter != this->sub_end) {
        this->item.reset(*this->sub_iter);
      }
    }

    Iterator(const Iterator& other)
        : sub_iter{other.sub_iter},
          sub_end{other.sub_end},
          item{other.item},
          key_func{other.key_func} {}

    Iterator& operator=(const Iterator& other) {
      if (this == &other) {
        return *this;
      }
      this->sub_iter = other.sub_iter;
      this->sub_end = other.sub_end;
      this->item = other.item;
      this->key_func = other.key_func;
      this->current_key_group_pair.reset();
      return *this;
    }

    ~Iterator() = default;

    // NOTE the implicitly generated move constructor would
    // be wrong

    KeyGroupPair& operator*() {
      set_key_group_pair();
      return *this->current_key_group_pair;
    }

    KeyGroupPair* operator->() {
      set_key_group_pair();
      return this->current_key_group_pair.get();
    }

    Iterator& operator++() {
      if (!this->current_key_group_pair) {
        this->set_key_group_pair();
      }
      this->current_key_group_pair.reset();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

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

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    void increment_iterator() {
      if (this->sub_iter != this->sub_end) {
        ++this->sub_iter;
        if (this->sub_iter != this->sub_end) {
          this->item.reset(*this->sub_iter);
        }
      }
    }

    bool exhausted() const {
      return !(this->sub_iter != this->sub_end);
    }

    typename Holder::reference get() {
      return this->item.get();
    }

    typename Holder::pointer get_ptr() {
      return this->item.get_ptr();
    }

    key_func_ret next_key() {
      return (*this->key_func)(this->item.get());
    }

    void set_key_group_pair() {
      if (!this->current_key_group_pair) {
        this->current_key_group_pair =
            std::make_unique<KeyGroupPair>((*this->key_func)(this->item.get()),
                Group{*this, this->next_key()});
      }
    }
  };

  class Group {
   private:
    friend Iterator;
    friend class GroupIterator;
    Iterator& owner;
    key_func_ret key;

    // completed is set if a Group is iterated through
    // completely.  It is checked in the destructor, and
    // if the Group has not been completed, the destructor
    // exhausts it.  This ensures that the next Group starts
    // at the correct position when the user short-circuits
    // iteration over a Group.
    // The move constructor sets the rvalue's completed
    // attribute to true, so its destructor doesn't do anything
    // when called.
    bool completed = false;

    Group(Iterator& in_owner, key_func_ret in_key)
        : owner(in_owner), key(in_key) {}

   public:
    ~Group() {
      if (!this->completed) {
        for (auto iter = this->begin(), end = this->end(); iter != end;
             ++iter) {
        }
      }
    }

    // move-constructible, non-copy-constructible, non-assignable
    Group(Group&& other) noexcept
        : owner(other.owner), key{other.key}, completed{other.completed} {
      other.completed = true;
    }

    class GroupIterator : public std::iterator<std::input_iterator_tag,
                              iterator_traits_deref<Container>> {
     private:
      std::remove_reference_t<key_func_ret>* key;
      Group* group_p;

      bool not_at_end() {
        return !this->group_p->owner.exhausted()
               && this->group_p->owner.next_key() == *this->key;
      }

     public:
      GroupIterator(Group* in_group_p, key_func_ret& in_key)
          : key{&in_key}, group_p{in_group_p} {}

      bool operator!=(const GroupIterator& other) const {
        return !(*this == other);
      }

      bool operator==(const GroupIterator& other) const {
        return this->group_p == other.group_p;
      }

      GroupIterator& operator++() {
        this->group_p->owner.increment_iterator();
        if (!this->not_at_end()) {
          this->group_p->completed = true;
          this->group_p = nullptr;
        }
        return *this;
      }

      GroupIterator operator++(int) {
        auto ret = *this;
        ++*this;
        return ret;
      }

      iterator_deref<Container> operator*() {
        return this->group_p->owner.get();
      }

      typename Holder::pointer operator->() {
        return this->group_p->owner.get_ptr();
      }
    };

    GroupIterator begin() {
      return {this, key};
    }

    GroupIterator end() {
      return {nullptr, key};
    }
  };

  Iterator begin() {
    return {
        std::begin(this->container), std::end(this->container), this->key_func};
  }

  Iterator end() {
    return {
        std::end(this->container), std::end(this->container), this->key_func};
  }
};

#endif
<commit_msg>trailing _ on data members<commit_after>#ifndef ITER_GROUP_BY_HPP_
#define ITER_GROUP_BY_HPP_

// this is easily the most functionally complex itertool

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Container, typename KeyFunc>
    class GroupProducer;

    struct Identity {
      template <typename T>
      const T& operator()(const T& t) const {
        return t;
      }
    };

    using GroupByFn = IterToolFnOptionalBindSecond<GroupProducer, Identity>;
  }
  constexpr impl::GroupByFn groupby{};
}

template <typename Container, typename KeyFunc>
class iter::impl::GroupProducer {
 private:
  Container container_;
  KeyFunc key_func_;

  friend GroupByFn;

  using key_func_ret = std::result_of_t<KeyFunc(iterator_deref<Container>)>;

  GroupProducer(Container&& container, KeyFunc key_func)
      : container_(std::forward<Container>(container)), key_func_(key_func) {}

 public:
  GroupProducer(GroupProducer&&) = default;

  class Iterator;
  class Group;

 private:
  using KeyGroupPair = std::pair<key_func_ret, Group>;
  using Holder = DerefHolder<iterator_deref<Container>>;

 public:
  class Iterator : public std::iterator<std::input_iterator_tag, KeyGroupPair> {
   private:
    IteratorWrapper<Container> sub_iter_;
    IteratorWrapper<Container> sub_end_;
    Holder item_;
    KeyFunc* key_func_;
    std::unique_ptr<KeyGroupPair> current_key_group_pair_;

   public:
    Iterator(IteratorWrapper<Container>&& sub_iter,
        IteratorWrapper<Container>&& sub_end, KeyFunc& key_func)
        : sub_iter_{std::move(sub_iter)},
          sub_end_{std::move(sub_end)},
          key_func_(&key_func) {
      if (sub_iter_ != sub_end_) {
        item_.reset(*sub_iter_);
      }
    }

    Iterator(const Iterator& other)
        : sub_iter_{other.sub_iter_},
          sub_end_{other.sub_end_},
          item_{other.item_},
          key_func_{other.key_func_} {}

    Iterator& operator=(const Iterator& other) {
      if (this == &other) {
        return *this;
      }
      sub_iter_ = other.sub_iter_;
      sub_end_ = other.sub_end_;
      item_ = other.item_;
      key_func_ = other.key_func_;
      current_key_group_pair_.reset();
      return *this;
    }

    ~Iterator() = default;

    // NOTE the implicitly generated move constructor would
    // be wrong

    KeyGroupPair& operator*() {
      set_key_group_pair();
      return *current_key_group_pair_;
    }

    KeyGroupPair* operator->() {
      set_key_group_pair();
      return current_key_group_pair_.get();
    }

    Iterator& operator++() {
      if (!current_key_group_pair_) {
        set_key_group_pair();
      }
      current_key_group_pair_.reset();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    void increment_iterator() {
      if (sub_iter_ != sub_end_) {
        ++sub_iter_;
        if (sub_iter_ != sub_end_) {
          item_.reset(*sub_iter_);
        }
      }
    }

    bool exhausted() const {
      return !(sub_iter_ != sub_end_);
    }

    typename Holder::reference get() {
      return item_.get();
    }

    typename Holder::pointer get_ptr() {
      return item_.get_ptr();
    }

    key_func_ret next_key() {
      return (*key_func_)(item_.get());
    }

    void set_key_group_pair() {
      if (!current_key_group_pair_) {
        current_key_group_pair_ = std::make_unique<KeyGroupPair>(
            (*key_func_)(item_.get()), Group{*this, next_key()});
      }
    }
  };

  class Group {
   private:
    friend Iterator;
    friend class GroupIterator;
    Iterator& owner_;
    key_func_ret key_;

    // completed is set if a Group is iterated through
    // completely.  It is checked in the destructor, and
    // if the Group has not been completed, the destructor
    // exhausts it.  This ensures that the next Group starts
    // at the correct position when the user short-circuits
    // iteration over a Group.
    // The move constructor sets the rvalue's completed
    // attribute to true, so its destructor doesn't do anything
    // when called.
    bool completed = false;

    Group(Iterator& owner, key_func_ret key) : owner_(owner), key_(key) {}

   public:
    ~Group() {
      if (!completed) {
        for (auto iter = begin(), end_it = end(); iter != end_it; ++iter) {
        }
      }
    }

    // move-constructible, non-copy-constructible, non-assignable
    Group(Group&& other) noexcept
        : owner_(other.owner_), key_{other.key_}, completed{other.completed} {
      other.completed = true;
    }

    class GroupIterator : public std::iterator<std::input_iterator_tag,
                              iterator_traits_deref<Container>> {
     private:
      std::remove_reference_t<key_func_ret>* key_;
      Group* group_p_;

      bool not_at_end() {
        return !group_p_->owner_.exhausted()
               && group_p_->owner_.next_key() == *key_;
      }

     public:
      GroupIterator(Group* group_p, key_func_ret& key)
          : key_{&key}, group_p_{group_p} {}

      bool operator!=(const GroupIterator& other) const {
        return !(*this == other);
      }

      bool operator==(const GroupIterator& other) const {
        return group_p_ == other.group_p_;
      }

      GroupIterator& operator++() {
        group_p_->owner_.increment_iterator();
        if (!not_at_end()) {
          group_p_->completed = true;
          group_p_ = nullptr;
        }
        return *this;
      }

      GroupIterator operator++(int) {
        auto ret = *this;
        ++*this;
        return ret;
      }

      iterator_deref<Container> operator*() {
        return group_p_->owner_.get();
      }

      typename Holder::pointer operator->() {
        return group_p_->owner_.get_ptr();
      }
    };

    GroupIterator begin() {
      return {this, key_};
    }

    GroupIterator end() {
      return {nullptr, key_};
    }
  };

  Iterator begin() {
    return {std::begin(container_), std::end(container_), key_func_};
  }

  Iterator end() {
    return {std::end(container_), std::end(container_), key_func_};
  }
};

#endif
<|endoftext|>