<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <minizinc/optimize_constraints.hh>
#include <minizinc/eval_par.hh>
#include <minizinc/flatten_internal.hh>

namespace MiniZinc {

  void
  OptimizeRegistry::reg(const MiniZinc::ASTString& call, optimizer opt) {
    _m.insert(std::make_pair(call, opt));
  }

  OptimizeRegistry::ConstraintStatus
  OptimizeRegistry::process(EnvI& env, MiniZinc::Item* i, MiniZinc::Call* c, Expression*& rewrite) {
    ASTStringMap<optimizer>::t::iterator it = _m.find(c->id());
    if (it != _m.end()) {
      return it->second(env,i,c,rewrite);
    }
    return CS_NONE;
  }

  OptimizeRegistry&
  OptimizeRegistry::registry(void) {
    static OptimizeRegistry reg;
    return reg;
  }

  namespace Optimizers {

    OptimizeRegistry::ConstraintStatus o_linear(EnvI& env, Item* ii, Call* c, Expression*& rewrite) {
      ArrayLit* al_c = eval_array_lit(env,c->args()[0]);
      std::vector<IntVal> coeffs(al_c->v().size());
      for (unsigned int i=0; i<al_c->v().size(); i++) {
        coeffs[i] = eval_int(env,al_c->v()[i]);
      }
      ArrayLit* al_x = eval_array_lit(env,c->args()[1]);
      std::vector<KeepAlive> x(al_x->v().size());
      for (unsigned int i=0; i<al_x->v().size(); i++) {
        x[i] = al_x->v()[i];
      }
      IntVal d = 0;
      simplify_lin<IntLit>(coeffs, x, d);
      if (coeffs.size()==0) {
        bool failed;
        if (c->id()==constants().ids.int_.lin_le) {
          failed = (d > eval_int(env,c->args()[2]));
        } else if (c->id()==constants().ids.int_.lin_eq) {
          failed = (d != eval_int(env,c->args()[2]));
        } else {
          failed = (d == eval_int(env,c->args()[2]));
        }
        if (failed) {
          return OptimizeRegistry::CS_FAILED;
        } else {
          return OptimizeRegistry::CS_ENTAILED;
        }
      } else if (coeffs.size()==1 && (ii->isa<ConstraintI>() || ii->cast<VarDeclI>()->e()->ti()->domain()==constants().lit_true)) {
        VarDecl* vd = x[0]()->cast<Id>()->decl();
        IntSetVal* domain = vd->ti()->domain() ? eval_intset(env,vd->ti()->domain()) : NULL;
        if (c->id()==constants().ids.int_.lin_eq) {
          IntVal rd = eval_int(env,c->args()[2])-d;
          if (rd % coeffs[0] == 0) {
            IntVal nd = rd / coeffs[0];
            if (domain && !domain->contains(nd))
              return OptimizeRegistry::CS_FAILED;
            std::vector<Expression*> args(2);
            args[0] = x[0](); args[1] = IntLit::a(nd);
            Call* c = new Call(Location(), constants().ids.int_.eq, args);
            c->type(Type::varbool());
            rewrite = c;
            return OptimizeRegistry::CS_REWRITE;
          } else {
            return OptimizeRegistry::CS_FAILED;
          }
        } else if (c->id()==constants().ids.int_.lin_le) {
          IntVal ac = std::abs(coeffs[0]);
          IntVal rd = eval_int(env,c->args()[2])-d;
          IntVal ad = std::abs(rd);
          IntVal nd;
          if (ad % ac == 0) {
            nd = rd / coeffs[0];
          } else {
            double nd_d = static_cast<double>(ad.toInt()) / static_cast<double>(ac.toInt());
            if (coeffs[0] >= 0 && rd >= 0) {
              nd = static_cast<long long int>(std::floor(nd_d));
            } else if (rd >= 0) {
              nd = -static_cast<long long int>(std::floor(nd_d));
            } else if (coeffs[0] >= 0) {
              nd = -static_cast<long long int>(std::ceil(nd_d));
            } else {
              nd = static_cast<long long int>(std::ceil(nd_d));
            }
          }
          bool swapSign = coeffs[0] < 0;
          if (domain) {
            if (swapSign) {
              if (domain->max() < nd) {
                return OptimizeRegistry::CS_FAILED;
              }
              else if (domain->min() >= nd)
                return OptimizeRegistry::CS_ENTAILED;
            } else {
              if (domain->min() > nd) {
                return OptimizeRegistry::CS_FAILED;
              }
              else if (domain->max() <= nd)
                return OptimizeRegistry::CS_ENTAILED;
            }
            std::vector<Expression*> args(2);
            args[0] = x[0](); args[1] = IntLit::a(nd);
            if (swapSign)
              std::swap(args[0], args[1]);
            Call* nc = new Call(Location(), constants().ids.int_.le, args);
            nc->type(Type::varbool());
            rewrite = nc;
            return OptimizeRegistry::CS_REWRITE;
          }
        }
      } else if (c->id()==constants().ids.int_.lin_eq && coeffs.size()==2  &&
                 ((coeffs[0]==1 && coeffs[1]==-1) || (coeffs[1]==1 && coeffs[0]==-1)) && eval_int(env,c->args()[2])-d==0) {
        std::vector<Expression*> args(2);
        args[0] = x[0](); args[1] = x[1]();
        Call* c = new Call(Location(), constants().ids.int_.eq, args);
        rewrite = c;
        return OptimizeRegistry::CS_REWRITE;
      }
      if (coeffs.size() < al_c->v().size()) {
        std::vector<Expression*> coeffs_e(coeffs.size());
        std::vector<Expression*> x_e(coeffs.size());
        for (unsigned int i=0; i<coeffs.size(); i++) {
          coeffs_e[i] = IntLit::a(coeffs[i]);
          x_e[i] = x[i]();
        }
        ArrayLit* al_c_new = new ArrayLit(al_c->loc(),coeffs_e);
        al_c_new->type(Type::parint(1));
        ArrayLit* al_x_new = new ArrayLit(al_x->loc(),x_e);
        al_x_new->type(al_x->type());

        std::vector<Expression*> args(3);
        args[0] = al_c_new;
        args[1] = al_x_new;
        args[2] = IntLit::a(eval_int(env,c->args()[2])-d);
        Call* nc = new Call(Location(), c->id(), args);
        nc->type(Type::varbool());
        rewrite = nc;
        return OptimizeRegistry::CS_REWRITE;
      }
      return OptimizeRegistry::CS_OK;
    }

    OptimizeRegistry::ConstraintStatus o_lin_exp(EnvI& env, Item* i, Call* c, Expression*& rewrite) {
      if (c->type().isint()) {
        ArrayLit* al_c = eval_array_lit(env,c->args()[0]);
        std::vector<IntVal> coeffs(al_c->v().size());
        for (unsigned int i=0; i<al_c->v().size(); i++) {
          coeffs[i] = eval_int(env,al_c->v()[i]);
        }
        ArrayLit* al_x = eval_array_lit(env,c->args()[1]);
        std::vector<KeepAlive> x(al_x->v().size());
        for (unsigned int i=0; i<al_x->v().size(); i++) {
          x[i] = al_x->v()[i];
        }
        IntVal d = eval_int(env,c->args()[2]);
        simplify_lin<IntLit>(coeffs, x, d);
        if (coeffs.size()==0) {
          rewrite = IntLit::a(d);
          return OptimizeRegistry::CS_REWRITE;
        } else if (coeffs.size() < al_c->v().size()) {
          if (coeffs.size()==1 && coeffs[0]==1 && d==0) {
            rewrite = x[0]();
            return OptimizeRegistry::CS_REWRITE;
          }

          std::vector<Expression*> coeffs_e(coeffs.size());
          std::vector<Expression*> x_e(coeffs.size());
          for (unsigned int i=0; i<coeffs.size(); i++) {
            coeffs_e[i] = IntLit::a(coeffs[i]);
            x_e[i] = x[i]();
          }
          ArrayLit* al_c_new = new ArrayLit(al_c->loc(),coeffs_e);
          al_c_new->type(Type::parint(1));
          ArrayLit* al_x_new = new ArrayLit(al_x->loc(),x_e);
          al_x_new->type(al_x->type());

          std::vector<Expression*> args(3);
          args[0] = al_c_new;
          args[1] = al_x_new;
          args[2] = IntLit::a(d);
          Call* nc = new Call(Location(),c->id(),args);
          nc->type(c->type());
          rewrite = nc;
          return OptimizeRegistry::CS_REWRITE;
        }
      }
      return OptimizeRegistry::CS_OK;
    }

    OptimizeRegistry::ConstraintStatus o_element(EnvI& env, Item* i, Call* c, Expression*& rewrite) {
      if (c->args()[0]->isa<IntLit>()) {
        IntVal idx = eval_int(env,c->args()[0]);
        ArrayLit* al = eval_array_lit(env,c->args()[1]);
        if (idx < 1 || idx > al->v().size()) {
          return OptimizeRegistry::CS_FAILED;
        }
        Expression* result = al->v()[idx.toInt()-1];
        std::vector<Expression*> args(2);
        args[0] = result;
        args[1] = c->args()[2];
        Call* eq = new Call(Location(),constants().ids.int_.eq,args);
        rewrite = eq;
        return OptimizeRegistry::CS_REWRITE;
      }
      return OptimizeRegistry::CS_OK;
    }

    OptimizeRegistry::ConstraintStatus o_clause(EnvI& env, Item* i, Call* c, Expression*& rewrite) {
      std::vector<VarDecl*> pos;
      std::vector<VarDecl*> neg;
      ArrayLit* al_pos = eval_array_lit(env, c->args()[0]);
      for (unsigned int i=0; i<al_pos->v().size(); i++) {
        if (Id* ident = al_pos->v()[i]->dyn_cast<Id>()) {
          if (ident->decl()->ti()->domain()==NULL)
            pos.push_back(ident->decl());
        }
      }
      ArrayLit* al_neg = eval_array_lit(env, c->args()[1]);
      for (unsigned int i=0; i<al_neg->v().size(); i++) {
        if (Id* ident = al_neg->v()[i]->dyn_cast<Id>()) {
          if (ident->decl()->ti()->domain()==NULL)
            neg.push_back(ident->decl());
        }
      }
      bool subsumed = false;
      if (pos.size() > 0 && neg.size() > 0) {
        std::sort(pos.begin(),pos.end());
        std::sort(neg.begin(), neg.end());
        unsigned int ix=0;
        unsigned int iy=0;
        for (;;) {
          if (pos[ix]==neg[iy]) {
            subsumed = true;
            break;
          }
          if (pos[ix] < neg[iy]) {
            ix++;
          } else {
            iy++;
          }
          if (ix==pos.size() || iy==neg.size())
            break;
        }
      }
      if (subsumed) {
        return OptimizeRegistry::CS_ENTAILED;
      } else {
        return OptimizeRegistry::CS_OK;
      }
    }

    class Register {
    public:
      Register(void) {
        GCLock lock;
        Model* m = new Model;
        ASTString id_element("array_int_element");
        ASTString id_var_element("array_var_int_element");
        std::vector<Expression*> e;
        e.push_back(new StringLit(Location(),id_element));
        e.push_back(new StringLit(Location(),id_var_element));
        m->addItem(new ConstraintI(Location(),new ArrayLit(Location(),e)));
        OptimizeRegistry::registry().reg(constants().ids.int_.lin_eq, o_linear);
        OptimizeRegistry::registry().reg(constants().ids.int_.lin_le, o_linear);
        OptimizeRegistry::registry().reg(constants().ids.int_.lin_ne, o_linear);
        OptimizeRegistry::registry().reg(id_element, o_element);
        OptimizeRegistry::registry().reg(constants().ids.lin_exp, o_lin_exp);
        OptimizeRegistry::registry().reg(id_var_element, o_element);
        OptimizeRegistry::registry().reg(constants().ids.clause, o_clause);
        OptimizeRegistry::registry().reg(constants().ids.bool_clause, o_clause);
      }
    } _r;

  }

}<commit_msg>Keep annotations when rewriting linear constraints. Partly fixes #69.<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <minizinc/optimize_constraints.hh>
#include <minizinc/eval_par.hh>
#include <minizinc/flatten_internal.hh>

namespace MiniZinc {

  void
  OptimizeRegistry::reg(const MiniZinc::ASTString& call, optimizer opt) {
    _m.insert(std::make_pair(call, opt));
  }

  OptimizeRegistry::ConstraintStatus
  OptimizeRegistry::process(EnvI& env, MiniZinc::Item* i, MiniZinc::Call* c, Expression*& rewrite) {
    ASTStringMap<optimizer>::t::iterator it = _m.find(c->id());
    if (it != _m.end()) {
      return it->second(env,i,c,rewrite);
    }
    return CS_NONE;
  }

  OptimizeRegistry&
  OptimizeRegistry::registry(void) {
    static OptimizeRegistry reg;
    return reg;
  }

  namespace Optimizers {

    OptimizeRegistry::ConstraintStatus o_linear(EnvI& env, Item* ii, Call* c, Expression*& rewrite) {
      ArrayLit* al_c = eval_array_lit(env,c->args()[0]);
      std::vector<IntVal> coeffs(al_c->v().size());
      for (unsigned int i=0; i<al_c->v().size(); i++) {
        coeffs[i] = eval_int(env,al_c->v()[i]);
      }
      ArrayLit* al_x = eval_array_lit(env,c->args()[1]);
      std::vector<KeepAlive> x(al_x->v().size());
      for (unsigned int i=0; i<al_x->v().size(); i++) {
        x[i] = al_x->v()[i];
      }
      IntVal d = 0;
      simplify_lin<IntLit>(coeffs, x, d);
      if (coeffs.size()==0) {
        bool failed;
        if (c->id()==constants().ids.int_.lin_le) {
          failed = (d > eval_int(env,c->args()[2]));
        } else if (c->id()==constants().ids.int_.lin_eq) {
          failed = (d != eval_int(env,c->args()[2]));
        } else {
          failed = (d == eval_int(env,c->args()[2]));
        }
        if (failed) {
          return OptimizeRegistry::CS_FAILED;
        } else {
          return OptimizeRegistry::CS_ENTAILED;
        }
      } else if (coeffs.size()==1 && (ii->isa<ConstraintI>() || ii->cast<VarDeclI>()->e()->ti()->domain()==constants().lit_true)) {
        VarDecl* vd = x[0]()->cast<Id>()->decl();
        IntSetVal* domain = vd->ti()->domain() ? eval_intset(env,vd->ti()->domain()) : NULL;
        if (c->id()==constants().ids.int_.lin_eq) {
          IntVal rd = eval_int(env,c->args()[2])-d;
          if (rd % coeffs[0] == 0) {
            IntVal nd = rd / coeffs[0];
            if (domain && !domain->contains(nd))
              return OptimizeRegistry::CS_FAILED;
            std::vector<Expression*> args(2);
            args[0] = x[0](); args[1] = IntLit::a(nd);
            Call* c = new Call(Location(), constants().ids.int_.eq, args);
            c->type(Type::varbool());
            rewrite = c;
            return OptimizeRegistry::CS_REWRITE;
          } else {
            return OptimizeRegistry::CS_FAILED;
          }
        } else if (c->id()==constants().ids.int_.lin_le) {
          IntVal ac = std::abs(coeffs[0]);
          IntVal rd = eval_int(env,c->args()[2])-d;
          IntVal ad = std::abs(rd);
          IntVal nd;
          if (ad % ac == 0) {
            nd = rd / coeffs[0];
          } else {
            double nd_d = static_cast<double>(ad.toInt()) / static_cast<double>(ac.toInt());
            if (coeffs[0] >= 0 && rd >= 0) {
              nd = static_cast<long long int>(std::floor(nd_d));
            } else if (rd >= 0) {
              nd = -static_cast<long long int>(std::floor(nd_d));
            } else if (coeffs[0] >= 0) {
              nd = -static_cast<long long int>(std::ceil(nd_d));
            } else {
              nd = static_cast<long long int>(std::ceil(nd_d));
            }
          }
          bool swapSign = coeffs[0] < 0;
          if (domain) {
            if (swapSign) {
              if (domain->max() < nd) {
                return OptimizeRegistry::CS_FAILED;
              }
              else if (domain->min() >= nd)
                return OptimizeRegistry::CS_ENTAILED;
            } else {
              if (domain->min() > nd) {
                return OptimizeRegistry::CS_FAILED;
              }
              else if (domain->max() <= nd)
                return OptimizeRegistry::CS_ENTAILED;
            }
            std::vector<Expression*> args(2);
            args[0] = x[0](); args[1] = IntLit::a(nd);
            if (swapSign)
              std::swap(args[0], args[1]);
            Call* nc = new Call(Location(), constants().ids.int_.le, args);
            nc->type(Type::varbool());
            rewrite = nc;
            return OptimizeRegistry::CS_REWRITE;
          }
        }
      } else if (c->id()==constants().ids.int_.lin_eq && coeffs.size()==2  &&
                 ((coeffs[0]==1 && coeffs[1]==-1) || (coeffs[1]==1 && coeffs[0]==-1)) && eval_int(env,c->args()[2])-d==0) {
        std::vector<Expression*> args(2);
        args[0] = x[0](); args[1] = x[1]();
        Call* c = new Call(Location(), constants().ids.int_.eq, args);
        rewrite = c;
        return OptimizeRegistry::CS_REWRITE;
      }
      if (coeffs.size() < al_c->v().size()) {
        std::vector<Expression*> coeffs_e(coeffs.size());
        std::vector<Expression*> x_e(coeffs.size());
        for (unsigned int i=0; i<coeffs.size(); i++) {
          coeffs_e[i] = IntLit::a(coeffs[i]);
          x_e[i] = x[i]();
        }
        ArrayLit* al_c_new = new ArrayLit(al_c->loc(),coeffs_e);
        al_c_new->type(Type::parint(1));
        ArrayLit* al_x_new = new ArrayLit(al_x->loc(),x_e);
        al_x_new->type(al_x->type());

        std::vector<Expression*> args(3);
        args[0] = al_c_new;
        args[1] = al_x_new;
        args[2] = IntLit::a(eval_int(env,c->args()[2])-d);
        Call* nc = new Call(Location(), c->id(), args);
        nc->type(Type::varbool());
        for (ExpressionSetIter it = c->ann().begin(); it != c->ann().end(); ++it) {
          nc->addAnnotation(*it);
        }

        rewrite = nc;
        return OptimizeRegistry::CS_REWRITE;
      }
      return OptimizeRegistry::CS_OK;
    }

    OptimizeRegistry::ConstraintStatus o_lin_exp(EnvI& env, Item* i, Call* c, Expression*& rewrite) {
      if (c->type().isint()) {
        ArrayLit* al_c = eval_array_lit(env,c->args()[0]);
        std::vector<IntVal> coeffs(al_c->v().size());
        for (unsigned int i=0; i<al_c->v().size(); i++) {
          coeffs[i] = eval_int(env,al_c->v()[i]);
        }
        ArrayLit* al_x = eval_array_lit(env,c->args()[1]);
        std::vector<KeepAlive> x(al_x->v().size());
        for (unsigned int i=0; i<al_x->v().size(); i++) {
          x[i] = al_x->v()[i];
        }
        IntVal d = eval_int(env,c->args()[2]);
        simplify_lin<IntLit>(coeffs, x, d);
        if (coeffs.size()==0) {
          rewrite = IntLit::a(d);
          return OptimizeRegistry::CS_REWRITE;
        } else if (coeffs.size() < al_c->v().size()) {
          if (coeffs.size()==1 && coeffs[0]==1 && d==0) {
            rewrite = x[0]();
            return OptimizeRegistry::CS_REWRITE;
          }

          std::vector<Expression*> coeffs_e(coeffs.size());
          std::vector<Expression*> x_e(coeffs.size());
          for (unsigned int i=0; i<coeffs.size(); i++) {
            coeffs_e[i] = IntLit::a(coeffs[i]);
            x_e[i] = x[i]();
          }
          ArrayLit* al_c_new = new ArrayLit(al_c->loc(),coeffs_e);
          al_c_new->type(Type::parint(1));
          ArrayLit* al_x_new = new ArrayLit(al_x->loc(),x_e);
          al_x_new->type(al_x->type());

          std::vector<Expression*> args(3);
          args[0] = al_c_new;
          args[1] = al_x_new;
          args[2] = IntLit::a(d);
          Call* nc = new Call(Location(),c->id(),args);
          nc->type(c->type());
          for (ExpressionSetIter it = c->ann().begin(); it != c->ann().end(); ++it) {
            nc->addAnnotation(*it);
          }
          rewrite = nc;
          return OptimizeRegistry::CS_REWRITE;
        }
      }
      return OptimizeRegistry::CS_OK;
    }

    OptimizeRegistry::ConstraintStatus o_element(EnvI& env, Item* i, Call* c, Expression*& rewrite) {
      if (c->args()[0]->isa<IntLit>()) {
        IntVal idx = eval_int(env,c->args()[0]);
        ArrayLit* al = eval_array_lit(env,c->args()[1]);
        if (idx < 1 || idx > al->v().size()) {
          return OptimizeRegistry::CS_FAILED;
        }
        Expression* result = al->v()[idx.toInt()-1];
        std::vector<Expression*> args(2);
        args[0] = result;
        args[1] = c->args()[2];
        Call* eq = new Call(Location(),constants().ids.int_.eq,args);
        rewrite = eq;
        return OptimizeRegistry::CS_REWRITE;
      }
      return OptimizeRegistry::CS_OK;
    }

    OptimizeRegistry::ConstraintStatus o_clause(EnvI& env, Item* i, Call* c, Expression*& rewrite) {
      std::vector<VarDecl*> pos;
      std::vector<VarDecl*> neg;
      ArrayLit* al_pos = eval_array_lit(env, c->args()[0]);
      for (unsigned int i=0; i<al_pos->v().size(); i++) {
        if (Id* ident = al_pos->v()[i]->dyn_cast<Id>()) {
          if (ident->decl()->ti()->domain()==NULL)
            pos.push_back(ident->decl());
        }
      }
      ArrayLit* al_neg = eval_array_lit(env, c->args()[1]);
      for (unsigned int i=0; i<al_neg->v().size(); i++) {
        if (Id* ident = al_neg->v()[i]->dyn_cast<Id>()) {
          if (ident->decl()->ti()->domain()==NULL)
            neg.push_back(ident->decl());
        }
      }
      bool subsumed = false;
      if (pos.size() > 0 && neg.size() > 0) {
        std::sort(pos.begin(),pos.end());
        std::sort(neg.begin(), neg.end());
        unsigned int ix=0;
        unsigned int iy=0;
        for (;;) {
          if (pos[ix]==neg[iy]) {
            subsumed = true;
            break;
          }
          if (pos[ix] < neg[iy]) {
            ix++;
          } else {
            iy++;
          }
          if (ix==pos.size() || iy==neg.size())
            break;
        }
      }
      if (subsumed) {
        return OptimizeRegistry::CS_ENTAILED;
      } else {
        return OptimizeRegistry::CS_OK;
      }
    }

    class Register {
    public:
      Register(void) {
        GCLock lock;
        Model* m = new Model;
        ASTString id_element("array_int_element");
        ASTString id_var_element("array_var_int_element");
        std::vector<Expression*> e;
        e.push_back(new StringLit(Location(),id_element));
        e.push_back(new StringLit(Location(),id_var_element));
        m->addItem(new ConstraintI(Location(),new ArrayLit(Location(),e)));
        OptimizeRegistry::registry().reg(constants().ids.int_.lin_eq, o_linear);
        OptimizeRegistry::registry().reg(constants().ids.int_.lin_le, o_linear);
        OptimizeRegistry::registry().reg(constants().ids.int_.lin_ne, o_linear);
        OptimizeRegistry::registry().reg(id_element, o_element);
        OptimizeRegistry::registry().reg(constants().ids.lin_exp, o_lin_exp);
        OptimizeRegistry::registry().reg(id_var_element, o_element);
        OptimizeRegistry::registry().reg(constants().ids.clause, o_clause);
        OptimizeRegistry::registry().reg(constants().ids.bool_clause, o_clause);
      }
    } _r;

  }

}<|endoftext|>


<commit_before>#include "../t1/Foo.hpp"
#include "rice/Data_Type.hpp"

using namespace Rice;

extern "C"
void Init_t2()
{
  define_class<Foo>("Foo");
}

<commit_msg>Fixed implementation to not use define_class, which has the side effect of undefining the allocate function.<commit_after>#include "../t1/Foo.hpp"
#include "rice/Data_Type.hpp"

using namespace Rice;

extern "C"
void Init_t2()
{
  volatile Data_Type<Foo> foo;
}

<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2011.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : tests singleton dataset
// ***************************************************************************

// Boost.Test
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>
namespace data=boost::unit_test::data;

#include "test_datasets.hpp"

//____________________________________________________________________________//

int samples1[] = {1,2,3};
int index1 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_01, samples1 )
{
    BOOST_CHECKA( sample == samples1[index1++] );
}

//____________________________________________________________________________//

char const* samples2[] = {"qwerty","asdfg"};
int index2 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_02, samples2 )
{
    BOOST_CHECKA( sample == samples2[index2++] );
}

//____________________________________________________________________________//

int samples3[] = {7,9};
int index3 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_03, data::make(samples1)+samples3 )
{
    if( index3 < 3 )
        BOOST_CHECKA( sample == samples1[index3] );
    else
        BOOST_CHECKA( sample == samples3[index3-3] );

    ++index3;
}

//____________________________________________________________________________//

int index4 = 0;

BOOST_DATA_TEST_CASE_N( 2, test_case_interface_04, data::make(samples2)^samples3 )
{
    BOOST_CHECKA( sample0 == samples2[index4] );
    BOOST_CHECKA( sample1 == samples3[index4] );

    ++index4;
}

//____________________________________________________________________________//

int index5 = 0;

BOOST_DATA_TEST_CASE_N( 2, test_case_interface_05, data::make(samples1) * samples2 )
{
    BOOST_CHECKA( sample0 == samples1[index5/2] );
    BOOST_CHECKA( sample1 == samples2[index5%2] );

    ++index5;
}

//____________________________________________________________________________//

int index6 = 0;

BOOST_DATA_TEST_CASE_N( 3, test_case_interface_06, data::make(samples1) * samples2 * samples3 )
{
    BOOST_CHECKA( sample0 == samples1[index6/4] );
    BOOST_CHECKA( sample1 == samples2[(index6/2)%2] );
    BOOST_CHECKA( sample2 == samples3[index6%2] );

    ++index6;
}

//____________________________________________________________________________//

// EOF
<commit_msg>updated interface<commit_after>//  (C) Copyright Gennadiy Rozental 2011.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : tests singleton dataset
// ***************************************************************************

// Boost.Test
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>
namespace data=boost::unit_test::data;

#include "test_datasets.hpp"

//____________________________________________________________________________//

int samples1[] = {1,2,3};
int index1 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_01, samples1, sample )
{
    BOOST_CHECKA( sample == samples1[index1++] );
}

//____________________________________________________________________________//

char const* samples2[] = {"qwerty","asdfg"};
int index2 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_02, samples2, str )
{
    BOOST_CHECKA( str == samples2[index2++] );
}

//____________________________________________________________________________//

int samples3[] = {7,9};
int index3 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_03, data::make(samples1)+samples3, val )
{
    if( index3 < 3 )
        BOOST_CHECKA( val == samples1[index3] );
    else
        BOOST_CHECKA( val == samples3[index3-3] );

    ++index3;
}

//____________________________________________________________________________//

int index4 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_04, data::make(samples2)^samples3, str, intval )
{
    BOOST_CHECKA( str == samples2[index4] );
    BOOST_CHECKA( intval == samples3[index4] );

    ++index4;
}

//____________________________________________________________________________//

int index5 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_05, data::make(samples1) * samples2, sample0, sample1 )
{
    BOOST_CHECKA( sample0 == samples1[index5/2] );
    BOOST_CHECKA( sample1 == samples2[index5%2] );

    ++index5;
}

//____________________________________________________________________________//

int index6 = 0;

BOOST_DATA_TEST_CASE( test_case_interface_06, data::make(samples1) * samples2 * samples3, intval, str, val2 )
{
    BOOST_CHECKA( intval == samples1[index6/4] );
    BOOST_CHECKA( str == samples2[(index6/2)%2] );
    BOOST_CHECKA( val2 == samples3[index6%2] );

    ++index6;
}

//____________________________________________________________________________//

// EOF
<|endoftext|>


<commit_before>/* ******************************
 * Copyleft 2014 Verbalsaint
 * ******************************/

#ifndef _DISPOSITION_HPP
#define _DISPOSITION_HPP
#include "signal_include.hpp"

namespace vsd { namespace signal { namespace disposition {

/*
 * Used in child process
 * [in] sig : set sig to default then raise again causing child to stop/die
 */
void child_term_handler(int sig)
{
   SAVEERRNO

   ::signal(sig, SIG_DFL);
   ::raise(sig);

   GETERRNO
}

/*
 * Trigger process to read config/resetup process
 * [in] sig : must be SIGHUP
 */
void SIGHUP_daemon_handler(int sig)
{
   SAVEERRNO

   /* re-read config or else for daemon process */
   assert(sig == SIGHUP);

   UNUSED(sig);

   GETERRNO
}

void SIGINT_test_handler(int sig)
{
   SAVEERRNO

   assert(sig == SIGINT);
   /* test installed handler for [c-c] */
   using namespace std;
   cout << "in SIGINT handler : " << sig << endl;

   GETERRNO
}

}}} // vsd::signal::disposition

#endif // for #ifndef _DISPOSITION_HPP
<commit_msg>signal module<commit_after>/* ******************************
 * Copyleft 2014 Verbalsaint
 * ******************************/

#ifndef _DISPOSITION_HPP
#define _DISPOSITION_HPP
#include "signal_include.hpp"

namespace vsd { namespace signal { namespace disposition {

/*
 * Used in child process
 * [in] sig : set sig to default then raise again causing child to stop/die
 */
void child_term_handler(int sig)
{
   SAVEERRNO

   ::signal(sig, SIG_DFL);
   ::raise(sig);

   GETERRNO
}

/*
 * Trigger process to read config/resetup process
 * [in] sig : must be SIGHUP
 */
void SIGHUP_daemon_handler(int sig)
{
   SAVEERRNO

   /* re-read config or else for daemon process */
   assert(sig == SIGHUP);

 //  UNUSED(sig);

   GETERRNO
}

void SIGINT_test_handler(int sig)
{
   SAVEERRNO

   assert(sig == SIGINT);
   /* test installed handler for [c-c] */
   using namespace std;
   cout << "in SIGINT handler : " << sig << endl;

   GETERRNO
}

}}} // vsd::signal::disposition

#endif // for #ifndef _DISPOSITION_HPP
<|endoftext|>


<commit_before>/* LICENSE NOTICE
	Copyright (c) 2009, Frederick Emmott <mail@fredemmott.co.uk>

	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.

	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "OutputDevice.h"

#include "StandardOutputRecord.h"

namespace FastCgiQt
{
	OutputDevice::OutputDevice(quint16 requestId, QIODevice* socket, QObject* parent)
		:
			QIODevice(parent),
			m_haveSentData(false),
			m_requestId(requestId),
			m_socket(socket),
			m_mode(Streamed),
			m_sendHeaders(true)
	{
		open(QIODevice::WriteOnly);
		m_headers.insert("CONTENT-TYPE", "text/html");
		m_headers.insert("STATUS", "200 OK");
	}

	bool OutputDevice::isSendingHeadersEnabled() const
	{
		return m_sendHeaders;
	}

	void OutputDevice::setSendingHeadersEnabled(bool enabled)
	{
		Q_ASSERT(!haveSentData());
		m_sendHeaders = enabled;
	}

	void OutputDevice::setMode(Mode mode)
	{
		Q_ASSERT(!haveSentData());
		Q_ASSERT(mode != Buffered); // not yet supported
		m_mode = mode;
	}

	OutputDevice::Mode OutputDevice::mode() const
	{
		return m_mode;
	}

	QByteArray OutputDevice::buffer() const
	{
		return m_buffer;
	}

	qint64 OutputDevice::readData(char* data, qint64 maxSize)
	{
		Q_UNUSED(data);
		Q_UNUSED(maxSize);
		return -1;
	}

	bool OutputDevice::haveSentData() const
	{
		return m_haveSentData;
	}

	qint64 OutputDevice::writeData(const char* data, qint64 maxSize)
	{
		if(isSendingHeadersEnabled() && !m_haveSentData)
		{
			m_haveSentData = true;
			QString headerData;
			for(
				QHash<QString, QString>::ConstIterator it = m_headers.constBegin();
				it != m_headers.constEnd();
				++it
			)
			{
				headerData += QString("%1: %2\r\n").arg(it.key(), it.value());
			}
			headerData += "\r\n";
			QByteArray raw = headerData.toUtf8();
			writeData(raw.constData(), raw.length());
		}

		QByteArray record = StandardOutputRecord::create(
			m_requestId,
			QByteArray::fromRawData(data, maxSize)
		);
		qint64 wrote = m_socket->write(record.constData(), record.length());
		Q_ASSERT(wrote == record.length());
		if(wrote == record.length())
		{
			if(mode() == Logged)
			{
				m_buffer.append(QByteArray(data, maxSize));
			}
			return maxSize;
		}
		else
		{
			return -1;
		}
	}

	bool OutputDevice::setHeader(const QString& name, const QString& value)
	{
		if(m_haveSentData)
		{
			qCritical("Attempted to set a header after data has been sent.");
			return false;
		}

		m_headers[name.toUpper()] = value;
		return true;
	}
}
<commit_msg>default charset UTF-8<commit_after>/* LICENSE NOTICE
	Copyright (c) 2009, Frederick Emmott <mail@fredemmott.co.uk>

	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.

	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "OutputDevice.h"

#include "StandardOutputRecord.h"

namespace FastCgiQt
{
	OutputDevice::OutputDevice(quint16 requestId, QIODevice* socket, QObject* parent)
		:
			QIODevice(parent),
			m_haveSentData(false),
			m_requestId(requestId),
			m_socket(socket),
			m_mode(Streamed),
			m_sendHeaders(true)
	{
		open(QIODevice::WriteOnly);
		m_headers.insert("CONTENT-TYPE", "text/html; charset=UTF-8");
		m_headers.insert("STATUS", "200 OK");
	}

	bool OutputDevice::isSendingHeadersEnabled() const
	{
		return m_sendHeaders;
	}

	void OutputDevice::setSendingHeadersEnabled(bool enabled)
	{
		Q_ASSERT(!haveSentData());
		m_sendHeaders = enabled;
	}

	void OutputDevice::setMode(Mode mode)
	{
		Q_ASSERT(!haveSentData());
		Q_ASSERT(mode != Buffered); // not yet supported
		m_mode = mode;
	}

	OutputDevice::Mode OutputDevice::mode() const
	{
		return m_mode;
	}

	QByteArray OutputDevice::buffer() const
	{
		return m_buffer;
	}

	qint64 OutputDevice::readData(char* data, qint64 maxSize)
	{
		Q_UNUSED(data);
		Q_UNUSED(maxSize);
		return -1;
	}

	bool OutputDevice::haveSentData() const
	{
		return m_haveSentData;
	}

	qint64 OutputDevice::writeData(const char* data, qint64 maxSize)
	{
		if(isSendingHeadersEnabled() && !m_haveSentData)
		{
			m_haveSentData = true;
			QString headerData;
			for(
				QHash<QString, QString>::ConstIterator it = m_headers.constBegin();
				it != m_headers.constEnd();
				++it
			)
			{
				headerData += QString("%1: %2\r\n").arg(it.key(), it.value());
			}
			headerData += "\r\n";
			QByteArray raw = headerData.toUtf8();
			writeData(raw.constData(), raw.length());
		}

		QByteArray record = StandardOutputRecord::create(
			m_requestId,
			QByteArray::fromRawData(data, maxSize)
		);
		qint64 wrote = m_socket->write(record.constData(), record.length());
		Q_ASSERT(wrote == record.length());
		if(wrote == record.length())
		{
			if(mode() == Logged)
			{
				m_buffer.append(QByteArray(data, maxSize));
			}
			return maxSize;
		}
		else
		{
			return -1;
		}
	}

	bool OutputDevice::setHeader(const QString& name, const QString& value)
	{
		if(m_haveSentData)
		{
			qCritical("Attempted to set a header after data has been sent.");
			return false;
		}

		m_headers[name.toUpper()] = value;
		return true;
	}
}
<|endoftext|>


<commit_before>/*
 *  File:			    gpio_test.cpp
 *	Description:	Tests GPIO memory access using Broadcom GPIO Pin 17 on revision 2
 * 					      of the Raspberry Pi
 *	Programmer:		Thomas Newman
 *	Date:			    2013/07/30
 *
 *	Note:		      This program must run as root to successfully map the file.
 *					      This program is just to test the basic functionality. All it does
 *					      is turn one LED on.
 *
 *	The MIT License (MIT)
 *
 *	Copyright (c) 2013 Thomas Newman
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy of
 *	this software and associated documentation files (the "Software"), to deal in
 *	the Software without restriction, including without limitation the rights to
 *	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 *	the Software, and to permit persons to whom the Software is furnished to do so,
 *	subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in all
 *	copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 *	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 *	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 *	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 *	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>

#define GPIO_START_ADDRESS 0x20200000
#define BLOCK_SIZE (4*1024)
// Offsets are required to convert byte level addressing to 4 byte addressing
#define GPIO_FUNC_REG_1 0x04 / 4
#define GPIO_PIN_REG_1 0x1C / 4

int main()
{
	int mapped_registers;
	volatile uint32_t* register_address;

	// Map the GPIO memory
	mapped_registers = open("/dev/mem", O_RDWR | O_SYNC);
	register_address = (uint32_t*) mmap(NULL, BLOCK_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, mapped_registers, GPIO_START_ADDRESS);

	// Set the register to output mode
	*(register_address + GPIO_FUNC_REG_1) = *(register_address + GPIO_FUNC_REG_1) | 0x200000;

	// Set the output
	*(register_address + GPIO_PIN_REG_1) = *(register_address + GPIO_PIN_REG_1) | 0x20000;

	// Unmap the GPIO memory
	munmap((uint32_t*) register_address, BLOCK_SIZE);
	close(mapped_registers);

	return 0;
}
<commit_msg>Update gpio_test.cpp<commit_after>/*
 *	File:		gpio_test.cpp
 *	Description:	Tests GPIO memory access using Broadcom GPIO Pin 17 on revision 2
 *			of the Raspberry Pi
 *	Programmer:	Thomas Newman
 *	Date:		2013/07/30
 *
 *	Note:		This program must run as root to successfully map the file.
 *			This program is just to test the basic functionality. All it does
 *			is turn one LED on.
 *
 *	The MIT License (MIT)
 *
 *	Copyright (c) 2013 Thomas Newman
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy of
 *	this software and associated documentation files (the "Software"), to deal in
 *	the Software without restriction, including without limitation the rights to
 *	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 *	the Software, and to permit persons to whom the Software is furnished to do so,
 *	subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in all
 *	copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 *	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 *	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 *	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 *	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>

#define GPIO_START_ADDRESS 0x20200000
#define BLOCK_SIZE (4*1024)
// Offsets are required to convert byte level addressing to 4 byte addressing
#define GPIO_FUNC_REG_1 0x04 / 4
#define GPIO_PIN_REG_1 0x1C / 4

int main()
{
	int mapped_registers;
	volatile uint32_t* register_address;

	// Map the GPIO memory
	mapped_registers = open("/dev/mem", O_RDWR | O_SYNC);
	register_address = (uint32_t*) mmap(NULL, BLOCK_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, mapped_registers, GPIO_START_ADDRESS);

	// Set the register to output mode
	*(register_address + GPIO_FUNC_REG_1) = *(register_address + GPIO_FUNC_REG_1) | 0x200000;

	// Set the output
	*(register_address + GPIO_PIN_REG_1) = *(register_address + GPIO_PIN_REG_1) | 0x20000;

	// Unmap the GPIO memory
	munmap((uint32_t*) register_address, BLOCK_SIZE);
	close(mapped_registers);

	return 0;
}
<|endoftext|>


<commit_before>#include "test.h"
#include "pack.h"

#define EPSILON     0.0001

static void TestIeeeFloat(CuTest* tc)
{
    for (float i = 0.f; i < 1000.f; i += 0.001f) {
        Posit p(i);
        float r = p.getFloat();
        CuAssertTrue(tc, i == r);
    }
}

static void TestIeeeFloatPackDenormal(CuTest* tc)
{
    union {
        float f;
        uint32_t u;
    };

    for (u = 0x00000001; u < 0x00800000; u++) {
        CuAssertTrue(tc, f == pack_float(unpack_float(f)));
    }
}

static void TestIeeeDouble(CuTest* tc)
{
    for (double i = 0.0; i < 1000.0; i += 0.001) {
        Posit p(i);
        double r = p.getDouble();
        CuAssertTrue(tc, i - EPSILON < r && r < i + EPSILON);
    }
}

CuSuite* TestIeeeGetSuite(void)
{
    CuSuite* suite = CuSuiteNew();

    SUITE_ADD_TEST(suite, TestIeeeFloat);
    SUITE_ADD_TEST(suite, TestIeeeFloatPackDenormal);
    SUITE_ADD_TEST(suite, TestIeeeDouble);

    return suite;
}
<commit_msg>ieee_test: extend range to negative, use Posit32<commit_after>#include "test.h"
#include "pack.h"

#define EPSILON     0.0001

static void TestIeeeFloat(CuTest* tc)
{
    for (float i = -1000.f; i < 1000.f; i += 0.001f) {
        Posit32 p(i);
        float r = p.getFloat();
        CuAssertTrue(tc, i == r);
    }
}

static void TestIeeeFloatPackDenormal(CuTest* tc)
{
    union {
        float f;
        uint32_t u;
    };

    for (u = 0x00000001; u < 0x00800000; u++) {
        CuAssertTrue(tc, f == pack_float(unpack_float(f)));
    }
}

static void TestIeeeDouble(CuTest* tc)
{
    for (double i = -1000.0; i < 1000.0; i += 0.001) {
        Posit32 p(i);
        double r = p.getDouble();
        CuAssertTrue(tc, i - EPSILON < r && r < i + EPSILON);
    }
}

CuSuite* TestIeeeGetSuite(void)
{
    CuSuite* suite = CuSuiteNew();

    SUITE_ADD_TEST(suite, TestIeeeFloat);
    SUITE_ADD_TEST(suite, TestIeeeFloatPackDenormal);
    SUITE_ADD_TEST(suite, TestIeeeDouble);

    return suite;
}
<|endoftext|>


<commit_before>/**
 *  @file NASA9poly_test
 *       test problem for NASA 9 coefficient formulation
 */

#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <iomanip>

using namespace std;

/*****************************************************************/
/*****************************************************************/

#include "cantera/transport.h"
#include "cantera/IdealGasMix.h"
#include "cantera/transport/TransportFactory.h"

using namespace Cantera;

void printDbl(double val)
{
    if (fabs(val) < 5.0E-17) {
        cout << " nil";
    } else {
        cout << val;
    }
}

int main(int argc, char** argv)
{
#ifdef _MSC_VER
    _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
    try {
        //throw ArraySizeError("MadeUpFunction", 12, 22);

        IdealGasMix g("gasNASA9.xml", "gri30_mix");
        int nsp = g.nSpecies();
        double pres = 1.0E5;
        vector_fp Xset(nsp, 0.0);
        Xset[0] =  0.5 ;
        Xset[1] =  0.5;

        g.setState_TPX(1500.0, pres, DATA_PTR(Xset));

        vector_fp cp_R(nsp, 0.0);
        g.getCp_R(DATA_PTR(cp_R));

        vector_fp Gvalues(nsp, 0.0);

        printf("Comparisons of H2 calculated via several equivalent classes:\n");
        printf("1500 K and 1 atm:\n");
        printf("         NasaThermo   Nasa9   Nasa9_4reg \n");
        printf("  cp/R: %11.6g %11.6g %11.6g\n", cp_R[0], cp_R[1], cp_R[2]);

        vector_fp H_RT(nsp, 0.0);
        g.getEnthalpy_RT(DATA_PTR(H_RT));

        printf("  H/RT: %11.6g %11.6g %11.6g\n", H_RT[0], H_RT[1], H_RT[2]);

        vector_fp S_R(nsp, 0.0);
        g.getEntropy_R(DATA_PTR(S_R));
        printf("  S/R: %11.6g %11.6g %11.6g\n", S_R[0], S_R[1], S_R[2]);

        Transport* tran = newTransportMgr("Mix", &g);

        // MultiTransport * tranMix = dynamic_cast<MultiTransport *>(tran);
        printf("Viscoscity and thermal Cond vs. T\n");
        for (int k = 0; k < 40; k++) {
            double T1 = 400. + 200. * k;
            g.setState_TPX(T1, pres, DATA_PTR(Xset));
            g.getPureGibbs(DATA_PTR(Gvalues));
            //printf("     --  %13g %13.5g %13.5g %13.5g %13.5g \n",
            //    Gvalues[0],  Gvalues[1],  Gvalues[2],
            //    Gvalues[3],  Gvalues[4]);
            double visc = tran->viscosity();
            double cond = tran->thermalConductivity();
            printf("    %13g %13.5g %13.5g\n", T1, visc, cond);
        }

    } catch (CanteraError& err) {
        err.save();
//        cout << err.what() << endl;
        showErrors(cout);
        return 1;
    }

    return 0;
}
/***********************************************************/
<commit_msg>Cleaned up the implementation of the NASA9poly test<commit_after>/**
 *  @file NASA9poly_test
 *       test problem for NASA 9 coefficient formulation
 */
#include "cantera/transport.h"
#include "cantera/IdealGasMix.h"
#include "cantera/transport/TransportFactory.h"

#include <iostream>
#include <vector>
#include <memory>

using namespace Cantera;

int main(int argc, char** argv)
{
#ifdef _MSC_VER
    _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
    try {
        IdealGasMix g("gasNASA9.xml", "gri30_mix");
        size_t nsp = g.nSpecies();
        double pres = 1.0E5;
        vector_fp Xset(nsp, 0.0);
        Xset[0] = 0.5 ;
        Xset[1] = 0.5;

        g.setState_TPX(1500.0, pres, &Xset[0]);

        vector_fp cp_R(nsp, 0.0);
        vector_fp H_RT(nsp, 0.0);
        vector_fp S_R(nsp, 0.0);

        g.getEntropy_R(&S_R[0]);
        g.getCp_R(&cp_R[0]);
        g.getEnthalpy_RT(&H_RT[0]);

        printf("Comparisons of H2 calculated via several equivalent classes:\n");
        printf("1500 K and 1 atm:\n");
        printf("         NasaThermo   Nasa9   Nasa9_4reg \n");
        printf("  cp/R: %11.6g %11.6g %11.6g\n", cp_R[0], cp_R[1], cp_R[2]);
        printf("  H/RT: %11.6g %11.6g %11.6g\n", H_RT[0], H_RT[1], H_RT[2]);
        printf("  S/R: %11.6g %11.6g %11.6g\n", S_R[0], S_R[1], S_R[2]);

        std::auto_ptr<Transport> tran(newTransportMgr("Mix", &g));
        vector_fp Gvalues(nsp, 0.0);

        printf("Viscoscity and thermal Cond vs. T\n");
        for (int k = 0; k < 40; k++) {
            double T1 = 400. + 200. * k;
            g.setState_TPX(T1, pres, &Xset[0]);
            g.getPureGibbs(&Gvalues[0]);
            double visc = tran->viscosity();
            double cond = tran->thermalConductivity();
            printf("    %13g %13.5g %13.5g\n", T1, visc, cond);
        }
    } catch (CanteraError& err) {
        std::cout << err.what() << std::endl;
        return 1;
    }
    return 0;
}
<|endoftext|>


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

#include <stack>

#include "CImg.h"
#include "SOCEL.hpp"

// IChar

Socel::IChar::~IChar() {}

Socel::IChar::IChar() {}

Socel::IChar::IChar(const IChar &Ichar) {
  *this = Ichar;
}

Socel::IChar::IChar(const ScaleImage<uchar> &img,
		    uint posX, uint posY,
		    uint width, uint height)
{
  this->img = img;
  this->bound = Bound(posX, posY, width, height);
}

Socel::IChar::IChar(const ScaleImage<uchar> &img,
		    const Bound &bound)
{
  this->img = img;
  this->bound = bound;
}

const Socel::IChar &
Socel::IChar::operator=(const IChar &Ichar) {
  this->img = Ichar.img;
  this->bound = Ichar.bound;
  return (*this);
}

void
Socel::IChar::save(const std::string &path) {
  cimg_library::CImg<uint> img(this->img.getWidth(), this->img.getHeight());

  for (uint y = 0; y < this->img.getHeight(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1) {
      uint   color;
      uchar *ptn = (uchar *)(&color);

      ptn[0] = this->img.valueAt(x, y);
      ptn[1] = this->img.valueAt(x, y);
      ptn[2] = this->img.valueAt(x, y);
      ptn[3] = this->img.valueAt(x, y);
      img(x, y) = color;
    }
  img.save(path.c_str());
}

void
Socel::IChar::resize(uint width, uint height) {
  *this = this->getResize(width, height);
}

Socel::IChar
Socel::IChar::getResize(uint width, uint height) const {
  ScaleImage<uchar> img(width, height);

  for (uint y = 0; y < height; y += 1)
    for (uint x = 0; x < width; x += 1)
      {
	img.setValueAt(x, y,
		       this->img.valueAt(((double)(x) / (double)(width)) *
					 (double)(this->img.getWidth()),
					 ((double)(y) / (double)(height)) *
					 (double)(this->img.getHeight()))
		       );
      }
  return (Socel::IChar(img, this->bound));
}

const ScaleImage<uchar>		&Socel::IChar::getImg(const std::string &) const
{
  return (this->img);
}

const Bound			&Socel::IChar::getBound() const
{
  return (this->bound);
}
//SOCEL

Socel::~Socel() {}

Socel::Socel() {}

Socel::Socel(const std::string &s) {
  this->init(s);
}

bool
Socel::init(const std::string &s) {
  cimg_library::CImg<uint> img(s.c_str());

  this->img = ScaleImage<uchar>(img.width(), img.height());
  for (int y = 0; y < img.height(); y += 1)
    for (int x = 0; x < img.width(); x += 1)
      {
	uint	v;

	v = 0;
	v += img(x, y, 0, 0);
	v += img(x, y, 0, 1);
	v += img(x, y, 0, 2);
	v /= 3;
	this->img.setValueAt(x, y, v);
      }
  return (true);
}

typedef struct {
  uint x;
  uint y;
} t_ptn;

static void
verifMaxMinV(uint &max, uint &min, uint &v) {
  if (v > max)
    max = v;
  if (v < min)
    min = v;
}

Socel::IChar			Socel::getIChar(int x, int y, int width, int height) const
{
  ScaleImage<uchar>		img(width, height);

  for (int iy = 0; iy < height; iy += 1)
    for (int ix = 0; ix < width; ix += 1)
      img.setValueAt(ix, iy,
		     this->img.valueAt(x + ix, y + iy));
  return (IChar(img,
		x, y,
		width, height));

}

Socel::IChar			Socel::getIChar(uint x, uint y,
						ScaleImage<bool> &binImg,
						ScaleImage<bool> &testImg) const
{
  std::stack<t_ptn>		stack;
  uint				maxX = x;
  uint				minX = x;
  uint				maxY = y;
  uint				minY = y;

  stack.push({x, y});
  // std::cout << "start";
  while (stack.empty() == false) {
    t_ptn ptn = stack.top();

    x = ptn.x;
    y = ptn.y;
    // std::cout << "a";
    stack.pop();
    if (testImg.valueAt(x, y) == true)
      continue;
    testImg.setValueAt(x, y, true);
    if (binImg.valueAt(x, y) == true) {
      verifMaxMinV(maxX, minX, x);
      verifMaxMinV(maxY, minY, y);
      stack.push({x + 1, y});
      stack.push({x - 1, y});
      stack.push({x, y + 1});
      stack.push({x, y - 1});
    }
  }
  // std::cout << "end";
  // return
  {
    maxX += 2;
    minX -= 2;
    maxY += 2;
    minY -= 2;
    ScaleImage<uchar> img(maxX - minX, maxY - minY);

    for (uint y = minY; y < maxY; y += 1)
      for (uint x = minX; x < maxX; x += 1)
	img.setValueAt(x - minX, y - minY,
		       this->img.valueAt(x, y));
    return (IChar(img,
		  minX, minY,
		  maxX - minX, maxY - minY));
  }
}

void				Socel::sortList(std::list<Socel::IChar> &Alist) const
{
  std::list<Socel::IChar>	list;

  list = Alist;
}

unsigned int			Socel::getMeanY(const std::list<Socel::IChar> &list) const
{
  unsigned int			mean = 0;

  for (auto it = list.begin(); it != list.end(); it++)
    mean += (*it).getBound().getHeight();
  mean /= list.size();
  return (mean);
}

void				Socel::fixAccend(std::list<Socel::IChar> &list) const
{
  auto				it = list.begin();
  int			lim = (double)(this->getMeanY(list)) * 0.42;

 start:
  while (it != list.end())
    {
      Bound bound = (*it).getBound();

      for (auto itt = list.begin(); itt != list.end(); itt++)
	{
	  int	dY = Bound::getDistY(bound, (*itt).getBound());
	  int	dX = Bound::getDistX(bound, (*itt).getBound());

	  /*
	  std::cout << "y1 " << bound.getY() << " y2 "<< (*itt).getBound().getY() <<
	    " lim = " << lim << " test = " <<
	    Bound::getDistY(bound, (*itt).getBound()) << std::endl;*/
	  if (dX <= 0 && dY <= lim && dY > 0)
	    {
	      int maxX = bound.getX() + bound.getWidth();
	      int minX = bound.getX();
	      int maxY = bound.getY() + bound.getHeight();
	      int minY = bound.getY();
	      bound = (*itt).getBound();

	      if (maxX < bound.getX() + bound.getWidth())
		maxX = bound.getX() + bound.getWidth();
	      if (minX > bound.getX())
		minX = bound.getX();
	      if (maxY < bound.getY() + bound.getHeight())
		maxY = bound.getY() + bound.getHeight();
	      if (minY > bound.getY())
		minY = bound.getY();

	      (*itt) = getIChar(minX, minY, maxX - minX, maxY - minY);
	      it = list.erase(it);
	      goto start;
	    }
	}
      it++;
    }
}

std::list<Socel::IChar>		Socel::getChar(uint CWidth, uint CHeight) const
{
  ScaleImage<bool>		binImg(this->img.getWidth(), this->img.getHeight());
  ScaleImage<bool>		testImg(this->img.getWidth(), this->img.getHeight());
  std::list<Socel::IChar>	list;

  // init
  for (uint y = 0; y < this->img.getWidth(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1)
      {
	testImg.setValueAt(x, y, false);
	binImg.setValueAt(x, y,
			  this->img.valueAt(x, y) <= 85 ? true : false);
      }
  //iterate
  for (uint y = 0; y < this->img.getWidth(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1) {
      if (testImg.valueAt(x, y) == true)
        continue;
      if (binImg.valueAt(x, y) == true) {
        Socel::IChar Ichar = this->getIChar(x, y, binImg, testImg);
        list.push_back(Ichar.getResize(CWidth, CHeight));
      }
    }
  this->fixAccend(list);
  this->sortList(list);
  return (list);
}

const std::string	&Socel::getPathName() const
{
  return (this->pathName);
}

const ScaleImage<uchar> &
Socel::getImg() const {
  return (this->img);
}

void				Socel::save(const std::string &path)
{
  cimg_library::CImg<uint>	img(this->img.getWidth(), this->img.getHeight());

  for (uint y = 0; y < this->img.getHeight(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1)
      {
	uint	color;
	uchar	*ptn = (uchar*)(&color);

	ptn[0] = this->img.valueAt(x, y);
	ptn[1] = this->img.valueAt(x, y);
	ptn[2] = this->img.valueAt(x, y);
	ptn[3] = this->img.valueAt(x, y);
	img(x, y) = color;
      }
  img.save(path.c_str());
}
<commit_msg>fix accent marge<commit_after>//
// MIT License
//
// Copyright (c) 2016 Lucas Mayol
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//

#include <stack>

#include "CImg.h"
#include "SOCEL.hpp"

// IChar

Socel::IChar::~IChar() {}

Socel::IChar::IChar() {}

Socel::IChar::IChar(const IChar &Ichar) {
  *this = Ichar;
}

Socel::IChar::IChar(const ScaleImage<uchar> &img,
		    uint posX, uint posY,
		    uint width, uint height)
{
  this->img = img;
  this->bound = Bound(posX, posY, width, height);
}

Socel::IChar::IChar(const ScaleImage<uchar> &img,
		    const Bound &bound)
{
  this->img = img;
  this->bound = bound;
}

const Socel::IChar &
Socel::IChar::operator=(const IChar &Ichar) {
  this->img = Ichar.img;
  this->bound = Ichar.bound;
  return (*this);
}

void
Socel::IChar::save(const std::string &path) {
  cimg_library::CImg<uint> img(this->img.getWidth(), this->img.getHeight());

  for (uint y = 0; y < this->img.getHeight(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1) {
      uint   color;
      uchar *ptn = (uchar *)(&color);

      ptn[0] = this->img.valueAt(x, y);
      ptn[1] = this->img.valueAt(x, y);
      ptn[2] = this->img.valueAt(x, y);
      ptn[3] = this->img.valueAt(x, y);
      img(x, y) = color;
    }
  img.save(path.c_str());
}

void
Socel::IChar::resize(uint width, uint height) {
  *this = this->getResize(width, height);
}

Socel::IChar
Socel::IChar::getResize(uint width, uint height) const {
  ScaleImage<uchar> img(width, height);

  for (uint y = 0; y < height; y += 1)
    for (uint x = 0; x < width; x += 1)
      {
	img.setValueAt(x, y,
		       this->img.valueAt(((double)(x) / (double)(width)) *
					 (double)(this->img.getWidth()),
					 ((double)(y) / (double)(height)) *
					 (double)(this->img.getHeight()))
		       );
      }
  return (Socel::IChar(img, this->bound));
}

const ScaleImage<uchar>		&Socel::IChar::getImg(const std::string &) const
{
  return (this->img);
}

const Bound			&Socel::IChar::getBound() const
{
  return (this->bound);
}
//SOCEL

Socel::~Socel() {}

Socel::Socel() {}

Socel::Socel(const std::string &s) {
  this->init(s);
}

bool
Socel::init(const std::string &s) {
  cimg_library::CImg<uint> img(s.c_str());

  this->img = ScaleImage<uchar>(img.width(), img.height());
  for (int y = 0; y < img.height(); y += 1)
    for (int x = 0; x < img.width(); x += 1)
      {
	uint	v;

	v = 0;
	v += img(x, y, 0, 0);
	v += img(x, y, 0, 1);
	v += img(x, y, 0, 2);
	v /= 3;
	this->img.setValueAt(x, y, v);
      }
  return (true);
}

typedef struct {
  uint x;
  uint y;
} t_ptn;

static void
verifMaxMinV(uint &max, uint &min, uint &v) {
  if (v > max)
    max = v;
  if (v < min)
    min = v;
}

Socel::IChar			Socel::getIChar(int x, int y, int width, int height) const
{
  ScaleImage<uchar>		img(width, height);

  for (int iy = 0; iy < height; iy += 1)
    for (int ix = 0; ix < width; ix += 1)
      img.setValueAt(ix, iy,
		     this->img.valueAt(x + ix, y + iy));
  return (IChar(img,
		x, y,
		width, height));

}

Socel::IChar			Socel::getIChar(uint x, uint y,
						ScaleImage<bool> &binImg,
						ScaleImage<bool> &testImg) const
{
  std::stack<t_ptn>		stack;
  uint				maxX = x;
  uint				minX = x;
  uint				maxY = y;
  uint				minY = y;

  stack.push({x, y});
  // std::cout << "start";
  while (stack.empty() == false) {
    t_ptn ptn = stack.top();

    x = ptn.x;
    y = ptn.y;
    // std::cout << "a";
    stack.pop();
    if (testImg.valueAt(x, y) == true)
      continue;
    testImg.setValueAt(x, y, true);
    if (binImg.valueAt(x, y) == true) {
      verifMaxMinV(maxX, minX, x);
      verifMaxMinV(maxY, minY, y);
      stack.push({x + 1, y});
      stack.push({x - 1, y});
      stack.push({x, y + 1});
      stack.push({x, y - 1});
    }
  }
  // std::cout << "end";
  // return
  {
    maxX += 2;
    minX -= 2;
    maxY += 2;
    minY -= 2;
    ScaleImage<uchar> img(maxX - minX, maxY - minY);

    for (uint y = minY; y < maxY; y += 1)
      for (uint x = minX; x < maxX; x += 1)
	img.setValueAt(x - minX, y - minY,
		       this->img.valueAt(x, y));
    return (IChar(img,
		  minX, minY,
		  maxX - minX, maxY - minY));
  }
}

void				Socel::sortList(std::list<Socel::IChar> &Alist) const
{
  std::list<Socel::IChar>	list;

  list = Alist;
}

unsigned int			Socel::getMeanY(const std::list<Socel::IChar> &list) const
{
  unsigned int			mean = 0;

  for (auto it = list.begin(); it != list.end(); it++)
    mean += (*it).getBound().getHeight();
  mean /= list.size();
  return (mean);
}

void				Socel::fixAccend(std::list<Socel::IChar> &list) const
{
  auto				it = list.begin();
  int			lim = (double)(this->getMeanY(list)) * 0.25;

 start:
  while (it != list.end())
    {
      Bound bound = (*it).getBound();

      for (auto itt = list.begin(); itt != list.end(); itt++)
	{
	  int	dY = Bound::getDistY(bound, (*itt).getBound());
	  int	dX = Bound::getDistX(bound, (*itt).getBound());

	  /*
	  std::cout << "y1 " << bound.getY() << " y2 "<< (*itt).getBound().getY() <<
	    " lim = " << lim << " test = " <<
	    Bound::getDistY(bound, (*itt).getBound()) << std::endl;*/
	  if (dX <= 0 && dY <= lim && dY > 0)
	    {
	      int maxX = bound.getX() + bound.getWidth();
	      int minX = bound.getX();
	      int maxY = bound.getY() + bound.getHeight();
	      int minY = bound.getY();
	      bound = (*itt).getBound();

	      if (maxX < bound.getX() + bound.getWidth())
		maxX = bound.getX() + bound.getWidth();
	      if (minX > bound.getX())
		minX = bound.getX();
	      if (maxY < bound.getY() + bound.getHeight())
		maxY = bound.getY() + bound.getHeight();
	      if (minY > bound.getY())
		minY = bound.getY();

	      (*itt) = getIChar(minX, minY, maxX - minX, maxY - minY);
	      it = list.erase(it);
	      goto start;
	    }
	}
      it++;
    }
}

std::list<Socel::IChar>		Socel::getChar(uint CWidth, uint CHeight) const
{
  ScaleImage<bool>		binImg(this->img.getWidth(), this->img.getHeight());
  ScaleImage<bool>		testImg(this->img.getWidth(), this->img.getHeight());
  std::list<Socel::IChar>	list;

  // init
  for (uint y = 0; y < this->img.getWidth(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1)
      {
	testImg.setValueAt(x, y, false);
	binImg.setValueAt(x, y,
			  this->img.valueAt(x, y) <= 85 ? true : false);
      }
  //iterate
  for (uint y = 0; y < this->img.getWidth(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1) {
      if (testImg.valueAt(x, y) == true)
        continue;
      if (binImg.valueAt(x, y) == true) {
        Socel::IChar Ichar = this->getIChar(x, y, binImg, testImg);
        list.push_back(Ichar.getResize(CWidth, CHeight));
      }
    }
  this->fixAccend(list);
  this->sortList(list);
  return (list);
}

const std::string	&Socel::getPathName() const
{
  return (this->pathName);
}

const ScaleImage<uchar> &
Socel::getImg() const {
  return (this->img);
}

void				Socel::save(const std::string &path)
{
  cimg_library::CImg<uint>	img(this->img.getWidth(), this->img.getHeight());

  for (uint y = 0; y < this->img.getHeight(); y += 1)
    for (uint x = 0; x < this->img.getWidth(); x += 1)
      {
	uint	color;
	uchar	*ptn = (uchar*)(&color);

	ptn[0] = this->img.valueAt(x, y);
	ptn[1] = this->img.valueAt(x, y);
	ptn[2] = this->img.valueAt(x, y);
	ptn[3] = this->img.valueAt(x, y);
	img(x, y) = color;
      }
  img.save(path.c_str());
}
<|endoftext|>


<commit_before>#ifndef DKN_HPP_
#define DKN_HPP_
#include "basics.hpp"

#include <vector>
#include <flann/flann.hpp>

template <typename Distance>
std::vector<typename Distance::ResultType> DKN(
        flann::Index<Distance> &index,
        const flann::Matrix<typename Distance::ElementType> &query,
        int k = 3,
        const flann::SearchParams &search_params = flann::SearchParams())
{   /* Get the distances to the k-th nearest neighbor of each element in query
     * using the passed index and search params.
     */
    using std::vector;
    using flann::Matrix;

    typedef typename Distance::ResultType DistanceType;

    // matrices to store the results
    Matrix<int> indices(new int[query.rows*k], query.rows, k);
    Matrix<DistanceType> dists(new float[query.rows*k], query.rows, k);

    // build the index if necessary
    index.buildIndex();

    // search!
    index.knnSearch(query, indices, dists, k, search_params);

    // get out just the results we want
    vector<DistanceType> dkn;
    dkn.reserve(query.rows);
    for (size_t i = 0; i < query.rows; i++) {
        dkn.push_back(query[i][k]);
    }

    delete[] indices.ptr();
    delete[] dists.ptr();

    return dkn;
}

#endif
<commit_msg>dkn oops<commit_after>#ifndef DKN_HPP_
#define DKN_HPP_
#include "basics.hpp"

#include <vector>
#include <flann/flann.hpp>

template <typename Distance>
std::vector<typename Distance::ResultType> DKN(
        flann::Index<Distance> &index,
        const flann::Matrix<typename Distance::ElementType> &query,
        int k = 3,
        const flann::SearchParams &search_params = flann::SearchParams())
{   /* Get the distances to the k-th nearest neighbor of each element in query
     * using the passed index and search params.
     */
    using std::vector;
    using flann::Matrix;

    typedef typename Distance::ResultType DistanceType;

    // matrices to store the results
    Matrix<int> indices(new int[query.rows*k], query.rows, k);
    Matrix<DistanceType> dists(new DistanceType[query.rows*k], query.rows, k);

    // build the index if necessary
    index.buildIndex();

    // search!
    index.knnSearch(query, indices, dists, k, search_params);

    // get out just the results we want
    vector<DistanceType> dkn;
    dkn.reserve(query.rows);
    for (size_t i = 0; i < query.rows; i++) {
        dkn.push_back(dists[i][k-1]);
    }

    delete[] indices.ptr();
    delete[] dists.ptr();

    return dkn;
}

#endif
<|endoftext|>


<commit_before>#include "testsettings.hpp"
#ifdef TEST_FILE

#include <sstream>
#include <ostream>

#include <tightdb/util/file.hpp>

#include "test.hpp"
#include "crypt_key.hpp"

using namespace std;
using namespace tightdb::util;

// Test independence and thread-safety
// -----------------------------------
//
// All tests must be thread safe and independent of each other. This
// is required because it allows for both shuffling of the execution
// order and for parallelized testing.
//
// In particular, avoid using std::rand() since it is not guaranteed
// to be thread safe. Instead use the API offered in
// `test/util/random.hpp`.
//
// All files created in tests must use the TEST_PATH macro (or one of
// its friends) to obtain a suitable file system path. See
// `test/util/test_path.hpp`.
//
//
// Debugging and the ONLY() macro
// ------------------------------
//
// A simple way of disabling all tests except one called `Foo`, is to
// replace TEST(Foo) with ONLY(Foo) and then recompile and rerun the
// test suite. Note that you can also use filtering by setting the
// environment varible `UNITTEST_FILTER`. See `README.md` for more on
// this.
//
// Another way to debug a particular test, is to copy that test into
// `experiments/testcase.cpp` and then run `sh build.sh
// check-testcase` (or one of its friends) from the command line.

TEST(File_ExistsAndRemove)
{
    TEST_PATH(path);
    File(path, File::mode_Write);
    CHECK(File::exists(path));
    CHECK(File::try_remove(path));
    CHECK(!File::exists(path));
    CHECK(!File::try_remove(path));
}

TEST(File_IsSame)
{
    TEST_PATH(path_1);
    TEST_PATH(path_2);
    {
        File f1(path_1, File::mode_Write);
        File f2(path_1, File::mode_Read);
        File f3(path_2, File::mode_Write);

        CHECK(f1.is_same_file(f1));
        CHECK(f1.is_same_file(f2));
        CHECK(!f1.is_same_file(f3));
        CHECK(!f2.is_same_file(f3));
    }
}

TEST(File_Streambuf)
{
    TEST_PATH(path);
    {
        File f(path, File::mode_Write);
        File::Streambuf b(&f);
        ostream out(&b);
        out << "Line " << 1 << endl;
        out << "Line " << 2 << endl;
    }
    {
        File f(path, File::mode_Read);
        char buffer[256];
        size_t n = f.read(buffer);
        string s_1(buffer, buffer+n);
        ostringstream out;
        out << "Line " << 1 << endl;
        out << "Line " << 2 << endl;
        string s_2 = out.str();
        CHECK(s_1 == s_2);
    }
}

TEST(File_Map)
{
    TEST_PATH(path);
    const char data[4096] = "12345678901234567890";
    size_t len = strlen(data);
    {
        File f(path, File::mode_Write);
        f.set_encryption_key(crypt_key(true));
        f.resize(len);

        File::Map<char> map(f, File::access_ReadWrite, len);
        memcpy(map.get_addr(), data, len);
    }
    {
        File f(path, File::mode_Read);
        f.set_encryption_key(crypt_key(true));
        File::Map<char> map(f, File::access_ReadOnly, len);
        CHECK(memcmp(map.get_addr(), data, len) == 0);
    }
}

TEST(File_MapMultiplePages)
{
    // two blocks of IV tables
    const size_t count = 4096 / sizeof(size_t) * 256 * 2;

    TEST_PATH(path);
    {
        File f(path, File::mode_Write);
        f.set_encryption_key(crypt_key(true));
        f.resize(count * sizeof(size_t));

        File::Map<size_t> map(f, File::access_ReadWrite, count * sizeof(size_t));
        for (size_t i = 0; i < count; ++i)
            map.get_addr()[i] = i;
    }
    {
        File f(path, File::mode_Read);
        f.set_encryption_key(crypt_key(true));
        File::Map<size_t> map(f, File::access_ReadOnly, count * sizeof(size_t));
        for (size_t i = 0; i < count; ++i) {
            CHECK_EQUAL(map.get_addr()[i], i);
            if (map.get_addr()[i] != i)
                return;
          }
    }
}

TEST(File_ReaderAndWriter)
{
    const size_t count = 4096 / sizeof(size_t) * 256 * 2;

    TEST_PATH(path);

    File writer(path, File::mode_Write);
    writer.set_encryption_key(crypt_key(true));
    writer.resize(count * sizeof(size_t));

    File reader(path, File::mode_Read);
    reader.set_encryption_key(crypt_key(true));
    CHECK_EQUAL(writer.get_size(), reader.get_size());

    File::Map<size_t> write(writer, File::access_ReadWrite, count * sizeof(size_t));
    File::Map<size_t> read(reader, File::access_ReadOnly, count * sizeof(size_t));

    for (size_t i = 0; i < count; i += 100) {
        write.get_addr()[i] = i;
        CHECK_EQUAL(read.get_addr()[i], i);
        if (read.get_addr()[i] != i)
            return;
    }
}

TEST(File_MultipleWriters)
{
    const size_t count = 4096 / sizeof(size_t) * 256 * 2;

    TEST_PATH(path);

    {
        File w1(path, File::mode_Write);
        w1.set_encryption_key(crypt_key(true));
        w1.resize(count * sizeof(size_t));

        File w2(path, File::mode_Write);
        w2.set_encryption_key(crypt_key(true));
        w2.resize(count * sizeof(size_t));

        File::Map<size_t> map1(w1, File::access_ReadWrite, count * sizeof(size_t));
        File::Map<size_t> map2(w2, File::access_ReadWrite, count * sizeof(size_t));

        for (size_t i = 0; i < count; i += 100) {
            ++map1.get_addr()[i];
            ++map2.get_addr()[i];
        }
    }

    File reader(path, File::mode_Read);
    reader.set_encryption_key(crypt_key(true));

    File::Map<size_t> read(reader, File::access_ReadOnly, count * sizeof(size_t));

    for (size_t i = 0; i < count; i += 100) {
        CHECK_EQUAL(read.get_addr()[i], 2);
        if (read.get_addr()[i] != 2)
            return;
    }
}

TEST(File_SetEncryptionKey)
{
    TEST_PATH(path);
    File f(path, File::mode_Write);
    const char key[64] = {0};

#ifdef TIGHTDB_ENABLE_ENCRYPTION
    f.set_encryption_key(key); // should not throw
#else
    CHECK_THROW(f.set_encryption_key(key), std::runtime_error);
#endif
}

TEST(File_ReadWrite)
{
    TEST_PATH(path);
    File f(path, File::mode_Write);
    f.set_encryption_key(crypt_key(true));
    f.resize(100);

    for (char i = 0; i < 100; ++i)
        f.write(&i, 1);
    f.seek(0);
    for (char i = 0; i < 100; ++i) {
        char read;
        f.read(&read, 1);
        CHECK_EQUAL(i, read);
    }
}

TEST(File_Resize)
{
    TEST_PATH(path);
    File f(path, File::mode_Write);
    f.set_encryption_key(crypt_key(true));

    f.resize(8192);
    CHECK_EQUAL(8192, f.get_size());
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 8192);
        for (int i = 0; i < 8192; ++i)
            m.get_addr()[i] = static_cast<unsigned char>(i);
        m.sync();
        for (int i = 0; i < 8192; ++i)
            m.get_addr()[i] = static_cast<unsigned char>(i);
    }

    f.resize(4096);
    CHECK_EQUAL(4096, f.get_size());
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 4096);
        for (int i = 0; i < 4096; ++i) {
            CHECK_EQUAL(static_cast<unsigned char>(i), m.get_addr()[i]);
            if (static_cast<unsigned char>(i) != m.get_addr()[i])
                return;
        }
    }

    f.resize(8192);
    CHECK_EQUAL(8192, f.get_size());
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 8192);
        for (int i = 0; i < 8192; ++i)
            m.get_addr()[i] = static_cast<unsigned char>(i);
    }
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 8192);
        for (int i = 0; i < 8192; ++i) {
            CHECK_EQUAL(static_cast<unsigned char>(i), m.get_addr()[i]);
            if (static_cast<unsigned char>(i) != m.get_addr()[i])
                return;
        }
    }
}

#endif // TEST_FILE
<commit_msg>Add explanatory comment<commit_after>#include "testsettings.hpp"
#ifdef TEST_FILE

#include <sstream>
#include <ostream>

#include <tightdb/util/file.hpp>

#include "test.hpp"
#include "crypt_key.hpp"

using namespace std;
using namespace tightdb::util;

// Test independence and thread-safety
// -----------------------------------
//
// All tests must be thread safe and independent of each other. This
// is required because it allows for both shuffling of the execution
// order and for parallelized testing.
//
// In particular, avoid using std::rand() since it is not guaranteed
// to be thread safe. Instead use the API offered in
// `test/util/random.hpp`.
//
// All files created in tests must use the TEST_PATH macro (or one of
// its friends) to obtain a suitable file system path. See
// `test/util/test_path.hpp`.
//
//
// Debugging and the ONLY() macro
// ------------------------------
//
// A simple way of disabling all tests except one called `Foo`, is to
// replace TEST(Foo) with ONLY(Foo) and then recompile and rerun the
// test suite. Note that you can also use filtering by setting the
// environment varible `UNITTEST_FILTER`. See `README.md` for more on
// this.
//
// Another way to debug a particular test, is to copy that test into
// `experiments/testcase.cpp` and then run `sh build.sh
// check-testcase` (or one of its friends) from the command line.

TEST(File_ExistsAndRemove)
{
    TEST_PATH(path);
    File(path, File::mode_Write);
    CHECK(File::exists(path));
    CHECK(File::try_remove(path));
    CHECK(!File::exists(path));
    CHECK(!File::try_remove(path));
}

TEST(File_IsSame)
{
    TEST_PATH(path_1);
    TEST_PATH(path_2);
    {
        File f1(path_1, File::mode_Write);
        File f2(path_1, File::mode_Read);
        File f3(path_2, File::mode_Write);

        CHECK(f1.is_same_file(f1));
        CHECK(f1.is_same_file(f2));
        CHECK(!f1.is_same_file(f3));
        CHECK(!f2.is_same_file(f3));
    }
}

TEST(File_Streambuf)
{
    TEST_PATH(path);
    {
        File f(path, File::mode_Write);
        File::Streambuf b(&f);
        ostream out(&b);
        out << "Line " << 1 << endl;
        out << "Line " << 2 << endl;
    }
    {
        File f(path, File::mode_Read);
        char buffer[256];
        size_t n = f.read(buffer);
        string s_1(buffer, buffer+n);
        ostringstream out;
        out << "Line " << 1 << endl;
        out << "Line " << 2 << endl;
        string s_2 = out.str();
        CHECK(s_1 == s_2);
    }
}

TEST(File_Map)
{
    TEST_PATH(path);
    const char data[4096] = "12345678901234567890";
    size_t len = strlen(data);
    {
        File f(path, File::mode_Write);
        f.set_encryption_key(crypt_key(true));
        f.resize(len);

        File::Map<char> map(f, File::access_ReadWrite, len);
        memcpy(map.get_addr(), data, len);
    }
    {
        File f(path, File::mode_Read);
        f.set_encryption_key(crypt_key(true));
        File::Map<char> map(f, File::access_ReadOnly, len);
        CHECK(memcmp(map.get_addr(), data, len) == 0);
    }
}

TEST(File_MapMultiplePages)
{
    // two blocks of IV tables
    const size_t count = 4096 / sizeof(size_t) * 256 * 2;

    TEST_PATH(path);
    {
        File f(path, File::mode_Write);
        f.set_encryption_key(crypt_key(true));
        f.resize(count * sizeof(size_t));

        File::Map<size_t> map(f, File::access_ReadWrite, count * sizeof(size_t));
        for (size_t i = 0; i < count; ++i)
            map.get_addr()[i] = i;
    }
    {
        File f(path, File::mode_Read);
        f.set_encryption_key(crypt_key(true));
        File::Map<size_t> map(f, File::access_ReadOnly, count * sizeof(size_t));
        for (size_t i = 0; i < count; ++i) {
            CHECK_EQUAL(map.get_addr()[i], i);
            if (map.get_addr()[i] != i)
                return;
          }
    }
}

TEST(File_ReaderAndWriter)
{
    const size_t count = 4096 / sizeof(size_t) * 256 * 2;

    TEST_PATH(path);

    File writer(path, File::mode_Write);
    writer.set_encryption_key(crypt_key(true));
    writer.resize(count * sizeof(size_t));

    File reader(path, File::mode_Read);
    reader.set_encryption_key(crypt_key(true));
    CHECK_EQUAL(writer.get_size(), reader.get_size());

    File::Map<size_t> write(writer, File::access_ReadWrite, count * sizeof(size_t));
    File::Map<size_t> read(reader, File::access_ReadOnly, count * sizeof(size_t));

    for (size_t i = 0; i < count; i += 100) {
        write.get_addr()[i] = i;
        CHECK_EQUAL(read.get_addr()[i], i);
        if (read.get_addr()[i] != i)
            return;
    }
}

TEST(File_MultipleWriters)
{
    const size_t count = 4096 / sizeof(size_t) * 256 * 2;

    TEST_PATH(path);

    {
        File w1(path, File::mode_Write);
        w1.set_encryption_key(crypt_key(true));
        w1.resize(count * sizeof(size_t));

        File w2(path, File::mode_Write);
        w2.set_encryption_key(crypt_key(true));
        w2.resize(count * sizeof(size_t));

        File::Map<size_t> map1(w1, File::access_ReadWrite, count * sizeof(size_t));
        File::Map<size_t> map2(w2, File::access_ReadWrite, count * sizeof(size_t));

        for (size_t i = 0; i < count; i += 100) {
            ++map1.get_addr()[i];
            ++map2.get_addr()[i];
        }
    }

    File reader(path, File::mode_Read);
    reader.set_encryption_key(crypt_key(true));

    File::Map<size_t> read(reader, File::access_ReadOnly, count * sizeof(size_t));

    for (size_t i = 0; i < count; i += 100) {
        CHECK_EQUAL(read.get_addr()[i], 2);
        if (read.get_addr()[i] != 2)
            return;
    }
}

TEST(File_SetEncryptionKey)
{
    TEST_PATH(path);
    File f(path, File::mode_Write);
    const char key[64] = {0};

#ifdef TIGHTDB_ENABLE_ENCRYPTION
    f.set_encryption_key(key); // should not throw
#else
    CHECK_THROW(f.set_encryption_key(key), std::runtime_error);
#endif
}

TEST(File_ReadWrite)
{
    TEST_PATH(path);
    File f(path, File::mode_Write);
    f.set_encryption_key(crypt_key(true));
    f.resize(100);

    for (char i = 0; i < 100; ++i)
        f.write(&i, 1);
    f.seek(0);
    for (char i = 0; i < 100; ++i) {
        char read;
        f.read(&read, 1);
        CHECK_EQUAL(i, read);
    }
}

TEST(File_Resize)
{
    TEST_PATH(path);
    File f(path, File::mode_Write);
    f.set_encryption_key(crypt_key(true));

    f.resize(8192);
    CHECK_EQUAL(8192, f.get_size());
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 8192);
        for (int i = 0; i < 8192; ++i)
            m.get_addr()[i] = static_cast<unsigned char>(i);

        // Resizing away the first write is indistinguishable in encrypted files
        // from the process being interrupted before it does the first write,
        // but with subsequent writes it can tell that there was once valid
        // encrypted data there, so flush and write a second time
        m.sync();
        for (int i = 0; i < 8192; ++i)
            m.get_addr()[i] = static_cast<unsigned char>(i);
    }

    f.resize(4096);
    CHECK_EQUAL(4096, f.get_size());
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 4096);
        for (int i = 0; i < 4096; ++i) {
            CHECK_EQUAL(static_cast<unsigned char>(i), m.get_addr()[i]);
            if (static_cast<unsigned char>(i) != m.get_addr()[i])
                return;
        }
    }

    f.resize(8192);
    CHECK_EQUAL(8192, f.get_size());
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 8192);
        for (int i = 0; i < 8192; ++i)
            m.get_addr()[i] = static_cast<unsigned char>(i);
    }
    {
        File::Map<unsigned char> m(f, File::access_ReadWrite, 8192);
        for (int i = 0; i < 8192; ++i) {
            CHECK_EQUAL(static_cast<unsigned char>(i), m.get_addr()[i]);
            if (static_cast<unsigned char>(i) != m.get_addr()[i])
                return;
        }
    }
}

#endif // TEST_FILE
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/init.hpp"
#include <boost/test/unit_test.hpp>

BOOST_TEST_DONT_PRINT_LOG_VALUE(flusspferd::context)

BOOST_AUTO_TEST_CASE( initialize ) {
  flusspferd::init *init = 0;
  BOOST_CHECK_NO_THROW(init = &flusspferd::init::initialize());
  BOOST_CHECK_NE(init, (flusspferd::init*) 0);

  flusspferd::context &context = init->get_current_context();
  BOOST_CHECK(!context.is_valid());
}

BOOST_AUTO_TEST_CASE( enter_leave ) {
  flusspferd::init &init = flusspferd::init::initialize();

  flusspferd::context old_context(init.get_current_context());

  flusspferd::context context(flusspferd::context::create());

  BOOST_CHECK_NE(context, init.get_current_context());

  init.enter_current_context(context);

  BOOST_CHECK_EQUAL(context, init.get_current_context());

  init.leave_current_context(context);

  BOOST_CHECK_EQUAL(old_context, init.get_current_context());
}
<commit_msg>improve enter_leave check<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/init.hpp"
#include <boost/test/unit_test.hpp>

BOOST_TEST_DONT_PRINT_LOG_VALUE(flusspferd::context)

BOOST_AUTO_TEST_CASE( initialize ) {
  flusspferd::init *init = 0;
  BOOST_CHECK_NO_THROW(init = &flusspferd::init::initialize());
  BOOST_CHECK_NE(init, (flusspferd::init*) 0);

  flusspferd::context &context = init->get_current_context();
  BOOST_CHECK(!context.is_valid());
}

BOOST_AUTO_TEST_CASE( enter_leave ) {
  flusspferd::init &init = flusspferd::init::initialize();

  flusspferd::context old_context(init.get_current_context());

  flusspferd::context context(flusspferd::context::create());

  BOOST_CHECK_NE(context, init.get_current_context());

  BOOST_CHECK_EQUAL(init.enter_current_context(context), old_context);

  BOOST_CHECK_EQUAL(context, init.get_current_context());

  BOOST_CHECK(!init.leave_current_context(old_context));

  BOOST_CHECK(init.leave_current_context(context));

  BOOST_CHECK_EQUAL(old_context, init.get_current_context());
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>
#include <unistd.h>

#include "test.h"

struct test_exception : public std::runtime_error{
	test_exception(const std::string& msg):std::runtime_error(msg){}
};

void emit_error(const std::string& file, size_t line,
				const std::string& criterion, const std::string& message){
	std::ostringstream ss;
	ss << file << ':' << line << "\n\t";
	if(message.empty())
		ss << "Assertion failed: \n";
	else
		ss << message << ": \n";
	ss << '\t' << criterion << std::endl;
	throw test_exception(ss.str());
}

std::map<std::string,void(*)()>&
test_registry()
{
	static std::map<std::string,void(*)()> *registry = new std::map<std::string,void(*)()>;
	return *registry;
}

int main(int argc, char* argv[]){
	for(int i=1; i<argc; i++){
		std::string arg=argv[i];
		if(arg=="WORKING_DIRECTORY"){
			if(i+1>=argc){
				std::cerr << "WORKING_DIRECTORY not specified" << std::endl;
				return(1);
			}
			if(chdir(argv[i+1])!=0){
				std::cerr << "Failed to change working directory to " << argv[i+1] << std::endl;
				return(1);
			}
			i++;
		}
	}

	std::cout << "Running " << test_registry().size() << " tests" << std::endl;
	bool all_pass=true;
	size_t passes=0, failures=0;
	for(std::map<std::string,void(*)()>::const_iterator test=test_registry().begin();
		test!=test_registry().end(); test++){
		bool pass=false;
		std::cout << test->first << ": ";
		std::cout.flush();
		try{
			(test->second)();
			pass=true;
		}catch(test_exception& ex){
			std::cout << "FAIL\n " << ex.what() << std::endl;
		}catch(std::exception& ex){
			std::cout << "FAIL\n Exception: " << ex.what() << std::endl;
		}catch(...){
			std::cout << "FAIL\n Unknown object thrown" << std::endl;
		}
		if(pass)
			std::cout << "PASS" << std::endl;
		(pass?passes:failures)++;
		all_pass &= pass;
	}
	std::cout << passes << " test" << (passes!=1?"s":"") << " pass"
	<< (passes!=1?"":"es") << ", "
	<< failures << " fail" << (failures!=1?"":"s") << std::endl;
	return(all_pass ? 0 : 1);
}<commit_msg>Make tests selectable<commit_after>#include <iostream>
#include <stdexcept>
#include <unistd.h>
#include <vector>

#include "test.h"

struct test_exception : public std::runtime_error{
	test_exception(const std::string& msg):std::runtime_error(msg){}
};

void emit_error(const std::string& file, size_t line,
				const std::string& criterion, const std::string& message){
	std::ostringstream ss;
	ss << file << ':' << line << "\n\t";
	if(message.empty())
		ss << "Assertion failed: \n";
	else
		ss << message << ": \n";
	ss << '\t' << criterion << std::endl;
	throw test_exception(ss.str());
}

std::map<std::string,void(*)()>&
test_registry()
{
	static std::map<std::string,void(*)()> *registry = new std::map<std::string,void(*)()>;
	return *registry;
}

int main(int argc, char* argv[]){
	std::vector<std::string> test_filters;
	for(int i=1; i<argc; i++){
		std::string arg=argv[i];
		if(arg=="WORKING_DIRECTORY"){
			if(i+1>=argc){
				std::cerr << "WORKING_DIRECTORY not specified" << std::endl;
				return(1);
			}
			if(chdir(argv[i+1])!=0){
				std::cerr << "Failed to change working directory to " << argv[i+1] << std::endl;
				return(1);
			}
			i++;
		} else if (arg=="-k"){
			if(i+1>=argc){
				std::cerr << "-k requires an argument" << std::endl;
				return(1);
			}
			test_filters.push_back(argv[i+1]);
			i++;
		}
	}

	std::cout << "Running " << test_registry().size() << " tests" << std::endl;
	bool all_pass=true;
	size_t passes=0, failures=0;
	for(std::map<std::string,void(*)()>::const_iterator test=test_registry().begin();
		test!=test_registry().end(); test++){
		if (!test_filters.empty()) {
			bool target=false;
			for(auto &f : test_filters) {
				if (test->first.find(f) != std::string::npos) {
					target=true;
					break;
				}
			}
			if (!target)
				continue;
		}
		bool pass=false;
		std::cout << test->first << ": ";
		std::cout.flush();
		try{
			(test->second)();
			pass=true;
		}catch(test_exception& ex){
			std::cout << "FAIL\n " << ex.what() << std::endl;
		}catch(std::exception& ex){
			std::cout << "FAIL\n Exception: " << ex.what() << std::endl;
		}catch(...){
			std::cout << "FAIL\n Unknown object thrown" << std::endl;
		}
		if(pass)
			std::cout << "PASS" << std::endl;
		(pass?passes:failures)++;
		all_pass &= pass;
	}
	std::cout << passes << " test" << (passes!=1?"s":"") << " pass"
	<< (passes!=1?"":"es") << ", "
	<< failures << " fail" << (failures!=1?"":"s") << std::endl;
	return(all_pass ? 0 : 1);
}<|endoftext|>