<commit_before>#include <iostream>
#include <string>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include "parsers.hpp"

namespace Parsers {

namespace Int {

Expr::Parser<mpz_class> parser(convert, "%^");

gmp_randclass random(gmp_randinit_default);

inline bool assert_positive(std::string func_name, const mpz_class &n){
  if(n <= 0)
    throw func_name + "(): Out of function definition";
}

inline bool assert_non_negative(std::string func_name, const mpz_class &n){
  if(n < 0)
    throw func_name + "(): Out of function definition";
}

mpz_class convert(const std::string &str){
  return mpz_class(str);
}

mpz_class mod(const mpz_class &left, const mpz_class &right){
  if(right == 0)
    throw "Math Error: Division by zero";
  mpz_class result = left % right;
  return (result < 0)? (result + right): result;
}

mpz_class power(const mpz_class &left, const mpz_class &right){
  if(right < 0 && left == -1)
    return -1 - 2*(-right%2 - 1);
  if(right < 0 && left != 1)
    return 0;
  if(right == 0 && left == 0)
    throw "Math Error: 0 to the power of 0 is undefined";
  mpz_class x = left;
  mpz_class n = right;
  mpz_class result(1);
  while(n){
    if(n % 2 == 1)
      result *= x;
    x *= x;
    n /= 2;
  }
  return result;
}

mpz_class abs(const std::vector<mpz_class> &argv){
  return abs(argv[0]);
}

mpz_class sgn(const std::vector<mpz_class> &argv){
  return sgn(argv[0]);
}

mpz_class sqrt(const std::vector<mpz_class> &argv){
  return sqrt(argv[0]);
}

mpz_class fac(const std::vector<mpz_class> &argv){
  assert_non_negative("fac", argv[0]);
  mpz_class result = 1;
  mpz_class n = argv[0];
  while(n){
    result *= n;
    n--;
  }
  return result;
}

mpz_class P(const std::vector<mpz_class> &argv){
  assert_positive("P", argv[0]);
  assert_positive("P", argv[1]);
  if(argv[0] < argv[1])
    throw "P(): Out of function definition";
  mpz_class n = argv[0];
  mpz_class r = argv[1];
  mpz_class result = 1;
  while(r--){
    result *= n;
    n--;
  }
  return result;
}

mpz_class C(const std::vector<mpz_class> &argv){
  assert_non_negative("C", argv[0]);
  assert_non_negative("C", argv[1]);
  if(argv[0] < argv[1])
    throw "C(): Out of function definition";
  mpz_class n = argv[0];
  mpz_class r = argv[1];

  if(n == 0)
    return 1;
  if(r == 0)
    return 1;

  if(r > n/2)
    r = n - r;
  mpz_class result = 1;
  mpz_class i;
  for(i=1; i<=r; i++)
    result = result*(n-i+1)/i;

  return result;
}

mpz_class max(const std::vector<mpz_class> &argv){
  return (argv[0] > argv[1])? argv[0]: argv[1];
}

mpz_class min(const std::vector<mpz_class> &argv){
  return (argv[0] < argv[1])? argv[0]: argv[1];
}

mpz_class gcd(const mpz_class &left, const mpz_class &right){
  assert_non_negative("gcd", left);
  assert_non_negative("gcd", right);
  if(right == 0)
    return left;
  return gcd(right, left % right);
}

mpz_class gcd(const std::vector<mpz_class> &argv){
  return gcd(argv[0], argv[1]);
}

mpz_class lcm(const std::vector<mpz_class> &argv){
  return (argv[0] * argv[1])/gcd(argv[0], argv[1]);
}

mpz_class rand(const std::vector<mpz_class> &argv){
  assert_positive("rand", argv[0]);
  return random.get_z_range(argv[0]);
}

void factor(mpz_class n){
  if(n < 0){
    std::cout << "factor: positive number required";
  }else if(n == 0){
    std::cout << "0";
  }else if(n == 1){
    std::cout << "1";
  }else{
    std::cout << "1";
    mpz_class L = sqrt(n)+1;
    for(mpz_class i=2; i<=L; i++){
      mpz_class p = 0;
      while(n%i == 0){
	n /= i;
	p++;
      }
      if(p > 0){
	if(p == 1)
	  std::cout << "*" << i;
	else
	  std::cout << "*" << i << "^" << p;
      }
    }
    if(n != 1)
      std::cout << "*" << n;
  }
  std::cout << '\n';
}

void init(){
  parser.operators["%"] = Expr::Operator<mpz_class>(Expr::R, 80, mod);
  parser.operators["^"] = Expr::Operator<mpz_class>(Expr::R, 85, power);
  parser.functions["abs"] = Expr::Function<mpz_class>(abs, 1);
  parser.functions["sgn"] = Expr::Function<mpz_class>(sgn, 1);
  parser.functions["sqrt"] = Expr::Function<mpz_class>(sqrt, 1);
  parser.functions["fac"] = Expr::Function<mpz_class>(fac, 1);
  parser.functions["P"] = Expr::Function<mpz_class>(P, 2);
  parser.functions["C"] = Expr::Function<mpz_class>(C, 2);
  parser.functions["max"] = Expr::Function<mpz_class>(max, 2);
  parser.functions["min"] = Expr::Function<mpz_class>(min, 2);
  parser.functions["gcd"] = Expr::Function<mpz_class>(gcd, 2);
  parser.functions["lcm"] = Expr::Function<mpz_class>(lcm, 2);
  random.seed(time(NULL));
  parser.functions["rand"] = Expr::Function<mpz_class>(rand, 1);
}

}

namespace Double {

Expr::Parser<double> parser(convert, "%^");

double convert(const std::string &str){
  return std::stod(str);
}

double power(const double &left, const double &right){
  if(left == 0 && right == 0)
    throw "Math Error: 0 to the power of 0 is undefined";
  return pow(left, right);
}

double mod(const double &left, const double &right){
  if(right == 0)
    throw "Math Error: Division by zero";
  return fmod(left, right);
}

double abs(const std::vector<double> &argv){
  return fabs((double)argv[0]);
}

double sgn(const std::vector<double> &argv){
  if(argv[0] > 0)
    return 1;
  if(argv[0] < 0)
    return -1;
  return 0;
}

double sqrt_(const std::vector<double> &argv){
  return sqrt(argv[0]);
}

double cbrt_(const std::vector<double> &argv){
  return cbrt(argv[0]);
}

double floor_(const std::vector<double> &argv){
  return floor(argv[0]);
}

double ceil_(const std::vector<double> &argv){
  return ceil(argv[0]);
}

double sin_(const std::vector<double> &argv){
  return sin(argv[0]);
}

double cos_(const std::vector<double> &argv){
  return cos(argv[0]);
}

double tan_(const std::vector<double> &argv){
  return tan(argv[0]);
}

double asin_(const std::vector<double> &argv){
  return asin(argv[0]);
}

double acos_(const std::vector<double> &argv){
  return acos(argv[0]);
}

double atan_(const std::vector<double> &argv){
  return atan(argv[0]);
}

double exp_(const std::vector<double> &argv){
  return exp(argv[0]);
}

double erf_(const std::vector<double> &argv){
  return erf(argv[0]);
}

double log_(const std::vector<double> &argv){
  return log(argv[0]);
}

double log2_(const std::vector<double> &argv){
  return log2(argv[0]);
}

double log10_(const std::vector<double> &argv){
  return log10(argv[0]);
}

double rand_(const std::vector<double> &argv){
  return (double)rand()/RAND_MAX;
}

void init(){
  parser.operators["%"] = Expr::Operator<double>(Expr::R, 80, mod);
  parser.operators["^"] = Expr::Operator<double>(Expr::R, 85, power);
  parser.functions["abs"] = Expr::Function<double>(abs, 1);
  parser.functions["sgn"] = Expr::Function<double>(sgn, 1);
  parser.functions["sqrt"] = Expr::Function<double>(sqrt_, 1);
  parser.functions["cbrt"] = Expr::Function<double>(cbrt_, 1);
  parser.functions["floor"] = Expr::Function<double>(floor_, 1);
  parser.functions["ceil"] = Expr::Function<double>(ceil_, 1);
  parser.functions["sin"] = Expr::Function<double>(sin_, 1);
  parser.functions["cos"] = Expr::Function<double>(cos_, 1);
  parser.functions["tan"] = Expr::Function<double>(tan_, 1);
  parser.functions["asin"] = Expr::Function<double>(asin_, 1);
  parser.functions["acos"] = Expr::Function<double>(acos_, 1);
  parser.functions["atan"] = Expr::Function<double>(atan_, 1);
  parser.functions["exp"] = Expr::Function<double>(exp_, 1);
  parser.functions["erf"] = Expr::Function<double>(erf_, 1);
  parser.functions["log"] = Expr::Function<double>(log_, 1);
  parser.functions["log2"] = Expr::Function<double>(log2_, 1);
  parser.functions["log10"] = Expr::Function<double>(log10_, 1);
  parser.functions["rand"] = Expr::Function<double>(rand_, 0);
  parser.constants["PI"] = 3.141592653589793;
  parser.scientific_notation_enabled = true;
  parser.decimal_point_enabled = true;
  srand(time(NULL));
}

}

}
<commit_msg>Add second-order determinant and fix a bug<commit_after>#include <iostream>
#include <string>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include "parsers.hpp"

namespace Parsers {

namespace Int {

Expr::Parser<mpz_class> parser(convert, "%^");

gmp_randclass random(gmp_randinit_default);

inline bool assert_positive(std::string func_name, const mpz_class &n){
  if(n <= 0)
    throw func_name + "(): Out of function definition";
}

inline bool assert_non_negative(std::string func_name, const mpz_class &n){
  if(n < 0)
    throw func_name + "(): Out of function definition";
}

mpz_class convert(const std::string &str){
  return mpz_class(str);
}

mpz_class mod(const mpz_class &left, const mpz_class &right){
  if(right == 0)
    throw "Math Error: Division by zero";
  mpz_class result = left % right;
  return (result < 0)? (result + right): result;
}

mpz_class power(const mpz_class &left, const mpz_class &right){
  if(right < 0 && left == -1)
    return -1 - 2*(-right%2 - 1);
  if(right < 0 && left != 1)
    return 0;
  if(right == 0 && left == 0)
    throw "Math Error: 0 to the power of 0 is undefined";
  mpz_class x = left;
  mpz_class n = right;
  mpz_class result(1);
  while(n){
    if(n % 2 == 1)
      result *= x;
    x *= x;
    n /= 2;
  }
  return result;
}

mpz_class abs(const std::vector<mpz_class> &argv){
  return abs(argv[0]);
}

mpz_class sgn(const std::vector<mpz_class> &argv){
  return sgn(argv[0]);
}

mpz_class sqrt(const std::vector<mpz_class> &argv){
  return sqrt(argv[0]);
}

mpz_class fac(const std::vector<mpz_class> &argv){
  assert_non_negative("fac", argv[0]);
  mpz_class result = 1;
  mpz_class n = argv[0];
  while(n){
    result *= n;
    n--;
  }
  return result;
}

mpz_class P(const std::vector<mpz_class> &argv){
  assert_positive("P", argv[0]);
  assert_positive("P", argv[1]);
  if(argv[0] < argv[1])
    throw "P(): Out of function definition";
  mpz_class n = argv[0];
  mpz_class r = argv[1];
  mpz_class result = 1;
  while(r--){
    result *= n;
    n--;
  }
  return result;
}

mpz_class C(const std::vector<mpz_class> &argv){
  assert_non_negative("C", argv[0]);
  assert_non_negative("C", argv[1]);
  if(argv[0] < argv[1])
    throw "C(): Out of function definition";
  mpz_class n = argv[0];
  mpz_class r = argv[1];

  if(n == 0)
    return 1;
  if(r == 0)
    return 1;

  if(r > n/2)
    r = n - r;
  mpz_class result = 1;
  mpz_class i;
  for(i=1; i<=r; i++)
    result = result*(n-i+1)/i;

  return result;
}

mpz_class max(const std::vector<mpz_class> &argv){
  return (argv[0] > argv[1])? argv[0]: argv[1];
}

mpz_class min(const std::vector<mpz_class> &argv){
  return (argv[0] < argv[1])? argv[0]: argv[1];
}

mpz_class gcd(const mpz_class &left, const mpz_class &right){
  assert_non_negative("gcd", left);
  assert_non_negative("gcd", right);
  if(right == 0)
    return left;
  return gcd(right, left % right);
}

mpz_class gcd(const std::vector<mpz_class> &argv){
  return gcd(argv[0], argv[1]);
}

mpz_class lcm(const std::vector<mpz_class> &argv){
  return (argv[0] * argv[1])/gcd(argv[0], argv[1]);
}

mpz_class rand(const std::vector<mpz_class> &argv){
  assert_positive("rand", argv[0]);
  return random.get_z_range(argv[0]);
}

mpz_class det2(const std::vector<mpz_class> &argv){
  return (argv[0]*argv[3] - argv[1]*argv[2]);
}

void factor(mpz_class n){
  if(n < 0){
    std::cerr << "factor: positive number required";
  }else if(n == 0){
    std::cout << "0";
  }else if(n == 1){
    std::cout << "1";
  }else{
    std::cout << "1";
    mpz_class L = sqrt(n)+1;
    for(mpz_class i=2; i<=L; i++){
      mpz_class p = 0;
      while(n%i == 0){
	n /= i;
	p++;
      }
      if(p > 0){
	if(p == 1)
	  std::cout << "*" << i;
	else
	  std::cout << "*" << i << "^" << p;
      }
    }
    if(n != 1)
      std::cout << "*" << n;
  }
  std::cout << '\n';
}

void init(){
  parser.operators["%"] = Expr::Operator<mpz_class>(Expr::R, 80, mod);
  parser.operators["^"] = Expr::Operator<mpz_class>(Expr::R, 85, power);
  parser.functions["abs"] = Expr::Function<mpz_class>(abs, 1);
  parser.functions["sgn"] = Expr::Function<mpz_class>(sgn, 1);
  parser.functions["sqrt"] = Expr::Function<mpz_class>(sqrt, 1);
  parser.functions["fac"] = Expr::Function<mpz_class>(fac, 1);
  parser.functions["P"] = Expr::Function<mpz_class>(P, 2);
  parser.functions["C"] = Expr::Function<mpz_class>(C, 2);
  parser.functions["max"] = Expr::Function<mpz_class>(max, 2);
  parser.functions["min"] = Expr::Function<mpz_class>(min, 2);
  parser.functions["gcd"] = Expr::Function<mpz_class>(gcd, 2);
  parser.functions["lcm"] = Expr::Function<mpz_class>(lcm, 2);
  random.seed(time(NULL));
  parser.functions["rand"] = Expr::Function<mpz_class>(rand, 1);
  parser.functions["det2"] = Expr::Function<mpz_class>(det2, 4);
}

}

namespace Double {

Expr::Parser<double> parser(convert, "%^");

double convert(const std::string &str){
  return std::stod(str);
}

double power(const double &left, const double &right){
  if(left == 0 && right == 0)
    throw "Math Error: 0 to the power of 0 is undefined";
  return pow(left, right);
}

double mod(const double &left, const double &right){
  if(right == 0)
    throw "Math Error: Division by zero";
  return fmod(left, right);
}

double abs(const std::vector<double> &argv){
  return fabs((double)argv[0]);
}

double sgn(const std::vector<double> &argv){
  if(argv[0] > 0)
    return 1;
  if(argv[0] < 0)
    return -1;
  return 0;
}

double sqrt_(const std::vector<double> &argv){
  return sqrt(argv[0]);
}

double cbrt_(const std::vector<double> &argv){
  return cbrt(argv[0]);
}

double floor_(const std::vector<double> &argv){
  return floor(argv[0]);
}

double ceil_(const std::vector<double> &argv){
  return ceil(argv[0]);
}

double sin_(const std::vector<double> &argv){
  return sin(argv[0]);
}

double cos_(const std::vector<double> &argv){
  return cos(argv[0]);
}

double tan_(const std::vector<double> &argv){
  return tan(argv[0]);
}

double asin_(const std::vector<double> &argv){
  return asin(argv[0]);
}

double acos_(const std::vector<double> &argv){
  return acos(argv[0]);
}

double atan_(const std::vector<double> &argv){
  return atan(argv[0]);
}

double exp_(const std::vector<double> &argv){
  return exp(argv[0]);
}

double erf_(const std::vector<double> &argv){
  return erf(argv[0]);
}

double log_(const std::vector<double> &argv){
  return log(argv[0]);
}

double log2_(const std::vector<double> &argv){
  return log2(argv[0]);
}

double log10_(const std::vector<double> &argv){
  return log10(argv[0]);
}

double rand_(const std::vector<double> &argv){
  return (double)rand()/RAND_MAX;
}

double det2(const std::vector<double> &argv){
  return (argv[0]*argv[3] - argv[1]*argv[2]);
}

void init(){
  parser.operators["%"] = Expr::Operator<double>(Expr::R, 80, mod);
  parser.operators["^"] = Expr::Operator<double>(Expr::R, 85, power);
  parser.functions["abs"] = Expr::Function<double>(abs, 1);
  parser.functions["sgn"] = Expr::Function<double>(sgn, 1);
  parser.functions["sqrt"] = Expr::Function<double>(sqrt_, 1);
  parser.functions["cbrt"] = Expr::Function<double>(cbrt_, 1);
  parser.functions["floor"] = Expr::Function<double>(floor_, 1);
  parser.functions["ceil"] = Expr::Function<double>(ceil_, 1);
  parser.functions["sin"] = Expr::Function<double>(sin_, 1);
  parser.functions["cos"] = Expr::Function<double>(cos_, 1);
  parser.functions["tan"] = Expr::Function<double>(tan_, 1);
  parser.functions["asin"] = Expr::Function<double>(asin_, 1);
  parser.functions["acos"] = Expr::Function<double>(acos_, 1);
  parser.functions["atan"] = Expr::Function<double>(atan_, 1);
  parser.functions["exp"] = Expr::Function<double>(exp_, 1);
  parser.functions["erf"] = Expr::Function<double>(erf_, 1);
  parser.functions["log"] = Expr::Function<double>(log_, 1);
  parser.functions["log2"] = Expr::Function<double>(log2_, 1);
  parser.functions["log10"] = Expr::Function<double>(log10_, 1);
  parser.functions["rand"] = Expr::Function<double>(rand_, 0);
  parser.functions["det2"] = Expr::Function<double>(det2, 4);
  parser.constants["PI"] = 3.141592653589793;
  parser.scientific_notation_enabled = true;
  parser.decimal_point_enabled = true;
  srand(time(NULL));
}

}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2009 Bjorn Fahller <bjorn@fahller.se>
 * All rights reserved

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <gmock/gmock.h>
#include <crpcut.hpp>
#include <cstdio>

extern "C"
{
#include <stdarg.h>
#include <unistd.h>
}

namespace testing
{
  void InitGoogleTest(int*, char **) {}
  void InitGoogleTest(int*, wchar_t **) {}

  namespace internal
  {
    Mutex g_linked_ptr_mutex;

    const char * String::CloneCString(const char *p)
    {
      if (!p) return 0;
      size_t len = std::strlen(p);
      char *rv = new char[len + 1];
      std::strcpy(rv, p);
      return rv;
    }

    const String &String::operator=(const char * p)
    {
      if (p != c_str_)
        {
          const char *pc = CloneCString(p);
          delete[] c_str_;
          c_str_ = pc;
        }
      return *this;
    }

    String String::Format(const char *format, ...)
    {
      va_list args;
      va_start(args, format);

      size_t len = std::vsnprintf("", 0, format, args);
      char *array = static_cast<char*>(::alloca(len + 1));
      std::vsnprintf(array, len + 1, format, args);
      va_end(args);
      return String(array);
    }

    String StrStreamToString(StrStream *s)
    {
      const std::string &str = s->str();
      const char *const begin = str.c_str();
      const char *const end = begin + str.length();

      std::ostringstream os;
      for (const char *p = begin; p != end; ++p)
        {
          if (*p == 0)
            {
              os << "\\0";
            }
          else
            {
              os << *p;
            }
        }
      return os.str();
    }

    AssertHelper::AssertHelper(TestPartResultType type, const char* file,
                               int line, const char* message)
      : type_(type),
        file_(file),
        line_(line),
        message_(message)
    {
    }

    void AssertHelper::operator=(const Message &msg) const
    {
      if (type_ == TPRT_SUCCESS) return;

      std::ostringstream os;
      if (file_)
        {
          os << file_ << ':' << line_ << '\n';
        }
      os << message_ << msg;
      crpcut::comm::report(crpcut::comm::exit_fail, os);
    }

    String GetCurrentOsStackTraceExceptTop(UnitTest *, int)
    {
      return "";
    }
    bool String::CStringEquals(const char *lh, const char *rh)
    {
      return lh == rh || (std::strcmp(lh, rh) == 0);
    }

    String String::ShowWideCString(const wchar_t * wstr)
    {
      if (!wstr) return "(null)";
      std::ostringstream os;
      for (;*wstr; ++wstr)
        {
          os << static_cast<char>(*wstr & 0xff);
        }
      return os.str();
    }

  }

  UnitTest* UnitTest::GetInstance() { static UnitTest obj; return &obj; }
  UnitTest::UnitTest() {}
  UnitTest::~UnitTest() { }
}
<commit_msg>Mask wchar_t to ASCII<commit_after>/*
 * Copyright 2009 Bjorn Fahller <bjorn@fahller.se>
 * All rights reserved

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <gmock/gmock.h>
#include <crpcut.hpp>
#include <cstdio>

extern "C"
{
#include <stdarg.h>
#include <unistd.h>
}

namespace testing
{
  void InitGoogleTest(int*, char **) {}
  void InitGoogleTest(int*, wchar_t **) {}

  namespace internal
  {
    Mutex g_linked_ptr_mutex;

    const char * String::CloneCString(const char *p)
    {
      if (!p) return 0;
      size_t len = std::strlen(p);
      char *rv = new char[len + 1];
      std::strcpy(rv, p);
      return rv;
    }

    const String &String::operator=(const char * p)
    {
      if (p != c_str_)
        {
          const char *pc = CloneCString(p);
          delete[] c_str_;
          c_str_ = pc;
        }
      return *this;
    }

    String String::Format(const char *format, ...)
    {
      va_list args;
      va_start(args, format);

      size_t len = std::vsnprintf("", 0, format, args);
      char *array = static_cast<char*>(::alloca(len + 1));
      std::vsnprintf(array, len + 1, format, args);
      va_end(args);
      return String(array);
    }

    String StrStreamToString(StrStream *s)
    {
      const std::string &str = s->str();
      const char *const begin = str.c_str();
      const char *const end = begin + str.length();

      std::ostringstream os;
      for (const char *p = begin; p != end; ++p)
        {
          if (*p == 0)
            {
              os << "\\0";
            }
          else
            {
              os << *p;
            }
        }
      return os.str();
    }

    AssertHelper::AssertHelper(TestPartResultType type, const char* file,
                               int line, const char* message)
      : type_(type),
        file_(file),
        line_(line),
        message_(message)
    {
    }

    void AssertHelper::operator=(const Message &msg) const
    {
      if (type_ == TPRT_SUCCESS) return;

      std::ostringstream os;
      if (file_)
        {
          os << file_ << ':' << line_ << '\n';
        }
      os << message_ << msg;
      crpcut::comm::report(crpcut::comm::exit_fail, os);
    }

    String GetCurrentOsStackTraceExceptTop(UnitTest *, int)
    {
      return "";
    }
    bool String::CStringEquals(const char *lh, const char *rh)
    {
      return lh == rh || (std::strcmp(lh, rh) == 0);
    }

    String String::ShowWideCString(const wchar_t * wstr)
    {
      if (!wstr) return "(null)";
      std::ostringstream os;
      for (;*wstr; ++wstr)
        {
          os << static_cast<char>(*wstr & 0x7f);
        }
      return os.str();
    }

  }

  UnitTest* UnitTest::GetInstance() { static UnitTest obj; return &obj; }
  UnitTest::UnitTest() {}
  UnitTest::~UnitTest() { }
}
<|endoftext|>


<commit_before>#include "groups.h"

#include <iostream>
#include <string>
#include <vector>
#include <cassert>

namespace redsea {

std::string lcd_char(int code) {
  assert (code >= 32);
  const std::vector<std::string> char_map ({
      " ","!","\"","#","¤","%","&","'","(",")","*","+",",","-",".","/",
      "0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?",
      "@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
      "P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","―","_",
      "‖","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
      "p","q","r","s","t","u","v","w","x","y","z","{","|","}","¯"," ",
      "á","à","é","è","í","ì","ó","ò","ú","ù","Ñ","Ç","Ş","β","¡","Ĳ",
      "â","ä","ê","ë","î","ï","ô","ö","û","ü","ñ","ç","ş","ǧ","ı","ĳ",
      "ª","α","©","‰","Ǧ","ě","ň","ő","π","€","£","$","←","↑","→","↓",
      "º","¹","²","³","±","İ","ń","ű","µ","¿","÷","°","¼","½","¾","§",
      "Á","À","É","È","Í","Ì","Ó","Ò","Ú","Ù","Ř","Č","Š","Ž","Ð","Ŀ",
      "Â","Ä","Ê","Ë","Î","Ï","Ô","Ö","Û","Ü","ř","č","š","ž","đ","ŀ",
      "Ã","Å","Æ","Œ","ŷ","Ý","Õ","Ø","Þ","Ŋ","Ŕ","Ć","Ś","Ź","Ŧ","ð",
      "ã","å","æ","œ","ŵ","ý","õ","ø","þ","ŋ","ŕ","ć","ś","ź","ŧ"," "});
  return char_map[code - 32];
}

// extract len bits from bitstring, starting at starting_at from the right
uint16_t bits (uint16_t bitstring, int starting_at, int len) {
  return ((bitstring >> starting_at) & ((1<<len) - 1));
}

RDSString::RDSString(int len) : chars_(len), is_char_sequential_(len), prev_pos_(-1) {
  last_complete_string_ = getString();
}

void RDSString::setAt(int pos, int chr) {
  if (pos < 0 || pos >= (int)chars_.size())
    return;

  chars_[pos] = chr;

  if (pos != prev_pos_ + 1) {
    for (size_t i=0; i<is_char_sequential_.size(); i++)
      is_char_sequential_[i] = false;
  }

  is_char_sequential_[pos] = true;

  if (isComplete())
    last_complete_string_ = getString();

  prev_pos_ = pos;

}

size_t RDSString::lengthReceived() const {

  size_t result = 0;
  for (size_t i=0; i<is_char_sequential_.size(); i++) {
    if (!is_char_sequential_[i])
      break;
    result = i+1;
  }

  return result;
}

size_t RDSString::lengthExpected() const {

  size_t result = chars_.size();

  for (size_t i=0; i<chars_.size(); i++) {
    if (chars_[i] == 0x0D) {
      result = i;
      break;
    }
  }

  return result;
}

std::string RDSString::getString() const {
  std::string result;
  size_t len = lengthExpected();
  for (size_t i=0; i<len; i++) {
    result += (is_char_sequential_[i] ? lcd_char(chars_[i]) : " ");
  }

  return result;

}

std::string RDSString::getLastCompleteString() const {
  return last_complete_string_;
}

bool RDSString::isComplete() const {
  return lengthReceived() >= lengthExpected();
}

void RDSString::clear() {
  for (size_t i=0; i<chars_.size(); i++) {
    is_char_sequential_[i] = false;
  }
  last_complete_string_ = getString();
}

Station::Station() : Station(0x0000) {

}

Station::Station(uint16_t _pi) : pi_(_pi), ps_(8), rt_(64) {

}

void Station::add(Group group) {

  is_tp_   = bits(group.block2, 10, 1);
  pty_     = bits(group.block2,  5, 5);

  printf(":%d%s\n",group.type, group.type_ab == TYPE_A ? "A" : "B");

  if      (group.type == 0) { decodeType0(group); }
  else if (group.type == 1) { decodeType1(group); }
  else if (group.type == 2) { decodeType2(group); }
  else if (group.type == 4) { decodeType4(group); }
}

void Station::addAltFreq(uint8_t af_code) {
  if (af_code >= 1 && af_code <= 204) {
    alt_freqs_.push_back(87.5 + af_code / 10.0);
  } else if (af_code == 205) {
    // filler
  } else if (af_code == 224) {
    // no AF exists
  } else if (af_code >= 225 && af_code <= 249) {
    num_alt_freqs_ = af_code - 224;
  } else if (af_code == 250) {
    // AM/LF freq follows
  }
}

bool Station::hasPS() const {
  return ps_.isComplete();
}

std::string Station::getPS() const {
  return ps_.getLastCompleteString();
}

std::string Station::getRT() const {
  return rt_.getLastCompleteString();
}

uint16_t Station::getPI() const {
  return pi_;
}

std::string Station::getCountryCode() const {

}

void Station::updatePS(int pos, std::vector<int> chars) {

  for (int i=pos; i<pos+(int)chars.size(); i++)
    ps_.setAt(i, chars[i-pos]);

}

void Station::updateRadioText(int pos, std::vector<int> chars) {

  for (int i=pos; i<pos+(int)chars.size(); i++)
    rt_.setAt(i, chars[i-pos]);

}

void Station::decodeType0 (Group group) {

  // not implemented: Decoder Identification

  is_ta_    = bits(group.block2, 4, 1);
  is_music_ = bits(group.block2, 3, 1);

  if (group.num_blocks < 3)
    return;

  if (group.type_ab == TYPE_A) {
    for (int i=0; i<2; i++) {
      addAltFreq(bits(group.block3, 8-i*8, 8));
    }
  }

  if (group.num_blocks < 4)
    return;

  updatePS(bits(group.block2, 0, 2) * 2,
      { bits(group.block4, 8, 8), bits(group.block4, 0, 8) });

}

void Station::decodeType1 (Group group) {

  if (group.num_blocks < 4)
    return;

  pin_ = group.block4;

  if (group.type_ab == TYPE_A) {
    pager_tng_ = bits(group.block2, 2, 3);
    if (pager_tng_ != 0) {
      pager_interval_ = bits(group.block2, 0, 2);
    }
    linkage_la_ = bits(group.block3, 15, 1);

    int slc_variant = bits(group.block3, 12, 3);

    if (slc_variant == 0) {
      if (pager_tng_ != 0) {
        pager_opc_ = bits(group.block3, 8, 4);
      }

      // No PIN, section M.3.2.4.3
      if (group.num_blocks == 4 && (group.block4 >> 11) == 0) {
        int subtype = bits(group.block4, 10, 1);
        if (subtype == 0) {
          if (pager_tng_ != 0) {
            pager_pac_ = bits(group.block4, 4, 6);
            pager_opc_ = bits(group.block4, 0, 4);
          }
        } else if (subtype == 1) {
          if (pager_tng_ != 0) {
            int b = bits(group.block4, 8, 2);
            if (b == 0) {
              pager_ecc_ = bits(group.block4, 0, 6);
            } else if (b == 3) {
              pager_ccf_ = bits(group.block4, 0, 4);
            }
          }
        }
      }

      ecc_ = bits(group.block3,  0, 8);
      cc_  = bits(group.block1, 12, 4);

      has_country_ = true;

    } else if (slc_variant == 1) {
      tmc_id_ = bits(group.block3, 0, 12);

    } else if (slc_variant == 2) {
      if (pager_tng_ != 0) {
        pager_pac_ = bits(group.block3, 0, 6);
        pager_opc_ = bits(group.block3, 8, 4);
      }

      // No PIN, section M.3.2.4.3
      if (group.num_blocks == 4 && (group.block4 >> 11) == 0) {
        int subtype = bits(group.block4, 10, 1);
        if (subtype == 0) {
          if (pager_tng_ != 0) {
            pager_pac_ = bits(group.block4, 4, 6);
            pager_opc_ = bits(group.block4, 0, 4);
          }
        } else if (subtype == 1) {
          if (pager_tng_ != 0) {
            int b = bits(group.block4, 8, 2);
            if (b == 0) {
              pager_ecc_ = bits(group.block4, 0, 6);
            } else if (b == 3) {
              pager_ccf_ = bits(group.block4, 0, 4);
            }
          }
        }
      }

    } else if (slc_variant == 3) {
      lang_ = bits(group.block3, 0, 8);

    } else if (slc_variant == 6) {
      // TODO:
      // broadcaster data

    } else if (slc_variant == 7) {
      ews_channel_ = bits(group.block3, 0, 12);
    }

  }

}

void Station::decodeType2 (Group group) {

  if (group.num_blocks < 3)
    return;

  int rt_position = bits(group.block2, 0, 4) * (group.type_ab == TYPE_A ? 4 : 2);
  int prev_textAB = rt_ab_;
  rt_ab_          = bits(group.block2, 4, 1);

  if (prev_textAB != rt_ab_)
    rt_.clear();

  std::string chars;

  if (group.type_ab == TYPE_A) {
    updateRadioText(rt_position, {bits(group.block3, 8, 8), bits(group.block3, 0, 8)});
  }

  if (group.num_blocks == 4) {
    updateRadioText(rt_position+2, {bits(group.block4, 8, 8), bits(group.block4, 0, 8)});
  }

}

void Station::decodeType4 (Group group) {

  if (group.num_blocks < 3 || group.type_ab == TYPE_B)
    return;

  double mjd = (bits(group.block2, 0, 2) << 15) + bits(group.block3, 1, 15);
  double lto;

  if (group.num_blocks == 4) {
    lto = (bits(group.block4, 5, 1) ? -1 : 1) * bits(group.block4, 0, 5) / 2.0;
    mjd = int(mjd + lto / 24.0);
  }

  int yr = int((mjd - 15078.2) / 365.25);
  int mo = int((mjd - 14956.1 - int(yr * 365.25)) / 30.6001);
  int dy = mjd - 14956 - int(yr * 365.25) - int(mo * 30.6001);
  if (mo == 14 || mo == 15) {
    yr += 1;
    mo -= 12;
  }
  yr += 1900;
  mo -= 1;

  if (group.num_blocks == 4) {
    int ltom = (lto - int(lto)) * 60;

    int hr = int((bits(group.block3, 0, 1) << 4) +
        bits(group.block4, 12, 14) + lto) % 24;
    int mn = bits(group.block4, 6, 6) + ltom;

    char buff[100];
    snprintf(buff, sizeof(buff),
        "%04d-%02d-%02dT%02d:%02d:00%+03d:%02d\n",yr,mo,dy,hr,mn,int(lto),ltom);
    clock_time_ = buff;
    std::cout<<"clock_time:"<<clock_time_<<"\n";

  }
}

} // namespace redsea
<commit_msg>escape "<commit_after>#include "groups.h"

#include <iostream>
#include <string>
#include <vector>
#include <cassert>

namespace redsea {

std::string getLCDchar(int code) {
  assert (code >= 32);
  const std::vector<std::string> char_map ({
      " ","!","\\\"","#","¤","%","&","'","(",")","*","+",",","-",".","/",
      "0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?",
      "@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
      "P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","―","_",
      "‖","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
      "p","q","r","s","t","u","v","w","x","y","z","{","|","}","¯"," ",
      "á","à","é","è","í","ì","ó","ò","ú","ù","Ñ","Ç","Ş","β","¡","Ĳ",
      "â","ä","ê","ë","î","ï","ô","ö","û","ü","ñ","ç","ş","ǧ","ı","ĳ",
      "ª","α","©","‰","Ǧ","ě","ň","ő","π","€","£","$","←","↑","→","↓",
      "º","¹","²","³","±","İ","ń","ű","µ","¿","÷","°","¼","½","¾","§",
      "Á","À","É","È","Í","Ì","Ó","Ò","Ú","Ù","Ř","Č","Š","Ž","Ð","Ŀ",
      "Â","Ä","Ê","Ë","Î","Ï","Ô","Ö","Û","Ü","ř","č","š","ž","đ","ŀ",
      "Ã","Å","Æ","Œ","ŷ","Ý","Õ","Ø","Þ","Ŋ","Ŕ","Ć","Ś","Ź","Ŧ","ð",
      "ã","å","æ","œ","ŵ","ý","õ","ø","þ","ŋ","ŕ","ć","ś","ź","ŧ"," "});
  return char_map[code - 32];
}

// extract len bits from bitstring, starting at starting_at from the right
uint16_t bits (uint16_t bitstring, int starting_at, int len) {
  return ((bitstring >> starting_at) & ((1<<len) - 1));
}

RDSString::RDSString(int len) : chars_(len), is_char_sequential_(len), prev_pos_(-1) {
  last_complete_string_ = getString();
}

void RDSString::setAt(int pos, int chr) {
  if (pos < 0 || pos >= (int)chars_.size())
    return;

  chars_[pos] = chr;

  if (pos != prev_pos_ + 1) {
    for (size_t i=0; i<is_char_sequential_.size(); i++)
      is_char_sequential_[i] = false;
  }

  is_char_sequential_[pos] = true;

  if (isComplete())
    last_complete_string_ = getString();

  prev_pos_ = pos;

}

size_t RDSString::lengthReceived() const {

  size_t result = 0;
  for (size_t i=0; i<is_char_sequential_.size(); i++) {
    if (!is_char_sequential_[i])
      break;
    result = i+1;
  }

  return result;
}

size_t RDSString::lengthExpected() const {

  size_t result = chars_.size();

  for (size_t i=0; i<chars_.size(); i++) {
    if (chars_[i] == 0x0D) {
      result = i;
      break;
    }
  }

  return result;
}

std::string RDSString::getString() const {
  std::string result;
  size_t len = lengthExpected();
  for (size_t i=0; i<len; i++) {
    result += (is_char_sequential_[i] ? lcd_char(chars_[i]) : " ");
  }

  return result;

}

std::string RDSString::getLastCompleteString() const {
  return last_complete_string_;
}

bool RDSString::isComplete() const {
  return lengthReceived() >= lengthExpected();
}

void RDSString::clear() {
  for (size_t i=0; i<chars_.size(); i++) {
    is_char_sequential_[i] = false;
  }
  last_complete_string_ = getString();
}

Station::Station() : Station(0x0000) {

}

Station::Station(uint16_t _pi) : pi_(_pi), ps_(8), rt_(64) {

}

void Station::add(Group group) {

  is_tp_   = bits(group.block2, 10, 1);
  pty_     = bits(group.block2,  5, 5);

  printf(":%d%s\n",group.type, group.type_ab == TYPE_A ? "A" : "B");

  if      (group.type == 0) { decodeType0(group); }
  else if (group.type == 1) { decodeType1(group); }
  else if (group.type == 2) { decodeType2(group); }
  else if (group.type == 4) { decodeType4(group); }
}

void Station::addAltFreq(uint8_t af_code) {
  if (af_code >= 1 && af_code <= 204) {
    alt_freqs_.push_back(87.5 + af_code / 10.0);
  } else if (af_code == 205) {
    // filler
  } else if (af_code == 224) {
    // no AF exists
  } else if (af_code >= 225 && af_code <= 249) {
    num_alt_freqs_ = af_code - 224;
  } else if (af_code == 250) {
    // AM/LF freq follows
  }
}

bool Station::hasPS() const {
  return ps_.isComplete();
}

std::string Station::getPS() const {
  return ps_.getLastCompleteString();
}

std::string Station::getRT() const {
  return rt_.getLastCompleteString();
}

uint16_t Station::getPI() const {
  return pi_;
}

std::string Station::getCountryCode() const {

}

void Station::updatePS(int pos, std::vector<int> chars) {

  for (int i=pos; i<pos+(int)chars.size(); i++)
    ps_.setAt(i, chars[i-pos]);

}

void Station::updateRadioText(int pos, std::vector<int> chars) {

  for (int i=pos; i<pos+(int)chars.size(); i++)
    rt_.setAt(i, chars[i-pos]);

}

void Station::decodeType0 (Group group) {

  // not implemented: Decoder Identification

  is_ta_    = bits(group.block2, 4, 1);
  is_music_ = bits(group.block2, 3, 1);

  if (group.num_blocks < 3)
    return;

  if (group.type_ab == TYPE_A) {
    for (int i=0; i<2; i++) {
      addAltFreq(bits(group.block3, 8-i*8, 8));
    }
  }

  if (group.num_blocks < 4)
    return;

  updatePS(bits(group.block2, 0, 2) * 2,
      { bits(group.block4, 8, 8), bits(group.block4, 0, 8) });

}

void Station::decodeType1 (Group group) {

  if (group.num_blocks < 4)
    return;

  pin_ = group.block4;

  if (group.type_ab == TYPE_A) {
    pager_tng_ = bits(group.block2, 2, 3);
    if (pager_tng_ != 0) {
      pager_interval_ = bits(group.block2, 0, 2);
    }
    linkage_la_ = bits(group.block3, 15, 1);

    int slc_variant = bits(group.block3, 12, 3);

    if (slc_variant == 0) {
      if (pager_tng_ != 0) {
        pager_opc_ = bits(group.block3, 8, 4);
      }

      // No PIN, section M.3.2.4.3
      if (group.num_blocks == 4 && (group.block4 >> 11) == 0) {
        int subtype = bits(group.block4, 10, 1);
        if (subtype == 0) {
          if (pager_tng_ != 0) {
            pager_pac_ = bits(group.block4, 4, 6);
            pager_opc_ = bits(group.block4, 0, 4);
          }
        } else if (subtype == 1) {
          if (pager_tng_ != 0) {
            int b = bits(group.block4, 8, 2);
            if (b == 0) {
              pager_ecc_ = bits(group.block4, 0, 6);
            } else if (b == 3) {
              pager_ccf_ = bits(group.block4, 0, 4);
            }
          }
        }
      }

      ecc_ = bits(group.block3,  0, 8);
      cc_  = bits(group.block1, 12, 4);

      has_country_ = true;

    } else if (slc_variant == 1) {
      tmc_id_ = bits(group.block3, 0, 12);

    } else if (slc_variant == 2) {
      if (pager_tng_ != 0) {
        pager_pac_ = bits(group.block3, 0, 6);
        pager_opc_ = bits(group.block3, 8, 4);
      }

      // No PIN, section M.3.2.4.3
      if (group.num_blocks == 4 && (group.block4 >> 11) == 0) {
        int subtype = bits(group.block4, 10, 1);
        if (subtype == 0) {
          if (pager_tng_ != 0) {
            pager_pac_ = bits(group.block4, 4, 6);
            pager_opc_ = bits(group.block4, 0, 4);
          }
        } else if (subtype == 1) {
          if (pager_tng_ != 0) {
            int b = bits(group.block4, 8, 2);
            if (b == 0) {
              pager_ecc_ = bits(group.block4, 0, 6);
            } else if (b == 3) {
              pager_ccf_ = bits(group.block4, 0, 4);
            }
          }
        }
      }

    } else if (slc_variant == 3) {
      lang_ = bits(group.block3, 0, 8);

    } else if (slc_variant == 6) {
      // TODO:
      // broadcaster data

    } else if (slc_variant == 7) {
      ews_channel_ = bits(group.block3, 0, 12);
    }

  }

}

void Station::decodeType2 (Group group) {

  if (group.num_blocks < 3)
    return;

  int rt_position = bits(group.block2, 0, 4) * (group.type_ab == TYPE_A ? 4 : 2);
  int prev_textAB = rt_ab_;
  rt_ab_          = bits(group.block2, 4, 1);

  if (prev_textAB != rt_ab_)
    rt_.clear();

  std::string chars;

  if (group.type_ab == TYPE_A) {
    updateRadioText(rt_position, {bits(group.block3, 8, 8), bits(group.block3, 0, 8)});
  }

  if (group.num_blocks == 4) {
    updateRadioText(rt_position+2, {bits(group.block4, 8, 8), bits(group.block4, 0, 8)});
  }

}

void Station::decodeType4 (Group group) {

  if (group.num_blocks < 3 || group.type_ab == TYPE_B)
    return;

  double mjd = (bits(group.block2, 0, 2) << 15) + bits(group.block3, 1, 15);
  double lto;

  if (group.num_blocks == 4) {
    lto = (bits(group.block4, 5, 1) ? -1 : 1) * bits(group.block4, 0, 5) / 2.0;
    mjd = int(mjd + lto / 24.0);
  }

  int yr = int((mjd - 15078.2) / 365.25);
  int mo = int((mjd - 14956.1 - int(yr * 365.25)) / 30.6001);
  int dy = mjd - 14956 - int(yr * 365.25) - int(mo * 30.6001);
  if (mo == 14 || mo == 15) {
    yr += 1;
    mo -= 12;
  }
  yr += 1900;
  mo -= 1;

  if (group.num_blocks == 4) {
    int ltom = (lto - int(lto)) * 60;

    int hr = int((bits(group.block3, 0, 1) << 4) +
        bits(group.block4, 12, 14) + lto) % 24;
    int mn = bits(group.block4, 6, 6) + ltom;

    char buff[100];
    snprintf(buff, sizeof(buff),
        "%04d-%02d-%02dT%02d:%02d:00%+03d:%02d\n",yr,mo,dy,hr,mn,int(lto),ltom);
    clock_time_ = buff;
    std::cout<<"clock_time:"<<clock_time_<<"\n";

  }
}

} // namespace redsea
<|endoftext|>


<commit_before>/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include "skin.h"
#include "utils/polygonUtils.h"

#define MIN_AREA_SIZE (0.4 * 0.4)

namespace cura
{

void generateSkins(int layerNr, SliceMeshStorage& mesh, int extrusionWidth, int downSkinCount, int upSkinCount, int wall_line_count, int innermost_wall_extrusion_width, int insetCount, bool no_small_gaps_heuristic)
{
    generateSkinAreas(layerNr, mesh, innermost_wall_extrusion_width, downSkinCount, upSkinCount, wall_line_count, no_small_gaps_heuristic);

    SliceLayer* layer = &mesh.layers[layerNr];
    for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++)
    {
        SliceLayerPart* part = &layer->parts[partNr];
        generateSkinInsets(part, extrusionWidth, insetCount);
    }
}

void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, int innermost_wall_extrusion_width, int downSkinCount, int upSkinCount, int wall_line_count, bool no_small_gaps_heuristic)
{
    SliceLayer& layer = mesh.layers[layer_nr];

    if (downSkinCount == 0 && upSkinCount == 0)
    {
        return;
    }

    for(unsigned int partNr = 0; partNr < layer.parts.size(); partNr++)
    {
        SliceLayerPart& part = layer.parts[partNr];

        if (int(part.insets.size()) < wall_line_count)
        {
            continue; // the last wall is not present, the part should only get inter preimeter gaps, but no skin.
        }

        Polygons upskin = part.insets.back().offset(-innermost_wall_extrusion_width/2);
        Polygons downskin = (downSkinCount == 0)? Polygons() : upskin;
        if (upSkinCount == 0) upskin = Polygons();

        auto getInsidePolygons = [&part, wall_line_count](SliceLayer& layer2)
            {
                Polygons result;
                for(SliceLayerPart& part2 : layer2.parts)
                {
                    if (part.boundaryBox.hit(part2.boundaryBox))
                    {
                        unsigned int wall_idx = std::max(0, std::min(wall_line_count, (int) part2.insets.size()) - 1);
                        result.add(part2.insets[wall_idx]);
                    }
                }
                return result;
            };

        if (no_small_gaps_heuristic)
        {
            if (static_cast<int>(layer_nr - downSkinCount) >= 0)
            {
                downskin = downskin.difference(getInsidePolygons(mesh.layers[layer_nr - downSkinCount])); // skin overlaps with the walls
            }

            if (static_cast<int>(layer_nr + upSkinCount) < static_cast<int>(mesh.layers.size()))
            {
                upskin = upskin.difference(getInsidePolygons(mesh.layers[layer_nr + upSkinCount])); // skin overlaps with the walls
            }
        }
        else
        {
            if (layer_nr >= downSkinCount && downSkinCount > 0)
            {
                Polygons not_air = getInsidePolygons(mesh.layers[layer_nr - 1]);
                for (int downskin_layer_nr = layer_nr - downSkinCount; downskin_layer_nr < layer_nr - 1; downskin_layer_nr++)
                {
                    not_air = not_air.intersection(getInsidePolygons(mesh.layers[downskin_layer_nr]));
                }
                downskin = downskin.difference(not_air); // skin overlaps with the walls
            }

            if (layer_nr < static_cast<int>(mesh.layers.size()) - 1 && upSkinCount > 0)
            {
                Polygons not_air = getInsidePolygons(mesh.layers[layer_nr + 1]);
                for (int upskin_layer_nr = layer_nr + 2; upskin_layer_nr < layer_nr + upSkinCount + 1; upskin_layer_nr++)
                {
                    not_air = not_air.intersection(getInsidePolygons(mesh.layers[upskin_layer_nr]));
                }
                upskin = upskin.difference(not_air); // skin overlaps with the walls
            }
        }

        Polygons skin = upskin.unionPolygons(downskin);

        skin.removeSmallAreas(MIN_AREA_SIZE);

        for (PolygonsPart& skin_area_part : skin.splitIntoParts())
        {
            part.skin_parts.emplace_back();
            part.skin_parts.back().outline = skin_area_part;
        }
    }
}

void generateSkinInsets(SliceLayerPart* part, int extrusionWidth, int insetCount)
{
    if (insetCount == 0)
    {
        return;
    }

    for (SkinPart& skin_part : part->skin_parts)
    {
        for(int i=0; i<insetCount; i++)
        {
            skin_part.insets.push_back(Polygons());
            if (i == 0)
            {
                skin_part.insets[0] = skin_part.outline.offset(- extrusionWidth/2);
            } else
            {
                skin_part.insets[i] = skin_part.insets[i - 1].offset(-extrusionWidth);
            }

            // optimize polygons: remove unnnecesary verts
            skin_part.insets[i].simplify();
            if (skin_part.insets[i].size() < 1)
            {
                skin_part.insets.pop_back();
                break;
            }
        }
    }
}

void generateInfill(int layerNr, SliceMeshStorage& mesh, int innermost_wall_extrusion_width, int infill_skin_overlap, int wall_line_count)
{
    SliceLayer& layer = mesh.layers[layerNr];

    for(SliceLayerPart& part : layer.parts)
    {
        if (int(part.insets.size()) < wall_line_count)
        {
            continue; // the last wall is not present, the part should only get inter preimeter gaps, but no infill.
        }
        Polygons infill = part.insets.back().offset(-innermost_wall_extrusion_width / 2 - infill_skin_overlap);

        for(SliceLayerPart& part2 : layer.parts)
        {
            if (part.boundaryBox.hit(part2.boundaryBox))
            {
                for(SkinPart& skin_part : part2.skin_parts)
                {
                    infill = infill.difference(skin_part.outline);
                }
            }
        }
        infill.removeSmallAreas(MIN_AREA_SIZE);

        part.infill_area = infill.offset(infill_skin_overlap);
    }
}

void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh, unsigned int gradual_infill_step_height, unsigned int max_infill_steps)
{
    // no early-out for this function; it needs to initialize the [infill_area_per_combine_per_density]
    unsigned int layer_skip_count = 8; // skip every so many layers as to ignore small gaps in the model making computation more easy
    if (!mesh.getSettingBoolean("skin_no_small_gaps_heuristic"))
    {
        layer_skip_count = 1;
    }
    unsigned int gradual_infill_step_layer_count = gradual_infill_step_height / mesh.getSettingInMicrons("layer_height"); // The difference in layer count between consecutive density infill areas
    layer_skip_count = gradual_infill_step_layer_count / ((gradual_infill_step_layer_count - 1) / layer_skip_count + 1); // make gradual_infill_step_height divisable by layer_skip_count

    size_t min_layer = mesh.getSettingAsCount("bottom_layers");
    size_t max_layer = mesh.layers.size() - 1 - mesh.getSettingAsCount("top_layers");

    for (size_t layer_idx = 0; layer_idx < mesh.layers.size(); layer_idx++)
    { // loop also over layers which don't contain infill cause of bottom_ and top_layer to initialize their infill_area_per_combine_per_density
        SliceLayer& layer = mesh.layers[layer_idx];

        for (SliceLayerPart& part : layer.parts)
        {
            assert(part.infill_area_per_combine_per_density.size() == 0 && "infill_area_per_combine_per_density is supposed to be uninitialized");

            if (part.infill_area.size() == 0 || layer_idx < min_layer || layer_idx > max_layer)
            { // initialize infill_area_per_combine_per_density empty
                part.infill_area_per_combine_per_density.emplace_back(); // create a new infill_area_per_combine
                part.infill_area_per_combine_per_density.back().emplace_back(); // put empty infill area in the newly contructed infill_area_per_combine
                // note: no need to copy part.infill_area, cause it's the empty vector anyway
                continue;
            }

            Polygons less_dense_infill = part.infill_area; // one step less dense with each infill_step
            for (unsigned int infill_step = 0; infill_step < max_infill_steps; infill_step++)
            {
                size_t min_layer = layer_idx + infill_step * gradual_infill_step_layer_count + layer_skip_count;
                size_t max_layer = layer_idx + (infill_step + 1) * gradual_infill_step_layer_count;

                for (size_t upper_layer_idx = min_layer; upper_layer_idx < max_layer; upper_layer_idx += layer_skip_count)
                {
                    if (upper_layer_idx >= mesh.layers.size())
                    {
                        less_dense_infill.clear();
                        break;
                    }
                    SliceLayer& upper_layer = mesh.layers[upper_layer_idx];
                    Polygons relevent_upper_polygons;
                    for (SliceLayerPart& upper_layer_part : upper_layer.parts)
                    {
                        if (!upper_layer_part.boundaryBox.hit(part.boundaryBox))
                        {
                            continue;
                        }
                        relevent_upper_polygons.add(upper_layer_part.infill_area);
                    }
                    less_dense_infill = less_dense_infill.intersection(relevent_upper_polygons);
                }
                if (less_dense_infill.size() == 0)
                {
                    break;
                }
                // add new infill_area_per_combine for the current density
                part.infill_area_per_combine_per_density.emplace_back();
                std::vector<Polygons>& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back();
                const Polygons more_dense_infill = part.infill_area.difference(less_dense_infill);
                infill_area_per_combine_current_density.push_back(more_dense_infill);

                if (less_dense_infill.size() == 0)
                {
                    break;
                }
            }
            part.infill_area_per_combine_per_density.emplace_back();
            std::vector<Polygons>& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back();
            infill_area_per_combine_current_density.push_back(part.infill_area);
            assert(part.infill_area_per_combine_per_density.size() != 0 && "infill_area_per_combine_per_density is now initialized");
        }
    }
}

void combineInfillLayers(SliceMeshStorage& mesh, unsigned int amount)
{
    if (mesh.layers.empty() || mesh.layers.size() - 1 < static_cast<size_t>(mesh.getSettingAsCount("top_layers")) || mesh.getSettingAsCount("infill_line_distance") <= 0) //No infill is even generated.
    {
        return;
    }
    if(amount <= 1) //If we must combine 1 layer, nothing needs to be combined. Combining 0 layers is invalid.
    {
        return;
    }
    /* We need to round down the layer index we start at to the nearest
    divisible index. Otherwise we get some parts that have infill at divisible
    layers and some at non-divisible layers. Those layers would then miss each
    other. */
    size_t min_layer = mesh.getSettingAsCount("bottom_layers") + amount - 1;
    min_layer -= min_layer % amount; //Round upwards to the nearest layer divisible by infill_sparse_combine.
    size_t max_layer = mesh.layers.size() - 1 - mesh.getSettingAsCount("top_layers");
    max_layer -= max_layer % amount; //Round downwards to the nearest layer divisible by infill_sparse_combine.
    for(size_t layer_idx = min_layer;layer_idx <= max_layer;layer_idx += amount) //Skip every few layers, but extrude more.
    {
        SliceLayer* layer = &mesh.layers[layer_idx];
        for(unsigned int combine_count_here = 1; combine_count_here < amount; combine_count_here++)
        {
            if(layer_idx < combine_count_here)
            {
                break;
            }

            size_t lower_layer_idx = layer_idx - combine_count_here;
            if (lower_layer_idx < min_layer)
            {
                break;
            }
            SliceLayer* lower_layer = &mesh.layers[lower_layer_idx];
            for (SliceLayerPart& part : layer->parts)
            {
                for (unsigned int density_idx = 0; density_idx < part.infill_area_per_combine_per_density.size(); density_idx++)
                { // go over eacht density of gradual infill (these density areas overlap!)
                    std::vector<Polygons>& infill_area_per_combine = part.infill_area_per_combine_per_density[density_idx];
                    Polygons result;
                    for (SliceLayerPart& lower_layer_part : lower_layer->parts)
                    {
                        if (part.boundaryBox.hit(lower_layer_part.boundaryBox))
                        {

                            Polygons intersection = infill_area_per_combine[combine_count_here - 1].intersection(lower_layer_part.infill_area).offset(-200).offset(200);
                            result.add(intersection); // add area to be thickened
                            infill_area_per_combine[combine_count_here - 1] = infill_area_per_combine[combine_count_here - 1].difference(intersection); // remove thickened area from less thick layer here
                            if (density_idx < lower_layer_part.infill_area_per_combine_per_density.size())
                            { // only remove from *same density* areas on layer below
                                // If there are no same density areas, then it's ok to print them anyway
                                // Don't remove other density areas
                                unsigned int lower_density_idx = density_idx;
                                std::vector<Polygons>& lower_infill_area_per_combine = lower_layer_part.infill_area_per_combine_per_density[lower_density_idx];
                                lower_infill_area_per_combine[0] = lower_infill_area_per_combine[0].difference(intersection); // remove thickened area from lower (thickened) layer
                            }
                        }
                    }

                    infill_area_per_combine.push_back(result);
                }
            }
        }
    }
}

}//namespace cura
<commit_msg>fix: gradual infill steps are skipped through regularly now (CURA-836)<commit_after>/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <cmath> // std::ceil
#include "skin.h"
#include "utils/polygonUtils.h"

#define MIN_AREA_SIZE (0.4 * 0.4)

namespace cura
{

void generateSkins(int layerNr, SliceMeshStorage& mesh, int extrusionWidth, int downSkinCount, int upSkinCount, int wall_line_count, int innermost_wall_extrusion_width, int insetCount, bool no_small_gaps_heuristic)
{
    generateSkinAreas(layerNr, mesh, innermost_wall_extrusion_width, downSkinCount, upSkinCount, wall_line_count, no_small_gaps_heuristic);

    SliceLayer* layer = &mesh.layers[layerNr];
    for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++)
    {
        SliceLayerPart* part = &layer->parts[partNr];
        generateSkinInsets(part, extrusionWidth, insetCount);
    }
}

void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, int innermost_wall_extrusion_width, int downSkinCount, int upSkinCount, int wall_line_count, bool no_small_gaps_heuristic)
{
    SliceLayer& layer = mesh.layers[layer_nr];

    if (downSkinCount == 0 && upSkinCount == 0)
    {
        return;
    }

    for(unsigned int partNr = 0; partNr < layer.parts.size(); partNr++)
    {
        SliceLayerPart& part = layer.parts[partNr];

        if (int(part.insets.size()) < wall_line_count)
        {
            continue; // the last wall is not present, the part should only get inter preimeter gaps, but no skin.
        }

        Polygons upskin = part.insets.back().offset(-innermost_wall_extrusion_width/2);
        Polygons downskin = (downSkinCount == 0)? Polygons() : upskin;
        if (upSkinCount == 0) upskin = Polygons();

        auto getInsidePolygons = [&part, wall_line_count](SliceLayer& layer2)
            {
                Polygons result;
                for(SliceLayerPart& part2 : layer2.parts)
                {
                    if (part.boundaryBox.hit(part2.boundaryBox))
                    {
                        unsigned int wall_idx = std::max(0, std::min(wall_line_count, (int) part2.insets.size()) - 1);
                        result.add(part2.insets[wall_idx]);
                    }
                }
                return result;
            };

        if (no_small_gaps_heuristic)
        {
            if (static_cast<int>(layer_nr - downSkinCount) >= 0)
            {
                downskin = downskin.difference(getInsidePolygons(mesh.layers[layer_nr - downSkinCount])); // skin overlaps with the walls
            }

            if (static_cast<int>(layer_nr + upSkinCount) < static_cast<int>(mesh.layers.size()))
            {
                upskin = upskin.difference(getInsidePolygons(mesh.layers[layer_nr + upSkinCount])); // skin overlaps with the walls
            }
        }
        else
        {
            if (layer_nr >= downSkinCount && downSkinCount > 0)
            {
                Polygons not_air = getInsidePolygons(mesh.layers[layer_nr - 1]);
                for (int downskin_layer_nr = layer_nr - downSkinCount; downskin_layer_nr < layer_nr - 1; downskin_layer_nr++)
                {
                    not_air = not_air.intersection(getInsidePolygons(mesh.layers[downskin_layer_nr]));
                }
                downskin = downskin.difference(not_air); // skin overlaps with the walls
            }

            if (layer_nr < static_cast<int>(mesh.layers.size()) - 1 && upSkinCount > 0)
            {
                Polygons not_air = getInsidePolygons(mesh.layers[layer_nr + 1]);
                for (int upskin_layer_nr = layer_nr + 2; upskin_layer_nr < layer_nr + upSkinCount + 1; upskin_layer_nr++)
                {
                    not_air = not_air.intersection(getInsidePolygons(mesh.layers[upskin_layer_nr]));
                }
                upskin = upskin.difference(not_air); // skin overlaps with the walls
            }
        }

        Polygons skin = upskin.unionPolygons(downskin);

        skin.removeSmallAreas(MIN_AREA_SIZE);

        for (PolygonsPart& skin_area_part : skin.splitIntoParts())
        {
            part.skin_parts.emplace_back();
            part.skin_parts.back().outline = skin_area_part;
        }
    }
}

void generateSkinInsets(SliceLayerPart* part, int extrusionWidth, int insetCount)
{
    if (insetCount == 0)
    {
        return;
    }

    for (SkinPart& skin_part : part->skin_parts)
    {
        for(int i=0; i<insetCount; i++)
        {
            skin_part.insets.push_back(Polygons());
            if (i == 0)
            {
                skin_part.insets[0] = skin_part.outline.offset(- extrusionWidth/2);
            } else
            {
                skin_part.insets[i] = skin_part.insets[i - 1].offset(-extrusionWidth);
            }

            // optimize polygons: remove unnnecesary verts
            skin_part.insets[i].simplify();
            if (skin_part.insets[i].size() < 1)
            {
                skin_part.insets.pop_back();
                break;
            }
        }
    }
}

void generateInfill(int layerNr, SliceMeshStorage& mesh, int innermost_wall_extrusion_width, int infill_skin_overlap, int wall_line_count)
{
    SliceLayer& layer = mesh.layers[layerNr];

    for(SliceLayerPart& part : layer.parts)
    {
        if (int(part.insets.size()) < wall_line_count)
        {
            continue; // the last wall is not present, the part should only get inter preimeter gaps, but no infill.
        }
        Polygons infill = part.insets.back().offset(-innermost_wall_extrusion_width / 2 - infill_skin_overlap);

        for(SliceLayerPart& part2 : layer.parts)
        {
            if (part.boundaryBox.hit(part2.boundaryBox))
            {
                for(SkinPart& skin_part : part2.skin_parts)
                {
                    infill = infill.difference(skin_part.outline);
                }
            }
        }
        infill.removeSmallAreas(MIN_AREA_SIZE);

        part.infill_area = infill.offset(infill_skin_overlap);
    }
}

void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh, unsigned int gradual_infill_step_height, unsigned int max_infill_steps)
{
    // no early-out for this function; it needs to initialize the [infill_area_per_combine_per_density]
    float layer_skip_count = 8; // skip every so many layers as to ignore small gaps in the model making computation more easy
    if (!mesh.getSettingBoolean("skin_no_small_gaps_heuristic"))
    {
        layer_skip_count = 1;
    }
    unsigned int gradual_infill_step_layer_count = gradual_infill_step_height / mesh.getSettingInMicrons("layer_height"); // The difference in layer count between consecutive density infill areas

    // make gradual_infill_step_height divisable by layer_skip_count
    float n_skip_steps_per_gradual_step = std::max(1.0f, std::ceil(gradual_infill_step_layer_count / layer_skip_count)); // only decrease layer_skip_count to make it a divisor of gradual_infill_step_layer_count
    layer_skip_count = gradual_infill_step_layer_count / n_skip_steps_per_gradual_step;

    size_t min_layer = mesh.getSettingAsCount("bottom_layers");
    size_t max_layer = mesh.layers.size() - 1 - mesh.getSettingAsCount("top_layers");

    for (size_t layer_idx = 0; layer_idx < mesh.layers.size(); layer_idx++)
    { // loop also over layers which don't contain infill cause of bottom_ and top_layer to initialize their infill_area_per_combine_per_density
        SliceLayer& layer = mesh.layers[layer_idx];

        for (SliceLayerPart& part : layer.parts)
        {
            assert(part.infill_area_per_combine_per_density.size() == 0 && "infill_area_per_combine_per_density is supposed to be uninitialized");

            if (part.infill_area.size() == 0 || layer_idx < min_layer || layer_idx > max_layer)
            { // initialize infill_area_per_combine_per_density empty
                part.infill_area_per_combine_per_density.emplace_back(); // create a new infill_area_per_combine
                part.infill_area_per_combine_per_density.back().emplace_back(); // put empty infill area in the newly contructed infill_area_per_combine
                // note: no need to copy part.infill_area, cause it's the empty vector anyway
                continue;
            }
            Polygons less_dense_infill = part.infill_area; // one step less dense with each infill_step
            for (unsigned int infill_step = 0; infill_step < max_infill_steps; infill_step++)
            {
                size_t min_layer = layer_idx + infill_step * gradual_infill_step_layer_count + layer_skip_count;
                size_t max_layer = layer_idx + (infill_step + 1) * gradual_infill_step_layer_count;

                for (float upper_layer_idx = min_layer; static_cast<unsigned int>(upper_layer_idx) <= max_layer; upper_layer_idx += layer_skip_count)
                {
                    if (static_cast<unsigned int>(upper_layer_idx) >= mesh.layers.size())
                    {
                        less_dense_infill.clear();
                        break;
                    }
                    SliceLayer& upper_layer = mesh.layers[static_cast<unsigned int>(upper_layer_idx)];
                    Polygons relevent_upper_polygons;
                    for (SliceLayerPart& upper_layer_part : upper_layer.parts)
                    {
                        if (!upper_layer_part.boundaryBox.hit(part.boundaryBox))
                        {
                            continue;
                        }
                        relevent_upper_polygons.add(upper_layer_part.infill_area);
                    }
                    less_dense_infill = less_dense_infill.intersection(relevent_upper_polygons);
                }
                if (less_dense_infill.size() == 0)
                {
                    break;
                }
                // add new infill_area_per_combine for the current density
                part.infill_area_per_combine_per_density.emplace_back();
                std::vector<Polygons>& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back();
                const Polygons more_dense_infill = part.infill_area.difference(less_dense_infill);
                infill_area_per_combine_current_density.push_back(more_dense_infill);

                if (less_dense_infill.size() == 0)
                {
                    break;
                }
            }
            part.infill_area_per_combine_per_density.emplace_back();
            std::vector<Polygons>& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back();
            infill_area_per_combine_current_density.push_back(part.infill_area);
            assert(part.infill_area_per_combine_per_density.size() != 0 && "infill_area_per_combine_per_density is now initialized");
        }
    }
}

void combineInfillLayers(SliceMeshStorage& mesh, unsigned int amount)
{
    if (mesh.layers.empty() || mesh.layers.size() - 1 < static_cast<size_t>(mesh.getSettingAsCount("top_layers")) || mesh.getSettingAsCount("infill_line_distance") <= 0) //No infill is even generated.
    {
        return;
    }
    if(amount <= 1) //If we must combine 1 layer, nothing needs to be combined. Combining 0 layers is invalid.
    {
        return;
    }
    /* We need to round down the layer index we start at to the nearest
    divisible index. Otherwise we get some parts that have infill at divisible
    layers and some at non-divisible layers. Those layers would then miss each
    other. */
    size_t min_layer = mesh.getSettingAsCount("bottom_layers") + amount - 1;
    min_layer -= min_layer % amount; //Round upwards to the nearest layer divisible by infill_sparse_combine.
    size_t max_layer = mesh.layers.size() - 1 - mesh.getSettingAsCount("top_layers");
    max_layer -= max_layer % amount; //Round downwards to the nearest layer divisible by infill_sparse_combine.
    for(size_t layer_idx = min_layer;layer_idx <= max_layer;layer_idx += amount) //Skip every few layers, but extrude more.
    {
        SliceLayer* layer = &mesh.layers[layer_idx];
        for(unsigned int combine_count_here = 1; combine_count_here < amount; combine_count_here++)
        {
            if(layer_idx < combine_count_here)
            {
                break;
            }

            size_t lower_layer_idx = layer_idx - combine_count_here;
            if (lower_layer_idx < min_layer)
            {
                break;
            }
            SliceLayer* lower_layer = &mesh.layers[lower_layer_idx];
            for (SliceLayerPart& part : layer->parts)
            {
                for (unsigned int density_idx = 0; density_idx < part.infill_area_per_combine_per_density.size(); density_idx++)
                { // go over eacht density of gradual infill (these density areas overlap!)
                    std::vector<Polygons>& infill_area_per_combine = part.infill_area_per_combine_per_density[density_idx];
                    Polygons result;
                    for (SliceLayerPart& lower_layer_part : lower_layer->parts)
                    {
                        if (part.boundaryBox.hit(lower_layer_part.boundaryBox))
                        {

                            Polygons intersection = infill_area_per_combine[combine_count_here - 1].intersection(lower_layer_part.infill_area).offset(-200).offset(200);
                            result.add(intersection); // add area to be thickened
                            infill_area_per_combine[combine_count_here - 1] = infill_area_per_combine[combine_count_here - 1].difference(intersection); // remove thickened area from less thick layer here
                            if (density_idx < lower_layer_part.infill_area_per_combine_per_density.size())
                            { // only remove from *same density* areas on layer below
                                // If there are no same density areas, then it's ok to print them anyway
                                // Don't remove other density areas
                                unsigned int lower_density_idx = density_idx;
                                std::vector<Polygons>& lower_infill_area_per_combine = lower_layer_part.infill_area_per_combine_per_density[lower_density_idx];
                                lower_infill_area_per_combine[0] = lower_infill_area_per_combine[0].difference(intersection); // remove thickened area from lower (thickened) layer
                            }
                        }
                    }

                    infill_area_per_combine.push_back(result);
                }
            }
        }
    }
}

}//namespace cura
<|endoftext|>


<commit_before><commit_msg>Fix for gratuitous fake emboldening of already-bold fonts on Linux.<commit_after><|endoftext|>


<commit_before>#ifndef IOPROCESSES_H
#define IOPROCESSES_H
#include<boost/shared_ptr.hpp>
#include<boost/scoped_ptr.hpp>
#include<vector>
#include<utility>
#include<stack>
#include<string>

#include"processes.hpp"

class PortData; /*abstract port data class*/

class CentralIOToDo;

enum IOActionType {
	ioaction_read,		/*read some bytes*/
	ioaction_write,		/*write some bytes*/
	ioaction_stdin,		/*get PortData for stdin*/
	ioaction_stdout,	/*get PortData for stdout*/
	ioaction_stderr,	/*get PortData for stderr*/
	ioaction_open,		/*open a filesystem file*/
	ioaction_close,		/*close a PortData*/
	ioaction_server,	/*create a server at port*/
	ioaction_listen,	/*listen on a server PortData*/
	ioaction_sleep,		/*wait a particular amount of time*/
	ioaction_system		/*start another OS process and wait*/
};

class IOAction {
public:
	IOActionType action;
	boost::shared_ptr<PortData> port;
	boost::shared_ptr<std::vector<unsigned char> > data;
	int num;
	std::string str;
};

/*abstract base*/
class CentralIO {
public:
	/*performs members of the to-do lists that
	can be done now, and returns as soon as those
	are handled
	*/
	virtual void poll(CentralIOToDo) =0;
	/*performs members of the to-do lists
	that can be done now.  If there aren't
	any, waits until at least one can be
	done.
	*/
	virtual void wait(CentralIOToDo) =0;
	/*determine if there are any pending request: returns
	true if no pending requests
	*/
	virtual bool empty(void) =0;
	virtual ~CentralIO(){}
};

CentralIO* NewCentralIO(void);

class CentralIOProcess;

CentralIOProcess* NewCentralIOProcess(void);

/*PImpl*/
class CentralIOProcess : public ProcessBase {
private:
	boost::scoped_ptr<CentralIO> impl;

	bool waiting;

	typedef std::pair<boost::shared_ptr<Semispace>, Generic* > message;
	typedef std::pair<boost::shared_ptr<ProcessHandle>, message> response;

	/*received queue*/
	std::vector<message> rcv_queue;//protect with lock
	/*to-do list*/
	std::vector<IOAction> todo;
	/*for commission*/
	std::vector<response> snd_queue;

	/*ctor*/
	CentralIOProcess() : waiting(1) {}

public:
	virtual bool receive(boost::shared_ptr<Semispace>, Generic*);
	virtual ProcessStatus run(void);
	virtual ~CentralIOProcess(){}

	CentralIOProcess() : impl(NewCentralIO()), waiting(0) {}

	friend class CentralIOToDo;
	friend CentralIOProcess* NewCentralIOProcess(void);
};

/*TODO: think of best way to do this*/
class CentralIOToDo {
private:
	CentralIOProcess* proc;
public:
	explicit CentralIOToDo(CentralIOProcess* p) : proc(p){}
	bool empty(void){
		return proc->todo.empty();
	}
	IOAction get(void);
	void respond(IOAction);
	void error(IOAction, std::string);
};

#endif //IOPROCESSES_H
<commit_msg>ioprocesses: various backend changes<commit_after>#ifndef IOPROCESSES_H
#define IOPROCESSES_H
#include<boost/shared_ptr.hpp>
#include<boost/scoped_ptr.hpp>
#include<vector>
#include<utility>
#include<stack>
#include<string>

#include"processes.hpp"

class PortData; /*abstract port data class*/

class CentralIOToDo;

enum IOActionType {
	ioaction_read,		/*read some bytes*/
	ioaction_write,		/*write some bytes*/
	ioaction_stdin,		/*get PortData for stdin*/
	ioaction_stdout,	/*get PortData for stdout*/
	ioaction_stderr,	/*get PortData for stderr*/
	ioaction_open,		/*open a filesystem file*/
	ioaction_close,		/*close a PortData*/
	ioaction_server,	/*create a server at port*/
	ioaction_listen,	/*listen on a server PortData*/
	ioaction_sleep,		/*wait a particular amount of time*/
	ioaction_system		/*start another OS process and wait*/
};

class IOAction {
private:
	boost::shared_ptr<ProcessHandle> requester;
public:
	IOActionType action;
	boost::shared_ptr<PortData> port;
	boost::shared_ptr<std::vector<unsigned char> > data;
	int num;
	std::string str;
	friend class CentralIOToDo;
};

/*abstract base*/
class CentralIO {
public:
	/*performs members of the to-do lists that
	can be done now, and returns as soon as those
	are handled
	*/
	virtual void poll(CentralIOToDo) =0;
	/*performs members of the to-do lists
	that can be done now.  If there aren't
	any, waits until at least one can be
	done.
	*/
	virtual void wait(CentralIOToDo) =0;
	/*determine if there are any pending request: returns
	true if no pending requests
	*/
	virtual bool empty(void) =0;
	virtual ~CentralIO(){}
};

CentralIO* NewCentralIO(void);

class CentralIOProcess;

CentralIOProcess* NewCentralIOProcess(void);

/*PImpl*/
class CentralIOProcess : public ProcessBase {
private:
	boost::scoped_ptr<CentralIO> impl;

	bool waiting;

	typedef std::pair<boost::shared_ptr<Semispace>, Generic* > message;
	typedef std::pair<boost::shared_ptr<ProcessHandle>, message> response;

	/*received queue*/
	std::vector<message> rcv_queue;//protect with lock
	/*to-do list*/
	std::vector<IOAction> todo;
	/*for commission*/
	std::vector<response> snd_queue;

	/*ctor*/
	CentralIOProcess() : impl(NewCentralIO()), waiting(1) {}

public:
	virtual bool receive(boost::shared_ptr<Semispace>, Generic*);
	virtual ProcessStatus run(void);
	virtual ~CentralIOProcess(){}

	friend class CentralIOToDo;
	friend CentralIOProcess* NewCentralIOProcess(void);
};

/*TODO: think of best way to do this*/
class CentralIOToDo {
private:
	CentralIOProcess* proc;
public:
	explicit CentralIOToDo(CentralIOProcess* p) : proc(p){}
	bool empty(void){
		return proc->todo.empty();
	}
	/*returns an IOAction.  Once an IOAction is released
	using this, it is the responsibility of the CentralIO
	object.
	*/
	IOAction get(void){
		IOAction tmp = proc->todo.back();
		proc->todo.pop_back();
		return tmp;
	}

	/*responses to an IOAction*/
	void respond(IOAction);
	void error(IOAction, std::string);
	void eof(IOAction);
};

#endif //IOPROCESSES_H
<|endoftext|>


<commit_before>#include <shogun/features/DataGenerator.h>
#include <shogun/transfer/multitask/MultitaskL12LogisticRegression.h>
#include <shogun/transfer/multitask/MultitaskClusteredLogisticRegression.h>
#include <shogun/transfer/multitask/MultitaskTraceLogisticRegression.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/labels/BinaryLabels.h>

#include <gtest/gtest.h>

#include <utility>

using namespace shogun;

typedef std::pair<CDotFeatures*, CDotFeatures*> SplittedFeatures;
typedef std::pair<SplittedFeatures, CBinaryLabels*> SplittedDataset;

#ifdef HAVE_LAPACK
SplittedDataset generate_data()
{
	index_t num_samples = 50;
	CMath::init_random(5);
	SGMatrix<float64_t> data =
		CDataGenerator::generate_gaussians(num_samples, 2, 2);
	CDenseFeatures<float64_t>* features = new CDenseFeatures<float64_t>(data);

	SGVector<index_t> train_idx(num_samples), test_idx(num_samples);
	SGVector<float64_t> labels(num_samples);
	for (index_t i = 0, j = 0; i < num_samples; ++i)
	{
		if (i % 2 == 0)
			train_idx[j] = i;
		else
			test_idx[j++] = i;

		labels[i] = (i < num_samples/2) ? 1.0 : -1.0;
	}

	CDenseFeatures<float64_t>* train_feats = (CDenseFeatures<float64_t>*)features->copy_subset(train_idx);
	CDenseFeatures<float64_t>* test_feats =  (CDenseFeatures<float64_t>*)features->copy_subset(test_idx);

	CBinaryLabels* ground_truth = new CBinaryLabels(labels);
	SG_UNREF(features);

	return SplittedDataset(SplittedFeatures(train_feats, test_feats), ground_truth);
}

TEST(MalsarL12Test, train)
{
	SplittedDataset data = generate_data();

	CTaskGroup* task_group = new CTaskGroup();
	CTask* task = new CTask(0, data.second->get_num_labels());
	task_group->append_task(task);

	CMultitaskL12LogisticRegression* mtlr = new CMultitaskL12LogisticRegression(0.1,0.1,data.first.first,data.second,task_group);
	mtlr->train();
	mtlr->set_features(data.first.second);
	CLabels* output = mtlr->apply();
	SG_UNREF(output);
	SG_UNREF(mtlr);
	SG_UNREF(data.first.first);
	SG_UNREF(data.first.second);
}

TEST(MalsarClusteredTest, train)
{
	SplittedDataset data = generate_data();

	CTaskGroup* task_group = new CTaskGroup();
	CTask* task = new CTask(0, data.second->get_num_labels());
	task_group->append_task(task);

	CMultitaskClusteredLogisticRegression* mtlr = new CMultitaskClusteredLogisticRegression(0.1,0.1,data.first.first,data.second,task_group,1);
	mtlr->train();
	mtlr->set_features(data.first.second);
	CLabels* output = mtlr->apply();
	SG_UNREF(output);
	SG_UNREF(mtlr);
	SG_UNREF(data.first.first);
	SG_UNREF(data.first.second);
}

TEST(MalsarTraceTest, train)
{
	SplittedDataset data = generate_data();

	CTaskGroup* task_group = new CTaskGroup();
	CTask* task = new CTask(0, data.second->get_num_labels());
	task_group->append_task(task);

	CMultitaskTraceLogisticRegression* mtlr = new CMultitaskTraceLogisticRegression(0.1,data.first.first,data.second,task_group);
	mtlr->train();
	mtlr->set_features(data.first.second);
	CLabels* output = mtlr->apply();
	SG_UNREF(output);
	SG_UNREF(mtlr);
	SG_UNREF(data.first.first);
	SG_UNREF(data.first.second);
}
#endif // HAVE_LAPACK

<commit_msg>Updated Malsar unittest (#1360)<commit_after>#include <shogun/features/DataGenerator.h>
#include <shogun/transfer/multitask/MultitaskL12LogisticRegression.h>
#include <shogun/transfer/multitask/MultitaskClusteredLogisticRegression.h>
#include <shogun/transfer/multitask/MultitaskTraceLogisticRegression.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/labels/BinaryLabels.h>

#include <gtest/gtest.h>

#include <utility>

using namespace shogun;

typedef std::pair<CDotFeatures*, CDotFeatures*> SplittedFeatures;
typedef std::pair<SplittedFeatures, CBinaryLabels*> SplittedDataset;

#ifdef HAVE_LAPACK
SplittedDataset generate_data()
{
	index_t num_samples = 50;
	CMath::init_random(5);
	SGMatrix<float64_t> data =
		CDataGenerator::generate_gaussians(num_samples, 2, 2);
	CDenseFeatures<float64_t>* features = new CDenseFeatures<float64_t>(data);

	SGVector<index_t> train_idx(num_samples), test_idx(num_samples);
	SGVector<float64_t> labels(num_samples);
	for (index_t i = 0, j = 0; i < 2*num_samples; ++i)
	{
		if (i % 2 == 0)
			train_idx[j] = i;
		else
			test_idx[j++] = i;

		labels[i/2] = (i < num_samples) ? 1.0 : -1.0;
	}

	CDenseFeatures<float64_t>* train_feats = (CDenseFeatures<float64_t>*)features->copy_subset(train_idx);
	CDenseFeatures<float64_t>* test_feats =  (CDenseFeatures<float64_t>*)features->copy_subset(test_idx);

	CBinaryLabels* ground_truth = new CBinaryLabels(labels);
	SG_UNREF(features);

	return SplittedDataset(SplittedFeatures(train_feats, test_feats), ground_truth);
}

TEST(MalsarL12Test, train)
{
	SplittedDataset data = generate_data();

	CTaskGroup* task_group = new CTaskGroup();
	CTask* task = new CTask(0, data.second->get_num_labels());
	task_group->append_task(task);

	CMultitaskL12LogisticRegression* mtlr = new CMultitaskL12LogisticRegression(0.1,0.1,data.first.first,data.second,task_group);
	mtlr->train();
	mtlr->set_features(data.first.second);
	CLabels* output = mtlr->apply();
	SG_UNREF(output);
	SG_UNREF(mtlr);
	SG_UNREF(data.first.first);
	SG_UNREF(data.first.second);
}

TEST(MalsarClusteredTest, train)
{
	SplittedDataset data = generate_data();

	CTaskGroup* task_group = new CTaskGroup();
	CTask* task = new CTask(0, data.second->get_num_labels());
	task_group->append_task(task);

	CMultitaskClusteredLogisticRegression* mtlr = new CMultitaskClusteredLogisticRegression(0.1,0.1,data.first.first,data.second,task_group,1);
	mtlr->train();
	mtlr->set_features(data.first.second);
	CLabels* output = mtlr->apply();
	SG_UNREF(output);
	SG_UNREF(mtlr);
	SG_UNREF(data.first.first);
	SG_UNREF(data.first.second);
}

TEST(MalsarTraceTest, train)
{
	SplittedDataset data = generate_data();

	CTaskGroup* task_group = new CTaskGroup();
	CTask* task = new CTask(0, data.second->get_num_labels());
	task_group->append_task(task);

	CMultitaskTraceLogisticRegression* mtlr = new CMultitaskTraceLogisticRegression(0.1,data.first.first,data.second,task_group);
	mtlr->train();
	mtlr->set_features(data.first.second);
	CLabels* output = mtlr->apply();
	SG_UNREF(output);
	SG_UNREF(mtlr);
	SG_UNREF(data.first.first);
	SG_UNREF(data.first.second);
}
#endif // HAVE_LAPACK

<|endoftext|>


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

#ifndef ETL_TMP_HPP
#define ETL_TMP_HPP

template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;

template<bool B, class T = void>
using disable_if_t = typename std::enable_if<!B, T>::type;

template<typename T>
using remove_reference_t = typename std::remove_reference<T>::type;

template<typename T>
using remove_cv_t = typename std::remove_cv<T>::type;

namespace detail {

//Note: Unfortunately, CLang is bugged (Bug 11723), therefore, it is not
//possible to use universal enable_if/disable_if directly, it is necessary to
//use the dummy :( FU Clang!

enum class enabler_t { DUMMY };
constexpr const enabler_t dummy = enabler_t::DUMMY;

} //end of detail

template<bool B>
using enable_if_u = typename std::enable_if<B, detail::enabler_t>::type;

template<bool B>
using disable_if_u = typename std::enable_if<!B, detail::enabler_t>::type;

template<bool b1>
struct not_u : std::true_type {};

template<>
struct not_u<true> : std::false_type {};

template<bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, bool b6 = true>
struct and_u : std::false_type {};

template<>
struct and_u<true, true, true, true, true, true> : std::true_type {};

template<bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false, bool b6 = false, bool b7 = false, bool b8 = false, bool b9 = false>
struct or_u : std::true_type {};

template<>
struct or_u<false, false, false, false, false, false, false, false, false> : std::false_type {};

template<template<typename...> class TT, typename T>
struct is_specialization_of : std::false_type {};

template<template<typename...> class TT, typename... Args>
struct is_specialization_of<TT, TT<Args...>> : std::true_type {};

template<typename V, typename F, typename... S>
struct all_convertible_to  : std::integral_constant<bool, and_u<all_convertible_to<V, F>::value, all_convertible_to<V, S...>::value>::value> {};

template<typename V, typename F>
struct all_convertible_to<V, F> : std::integral_constant<bool, std::is_convertible<F, V>::value> {};

//Variadic manipulations utilities

template<std::size_t N, typename... T>
struct nth_type {
    using type = typename std::tuple_element<N, std::tuple<T...>>::type;
};

template<typename... T>
struct first_type {
    using type = typename nth_type<0, T...>::type;
};

template<typename... T>
struct last_type {
    using type = typename nth_type<sizeof...(T)-1, T...>::type;
};

template<int I, typename T1, typename... T, enable_if_u<(I == 0)> = detail::dummy>
auto nth_value(T1&& t, T&&... /*args*/) -> decltype(std::forward<T1>(t)) {
    return std::forward<T1>(t);
}

template<int I, typename T1, typename... T, enable_if_u<(I > 0)> = detail::dummy>
auto nth_value(T1&& /*t*/, T&&... args)
        -> decltype(std::forward<typename nth_type<I, T1, T...>::type>(std::declval<typename nth_type<I, T1, T...>::type>())){
    using return_type = typename nth_type<I, T1, T...>::type;
    return std::forward<return_type>(nth_value<I - 1>((std::forward<T>(args))...));
}

template<typename... T>
auto last_value(T&&... args){
    return nth_value<sizeof...(T) - 1>(args...);
}

template<std::size_t I, std::size_t S, typename F, typename... T>
struct is_homogeneous_helper {
    template<std::size_t I1, std::size_t S1, typename Enable = void>
    struct helper_int : std::integral_constant<bool, and_u<std::is_same<F, typename nth_type<I1, T...>::type>::value, is_homogeneous_helper<I1+1, S1, F, T...>::value>::value> {};

    template<std::size_t I1, std::size_t S1>
    struct helper_int<I1, S1, enable_if_t<I1 == S1>> : std::integral_constant<bool, std::is_same<F, typename nth_type<I1, T...>::type>::value> {};

    static constexpr const auto value = helper_int<I, S>::value;
};

template<typename F, typename... T>
struct is_sub_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-2, F, T...>::value> {};

template<typename F, typename... T>
struct is_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-1, F, T...>::value> {};

#endif<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_TMP_HPP
#define ETL_TMP_HPP

template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;

template<bool B, class T = void>
using disable_if_t = typename std::enable_if<!B, T>::type;

template<typename T>
using remove_reference_t = typename std::remove_reference<T>::type;

template<typename T>
using remove_cv_t = typename std::remove_cv<T>::type;

namespace detail {

//Note: Unfortunately, CLang is bugged (Bug 11723), therefore, it is not
//possible to use universal enable_if/disable_if directly, it is necessary to
//use the dummy :( FU Clang!

enum class enabler_t { DUMMY };
constexpr const enabler_t dummy = enabler_t::DUMMY;

} //end of detail

template<bool B>
using enable_if_u = typename std::enable_if<B, detail::enabler_t>::type;

template<bool B>
using disable_if_u = typename std::enable_if<!B, detail::enabler_t>::type;

template<bool b1>
struct not_u : std::true_type {};

template<>
struct not_u<true> : std::false_type {};

template<bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true, bool b6 = true>
struct and_u : std::false_type {};

template<>
struct and_u<true, true, true, true, true, true> : std::true_type {};

template<bool b1, bool b2, bool b3 = false, bool b4 = false, bool b5 = false, bool b6 = false, bool b7 = false, bool b8 = false, bool b9 = false>
struct or_u : std::true_type {};

template<>
struct or_u<false, false, false, false, false, false, false, false, false> : std::false_type {};

template<template<typename...> class TT, typename T>
struct is_specialization_of : std::false_type {};

template<template<typename...> class TT, typename... Args>
struct is_specialization_of<TT, TT<Args...>> : std::true_type {};

//Variadic manipulations utilities

template<std::size_t N, typename... T>
struct nth_type {
    using type = typename std::tuple_element<N, std::tuple<T...>>::type;
};

template<typename... T>
struct first_type {
    using type = typename nth_type<0, T...>::type;
};

template<typename... T>
struct last_type {
    using type = typename nth_type<sizeof...(T)-1, T...>::type;
};

template<int I, typename T1, typename... T, enable_if_u<(I == 0)> = detail::dummy>
auto nth_value(T1&& t, T&&... /*args*/) -> decltype(std::forward<T1>(t)) {
    return std::forward<T1>(t);
}

template<int I, typename T1, typename... T, enable_if_u<(I > 0)> = detail::dummy>
auto nth_value(T1&& /*t*/, T&&... args)
        -> decltype(std::forward<typename nth_type<I, T1, T...>::type>(std::declval<typename nth_type<I, T1, T...>::type>())){
    return std::forward<typename nth_type<I, T1, T...>::type>(nth_value<I - 1>((std::forward<T>(args))...));
}

template<typename... T>
auto last_value(T&&... args){
    return std::forward<typename last_type<T...>::type>(nth_value<sizeof...(T) - 1>(args...));
}

template<typename... T>
auto first_value(T&&... args){
    return std::forward<typename first_type<T...>::type>(nth_value<0>(args...));
}

template<typename V, typename F, typename... S>
struct all_convertible_to  : std::integral_constant<bool, and_u<all_convertible_to<V, F>::value, all_convertible_to<V, S...>::value>::value> {};

template<typename V, typename F>
struct all_convertible_to<V, F> : std::integral_constant<bool, std::is_convertible<F, V>::value> {};

template<std::size_t I, std::size_t S, typename F, typename... T>
struct is_homogeneous_helper {
    template<std::size_t I1, std::size_t S1, typename Enable = void>
    struct helper_int : std::integral_constant<bool, and_u<std::is_same<F, typename nth_type<I1, T...>::type>::value, is_homogeneous_helper<I1+1, S1, F, T...>::value>::value> {};

    template<std::size_t I1, std::size_t S1>
    struct helper_int<I1, S1, enable_if_t<I1 == S1>> : std::integral_constant<bool, std::is_same<F, typename nth_type<I1, T...>::type>::value> {};

    static constexpr const auto value = helper_int<I, S>::value;
};

template<typename F, typename... T>
struct is_sub_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-2, F, T...>::value> {};

template<typename F, typename... T>
struct is_homogeneous : std::integral_constant<bool, is_homogeneous_helper<0, sizeof...(T)-1, F, T...>::value> {};

#endif<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2017 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP
#define MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP

#include <mapnik/json/positions_grammar_x3.hpp>
#include <mapnik/geometry/fusion_adapted.hpp>

namespace mapnik { namespace json { namespace grammar {

namespace x3 = boost::spirit::x3;
using x3::lit;
using x3::double_;
using x3::no_case;
using x3::omit;

// start rule
positions_grammar_type const positions("Positions");
// rules
x3::rule<class point_class, point> const point("Position");
x3::rule<class ring_class, ring> const ring("Ring");
x3::rule<class rings_class, rings> const rings("Rings");
x3::rule<class rings_array_class, rings_array> const rings_array("RingsArray");

auto const positions_def = rings_array | rings | ring | point ;
auto const point_def = lit('[') > double_ > lit(',') > double_ > omit[*(lit(',') > double_)] > lit(']');
auto const ring_def = lit('[') >> -(point % lit(',')) >> lit(']');
auto const rings_def = lit('[') >> (ring % lit(',') > lit(']'));
auto const rings_array_def = lit('[') >> (rings % lit(',') > lit(']'));

BOOST_SPIRIT_DEFINE(
    positions,
    point,
    ring,
    rings,
    rings_array
    );
}}}

namespace mapnik { namespace json {
grammar::positions_grammar_type const& positions_grammar()
{
    return grammar::positions;
}
}}

#endif // MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP
<commit_msg>use semantic actions to fix #3744 ( >= boost_1_65)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2017 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP
#define MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP

#include <mapnik/json/positions_grammar_x3.hpp>
#include <mapnik/geometry/fusion_adapted.hpp>

namespace mapnik { namespace json { namespace grammar {

namespace x3 = boost::spirit::x3;
using x3::lit;
using x3::double_;
using x3::no_case;
using x3::omit;

namespace {
auto assign_helper = [](auto const& ctx)
{
    _val(ctx) = std::move(_attr(ctx));
};
} // anonymous ns

// start rule
positions_grammar_type const positions("Positions");
// rules
x3::rule<class point_class, point> const point("Position");
x3::rule<class ring_class, ring> const ring("Ring");
x3::rule<class rings_class, rings> const rings("Rings");
x3::rule<class rings_array_class, rings_array> const rings_array("RingsArray");

auto const positions_def = rings_array[assign_helper] | rings[assign_helper] | ring[assign_helper] | point[assign_helper] ;
auto const point_def = lit('[') > double_ > lit(',') > double_ > omit[*(lit(',') > double_)] > lit(']');
auto const ring_def = lit('[') >> -(point % lit(',')) >> lit(']');
auto const rings_def = lit('[') >> (ring % lit(',') > lit(']'));
auto const rings_array_def = lit('[') >> (rings % lit(',') > lit(']'));

BOOST_SPIRIT_DEFINE(
    positions,
    point,
    ring,
    rings,
    rings_array
    );
}}}

namespace mapnik { namespace json {
grammar::positions_grammar_type const& positions_grammar()
{
    return grammar::positions;
}
}}

#endif // MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP
<|endoftext|>