<commit_before>//Copyright (c) 2022 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "infill.h"
#include "LayerPlan.h"
#include "sliceDataStorage.h"
#include "TopSurface.h"
#include "ExtruderTrain.h"

namespace cura
{

TopSurface::TopSurface()
{
    //Do nothing. Areas stays empty.
}

void TopSurface::setAreasFromMeshAndLayerNumber(SliceMeshStorage& mesh, size_t layer_number)
{
    //The top surface is all parts of the mesh where there's no mesh above it, so find the layer above it first.
    Polygons mesh_above;
    if (layer_number < mesh.layers.size() - 1)
    {
        mesh_above = mesh.layers[layer_number + 1].getOutlines();
    } //If this is the top-most layer, mesh_above stays empty.

    if (mesh.settings.get<bool>("magic_spiralize"))
    {
        // when spiralizing, the model is often solid so it's no good trying to determine if there is air above or not
        // in this situation, just iron the topmost of the bottom layers
        if (layer_number == mesh.settings.get<size_t>("initial_bottom_layers") - 1)
        {
            areas = mesh.layers[layer_number].getOutlines();
        }
    }
    else
    {
        areas = mesh.layers[layer_number].getOutlines().difference(mesh_above);
    }
}

bool TopSurface::ironing(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const GCodePathConfig& line_config, LayerPlan& layer, const FffGcodeWriter& gcode_writer) const
{
    if (areas.empty())
    {
        return false; //Nothing to do.
    }
    //Generate the lines to cover the surface.
    const bool extruder_nr = mesh.settings.get<ExtruderTrain&>("top_bottom_extruder_nr").extruder_nr;
    const EFillMethod pattern = mesh.settings.get<EFillMethod>("ironing_pattern");
    const bool zig_zaggify_infill = pattern == EFillMethod::ZIG_ZAG;
    constexpr bool connect_polygons = false; // midway connections can make the surface less smooth
    const coord_t line_spacing = mesh.settings.get<coord_t>("ironing_line_spacing");
    const coord_t line_width = line_config.getLineWidth();
    const size_t roofing_layer_count = std::min(mesh.settings.get<size_t>("roofing_layer_count"), mesh.settings.get<size_t>("top_layers"));
    const std::vector<AngleDegrees>& top_most_skin_angles = (roofing_layer_count > 0) ? mesh.roofing_angles : mesh.skin_angles;
    assert(top_most_skin_angles.size() > 0);
    const AngleDegrees direction = top_most_skin_angles[layer.getLayerNr() % top_most_skin_angles.size()] + AngleDegrees(90.0); //Always perpendicular to the skin lines.
    constexpr coord_t infill_overlap = 0;
    constexpr int infill_multiplier = 1;
    constexpr coord_t shift = 0;
    const coord_t max_resolution = mesh.settings.get<coord_t>("meshfix_maximum_resolution");
    const coord_t max_deviation = mesh.settings.get<coord_t>("meshfix_maximum_deviation");
    const Ratio ironing_flow = mesh.settings.get<Ratio>("ironing_flow");
    const bool enforce_monotonic_order = mesh.settings.get<bool>("ironing_monotonic");
    constexpr size_t wall_line_count = 0;
    const Point infill_origin = Point();
    const bool skip_line_stitching = enforce_monotonic_order;

    coord_t ironing_inset = -mesh.settings.get<coord_t>("ironing_inset");
    if (pattern == EFillMethod::ZIG_ZAG)
    {
        //Compensate for the outline_offset decrease that takes place when using the infill generator to generate ironing with the zigzag pattern
        const Ratio width_scale = (float)mesh.settings.get<coord_t>("layer_height") / mesh.settings.get<coord_t>("infill_sparse_thickness");
        ironing_inset += width_scale * line_width / 2;
        //Align the edge of the ironing line with the edge of the outer wall
        ironing_inset -= ironing_flow * line_width / 2;
    }
    else if (pattern == EFillMethod::CONCENTRIC)
    {
        //Counteract the outline_offset increase that takes place when using the infill generator to generate ironing with the concentric pattern
        ironing_inset += line_spacing - line_width / 2;
        //Align the edge of the ironing line with the edge of the outer wall
        ironing_inset -= ironing_flow * line_width / 2;
    }
    Polygons ironed_areas = areas.offset(ironing_inset);

    Infill infill_generator(pattern, zig_zaggify_infill, connect_polygons, ironed_areas, line_width, line_spacing, infill_overlap, infill_multiplier, direction, layer.z - 10, shift, max_resolution, max_deviation, wall_line_count, infill_origin, skip_line_stitching);
    std::vector<VariableWidthLines> ironing_paths;
    Polygons ironing_polygons;
    Polygons ironing_lines;
    infill_generator.generate(ironing_paths, ironing_polygons, ironing_lines, mesh.settings);

    if(ironing_polygons.empty() && ironing_lines.empty() && ironing_paths.empty())
    {
        return false; //Nothing to do.
    }

    layer.mode_skip_agressive_merge = true;

    bool added = false;
    if(!ironing_polygons.empty())
    {
        constexpr bool force_comb_retract = false;
        layer.addTravel(ironing_polygons[0][0], force_comb_retract);
        layer.addPolygonsByOptimizer(ironing_polygons, line_config, ZSeamConfig());
        added = true;
    }
    if(!ironing_lines.empty())
    {
        if (pattern == EFillMethod::LINES || pattern == EFillMethod::ZIG_ZAG)
        {
            //Move to a corner of the area that is perpendicular to the ironing lines, to reduce the number of seams.
            const AABB bounding_box(ironed_areas);
            PointMatrix rotate(-direction + 90);
            const Point center = bounding_box.getMiddle();
            const Point far_away = rotate.apply(Point(0, vSize(bounding_box.max - center) * 100)); //Some direction very far away in the direction perpendicular to the ironing lines, relative to the centre.
            //Two options to start, both perpendicular to the ironing lines. Which is closer?
            const Point front_side = PolygonUtils::findNearestVert(center + far_away, ironed_areas).p();
            const Point back_side = PolygonUtils::findNearestVert(center - far_away, ironed_areas).p();
            if (vSize2(layer.getLastPlannedPositionOrStartingPosition() - front_side) < vSize2(layer.getLastPlannedPositionOrStartingPosition() - back_side))
            {
                layer.addTravel(front_side);
            }
            else
            {
                layer.addTravel(back_side);
            }
        }

        if( ! enforce_monotonic_order)
        {
            layer.addLinesByOptimizer(ironing_lines, line_config, SpaceFillType::PolyLines);
        }
        else
        {
            const coord_t max_adjacent_distance = line_spacing * 1.1; //Lines are considered adjacent - meaning they need to be printed in monotonic order - if spaced 1 line apart, with 10% extra play.
            layer.addLinesMonotonic(Polygons(), ironing_lines, line_config, SpaceFillType::PolyLines, AngleRadians(direction), max_adjacent_distance);
        }
        added = true;
    }
    if(!ironing_paths.empty())
    {
        constexpr bool retract_before_outer_wall = false;
        constexpr coord_t wipe_dist = 0u;
        const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
        InsetOrderOptimizer wall_orderer(gcode_writer, storage, layer, mesh.settings, extruder_nr,
                                            line_config, line_config, line_config, line_config,
                                            retract_before_outer_wall, wipe_dist, wipe_dist, extruder_nr, extruder_nr, z_seam_config, ironing_paths);
        wall_orderer.addToLayer();
        added = true;
    }

    layer.mode_skip_agressive_merge = false;
    return added;
}

}
<commit_msg>All ironing lines should be ironing_line_spacing apart. Since we are using infill code to calculate this, we were offseting the concertric polygons by infill_line_width - line_distance. In the case of ironing we should have infill_line_width == line_distance == ironing_line_spacing This way our paths are always ironing_line_spacing apart.<commit_after>//Copyright (c) 2022 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "infill.h"
#include "LayerPlan.h"
#include "sliceDataStorage.h"
#include "TopSurface.h"
#include "ExtruderTrain.h"

namespace cura
{

TopSurface::TopSurface()
{
    //Do nothing. Areas stays empty.
}

void TopSurface::setAreasFromMeshAndLayerNumber(SliceMeshStorage& mesh, size_t layer_number)
{
    //The top surface is all parts of the mesh where there's no mesh above it, so find the layer above it first.
    Polygons mesh_above;
    if (layer_number < mesh.layers.size() - 1)
    {
        mesh_above = mesh.layers[layer_number + 1].getOutlines();
    } //If this is the top-most layer, mesh_above stays empty.

    if (mesh.settings.get<bool>("magic_spiralize"))
    {
        // when spiralizing, the model is often solid so it's no good trying to determine if there is air above or not
        // in this situation, just iron the topmost of the bottom layers
        if (layer_number == mesh.settings.get<size_t>("initial_bottom_layers") - 1)
        {
            areas = mesh.layers[layer_number].getOutlines();
        }
    }
    else
    {
        areas = mesh.layers[layer_number].getOutlines().difference(mesh_above);
    }
}

bool TopSurface::ironing(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const GCodePathConfig& line_config, LayerPlan& layer, const FffGcodeWriter& gcode_writer) const
{
    if (areas.empty())
    {
        return false; //Nothing to do.
    }
    //Generate the lines to cover the surface.
    const bool extruder_nr = mesh.settings.get<ExtruderTrain&>("top_bottom_extruder_nr").extruder_nr;
    const EFillMethod pattern = mesh.settings.get<EFillMethod>("ironing_pattern");
    const bool zig_zaggify_infill = pattern == EFillMethod::ZIG_ZAG;
    constexpr bool connect_polygons = false; // midway connections can make the surface less smooth
    const coord_t line_spacing = mesh.settings.get<coord_t>("ironing_line_spacing");
    const coord_t line_width = line_config.getLineWidth();
    const size_t roofing_layer_count = std::min(mesh.settings.get<size_t>("roofing_layer_count"), mesh.settings.get<size_t>("top_layers"));
    const std::vector<AngleDegrees>& top_most_skin_angles = (roofing_layer_count > 0) ? mesh.roofing_angles : mesh.skin_angles;
    assert(top_most_skin_angles.size() > 0);
    const AngleDegrees direction = top_most_skin_angles[layer.getLayerNr() % top_most_skin_angles.size()] + AngleDegrees(90.0); //Always perpendicular to the skin lines.
    constexpr coord_t infill_overlap = 0;
    constexpr int infill_multiplier = 1;
    constexpr coord_t shift = 0;
    const coord_t max_resolution = mesh.settings.get<coord_t>("meshfix_maximum_resolution");
    const coord_t max_deviation = mesh.settings.get<coord_t>("meshfix_maximum_deviation");
    const Ratio ironing_flow = mesh.settings.get<Ratio>("ironing_flow");
    const bool enforce_monotonic_order = mesh.settings.get<bool>("ironing_monotonic");
    constexpr size_t wall_line_count = 0;
    const Point infill_origin = Point();
    const bool skip_line_stitching = enforce_monotonic_order;

    coord_t ironing_inset = -mesh.settings.get<coord_t>("ironing_inset");
    if (pattern == EFillMethod::ZIG_ZAG)
    {
        //Compensate for the outline_offset decrease that takes place when using the infill generator to generate ironing with the zigzag pattern
        const Ratio width_scale = (float)mesh.settings.get<coord_t>("layer_height") / mesh.settings.get<coord_t>("infill_sparse_thickness");
        ironing_inset += width_scale * line_width / 2;
        //Align the edge of the ironing line with the edge of the outer wall
        ironing_inset -= ironing_flow * line_width / 2;
    }
    else if (pattern == EFillMethod::CONCENTRIC)
    {
        //Counteract the outline_offset increase that takes place when using the infill generator to generate ironing with the concentric pattern
        ironing_inset += line_spacing - line_width / 2;
        //Align the edge of the ironing line with the edge of the outer wall
        ironing_inset -= ironing_flow * line_width / 2;
    }
    Polygons ironed_areas = areas.offset(ironing_inset);

    Infill infill_generator(pattern, zig_zaggify_infill, connect_polygons, ironed_areas, line_spacing, line_spacing, infill_overlap, infill_multiplier, direction, layer.z - 10, shift, max_resolution, max_deviation, wall_line_count, infill_origin, skip_line_stitching);
    std::vector<VariableWidthLines> ironing_paths;
    Polygons ironing_polygons;
    Polygons ironing_lines;
    infill_generator.generate(ironing_paths, ironing_polygons, ironing_lines, mesh.settings);

    if(ironing_polygons.empty() && ironing_lines.empty() && ironing_paths.empty())
    {
        return false; //Nothing to do.
    }

    layer.mode_skip_agressive_merge = true;

    bool added = false;
    if(!ironing_polygons.empty())
    {
        constexpr bool force_comb_retract = false;
        layer.addTravel(ironing_polygons[0][0], force_comb_retract);
        layer.addPolygonsByOptimizer(ironing_polygons, line_config, ZSeamConfig());
        added = true;
    }
    if(!ironing_lines.empty())
    {
        if (pattern == EFillMethod::LINES || pattern == EFillMethod::ZIG_ZAG)
        {
            //Move to a corner of the area that is perpendicular to the ironing lines, to reduce the number of seams.
            const AABB bounding_box(ironed_areas);
            PointMatrix rotate(-direction + 90);
            const Point center = bounding_box.getMiddle();
            const Point far_away = rotate.apply(Point(0, vSize(bounding_box.max - center) * 100)); //Some direction very far away in the direction perpendicular to the ironing lines, relative to the centre.
            //Two options to start, both perpendicular to the ironing lines. Which is closer?
            const Point front_side = PolygonUtils::findNearestVert(center + far_away, ironed_areas).p();
            const Point back_side = PolygonUtils::findNearestVert(center - far_away, ironed_areas).p();
            if (vSize2(layer.getLastPlannedPositionOrStartingPosition() - front_side) < vSize2(layer.getLastPlannedPositionOrStartingPosition() - back_side))
            {
                layer.addTravel(front_side);
            }
            else
            {
                layer.addTravel(back_side);
            }
        }

        if( ! enforce_monotonic_order)
        {
            layer.addLinesByOptimizer(ironing_lines, line_config, SpaceFillType::PolyLines);
        }
        else
        {
            const coord_t max_adjacent_distance = line_spacing * 1.1; //Lines are considered adjacent - meaning they need to be printed in monotonic order - if spaced 1 line apart, with 10% extra play.
            layer.addLinesMonotonic(Polygons(), ironing_lines, line_config, SpaceFillType::PolyLines, AngleRadians(direction), max_adjacent_distance);
        }
        added = true;
    }
    if(!ironing_paths.empty())
    {
        constexpr bool retract_before_outer_wall = false;
        constexpr coord_t wipe_dist = 0u;
        const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
        InsetOrderOptimizer wall_orderer(gcode_writer, storage, layer, mesh.settings, extruder_nr,
                                            line_config, line_config, line_config, line_config,
                                            retract_before_outer_wall, wipe_dist, wipe_dist, extruder_nr, extruder_nr, z_seam_config, ironing_paths);
        wall_orderer.addToLayer();
        added = true;
    }

    layer.mode_skip_agressive_merge = false;
    return added;
}

}
<|endoftext|>


<commit_before><?hh //strict

namespace hhpack\getopt;

use LogicException;

final class ValueOption implements Option<string>
{

    use OptionBehavior<string>;

    public function __construct(
        string $name,
        string $shortName,
        string $longName,
        string $defaultValue,
        ArgumentType $required = ArgumentType::Required
    )
    {
        $this->name = $name;
        $this->shortName = $shortName;
        $this->longName = $longName;
        $this->required = $required;
        $this->defaultValue = $defaultValue;
    }

    public function isNoArgument() : bool
    {
        return false;
    }

    public function consume(ArgumentsConsumer $consumer) : Pair <string, string>
    {
        $name = $consumer->current();

        if (!$this->matchesName($name))  {
            throw new LogicException('Option name does not match');
        }

        if (!$consumer->hasNext()) {
            throw new LogicException('have not argument value');
        }

        $next = $consumer->next();
        $consumer->consume();

        if (preg_match('/^(-|--)/', $next) === 1) {
            throw new LogicException('have not argument value');
        }

        $consumer->consume();

        return Pair { $this->name(), $next };
    }

}
<commit_msg>default to Optional<commit_after><?hh //strict

namespace hhpack\getopt;

use LogicException;

final class ValueOption implements Option<string>
{

    use OptionBehavior<string>;

    public function __construct(
        string $name,
        string $shortName,
        string $longName,
        string $defaultValue,
        ArgumentType $required = ArgumentType::Optional
    )
    {
        $this->name = $name;
        $this->shortName = $shortName;
        $this->longName = $longName;
        $this->required = $required;
        $this->defaultValue = $defaultValue;
    }

    public function isNoArgument() : bool
    {
        return false;
    }

    public function consume(ArgumentsConsumer $consumer) : Pair <string, string>
    {
        $name = $consumer->current();

        if (!$this->matchesName($name))  {
            throw new LogicException('Option name does not match');
        }

        if (!$consumer->hasNext()) {
            throw new LogicException('have not argument value');
        }

        $next = $consumer->next();
        $consumer->consume();

        if (preg_match('/^(-|--)/', $next) === 1) {
            throw new LogicException('have not argument value');
        }

        $consumer->consume();

        return Pair { $this->name(), $next };
    }

}
<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-7 15:32:10
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const int infty = 1000000007;

int N, M, L, X;
int a[1010];
int DP[1010];
int DP2[1010];
int sum;

int main()
{
  cin >> N >> M >> L >> X;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  int maxi = (X - 1) * M + L;
  fill(DP, DP + M, infty);
  DP[0] = 0;
  for (auto i = 0; i < N; i++)
  {
    fill(DP2, DP2 + M, infty);
    for (auto j = 0; j < M; j++)
    {
      if (DP[j] == infty)
        continue;
      sum = DP[j] + a[i];
      DP2[sum % M] = min(DP[sum % M], sum);
    }
    for (auto j = 0; j < M; j++)
    {
      DP[j] = DP2[j];
    }
#if DEBUG == 1
    for (auto j = 0; j < M; j++)
    {
      cerr << DP[j] << " ";
    }
    cerr << endl;
#endif
  }
  cout << ((DP[L] <= maxi) ? "Yes" : "No") << endl;
}<commit_msg>submit D.cpp to 'D - Many Go Round' (maximum-cup-2018) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-7 15:32:10
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const int infty = 1000000007;

int N, M, L, X;
int a[1010];
int DP[1010];
int DP2[1010];
int sum;

int main()
{
  cin >> N >> M >> L >> X;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  int maxi = (X - 1) * M + L;
  fill(DP, DP + M, infty);
  DP[0] = 0;
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j < M; j++)
    {
      DP2[j] = DP[j];
    }
    for (auto j = 0; j < M; j++)
    {
      if (DP[j] == infty)
        continue;
      sum = DP[j] + a[i];
      DP2[sum % M] = min(DP[sum % M], sum);
    }
    for (auto j = 0; j < M; j++)
    {
      DP[j] = DP2[j];
    }
#if DEBUG == 1
    for (auto j = 0; j < M; j++)
    {
      cerr << DP[j] << " ";
    }
    cerr << endl;
#endif
  }
  cout << ((DP[L] <= maxi) ? "Yes" : "No") << endl;
}<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : A.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/28 20:51:38
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

void TLE()
{
  sleep(10);
}

void RE()
{
  assert(false);
}

std::random_device seed_gen;
std::mt19937 engine(seed_gen());

// ----- Solve -----

#if DEBUG == 1
constexpr int D = 5;
#else
constexpr int D = 365;
#endif
constexpr int C = 26;
constexpr int K = 1;
constexpr int M = 5000;

class Solve
{
  vector<ll> c;
  vector<vector<ll>> s;
  vector<int> t;
  vector<set<int>> contestDays;
  ll totalScore;

public:
  Solve() : c(C), s(D, vector<ll>(C, 0)), t(D), contestDays(C), totalScore{0}
  {
    for (auto i{0}; i < C; ++i)
    {
      cin >> c[i];
    }
    for (auto i{0}; i < D; ++i)
    {
      for (auto j{0}; j < C; ++j)
      {
        cin >> s[i][j];
      }
    }
    for (auto i{0}; i < C; ++i)
    {
      contestDays[i].insert(0);
      contestDays[i].insert(D + 1);
    }
  }

  void flush()
  {
    for (auto i{0}; i < D; ++i)
    {
      t[i] = engine() % C;
    }
    calc_score();
    for (auto i{0}; i < M; ++i)
    {
      auto pScore{totalScore};
      vector<int> d(K), q(K), p(K);
      for (auto j{0}; j < K; ++j)
      {
        d[j] = engine() % D;
        q[j] = engine() % C;
        p[j] = t[d[j] - 1];
        change_score(d[j] + 1, q[j]);
#if DEBUG == 1
        cerr << "d = " << d[j] << ", q = " << q[j] << ", p = " << p[j] << endl;
#endif
      }
      auto qScore{totalScore};
#if DEBUG == 1
      cerr << "pScore = " << pScore << ", qScore = " << qScore << endl;
#endif
      if (pScore > qScore)
      {
        for (auto j{K - 1}; j >= 0; --j)
        {
#if DEBUG == 1
          cerr << "d = " << d[j] << ", q = " << t[d[j] - 1] << ", p = " << p[j] << endl;
#endif
          change_score(d[j] + 1, p[j]);
        }
#if DEBUG == 1
        cerr << "score = " << totalScore << endl;
#endif
      }
    }
    for (auto e : t)
    {
      cout << e + 1 << endl;
    }
  }

private:
  ll change_score(int d, int q)
  {
    int p{t[d - 1]};
    if (p == q)
    {
      return totalScore;
    }
    ll newScore{totalScore};
    t[d - 1] = q;
    newScore -= s[d - 1][p];
    newScore += s[d - 1][q];
    {
      auto it{contestDays[p].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore -= c[p] * dif;
      --it;
      contestDays[p].erase(it);
    }
    {
      contestDays[q].insert(d);
      auto it{contestDays[q].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore += c[q] * dif;
    }
    return totalScore = newScore;
  }

  vector<ll> calc_score()
  {
    vector<ll> ans(D);
    vector<vector<int>> last(D + 1, vector<int>(C, 0));
    ll now{0};
    for (auto d{0}; d < D; ++d)
    {
      now += s[d][t[d]];
      contestDays[t[d]].insert(d + 1);
      last[d + 1] = last[d];
      last[d + 1][t[d]] = d + 1;
      ll penalty{0};
      for (auto i{0}; i < C; ++i)
      {
        penalty += c[i] * (d + 1 - last[d + 1][i]);
      }
      now -= penalty;
      ans[d] = now;
    }
    totalScore = now;
    return ans;
  }
};

// ----- main() -----

int main()
{
  ll d;
  cin >> d;
  Solve solve;
  solve.flush();
}
<commit_msg>tried A.cpp to 'A'<commit_after>#define DEBUG 1

/**
 * File    : A.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/28 20:51:38
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

void TLE()
{
  sleep(10);
}

void RE()
{
  assert(false);
}

std::random_device seed_gen;
std::mt19937 engine(seed_gen());

// ----- Solve -----

#if DEBUG == 1
constexpr int D = 5;
#else
constexpr int D = 365;
#endif
constexpr int C = 26;
constexpr int K = 1;
constexpr int M = 5000;

class Solve
{
  vector<ll> c;
  vector<vector<ll>> s;
  vector<int> t;
  vector<set<int>> contestDays;
  ll totalScore;

public:
  Solve() : c(C), s(D, vector<ll>(C, 0)), t(D), contestDays(C), totalScore{0}
  {
    for (auto i{0}; i < C; ++i)
    {
      cin >> c[i];
    }
    for (auto i{0}; i < D; ++i)
    {
      for (auto j{0}; j < C; ++j)
      {
        cin >> s[i][j];
      }
    }
    for (auto i{0}; i < C; ++i)
    {
      contestDays[i].insert(0);
      contestDays[i].insert(D + 1);
    }
  }

  void flush()
  {
    for (auto i{0}; i < D; ++i)
    {
      t[i] = engine() % C;
    }
    calc_score();
    for (auto i{0}; i < M; ++i)
    {
      auto pScore{totalScore};
      vector<int> d(K), q(K), p(K);
      for (auto j{0}; j < K; ++j)
      {
        d[j] = engine() % D;
        q[j] = engine() % C;
        p[j] = t[d[j] - 1];
        change_score(d[j] + 1, q[j]);
#if DEBUG == 1
        cerr << "d = " << d[j] << ", q = " << q[j] << ", p = " << p[j] << endl;
        cerr << t[d[j] - 1] << endl;
#endif
      }
      auto qScore{totalScore};
#if DEBUG == 1
      cerr << "pScore = " << pScore << ", qScore = " << qScore << endl;
#endif
      if (pScore > qScore)
      {
        for (auto j{K - 1}; j >= 0; --j)
        {
#if DEBUG == 1
          cerr << "d = " << d[j] << ", q = " << t[d[j] - 1] << ", p = " << p[j] << endl;
#endif
          change_score(d[j] + 1, p[j]);
        }
#if DEBUG == 1
        cerr << "score = " << totalScore << endl;
#endif
      }
    }
    for (auto e : t)
    {
      cout << e + 1 << endl;
    }
  }

private:
  ll change_score(int d, int q)
  {
    int p{t[d - 1]};
    if (p == q)
    {
      return totalScore;
    }
    ll newScore{totalScore};
    t[d - 1] = q;
    newScore -= s[d - 1][p];
    newScore += s[d - 1][q];
    {
      auto it{contestDays[p].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore -= c[p] * dif;
      --it;
      contestDays[p].erase(it);
    }
    {
      contestDays[q].insert(d);
      auto it{contestDays[q].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore += c[q] * dif;
    }
    return totalScore = newScore;
  }

  vector<ll> calc_score()
  {
    vector<ll> ans(D);
    vector<vector<int>> last(D + 1, vector<int>(C, 0));
    ll now{0};
    for (auto d{0}; d < D; ++d)
    {
      now += s[d][t[d]];
      contestDays[t[d]].insert(d + 1);
      last[d + 1] = last[d];
      last[d + 1][t[d]] = d + 1;
      ll penalty{0};
      for (auto i{0}; i < C; ++i)
      {
        penalty += c[i] * (d + 1 - last[d + 1][i]);
      }
      now -= penalty;
      ans[d] = now;
    }
    totalScore = now;
    return ans;
  }
};

// ----- main() -----

int main()
{
  ll d;
  cin >> d;
  Solve solve;
  solve.flush();
}
<|endoftext|>


<commit_before>//===-- ParseSatiliteFixes_Test.cpp -----------------------------*- C++ -*-===//
//
// This file is distributed uner the MIT license. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Unit test for ParseSatiliteFixes
///
//===----------------------------------------------------------------------===//

#include "NMEAParser.h"
#include "gtest/gtest.h"

#include <cmath>

#if 0
Test cases
| N | Variation |
|---+-----------|
| 1 | Valid     |
| 2 | Invalid   |
| 3 | Empty     |
#endif

namespace NMEA {
TEST(ParseSatiliteFixes, Valid_Fixes) {
  const std::string Fixes = "10";
  const int Expected = 10;

  auto Parser = NMEAParser{};

  EXPECT_EQ(Expected, Parser.ParseSatiliteFixes(Fixes));
}

TEST(ParseSatiliteFixes, Invalid_Fixes) {
  const std::string Fixes = "ertyhgf";
  const int Expected = 0;

  auto Parser = NMEAParser{};

  EXPECT_EQ(Expected, Parser.ParseSatiliteFixes(Fixes));
}

TEST(ParseSatiliteFixes, Empty_Fixes) {
  const std::string Fixes = "";
  const int Expected = 0;

  auto Parser = NMEAParser{};

  EXPECT_EQ(Expected, Parser.ParseSatiliteFixes(Fixes));
}
}
<commit_msg>Update ParseSatilitesFixes test comments<commit_after>//===-- ParseSatiliteFixes_Test.cpp -----------------------------*- C++ -*-===//
//
// This file is distributed uner the MIT license. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Unit tests for ParseSatiliteFixes(std::string Fixes)
///
//===----------------------------------------------------------------------===//

#include "NMEAParser.h"
#include "gtest/gtest.h"

#if 0
Test cases
| N | Fixes     |
|---+-----------|
| 1 | Valid     |
| 2 | Invalid   |
| 3 | Empty     |
#endif

namespace NMEA {
TEST(ParseSatiliteFixes, Valid_Fixes) {
  const std::string Fixes = "10";
  const int Expected = 10;

  auto Parser = NMEAParser{};

  EXPECT_EQ(Expected, Parser.ParseSatiliteFixes(Fixes));
}

TEST(ParseSatiliteFixes, Invalid_Fixes) {
  const std::string Fixes = "ertyhgf";
  const int Expected = 0;

  auto Parser = NMEAParser{};

  EXPECT_EQ(Expected, Parser.ParseSatiliteFixes(Fixes));
}

TEST(ParseSatiliteFixes, Empty_Fixes) {
  const std::string Fixes = "";
  const int Expected = 0;

  auto Parser = NMEAParser{};

  EXPECT_EQ(Expected, Parser.ParseSatiliteFixes(Fixes));
}
}
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2005 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <base/function_parser.h>
#include <base/point.h>
#include <lac/vector.h>

// Utility to split a string given a delimiter.

unsigned int SplitString(const std::string& input,
			 const std::string& delimiter,
			 std::vector<std::string>& results)
{
  int iPos = 0;
  int newPos = -1;
  int sizeS2 = delimiter.size();
  int isize = input.size();

  std::vector<int> positions;

  newPos = input.find (delimiter, 0);

  if( newPos < 0 ) { return 0; }

  unsigned int numFound = 0;

  while( newPos > iPos )
  {
    numFound++;
    positions.push_back(newPos);
    iPos = newPos;
    newPos = input.find (delimiter, iPos+sizeS2+1);
  }

  for(unsigned int i=0; i <= positions.size(); ++i)
  {
    std::string s;
    if( i == 0 ) { s = input.substr( i, positions[i] ); }
    int offset = positions[i-1] + sizeS2;
    if( offset < isize )
    {
      if( i == positions.size() )
      {
        s = input.substr(offset);
      }
      else if( i > 0 )
      {
        s = input.substr( positions[i-1] + sizeS2,
          positions[i] - positions[i-1] - sizeS2 );
      }
    }
    if( s.size() > 0 )
    {
      results.push_back(s);
    }
  }
  return numFound;
}

template <int dim>
FunctionParser<dim>::FunctionParser(const unsigned int n_components,
				    const double       initial_time)
                :
                Function<dim>(n_components, initial_time),
                fp (0)
{
  fp = new fparser::FunctionParser[n_components];
}

template <int dim>
FunctionParser<dim>::~FunctionParser() {
  delete[] fp;
}

#ifndef DEAL_II_DISABLE_PARSER

template <int dim>
void FunctionParser<dim>::initialize(const std::string variables,
				     const std::vector<std::string> expressions,
				     std::map<std::string, double> constants,
				     bool time_dependent,
				     bool use_degrees)
{
  // We check that the number of components of this function matches
  // the number of components passed in as a vector of strings.
  AssertThrow(this->n_components == expressions.size(),
	      ExcInvalidExpressionSize(this->n_components,
				       expressions.size()) );

  for (unsigned int i=0; i<this->n_components; ++i) {
    // Add the variuous constants to the parser.
    std::map< std::string, double >::const_iterator
      constant = constants.begin(),
      endc  = constants.end();
    for(;constant != endc; ++constant) {
      AssertThrow( fp[i].AddConstant(constant->first, constant->second),
		   ExcMessage("Invalid Constant Name"));
    }

    int ret_value = fp[i].Parse(expressions[i],
				variables,
				use_degrees);
    AssertThrow(ret_value == -1,
		ExcParseError(ret_value, fp[i].ErrorMsg()));

    // The fact that the parser did not throw an error does not mean
    // that everything went ok... we can still have problems with the
    // number of variables...
  }

  // Now we define how many variables we expect to read in.  We
  // distinguish between two cases: Time dependent problems, and not
  // time dependent problems. In the first case the number of
  // variables is given by the dimension plus one. In the other case,
  // the number of variables is equal to the dimension. Once we parsed
  // the variables string, if none of this is the case, then an
  // exception is thrown.
  if (time_dependent)
    n_vars = dim+1;
  else
    n_vars = dim;

  // Let's check if the number of variables is correct...
  AssertThrow(n_vars == fp[0].NVars(),
	      ExcDimensionMismatch(n_vars,fp[0].NVars()));

  // Now set the initialization bit.
  initialized = true;
}

template <int dim>
void FunctionParser<dim>::initialize(const std::string variables,
				     const std::string expression,
				     std::map<std::string, double> constants,
				     bool time_dependent,
				     bool use_degrees)
{
  // Start up with an empty vector of expressions.
  std::vector<std::string> expressions;

  // In this case a vector function is built with the number of
  // components found between the separators ';'
  SplitString(expression, ";", expressions);
  if (expressions.size() == 0) expressions.push_back(expression);
  // Now initialize with the things we got.
  initialize
    (variables, expressions, constants, time_dependent, use_degrees);
}

template <int dim>
double FunctionParser<dim>::value (const Point<dim> &p,
				   unsigned int component) const
{
  AssertThrow(initialized==true, ExcNotInitialized());
  AssertThrow(component < this->n_components,
	      ExcIndexRange(component, 0, this->n_components));
  // Statically allocates dim+1 double variables.
  double vars[dim+1];

  for(unsigned int i=0; i<dim; ++i)
    vars[i] = p(i);

  // We need the time variable only if the number of variables is
  // different from the dimension. In this case it can only be dim+1,
  // otherwise an exception would have already been thrown
  if(dim != n_vars)
    vars[dim] = this->get_time();

  double my_value = fp[component].Eval(vars);

  AssertThrow(fp[component].EvalError() == 0,
	      ExcMessage(fp[component].ErrorMsg()));
  return my_value;
}

template <int dim>
void FunctionParser<dim>::vector_value (const Point<dim> &p,
					Vector<double>   &values) const
{
    AssertThrow(initialized==true, ExcNotInitialized());
    AssertThrow(values.size() == this->n_components,
		ExcDimensionMismatch (values.size(), this->n_components));
    // Statically allocates dim+1 double variables.
    double vars[dim+1];

    for(unsigned int i=0; i<dim; ++i)
      vars[i] = p(i);

    // We need the time variable only if the number of variables is
    // different from the dimension. In this case it can only be dim+1,
    // otherwise an exception would have already been thrown
    if(dim != n_vars)
      vars[dim] = this->get_time();

    for(unsigned int component = 0; component < this->n_components;
	++component) {
      values(component) = fp[component].Eval(vars);
      Assert(fp[component].EvalError() == 0,
	     ExcMessage(fp[component].ErrorMsg()));
    }
}

#else

template <int dim>
void FunctionParser<dim>::initialize(
  const std::string, const std::vector<std::string>,
  std::map<std::string, double>, bool, bool)
{
  Assert(false, ExcDisabled("parser"));
}

template <int dim>
void FunctionParser<dim>::initialize(
  const std::string, const std::string,
  std::map<std::string, double>, bool, bool)
{
  Assert(false, ExcDisabled("parser"));
}

template <int dim>
double FunctionParser<dim>::value (
  const Point<dim> &, unsigned int) const
{
  Assert(false, ExcDisabled("parser"));
  return 0.;
}

template <int dim>
void FunctionParser<dim>::vector_value (
  const Point<dim>&, Vector<double>&) const
{
  Assert(false, ExcDisabled("parser"));
}

#endif

// Explicit Instantiations.

template class FunctionParser<1>;
template class FunctionParser<2>;
template class FunctionParser<3>;
<commit_msg>Fixed a bug in the split string utility. Made code more readable and less involuted.<commit_after>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2005 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <base/function_parser.h>
#include <base/point.h>
#include <lac/vector.h>

// Utility to split a string given a delimiter.

unsigned int SplitString(const std::string& input,
			 const std::string& delimiter,
			 std::vector<std::string>& results)
{
  // Size of the delimiter. Use it to calculate the offsets between
  // different pieces of the string
  unsigned int sizeS2 = delimiter.size();
  // Counter for Current Position
  unsigned int iPos = 0;
  // Counter for Position of next delimiter
  unsigned int newPos = 0;
  // Counter for Number of strings
  unsigned int numFound = 0;

  while( newPos != std::string::npos )
    {
      // Look for a delimiter starting with the correct offset. Note
      // that if it is the beginning of the cycle the offset is zero.
      newPos = input.find (delimiter, iPos);
      // We either found a delimiter inside the string or the
      // delimiter was not found. Increment the found counter anyway,
      // as if there are no delimiters, we return one vector
      // containing exacly one string anyway
      numFound++;
      // Add the string we just found to the output vector
      Assert(iPos <= input.size(), ExcInternalError());
      results.push_back(input.substr(iPos, newPos-iPos));
      // Update the current position with the correct offset.
      iPos = newPos+sizeS2+1;
    }
  // At least we found one string and no delimiters.
  Assert(numFound > 0, ExcInternalError());
  return numFound;
}

template <int dim>
FunctionParser<dim>::FunctionParser(const unsigned int n_components,
				    const double       initial_time)
                :
                Function<dim>(n_components, initial_time),
                fp (0)
{
  fp = new fparser::FunctionParser[n_components];
}

template <int dim>
FunctionParser<dim>::~FunctionParser() {
  delete[] fp;
}

#ifndef DEAL_II_DISABLE_PARSER

template <int dim>
void FunctionParser<dim>::initialize(const std::string variables,
				     const std::vector<std::string> expressions,
				     std::map<std::string, double> constants,
				     bool time_dependent,
				     bool use_degrees)
{
  // We check that the number of components of this function matches
  // the number of components passed in as a vector of strings.
  AssertThrow(this->n_components == expressions.size(),
	      ExcInvalidExpressionSize(this->n_components,
				       expressions.size()) );

  for (unsigned int i=0; i<this->n_components; ++i) {
    // Add the variuous constants to the parser.
    std::map< std::string, double >::const_iterator
      constant = constants.begin(),
      endc  = constants.end();
    for(;constant != endc; ++constant) {
      AssertThrow( fp[i].AddConstant(constant->first, constant->second),
		   ExcMessage("Invalid Constant Name"));
    }

    int ret_value = fp[i].Parse(expressions[i],
				variables,
				use_degrees);
    AssertThrow(ret_value == -1,
		ExcParseError(ret_value, fp[i].ErrorMsg()));

    // The fact that the parser did not throw an error does not mean
    // that everything went ok... we can still have problems with the
    // number of variables...
  }

  // Now we define how many variables we expect to read in.  We
  // distinguish between two cases: Time dependent problems, and not
  // time dependent problems. In the first case the number of
  // variables is given by the dimension plus one. In the other case,
  // the number of variables is equal to the dimension. Once we parsed
  // the variables string, if none of this is the case, then an
  // exception is thrown.
  if (time_dependent)
    n_vars = dim+1;
  else
    n_vars = dim;

  // Let's check if the number of variables is correct...
  AssertThrow(n_vars == fp[0].NVars(),
	      ExcDimensionMismatch(n_vars,fp[0].NVars()));

  // Now set the initialization bit.
  initialized = true;
}

template <int dim>
void FunctionParser<dim>::initialize(const std::string variables,
				     const std::string expression,
				     std::map<std::string, double> constants,
				     bool time_dependent,
				     bool use_degrees)
{
  // Start up with an empty vector of expressions.
  std::vector<std::string> expressions;

  // In this case a vector function is built with the number of
  // components found between the separators ';'
  SplitString(expression, ";", expressions);
  // Now initialize with the things we got.
  initialize
    (variables, expressions, constants, time_dependent, use_degrees);
}

template <int dim>
double FunctionParser<dim>::value (const Point<dim> &p,
				   unsigned int component) const
{
  AssertThrow(initialized==true, ExcNotInitialized());
  AssertThrow(component < this->n_components,
	      ExcIndexRange(component, 0, this->n_components));
  // Statically allocates dim+1 double variables.
  double vars[dim+1];

  for(unsigned int i=0; i<dim; ++i)
    vars[i] = p(i);

  // We need the time variable only if the number of variables is
  // different from the dimension. In this case it can only be dim+1,
  // otherwise an exception would have already been thrown
  if(dim != n_vars)
    vars[dim] = this->get_time();

  double my_value = fp[component].Eval(vars);

  AssertThrow(fp[component].EvalError() == 0,
	      ExcMessage(fp[component].ErrorMsg()));
  return my_value;
}

template <int dim>
void FunctionParser<dim>::vector_value (const Point<dim> &p,
					Vector<double>   &values) const
{
    AssertThrow(initialized==true, ExcNotInitialized());
    AssertThrow(values.size() == this->n_components,
		ExcDimensionMismatch (values.size(), this->n_components));
    // Statically allocates dim+1 double variables.
    double vars[dim+1];

    for(unsigned int i=0; i<dim; ++i)
      vars[i] = p(i);

    // We need the time variable only if the number of variables is
    // different from the dimension. In this case it can only be dim+1,
    // otherwise an exception would have already been thrown
    if(dim != n_vars)
      vars[dim] = this->get_time();

    for(unsigned int component = 0; component < this->n_components;
	++component) {
      values(component) = fp[component].Eval(vars);
      Assert(fp[component].EvalError() == 0,
	     ExcMessage(fp[component].ErrorMsg()));
    }
}

#else

template <int dim>
void FunctionParser<dim>::initialize(
  const std::string, const std::vector<std::string>,
  std::map<std::string, double>, bool, bool)
{
  Assert(false, ExcDisabled("parser"));
}

template <int dim>
void FunctionParser<dim>::initialize(
  const std::string, const std::string,
  std::map<std::string, double>, bool, bool)
{
  Assert(false, ExcDisabled("parser"));
}

template <int dim>
double FunctionParser<dim>::value (
  const Point<dim> &, unsigned int) const
{
  Assert(false, ExcDisabled("parser"));
  return 0.;
}

template <int dim>
void FunctionParser<dim>::vector_value (
  const Point<dim>&, Vector<double>&) const
{
  Assert(false, ExcDisabled("parser"));
}

#endif

// Explicit Instantiations.

template class FunctionParser<1>;
template class FunctionParser<2>;
template class FunctionParser<3>;
<|endoftext|>


<commit_before>// Copyright(c) Andre Caron <andre.l.caron@gmail.com>, 2011
//
// This document is covered by the an Open Source Initiative approved license. A
// copy of the license should have been provided alongside this software package
// (see "LICENSE.txt"). If not, terms of the license are available online at
// "http://www.opensource.org/licenses/mit".

#include "qwssession.hpp"

#include <algorithm>
#include <locale>
#include <sstream>

#include <QDebug>

namespace {

    class Lower {
        std::locale myLocale;
    public:
        Lower ( const std::locale& locale=std::locale() )
            : myLocale(locale)
        {}
        char operator() ( char x ) const {
            return (std::tolower(x, myLocale));
        }
    };

    const std::string lower ( std::string x ) {
        std::transform(x.begin(), x.end(), x.begin(), Lower()); return (x);
    }

    // Refer to websocket specification for details.
    const std::string accept_key ( const std::string& skey )
    {
        static const std::string guid
            ("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
        QCryptographicHash hash(QCryptographicHash::Sha1);
        hash.addData(skey.data(), skey.size());
        hash.addData(guid.data(), guid.size());
        const QByteArray result = hash.result().toBase64();
        return (std::string(result.data(), result.size()));
    }

}

namespace qws {

    Session::Session ( QTcpSocket * socket, QObject * parent )
        : QObject(parent), mySocket(socket), myState(Connecting)
    {
          // Configure in-bound web socket traffic.
        ::ws_iwire_init(&myIWire);
        myIWire.baton = this;
        myIWire.new_message    = &Session::new_message;
        myIWire.end_message    = &Session::end_message;
        myIWire.new_fragment   = &Session::new_frame;
        myIWire.end_fragment   = &Session::end_frame;
        myIWire.accept_content = &Session::accept_ibound_content;

          // Configure out-bound web socket traffic.
        ::ws_owire_init(&myOWire);
        myOWire.baton = this;
        myOWire.accept_content = &Session::accept_obound_content;

          // Delete this wrapper object when the socket is disconnected.
        QObject::connect(
            socket, SIGNAL(disconnected()), this, SLOT(deleteLater()));

          // Get notified when data arrives on the socket.  Make sure this call
          // is last.  Don't start processing data until we finished configuring
          // the object.
        QObject::connect(
            socket, SIGNAL(readyRead()), this, SLOT(consume()));
    }

    Session::~Session ()
    {
    }

    void Session::autopong ()
    {
        QObject::connect(
            this, SIGNAL(ping(const void*,quint64)),
            this,   SLOT(pong(const void*,quint64)));
    }

    void Session::sendtext ( const void * data, quint64 size )
    {
        ::ws_owire_put_text(&myOWire, data, size);
    }

    void Session::sendtext ( const QString& payload )
    {
        sendtext(payload.toUtf8());
    }

    void Session::sendtext ( const QByteArray& payload )
    {
        sendtext(payload.data(), payload.size());
    }

    void Session::senddata ( const void * data, quint64 size )
    {
        ::ws_owire_put_data(&myOWire, data, size);
    }

    void Session::senddata ( const QByteArray& payload )
    {
        senddata(payload.data(), payload.size());
    }

    void Session::ping ()
    {
        ::ws_owire_put_ping(&myOWire, 0, 0);
    }

    void Session::ping ( const void * data, quint64 size )
    {
        ::ws_owire_put_ping(&myOWire, data, size);
    }

    void Session::pong ()
    {
        ::ws_owire_put_pong(&myOWire, 0, 0);
    }

    void Session::pong ( const void * data, quint64 size )
    {
        ::ws_owire_put_pong(&myOWire, data, size);
    }

    void Session::close ()
    {
        ::ws_owire_put_kill(&myOWire, 0, 0);
    }

    void Session::close ( const void * data, quint64 size )
    {
        ::ws_owire_put_kill(&myOWire, data, size);
    }

    void Session::consume ()
    {
        if ( myState == Connecting )
        {
              // Read all available data and feed websocket parser.
            char data[1024];
            qint64 size = 0;
            do {
                size = mySocket->read(data, sizeof(data));
                ::ws_iwire_feed(&myIWire, data, size);
            }
            while ( size > 0 );
        }
          // Complete web socket handshake.
        else if ( myState == Open )
        {
              // Read all available data and feed HTTP parser.
            char data[1024];
            qint64 size = 0;
            qint64 used = 0;
            do {
                size = mySocket->read(data, sizeof(data));
                used = myRequest.feed(data, size);
            }
            while ((size > 0) && (used == size) && !myRequest.complete());

              // Repeat until request is complete.
            if ( !myRequest.complete() ) {
                return;
            }
            emit request();

              // Make sure this is a web socket upgrade request.
            // Check 'Host' header.
            // Check 'Origin' header.
            // Check 'Connection' header.
            if ( !myRequest.upgrade() ||
                (myRequest.header("Upgrade") != "websocket"))
            {
                print("Not an upgrade request!");
                emit invalid();
                  // Fail the web socket connection.
                shutdown();
                return;
            }

              // Check client/server compatibility.
            // Check 'Sec-WebSocket-Version' header.
            // Check 'Sec-WebSocket-Protocol' header.
            // Check 'Sec-WebSocket-Extensions' header.
            // ...

              // Check 'Sec-WebSocket-Key' header.
            const std::string key =
                ::accept_key(myRequest.header("Sec-WebSocket-Key"));

              // Confirm handshake completion.
            std::string response;
            {
                std::ostringstream stream;
                stream
                    << "HTTP/1.1 101 Switching Protocols\r\n"
                    << "Upgrade: websocket\r\n"
                    << "Connection: Upgrade\r\n"
                    << "Sec-WebSocket-Accept: " << key << "\r\n"
                    << "Sec-WebSocket-Version: 13" << "\r\n"
                    << "\r\n";
                response = stream.str();
            }
            mySocket->write(response.data(), response.size());

              // Connection upgrade successful.
            myState = Open;
            emit upgrade();

              // Forward any data following HTTP request.
            if ( used < size ) {
                ::ws_iwire_feed(&myIWire, data+used, size-used);
            }

              // Check right away for available data.
            emit consume();
        }
    }

    void Session::shutdown ()
    {
          // Start websocket closing handshake.
        ::ws_owire_put_kill(&myOWire, 0, 0);
        myState = Closing;
          // Initiate TCP shutdown.
        mySocket->disconnectFromHost();
    }

    void Session::kill ()
    {
          // Close socket without closing handshake or TCP shutdown.
        mySocket->abort();
    }

    void Session::new_message ( ::ws_iwire * backend )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.newmessage();
    }

    void Session::end_message ( ::ws_iwire * backend )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.endmessage();
        if ( ::ws_iwire_dead(backend) ) {
            emit client.closed();
        }
    }

    void Session::new_frame ( ::ws_iwire * backend, uint64 size )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.newframe(size);
    }

    void Session::end_frame ( ::ws_iwire * backend )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.endframe();
    }

    void Session::accept_ibound_content (
        ::ws_iwire * backend, const void * data, uint64 size )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        if ( ::ws_iwire_ping(backend) ) {
            emit client.pinged(data, size);
        }
        if ( ::ws_iwire_pong(backend) ) {
            emit client.ponged(data, size);
        }
        if ( ::ws_iwire_text(backend) ) {
            emit client.text(data, size);
        }
        if ( ::ws_iwire_data(backend) ) {
            emit client.data(data, size);
        }
    }

    void Session::accept_obound_content (
        ::ws_owire * backend, const void * data, uint64 size )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        quint64 used = 0;
        do {
            used += client.mySocket->write(
                static_cast<const char*>(data)+used, size-used);
        }
        while ( used < size );
    }

}
<commit_msg>Fixed inverted state.<commit_after>// Copyright(c) Andre Caron <andre.l.caron@gmail.com>, 2011
//
// This document is covered by the an Open Source Initiative approved license. A
// copy of the license should have been provided alongside this software package
// (see "LICENSE.txt"). If not, terms of the license are available online at
// "http://www.opensource.org/licenses/mit".

#include "qwssession.hpp"

#include <algorithm>
#include <locale>
#include <sstream>

#include <QDebug>

namespace {

    class Lower {
        std::locale myLocale;
    public:
        Lower ( const std::locale& locale=std::locale() )
            : myLocale(locale)
        {}
        char operator() ( char x ) const {
            return (std::tolower(x, myLocale));
        }
    };

    const std::string lower ( std::string x ) {
        std::transform(x.begin(), x.end(), x.begin(), Lower()); return (x);
    }

    // Refer to websocket specification for details.
    const std::string accept_key ( const std::string& skey )
    {
        static const std::string guid
            ("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
        QCryptographicHash hash(QCryptographicHash::Sha1);
        hash.addData(skey.data(), skey.size());
        hash.addData(guid.data(), guid.size());
        const QByteArray result = hash.result().toBase64();
        return (std::string(result.data(), result.size()));
    }

}

namespace qws {

    Session::Session ( QTcpSocket * socket, QObject * parent )
        : QObject(parent), mySocket(socket), myState(Connecting)
    {
          // Configure in-bound web socket traffic.
        ::ws_iwire_init(&myIWire);
        myIWire.baton = this;
        myIWire.new_message    = &Session::new_message;
        myIWire.end_message    = &Session::end_message;
        myIWire.new_fragment   = &Session::new_frame;
        myIWire.end_fragment   = &Session::end_frame;
        myIWire.accept_content = &Session::accept_ibound_content;

          // Configure out-bound web socket traffic.
        ::ws_owire_init(&myOWire);
        myOWire.baton = this;
        myOWire.accept_content = &Session::accept_obound_content;

          // Delete this wrapper object when the socket is disconnected.
        QObject::connect(
            socket, SIGNAL(disconnected()), this, SLOT(deleteLater()));

          // Get notified when data arrives on the socket.  Make sure this call
          // is last.  Don't start processing data until we finished configuring
          // the object.
        QObject::connect(
            socket, SIGNAL(readyRead()), this, SLOT(consume()));
    }

    Session::~Session ()
    {
    }

    void Session::autopong ()
    {
        QObject::connect(
            this, SIGNAL(ping(const void*,quint64)),
            this,   SLOT(pong(const void*,quint64)));
    }

    void Session::sendtext ( const void * data, quint64 size )
    {
        ::ws_owire_put_text(&myOWire, data, size);
    }

    void Session::sendtext ( const QString& payload )
    {
        sendtext(payload.toUtf8());
    }

    void Session::sendtext ( const QByteArray& payload )
    {
        sendtext(payload.data(), payload.size());
    }

    void Session::senddata ( const void * data, quint64 size )
    {
        ::ws_owire_put_data(&myOWire, data, size);
    }

    void Session::senddata ( const QByteArray& payload )
    {
        senddata(payload.data(), payload.size());
    }

    void Session::ping ()
    {
        ::ws_owire_put_ping(&myOWire, 0, 0);
    }

    void Session::ping ( const void * data, quint64 size )
    {
        ::ws_owire_put_ping(&myOWire, data, size);
    }

    void Session::pong ()
    {
        ::ws_owire_put_pong(&myOWire, 0, 0);
    }

    void Session::pong ( const void * data, quint64 size )
    {
        ::ws_owire_put_pong(&myOWire, data, size);
    }

    void Session::close ()
    {
        ::ws_owire_put_kill(&myOWire, 0, 0);
    }

    void Session::close ( const void * data, quint64 size )
    {
        ::ws_owire_put_kill(&myOWire, data, size);
    }

    void Session::consume ()
    {
        if ( myState == Open )
        {
              // Read all available data and feed websocket parser.
            char data[1024];
            qint64 size = 0;
            do {
                size = mySocket->read(data, sizeof(data));
                ::ws_iwire_feed(&myIWire, data, size);
            }
            while ( size > 0 );
        }
          // Complete web socket handshake.
        else if ( myState == Connecting )
        {
              // Read all available data and feed HTTP parser.
            char data[1024];
            qint64 size = 0;
            qint64 used = 0;
            do {
                size = mySocket->read(data, sizeof(data));
                used = myRequest.feed(data, size);
            }
            while ((size > 0) && (used == size) && !myRequest.complete());

              // Repeat until request is complete.
            if ( !myRequest.complete() ) {
                return;
            }
            emit request();

              // Make sure this is a web socket upgrade request.
            // Check 'Host' header.
            // Check 'Origin' header.
            // Check 'Connection' header.
            if ( !myRequest.upgrade() ||
                (myRequest.header("Upgrade") != "websocket"))
            {
                print("Not an upgrade request!");
                emit invalid();
                  // Fail the web socket connection.
                shutdown();
                return;
            }

              // Check client/server compatibility.
            // Check 'Sec-WebSocket-Version' header.
            // Check 'Sec-WebSocket-Protocol' header.
            // Check 'Sec-WebSocket-Extensions' header.
            // ...

              // Check 'Sec-WebSocket-Key' header.
            const std::string key =
                ::accept_key(myRequest.header("Sec-WebSocket-Key"));

              // Confirm handshake completion.
            std::string response;
            {
                std::ostringstream stream;
                stream
                    << "HTTP/1.1 101 Switching Protocols\r\n"
                    << "Upgrade: websocket\r\n"
                    << "Connection: Upgrade\r\n"
                    << "Sec-WebSocket-Accept: " << key << "\r\n"
                    << "Sec-WebSocket-Version: 13" << "\r\n"
                    << "\r\n";
                response = stream.str();
            }
            mySocket->write(response.data(), response.size());

              // Connection upgrade successful.
            myState = Open;
            emit upgrade();

              // Forward any data following HTTP request.
            if ( used < size ) {
                ::ws_iwire_feed(&myIWire, data+used, size-used);
            }

              // Check right away for available data.
            emit consume();
        }
    }

    void Session::shutdown ()
    {
          // Start websocket closing handshake.
        ::ws_owire_put_kill(&myOWire, 0, 0);
        myState = Closing;
          // Initiate TCP shutdown.
        mySocket->disconnectFromHost();
    }

    void Session::kill ()
    {
          // Close socket without closing handshake or TCP shutdown.
        mySocket->abort();
    }

    void Session::new_message ( ::ws_iwire * backend )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.newmessage();
    }

    void Session::end_message ( ::ws_iwire * backend )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.endmessage();
        if ( ::ws_iwire_dead(backend) ) {
            emit client.closed();
        }
    }

    void Session::new_frame ( ::ws_iwire * backend, uint64 size )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.newframe(size);
    }

    void Session::end_frame ( ::ws_iwire * backend )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        emit client.endframe();
    }

    void Session::accept_ibound_content (
        ::ws_iwire * backend, const void * data, uint64 size )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        if ( ::ws_iwire_ping(backend) ) {
            emit client.pinged(data, size);
        }
        if ( ::ws_iwire_pong(backend) ) {
            emit client.ponged(data, size);
        }
        if ( ::ws_iwire_text(backend) ) {
            emit client.text(data, size);
        }
        if ( ::ws_iwire_data(backend) ) {
            emit client.data(data, size);
        }
    }

    void Session::accept_obound_content (
        ::ws_owire * backend, const void * data, uint64 size )
    {
        Session& client = *static_cast<Session*>(backend->baton);
        quint64 used = 0;
        do {
            used += client.mySocket->write(
                static_cast<const char*>(data)+used, size-used);
        }
        while ( used < size );
    }

}
<|endoftext|>


<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <cmath>
#include "Effects.hpp"
#include "Audio.hpp"
#include "scene/Actor.hpp"
#include "math/MathUtils.hpp"
#include "smbPitchShift.hpp"

namespace ouzel
{
    namespace audio
    {
        class DelayProcessor final: public mixer::Processor
        {
        public:
            DelayProcessor(float initDelay):
                delay(initDelay)
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
                const uint32_t delayFrames = static_cast<uint32_t>(delay * sampleRate);
                const uint32_t bufferFrames = frames + delayFrames;

                buffer.resize(bufferFrames * channels);

                for (uint16_t channel = 0; channel < channels; ++channel)
                {
                    float* bufferChannel = &buffer[channel * bufferFrames];
                    float* outputChannel = &samples[channel * frames];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        bufferChannel[frame + delayFrames] += outputChannel[frame];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        outputChannel[frame] = bufferChannel[frame];

                    // erase frames from beginning
                    for (uint32_t frame = 0; frame < bufferFrames - frames; ++frame)
                        bufferChannel[frame] = bufferChannel[frame + frames];

                    for (uint32_t frame = bufferFrames - frames; frame < bufferFrames; ++frame)
                        bufferChannel[frame] = 0.0F;
                }
            }

            void setDelay(float newDelay)
            {
                delay = newDelay;
            }

        private:
            float delay = 0.0F;
            std::vector<float> buffer;
        };

        Delay::Delay(Audio& initAudio, float initDelay):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new DelayProcessor(initDelay)))),
            delay(initDelay)
        {
        }

        Delay::~Delay()
        {
        }

        void Delay::setDelay(float newDelay)
        {
            delay = newDelay;

            audio.updateProcessor(processorId, [newDelay](mixer::Object* node) {
                DelayProcessor* delayProcessor = static_cast<DelayProcessor*>(node);
                delayProcessor->setDelay(newDelay);
            });
        }

        class GainProcessor final: public mixer::Processor
        {
        public:
            GainProcessor(float initGain = 0.0F):
                gain(initGain),
                gainFactor(pow(10.0F, initGain / 20.0F))
            {
            }

            void process(uint32_t, uint16_t, uint32_t,
                         std::vector<float>& samples) override
            {
                for (float& sample : samples)
                    sample *= gainFactor;
            }

            void setGain(float newGain)
            {
                gain = newGain;
                gainFactor = pow(10.0F, gain / 20.0F);
            }

        private:
            float gain = 0.0F;
            float gainFactor = 1.0F;
        };

        Gain::Gain(Audio& initAudio, float initGain):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new GainProcessor(initGain)))),
            gain(initGain)
        {
        }

        Gain::~Gain()
        {
        }

        void Gain::setGain(float newGain)
        {
            gain = newGain;

            audio.updateProcessor(processorId, [newGain](mixer::Object* node) {
                GainProcessor* gainProcessor = static_cast<GainProcessor*>(node);
                gainProcessor->setGain(newGain);
            });
        }

        class PannerProcessor final: public mixer::Processor
        {
        public:
            PannerProcessor()
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
            }

            void setPosition(const Vector3F& newPosition)
            {
                position = newPosition;
            }

            void setRolloffFactor(float newRolloffFactor)
            {
                rolloffFactor = newRolloffFactor;
            }

            void setMinDistance(float newMinDistance)
            {
                minDistance = newMinDistance;
            }

            void setMaxDistance(float newMaxDistance)
            {
                maxDistance = newMaxDistance;
            }

        private:
            Vector3F position;
            float rolloffFactor = 1.0F;
            float minDistance = 1.0F;
            float maxDistance = FLT_MAX;
        };

        Panner::Panner(Audio& initAudio):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new PannerProcessor()))),
            scene::Component(scene::Component::SOUND)
        {
        }

        Panner::~Panner()
        {
        }

        void Panner::setPosition(const Vector3F& newPosition)
        {
            position = newPosition;

            audio.updateProcessor(processorId, [newPosition](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setPosition(newPosition);
            });
        }

        void Panner::setRolloffFactor(float newRolloffFactor)
        {
            rolloffFactor = newRolloffFactor;

            audio.updateProcessor(processorId, [newRolloffFactor](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setRolloffFactor(newRolloffFactor);
            });
        }

        void Panner::setMinDistance(float newMinDistance)
        {
            minDistance = newMinDistance;

            audio.updateProcessor(processorId, [newMinDistance](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setMinDistance(newMinDistance);
            });
        }

        void Panner::setMaxDistance(float newMaxDistance)
        {
            maxDistance = newMaxDistance;

            audio.updateProcessor(processorId, [newMaxDistance](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setMaxDistance(newMaxDistance);
            });
        }

        void Panner::updateTransform()
        {
            setPosition(actor->getWorldPosition());
        }

        static constexpr float MIN_PITCH = 0.5F;
        static constexpr float MAX_PITCH = 2.0F;

        class PitchProcessor final: public mixer::Processor
        {
        public:
            PitchProcessor(float initPitch):
                pitch(clamp(initPitch, MIN_PITCH, MAX_PITCH))
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
                channelSamples.resize(frames);
                pitchShift.resize(channels);

                for (uint16_t channel = 0; channel < channels; ++channel)
                {
                    pitchShift[channel].process(pitch, frames, 1024, 4, static_cast<float>(sampleRate),
                                                samples.data() + channel * frames,
                                                channelSamples.data());

                    float* outputChannel = &samples[channel * frames];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        outputChannel[frame] = channelSamples[frame];
                }
            }

            void setPitch(float newPitch)
            {
                pitch = clamp(newPitch, MIN_PITCH, MAX_PITCH);
            }

        private:
            float pitch = 1.0f;
            std::vector<float> channelSamples;
            std::vector<smb::PitchShift> pitchShift;
        };

        Pitch::Pitch(Audio& initAudio, float initPitch):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new PitchProcessor(initPitch)))),
            pitch(initPitch)
        {
        }

        Pitch::~Pitch()
        {
        }

        void Pitch::setPitch(float newPitch)
        {
            pitch = newPitch;

            audio.updateProcessor(processorId, [newPitch](mixer::Object* node) {
                PitchProcessor* pitchProcessor = static_cast<PitchProcessor*>(node);
                pitchProcessor->setPitch(newPitch);
            });
        }

        class ReverbProcessor final: public mixer::Processor
        {
        public:
            ReverbProcessor(float initDelay, float initDecay):
                delay(initDelay), decay(initDecay)
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
                const uint32_t delayFrames = static_cast<uint32_t>(delay * sampleRate);
                const uint32_t bufferFrames = frames + delayFrames;

                buffers.resize(channels);

                for (uint16_t channel = 0; channel < channels; ++channel)
                {
                    std::vector<float>& buffer = buffers[channel];
                    buffer.resize(bufferFrames);

                    float* outputChannel = &samples[channel * frames];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        buffer[frame] += outputChannel[frame];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        buffer[frame + delayFrames] += buffer[frame] * decay;

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        outputChannel[frame] = buffer[frame];

                    // erase frames from beginning
                    buffer.erase(buffer.begin(), buffer.begin() + frames);
                }
            }

        private:
            float delay = 0.1F;
            float decay = 0.5F;
            std::vector<std::vector<float>> buffers;
        };

        Reverb::Reverb(Audio& initAudio, float initDelay, float initDecay):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new ReverbProcessor(initDelay, initDecay)))),
            delay(initDelay),
            decay(initDecay)
        {
        }

        Reverb::~Reverb()
        {
        }

        LowPass::LowPass(Audio& initAudio):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>()))
        {
        }

        LowPass::~LowPass()
        {
        }

        HighPass::HighPass(Audio& initAudio):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>()))
        {
        }

        HighPass::~HighPass()
        {
        }
    } // namespace audio
} // namespace ouzel
<commit_msg>Don't use a separate buffer for channel samples in the pitch filter<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <cmath>
#include "Effects.hpp"
#include "Audio.hpp"
#include "scene/Actor.hpp"
#include "math/MathUtils.hpp"
#include "smbPitchShift.hpp"

namespace ouzel
{
    namespace audio
    {
        class DelayProcessor final: public mixer::Processor
        {
        public:
            DelayProcessor(float initDelay):
                delay(initDelay)
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
                const uint32_t delayFrames = static_cast<uint32_t>(delay * sampleRate);
                const uint32_t bufferFrames = frames + delayFrames;

                buffer.resize(bufferFrames * channels);

                for (uint16_t channel = 0; channel < channels; ++channel)
                {
                    float* bufferChannel = &buffer[channel * bufferFrames];
                    float* outputChannel = &samples[channel * frames];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        bufferChannel[frame + delayFrames] += outputChannel[frame];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        outputChannel[frame] = bufferChannel[frame];

                    // erase frames from beginning
                    for (uint32_t frame = 0; frame < bufferFrames - frames; ++frame)
                        bufferChannel[frame] = bufferChannel[frame + frames];

                    for (uint32_t frame = bufferFrames - frames; frame < bufferFrames; ++frame)
                        bufferChannel[frame] = 0.0F;
                }
            }

            void setDelay(float newDelay)
            {
                delay = newDelay;
            }

        private:
            float delay = 0.0F;
            std::vector<float> buffer;
        };

        Delay::Delay(Audio& initAudio, float initDelay):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new DelayProcessor(initDelay)))),
            delay(initDelay)
        {
        }

        Delay::~Delay()
        {
        }

        void Delay::setDelay(float newDelay)
        {
            delay = newDelay;

            audio.updateProcessor(processorId, [newDelay](mixer::Object* node) {
                DelayProcessor* delayProcessor = static_cast<DelayProcessor*>(node);
                delayProcessor->setDelay(newDelay);
            });
        }

        class GainProcessor final: public mixer::Processor
        {
        public:
            GainProcessor(float initGain = 0.0F):
                gain(initGain),
                gainFactor(pow(10.0F, initGain / 20.0F))
            {
            }

            void process(uint32_t, uint16_t, uint32_t,
                         std::vector<float>& samples) override
            {
                for (float& sample : samples)
                    sample *= gainFactor;
            }

            void setGain(float newGain)
            {
                gain = newGain;
                gainFactor = pow(10.0F, gain / 20.0F);
            }

        private:
            float gain = 0.0F;
            float gainFactor = 1.0F;
        };

        Gain::Gain(Audio& initAudio, float initGain):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new GainProcessor(initGain)))),
            gain(initGain)
        {
        }

        Gain::~Gain()
        {
        }

        void Gain::setGain(float newGain)
        {
            gain = newGain;

            audio.updateProcessor(processorId, [newGain](mixer::Object* node) {
                GainProcessor* gainProcessor = static_cast<GainProcessor*>(node);
                gainProcessor->setGain(newGain);
            });
        }

        class PannerProcessor final: public mixer::Processor
        {
        public:
            PannerProcessor()
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
            }

            void setPosition(const Vector3F& newPosition)
            {
                position = newPosition;
            }

            void setRolloffFactor(float newRolloffFactor)
            {
                rolloffFactor = newRolloffFactor;
            }

            void setMinDistance(float newMinDistance)
            {
                minDistance = newMinDistance;
            }

            void setMaxDistance(float newMaxDistance)
            {
                maxDistance = newMaxDistance;
            }

        private:
            Vector3F position;
            float rolloffFactor = 1.0F;
            float minDistance = 1.0F;
            float maxDistance = FLT_MAX;
        };

        Panner::Panner(Audio& initAudio):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new PannerProcessor()))),
            scene::Component(scene::Component::SOUND)
        {
        }

        Panner::~Panner()
        {
        }

        void Panner::setPosition(const Vector3F& newPosition)
        {
            position = newPosition;

            audio.updateProcessor(processorId, [newPosition](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setPosition(newPosition);
            });
        }

        void Panner::setRolloffFactor(float newRolloffFactor)
        {
            rolloffFactor = newRolloffFactor;

            audio.updateProcessor(processorId, [newRolloffFactor](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setRolloffFactor(newRolloffFactor);
            });
        }

        void Panner::setMinDistance(float newMinDistance)
        {
            minDistance = newMinDistance;

            audio.updateProcessor(processorId, [newMinDistance](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setMinDistance(newMinDistance);
            });
        }

        void Panner::setMaxDistance(float newMaxDistance)
        {
            maxDistance = newMaxDistance;

            audio.updateProcessor(processorId, [newMaxDistance](mixer::Object* node) {
                PannerProcessor* pannerProcessor = static_cast<PannerProcessor*>(node);
                pannerProcessor->setMaxDistance(newMaxDistance);
            });
        }

        void Panner::updateTransform()
        {
            setPosition(actor->getWorldPosition());
        }

        static constexpr float MIN_PITCH = 0.5F;
        static constexpr float MAX_PITCH = 2.0F;

        class PitchProcessor final: public mixer::Processor
        {
        public:
            PitchProcessor(float initPitch):
                pitch(clamp(initPitch, MIN_PITCH, MAX_PITCH))
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
                pitchShift.resize(channels);

                for (uint16_t channel = 0; channel < channels; ++channel)
                {
                    pitchShift[channel].process(pitch, frames, 1024, 4, static_cast<float>(sampleRate),
                                                &samples[channel * frames],
                                                &samples[channel * frames]);
                }
            }

            void setPitch(float newPitch)
            {
                pitch = clamp(newPitch, MIN_PITCH, MAX_PITCH);
            }

        private:
            float pitch = 1.0f;
            std::vector<smb::PitchShift> pitchShift;
        };

        Pitch::Pitch(Audio& initAudio, float initPitch):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new PitchProcessor(initPitch)))),
            pitch(initPitch)
        {
        }

        Pitch::~Pitch()
        {
        }

        void Pitch::setPitch(float newPitch)
        {
            pitch = newPitch;

            audio.updateProcessor(processorId, [newPitch](mixer::Object* node) {
                PitchProcessor* pitchProcessor = static_cast<PitchProcessor*>(node);
                pitchProcessor->setPitch(newPitch);
            });
        }

        class ReverbProcessor final: public mixer::Processor
        {
        public:
            ReverbProcessor(float initDelay, float initDecay):
                delay(initDelay), decay(initDecay)
            {
            }

            void process(uint32_t frames, uint16_t channels, uint32_t sampleRate,
                         std::vector<float>& samples) override
            {
                const uint32_t delayFrames = static_cast<uint32_t>(delay * sampleRate);
                const uint32_t bufferFrames = frames + delayFrames;

                buffers.resize(channels);

                for (uint16_t channel = 0; channel < channels; ++channel)
                {
                    std::vector<float>& buffer = buffers[channel];
                    buffer.resize(bufferFrames);

                    float* outputChannel = &samples[channel * frames];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        buffer[frame] += outputChannel[frame];

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        buffer[frame + delayFrames] += buffer[frame] * decay;

                    for (uint32_t frame = 0; frame < frames; ++frame)
                        outputChannel[frame] = buffer[frame];

                    // erase frames from beginning
                    buffer.erase(buffer.begin(), buffer.begin() + frames);
                }
            }

        private:
            float delay = 0.1F;
            float decay = 0.5F;
            std::vector<std::vector<float>> buffers;
        };

        Reverb::Reverb(Audio& initAudio, float initDelay, float initDecay):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>(new ReverbProcessor(initDelay, initDecay)))),
            delay(initDelay),
            decay(initDecay)
        {
        }

        Reverb::~Reverb()
        {
        }

        LowPass::LowPass(Audio& initAudio):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>()))
        {
        }

        LowPass::~LowPass()
        {
        }

        HighPass::HighPass(Audio& initAudio):
            Effect(initAudio,
                   initAudio.initProcessor(std::unique_ptr<mixer::Processor>()))
        {
        }

        HighPass::~HighPass()
        {
        }
    } // namespace audio
} // namespace ouzel
<|endoftext|>