<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CFunction.cpp,v $
   $Revision: 1.62 $
   $Name:  $
   $Author: gauges $
   $Date: 2006/03/15 20:09:34 $
   End CVS Header */

#include "copasi.h"

#include "CFunction.h"

CFunction::CFunction(const std::string & name,
                     const CCopasiContainer * pParent,
                     const CEvaluationTree::Type & type):
    CEvaluationTree(name, pParent, type),
    mVariables(),
    mpCallParameters(NULL),
    mReversible(TriUnspecified)
{}

CFunction::CFunction(const CFunction & src,
                     const CCopasiContainer * pParent):
    CEvaluationTree(src, pParent),
    mVariables(src.mVariables),
    mpCallParameters(NULL),
    mReversible(src.mReversible)
{}

CFunction::~CFunction()
{}

bool CFunction::setInfix(const std::string & infix)
{
  if (!CEvaluationTree::setInfix(infix) && infix != "") return false;
  if (!initVariables()) return false;

  return true;
}

bool CFunction::compile()
{return compileNodes();}

unsigned C_INT32 CFunction::getVariableIndex(const std::string & name) const
  {
    CFunctionParameter::DataType VariableType;
    return mVariables.findParameterByName(name, VariableType);
  }

const C_FLOAT64 & CFunction::getVariableValue(const unsigned C_INT32 & index) const
  {return *(*mpCallParameters)[index].value;}

void CFunction::setReversible(const TriLogic & reversible)
{mReversible = reversible;}

const TriLogic & CFunction::isReversible() const
  {return mReversible;}

CFunctionParameters & CFunction::getVariables()
{return mVariables;}

const CFunctionParameters & CFunction::getVariables() const
  {return mVariables;}

bool CFunction::addVariable(const std::string & name,
                            CFunctionParameter::Role usage,
                            const CFunctionParameter::DataType & type)
{return mVariables.add(name, type, usage);}

const C_FLOAT64 & CFunction::calcValue(const CCallParameters<C_FLOAT64> & callParameters)
{
  mpCallParameters = & callParameters;

  try
    {
      return mValue = mpRoot->value();
    }
  catch (...)
    {
      return mValue = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    }
}

bool CFunction::dependsOn(const C_FLOAT64 * parameter,
                          const CCallParameters<C_FLOAT64> & callParameters) const
  {
    CCallParameters<C_FLOAT64>::const_iterator it = callParameters.begin();
    CCallParameters<C_FLOAT64>::const_iterator end = callParameters.end();

    while (it != end && parameter != it->value) it++;

    if (it != end)
      return true;
    else
      return false;
  }

void CFunction::load(CReadConfig & configBuffer,
                     CReadConfig::Mode mode)
{
  //  cleanup();

  C_INT32 Type;

  mode = CReadConfig::SEARCH;
  configBuffer.getVariable("User-defined", "C_INT32", &Type, mode);

  switch (Type)
    {
    case 1:
      setType(UserDefined);
      break;

    default:
      fatalError();
    }

  configBuffer.getVariable("Reversible", "C_INT32", &mReversible);

  mode = CReadConfig::SEARCH;

  std::string tmp;
  configBuffer.getVariable("FunctionName", "string", &tmp, mode);
  setObjectName(tmp);

  configBuffer.getVariable("Description", "string", &tmp);
  setInfix(tmp);

  // For older file version the parameters have to be build from information
  // dependend on the function type. Luckilly, only user defined functions are
  // the only ones occuring in those files.
}

bool CFunction::initVariables()
{
  if (mpNodeList == NULL && mInfix != "") return false;

  //first add all variables to the existing list
  std::vector< CEvaluationNode * >::iterator it;
  std::vector< CEvaluationNode * >::iterator end;

  if (mInfix != "")
    {
      it = mpNodeList->begin();
      end = mpNodeList->end();
    }
  else
    {
      it = mpNodeList->end();
      end = mpNodeList->end();
    }

  CFunctionParameters NewVariables;

  for (; it != end; ++it)
    if (CEvaluationNode::type((*it)->getType()) == CEvaluationNode::VARIABLE)
      {
        mVariables.add((*it)->getData(), CFunctionParameter::FLOAT64, CFunctionParameter::VARIABLE);
        NewVariables.add((*it)->getData(), CFunctionParameter::FLOAT64, CFunctionParameter::VARIABLE);
      }

  //now remove all variables that are not in the tree anymore
  CFunctionParameter::DataType Type;
  unsigned C_INT32 i;
  for (i = mVariables.size() - 1; i < C_INVALID_INDEX; i--)
    if (NewVariables.findParameterByName(mVariables[i]->getObjectName(), Type) == C_INVALID_INDEX)
      mVariables.remove(mVariables[i]->getObjectName());

  return true;
}

bool CFunction::isSuitable(const unsigned C_INT32 noSubstrates,
                           const unsigned C_INT32 noProducts,
                           const TriLogic reversible)
{
  //first reversibility:
  if (reversible != this->isReversible() &&
      this->isReversible() != TriUnspecified)
    return false;

  //check substrates
  if (mVariables.isVector(CFunctionParameter::SUBSTRATE))
    {
      if (noSubstrates < 1)
        return false;
    }
  else //is no vector
    {
      if (mVariables.getNumberOfParametersByUsage(CFunctionParameter::SUBSTRATE) != noSubstrates)
        return false;
    }

  //check products
  if (reversible == TriTrue)
    {
      if (mVariables.isVector(CFunctionParameter::PRODUCT))
        {
          if (noProducts < 1)
            return false;
        }
      else //is no vector
        {
          if (mVariables.getNumberOfParametersByUsage(CFunctionParameter::PRODUCT) != noProducts)
            return false;
        }
    }

  //no VARIABLE variables allowed for kinetic functions
  if (mVariables.getNumberOfParametersByUsage(CFunctionParameter::VARIABLE) != 0)
    return false;

  return true;
}

#include "utilities/copasimathml.h"

void CFunction::writeMathML(std::ostream & out,
                            const std::vector<std::vector<std::string> > & env,
                            bool expand, bool fullExpand,
                            unsigned C_INT32 l) const
  {
    if (expand)
      {
        bool flag = true; //TODO include check if parantheses are necessary
        if (flag) out << SPC(l) << "<mfenced>" << std::endl;
        mpRoot->writeMathML(out, env, fullExpand, l + 1);
        if (flag) out << SPC(l) << "</mfenced>" << std::endl;
      }
    else //no expand
      {
        out << SPC(l) << "<mrow>" << std::endl;
        out << SPC(l + 1) << CMathMl::fixName(getObjectName()) << std::endl;
        out << SPC(l + 1) << "<mfenced>" << std::endl;

        unsigned C_INT32 i, imax = getVariables().size();
        for (i = 0; i < imax; ++i)
          {
            out << SPC(l + 2) << env[i][0] << std::endl;
          }

        out << SPC(l + 1) << "</mfenced>" << std::endl;
        out << SPC(l) << "</mrow>" << std::endl;
      }
  }

void CFunction::writeMathML(std::ostream & out, unsigned C_INT32 l) const
  {
    //out << "<math>" << std::endl;

    out << SPC(l) << "<mrow>" << std::endl;
    out << SPC(l + 1) << CMathMl::fixName(getObjectName()) << std::endl;
    out << SPC(l + 1) << "<mfenced>" << std::endl;

    unsigned C_INT32 i, imax = getVariables().size();
    for (i = 0; i < imax; ++i)
      {
        out << SPC(l + 2) << "<mi>" << getVariables()[i]->getObjectName() << "</mi>" << std::endl;
      }

    out << SPC(l + 1) << "</mfenced>" << std::endl;
    out << SPC(l) << "</mrow>" << std::endl;

    //out << "</math>" << std::endl;
  }
<commit_msg>mpNodelist will be NULL therefore we must not use it.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CFunction.cpp,v $
   $Revision: 1.63 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/03/15 20:51:36 $
   End CVS Header */

#include "copasi.h"

#include "CFunction.h"

CFunction::CFunction(const std::string & name,
                     const CCopasiContainer * pParent,
                     const CEvaluationTree::Type & type):
    CEvaluationTree(name, pParent, type),
    mVariables(),
    mpCallParameters(NULL),
    mReversible(TriUnspecified)
{}

CFunction::CFunction(const CFunction & src,
                     const CCopasiContainer * pParent):
    CEvaluationTree(src, pParent),
    mVariables(src.mVariables),
    mpCallParameters(NULL),
    mReversible(src.mReversible)
{}

CFunction::~CFunction()
{}

bool CFunction::setInfix(const std::string & infix)
{
  if (!CEvaluationTree::setInfix(infix) && infix != "") return false;
  if (!initVariables()) return false;

  return true;
}

bool CFunction::compile()
{return compileNodes();}

unsigned C_INT32 CFunction::getVariableIndex(const std::string & name) const
  {
    CFunctionParameter::DataType VariableType;
    return mVariables.findParameterByName(name, VariableType);
  }

const C_FLOAT64 & CFunction::getVariableValue(const unsigned C_INT32 & index) const
  {return *(*mpCallParameters)[index].value;}

void CFunction::setReversible(const TriLogic & reversible)
{mReversible = reversible;}

const TriLogic & CFunction::isReversible() const
  {return mReversible;}

CFunctionParameters & CFunction::getVariables()
{return mVariables;}

const CFunctionParameters & CFunction::getVariables() const
  {return mVariables;}

bool CFunction::addVariable(const std::string & name,
                            CFunctionParameter::Role usage,
                            const CFunctionParameter::DataType & type)
{return mVariables.add(name, type, usage);}

const C_FLOAT64 & CFunction::calcValue(const CCallParameters<C_FLOAT64> & callParameters)
{
  mpCallParameters = & callParameters;

  try
    {
      return mValue = mpRoot->value();
    }
  catch (...)
    {
      return mValue = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    }
}

bool CFunction::dependsOn(const C_FLOAT64 * parameter,
                          const CCallParameters<C_FLOAT64> & callParameters) const
  {
    CCallParameters<C_FLOAT64>::const_iterator it = callParameters.begin();
    CCallParameters<C_FLOAT64>::const_iterator end = callParameters.end();

    while (it != end && parameter != it->value) it++;

    if (it != end)
      return true;
    else
      return false;
  }

void CFunction::load(CReadConfig & configBuffer,
                     CReadConfig::Mode mode)
{
  //  cleanup();

  C_INT32 Type;

  mode = CReadConfig::SEARCH;
  configBuffer.getVariable("User-defined", "C_INT32", &Type, mode);

  switch (Type)
    {
    case 1:
      setType(UserDefined);
      break;

    default:
      fatalError();
    }

  configBuffer.getVariable("Reversible", "C_INT32", &mReversible);

  mode = CReadConfig::SEARCH;

  std::string tmp;
  configBuffer.getVariable("FunctionName", "string", &tmp, mode);
  setObjectName(tmp);

  configBuffer.getVariable("Description", "string", &tmp);
  setInfix(tmp);

  // For older file version the parameters have to be build from information
  // dependend on the function type. Luckilly, only user defined functions are
  // the only ones occuring in those files.
}

bool CFunction::initVariables()
{
  if (mpNodeList == NULL && mInfix != "") return false;

  //first add all variables to the existing list
  std::vector< CEvaluationNode * >::iterator it;
  std::vector< CEvaluationNode * >::iterator end;

  if (mInfix != "")
    {
      it = mpNodeList->begin();
      end = mpNodeList->end();
    }
  else
    it = end;

  CFunctionParameters NewVariables;

  for (; it != end; ++it)
    if (CEvaluationNode::type((*it)->getType()) == CEvaluationNode::VARIABLE)
      {
        mVariables.add((*it)->getData(), CFunctionParameter::FLOAT64, CFunctionParameter::VARIABLE);
        NewVariables.add((*it)->getData(), CFunctionParameter::FLOAT64, CFunctionParameter::VARIABLE);
      }

  //now remove all variables that are not in the tree anymore
  CFunctionParameter::DataType Type;
  unsigned C_INT32 i;
  for (i = mVariables.size() - 1; i < C_INVALID_INDEX; i--)
    if (NewVariables.findParameterByName(mVariables[i]->getObjectName(), Type) == C_INVALID_INDEX)
      mVariables.remove(mVariables[i]->getObjectName());

  return true;
}

bool CFunction::isSuitable(const unsigned C_INT32 noSubstrates,
                           const unsigned C_INT32 noProducts,
                           const TriLogic reversible)
{
  //first reversibility:
  if (reversible != this->isReversible() &&
      this->isReversible() != TriUnspecified)
    return false;

  //check substrates
  if (mVariables.isVector(CFunctionParameter::SUBSTRATE))
    {
      if (noSubstrates < 1)
        return false;
    }
  else //is no vector
    {
      if (mVariables.getNumberOfParametersByUsage(CFunctionParameter::SUBSTRATE) != noSubstrates)
        return false;
    }

  //check products
  if (reversible == TriTrue)
    {
      if (mVariables.isVector(CFunctionParameter::PRODUCT))
        {
          if (noProducts < 1)
            return false;
        }
      else //is no vector
        {
          if (mVariables.getNumberOfParametersByUsage(CFunctionParameter::PRODUCT) != noProducts)
            return false;
        }
    }

  //no VARIABLE variables allowed for kinetic functions
  if (mVariables.getNumberOfParametersByUsage(CFunctionParameter::VARIABLE) != 0)
    return false;

  return true;
}

#include "utilities/copasimathml.h"

void CFunction::writeMathML(std::ostream & out,
                            const std::vector<std::vector<std::string> > & env,
                            bool expand, bool fullExpand,
                            unsigned C_INT32 l) const
  {
    if (expand)
      {
        bool flag = true; //TODO include check if parantheses are necessary
        if (flag) out << SPC(l) << "<mfenced>" << std::endl;
        mpRoot->writeMathML(out, env, fullExpand, l + 1);
        if (flag) out << SPC(l) << "</mfenced>" << std::endl;
      }
    else //no expand
      {
        out << SPC(l) << "<mrow>" << std::endl;
        out << SPC(l + 1) << CMathMl::fixName(getObjectName()) << std::endl;
        out << SPC(l + 1) << "<mfenced>" << std::endl;

        unsigned C_INT32 i, imax = getVariables().size();
        for (i = 0; i < imax; ++i)
          {
            out << SPC(l + 2) << env[i][0] << std::endl;
          }

        out << SPC(l + 1) << "</mfenced>" << std::endl;
        out << SPC(l) << "</mrow>" << std::endl;
      }
  }

void CFunction::writeMathML(std::ostream & out, unsigned C_INT32 l) const
  {
    //out << "<math>" << std::endl;

    out << SPC(l) << "<mrow>" << std::endl;
    out << SPC(l + 1) << CMathMl::fixName(getObjectName()) << std::endl;
    out << SPC(l + 1) << "<mfenced>" << std::endl;

    unsigned C_INT32 i, imax = getVariables().size();
    for (i = 0; i < imax; ++i)
      {
        out << SPC(l + 2) << "<mi>" << getVariables()[i]->getObjectName() << "</mi>" << std::endl;
      }

    out << SPC(l + 1) << "</mfenced>" << std::endl;
    out << SPC(l) << "</mrow>" << std::endl;

    //out << "</math>" << std::endl;
  }
<|endoftext|>


<commit_before>// Copyright 2020 Intel Corporation
#include "mlir/ExecutionEngine/RunnerUtils.h"
#include "pmlc/compiler/registry.h"
#include "pmlc/util/logging.h"

extern "C" void plaidml_rt_prng(unsigned stateRank,
                                StridedMemRefType<int32_t, 1> *state,
                                unsigned resultRank,
                                StridedMemRefType<float, 1> *result,
                                unsigned newStateRank,
                                StridedMemRefType<int32_t, 1> *newState) {
  if (resultRank == 0) {
    // Nothing to do.
    return;
  }

  unsigned count = result->sizes[0];
  for (unsigned i = 1; i < resultRank; i++) {
    count *= result->sizes[i];
  }

  int *in_state = state->data + state->offset;
  float *buf = result->data + result->offset;
  int *out_state = newState->data + newState->offset;

  // A reimplementation of the PRNG from tile/lang/gen_special.cc.
  // x_n = (s1_n ^ s2_n ^ s3_n)
  // s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
  // s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
  // s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
  int32_t s0 = in_state[0];
  int32_t s1 = in_state[1];
  int32_t s2 = in_state[2];
  for (unsigned i = 0; i < count; ++i) {
    buf[i] = (s0 ^ s1 ^ s2) / 4294967296.0;
    s0 = (((s0 & 4294967294) << 12) ^ (((s0 << 13) ^ s0) >> 19));
    s1 = (((s1 & 4294967288) << 4) ^ (((s1 << 2) ^ s1) >> 25));
    s2 = (((s2 & 4294967280) << 17) ^ (((s2 << 3) ^ s2) >> 11));
  }

  out_state[0] = s0;
  out_state[1] = s1;
  out_state[2] = s2;
}

namespace {
struct Registration {
  Registration() {
    using pmlc::compiler::registerSymbol;
    registerSymbol("plaidml_rt_prng",
                   reinterpret_cast<void *>(plaidml_rt_prng));
  }
};
static Registration reg;
} // namespace
<commit_msg>Use unsigned ints instead of ints (#1051)<commit_after>// Copyright 2020 Intel Corporation
#include "mlir/ExecutionEngine/RunnerUtils.h"
#include "pmlc/compiler/registry.h"
#include "pmlc/util/logging.h"

extern "C" void plaidml_rt_prng(unsigned stateRank,
                                StridedMemRefType<uint32_t, 1> *state,
                                unsigned resultRank,
                                StridedMemRefType<float, 1> *result,
                                unsigned newStateRank,
                                StridedMemRefType<uint32_t, 1> *newState) {
  if (resultRank == 0) {
    // Nothing to do.
    return;
  }

  unsigned count = result->sizes[0];
  for (unsigned i = 1; i < resultRank; i++) {
    count *= result->sizes[i];
  }

  uint32_t *in_state = state->data + state->offset;
  float *buf = result->data + result->offset;
  uint32_t *out_state = newState->data + newState->offset;

  // A reimplementation of the PRNG from tile/lang/gen_special.cc.
  // x_n = (s1_n ^ s2_n ^ s3_n)
  // s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
  // s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
  // s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
  uint32_t s0 = in_state[0];
  uint32_t s1 = in_state[1];
  uint32_t s2 = in_state[2];
  for (unsigned i = 0; i < count; ++i) {
    buf[i] = (s0 ^ s1 ^ s2) / 4294967296.0;
    s0 = (((s0 & 4294967294) << 12) ^ (((s0 << 13) ^ s0) >> 19));
    s1 = (((s1 & 4294967288) << 4) ^ (((s1 << 2) ^ s1) >> 25));
    s2 = (((s2 & 4294967280) << 17) ^ (((s2 << 3) ^ s2) >> 11));
  }

  out_state[0] = s0;
  out_state[1] = s1;
  out_state[2] = s2;
}

namespace {
struct Registration {
  Registration() {
    using pmlc::compiler::registerSymbol;
    registerSymbol("plaidml_rt_prng",
                   reinterpret_cast<void *>(plaidml_rt_prng));
  }
};
static Registration reg;
} // namespace
<|endoftext|>


<commit_before>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TROOT.h"
#include "el.h"
#include "TRegexp.h"
#include "TClassTable.h"
#include "TInterpreter.h"
#include <stack>
#include <set>

using namespace std;

void setKeywordColors(const char* colorTab, const char* colorBracket, const char* colorBadBracket);
int selectColor(const char* str);
void highlightKeywords(EditLine_t* el);
int matchParentheses(EditLine_t* el);
void colorWord(EditLine_t* el, int first, int num, int color);
void colorBrackets(EditLine_t* el, int open, int close, int color);
char** rl_complete2ROOT(const char*, int, int);

struct KeywordInLine_t {
   KeywordInLine_t(const TString& w, Long64_t hash, Ssiz_t pos):
      fWord(w),
      fHash(hash),
      fPosBegin(pos) {}

   TString fWord;
   Long64_t fHash;
   Ssiz_t fPosBegin;
};

// int values for colour highlighting
int color_class = 4;           // NCurses COLOR_BLUE
int color_type = 4;            // NCurses COLOR_BLUE
int color_bracket = 2;         // NCurses COLOR_GREEN
int color_badbracket = 1;      // NCurses COLOR_RED

/**
 *   Sets the colours to use for highlighting keywords (types and classnames),
 *   matching bracket pairs, mismatched brackets and tab completion.
 *   Overrides the default colour settings:
 *   class and type: 4 (blue)
 *   bracket pair:   2 (green)
 *   bad bracket:   1 (red)
 */
void
setKeywordColors(int colorType, int colorBracket, int colorBadBracket) {
   color_class = colorType;
   color_type = colorType;
   color_bracket = colorBracket;
   color_badbracket = colorBadBracket;
} // setKeywordColors

/*
 *      Use gRoot to establish keywords known to root.
 *
 */
void
highlightKeywords(EditLine_t* el) {
   typedef std::set<int> HashSet_t;
   static HashSet_t sHashedKnownTypes;

   TString sBuffer(el->fLine.fBuffer, el->fLine.fLastChar - el->fLine.fBuffer);

   TString keyword;
   Ssiz_t posNextTok = 0;
   Ssiz_t posPrevTok = 0;

   // regular expression inverse of match expression to find end of match
   while (sBuffer.Tokenize(keyword, posNextTok, "[^a-zA-Z0-9_]")) {
      Ssiz_t toklen = posNextTok - posPrevTok;

      if (posNextTok == -1) {
         toklen = sBuffer.Length() - posPrevTok;
      }
      TString tok = sBuffer(posPrevTok, toklen);
      Ssiz_t pos = posPrevTok + tok.Index(keyword);
      int color = -1;

      if (gROOT->GetListOfTypes()->FindObject(keyword)) {
         color = color_type;
      } else if (gInterpreter->CheckClassInfo(keyword, kFALSE)) {
         color = color_class;
      }
      colorWord(el, pos, keyword.Length(), color);
      posPrevTok = posNextTok;
   }
} // highlightKeywords

/** if buffer has content, check each char to see if it is an opening bracket,
    if so, check for its closing one and return the indices to both
 * alt:
 * check each char for a match against each type of open and close bracket
 * if open found, push index onto a seperate stack for each type of bracket
 * if close found, pop previous value off relevant stack
 * and pass both pointers to highlight()
 */
int
matchParentheses(EditLine_t* el) {
   static const int amtBrackets = 3;
   int bracketPos = -1;
   int foundParenIdx = -1;
   char bTypes[amtBrackets][2];

   bTypes[0][0] = '(';
   bTypes[0][1] = ')';
   bTypes[1][0] = '{';
   bTypes[1][1] = '}';
   bTypes[2][0] = '[';
   bTypes[2][1] = ']';
   //static char bTypes[] = "(){}[]"; with strchr(bTypes, sBuffer[bracketPos])

   // CURRENT STUFF
   // create a string of the buffer contents
   TString sBuffer = "";

   for (char* c = el->fLine.fBuffer; c < el->fLine.fLastChar; c++) {
      sBuffer.Append(*c);
   }

   // check whole buffer for any highlighted brackets and remove colour info
   for (int i = 0; i < (el->fLine.fLastChar - el->fLine.fBuffer); i++) {
      if (el->fLine.fBufColor[i].fForeColor == color_bracket || el->fLine.fBufColor[i].fForeColor == color_badbracket) {
         el->fLine.fBufColor[i] = -1;                      // reset to default colours
         term__repaint(el, i);
      }
   }

   // char* stack for pointers to locations of brackets
   stack<int> locBrackets;

   if (sBuffer.Length() > 0) {
      int cursorPos = el->fLine.fCursor - el->fLine.fBuffer;
      bracketPos = cursorPos;

      // check against each bracket type
      int bIndex = 0;

      for (bIndex = 0; bIndex < amtBrackets; bIndex++) {
         // if current char is equal to opening bracket, push onto stack
         if (sBuffer[bracketPos] == bTypes[bIndex][0]) {
            locBrackets.push(bracketPos);
            foundParenIdx = 0;
            break;
         } else if (sBuffer[bracketPos] == bTypes[bIndex][1]) {
            locBrackets.push(bracketPos);
            foundParenIdx = 1;
            break;
         }
      }

      // current cursor char is not an open bracket, and there is a previous char to check
      if (foundParenIdx == -1 && bracketPos > 0) {
         //check previously typed char for being a closing bracket
         bracketPos--;
         // check against each bracket type
         bIndex = 0;

         for (bIndex = 0; bIndex < amtBrackets; bIndex++) {
            // if current char is equal to closing bracket, push onto stack
            if (sBuffer[bracketPos] == bTypes[bIndex][1]) {
               locBrackets.push(bracketPos);
               foundParenIdx = 1;
               break;
            }
         }
      }

      // no bracket found on either current or previous char, return.
      if (foundParenIdx == -1) {
         return foundParenIdx;
      }

      // iterate through remaining letters until find a matching closing bracket
      // if another open bracket of the same type is found, push onto stack
      // and pop on next closing bracket match
      int step = 1;

      if (foundParenIdx == 1) {
         step = -1;
      }

      for (int i = bracketPos + step; i >= 0 && i < sBuffer.Length(); i += step) {
         //if current char is equal to another opening bracket, push onto stack
         if (sBuffer[i] == bTypes[bIndex][foundParenIdx]) {
            // push index of bracket
            locBrackets.push(i);
         }
         //if current char is equal to closing bracket
         else if (sBuffer[i] == bTypes[bIndex][1 - foundParenIdx]) {
            // pop previous opening bracket off stack
            locBrackets.pop();

            // if previous opening was the last entry, then highlight match
            if (locBrackets.empty()) {
               colorBrackets(el, bracketPos, i, color_bracket);
               break;
            }
         }
      }

      if (!locBrackets.empty()) {
         colorBrackets(el, bracketPos, bracketPos, color_badbracket);
      }
   }

   return foundParenIdx;
} // matchParentheses

/**
 *      Highlight a word within the buffer.
 *      Requires the start and end index of the word, and the color pair index (class or type).
 *      Writes colour info for each char in range to el->fLine.bufcol.
 *      Background colour is set to the same as the current terminal background colour.
 *      Foreground (text) colour is set according to the type of word being highlighted (e.g. class or type).
 */
void
colorWord(EditLine_t* el, int first, int num, int textColor) {
   int bgColor = -1;            // default background
   bool anyChange = false;

   // add colour information to el.
   for (int index = first; index < first + num; ++index) {
      bool changed = el->fLine.fBufColor[index].fForeColor != textColor;
      anyChange |= changed;
      el->fLine.fBufColor[index].fForeColor = textColor;
      el->fLine.fBufColor[index].fBackColor = bgColor;

      if (changed) {
         term__repaint(el, index);
      }
   }

   if (anyChange) {
      term__setcolor(-1);
   }
} // colorWord

/*
 *      Set the colour information in the SEditLine_t buffer,
 *      Then call repaint to repaint the chars with the new colour information
 */
void
colorBrackets(EditLine_t* el, int open, int close, int textColor) {
   int bgColor = -1;            // default background

   el->fLine.fBufColor[open].fForeColor = textColor;
   el->fLine.fBufColor[open].fBackColor = bgColor;
   term__repaint(el, open);

   el->fLine.fBufColor[close].fForeColor = textColor;
   el->fLine.fBufColor[close].fBackColor = bgColor;
   term__repaint(el, close);

   term__setcolor(-1);
}
<commit_msg>Remove unused includes, struct definition. Split ROOT-dependent (types) from generic (brackets) part.<commit_after>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "el.h"
#include <stack>
#include <set>
#include <string>

#include "TROOT.h"
#include "TInterpreter.h"

using namespace std;

void setKeywordColors(const char* colorTab, const char* colorBracket, const char* colorBadBracket);
int selectColor(const char* str);
void highlightKeywords(EditLine_t* el);
int matchParentheses(EditLine_t* el);
void colorWord(EditLine_t* el, int first, int num, int color);
void colorBrackets(EditLine_t* el, int open, int close, int color);
char** rl_complete2ROOT(const char*, int, int);

// int values for colour highlighting
int color_class = 4;           // NCurses COLOR_BLUE
int color_type = 4;            // NCurses COLOR_BLUE
int color_bracket = 2;         // NCurses COLOR_GREEN
int color_badbracket = 1;      // NCurses COLOR_RED

/**
 *   Sets the colours to use for highlighting keywords (types and classnames),
 *   matching bracket pairs, mismatched brackets and tab completion.
 *   Overrides the default colour settings:
 *   class and type: 4 (blue)
 *   bracket pair:   2 (green)
 *   bad bracket:   1 (red)
 */
void
setKeywordColors(int colorType, int colorBracket, int colorBadBracket) {
   color_class = colorType;
   color_type = colorType;
   color_bracket = colorBracket;
   color_badbracket = colorBadBracket;
} // setKeywordColors

/*
 *      Use gRoot to establish keywords known to root.
 *
 */
void
highlightKeywords(EditLine_t* el) {
   typedef std::set<int> HashSet_t;
   static HashSet_t sHashedKnownTypes;

   TString sBuffer(el->fLine.fBuffer, el->fLine.fLastChar - el->fLine.fBuffer);

   TString keyword;
   Ssiz_t posNextTok = 0;
   Ssiz_t posPrevTok = 0;

   // regular expression inverse of match expression to find end of match
   while (sBuffer.Tokenize(keyword, posNextTok, "[^a-zA-Z0-9_]")) {
      Ssiz_t toklen = posNextTok - posPrevTok;

      if (posNextTok == -1) {
         toklen = sBuffer.Length() - posPrevTok;
      }
      TString tok = sBuffer(posPrevTok, toklen);
      Ssiz_t pos = posPrevTok + tok.Index(keyword);
      int color = -1;

      if (gROOT->GetListOfTypes()->FindObject(keyword)) {
         color = color_type;
      } else if (gInterpreter->CheckClassInfo(keyword, kFALSE)) {
         color = color_class;
      }
      colorWord(el, pos, keyword.Length(), color);
      posPrevTok = posNextTok;
   }
} // highlightKeywords

/** if buffer has content, check each char to see if it is an opening bracket,
    if so, check for its closing one and return the indices to both
 * alt:
 * check each char for a match against each type of open and close bracket
 * if open found, push index onto a seperate stack for each type of bracket
 * if close found, pop previous value off relevant stack
 * and pass both pointers to highlight()
 */
int
matchParentheses(EditLine_t* el) {
   static const int amtBrackets = 3;
   int bracketPos = -1;
   int foundParenIdx = -1;
   char bTypes[amtBrackets][2];

   bTypes[0][0] = '(';
   bTypes[0][1] = ')';
   bTypes[1][0] = '{';
   bTypes[1][1] = '}';
   bTypes[2][0] = '[';
   bTypes[2][1] = ']';
   //static char bTypes[] = "(){}[]"; with strchr(bTypes, sBuffer[bracketPos])

   // CURRENT STUFF
   // create a string of the buffer contents
   std::string sBuffer = "";

   for (char* c = el->fLine.fBuffer; c < el->fLine.fLastChar; c++) {
      sBuffer += *c;
   }

   // check whole buffer for any highlighted brackets and remove colour info
   for (int i = 0; i < (el->fLine.fLastChar - el->fLine.fBuffer); i++) {
      if (el->fLine.fBufColor[i].fForeColor == color_bracket || el->fLine.fBufColor[i].fForeColor == color_badbracket) {
         el->fLine.fBufColor[i] = -1;                      // reset to default colours
         term__repaint(el, i);
      }
   }

   // char* stack for pointers to locations of brackets
   stack<int> locBrackets;

   if (!sBuffer.empty()) {
      int cursorPos = el->fLine.fCursor - el->fLine.fBuffer;
      bracketPos = cursorPos;

      // check against each bracket type
      int bIndex = 0;

      for (bIndex = 0; bIndex < amtBrackets; bIndex++) {
         // if current char is equal to opening bracket, push onto stack
         if (sBuffer[bracketPos] == bTypes[bIndex][0]) {
            locBrackets.push(bracketPos);
            foundParenIdx = 0;
            break;
         } else if (sBuffer[bracketPos] == bTypes[bIndex][1]) {
            locBrackets.push(bracketPos);
            foundParenIdx = 1;
            break;
         }
      }

      // current cursor char is not an open bracket, and there is a previous char to check
      if (foundParenIdx == -1 && bracketPos > 0) {
         //check previously typed char for being a closing bracket
         bracketPos--;
         // check against each bracket type
         bIndex = 0;

         for (bIndex = 0; bIndex < amtBrackets; bIndex++) {
            // if current char is equal to closing bracket, push onto stack
            if (sBuffer[bracketPos] == bTypes[bIndex][1]) {
               locBrackets.push(bracketPos);
               foundParenIdx = 1;
               break;
            }
         }
      }

      // no bracket found on either current or previous char, return.
      if (foundParenIdx == -1) {
         return foundParenIdx;
      }

      // iterate through remaining letters until find a matching closing bracket
      // if another open bracket of the same type is found, push onto stack
      // and pop on next closing bracket match
      int step = 1;

      if (foundParenIdx == 1) {
         step = -1;
      }

      for (int i = bracketPos + step; i >= 0 && i < (int)sBuffer.size(); i += step) {
         //if current char is equal to another opening bracket, push onto stack
         if (sBuffer[i] == bTypes[bIndex][foundParenIdx]) {
            // push index of bracket
            locBrackets.push(i);
         }
         //if current char is equal to closing bracket
         else if (sBuffer[i] == bTypes[bIndex][1 - foundParenIdx]) {
            // pop previous opening bracket off stack
            locBrackets.pop();

            // if previous opening was the last entry, then highlight match
            if (locBrackets.empty()) {
               colorBrackets(el, bracketPos, i, color_bracket);
               break;
            }
         }
      }

      if (!locBrackets.empty()) {
         colorBrackets(el, bracketPos, bracketPos, color_badbracket);
      }
   }

   return foundParenIdx;
} // matchParentheses

/**
 *      Highlight a word within the buffer.
 *      Requires the start and end index of the word, and the color pair index (class or type).
 *      Writes colour info for each char in range to el->fLine.bufcol.
 *      Background colour is set to the same as the current terminal background colour.
 *      Foreground (text) colour is set according to the type of word being highlighted (e.g. class or type).
 */
void
colorWord(EditLine_t* el, int first, int num, int textColor) {
   int bgColor = -1;            // default background
   bool anyChange = false;

   // add colour information to el.
   for (int index = first; index < first + num; ++index) {
      bool changed = el->fLine.fBufColor[index].fForeColor != textColor;
      anyChange |= changed;
      el->fLine.fBufColor[index].fForeColor = textColor;
      el->fLine.fBufColor[index].fBackColor = bgColor;

      if (changed) {
         term__repaint(el, index);
      }
   }

   if (anyChange) {
      term__setcolor(-1);
   }
} // colorWord

/*
 *      Set the colour information in the SEditLine_t buffer,
 *      Then call repaint to repaint the chars with the new colour information
 */
void
colorBrackets(EditLine_t* el, int open, int close, int textColor) {
   int bgColor = -1;            // default background

   el->fLine.fBufColor[open].fForeColor = textColor;
   el->fLine.fBufColor[open].fBackColor = bgColor;
   term__repaint(el, open);

   el->fLine.fBufColor[close].fForeColor = textColor;
   el->fLine.fBufColor[close].fBackColor = bgColor;
   term__repaint(el, close);

   term__setcolor(-1);
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2016 Esteban Tovagliari, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "appleseedmaya/exporters/rampexporter.h"

// Standard headers.
#include <algorithm>
#include <sstream>
#include <vector>

// Maya headers.
#include <maya/MFnDependencyNode.h>

// appleseed.maya headers.
#include "appleseedmaya/attributeutils.h"
#include "appleseedmaya/exporters/exporterfactory.h"

namespace asf = foundation;
namespace asr = renderer;

namespace
{

struct RampEntry
{
    RampEntry(float pos, const MColor& col)
      : m_pos(pos)
      , m_col(col)
    {
    }

    bool operator<(const RampEntry& other) const
    {
        return m_pos < other.m_pos;
    }

    float   m_pos;
    MColor  m_col;
};

} // unnamed

void RampExporter::registerExporter()
{
    NodeExporterFactory::registerShadingNodeExporter(
        "ramp",
        &RampExporter::create);
}

ShadingNodeExporter *RampExporter::create(
    const MObject&      object,
    asr::ShaderGroup&   shaderGroup)
{
    return new RampExporter(object, shaderGroup);
}

void RampExporter::exportParameterValue(
    const MPlug&        plug,
    const OSLParamInfo& paramInfo,
    asr::ParamArray&    shaderParams)
{
    MFnDependencyNode depNodeFn(node());
    MStatus status;

    if(paramInfo.paramName == "in_position")
    {
        MPlug plug = depNodeFn.findPlug("colorEntryList", &status);

        std::vector<RampEntry> rampColors;
        rampColors.reserve(plug.numElements());

        for(size_t i = 0, e = plug.numElements(); i < e; ++i)
        {
            MPlug entry = plug.elementByLogicalIndex(i);
            MPlug position = entry.child(0);
            MPlug color = entry.child(1);

            float p;
            AttributeUtils::get(position, p);

            MColor c;
            AttributeUtils::get(color, c);

            rampColors.push_back(RampEntry(p, c));
        }

        std::sort(rampColors.begin(), rampColors.end());

        std::stringstream ssp;
        ssp << "float[] ";

        std::stringstream ssc;
        ssc << "color[] ";
        for(size_t i = 0, e = rampColors.size(); i < e; ++i)
        {
            ssp << rampColors[i].m_pos << " ";
            ssc << rampColors[i].m_col.r << " " << rampColors[i].m_col.g << " " << rampColors[i].m_col.b << " ";
        }

        shaderParams.insert("in_position", ssp.str().c_str());
        shaderParams.insert("in_color"   , ssc.str().c_str());
    }
    else if(paramInfo.paramName == "in_color")
    {
        // skip.
    }
    else
    {
        ShadingNodeExporter::exportParameterValue(
            plug,
            paramInfo,
            shaderParams);
    }
}

RampExporter::RampExporter(
    const MObject&      object,
    asr::ShaderGroup&   shaderGroup)
  : ShadingNodeExporter(object, shaderGroup)
{
}
<commit_msg>Handle four corner ramps differently.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2016 Esteban Tovagliari, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "appleseedmaya/exporters/rampexporter.h"

// Standard headers.
#include <algorithm>
#include <sstream>
#include <vector>

// Maya headers.
#include <maya/MFnDependencyNode.h>

// appleseed.maya headers.
#include "appleseedmaya/attributeutils.h"
#include "appleseedmaya/exporters/exporterfactory.h"

namespace asf = foundation;
namespace asr = renderer;

namespace
{

struct RampEntry
{
    RampEntry(float pos, const MColor& col)
      : m_pos(pos)
      , m_col(col)
    {
    }

    bool operator<(const RampEntry& other) const
    {
        return m_pos < other.m_pos;
    }

    float   m_pos;
    MColor  m_col;
};

} // unnamed

void RampExporter::registerExporter()
{
    NodeExporterFactory::registerShadingNodeExporter(
        "ramp",
        &RampExporter::create);
}

ShadingNodeExporter *RampExporter::create(
    const MObject&      object,
    asr::ShaderGroup&   shaderGroup)
{
    return new RampExporter(object, shaderGroup);
}

void RampExporter::exportParameterValue(
    const MPlug&        plug,
    const OSLParamInfo& paramInfo,
    asr::ParamArray&    shaderParams)
{
    MFnDependencyNode depNodeFn(node());
    MStatus status;

    if(paramInfo.paramName == "in_position")
    {
        MPlug plug = depNodeFn.findPlug("colorEntryList", &status);

        std::vector<RampEntry> rampColors;
        rampColors.reserve(plug.numElements());

        for(size_t i = 0, e = plug.numElements(); i < e; ++i)
        {
            MPlug entry = plug.elementByPhysicalIndex(i);
            MPlug position = entry.child(0);
            MPlug color = entry.child(1);

            float p;
            AttributeUtils::get(position, p);

            MColor c;
            AttributeUtils::get(color, c);

            rampColors.push_back(RampEntry(p, c));
        }

        plug = depNodeFn.findPlug("type", &status);
        int rampType;
        AttributeUtils::get(plug, rampType);

        // Check if the type is four corner.
        if(rampType == 7)
        {
            // Fill with black if we have less than 4 elements.
            while(rampColors.size() < 4)
                rampColors.push_back(RampEntry(1.0f, MColor(0.0f, 0.0f, 0.0f)));
        }
        else
        {
            // Sort the ramp entries.
            std::sort(rampColors.begin(), rampColors.end());
        }

        std::stringstream ssp;
        ssp << "float[] ";

        std::stringstream ssc;
        ssc << "color[] ";
        for(size_t i = 0, e = rampColors.size(); i < e; ++i)
        {
            ssp << rampColors[i].m_pos << " ";
            ssc << rampColors[i].m_col.r << " " << rampColors[i].m_col.g << " " << rampColors[i].m_col.b << " ";
        }

        shaderParams.insert("in_position", ssp.str().c_str());
        shaderParams.insert("in_color"   , ssc.str().c_str());
    }
    else if(paramInfo.paramName == "in_color")
    {
        // We save the colors at the same time we save the positions.
    }
    else
    {
        ShadingNodeExporter::exportParameterValue(
            plug,
            paramInfo,
            shaderParams);
    }
}

RampExporter::RampExporter(
    const MObject&      object,
    asr::ShaderGroup&   shaderGroup)
  : ShadingNodeExporter(object, shaderGroup)
{
}
<|endoftext|>


<commit_before>/*
 * OpenCMISS-Zinc Library Unit Tests
 *
 * 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 <gtest/gtest.h>

#include <zinc/field.hpp>
#include <zinc/fieldcache.hpp>
#include <zinc/fieldconstant.hpp>
#include <zinc/fieldfiniteelement.hpp>
#include <zinc/fieldmeshoperators.hpp>
#include <zinc/fieldmodule.hpp>
#include <zinc/fieldsubobjectgroup.hpp>
#include <zinc/region.hpp>
#include <zinc/streamregion.hpp>

#include "utilities/zinctestsetupcpp.hpp"
#include "utilities/fileio.hpp"

#include "test_resources.h"

#define FIELDML_OUTPUT_FOLDER "fieldmltest"

ManageOutputFolder manageOutputFolderFieldML(FIELDML_OUTPUT_FOLDER);

namespace {

void check_cube_model(Fieldmodule& fm)
{
	int result;
	Field coordinates = fm.findFieldByName("coordinates");
	EXPECT_TRUE(coordinates.isValid());
	EXPECT_EQ(3, coordinates.getNumberOfComponents());
	EXPECT_TRUE(coordinates.isTypeCoordinate());

	Field pressure = fm.findFieldByName("pressure");
	EXPECT_TRUE(pressure.isValid());
	EXPECT_EQ(1, pressure.getNumberOfComponents());
	EXPECT_FALSE(pressure.isTypeCoordinate());

	EXPECT_EQ(OK, result = fm.defineAllFaces());
	Mesh mesh3d = fm.findMeshByDimension(3);
	EXPECT_EQ(1, mesh3d.getSize());
	Mesh mesh2d = fm.findMeshByDimension(2);
	EXPECT_EQ(6, mesh2d.getSize());
	Mesh mesh1d = fm.findMeshByDimension(1);
	EXPECT_EQ(12, mesh1d.getSize());
	Nodeset nodes = fm.findNodesetByFieldDomainType(Field::DOMAIN_TYPE_NODES);
	EXPECT_EQ(8, nodes.getSize());
	Element element = mesh3d.findElementByIdentifier(1);
	EXPECT_TRUE(element.isValid());
	EXPECT_EQ(Element::SHAPE_TYPE_CUBE, element.getShapeType());

	const double valueOne = 1.0;
	Field one = fm.createFieldConstant(1, &valueOne);
	FieldMeshIntegral volume = fm.createFieldMeshIntegral(one, coordinates, mesh3d);
	const int numberOfPoints = 2;
	EXPECT_EQ(OK, result = volume.setNumbersOfPoints(1, &numberOfPoints));
	FieldMeshIntegral surfacePressureIntegral = fm.createFieldMeshIntegral(pressure, coordinates, mesh2d);
	EXPECT_EQ(OK, result = surfacePressureIntegral.setNumbersOfPoints(1, &numberOfPoints));

	Fieldcache cache = fm.createFieldcache();
	double outVolume;
	EXPECT_EQ(OK, result = volume.evaluateReal(cache, 1, &outVolume));
	ASSERT_DOUBLE_EQ(1.0, outVolume);
	double outSurfacePressureIntegral;
	EXPECT_EQ(OK, result = surfacePressureIntegral.evaluateReal(cache, 1, &outSurfacePressureIntegral));
	ASSERT_DOUBLE_EQ(540000.0, outSurfacePressureIntegral);
}

}

// cube model defines a 3-D RC coordinates field and 1-D pressure field
// using the same trilinear Lagrange scalar template.
// field dofs and mesh nodes connectivity are inline text in the fieldml document
TEST(ZincRegion, read_fieldml_cube)
{
	ZincTestSetupCpp zinc;
	int result;

	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_CUBE_RESOURCE)));
	check_cube_model(zinc.fm);

	// test writing and re-reading into different region
	EXPECT_EQ(OK, result = zinc.root_region.writeFile(FIELDML_OUTPUT_FOLDER "/cube.fieldml"));
	Region testRegion = zinc.root_region.createChild("test");
	EXPECT_EQ(OK, result = testRegion.readFile(FIELDML_OUTPUT_FOLDER "/cube.fieldml"));
	Fieldmodule testFm = testRegion.getFieldmodule();
	check_cube_model(testFm);
}

// Also reads cube model, but tries to read it as EX format which should fail
TEST(ZincStreaminformationRegion, fileFormat)
{
	ZincTestSetupCpp zinc;
	int result;

	StreaminformationRegion streamInfo = zinc.root_region.createStreaminformationRegion();
	EXPECT_TRUE(streamInfo.isValid());
	StreamresourceFile fileResource = streamInfo.createStreamresourceFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_CUBE_RESOURCE));
	EXPECT_TRUE(fileResource.isValid());
	StreaminformationRegion::FileFormat fileFormat = streamInfo.getFileFormat();
	EXPECT_EQ(StreaminformationRegion::FILE_FORMAT_AUTOMATIC, fileFormat);
	EXPECT_EQ(OK, result = streamInfo.setFileFormat(StreaminformationRegion::FILE_FORMAT_EX));
	EXPECT_EQ(StreaminformationRegion::FILE_FORMAT_EX, fileFormat = streamInfo.getFileFormat());
	result = zinc.root_region.read(streamInfo);
	EXPECT_EQ(ERROR_GENERAL, result); // not in EX format
	EXPECT_EQ(OK, result = streamInfo.setFileFormat(StreaminformationRegion::FILE_FORMAT_FIELDML));
	EXPECT_EQ(StreaminformationRegion::FILE_FORMAT_FIELDML, fileFormat = streamInfo.getFileFormat());
	result = zinc.root_region.read(streamInfo);
	EXPECT_EQ(OK, result); // in FieldML format
	check_cube_model(zinc.fm);
}

namespace {

void check_tetmesh_model(Fieldmodule& fm)
{
	int result;
	Field coordinates = fm.findFieldByName("coordinates");
	EXPECT_TRUE(coordinates.isValid());
	EXPECT_EQ(3, coordinates.getNumberOfComponents());
	EXPECT_TRUE(coordinates.isTypeCoordinate());

	EXPECT_EQ(OK, result = fm.defineAllFaces());
	Mesh mesh3d = fm.findMeshByDimension(3);
	EXPECT_EQ(102, mesh3d.getSize());
	Mesh mesh2d = fm.findMeshByDimension(2);
	EXPECT_EQ(232, mesh2d.getSize());
	Mesh mesh1d = fm.findMeshByDimension(1);
	EXPECT_EQ(167, mesh1d.getSize());
	Nodeset nodes = fm.findNodesetByFieldDomainType(Field::DOMAIN_TYPE_NODES);
	EXPECT_EQ(38, nodes.getSize());
	for (int i = 1; i < 102; ++i)
	{
		Element element = mesh3d.findElementByIdentifier(i);
		EXPECT_TRUE(element.isValid());
		Element::ShapeType shapeType = element.getShapeType();
		EXPECT_EQ(Element::SHAPE_TYPE_TETRAHEDRON, shapeType);
	}

	const double valueOne = 1.0;
	Field one = fm.createFieldConstant(1, &valueOne);
	FieldMeshIntegral volume = fm.createFieldMeshIntegral(one, coordinates, mesh3d);
	EXPECT_TRUE(volume.isValid());

	FieldElementGroup exteriorFacesGroup = fm.createFieldElementGroup(mesh2d);
	EXPECT_TRUE(exteriorFacesGroup.isValid());
	EXPECT_EQ(OK, result = exteriorFacesGroup.setManaged(true));
	MeshGroup exteriorFacesMeshGroup = exteriorFacesGroup.getMeshGroup();
	EXPECT_TRUE(exteriorFacesMeshGroup.isValid());
	FieldIsExterior isExterior = fm.createFieldIsExterior();
	EXPECT_TRUE(isExterior.isValid());
	exteriorFacesMeshGroup.addElementsConditional(isExterior);
	EXPECT_EQ(56, exteriorFacesMeshGroup.getSize());
	FieldMeshIntegral surfaceArea = fm.createFieldMeshIntegral(one, coordinates, exteriorFacesMeshGroup);
	EXPECT_TRUE(surfaceArea.isValid());

	Fieldcache cache = fm.createFieldcache();
	double outVolume;
	EXPECT_EQ(OK, result = volume.evaluateReal(cache, 1, &outVolume));
	ASSERT_DOUBLE_EQ(0.41723178864303812, outVolume);
	double outSurfaceArea;
	EXPECT_EQ(OK, result = surfaceArea.evaluateReal(cache, 1, &outSurfaceArea));
	ASSERT_DOUBLE_EQ(2.7717561493468423, outSurfaceArea);
}

}

// tetmesh model defines a 3-D RC coordinates field over a tetrahedral
// mesh in approximate unit sphere shape with trilinearSimplex basis/
// node coordinates and connectivity are read from separate files
TEST(ZincRegion, read_fieldml_tetmesh)
{
	ZincTestSetupCpp zinc;
	int result;

	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_TETMESH_RESOURCE)));
	check_tetmesh_model(zinc.fm);

	// check can't merge cube model since it redefines element 1 shape
	result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_CUBE_RESOURCE));
	EXPECT_EQ(ERROR_INCOMPATIBLE_DATA, result);

	// test writing and re-reading into different region
	EXPECT_EQ(OK, result = zinc.root_region.writeFile(FIELDML_OUTPUT_FOLDER "/tetmesh.fieldml"));
	Region testRegion = zinc.root_region.createChild("test");
	EXPECT_EQ(OK, result = testRegion.readFile(FIELDML_OUTPUT_FOLDER "/tetmesh.fieldml"));
	Fieldmodule testFm = testRegion.getFieldmodule();
	check_tetmesh_model(testFm);
}

namespace {

void check_wheel_model(Fieldmodule& fm)
{
	int result;
	Field coordinates = fm.findFieldByName("coordinates");
	EXPECT_TRUE(coordinates.isValid());
	EXPECT_EQ(3, coordinates.getNumberOfComponents());
	EXPECT_TRUE(coordinates.isTypeCoordinate());

	EXPECT_EQ(OK, result = fm.defineAllFaces());
	Mesh mesh3d = fm.findMeshByDimension(3);
	EXPECT_EQ(12, mesh3d.getSize());
	Mesh mesh2d = fm.findMeshByDimension(2);
	EXPECT_EQ(48, mesh2d.getSize());
	Mesh mesh1d = fm.findMeshByDimension(1);
	EXPECT_EQ(61, mesh1d.getSize());
	Nodeset nodes = fm.findNodesetByFieldDomainType(Field::DOMAIN_TYPE_NODES);
	EXPECT_EQ(129, nodes.getSize());
	for (int i = 1; i < 12; ++i)
	{
		Element element = mesh3d.findElementByIdentifier(i);
		EXPECT_TRUE(element.isValid());
		Element::ShapeType shapeType = element.getShapeType();
		if (i <= 6)
			EXPECT_EQ(Element::SHAPE_TYPE_WEDGE12, shapeType);
		else
			EXPECT_EQ(Element::SHAPE_TYPE_CUBE, shapeType);
	}

	const double valueOne = 1.0;
	Field one = fm.createFieldConstant(1, &valueOne);
	FieldMeshIntegral volume = fm.createFieldMeshIntegral(one, coordinates, mesh3d);
	EXPECT_TRUE(volume.isValid());
	const int pointCount = 2;
	EXPECT_EQ(OK, result = volume.setNumbersOfPoints(1, &pointCount));

	FieldElementGroup exteriorFacesGroup = fm.createFieldElementGroup(mesh2d);
	EXPECT_TRUE(exteriorFacesGroup.isValid());
	EXPECT_EQ(OK, result = exteriorFacesGroup.setManaged(true));
	MeshGroup exteriorFacesMeshGroup = exteriorFacesGroup.getMeshGroup();
	EXPECT_TRUE(exteriorFacesMeshGroup.isValid());
	FieldIsExterior isExterior = fm.createFieldIsExterior();
	EXPECT_TRUE(isExterior.isValid());
	exteriorFacesMeshGroup.addElementsConditional(isExterior);
	EXPECT_EQ(30, exteriorFacesMeshGroup.getSize());
	FieldMeshIntegral surfaceArea = fm.createFieldMeshIntegral(one, coordinates, exteriorFacesMeshGroup);
	EXPECT_TRUE(surfaceArea.isValid());
	EXPECT_EQ(OK, result = surfaceArea.setNumbersOfPoints(1, &pointCount));

	Fieldcache cache = fm.createFieldcache();
	double outVolume;
	EXPECT_EQ(OK, result = volume.evaluateReal(cache, 1, &outVolume));
	ASSERT_DOUBLE_EQ(100.28718664065387, outVolume);
	double outSurfaceArea;
	EXPECT_EQ(OK, result = surfaceArea.evaluateReal(cache, 1, &outSurfaceArea));
	ASSERT_DOUBLE_EQ(150.53218306379620, outSurfaceArea);
}

}

// wheel_direct model defines a 3-D RC coordinates field over a wheel mesh
// consisting of 6 wedge elements in the centre, and 6 cube elements around
// them, all coordinates interpolated with triquadratic bases.
// This model tests having variant element shapes and a piecewise field
// template which directly maps element to function (basis + parameter map).
// It also reads shapeids, node coordinates and connectivity (for wedge and
// cube connectivity) from separate files, and the connectivity data uses
// dictionary of keys (DOK) format with key data in the first column of the
// same file.
TEST(ZincRegion, read_fieldml_wheel_direct)
{
	ZincTestSetupCpp zinc;
	int result;
	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_WHEEL_DIRECT_RESOURCE)));
	check_wheel_model(zinc.fm);
}

// wheel_indirect model is the same as the wheel_direct model except that it
// uses a more efficient indirect element-to-function map
TEST(ZincRegion, read_fieldml_wheel_indirect)
{
	ZincTestSetupCpp zinc;
	int result;
	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_WHEEL_INDIRECT_RESOURCE)));
	check_wheel_model(zinc.fm);

	// test writing and re-reading into different region
	EXPECT_EQ(OK, result = zinc.root_region.writeFile(FIELDML_OUTPUT_FOLDER "/wheel.fieldml"));
	Region testRegion = zinc.root_region.createChild("test");
	EXPECT_EQ(OK, result = testRegion.readFile(FIELDML_OUTPUT_FOLDER "/wheel.fieldml"));
	Fieldmodule testFm = testRegion.getFieldmodule();
	check_wheel_model(testFm);
}
<commit_msg>Loosen tolerance on FieldML tests to pass with less than full double precision serialisation. https://tracker.physiomeproject.org/show_bug.cgi?id=3827<commit_after>/*
 * OpenCMISS-Zinc Library Unit Tests
 *
 * 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 <gtest/gtest.h>

#include <zinc/field.hpp>
#include <zinc/fieldcache.hpp>
#include <zinc/fieldconstant.hpp>
#include <zinc/fieldfiniteelement.hpp>
#include <zinc/fieldmeshoperators.hpp>
#include <zinc/fieldmodule.hpp>
#include <zinc/fieldsubobjectgroup.hpp>
#include <zinc/region.hpp>
#include <zinc/streamregion.hpp>

#include "utilities/zinctestsetupcpp.hpp"
#include "utilities/fileio.hpp"

#include "test_resources.h"

#define FIELDML_OUTPUT_FOLDER "fieldmltest"

ManageOutputFolder manageOutputFolderFieldML(FIELDML_OUTPUT_FOLDER);

namespace {

void check_cube_model(Fieldmodule& fm)
{
	int result;
	Field coordinates = fm.findFieldByName("coordinates");
	EXPECT_TRUE(coordinates.isValid());
	EXPECT_EQ(3, coordinates.getNumberOfComponents());
	EXPECT_TRUE(coordinates.isTypeCoordinate());

	Field pressure = fm.findFieldByName("pressure");
	EXPECT_TRUE(pressure.isValid());
	EXPECT_EQ(1, pressure.getNumberOfComponents());
	EXPECT_FALSE(pressure.isTypeCoordinate());

	EXPECT_EQ(OK, result = fm.defineAllFaces());
	Mesh mesh3d = fm.findMeshByDimension(3);
	EXPECT_EQ(1, mesh3d.getSize());
	Mesh mesh2d = fm.findMeshByDimension(2);
	EXPECT_EQ(6, mesh2d.getSize());
	Mesh mesh1d = fm.findMeshByDimension(1);
	EXPECT_EQ(12, mesh1d.getSize());
	Nodeset nodes = fm.findNodesetByFieldDomainType(Field::DOMAIN_TYPE_NODES);
	EXPECT_EQ(8, nodes.getSize());
	Element element = mesh3d.findElementByIdentifier(1);
	EXPECT_TRUE(element.isValid());
	EXPECT_EQ(Element::SHAPE_TYPE_CUBE, element.getShapeType());

	const double valueOne = 1.0;
	Field one = fm.createFieldConstant(1, &valueOne);
	FieldMeshIntegral volume = fm.createFieldMeshIntegral(one, coordinates, mesh3d);
	const int numberOfPoints = 2;
	EXPECT_EQ(OK, result = volume.setNumbersOfPoints(1, &numberOfPoints));
	FieldMeshIntegral surfacePressureIntegral = fm.createFieldMeshIntegral(pressure, coordinates, mesh2d);
	EXPECT_EQ(OK, result = surfacePressureIntegral.setNumbersOfPoints(1, &numberOfPoints));

	Fieldcache cache = fm.createFieldcache();
	double outVolume;
	EXPECT_EQ(OK, result = volume.evaluateReal(cache, 1, &outVolume));
	ASSERT_DOUBLE_EQ(1.0, outVolume);
	double outSurfacePressureIntegral;
	EXPECT_EQ(OK, result = surfacePressureIntegral.evaluateReal(cache, 1, &outSurfacePressureIntegral));
	ASSERT_DOUBLE_EQ(540000.0, outSurfacePressureIntegral);
}

}

// cube model defines a 3-D RC coordinates field and 1-D pressure field
// using the same trilinear Lagrange scalar template.
// field dofs and mesh nodes connectivity are inline text in the fieldml document
TEST(ZincRegion, read_fieldml_cube)
{
	ZincTestSetupCpp zinc;
	int result;

	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_CUBE_RESOURCE)));
	check_cube_model(zinc.fm);

	// test writing and re-reading into different region
	EXPECT_EQ(OK, result = zinc.root_region.writeFile(FIELDML_OUTPUT_FOLDER "/cube.fieldml"));
	Region testRegion = zinc.root_region.createChild("test");
	EXPECT_EQ(OK, result = testRegion.readFile(FIELDML_OUTPUT_FOLDER "/cube.fieldml"));
	Fieldmodule testFm = testRegion.getFieldmodule();
	check_cube_model(testFm);
}

// Also reads cube model, but tries to read it as EX format which should fail
TEST(ZincStreaminformationRegion, fileFormat)
{
	ZincTestSetupCpp zinc;
	int result;

	StreaminformationRegion streamInfo = zinc.root_region.createStreaminformationRegion();
	EXPECT_TRUE(streamInfo.isValid());
	StreamresourceFile fileResource = streamInfo.createStreamresourceFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_CUBE_RESOURCE));
	EXPECT_TRUE(fileResource.isValid());
	StreaminformationRegion::FileFormat fileFormat = streamInfo.getFileFormat();
	EXPECT_EQ(StreaminformationRegion::FILE_FORMAT_AUTOMATIC, fileFormat);
	EXPECT_EQ(OK, result = streamInfo.setFileFormat(StreaminformationRegion::FILE_FORMAT_EX));
	EXPECT_EQ(StreaminformationRegion::FILE_FORMAT_EX, fileFormat = streamInfo.getFileFormat());
	result = zinc.root_region.read(streamInfo);
	EXPECT_EQ(ERROR_GENERAL, result); // not in EX format
	EXPECT_EQ(OK, result = streamInfo.setFileFormat(StreaminformationRegion::FILE_FORMAT_FIELDML));
	EXPECT_EQ(StreaminformationRegion::FILE_FORMAT_FIELDML, fileFormat = streamInfo.getFileFormat());
	result = zinc.root_region.read(streamInfo);
	EXPECT_EQ(OK, result); // in FieldML format
	check_cube_model(zinc.fm);
}

namespace {

void check_tetmesh_model(Fieldmodule& fm)
{
	int result;
	Field coordinates = fm.findFieldByName("coordinates");
	EXPECT_TRUE(coordinates.isValid());
	EXPECT_EQ(3, coordinates.getNumberOfComponents());
	EXPECT_TRUE(coordinates.isTypeCoordinate());

	EXPECT_EQ(OK, result = fm.defineAllFaces());
	Mesh mesh3d = fm.findMeshByDimension(3);
	EXPECT_EQ(102, mesh3d.getSize());
	Mesh mesh2d = fm.findMeshByDimension(2);
	EXPECT_EQ(232, mesh2d.getSize());
	Mesh mesh1d = fm.findMeshByDimension(1);
	EXPECT_EQ(167, mesh1d.getSize());
	Nodeset nodes = fm.findNodesetByFieldDomainType(Field::DOMAIN_TYPE_NODES);
	EXPECT_EQ(38, nodes.getSize());
	for (int i = 1; i < 102; ++i)
	{
		Element element = mesh3d.findElementByIdentifier(i);
		EXPECT_TRUE(element.isValid());
		Element::ShapeType shapeType = element.getShapeType();
		EXPECT_EQ(Element::SHAPE_TYPE_TETRAHEDRON, shapeType);
	}

	const double valueOne = 1.0;
	Field one = fm.createFieldConstant(1, &valueOne);
	FieldMeshIntegral volume = fm.createFieldMeshIntegral(one, coordinates, mesh3d);
	EXPECT_TRUE(volume.isValid());

	FieldElementGroup exteriorFacesGroup = fm.createFieldElementGroup(mesh2d);
	EXPECT_TRUE(exteriorFacesGroup.isValid());
	EXPECT_EQ(OK, result = exteriorFacesGroup.setManaged(true));
	MeshGroup exteriorFacesMeshGroup = exteriorFacesGroup.getMeshGroup();
	EXPECT_TRUE(exteriorFacesMeshGroup.isValid());
	FieldIsExterior isExterior = fm.createFieldIsExterior();
	EXPECT_TRUE(isExterior.isValid());
	exteriorFacesMeshGroup.addElementsConditional(isExterior);
	EXPECT_EQ(56, exteriorFacesMeshGroup.getSize());
	FieldMeshIntegral surfaceArea = fm.createFieldMeshIntegral(one, coordinates, exteriorFacesMeshGroup);
	EXPECT_TRUE(surfaceArea.isValid());

	Fieldcache cache = fm.createFieldcache();
	double outVolume;
	EXPECT_EQ(OK, result = volume.evaluateReal(cache, 1, &outVolume));
	//ASSERT_DOUBLE_EQ(0.41723178864303812, outVolume);
	EXPECT_NEAR(0.41723178864303812, outVolume, 0.5E-7);
	double outSurfaceArea;
	EXPECT_EQ(OK, result = surfaceArea.evaluateReal(cache, 1, &outSurfaceArea));
	//ASSERT_DOUBLE_EQ(2.7717561493468423, outSurfaceArea);
	EXPECT_NEAR(2.7717561493468423, outSurfaceArea, 1.0E-7);
}

}

// tetmesh model defines a 3-D RC coordinates field over a tetrahedral
// mesh in approximate unit sphere shape with trilinearSimplex basis/
// node coordinates and connectivity are read from separate files
TEST(ZincRegion, read_fieldml_tetmesh)
{
	ZincTestSetupCpp zinc;
	int result;

	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_TETMESH_RESOURCE)));
	check_tetmesh_model(zinc.fm);

	// check can't merge cube model since it redefines element 1 shape
	result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_CUBE_RESOURCE));
	EXPECT_EQ(ERROR_INCOMPATIBLE_DATA, result);

	// test writing and re-reading into different region
	EXPECT_EQ(OK, result = zinc.root_region.writeFile(FIELDML_OUTPUT_FOLDER "/tetmesh.fieldml"));
	Region testRegion = zinc.root_region.createChild("test");
	EXPECT_EQ(OK, result = testRegion.readFile(FIELDML_OUTPUT_FOLDER "/tetmesh.fieldml"));
	Fieldmodule testFm = testRegion.getFieldmodule();
	check_tetmesh_model(testFm);
}

namespace {

void check_wheel_model(Fieldmodule& fm)
{
	int result;
	Field coordinates = fm.findFieldByName("coordinates");
	EXPECT_TRUE(coordinates.isValid());
	EXPECT_EQ(3, coordinates.getNumberOfComponents());
	EXPECT_TRUE(coordinates.isTypeCoordinate());

	EXPECT_EQ(OK, result = fm.defineAllFaces());
	Mesh mesh3d = fm.findMeshByDimension(3);
	EXPECT_EQ(12, mesh3d.getSize());
	Mesh mesh2d = fm.findMeshByDimension(2);
	EXPECT_EQ(48, mesh2d.getSize());
	Mesh mesh1d = fm.findMeshByDimension(1);
	EXPECT_EQ(61, mesh1d.getSize());
	Nodeset nodes = fm.findNodesetByFieldDomainType(Field::DOMAIN_TYPE_NODES);
	EXPECT_EQ(129, nodes.getSize());
	for (int i = 1; i < 12; ++i)
	{
		Element element = mesh3d.findElementByIdentifier(i);
		EXPECT_TRUE(element.isValid());
		Element::ShapeType shapeType = element.getShapeType();
		if (i <= 6)
			EXPECT_EQ(Element::SHAPE_TYPE_WEDGE12, shapeType);
		else
			EXPECT_EQ(Element::SHAPE_TYPE_CUBE, shapeType);
	}

	const double valueOne = 1.0;
	Field one = fm.createFieldConstant(1, &valueOne);
	FieldMeshIntegral volume = fm.createFieldMeshIntegral(one, coordinates, mesh3d);
	EXPECT_TRUE(volume.isValid());
	const int pointCount = 2;
	EXPECT_EQ(OK, result = volume.setNumbersOfPoints(1, &pointCount));

	FieldElementGroup exteriorFacesGroup = fm.createFieldElementGroup(mesh2d);
	EXPECT_TRUE(exteriorFacesGroup.isValid());
	EXPECT_EQ(OK, result = exteriorFacesGroup.setManaged(true));
	MeshGroup exteriorFacesMeshGroup = exteriorFacesGroup.getMeshGroup();
	EXPECT_TRUE(exteriorFacesMeshGroup.isValid());
	FieldIsExterior isExterior = fm.createFieldIsExterior();
	EXPECT_TRUE(isExterior.isValid());
	exteriorFacesMeshGroup.addElementsConditional(isExterior);
	EXPECT_EQ(30, exteriorFacesMeshGroup.getSize());
	FieldMeshIntegral surfaceArea = fm.createFieldMeshIntegral(one, coordinates, exteriorFacesMeshGroup);
	EXPECT_TRUE(surfaceArea.isValid());
	EXPECT_EQ(OK, result = surfaceArea.setNumbersOfPoints(1, &pointCount));

	Fieldcache cache = fm.createFieldcache();
	double outVolume;
	EXPECT_EQ(OK, result = volume.evaluateReal(cache, 1, &outVolume));
	//ASSERT_DOUBLE_EQ(100.28718664065387, outVolume);
	EXPECT_NEAR(100.28718664065387, outVolume, 5.0E-5);
	double outSurfaceArea;
	EXPECT_EQ(OK, result = surfaceArea.evaluateReal(cache, 1, &outSurfaceArea));
	//ASSERT_DOUBLE_EQ(150.53218306379620, outSurfaceArea);
	EXPECT_NEAR(150.53218306379620, outSurfaceArea, 1.0E-4);
}

}

// wheel_direct model defines a 3-D RC coordinates field over a wheel mesh
// consisting of 6 wedge elements in the centre, and 6 cube elements around
// them, all coordinates interpolated with triquadratic bases.
// This model tests having variant element shapes and a piecewise field
// template which directly maps element to function (basis + parameter map).
// It also reads shapeids, node coordinates and connectivity (for wedge and
// cube connectivity) from separate files, and the connectivity data uses
// dictionary of keys (DOK) format with key data in the first column of the
// same file.
TEST(ZincRegion, read_fieldml_wheel_direct)
{
	ZincTestSetupCpp zinc;
	int result;
	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_WHEEL_DIRECT_RESOURCE)));
	check_wheel_model(zinc.fm);
}

// wheel_indirect model is the same as the wheel_direct model except that it
// uses a more efficient indirect element-to-function map
TEST(ZincRegion, read_fieldml_wheel_indirect)
{
	ZincTestSetupCpp zinc;
	int result;
	EXPECT_EQ(OK, result = zinc.root_region.readFile(
		TestResources::getLocation(TestResources::FIELDIO_FIELDML_WHEEL_INDIRECT_RESOURCE)));
	check_wheel_model(zinc.fm);

	// test writing and re-reading into different region
	EXPECT_EQ(OK, result = zinc.root_region.writeFile(FIELDML_OUTPUT_FOLDER "/wheel.fieldml"));
	Region testRegion = zinc.root_region.createChild("test");
	EXPECT_EQ(OK, result = testRegion.readFile(FIELDML_OUTPUT_FOLDER "/wheel.fieldml"));
	Fieldmodule testFm = testRegion.getFieldmodule();
	check_wheel_model(testFm);
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// ycsb_workload.cpp
//
// Identification: benchmark/ycsb/ycsb_workload.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <thread>
#include <algorithm>
#include <random>
#include <cstddef>
#include <limits>

#undef NDEBUG

#include "backend/benchmark/ycsb/ycsb_workload.h"
#include "backend/benchmark/ycsb/ycsb_configuration.h"
#include "backend/benchmark/ycsb/ycsb_loader.h"

#include "backend/catalog/manager.h"
#include "backend/catalog/schema.h"

#include "backend/common/types.h"
#include "backend/common/value.h"
#include "backend/common/value_factory.h"
#include "backend/common/logger.h"
#include "backend/common/timer.h"
#include "backend/common/generator.h"
#include "backend/common/platform.h"

#include "backend/concurrency/transaction.h"
#include "backend/concurrency/transaction_manager_factory.h"

#include "backend/executor/executor_context.h"
#include "backend/executor/abstract_executor.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/executor/materialization_executor.h"
#include "backend/executor/update_executor.h"
#include "backend/executor/index_scan_executor.h"

#include "backend/expression/abstract_expression.h"
#include "backend/expression/constant_value_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/comparison_expression.h"
#include "backend/expression/expression_util.h"

#include "backend/index/index_factory.h"

#include "backend/logging/log_manager.h"

#include "backend/planner/abstract_plan.h"
#include "backend/planner/materialization_plan.h"
#include "backend/planner/insert_plan.h"
#include "backend/planner/update_plan.h"
#include "backend/planner/index_scan_plan.h"

#include "backend/storage/data_table.h"
#include "backend/storage/table_factory.h"

namespace peloton {
namespace benchmark {
namespace ycsb {

/////////////////////////////
///// Random Generator //////
/////////////////////////////

// Helper function to pin current thread to a specific core
static void PinToCore(size_t core) {
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  CPU_SET(core, &cpuset);
  pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}

// Fast random number generator
class fast_random {
 public:
  fast_random(unsigned long seed) : seed(0) { set_seed0(seed); }

  inline unsigned long next() {
    return ((unsigned long)next(32) << 32) + next(32);
  }

  inline uint32_t next_u32() { return next(32); }

  inline uint16_t next_u16() { return (uint16_t)next(16); }

  /** [0.0, 1.0) */
  inline double next_uniform() {
    return (((unsigned long)next(26) << 27) + next(27)) / (double)(1L << 53);
  }

  inline char next_char() { return next(8) % 256; }

  inline char next_readable_char() {
    static const char readables[] =
        "0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
    return readables[next(6)];
  }

  inline std::string next_string(size_t len) {
    std::string s(len, 0);
    for (size_t i = 0; i < len; i++) s[i] = next_char();
    return s;
  }

  inline std::string next_readable_string(size_t len) {
    std::string s(len, 0);
    for (size_t i = 0; i < len; i++) s[i] = next_readable_char();
    return s;
  }

  inline unsigned long get_seed() { return seed; }

  inline void set_seed(unsigned long seed) { this->seed = seed; }

 private:
  inline void set_seed0(unsigned long seed) {
    this->seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
  }

  inline unsigned long next(unsigned int bits) {
    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
    return (unsigned long)(seed >> (48 - bits));
  }

  unsigned long seed;
};

class ZipfDistribution {
 public:
  ZipfDistribution(const uint64_t &n, const double &theta)
 : rand_generator(rand()) {
    // range: 1-n
    the_n = n;
    zipf_theta = theta;
    zeta_2_theta = zeta(2, zipf_theta);
    denom = zeta(the_n, zipf_theta);
  }

  double zeta(uint64_t n, double theta) {
    double sum = 0;
    for (uint64_t i = 1; i <= n; i++) sum += pow(1.0 / i, theta);
    return sum;
  }

  int GenerateInteger(const int &min, const int &max) {
    return rand_generator.next() % (max - min + 1) + min;
  }

  uint64_t GetNextNumber() {
    double alpha = 1 / (1 - zipf_theta);
    double zetan = denom;
    double eta =
        (1 - pow(2.0 / the_n, 1 - zipf_theta)) / (1 - zeta_2_theta / zetan);
    double u = (double)(GenerateInteger(1, 10000000) % 10000000) / 10000000;
    double uz = u * zetan;
    if (uz < 1) return 1;
    if (uz < 1 + pow(0.5, zipf_theta)) return 2;
    return 1 + (uint64_t)(the_n * pow(eta * u - eta + 1, alpha));
  }

  uint64_t the_n;
  double zipf_theta;
  double denom;
  double zeta_2_theta;
  fast_random rand_generator;
};

/////////////////////////////////////////////////////////
// TRANSACTION TYPES
/////////////////////////////////////////////////////////

bool RunRead(ZipfDistribution &zipf);

bool RunInsert(ZipfDistribution &zipf);

/////////////////////////////////////////////////////////
// WORKLOAD
/////////////////////////////////////////////////////////

// Used to control backend execution
volatile bool run_backends = true;

// Committed transaction counts
std::vector<double> transaction_counts;

// Next insert key
std::atomic<int> next_insert_key;

void RunBackend(oid_t thread_id) {
  PinToCore(thread_id);

  auto update_ratio = state.update_ratio;

  // Set zipfian skew
  auto zipf_theta = 0.0;
  if(state.skew_factor == SKEW_FACTOR_HIGH) {
    zipf_theta = 0.5;
  }

  fast_random rng(rand());
  ZipfDistribution zipf((state.scale_factor * DEFAULT_TUPLES_PER_TILEGROUP) - 1, zipf_theta);
  auto committed_transaction_count = 0;
  next_insert_key.store(state.scale_factor * DEFAULT_TUPLES_PER_TILEGROUP);

  // Run these many transactions
  while (true) {
    // Check if the backend should stop
    if (run_backends == false) {
      break;
    }

    auto rng_val = rng.next_uniform();
    auto transaction_status = false;

    // Run transaction
    if (rng_val < update_ratio) {
      transaction_status = RunInsert(zipf);
    }
    else {
      transaction_status = RunRead(zipf);
    }

    // Update transaction count if it committed
    if(transaction_status == true){
      committed_transaction_count++;
    }
  }

  // Set committed_transaction_count
  transaction_counts[thread_id] = committed_transaction_count;
}

void RunWorkload() {
  // Execute the workload to build the log
  std::vector<std::thread> thread_group;
  oid_t num_threads = state.backend_count;
  transaction_counts.resize(num_threads);

  // Launch a group of threads
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group.push_back(std::move(std::thread(RunBackend, thread_itr)));
  }

  // Sleep for duration specified by user and then stop the backends
  auto sleep_period = std::chrono::milliseconds(state.duration);
  std::this_thread::sleep_for(sleep_period);
  run_backends = false;

  // Join the threads with the main thread
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group[thread_itr].join();
  }

  // Compute total committed transactions
  auto sum_transaction_count = 0;
  for(auto transaction_count : transaction_counts){
    sum_transaction_count += transaction_count;
  }

  // Compute average throughput and latency
  state.throughput = (sum_transaction_count * 1000)/state.duration;
  state.latency = state.backend_count/state.throughput;
}

/////////////////////////////////////////////////////////
// HARNESS
/////////////////////////////////////////////////////////

static void ExecuteTest(std::vector<executor::AbstractExecutor *> &executors) {
  bool status = false;

  // Run all the executors
  for (auto executor : executors) {
    status = executor->Init();
    if (status == false) {
      throw Exception("Init failed");
    }

    std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

    // Execute stuff
    while (executor->Execute() == true) {
      std::unique_ptr<executor::LogicalTile> result_tile(executor->GetOutput());
      result_tiles.emplace_back(result_tile.release());
    }
  }
}

static bool EndTransaction(concurrency::Transaction *txn) {
  auto result = txn->GetResult();
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  if (result == Result::RESULT_FAILURE) {
    LOG_ERROR("Insert failed : %d", next_insert_key.load());
  }

  // transaction passed execution.
  if (result == Result::RESULT_SUCCESS) {
    result = txn_manager.CommitTransaction();

    if (result == Result::RESULT_SUCCESS) {
      // transaction committed
      return true;
    } else {
      // transaction aborted or failed
      assert(result == Result::RESULT_ABORTED ||
             result == Result::RESULT_FAILURE);
      return false;
    }
  }
  // transaction aborted during execution.
  else {
    assert(result == Result::RESULT_ABORTED ||
           result == Result::RESULT_FAILURE);
    result = txn_manager.AbortTransaction();
    return false;
  }
}

/////////////////////////////////////////////////////////
// TRANSACTIONS
/////////////////////////////////////////////////////////

bool RunRead(ZipfDistribution &zipf) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  auto txn = txn_manager.BeginTransaction();

  /////////////////////////////////////////////////////////
  // INDEX SCAN + PREDICATE
  /////////////////////////////////////////////////////////

  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));

  // Column ids to be added to logical tile after scan.
  std::vector<oid_t> column_ids;
  oid_t column_count = state.column_count + 1;

  for (oid_t col_itr = 0; col_itr < column_count; col_itr++) {
    column_ids.push_back(col_itr);
  }

  // Create and set up index scan executor

  std::vector<oid_t> key_column_ids;
  std::vector<ExpressionType> expr_types;
  std::vector<Value> values;
  std::vector<expression::AbstractExpression *> runtime_keys;

  auto lookup_key = zipf.GetNextNumber();

  key_column_ids.push_back(0);
  expr_types.push_back(
      ExpressionType::EXPRESSION_TYPE_COMPARE_EQUAL);
  values.push_back(ValueFactory::GetIntegerValue(lookup_key));

  auto ycsb_pkey_index = user_table->GetIndexWithOid(
      user_table_pkey_index_oid);

  planner::IndexScanPlan::IndexScanDesc index_scan_desc(
      ycsb_pkey_index, key_column_ids, expr_types, values, runtime_keys);

  // Create plan node.
  auto predicate = nullptr;

  planner::IndexScanPlan index_scan_node(user_table,
                                         predicate, column_ids,
                                         index_scan_desc);

  // Run the executor
  executor::IndexScanExecutor index_scan_executor(&index_scan_node,
                                                  context.get());

  /////////////////////////////////////////////////////////
  // MATERIALIZE
  /////////////////////////////////////////////////////////

  // Create and set up materialization executor
  std::unordered_map<oid_t, oid_t> old_to_new_cols;
  for (oid_t col_itr = 0; col_itr < column_count; col_itr++) {
    old_to_new_cols[col_itr] = col_itr;
  }

  std::shared_ptr<const catalog::Schema> output_schema {
    catalog::Schema::CopySchema(user_table->GetSchema())
  };

  bool physify_flag = true;  // is going to create a physical tile
  planner::MaterializationPlan mat_node(old_to_new_cols,
                                        output_schema,
                                        physify_flag);

  executor::MaterializationExecutor mat_executor(&mat_node, nullptr);
  mat_executor.AddChild(&index_scan_executor);

  /////////////////////////////////////////////////////////
  // EXECUTE
  /////////////////////////////////////////////////////////

  std::vector<executor::AbstractExecutor *> executors;
  executors.push_back(&mat_executor);

  ExecuteTest(executors);

  auto txn_status = EndTransaction(txn);
  return txn_status;
}

bool RunInsert(__attribute__((unused)) ZipfDistribution &zipf) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  const oid_t col_count = state.column_count + 1;
  auto table_schema = user_table->GetSchema();
  const bool allocate = true;
  std::string field_raw_value(ycsb_field_length - 1, 'o');

  std::unique_ptr<VarlenPool> pool(new VarlenPool(BACKEND_TYPE_MM));

  auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));

  /////////////////////////////////////////////////////////
  // INSERT
  /////////////////////////////////////////////////////////

  std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(table_schema, allocate));

  next_insert_key++;
  auto key_value = ValueFactory::GetIntegerValue(next_insert_key);
  auto field_value = ValueFactory::GetStringValue(field_raw_value);

  tuple->SetValue(0, key_value, nullptr);
  for (oid_t col_itr = 1; col_itr < col_count; col_itr++) {
    tuple->SetValue(col_itr, field_value, pool.get());
  }

  planner::InsertPlan insert_node(user_table, std::move(tuple));
  executor::InsertExecutor insert_executor(&insert_node, context.get());

  /////////////////////////////////////////////////////////
  // EXECUTE
  /////////////////////////////////////////////////////////

  std::vector<executor::AbstractExecutor *> executors;
  executors.push_back(&insert_executor);

  ExecuteTest(executors);

  auto txn_status = EndTransaction(txn);
  return txn_status;
}

}  // namespace ycsb
}  // namespace benchmark
}  // namespace peloton
<commit_msg>Partition ycsb domain space<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// ycsb_workload.cpp
//
// Identification: benchmark/ycsb/ycsb_workload.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <thread>
#include <algorithm>
#include <random>
#include <cstddef>
#include <limits>

#undef NDEBUG

#include "backend/benchmark/ycsb/ycsb_workload.h"
#include "backend/benchmark/ycsb/ycsb_configuration.h"
#include "backend/benchmark/ycsb/ycsb_loader.h"

#include "backend/catalog/manager.h"
#include "backend/catalog/schema.h"

#include "backend/common/types.h"
#include "backend/common/value.h"
#include "backend/common/value_factory.h"
#include "backend/common/logger.h"
#include "backend/common/timer.h"
#include "backend/common/generator.h"
#include "backend/common/platform.h"

#include "backend/concurrency/transaction.h"
#include "backend/concurrency/transaction_manager_factory.h"

#include "backend/executor/executor_context.h"
#include "backend/executor/abstract_executor.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/executor/materialization_executor.h"
#include "backend/executor/update_executor.h"
#include "backend/executor/index_scan_executor.h"

#include "backend/expression/abstract_expression.h"
#include "backend/expression/constant_value_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/comparison_expression.h"
#include "backend/expression/expression_util.h"

#include "backend/index/index_factory.h"

#include "backend/logging/log_manager.h"

#include "backend/planner/abstract_plan.h"
#include "backend/planner/materialization_plan.h"
#include "backend/planner/insert_plan.h"
#include "backend/planner/update_plan.h"
#include "backend/planner/index_scan_plan.h"

#include "backend/storage/data_table.h"
#include "backend/storage/table_factory.h"

namespace peloton {
namespace benchmark {
namespace ycsb {

/////////////////////////////
///// Random Generator //////
/////////////////////////////

// Helper function to pin current thread to a specific core
static void PinToCore(size_t core) {
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  CPU_SET(core, &cpuset);
  pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}

// Fast random number generator
class fast_random {
 public:
  fast_random(unsigned long seed) : seed(0) { set_seed0(seed); }

  inline unsigned long next() {
    return ((unsigned long)next(32) << 32) + next(32);
  }

  inline uint32_t next_u32() { return next(32); }

  inline uint16_t next_u16() { return (uint16_t)next(16); }

  /** [0.0, 1.0) */
  inline double next_uniform() {
    return (((unsigned long)next(26) << 27) + next(27)) / (double)(1L << 53);
  }

  inline char next_char() { return next(8) % 256; }

  inline char next_readable_char() {
    static const char readables[] =
        "0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
    return readables[next(6)];
  }

  inline std::string next_string(size_t len) {
    std::string s(len, 0);
    for (size_t i = 0; i < len; i++) s[i] = next_char();
    return s;
  }

  inline std::string next_readable_string(size_t len) {
    std::string s(len, 0);
    for (size_t i = 0; i < len; i++) s[i] = next_readable_char();
    return s;
  }

  inline unsigned long get_seed() { return seed; }

  inline void set_seed(unsigned long seed) { this->seed = seed; }

 private:
  inline void set_seed0(unsigned long seed) {
    this->seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
  }

  inline unsigned long next(unsigned int bits) {
    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
    return (unsigned long)(seed >> (48 - bits));
  }

  unsigned long seed;
};

class ZipfDistribution {
 public:
  ZipfDistribution(const uint64_t &n, const double &theta)
 : rand_generator(rand()) {
    // range: 1-n
    the_n = n;
    zipf_theta = theta;
    zeta_2_theta = zeta(2, zipf_theta);
    denom = zeta(the_n, zipf_theta);
  }

  double zeta(uint64_t n, double theta) {
    double sum = 0;
    for (uint64_t i = 1; i <= n; i++) sum += pow(1.0 / i, theta);
    return sum;
  }

  int GenerateInteger(const int &min, const int &max) {
    return rand_generator.next() % (max - min + 1) + min;
  }

  uint64_t GetNextNumber() {
    double alpha = 1 / (1 - zipf_theta);
    double zetan = denom;
    double eta =
        (1 - pow(2.0 / the_n, 1 - zipf_theta)) / (1 - zeta_2_theta / zetan);
    double u = (double)(GenerateInteger(1, 10000000) % 10000000) / 10000000;
    double uz = u * zetan;
    if (uz < 1) return 1;
    if (uz < 1 + pow(0.5, zipf_theta)) return 2;
    return 1 + (uint64_t)(the_n * pow(eta * u - eta + 1, alpha));
  }

  uint64_t the_n;
  double zipf_theta;
  double denom;
  double zeta_2_theta;
  fast_random rand_generator;
};

/////////////////////////////////////////////////////////
// TRANSACTION TYPES
/////////////////////////////////////////////////////////

bool RunRead(ZipfDistribution &zipf);

bool RunInsert(ZipfDistribution &zipf, oid_t next_insert_key);

/////////////////////////////////////////////////////////
// WORKLOAD
/////////////////////////////////////////////////////////

// Used to control backend execution
volatile bool run_backends = true;

// Committed transaction counts
std::vector<double> transaction_counts;

void RunBackend(oid_t thread_id) {
  PinToCore(thread_id);

  auto update_ratio = state.update_ratio;

  // Set zipfian skew
  auto zipf_theta = 0.0;
  if(state.skew_factor == SKEW_FACTOR_HIGH) {
    zipf_theta = 0.5;
  }

  fast_random rng(rand());
  ZipfDistribution zipf((state.scale_factor * DEFAULT_TUPLES_PER_TILEGROUP) - 1, zipf_theta);
  auto committed_transaction_count = 0;

  // Partition the domain across backends
  auto insert_key_offset = state.scale_factor * DEFAULT_TUPLES_PER_TILEGROUP;
  auto next_insert_key = insert_key_offset + thread_id + 1;

  // Run these many transactions
  while (true) {
    // Check if the backend should stop
    if (run_backends == false) {
      break;
    }

    auto rng_val = rng.next_uniform();
    auto transaction_status = false;

    // Run transaction
    if (rng_val < update_ratio) {
      next_insert_key += state.backend_count;
      transaction_status = RunInsert(zipf, next_insert_key);
    }
    else {
      transaction_status = RunRead(zipf);
    }

    // Update transaction count if it committed
    if(transaction_status == true){
      committed_transaction_count++;
    }
  }

  // Set committed_transaction_count
  transaction_counts[thread_id] = committed_transaction_count;
}

void RunWorkload() {
  // Execute the workload to build the log
  std::vector<std::thread> thread_group;
  oid_t num_threads = state.backend_count;
  transaction_counts.resize(num_threads);

  // Launch a group of threads
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group.push_back(std::move(std::thread(RunBackend, thread_itr)));
  }

  // Sleep for duration specified by user and then stop the backends
  auto sleep_period = std::chrono::milliseconds(state.duration);
  std::this_thread::sleep_for(sleep_period);
  run_backends = false;

  // Join the threads with the main thread
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group[thread_itr].join();
  }

  // Compute total committed transactions
  auto sum_transaction_count = 0;
  for(auto transaction_count : transaction_counts){
    sum_transaction_count += transaction_count;
  }

  // Compute average throughput and latency
  state.throughput = (sum_transaction_count * 1000)/state.duration;
  state.latency = state.backend_count/state.throughput;
}

/////////////////////////////////////////////////////////
// HARNESS
/////////////////////////////////////////////////////////

static void ExecuteTest(std::vector<executor::AbstractExecutor *> &executors) {
  bool status = false;

  // Run all the executors
  for (auto executor : executors) {
    status = executor->Init();
    if (status == false) {
      throw Exception("Init failed");
    }

    std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

    // Execute stuff
    while (executor->Execute() == true) {
      std::unique_ptr<executor::LogicalTile> result_tile(executor->GetOutput());
      result_tiles.emplace_back(result_tile.release());
    }
  }
}

static bool EndTransaction(concurrency::Transaction *txn) {
  auto result = txn->GetResult();
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  // transaction passed execution.
  if (result == Result::RESULT_SUCCESS) {
    result = txn_manager.CommitTransaction();

    if (result == Result::RESULT_SUCCESS) {
      // transaction committed
      return true;
    } else {
      // transaction aborted or failed
      assert(result == Result::RESULT_ABORTED ||
             result == Result::RESULT_FAILURE);
      return false;
    }
  }
  // transaction aborted during execution.
  else {
    assert(result == Result::RESULT_ABORTED ||
           result == Result::RESULT_FAILURE);
    result = txn_manager.AbortTransaction();
    return false;
  }
}

/////////////////////////////////////////////////////////
// TRANSACTIONS
/////////////////////////////////////////////////////////

bool RunRead(ZipfDistribution &zipf) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  auto txn = txn_manager.BeginTransaction();

  /////////////////////////////////////////////////////////
  // INDEX SCAN + PREDICATE
  /////////////////////////////////////////////////////////

  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));

  // Column ids to be added to logical tile after scan.
  std::vector<oid_t> column_ids;
  oid_t column_count = state.column_count + 1;

  for (oid_t col_itr = 0; col_itr < column_count; col_itr++) {
    column_ids.push_back(col_itr);
  }

  // Create and set up index scan executor

  std::vector<oid_t> key_column_ids;
  std::vector<ExpressionType> expr_types;
  std::vector<Value> values;
  std::vector<expression::AbstractExpression *> runtime_keys;

  auto lookup_key = zipf.GetNextNumber();

  key_column_ids.push_back(0);
  expr_types.push_back(
      ExpressionType::EXPRESSION_TYPE_COMPARE_EQUAL);
  values.push_back(ValueFactory::GetIntegerValue(lookup_key));

  auto ycsb_pkey_index = user_table->GetIndexWithOid(
      user_table_pkey_index_oid);

  planner::IndexScanPlan::IndexScanDesc index_scan_desc(
      ycsb_pkey_index, key_column_ids, expr_types, values, runtime_keys);

  // Create plan node.
  auto predicate = nullptr;

  planner::IndexScanPlan index_scan_node(user_table,
                                         predicate, column_ids,
                                         index_scan_desc);

  // Run the executor
  executor::IndexScanExecutor index_scan_executor(&index_scan_node,
                                                  context.get());

  /////////////////////////////////////////////////////////
  // MATERIALIZE
  /////////////////////////////////////////////////////////

  // Create and set up materialization executor
  std::unordered_map<oid_t, oid_t> old_to_new_cols;
  for (oid_t col_itr = 0; col_itr < column_count; col_itr++) {
    old_to_new_cols[col_itr] = col_itr;
  }

  std::shared_ptr<const catalog::Schema> output_schema {
    catalog::Schema::CopySchema(user_table->GetSchema())
  };

  bool physify_flag = true;  // is going to create a physical tile
  planner::MaterializationPlan mat_node(old_to_new_cols,
                                        output_schema,
                                        physify_flag);

  executor::MaterializationExecutor mat_executor(&mat_node, nullptr);
  mat_executor.AddChild(&index_scan_executor);

  /////////////////////////////////////////////////////////
  // EXECUTE
  /////////////////////////////////////////////////////////

  std::vector<executor::AbstractExecutor *> executors;
  executors.push_back(&mat_executor);

  ExecuteTest(executors);

  auto txn_status = EndTransaction(txn);
  return txn_status;
}

bool RunInsert(__attribute__((unused)) ZipfDistribution &zipf,
               oid_t next_insert_key) {
  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  const oid_t col_count = state.column_count + 1;
  auto table_schema = user_table->GetSchema();
  const bool allocate = true;
  std::string field_raw_value(ycsb_field_length - 1, 'o');

  std::unique_ptr<VarlenPool> pool(new VarlenPool(BACKEND_TYPE_MM));

  auto txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));

  /////////////////////////////////////////////////////////
  // INSERT
  /////////////////////////////////////////////////////////

  std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(table_schema, allocate));
  auto key_value = ValueFactory::GetIntegerValue(next_insert_key);
  auto field_value = ValueFactory::GetStringValue(field_raw_value);

  tuple->SetValue(0, key_value, nullptr);
  for (oid_t col_itr = 1; col_itr < col_count; col_itr++) {
    tuple->SetValue(col_itr, field_value, pool.get());
  }

  planner::InsertPlan insert_node(user_table, std::move(tuple));
  executor::InsertExecutor insert_executor(&insert_node, context.get());

  /////////////////////////////////////////////////////////
  // EXECUTE
  /////////////////////////////////////////////////////////

  std::vector<executor::AbstractExecutor *> executors;
  executors.push_back(&insert_executor);

  ExecuteTest(executors);

  auto txn_status = EndTransaction(txn);
  return txn_status;
}

}  // namespace ycsb
}  // namespace benchmark
}  // namespace peloton
<|endoftext|>