<commit_before>#ifndef diff_hh_INCLUDED
#define diff_hh_INCLUDED

// Implementation of the linear space variant of the algorithm described in
// "An O(ND) Difference Algorithm and Its Variations"
// (http://xmailserver.org/diff2.pdf)

#include "array_view.hh"
#include "vector.hh"

#include <functional>
#include <iterator>

namespace Kakoune
{

struct Snake{ int x, y, u, v; bool add; };

template<typename Iterator, typename Equal>
Snake find_end_snake_of_further_reaching_dpath(Iterator a, int N, Iterator b, int M,
                                               const int* V, const int D, const int k, Equal eq)
{
    const bool add = k == -D or (k != D and V[k-1] < V[k+1]);

    // if diagonal on the right goes further along x than diagonal on the left,
    // then we take a vertical edge from it to this diagonal, hence x = V[k+1]
    // else, we take an horizontal edge from our left diagonal,x = V[k-1]+1
    const int x = add ? V[k+1] : V[k-1]+1;
    // we are by construction on diagonal k, so our position along b (y) is x - k.
    const int y = x - k;

    int u = x, v = y;
    // follow end snake along diagonal k
    while (u < N and v < M and eq(a[u], b[v]))
        ++u, ++v;

    return { x, y, u, v, add };
}

struct SnakeLen : Snake
{
    SnakeLen(Snake s, bool reverse, int d) : Snake(s), reverse(reverse), d(d) {}
    const bool reverse;
    const int d;
};

template<typename Iterator, typename Equal>
SnakeLen find_middle_snake(Iterator a, int N, Iterator b, int M,
                           int* V1, int* V2, Equal eq)
{
    const int delta = N - M;
    V1[1] = 0;
    V2[1] = 0;

    std::reverse_iterator<Iterator> ra{a + N}, rb{b + M};

    for (int D = 0; D <= (M + N + 1) / 2; ++D)
    {
        for (int k1 = -D; k1 <= D; k1 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(a, N, b, M, V1, D, k1, eq);
            V1[k1] = p.u;

            const int k2 = -(k1 - delta);
            if ((delta % 2 != 0) and -(D-1) <= k2 and k2 <= (D-1))
            {
                if (V1[k1] + V2[k2] >= N)
                    return { p, false, 2 * D - 1 };// return last snake on forward path
            }
        }

        for (int k2 = -D; k2 <= D; k2 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(ra, N, rb, M, V2, D, k2, eq);
            V2[k2] = p.u;

            const int k1 = -(k2 - delta);
            if ((delta % 2 == 0) and -D <= k1 and k1 <= D)
            {
                if (V1[k1] + V2[k2] >= N)
                    return { { N - p.u, M - p.v, N - p.x , M - p.y, p.add } , true, 2 * D };// return last snake on reverse path
            }
        }
    }

    kak_assert(false);
    return { {}, false, 0 };
}

struct Diff
{
    enum { Keep, Add, Remove } mode;
    int len;
    int posB;
};

inline void append_diff(Vector<Diff>& diffs, Diff diff)
{
    if (diff.len == 0)
        return;

    if (not diffs.empty() and diffs.back().mode == diff.mode
        and (diff.mode != Diff::Add or
             diffs.back().posB + diffs.back().len == diff.posB))
        diffs.back().len += diff.len;
    else
        diffs.push_back(diff);
}

template<typename Iterator, typename Equal>
void find_diff_rec(Iterator a, int begA, int endA,
                   Iterator b, int begB, int endB,
                   int* V1, int* V2, Equal eq, Vector<Diff>& diffs)
{
    int prefix_len = 0;
    while (begA != endA and begB != endB and a[begA] == b[begB])
         ++begA, ++begB, ++prefix_len;

    int suffix_len = 0;
    while (begA != endA and begB != endB and a[endA-1] == b[endB-1])
        --endA, --endB, ++suffix_len;

    append_diff(diffs, {Diff::Keep, prefix_len, 0});

    const auto lenA = endA - begA, lenB = endB - begB;

    if (lenA == 0)
        append_diff(diffs, {Diff::Add, lenB, begB});
    else if (lenB == 0)
        append_diff(diffs, {Diff::Remove, lenA, 0});
    else
    {
        auto snake = find_middle_snake(a + begA, lenA, b + begB, lenB, V1, V2, eq);
        kak_assert(snake.d > 0 and snake.u <= lenA and snake.v <= lenB);
        const bool recurse = snake.d > 1;

        if (recurse)
            find_diff_rec(a, begA, begA + snake.x - (snake.reverse ? 0 : (snake.add ? 0 : 1)),
                          b, begB, begB + snake.y - (snake.reverse ? 0 : (snake.add ? 1 : 0)),
                          V1, V2, eq, diffs);

        if (not snake.reverse)
            append_diff(diffs, snake.add ? Diff{Diff::Add, 1, begB + snake.y - 1}
                                         : Diff{Diff::Remove, 1, 0});

        append_diff(diffs, {Diff::Keep, snake.u - snake.x, 0});

        if (snake.reverse)
            append_diff(diffs, snake.add ? Diff{Diff::Add, 1, begB + snake.v}
                                         : Diff{Diff::Remove, 1, 0});

        if (recurse)
            find_diff_rec(a, begA + snake.u + (snake.reverse ? (snake.add ? 0 : 1) : 0), endA,
                          b, begB + snake.v + (snake.reverse ? (snake.add ? 1 : 0) : 0), endB,
                          V1, V2, eq, diffs);
    }

    append_diff(diffs, {Diff::Keep, suffix_len, 0});
}

template<typename Iterator, typename Equal = std::equal_to<typename std::iterator_traits<Iterator>::value_type>>
Vector<Diff> find_diff(Iterator a, int N, Iterator b, int M, Equal eq = Equal{})
{
    const int max = 2 * (N + M) + 1;
    Vector<int> data(2*max);
    Vector<Diff> diffs;
    find_diff_rec(a, 0, N, b, 0, M, &data[N+M], &data[max + N+M], eq, diffs);

    return diffs;
}

}

#endif // diff_hh_INCLUDED
<commit_msg>Use the provided equal functor for prefix/suffix detection in diff<commit_after>#ifndef diff_hh_INCLUDED
#define diff_hh_INCLUDED

// Implementation of the linear space variant of the algorithm described in
// "An O(ND) Difference Algorithm and Its Variations"
// (http://xmailserver.org/diff2.pdf)

#include "array_view.hh"
#include "vector.hh"

#include <functional>
#include <iterator>

namespace Kakoune
{

struct Snake{ int x, y, u, v; bool add; };

template<typename Iterator, typename Equal>
Snake find_end_snake_of_further_reaching_dpath(Iterator a, int N, Iterator b, int M,
                                               const int* V, const int D, const int k, Equal eq)
{
    const bool add = k == -D or (k != D and V[k-1] < V[k+1]);

    // if diagonal on the right goes further along x than diagonal on the left,
    // then we take a vertical edge from it to this diagonal, hence x = V[k+1]
    // else, we take an horizontal edge from our left diagonal,x = V[k-1]+1
    const int x = add ? V[k+1] : V[k-1]+1;
    // we are by construction on diagonal k, so our position along b (y) is x - k.
    const int y = x - k;

    int u = x, v = y;
    // follow end snake along diagonal k
    while (u < N and v < M and eq(a[u], b[v]))
        ++u, ++v;

    return { x, y, u, v, add };
}

struct SnakeLen : Snake
{
    SnakeLen(Snake s, bool reverse, int d) : Snake(s), reverse(reverse), d(d) {}
    const bool reverse;
    const int d;
};

template<typename Iterator, typename Equal>
SnakeLen find_middle_snake(Iterator a, int N, Iterator b, int M,
                           int* V1, int* V2, Equal eq)
{
    const int delta = N - M;
    V1[1] = 0;
    V2[1] = 0;

    std::reverse_iterator<Iterator> ra{a + N}, rb{b + M};

    for (int D = 0; D <= (M + N + 1) / 2; ++D)
    {
        for (int k1 = -D; k1 <= D; k1 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(a, N, b, M, V1, D, k1, eq);
            V1[k1] = p.u;

            const int k2 = -(k1 - delta);
            if ((delta % 2 != 0) and -(D-1) <= k2 and k2 <= (D-1))
            {
                if (V1[k1] + V2[k2] >= N)
                    return { p, false, 2 * D - 1 };// return last snake on forward path
            }
        }

        for (int k2 = -D; k2 <= D; k2 += 2)
        {
            auto p = find_end_snake_of_further_reaching_dpath(ra, N, rb, M, V2, D, k2, eq);
            V2[k2] = p.u;

            const int k1 = -(k2 - delta);
            if ((delta % 2 == 0) and -D <= k1 and k1 <= D)
            {
                if (V1[k1] + V2[k2] >= N)
                    return { { N - p.u, M - p.v, N - p.x , M - p.y, p.add } , true, 2 * D };// return last snake on reverse path
            }
        }
    }

    kak_assert(false);
    return { {}, false, 0 };
}

struct Diff
{
    enum { Keep, Add, Remove } mode;
    int len;
    int posB;
};

inline void append_diff(Vector<Diff>& diffs, Diff diff)
{
    if (diff.len == 0)
        return;

    if (not diffs.empty() and diffs.back().mode == diff.mode
        and (diff.mode != Diff::Add or
             diffs.back().posB + diffs.back().len == diff.posB))
        diffs.back().len += diff.len;
    else
        diffs.push_back(diff);
}

template<typename Iterator, typename Equal>
void find_diff_rec(Iterator a, int begA, int endA,
                   Iterator b, int begB, int endB,
                   int* V1, int* V2, Equal eq, Vector<Diff>& diffs)
{
    int prefix_len = 0;
    while (begA != endA and begB != endB and eq(a[begA], b[begB]))
         ++begA, ++begB, ++prefix_len;

    int suffix_len = 0;
    while (begA != endA and begB != endB and eq(a[endA-1], b[endB-1]))
        --endA, --endB, ++suffix_len;

    append_diff(diffs, {Diff::Keep, prefix_len, 0});

    const auto lenA = endA - begA, lenB = endB - begB;

    if (lenA == 0)
        append_diff(diffs, {Diff::Add, lenB, begB});
    else if (lenB == 0)
        append_diff(diffs, {Diff::Remove, lenA, 0});
    else
    {
        auto snake = find_middle_snake(a + begA, lenA, b + begB, lenB, V1, V2, eq);
        kak_assert(snake.d > 0 and snake.u <= lenA and snake.v <= lenB);
        const bool recurse = snake.d > 1;

        if (recurse)
            find_diff_rec(a, begA, begA + snake.x - (snake.reverse ? 0 : (snake.add ? 0 : 1)),
                          b, begB, begB + snake.y - (snake.reverse ? 0 : (snake.add ? 1 : 0)),
                          V1, V2, eq, diffs);

        if (not snake.reverse)
            append_diff(diffs, snake.add ? Diff{Diff::Add, 1, begB + snake.y - 1}
                                         : Diff{Diff::Remove, 1, 0});

        append_diff(diffs, {Diff::Keep, snake.u - snake.x, 0});

        if (snake.reverse)
            append_diff(diffs, snake.add ? Diff{Diff::Add, 1, begB + snake.v}
                                         : Diff{Diff::Remove, 1, 0});

        if (recurse)
            find_diff_rec(a, begA + snake.u + (snake.reverse ? (snake.add ? 0 : 1) : 0), endA,
                          b, begB + snake.v + (snake.reverse ? (snake.add ? 1 : 0) : 0), endB,
                          V1, V2, eq, diffs);
    }

    append_diff(diffs, {Diff::Keep, suffix_len, 0});
}

template<typename Iterator, typename Equal = std::equal_to<typename std::iterator_traits<Iterator>::value_type>>
Vector<Diff> find_diff(Iterator a, int N, Iterator b, int M, Equal eq = Equal{})
{
    const int max = 2 * (N + M) + 1;
    Vector<int> data(2*max);
    Vector<Diff> diffs;
    find_diff_rec(a, 0, N, b, 0, M, &data[N+M], &data[max + N+M], eq, diffs);

    return diffs;
}

}

#endif // diff_hh_INCLUDED
<|endoftext|>


<commit_before>/*
 * Copyright 2010,
 * François Bleibel,
 * Olivier Stasse,
 *
 * CNRS/AIST
 *
 * This file is part of sot-core.
 * sot-core is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * sot-core is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.  You should
 * have received a copy of the GNU Lesser General Public License along
 * with sot-core.  If not, see <http://www.gnu.org/licenses/>.
 */

/* --------------------------------------------------------------------- */
/* --- INCLUDE --------------------------------------------------------- */
/* --------------------------------------------------------------------- */

/* --- SOT --- */
#include <sot/core/periodic-call.hh>
#include <dynamic-graph/pool.h>
#include <sot/core/debug.hh>
#include <sot/core/exception-tools.hh>
#include <algorithm>
#include <dynamic-graph/python/interpreter.hh>
#include <dynamic-graph/all-commands.h>
#include <dynamic-graph/exception-factory.h>

using namespace std;
using namespace dynamicgraph::sot;

/* --------------------------------------------------------------------- */
/* --- CLASS ----------------------------------------------------------- */
/* --------------------------------------------------------------------- */

PeriodicCall::
PeriodicCall( void )
  : signalMap()
    ,cmdList()
    ,innerTime( 0 )
  ,py_sh( NULL )
{

}

void PeriodicCall::
setPyInterpreter( dynamicgraph::python::Interpreter* ptr )
{ py_sh = ptr; }

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void PeriodicCall::
addSignal( const std::string &name, SignalBase<int>& sig )
{
  signalMap[ name ] = &sig;
  return ;
}

void PeriodicCall::
addSignal( const std::string& sigpath )
{
  istringstream sigISS( sigpath );
  SignalBase<int>& signal = PoolStorage::getInstance()->getSignal( sigISS );
  addSignal( sigpath,signal );
  return ;
}

void PeriodicCall::
rmSignal( const std::string &name )
{
  signalMap.erase( name );
  return ;
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void PeriodicCall::
addCmd( const std::string& cmdLine )
{
  cmdList.push_back( cmdLine );
  return ;
}

void PeriodicCall::
rmCmd( const std::string& args )
{
  CmdListType::iterator iter = std::find( cmdList.begin(),cmdList.end(),args);
  if( cmdList.end()!=iter ) { cmdList.erase( iter ); }
  return ;
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void PeriodicCall::
runSignals( const int& t )
{
  for( SignalMapType::iterator iter = signalMap.begin();
       signalMap.end()!=iter; ++iter )
    {
      (*iter).second ->recompute( t );
    }
  return ;
}

void PeriodicCall::
runCmds( void )
{
  if( NULL==py_sh )
    {
      ExceptionTools( ExceptionTools::PY_SHELL_PTR,"Python interpreter not set." );
    }

  for( CmdListType::const_iterator iter = cmdList.begin();
       cmdList.end()!=iter; ++iter )
    {
      py_sh->python( *iter );
    }
  return ;
}

void PeriodicCall::
run( const int & t )
{
  runSignals( t ); runCmds();
  return ;
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

void PeriodicCall::
display( std::ostream& os ) const
{
  os <<"  (t=" << innerTime << ")" <<endl;

  os<<" -> SIGNALS:"<<endl;
  for( SignalMapType::const_iterator iter = signalMap.begin();
       signalMap.end()!=iter; ++iter )
    {
      os << " - " << (*iter).first << endl;
    }

  os<<" -> CMDS:"<<endl;
  for( CmdListType::const_iterator iter = cmdList.begin();
       cmdList.end()!=iter; ++iter )
    {
      os << " - " <<  (*iter) << endl;
    }

}

static std::string readLineStr( istringstream& args )
{
  stringbuf* pbuf=args.rdbuf();
  const unsigned int size = pbuf->in_avail();
  char * buffer = new char[ size+1 ];
  pbuf->sgetn( buffer,size );

  buffer[size]='\0';
  std::string res( buffer );
  delete [] buffer;
  return res;
}

bool PeriodicCall::
commandLine( const std::string& cmdLine,
	     std::istringstream& cmdArgs,
	     std::ostream& os )
{
  if( cmdLine == "help" )
    {
      os << "PeriodicCall:"<<endl
	 <<"  - addSignal/rmSignal  <int> " <<endl
	 <<"  - addCmd/rmCmd  " <<endl
	 <<"  - runSignal/runCmd " <<endl
	 <<"  - run" <<endl;
    }
  else if( cmdLine == "addSignal" )
    {
      std::string sigpath; cmdArgs >> std::skipws >> sigpath;
      addSignal( sigpath );
    }
  else if( cmdLine == "rmSignal" )
    {
      std::string sigpath; cmdArgs >> std::skipws >> sigpath;
      rmSignal( sigpath );
    }
  else if( cmdLine == "runSignals" )
    {      runSignals( innerTime++ );    }

  else if( cmdLine == "addCmd" )
    {      addCmd( readLineStr(cmdArgs) );    }
  else if( cmdLine == "rmCmd" )
    {      rmCmd( readLineStr(cmdArgs) );    }
  else if( cmdLine == "runCmds" )
    {      runCmds();    }

  else if( cmdLine == "run" )
    {      run( innerTime++ );    }
  else if( cmdLine == "clear" )
    {     clear();    }
  else if( cmdLine == "print" )
    { display(os) ; }
  else { return false; }
  return true;
}

#define ADD_COMMAND( name,def )                                     \
if (commandMap.count(prefix+name) != 0) {                            \
  DG_THROW ExceptionFactory(ExceptionFactory::OBJECT_CONFLICT,        \
			    "Command " + prefix+name +	               \
			    " already registered in Entity.");          \
 }                                                                       \
commandMap.insert( std::make_pair( prefix+name,def ) )

void PeriodicCall::addSpecificCommands(Entity& ent,
				       Entity::CommandMap_t& commandMap,
				       const std::string& prefix )
{
  using namespace dynamicgraph::command;

  /* Explicit typage to help the compiler. */
  boost::function< void( const std::string& ) >
    addSignal  = boost::bind( &PeriodicCall::addSignal, this,_1 ),
    rmSignal = boost::bind( &PeriodicCall::rmSignal, this,_1 );
  boost::function< void( void ) >
    clear  = boost::bind( &PeriodicCall::clear, this );
  boost::function< void( std::ostream& ) >
    disp  = boost::bind( &PeriodicCall::display, this,_1 );

   ADD_COMMAND("addSignal",
   	      makeCommandVoid1(ent,addSignal,
   			       docCommandVoid1("Add the signal to the refresh list",
   					       "string (sig name)")));
   ADD_COMMAND("rmSignal",
	       makeCommandVoid1(ent,rmSignal,
				docCommandVoid1("Remove the signal to the refresh list",
						"string (sig name)")));
   ADD_COMMAND("clear",
	       makeCommandVoid0(ent,clear,
				docCommandVoid0("Clear all signals and commands from the refresh list.")));

   ADD_COMMAND("disp",
	       makeCommandVerbose(ent,disp,
				  docCommandVerbose("Print the list of to-refresh signals and commands.")));

}

/*
 * Local variables:
 * c-basic-offset: 2
 * End:
 */

<commit_msg>Corrected the call to the former syntax of the pool.<commit_after>/*
 * Copyright 2010,
 * François Bleibel,
 * Olivier Stasse,
 *
 * CNRS/AIST
 *
 * This file is part of sot-core.
 * sot-core is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * sot-core is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.  You should
 * have received a copy of the GNU Lesser General Public License along
 * with sot-core.  If not, see <http://www.gnu.org/licenses/>.
 */

/* --------------------------------------------------------------------- */
/* --- INCLUDE --------------------------------------------------------- */
/* --------------------------------------------------------------------- */

/* --- SOT --- */
#include <sot/core/periodic-call.hh>
#include <dynamic-graph/pool.h>
#include <sot/core/debug.hh>
#include <sot/core/exception-tools.hh>
#include <algorithm>
#include <dynamic-graph/python/interpreter.hh>
#include <dynamic-graph/all-commands.h>
#include <dynamic-graph/exception-factory.h>

using namespace std;
using namespace dynamicgraph::sot;

/* --------------------------------------------------------------------- */
/* --- CLASS ----------------------------------------------------------- */
/* --------------------------------------------------------------------- */

PeriodicCall::
PeriodicCall( void )
  : signalMap()
    ,cmdList()
    ,innerTime( 0 )
  ,py_sh( NULL )
{

}

void PeriodicCall::
setPyInterpreter( dynamicgraph::python::Interpreter* ptr )
{ py_sh = ptr; }

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void PeriodicCall::
addSignal( const std::string &name, SignalBase<int>& sig )
{
  signalMap[ name ] = &sig;
  return ;
}

void PeriodicCall::
addSignal( const std::string& sigpath )
{
  istringstream sigISS( sigpath );
  SignalBase<int>& signal = ::dynamicgraph::PoolStorage::getInstance()->getSignal( sigISS );
  addSignal( sigpath,signal );
  return ;
}

void PeriodicCall::
rmSignal( const std::string &name )
{
  signalMap.erase( name );
  return ;
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void PeriodicCall::
addCmd( const std::string& cmdLine )
{
  cmdList.push_back( cmdLine );
  return ;
}

void PeriodicCall::
rmCmd( const std::string& args )
{
  CmdListType::iterator iter = std::find( cmdList.begin(),cmdList.end(),args);
  if( cmdList.end()!=iter ) { cmdList.erase( iter ); }
  return ;
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void PeriodicCall::
runSignals( const int& t )
{
  for( SignalMapType::iterator iter = signalMap.begin();
       signalMap.end()!=iter; ++iter )
    {
      (*iter).second ->recompute( t );
    }
  return ;
}

void PeriodicCall::
runCmds( void )
{
  if( NULL==py_sh )
    {
      ExceptionTools( ExceptionTools::PY_SHELL_PTR,"Python interpreter not set." );
    }

  for( CmdListType::const_iterator iter = cmdList.begin();
       cmdList.end()!=iter; ++iter )
    {
      py_sh->python( *iter );
    }
  return ;
}

void PeriodicCall::
run( const int & t )
{
  runSignals( t ); runCmds();
  return ;
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

void PeriodicCall::
display( std::ostream& os ) const
{
  os <<"  (t=" << innerTime << ")" <<endl;

  os<<" -> SIGNALS:"<<endl;
  for( SignalMapType::const_iterator iter = signalMap.begin();
       signalMap.end()!=iter; ++iter )
    {
      os << " - " << (*iter).first << endl;
    }

  os<<" -> CMDS:"<<endl;
  for( CmdListType::const_iterator iter = cmdList.begin();
       cmdList.end()!=iter; ++iter )
    {
      os << " - " <<  (*iter) << endl;
    }

}

static std::string readLineStr( istringstream& args )
{
  stringbuf* pbuf=args.rdbuf();
  const unsigned int size = pbuf->in_avail();
  char * buffer = new char[ size+1 ];
  pbuf->sgetn( buffer,size );

  buffer[size]='\0';
  std::string res( buffer );
  delete [] buffer;
  return res;
}

bool PeriodicCall::
commandLine( const std::string& cmdLine,
	     std::istringstream& cmdArgs,
	     std::ostream& os )
{
  if( cmdLine == "help" )
    {
      os << "PeriodicCall:"<<endl
	 <<"  - addSignal/rmSignal  <int> " <<endl
	 <<"  - addCmd/rmCmd  " <<endl
	 <<"  - runSignal/runCmd " <<endl
	 <<"  - run" <<endl;
    }
  else if( cmdLine == "addSignal" )
    {
      std::string sigpath; cmdArgs >> std::skipws >> sigpath;
      addSignal( sigpath );
    }
  else if( cmdLine == "rmSignal" )
    {
      std::string sigpath; cmdArgs >> std::skipws >> sigpath;
      rmSignal( sigpath );
    }
  else if( cmdLine == "runSignals" )
    {      runSignals( innerTime++ );    }

  else if( cmdLine == "addCmd" )
    {      addCmd( readLineStr(cmdArgs) );    }
  else if( cmdLine == "rmCmd" )
    {      rmCmd( readLineStr(cmdArgs) );    }
  else if( cmdLine == "runCmds" )
    {      runCmds();    }

  else if( cmdLine == "run" )
    {      run( innerTime++ );    }
  else if( cmdLine == "clear" )
    {     clear();    }
  else if( cmdLine == "print" )
    { display(os) ; }
  else { return false; }
  return true;
}

#define ADD_COMMAND( name,def )                                     \
if (commandMap.count(prefix+name) != 0) {                            \
  DG_THROW ExceptionFactory(ExceptionFactory::OBJECT_CONFLICT,        \
			    "Command " + prefix+name +	               \
			    " already registered in Entity.");          \
 }                                                                       \
commandMap.insert( std::make_pair( prefix+name,def ) )

void PeriodicCall::addSpecificCommands(Entity& ent,
				       Entity::CommandMap_t& commandMap,
				       const std::string& prefix )
{
  using namespace dynamicgraph::command;

  /* Explicit typage to help the compiler. */
  boost::function< void( const std::string& ) >
    addSignal  = boost::bind( &PeriodicCall::addSignal, this,_1 ),
    rmSignal = boost::bind( &PeriodicCall::rmSignal, this,_1 );
  boost::function< void( void ) >
    clear  = boost::bind( &PeriodicCall::clear, this );
  boost::function< void( std::ostream& ) >
    disp  = boost::bind( &PeriodicCall::display, this,_1 );

   ADD_COMMAND("addSignal",
   	      makeCommandVoid1(ent,addSignal,
   			       docCommandVoid1("Add the signal to the refresh list",
   					       "string (sig name)")));
   ADD_COMMAND("rmSignal",
	       makeCommandVoid1(ent,rmSignal,
				docCommandVoid1("Remove the signal to the refresh list",
						"string (sig name)")));
   ADD_COMMAND("clear",
	       makeCommandVoid0(ent,clear,
				docCommandVoid0("Clear all signals and commands from the refresh list.")));

   ADD_COMMAND("disp",
	       makeCommandVerbose(ent,disp,
				  docCommandVerbose("Print the list of to-refresh signals and commands.")));

}

/*
 * Local variables:
 * c-basic-offset: 2
 * End:
 */

<|endoftext|>


<commit_before>/*
  Adplug - Replayer for many OPL2/OPL3 audio file formats.
  Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  dtm.cpp - DTM loader by Riven the Mage <riven@ok.ru>
*/
/*
  NOTE: Panning (Ex) effect is ignored.
*/

#include <algorithm>
#include <cstring>
#include "dtm.h"

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

CPlayer *CdtmLoader::factory(Copl *newopl)
{
  return new CdtmLoader(newopl);
}

bool CdtmLoader::load(const std::string &filename, const CFileProvider &fp)
{
  static const unsigned char conv_inst[11] = {
    2, 1, 10, 9, 4, 3, 6, 5, 0, 8, 7
  };
  static const unsigned short conv_note[12] = {
    0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5,
    0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE
  };

  binistream *f = fp.open(filename);
  if (!f) return false;

  // read header
  f->readString(header.id, sizeof(header.id));
  header.version = f->readInt(1);
  f->readString(header.title, sizeof(header.title));
  f->readString(header.author, sizeof(header.author));
  // Ensure title and author are NUL terminated. We may overwrite the
  // last character because the arrays are too short.
  header.author[sizeof(header.author) - 1] =
    header.title[sizeof(header.title) - 1] = 0;
  header.numpat = f->readInt(1);
  header.numinst = f->readInt(1) + 1;

  // check header
  if (memcmp(header.id, "DeFy DTM ", 9) || // signature exists?
      header.version != 0x10 || // good version?
      header.numinst > MAX_INST ||
      header.numinst < N_CHAN || // need a default instrument for each channel
      f->error()) {
    fp.close (f);
    return false;
  }

  // load description
  memset(desc, 0, sizeof(desc));

  char *bufstr = desc;

  for (int i = 0; i < DESC_ROWS; i++) {
      // get line length
      unsigned char bufstr_length = f->readInt(1);

      if (bufstr_length > DESC_COLS) {
        // "desc" is too small to hold DESC_ROWS lines with DESC_COLS chars
        // each plus DESC_ROWS newlines and a NUL terminator. Accept a line
        // length of DESC_COLS anyway and truncate the last line if necessary.
        // Maybe we should grow desc or allocate it dynamically instead.
	fp.close(f);
	return false;
      }

      int max_length = desc + sizeof(desc) - 1 - bufstr;
      int discard = bufstr_length > max_length ? bufstr_length - max_length : 0;
      bufstr_length -= discard;

      // read line
      if (bufstr_length) {
	  f->readString(bufstr,bufstr_length);

	  for (int j = 0; j < bufstr_length; j++)
	    if (!bufstr[j])
	      bufstr[j] = 0x20;
          bufstr += bufstr_length;

	  if (discard)
            f->ignore(discard);
      }
      if (bufstr_length < max_length)
        *(bufstr++) = '\n';
  }
  *bufstr = 0;

  // init CmodPlayer
  realloc_instruments(header.numinst);
  realloc_order(N_ORD);
  realloc_patterns(header.numpat, N_ROW, N_CHAN);
  init_notetable(conv_note);
  init_trackord();

  // load instruments
  for (int i = 0; i < header.numinst; i++) {
      unsigned char name_length = f->readInt(1);

      if (name_length)
	f->readString(instruments[i].name, name_length);

      instruments[i].name[name_length] = 0;

      f->readString((char *)instruments[i].data, sizeof(instruments[i].data));

      for (int j = 0; j < sizeof(conv_inst); j++)
	inst[i].data[conv_inst[j]] = instruments[i].data[j];
  }

  // load order
  f->readString((char *)order, N_ORD);

  // load tracks
  dtm_event pattern[N_ROW][N_CHAN];
  nop = header.numpat;
  for (int t = 0, i = 0; i < nop; i++) {
      unsigned short packed_length = f->readInt(2);
      unsigned char *packed_pattern = new unsigned char [packed_length];

      f->readString((char *)packed_pattern, packed_length);

      long unpacked_length = unpack_pattern(packed_pattern, packed_length,
			            (unsigned char *)pattern, sizeof(pattern));
      delete [] packed_pattern;

      if (unpacked_length != sizeof(pattern)) {
	  fp.close(f);
	  return false;
      }

      // convert pattern
      for (int j = 0; j < N_CHAN; j++, t++) {
	  for (int k = 0; k < N_ROW; k++) {
	      dtm_event *event = &pattern[k][j];

	      // instrument
	      if (event->byte0 == 0x80) {
		  if (event->byte1 <= 0x80)
		    tracks[t][k].inst = event->byte1 + 1;
	      }

	      // note + effect
	      else {
		  tracks[t][k].note = event->byte0;

		  if ((event->byte0 != 0) && (event->byte0 != 127))
		    tracks[t][k].note++;

		  // convert effects
		  unsigned char ev_param = event->byte1 & 0x0F;
		  switch (event->byte1 >> 4) {
		    case 0x0: // pattern break
		      if (ev_param == 1)
			tracks[t][k].command = 13;
		      break;

		    case 0x1: // freq. slide up
		      tracks[t][k].command = 28;
		      tracks[t][k].param1 = ev_param;
		      break;

		    case 0x2: // freq. slide down
		      tracks[t][k].command = 28;
		      tracks[t][k].param2 = ev_param;
		      break;

		    case 0xA: // set carrier volume
		    case 0xC: // set instrument volume
		      tracks[t][k].command = 22;
		      tracks[t][k].param1 = (0x3F - ev_param) >> 4; // always 3
		      tracks[t][k].param2 = (0x3F - ev_param) & 0xF;
		      break;

		    case 0xB: // set modulator volume
		      tracks[t][k].command = 21;
		      tracks[t][k].param1 = (0x3F - ev_param) >> 4; // always 3
		      tracks[t][k].param2 = (0x3F - ev_param) & 0xF;
		      break;

		    case 0xE: // set panning
		      break;

		    case 0xF: // set speed
		      tracks[t][k].command = 13;
		      tracks[t][k].param2 = ev_param;
		      break;
		  }
	      }
	  }
      }
  }

  if (f->error()) {
      fp.close(f);
      return false;
  }
  fp.close(f);

  // order length
  for (int i = 0; i < N_ORD; i++) {
      if (order[i] & 0x80) {
	  length = i;

	  if (order[i] == 0xFF)
	    restartpos = 0;
	  else
	    restartpos = order[i] - 0x80;

	  break;
      }
  }

  // initial speed
  initspeed = 2;

  rewind(0);

  return true;
}

void CdtmLoader::rewind(int subsong)
{
  CmodPlayer::rewind(subsong);

  // default instruments
  for (int i = 0; i < N_CHAN; i++) {
      channel[i].inst = i;

      channel[i].vol1 = 63 - (inst[i].data[10] & 63);
      channel[i].vol2 = 63 - (inst[i].data[9] & 63);
  }
}

float CdtmLoader::getrefresh()
{
  return 18.2f;
}

std::string CdtmLoader::gettype()
{
  return std::string("DeFy Adlib Tracker");
}

std::string CdtmLoader::gettitle()
{
  return std::string(header.title);
}

std::string CdtmLoader::getauthor()
{
  return std::string(header.author);
}

std::string CdtmLoader::getdesc()
{
  return std::string(desc);
}

std::string CdtmLoader::getinstrument(unsigned int n)
{
  return n < header.numinst ? std::string(instruments[n].name) : std::string();
}

unsigned int CdtmLoader::getinstruments()
{
  return header.numinst;
}

/* -------- Private Methods ------------------------------- */

long CdtmLoader::unpack_pattern(unsigned char *ibuf, long ilen,
				unsigned char *obuf, long olen)
{
  long input_length = 0;
  long output_length = 0;

  // RLE
  while (input_length < ilen) {
    long repeat_counter = 1;
    unsigned char repeat_byte = ibuf[input_length++];

    if ((repeat_byte & 0xF0) == 0xD0) {
      if (input_length == ilen) break; // truncated input

      repeat_counter = repeat_byte & 15;
      repeat_byte = ibuf[input_length++];
    }

    repeat_counter = std::min(repeat_counter, olen - output_length);
    memset(obuf + output_length, repeat_byte, repeat_counter);
    output_length += repeat_counter;
  }

  return output_length;
}
<commit_msg>dtm.cpp: Add more checks during load()<commit_after>/*
  Adplug - Replayer for many OPL2/OPL3 audio file formats.
  Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  dtm.cpp - DTM loader by Riven the Mage <riven@ok.ru>
*/
/*
  NOTE: Panning (Ex) effect is ignored.
*/

#include <algorithm>
#include <cstring>
#include "dtm.h"

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

CPlayer *CdtmLoader::factory(Copl *newopl)
{
  return new CdtmLoader(newopl);
}

bool CdtmLoader::load(const std::string &filename, const CFileProvider &fp)
{
  static const unsigned char conv_inst[11] = {
    2, 1, 10, 9, 4, 3, 6, 5, 0, 8, 7
  };
  static const unsigned short conv_note[12] = {
    0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5,
    0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE
  };

  binistream *f = fp.open(filename);
  if (!f) return false;

  // read header
  f->readString(header.id, sizeof(header.id));
  header.version = f->readInt(1);
  f->readString(header.title, sizeof(header.title));
  f->readString(header.author, sizeof(header.author));
  // Ensure title and author are NUL terminated. We may overwrite the
  // last character because the arrays are too short.
  header.author[sizeof(header.author) - 1] =
    header.title[sizeof(header.title) - 1] = 0;
  header.numpat = f->readInt(1);
  header.numinst = f->readInt(1) + 1;

  // check header
  if (memcmp(header.id, "DeFy DTM ", 9) || // signature exists?
      header.version != 0x10 || // good version?
      header.numinst > MAX_INST ||
      header.numinst < N_CHAN || // need a default instrument for each channel
      header.numpat == 0 ||
      f->error()) {
    fp.close (f);
    return false;
  }

  // load description
  memset(desc, 0, sizeof(desc));

  char *bufstr = desc;

  for (int i = 0; i < DESC_ROWS; i++) {
      // get line length
      unsigned char bufstr_length = f->readInt(1);

      if (bufstr_length > DESC_COLS) {
        // "desc" is too small to hold DESC_ROWS lines with DESC_COLS chars
        // each plus DESC_ROWS newlines and a NUL terminator. Accept a line
        // length of DESC_COLS anyway and truncate the last line if necessary.
        // Maybe we should grow desc or allocate it dynamically instead.
	fp.close(f);
	return false;
      }

      int max_length = desc + sizeof(desc) - 1 - bufstr;
      int discard = bufstr_length > max_length ? bufstr_length - max_length : 0;
      bufstr_length -= discard;

      // read line
      if (bufstr_length) {
	  f->readString(bufstr,bufstr_length);

	  for (int j = 0; j < bufstr_length; j++)
	    if (!bufstr[j])
	      bufstr[j] = 0x20;
          bufstr += bufstr_length;

	  if (discard)
            f->ignore(discard);
      }
      if (bufstr_length < max_length)
        *(bufstr++) = '\n';
  }
  *bufstr = 0;

  // init CmodPlayer
  realloc_instruments(header.numinst);
  realloc_order(N_ORD);
  realloc_patterns(header.numpat, N_ROW, N_CHAN);
  init_notetable(conv_note);
  init_trackord();

  // load instruments
  for (int i = 0; i < header.numinst; i++) {
      unsigned char name_length = f->readInt(1);

      if (name_length >= sizeof(instruments[i].name)) {
	fp.close(f);
	return false; // or truncate the name instead?
      }

      if (name_length)
	f->readString(instruments[i].name, name_length);

      instruments[i].name[name_length] = 0;

      f->readString((char *)instruments[i].data, sizeof(instruments[i].data));

      for (int j = 0; j < sizeof(conv_inst); j++)
	inst[i].data[conv_inst[j]] = instruments[i].data[j];
  }

  // load order
  f->readString((char *)order, N_ORD);

  // load tracks
  dtm_event pattern[N_ROW][N_CHAN];
  nop = header.numpat;
  for (int t = 0, i = 0; i < nop; i++) {
      unsigned short packed_length = f->readInt(2);
      unsigned char *packed_pattern = new unsigned char [packed_length];

      f->readString((char *)packed_pattern, packed_length);

      long unpacked_length = unpack_pattern(packed_pattern, packed_length,
			            (unsigned char *)pattern, sizeof(pattern));
      delete [] packed_pattern;

      if (unpacked_length != sizeof(pattern)) {
	  fp.close(f);
	  return false;
      }

      // convert pattern
      for (int j = 0; j < N_CHAN; j++, t++) {
	  for (int k = 0; k < N_ROW; k++) {
	      dtm_event *event = &pattern[k][j];

	      // instrument
	      if (event->byte0 == 0x80) {
		if (event->byte1 < header.numinst) // not <= 0x80 !
		    tracks[t][k].inst = event->byte1 + 1;
	      }

	      // note + effect
	      else {
		  tracks[t][k].note = event->byte0;

		  if ((event->byte0 != 0) && (event->byte0 != 127))
		    tracks[t][k].note++;

		  // convert effects
		  unsigned char ev_param = event->byte1 & 0x0F;
		  switch (event->byte1 >> 4) {
		    case 0x0: // pattern break
		      if (ev_param == 1)
			tracks[t][k].command = 13;
		      break;

		    case 0x1: // freq. slide up
		      tracks[t][k].command = 28;
		      tracks[t][k].param1 = ev_param;
		      break;

		    case 0x2: // freq. slide down
		      tracks[t][k].command = 28;
		      tracks[t][k].param2 = ev_param;
		      break;

		    case 0xA: // set carrier volume
		    case 0xC: // set instrument volume
		      tracks[t][k].command = 22;
		      tracks[t][k].param1 = (0x3F - ev_param) >> 4; // always 3
		      tracks[t][k].param2 = (0x3F - ev_param) & 0xF;
		      break;

		    case 0xB: // set modulator volume
		      tracks[t][k].command = 21;
		      tracks[t][k].param1 = (0x3F - ev_param) >> 4; // always 3
		      tracks[t][k].param2 = (0x3F - ev_param) & 0xF;
		      break;

		    case 0xE: // set panning
		      break;

		    case 0xF: // set speed
		      tracks[t][k].command = 13;
		      tracks[t][k].param2 = ev_param;
		      break;
		  }
	      }
	  }
      }
  }

  if (f->error()) {
      fp.close(f);
      return false;
  }
  fp.close(f);

  // order length
  length = N_ORD;
  for (int i = 0; i < N_ORD; i++) {
      if (order[i] & 0x80) {
	  length = i;

	  if (order[i] == 0xFF)
	    restartpos = 0;
	  else
	    restartpos = order[i] - 0x80;

	  if (restartpos >= i) // bad restart position or empty order list
	    return false;

	  break;
      } else if (order[i] >= nop) {
	return false;
      }
  }

  // initial speed
  initspeed = 2;

  rewind(0);

  return true;
}

void CdtmLoader::rewind(int subsong)
{
  CmodPlayer::rewind(subsong);

  // default instruments
  for (int i = 0; i < N_CHAN; i++) {
      channel[i].inst = i;

      channel[i].vol1 = 63 - (inst[i].data[10] & 63);
      channel[i].vol2 = 63 - (inst[i].data[9] & 63);
  }
}

float CdtmLoader::getrefresh()
{
  return 18.2f;
}

std::string CdtmLoader::gettype()
{
  return std::string("DeFy Adlib Tracker");
}

std::string CdtmLoader::gettitle()
{
  return std::string(header.title);
}

std::string CdtmLoader::getauthor()
{
  return std::string(header.author);
}

std::string CdtmLoader::getdesc()
{
  return std::string(desc);
}

std::string CdtmLoader::getinstrument(unsigned int n)
{
  return n < header.numinst ? std::string(instruments[n].name) : std::string();
}

unsigned int CdtmLoader::getinstruments()
{
  return header.numinst;
}

/* -------- Private Methods ------------------------------- */

long CdtmLoader::unpack_pattern(unsigned char *ibuf, long ilen,
				unsigned char *obuf, long olen)
{
  long input_length = 0;
  long output_length = 0;

  // RLE
  while (input_length < ilen) {
    long repeat_counter = 1;
    unsigned char repeat_byte = ibuf[input_length++];

    if ((repeat_byte & 0xF0) == 0xD0) {
      if (input_length == ilen) break; // truncated input

      repeat_counter = repeat_byte & 15;
      repeat_byte = ibuf[input_length++];
    }

    repeat_counter = std::min(repeat_counter, olen - output_length);
    memset(obuf + output_length, repeat_byte, repeat_counter);
    output_length += repeat_counter;
  }

  return output_length;
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "TrackedBody.h"
#include "ApplyIMUToState.h"
#include "TrackedBodyIMU.h"
#include "TrackedBodyTarget.h"
#include "TrackingSystem.h"
#include "BodyTargetInterface.h"
#include "StateHistory.h"
#include "HistoryContainer.h"
#include "CannedIMUMeasurement.h"

// Library/third-party includes
#include <osvr/Kalman/FlexibleKalmanFilter.h>
#include <boost/optional.hpp>

#include <util/Stride.h>

// Standard includes
#include <iostream>

namespace osvr {
namespace vbtracker {
    using BodyStateHistoryEntry = StateHistoryEntry<BodyState>;

    struct TrackedBody::Impl {

        HistoryContainer<BodyStateHistoryEntry> stateHistory;
        HistoryContainer<CannedIMUMeasurement> imuMeasurements;
    };
    TrackedBody::TrackedBody(TrackingSystem &system, BodyId id)
        : m_system(system), m_id(id), m_impl(new Impl) {
        using StateVec = kalman::types::DimVector<BodyState>;
        /// Set error covariance matrix diagonal to large values for safety.
        m_state.setErrorCovariance(StateVec::Constant(10).asDiagonal());

        m_processModel.setDamping(getParams().linearVelocityDecayCoefficient,
                                  getParams().angularVelocityDecayCoefficient);
        m_processModel.setNoiseAutocorrelation(
            kalman::types::Vector<6>(getParams().processNoiseAutocorrelation));
    }

    TrackedBody::~TrackedBody() {}

    TrackedBodyIMU *
    TrackedBody::createIntegratedIMU(double orientationVariance,
                                     double angularVelocityVariance) {
        if (m_imu) {
            // already have an IMU!
            return nullptr;
        }
        m_imu.reset(new TrackedBodyIMU{*this, orientationVariance,
                                       angularVelocityVariance});
        return m_imu.get();
    }

    TrackedBodyTarget *
    TrackedBody::createTarget(Eigen::Vector3d const &targetToBody,
                              TargetSetupData const &setupData) {
        if (m_target) {
            // already have a target!
            /// @todo handle multiple targets!
            return nullptr;
        }
        /// The target will always be target 0...
        m_target.reset(
            new TrackedBodyTarget{*this, BodyTargetInterface{getState()},
                                  targetToBody, setupData, TargetId{0}});
        return m_target.get();
    }

    ConfigParams const &TrackedBody::getParams() const {
        return m_system.getParams();
    }

    BodyId TrackedBody::getId() const { return m_id; }
    osvr::util::time::TimeValue TrackedBody::getStateTime() const {
        return m_stateTime;
    }

    bool TrackedBody::getStateAtOrBefore(
        osvr::util::time::TimeValue const &desiredTime,
        osvr::util::time::TimeValue &outTime, BodyState &outState) {
        auto it = m_impl->stateHistory.closest_not_newer(desiredTime);
        if (m_impl->stateHistory.end() == it) {
            /// couldn't find such a state.
            return false;
        }
        outTime = it->first;
        it->second.restore(outState);
        return true;
    }

    inline boost::optional<osvr::util::time::TimeValue>
    getOldestPossibleMeasurementSource(TrackedBody const &body) {
        boost::optional<osvr::util::time::TimeValue> oldest;
        /// Little lambda to set `oldest` if we haven't recorded a timestamp or
        /// if the given timestamp is older.
        auto updateOldest = [&oldest](util::time::TimeValue const &timestamp) {
            if (!oldest || timestamp < *oldest) {
                oldest = timestamp;
            }
        };

        body.forEachTarget([&updateOldest](TrackedBodyTarget const &target) {
            /// If we haven't recorded a timestamp or the current target has
            /// an older timestamp
            updateOldest(target.getLastUpdate());
        });

        if (body.hasIMU()) {
            /// If we haven't recorded a timestamp or the IMU has an older
            /// timestamp
            updateOldest(body.getIMU().getLastUpdate());
        }
        return oldest;
    }

    void TrackedBody::pruneHistory() {
        if (m_impl->stateHistory.empty()) {
            // can't prune an empty structure
            return;
        }
        auto oldestOptional = getOldestPossibleMeasurementSource(*this);
        if (!oldestOptional) {
            // No timestamp yet - don't prune anything out yet.
            return;
        }
        auto oldest = *oldestOptional;
        if (m_impl->stateHistory.newest_timestamp() < oldest) {
            // It would be a strange set of circumstances to bring this about,
            // but we don't want to go from a non-empty history to an empty one.
            // So in this case, we want to make sure we have at least one entry
            // left over in the state history. Here's a quick way of doing that.
            oldest = m_impl->stateHistory.newest_timestamp();
        }

        m_impl->stateHistory.pop_before(oldest);

        m_impl->imuMeasurements.pop_before(oldest);
    }

    void TrackedBody::replaceStateSnapshot(
        osvr::util::time::TimeValue const &origTime,
        osvr::util::time::TimeValue const &newTime, BodyState const &newState) {
#if !(defined(OSVR_UVBI_ASSUME_SINGLE_CAMERA) &&                               \
      defined(OSVR_UVBI_ASSUME_CAMERA_ALWAYS_SLOWER))
#error "Current code assumes that all we have to replay is IMU measurements."
#endif // !(defined(OSVR_UVBI_ASSUME_SINGLE_CAMERA) &&
        // defined(OSVR_UVBI_ASSUME_CAMERA_ALWAYS_SLOWER))

        /// Clear off the state we're about to invalidate.
        auto numPopped = m_impl->stateHistory.pop_after(origTime);
        /// @todo number popped should be the same (or very nearly) as the
        /// number of IMU measurements we replay.

        /// Put on the new state estimate we just computed.
        m_state = newState;
        m_stateTime = newTime;
        if (m_impl->stateHistory.is_valid_to_push_newest(m_stateTime)) {
            pushState();
        }

        /// Replay the IMU measurements timestamped later than our estimate
        auto numReplayed = std::size_t{0};
        for (auto &imuHist :
             m_impl->imuMeasurements.get_range_newer_than(newTime)) {
            applyIMUMeasurement(imuHist.first, imuHist.second);
            ++numReplayed;
        }
#if 0
        static ::util::Stride s{43};
        if (++s) {
#endif
        if (numPopped != numReplayed) {
            std::cout << "Popped " << numPopped << ", replayed " << numReplayed
                      << "\n";
        }
    }

    void TrackedBody::pushState() {
        m_impl->stateHistory.push_newest(m_stateTime,
                                         BodyStateHistoryEntry{m_state});
    }

    void TrackedBody::incorporateNewMeasurementFromIMU(
        util::time::TimeValue const &tv, CannedIMUMeasurement const &meas) {
        if (!getSystem().isRoomCalibrationComplete()) {
            /// If room calibration is incomplete, don't handle this locally. If
            /// it's an orientation, hand it to the tracking system to hand off
            /// to the room calibrator.
            if (meas.orientationValid()) {
                Eigen::Quaterniond quat;
                meas.restoreQuat(quat);
                getSystem().calibrationHandleIMUData(getId(), tv, quat);
            }
            return;
        }

        if (!m_impl->imuMeasurements.is_valid_to_push_newest(tv)) {
            // This one is out of order from the IMU!
            /// @todo handle this better
            throw std::runtime_error("Got out of order timestamps from IMU!");
        }

        applyIMUMeasurement(tv, meas);

        m_impl->imuMeasurements.push_newest(tv, meas);
    }

    void TrackedBody::applyIMUMeasurement(util::time::TimeValue const &tv,
                                          CannedIMUMeasurement const &meas) {
        // Only apply and push new stuff
        if (m_impl->stateHistory.is_valid_to_push_newest(tv)) {
            applyIMUToState(getSystem(), m_stateTime, m_state, m_processModel,
                            tv, meas);
            m_stateTime = tv;
            pushState();
        }
    }

    bool TrackedBody::hasPoseEstimate() const {
        /// @todo handle IMU here.
        auto ret = false;
        forEachTarget([&ret](TrackedBodyTarget &target) {
            ret = ret || target.hasPoseEstimate();
        });
        return ret;
    }

} // namespace vbtracker
} // namespace osvr
<commit_msg>Adjust debugging message in tracked body<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "TrackedBody.h"
#include "ApplyIMUToState.h"
#include "TrackedBodyIMU.h"
#include "TrackedBodyTarget.h"
#include "TrackingSystem.h"
#include "BodyTargetInterface.h"
#include "StateHistory.h"
#include "HistoryContainer.h"
#include "CannedIMUMeasurement.h"

// Library/third-party includes
#include <osvr/Kalman/FlexibleKalmanFilter.h>
#include <boost/optional.hpp>

#include <util/Stride.h>

// Standard includes
#include <iostream>

namespace osvr {
namespace vbtracker {
    using BodyStateHistoryEntry = StateHistoryEntry<BodyState>;

    struct TrackedBody::Impl {

        HistoryContainer<BodyStateHistoryEntry> stateHistory;
        HistoryContainer<CannedIMUMeasurement> imuMeasurements;
    };
    TrackedBody::TrackedBody(TrackingSystem &system, BodyId id)
        : m_system(system), m_id(id), m_impl(new Impl) {
        using StateVec = kalman::types::DimVector<BodyState>;
        /// Set error covariance matrix diagonal to large values for safety.
        m_state.setErrorCovariance(StateVec::Constant(10).asDiagonal());

        m_processModel.setDamping(getParams().linearVelocityDecayCoefficient,
                                  getParams().angularVelocityDecayCoefficient);
        m_processModel.setNoiseAutocorrelation(
            kalman::types::Vector<6>(getParams().processNoiseAutocorrelation));
    }

    TrackedBody::~TrackedBody() {}

    TrackedBodyIMU *
    TrackedBody::createIntegratedIMU(double orientationVariance,
                                     double angularVelocityVariance) {
        if (m_imu) {
            // already have an IMU!
            return nullptr;
        }
        m_imu.reset(new TrackedBodyIMU{*this, orientationVariance,
                                       angularVelocityVariance});
        return m_imu.get();
    }

    TrackedBodyTarget *
    TrackedBody::createTarget(Eigen::Vector3d const &targetToBody,
                              TargetSetupData const &setupData) {
        if (m_target) {
            // already have a target!
            /// @todo handle multiple targets!
            return nullptr;
        }
        /// The target will always be target 0...
        m_target.reset(
            new TrackedBodyTarget{*this, BodyTargetInterface{getState()},
                                  targetToBody, setupData, TargetId{0}});
        return m_target.get();
    }

    ConfigParams const &TrackedBody::getParams() const {
        return m_system.getParams();
    }

    BodyId TrackedBody::getId() const { return m_id; }
    osvr::util::time::TimeValue TrackedBody::getStateTime() const {
        return m_stateTime;
    }

    bool TrackedBody::getStateAtOrBefore(
        osvr::util::time::TimeValue const &desiredTime,
        osvr::util::time::TimeValue &outTime, BodyState &outState) {
        auto it = m_impl->stateHistory.closest_not_newer(desiredTime);
        if (m_impl->stateHistory.end() == it) {
            /// couldn't find such a state.
            return false;
        }
        outTime = it->first;
        it->second.restore(outState);
        return true;
    }

    inline boost::optional<osvr::util::time::TimeValue>
    getOldestPossibleMeasurementSource(TrackedBody const &body) {
        boost::optional<osvr::util::time::TimeValue> oldest;
        /// Little lambda to set `oldest` if we haven't recorded a timestamp or
        /// if the given timestamp is older.
        auto updateOldest = [&oldest](util::time::TimeValue const &timestamp) {
            if (!oldest || timestamp < *oldest) {
                oldest = timestamp;
            }
        };

        body.forEachTarget([&updateOldest](TrackedBodyTarget const &target) {
            /// If we haven't recorded a timestamp or the current target has
            /// an older timestamp
            updateOldest(target.getLastUpdate());
        });

        if (body.hasIMU()) {
            /// If we haven't recorded a timestamp or the IMU has an older
            /// timestamp
            updateOldest(body.getIMU().getLastUpdate());
        }
        return oldest;
    }

    void TrackedBody::pruneHistory() {
        if (m_impl->stateHistory.empty()) {
            // can't prune an empty structure
            return;
        }
        auto oldestOptional = getOldestPossibleMeasurementSource(*this);
        if (!oldestOptional) {
            // No timestamp yet - don't prune anything out yet.
            return;
        }
        auto oldest = *oldestOptional;
        if (m_impl->stateHistory.newest_timestamp() < oldest) {
            // It would be a strange set of circumstances to bring this about,
            // but we don't want to go from a non-empty history to an empty one.
            // So in this case, we want to make sure we have at least one entry
            // left over in the state history. Here's a quick way of doing that.
            oldest = m_impl->stateHistory.newest_timestamp();
        }

        m_impl->stateHistory.pop_before(oldest);

        m_impl->imuMeasurements.pop_before(oldest);
    }

    void TrackedBody::replaceStateSnapshot(
        osvr::util::time::TimeValue const &origTime,
        osvr::util::time::TimeValue const &newTime, BodyState const &newState) {
#if !(defined(OSVR_UVBI_ASSUME_SINGLE_CAMERA) &&                               \
      defined(OSVR_UVBI_ASSUME_CAMERA_ALWAYS_SLOWER))
#error "Current code assumes that all we have to replay is IMU measurements."
#endif // !(defined(OSVR_UVBI_ASSUME_SINGLE_CAMERA) &&
        // defined(OSVR_UVBI_ASSUME_CAMERA_ALWAYS_SLOWER))

        /// Clear off the state we're about to invalidate.
        auto numPopped = m_impl->stateHistory.pop_after(origTime);
        /// @todo number popped should be the same (or very nearly) as the
        /// number of IMU measurements we replay.

        /// Put on the new state estimate we just computed.
        m_state = newState;
        m_stateTime = newTime;
        if (m_impl->stateHistory.is_valid_to_push_newest(m_stateTime)) {
            pushState();
        }

        /// Replay the IMU measurements timestamped later than our estimate
        auto numReplayed = std::size_t{0};
        for (auto &imuHist :
             m_impl->imuMeasurements.get_range_newer_than(newTime)) {
            applyIMUMeasurement(imuHist.first, imuHist.second);
            ++numReplayed;
        }
#if 0
        static ::util::Stride s{43};
        if (++s) {
#else
        if (numPopped != numReplayed) {
#endif
            std::cout << "Popped " << numPopped << ", replayed " << numReplayed
                      << "\n";
        }
    }

    void TrackedBody::pushState() {
        m_impl->stateHistory.push_newest(m_stateTime,
                                         BodyStateHistoryEntry{m_state});
    }

    void TrackedBody::incorporateNewMeasurementFromIMU(
        util::time::TimeValue const &tv, CannedIMUMeasurement const &meas) {
        if (!getSystem().isRoomCalibrationComplete()) {
            /// If room calibration is incomplete, don't handle this locally. If
            /// it's an orientation, hand it to the tracking system to hand off
            /// to the room calibrator.
            if (meas.orientationValid()) {
                Eigen::Quaterniond quat;
                meas.restoreQuat(quat);
                getSystem().calibrationHandleIMUData(getId(), tv, quat);
            }
            return;
        }

        if (!m_impl->imuMeasurements.is_valid_to_push_newest(tv)) {
            // This one is out of order from the IMU!
            /// @todo handle this better
            throw std::runtime_error("Got out of order timestamps from IMU!");
        }

        applyIMUMeasurement(tv, meas);

        m_impl->imuMeasurements.push_newest(tv, meas);
    }

    void TrackedBody::applyIMUMeasurement(util::time::TimeValue const &tv,
                                          CannedIMUMeasurement const &meas) {
        // Only apply and push new stuff
        if (m_impl->stateHistory.is_valid_to_push_newest(tv)) {
            applyIMUToState(getSystem(), m_stateTime, m_state, m_processModel,
                            tv, meas);
            m_stateTime = tv;
            pushState();
        }
    }

    bool TrackedBody::hasPoseEstimate() const {
        /// @todo handle IMU here.
        auto ret = false;
        forEachTarget([&ret](TrackedBodyTarget &target) {
            ret = ret || target.hasPoseEstimate();
        });
        return ret;
    }

} // namespace vbtracker
} // namespace osvr
<|endoftext|>


<commit_before>#include "LoginResponse.h"

<commit_msg>Add known data for LoginResponse PacketBuilder<commit_after>#include "LoginResponse.h"
#include "../../data/PSO2String.h"

LoginResponsePacket::LoginResponsePacket(std::u16string loginErr, std::u16string blockName) : loginErr(loginErr), blockName(blockName) {}

LoginResponsePacket::~LoginResponsePacket() {}

PacketData LoginResponsePacket::build() {
    Polaris::Data::PSO2String pso2LoginErr = Polaris::Data::CreatePSO2String(loginErr, 0xB6, 0x8BA4);
    PacketHeader header(sizeof(PacketHeader) + 4 + pso2LoginErr.dataLength + 0xC + 0x40 + 0xB0 + 0xC ,0x11, 0x1, 0x0, 0x0);
    PacketData packetData(header.length);
    packetData.appendData(&header, sizeof(PacketHeader));
    packetData.appendBytes(0, 4); // Unknown uint8 + uint8[3]
    packetData.appendData(&pso2LoginErr.magicValue, 4);
    packetData.appendData(pso2LoginErr.utf16string.data(), pso2LoginErr.dataLength);
    packetData.appendBytes(0, 0xC); // Unknown uint8[0xC]
    packetData.appendData(blockName.data(), blockName.size() * 2);
    if (blockName.size() * 2 < 0x40) { //TODO Verify block name isn't too big
        packetData.appendBytes(0, 0x40 - (blockName.size() * 2)); // Because fixed length
    }
    packetData.appendBytes(0, 0xB0); // Unknown float32[0x2C] ... Likely important!
    packetData.appendBytes(0, 0xC); // Unknown uint8[0xC]

    return packetData;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
#include <cstdio>
using namespace std;

void rotation(int x, int y, int a, int b)
{
	int x1 = -y + a + b;
	int y1 = x - a + b;
	cout << x1 << " " << y1 << endl;

	int x2 = -y1 + a + b;
	int y2 = x1 - a + b;
	cout << x2 << " " << y2 << endl;

	int x3 = -y2 + a + b;
	int y3 = x2 - a + b;
	cout << x3 << " " << y3 << endl;

	int x4 = -y3 + a + b;
	int y4 = x3 - a + b;
	cout << x4 << " " << y4 << endl;
	return;
}

bool FormSquare(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
{
	vector<int> dist;
	int d;
	d = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
	dist.push_back(d);

	d = (x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3);
	dist.push_back(d);

	d = (x1 - x4) * (x1 - x4) + (y1 - y4) * (y1 - y4);
	dist.push_back(d);

	d = (x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3);
	dist.push_back(d);

	d = (x2 - x4) * (x2 - x4) + (y2 - y4) * (y2 - y4);
	dist.push_back(d);

	d = (x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4);
	dist.push_back(d);

	sort(dist.begin(), dist.end());

	if (dist[0] == dist[1] && dist[1] == dist[2] && dist[2] == dist[3] &&
			dist[4] == dist[5] && dist[0] < dist[4])
		return true;
	else
		return false;
}

int main()
{
	//rotation(-1, 1, 0, 0);
	//freopen("input.txt", "r", stdin);
	int n;
	cin >> n;
	for (int k = 0; k < n; ++k)
	{
		//cout << "point " << k+1 << endl;
		vector<vector<pair<int, int> > > v(4);
		for (int i = 0; i < 4; ++i)
		{
			int x, y, a, b;
			cin >> x >> y >> a >> b;

			// no roration
			v[i].push_back(make_pair(x, y));

			// rotation once
			int x1 = -y + a + b;
			int y1 = x - a + b;
			v[i].push_back(make_pair(x1, y1));

			// rotation twice
			int x2 = -y1 + a + b;
			int y2 = x1 - a + b;
			v[i].push_back(make_pair(x2, y2));

			// rotation three times
			int x3 = -y2 + a + b;
			int y3 = x2 - a + b;
			v[i].push_back(make_pair(x3, y3));
		}

		bool flag = false;
		int ans = 300000;
		for (int j1 = 0; j1 < 4; ++j1)
		{
			int x1 = v[0][j1].first;
			int y1 = v[0][j1].second;

			for (int j2 = 0; j2 < 4; ++j2)
			{
				int x2 = v[1][j2].first;
				int y2 = v[1][j2].second;
				for (int j3 = 0; j3 < 4; ++j3)
				{
					int x3 = v[2][j3].first;
					int y3 = v[2][j3].second;
					for (int j4 = 0; j4 < 4; ++j4)
					{
						int x4 = v[3][j4].first;
						int y4 = v[3][j4].second;
						/*
							if (j1 + j2 + j3 + j4 == 3)
							{
								cout << j1 << " " << j2 << " " << j3 << " " << j4 << endl;
								cout << x1 << " " << y1 << endl;
								cout << x2 << " " << y2 << endl;
								cout << x3 << " " << y3 << endl;
								cout << x4 << " " << y4 << endl;
							}
							*/
						if (FormSquare(x1,y1,x2,y2,x3,y3,x4,y4))
						{
							flag = true;
							ans = min(j1+j2+j3+j4, ans);
						}
					}
				}
			}
		}
		if (flag) cout << ans << endl;
		else cout << -1 << endl;
	}

	return 0;
}
<commit_msg>int overflow, shold use longlong to avoid the square computation overflow, what a shame, shame !<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
#include <cstdio>
using namespace std;

void rotation(int x, int y, int a, int b)
{
	int x1 = -y + a + b;
	int y1 = x - a + b;
	cout << x1 << " " << y1 << endl;

	int x2 = -y1 + a + b;
	int y2 = x1 - a + b;
	cout << x2 << " " << y2 << endl;

	int x3 = -y2 + a + b;
	int y3 = x2 - a + b;
	cout << x3 << " " << y3 << endl;

	int x4 = -y3 + a + b;
	int y4 = x3 - a + b;
	cout << x4 << " " << y4 << endl;
	return;
}

bool FormSquare(long long x1, long long y1, long long x2, long long y2, long long x3, long long y3, long long x4, long long y4)
{
	vector<long long> dist;
	long long d;
	d = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
	dist.push_back(d);

	d = (x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3);
	dist.push_back(d);

	d = (x1 - x4) * (x1 - x4) + (y1 - y4) * (y1 - y4);
	dist.push_back(d);

	d = (x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3);
	dist.push_back(d);

	d = (x2 - x4) * (x2 - x4) + (y2 - y4) * (y2 - y4);
	dist.push_back(d);

	d = (x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4);
	dist.push_back(d);

	sort(dist.begin(), dist.end());

	if (dist[0] == dist[1] && dist[1] == dist[2] && dist[2] == dist[3] &&
			dist[4] == dist[5] && dist[0] < dist[4])
		return true;
	else
		return false;
}

int main()
{
	//rotation(-1, 1, 0, 0);
	//freopen("input.in", "r", stdin);
	int n;
	cin >> n;
	for (int k = 0; k < n; ++k)
	{
		//cout << "point " << k+1 << endl;
		vector<vector<pair<int, int> > > v(4);
		for (int i = 0; i < 4; ++i)
		{
			int x, y, a, b;
			cin >> x >> y >> a >> b;

			// no roration
			v[i].push_back(make_pair(x, y));

			// rotation once
			int x1 = -y + a + b;
			int y1 = x - a + b;
			v[i].push_back(make_pair(x1, y1));

			// rotation twice
			int x2 = -y1 + a + b;
			int y2 = x1 - a + b;
			v[i].push_back(make_pair(x2, y2));

			// rotation three times
			int x3 = -y2 + a + b;
			int y3 = x2 - a + b;
			v[i].push_back(make_pair(x3, y3));
		}

		bool flag = false;
		int ans = 300000;
		for (int j1 = 0; j1 < 4; ++j1)
		{
			int x1 = v[0][j1].first;
			int y1 = v[0][j1].second;

			for (int j2 = 0; j2 < 4; ++j2)
			{
				int x2 = v[1][j2].first;
				int y2 = v[1][j2].second;
				for (int j3 = 0; j3 < 4; ++j3)
				{
					int x3 = v[2][j3].first;
					int y3 = v[2][j3].second;
					for (int j4 = 0; j4 < 4; ++j4)
					{
						int x4 = v[3][j4].first;
						int y4 = v[3][j4].second;
						/*
							if (j1 + j2 + j3 + j4 == 8)
							{
								cout << "The rotations times---" << endl;
								cout << j1 << " " << j2 << " " << j3 << " " << j4 << endl;
								cout << "The four points:---" << endl;
								cout << x1 << " " << y1 << endl;
								cout << x2 << " " << y2 << endl;
								cout << x3 << " " << y3 << endl;
								cout << x4 << " " << y4 << endl;
							}
							*/
						if (FormSquare(x1,y1,x2,y2,x3,y3,x4,y4))
						{
							flag = true;
							ans = min(j1+j2+j3+j4, ans);
						}
					}
				}
			}
		}
		if (flag) cout << ans << endl;
		else cout << -1 << endl;
	}

	return 0;
}
<|endoftext|>


<commit_before>/*
* posixtools.node: A node.JS addon to add useful tools for creating *nix servers
* dervied from daemon.node, unicorn
*
* Copyright 2011 (c) <todd>
*
* Under MIT License. See LICENSE file.
*
*/

#include <v8.h>
#include <node.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>

#define PID_MAXLEN 10

using namespace v8;
using namespace node;

//
// Add fork method to allow forking node.js process
//
static Handle<Value> Fork(const Arguments& args) {
  HandleScope scope;
  pid_t sid, pid;
  int i, new_fd;

  pid = fork();
  // http://www.unixguide.net/unix/programming/1.1.2.shtml
  // vfork really isn't necessary... use fork

  if (pid < 0)      exit(1);

  if (pid == 0) {
    // Child process: We need to tell libev that we are forking because
    // kqueue can't deal with this gracefully.
    //
    // See: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_fork_code_the_audacity_to_re
    //printf("eio req: %d, threads: %d, pending: %d, ready: %d\n", eio_nreqs(), eio_nthreads(), eio_npending(), eio_nready());
    ev_default_fork();
#if HAVE_SRANDDEV == 1
    sranddev();
#else
    srand(time(NULL));
#endif

    return scope.Close(Number::New(pid));

  }

  return scope.Close(Number::New(pid));
}
static Handle<Value> SetSocketOpts(const Arguments& args) {
  HandleScope scope;
  int flags = 1;
  int r;
  int fd = args[0]->ToInteger()->Value();

  if ((r=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags))) < 0) {
    fprintf(stderr, "setsockopt(error): %d, %d:%s\n", r, errno, strerror(errno));
  }

  return scope.Close(Number::New(r));
}
static Handle<Value> Dup2(const Arguments& args) {
  HandleScope scope;
  int flags = 1;
  int r;
  int fd1 = args[0]->ToInteger()->Value();
  int fd2 = args[1]->ToInteger()->Value();

  if ((r=dup2(fd1, fd2)) < 0) {
    fprintf(stderr, "dup2(error): %d, %d:%s\n", r, errno, strerror(errno));
    return ThrowException(Exception::Error(String::New("dup2 error")));
  }

  return scope.Close(Number::New(r));
}
//
//  execve(const char *path, char *const argv[], char *const envp[]);
//
// see: man 2 execve
//
// some of this implementation is borrowed by reference to node_child_process.cc
static Handle<Value> Execve(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 3 ||
      !args[0]->IsString() ||
      !args[1]->IsArray() ||
      !args[2]->IsArray()) {
    fprintf(stderr, "args.Length: %d, %d, %d, %d\n", args.Length(), args[0]->IsString(), args[1]->IsArray(), args[2]->IsArray());
    return ThrowException(Exception::Error(String::New("Bad Arguments, expected: path, argv[], envp[]")));
  }

  int i;
  String::Utf8Value file(args[0]->ToString());
  // Copy arguments args[1] and args[2] into a c-string array called argv.
  // The array must be null terminated, and the first element must be
  // the name of the executable -- hence the complication.
  Local<Array> argv_handle = Local<Array>::Cast(args[1]);
  Local<Array> envp_handle = Local<Array>::Cast(args[2]);

  // setup argv
  int argc = argv_handle->Length();
  int argv_length = argc + 1 + 1;
  char **argv = new char*[argv_length]; // heap allocated to detect errors
  argv[0] = strdup(*file); // + 1 for file
  argv[argv_length-1] = NULL;  // + 1 for NULL;
  for (i = 0; i < argc; ++i) {
    String::Utf8Value arg(argv_handle->Get(Integer::New(i))->ToString());
    argv[i+1] = strdup(*arg);
  }

  // setup env
  int envc = envp_handle->Length();
  char **envp = new char*[envc+1];
  envp[envc] = NULL; // + 1 for NULL;
  for (i = 0; i < envc; ++i) {
    String::Utf8Value env(envp_handle->Get(Integer::New(i))->ToString());
    envp[i] = strdup(*env);
  }
  fprintf(stderr, "execute file: %s\n", *file);

  int r = execve(*file, argv, envp);

  // return's only on error
  return ThrowException(Exception::Error(String::New("Execve failed!")));
}

// set the fd to close on a call to exec
static Handle<Value> FdCloseOnExec(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsNumber()) {
    return ThrowException(Exception::Error(String::New("When setting a umask it must be an integer")));
  }
  int fd = args[0]->ToInteger()->Value();
  int flags = fcntl(fd, F_GETFD, 0);

  return scope.Close(Number::New(fcntl(fd, F_SETFD, flags | FD_CLOEXEC)));
}
// set the fd to stay open after an exec call
static Handle<Value> FdOpenOnExec(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsNumber()) {
    return ThrowException(Exception::Error(String::New("When setting a umask it must be an integer")));
  }
  int fd = args[0]->ToInteger()->Value();
  int flags = fcntl(fd, F_GETFD, 0);

  return scope.Close(Number::New(fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC)));
}

//
// Add getpid at least until process.pid returns the actual pid via getpid call this is necessary work around
//
static Handle<Value> GetPid(const Arguments& args) {
  HandleScope scope;
  return scope.Close(Number::New(getpid()));
}

//
// Add getppid get our parent process id
//
static Handle<Value> GetPPid(const Arguments& args) {
  HandleScope scope;
  return scope.Close(Number::New(getppid()));
}

static Handle<Value> SetSid(const Arguments& args) {
  HandleScope scope;
  return scope.Close(Number::New(setsid()));
}

static Handle<Value> Umask(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsNumber()) {
    return ThrowException(Exception::Error(String::New("When setting a umask it must be an integer")));
  }
  int mask = args[0]->ToInteger()->Value();
  return scope.Close(Number::New(umask(mask)));
}

static Handle<Value> IsAlive(const Arguments& args) {
  HandleScope scope;
  int status;
  int pid = args[0]->ToInteger()->Value();
  int r = waitpid(pid, &status, WNOHANG | WUNTRACED);
//  fprintf(stderr, "%d, %d:%s\n", r, errno, strerror(errno));
//  fflush(stderr);
  if (r == -1) { return scope.Close(Boolean::New(false)); }
  return scope.Close(Boolean::New(true));
}

//
// reopen stdout, stdin, stderr
// stdout and stderr may be reopened to a path or /dev/null
// stdin is always reopened to /dev/null
//
//   fork.reopen_stdio("/path/to/stdout", "/path/to/stderr");
//
static Handle<Value> ReOpenStdIO(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsString() || !args[1]->IsString()) {
    return ThrowException(Exception::Error(String::New("Must provide a path to reopen STDOUT and STDERR")));
  }
  String::Utf8Value stdout_path(args[0]->ToString());
  String::Utf8Value stderr_path(args[1]->ToString());

  stdin  = freopen("/dev/null", "r", stdin);
  stdout = freopen(*stdout_path, "a", stdout);
  stderr = freopen(*stderr_path, "a", stderr);

  if (stdout && stderr) {
    return scope.Close(Number::New(1));
  }
  else {
    return ThrowException(Exception::Error(String::New("Error unable to reopen stdout and stderr")));
  }
}

//
// Initialize this add-on
//
extern "C" void init(Handle<Object> target) {
  HandleScope scope;

  NODE_SET_METHOD(target, "fork", Fork);
  NODE_SET_METHOD(target, "getpid", GetPid);
  NODE_SET_METHOD(target, "setsid", SetSid);
  NODE_SET_METHOD(target, "reopen_stdio", ReOpenStdIO);
  NODE_SET_METHOD(target, "umask", Umask);
  NODE_SET_METHOD(target, "isalive", IsAlive);
  NODE_SET_METHOD(target, "getppid", GetPPid);
  NODE_SET_METHOD(target, "fd_close_on_exec", FdCloseOnExec);
  NODE_SET_METHOD(target, "fd_open_on_exec", FdOpenOnExec);
  NODE_SET_METHOD(target, "execve", Execve);
  NODE_SET_METHOD(target, "set_socket_opts", SetSocketOpts);
  NODE_SET_METHOD(target, "dup2", Dup2);
}
<commit_msg>a reference<commit_after>/*
* posixtools.node: A node.JS addon to add useful tools for creating *nix servers
* dervied from daemon.node, unicorn
*
* Copyright 2011 (c) <todd>
*
* Under MIT License. See LICENSE file.
*
*/

#include <v8.h>
#include <node.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>

#define PID_MAXLEN 10

using namespace v8;
using namespace node;

//
// Add fork method to allow forking node.js process
//
static Handle<Value> Fork(const Arguments& args) {
  HandleScope scope;
  pid_t sid, pid;
  int i, new_fd;

  pid = fork();
  // http://www.unixguide.net/unix/programming/1.1.2.shtml
  // vfork really isn't necessary... use fork

  if (pid < 0)      exit(1);

  if (pid == 0) {
    // Child process: We need to tell libev that we are forking because
    // kqueue can't deal with this gracefully.
    //
    // See: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_fork_code_the_audacity_to_re
    //printf("eio req: %d, threads: %d, pending: %d, ready: %d\n", eio_nreqs(), eio_nthreads(), eio_npending(), eio_nready());
    ev_default_fork();
#if HAVE_SRANDDEV == 1
    sranddev();
#else
    srand(time(NULL));
#endif

    return scope.Close(Number::New(pid));

  }

  return scope.Close(Number::New(pid));
}
static Handle<Value> SetSocketOpts(const Arguments& args) {
  HandleScope scope;
  int flags = 1;
  int r;
  int fd = args[0]->ToInteger()->Value();

  if ((r=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags))) < 0) {
    fprintf(stderr, "setsockopt(error): %d, %d:%s\n", r, errno, strerror(errno));
  }

  return scope.Close(Number::New(r));
}
static Handle<Value> Dup2(const Arguments& args) {
  HandleScope scope;
  int flags = 1;
  int r;
  int fd1 = args[0]->ToInteger()->Value();
  int fd2 = args[1]->ToInteger()->Value();

  if ((r=dup2(fd1, fd2)) < 0) {
    fprintf(stderr, "dup2(error): %d, %d:%s\n", r, errno, strerror(errno));
    return ThrowException(Exception::Error(String::New("dup2 error")));
  }

  return scope.Close(Number::New(r));
}
//
//  execve(const char *path, char *const argv[], char *const envp[]);
//
// see: man 2 execve
//
// some of this implementation is borrowed by reference to node_child_process.cc
static Handle<Value> Execve(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 3 ||
      !args[0]->IsString() ||
      !args[1]->IsArray() ||
      !args[2]->IsArray()) {
    fprintf(stderr, "args.Length: %d, %d, %d, %d\n", args.Length(), args[0]->IsString(), args[1]->IsArray(), args[2]->IsArray());
    return ThrowException(Exception::Error(String::New("Bad Arguments, expected: path, argv[], envp[]")));
  }

  int i;
  String::Utf8Value file(args[0]->ToString());
  // Copy arguments args[1] and args[2] into a c-string array called argv.
  // The array must be null terminated, and the first element must be
  // the name of the executable -- hence the complication.
  Local<Array> argv_handle = Local<Array>::Cast(args[1]);
  Local<Array> envp_handle = Local<Array>::Cast(args[2]);

  // setup argv
  int argc = argv_handle->Length();
  int argv_length = argc + 1 + 1;
  char **argv = new char*[argv_length]; // heap allocated to detect errors
  argv[0] = strdup(*file); // + 1 for file
  argv[argv_length-1] = NULL;  // + 1 for NULL;
  for (i = 0; i < argc; ++i) {
    String::Utf8Value arg(argv_handle->Get(Integer::New(i))->ToString());
    argv[i+1] = strdup(*arg);
  }

  // setup env
  int envc = envp_handle->Length();
  char **envp = new char*[envc+1];
  envp[envc] = NULL; // + 1 for NULL;
  for (i = 0; i < envc; ++i) {
    String::Utf8Value env(envp_handle->Get(Integer::New(i))->ToString());
    envp[i] = strdup(*env);
  }
  fprintf(stderr, "execute file: %s\n", *file);

  int r = execve(*file, argv, envp);

  // return's only on error
  return ThrowException(Exception::Error(String::New("Execve failed!")));
}

// set the fd to close on a call to exec
static Handle<Value> FdCloseOnExec(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsNumber()) {
    return ThrowException(Exception::Error(String::New("When setting a umask it must be an integer")));
  }
  int fd = args[0]->ToInteger()->Value();
  int flags = fcntl(fd, F_GETFD, 0);

  return scope.Close(Number::New(fcntl(fd, F_SETFD, flags | FD_CLOEXEC)));
}

// set the fd to stay open after an exec call
// see: http://www.gnu.org/s/hello/manual/libc/Descriptor-Flags.html
static Handle<Value> FdOpenOnExec(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsNumber()) {
    return ThrowException(Exception::Error(String::New("When setting a umask it must be an integer")));
  }
  int fd = args[0]->ToInteger()->Value();
  int flags = fcntl(fd, F_GETFD, 0);

  return scope.Close(Number::New(fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC)));
}

//
// Add getpid at least until process.pid returns the actual pid via getpid call this is necessary work around
//
static Handle<Value> GetPid(const Arguments& args) {
  HandleScope scope;
  return scope.Close(Number::New(getpid()));
}

//
// Add getppid get our parent process id
//
static Handle<Value> GetPPid(const Arguments& args) {
  HandleScope scope;
  return scope.Close(Number::New(getppid()));
}

static Handle<Value> SetSid(const Arguments& args) {
  HandleScope scope;
  return scope.Close(Number::New(setsid()));
}

static Handle<Value> Umask(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsNumber()) {
    return ThrowException(Exception::Error(String::New("When setting a umask it must be an integer")));
  }
  int mask = args[0]->ToInteger()->Value();
  return scope.Close(Number::New(umask(mask)));
}

static Handle<Value> IsAlive(const Arguments& args) {
  HandleScope scope;
  int status;
  int pid = args[0]->ToInteger()->Value();
  int r = waitpid(pid, &status, WNOHANG | WUNTRACED);
//  fprintf(stderr, "%d, %d:%s\n", r, errno, strerror(errno));
//  fflush(stderr);
  if (r == -1) { return scope.Close(Boolean::New(false)); }
  return scope.Close(Boolean::New(true));
}

//
// reopen stdout, stdin, stderr
// stdout and stderr may be reopened to a path or /dev/null
// stdin is always reopened to /dev/null
//
//   fork.reopen_stdio("/path/to/stdout", "/path/to/stderr");
//
static Handle<Value> ReOpenStdIO(const Arguments& args) {
  HandleScope scope;
  if (!args[0]->IsString() || !args[1]->IsString()) {
    return ThrowException(Exception::Error(String::New("Must provide a path to reopen STDOUT and STDERR")));
  }
  String::Utf8Value stdout_path(args[0]->ToString());
  String::Utf8Value stderr_path(args[1]->ToString());

  stdin  = freopen("/dev/null", "r", stdin);
  stdout = freopen(*stdout_path, "a", stdout);
  stderr = freopen(*stderr_path, "a", stderr);

  if (stdout && stderr) {
    return scope.Close(Number::New(1));
  }
  else {
    return ThrowException(Exception::Error(String::New("Error unable to reopen stdout and stderr")));
  }
}

//
// Initialize this add-on
//
extern "C" void init(Handle<Object> target) {
  HandleScope scope;

  NODE_SET_METHOD(target, "fork", Fork);
  NODE_SET_METHOD(target, "getpid", GetPid);
  NODE_SET_METHOD(target, "setsid", SetSid);
  NODE_SET_METHOD(target, "reopen_stdio", ReOpenStdIO);
  NODE_SET_METHOD(target, "umask", Umask);
  NODE_SET_METHOD(target, "isalive", IsAlive);
  NODE_SET_METHOD(target, "getppid", GetPPid);
  NODE_SET_METHOD(target, "fd_close_on_exec", FdCloseOnExec);
  NODE_SET_METHOD(target, "fd_open_on_exec", FdOpenOnExec);
  NODE_SET_METHOD(target, "execve", Execve);
  NODE_SET_METHOD(target, "set_socket_opts", SetSocketOpts);
  NODE_SET_METHOD(target, "dup2", Dup2);
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <vector>

#include <MultiRegions/ExpList.h>
#include <MultiRegions/ExpList1D.h>
#include <MultiRegions/ExpList2D.h>
#include <MultiRegions/ExpList2DHomogeneous1D.h>
#include <MultiRegions/ExpList3DHomogeneous1D.h>
#include <MultiRegions/ExpList3DHomogeneous2D.h>
using namespace Nektar;

int main(int argc, char *argv[])
{
    int i,j,k;

    if(argc != 6)
    {
        fprintf(stderr,
                "Usage: Fld2DTo2D5 2dmeshfile 2dfieldfile 3dmeshfile 3dfieldfile outfield\n");
        exit(1);
    }
    string datasave(argv[5]);

    string mesh2d(argv[1]);
    string mesh3d(argv[3]);

    // create 2d session
    LibUtilities::SessionReaderSharedPtr vSession2d
            = LibUtilities::SessionReader::CreateInstance(2, argv);
    std::vector<std::string> filenames;
    filenames.push_back(mesh3d);
    // create 3D session
    LibUtilities::SessionReaderSharedPtr vSession3d
            = LibUtilities::SessionReader::CreateInstance(2, argv, filenames, vSession2d->GetComm());

    SpatialDomains::MeshGraphSharedPtr graphShPt2d = SpatialDomains::MeshGraph::Read(vSession2d);
    SpatialDomains::MeshGraphSharedPtr graphShPt3d = SpatialDomains::MeshGraph::Read(vSession3d);
    // 2D
    string field2dfile(argv[2]);
    vector<LibUtilities::FieldDefinitionsSharedPtr> field2ddef;
    vector<vector<NekDouble> > field2ddata;
    LibUtilities::Import(field2dfile,field2ddef,field2ddata);
    // 3D
    string field3dfile(argv[4]);
    vector<LibUtilities::FieldDefinitionsSharedPtr> field3ddef;
    vector<vector<NekDouble> > field3ddata;
    LibUtilities::Import(field3dfile,field3ddef,field3ddata);
    vector<vector<NekDouble> > field3ddatanew(field3ddef.size());
    // Set up Expansion information
    vector< vector<LibUtilities::PointsType> > pointstype2d;
    vector< vector<LibUtilities::PointsType> > pointstype3d;
    for(i = 0; i < field2ddef.size(); ++i)
    {
        vector<LibUtilities::PointsType> ptype2d;
        for(j = 0; j < 2; ++j)
        {
            ptype2d.push_back(LibUtilities::ePolyEvenlySpaced);
        }
        pointstype2d.push_back(ptype2d);
    }
    graphShPt2d->SetExpansions(field2ddef,pointstype2d);
    for(i = 0; i < field3ddef.size(); ++i)
    {
        vector<LibUtilities::PointsType> ptype3d;
        for(j = 0; j < 2; ++j)
        {
            ptype3d.push_back(LibUtilities::ePolyEvenlySpaced);
        }
        pointstype3d.push_back(ptype3d);
    }
    graphShPt3d->SetExpansions(field3ddef,pointstype3d);
    bool useFFT = false;
    bool dealiasing = false;
    // Define Expansion
    int nfields2d = field2ddef[0]->m_fields.size();
    int nfields3d = field3ddef[0]->m_fields.size();
    // Gen 2d
    Array<OneD, MultiRegions::ExpListSharedPtr> Exp2d(nfields2d);
    MultiRegions::ExpList2DSharedPtr Exp2D;
    Exp2D = MemoryManager<MultiRegions::ExpList2D>::AllocateSharedPtr(vSession2d,graphShPt2d);
    Exp2d[0] =  Exp2D;
    for(i = 1; i < nfields2d; ++i)
    {
        Exp2d[i] = MemoryManager<MultiRegions::ExpList2D>::AllocateSharedPtr(*Exp2D);
    }
    // Gen 3d
    Array<OneD, MultiRegions::ExpListSharedPtr> Exp3d(nfields3d);
    MultiRegions::ExpList3DHomogeneous1DSharedPtr Exp3DH1;
    // Define Homogeneous expansion
    int nplanes;
    vSession3d->LoadParameter("HomModesZ",nplanes,field3ddef[0]->m_numModes[2]);
    // nplanes + 1 points
    const LibUtilities::PointsKey Pkey(nplanes,LibUtilities::ePolyEvenlySpaced);
    const LibUtilities::BasisKey  Bkey(field3ddef[0]->m_basis[2],nplanes,Pkey);
    NekDouble lz = field3ddef[0]->m_homogeneousLengths[0];
    Exp3DH1 = MemoryManager<MultiRegions::ExpList3DHomogeneous1D>::AllocateSharedPtr(vSession3d,Bkey,lz,useFFT,dealiasing,graphShPt3d);
    Exp3d[0] = Exp3DH1;
    for(j = 1; j < nfields3d; ++j)
    {
          Exp3d[j] = MemoryManager<MultiRegions::ExpList3DHomogeneous1D>::AllocateSharedPtr(*Exp3DH1);
    }

    k=0;
    for(j = 0; j < nfields2d-1; ++j)
    {
       	for(int i = 0; i < field2ddata.size(); ++i)
       	{
                   Exp2d[j]->ExtractDataToCoeffs(
                                        field2ddef[i],
		                                field2ddata[i],
		                                field2ddef[i]->m_fields[j],
		                                Exp3d[j]->GetPlane(k)->UpdateCoeffs());
        }
    }
    Array<OneD, Array<OneD, NekDouble> > fieldcoeffs(vSession3d->GetVariables().size());
    for(j = 0; j < fieldcoeffs.num_elements(); ++j)
    {
        fieldcoeffs[j] = Exp3d[j]->UpdateCoeffs();
        for(int i = 0; i < field3ddef.size(); ++i)
    	{
          Exp3d[0]->AppendFieldData(field3ddef[i], field3ddatanew[i],fieldcoeffs[j]);
    	}
    }
    LibUtilities::Write(datasave,field3ddef,field3ddatanew);
    return 0;
}
// Only for 2d to 2d5 Hui Xu 23 Aug 2013
<commit_msg>Added new pressure field<commit_after>#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <vector>

#include <MultiRegions/ExpList.h>
#include <MultiRegions/ExpList1D.h>
#include <MultiRegions/ExpList2D.h>
#include <MultiRegions/ExpList2DHomogeneous1D.h>
#include <MultiRegions/ExpList3DHomogeneous1D.h>
#include <MultiRegions/ExpList3DHomogeneous2D.h>
using namespace Nektar;

int main(int argc, char *argv[])
{
    int i,j,k;

    if(argc != 6)
    {
        fprintf(stderr,
                "Usage: Fld2DTo2D5 2dmeshfile 2dfieldfile 3dmeshfile 3dfieldfile outfield\n");
        exit(1);
    }
    string datasave(argv[5]);

    string mesh2d(argv[1]);
    string mesh3d(argv[3]);

    //create 2d session
    LibUtilities::SessionReaderSharedPtr vSession2d
            = LibUtilities::SessionReader::CreateInstance(2, argv);
    std::vector<std::string> filenames;
    filenames.push_back(mesh3d);
    //create 3D session
    LibUtilities::SessionReaderSharedPtr vSession3d
            = LibUtilities::SessionReader::CreateInstance(2, argv, filenames, vSession2d->GetComm());

    SpatialDomains::MeshGraphSharedPtr graphShPt2d = SpatialDomains::MeshGraph::Read(vSession2d);
    SpatialDomains::MeshGraphSharedPtr graphShPt3d = SpatialDomains::MeshGraph::Read(vSession3d);
    //2D
    string field2dfile(argv[2]);
    vector<LibUtilities::FieldDefinitionsSharedPtr> field2ddef;
    vector<vector<NekDouble> > field2ddata;
    LibUtilities::Import(field2dfile,field2ddef,field2ddata);
    //3D
    string field3dfile(argv[4]);
    vector<LibUtilities::FieldDefinitionsSharedPtr> field3ddef;
    vector<vector<NekDouble> > field3ddata;
    LibUtilities::Import(field3dfile,field3ddef,field3ddata);
    vector<vector<NekDouble> > field3ddatanew(field3ddef.size());
    // Set up Expansion information
    vector< vector<LibUtilities::PointsType> > pointstype2d;
    vector< vector<LibUtilities::PointsType> > pointstype3d;
    for(i = 0; i < field2ddef.size(); ++i)
    {
        vector<LibUtilities::PointsType> ptype2d;
        for(j = 0; j < 2; ++j)
        {
            ptype2d.push_back(LibUtilities::ePolyEvenlySpaced);
        }
        pointstype2d.push_back(ptype2d);
    }
    graphShPt2d->SetExpansions(field2ddef,pointstype2d);
    for(i = 0; i < field3ddef.size(); ++i)
    {
        vector<LibUtilities::PointsType> ptype3d;
        for(j = 0; j < 2; ++j)
        {
            ptype3d.push_back(LibUtilities::ePolyEvenlySpaced);
        }
        pointstype3d.push_back(ptype3d);
    }
    graphShPt3d->SetExpansions(field3ddef,pointstype3d);
    bool useFFT = false;
    bool dealiasing = false;
    // Define Expansion
    //int expdim2d  = graphShPt2d->GetMeshDimension();
    int nfields2d = field2ddef[0]->m_fields.size();
    //int expdim3d  = graphShPt3d->GetMeshDimension();
    int nfields3d = field3ddef[0]->m_fields.size();
    //Gen 2d
    Array<OneD, MultiRegions::ExpListSharedPtr> Exp2d(nfields2d);
    MultiRegions::ExpList2DSharedPtr Exp2D;
    Exp2D = MemoryManager<MultiRegions::ExpList2D>::AllocateSharedPtr(vSession2d,graphShPt2d);
    Exp2d[0] =  Exp2D;
    for(i = 1; i < nfields2d; ++i)
    {
        Exp2d[i] = MemoryManager<MultiRegions::ExpList2D>::AllocateSharedPtr(*Exp2D);
    }
    //Gen 3d
    Array<OneD, MultiRegions::ExpListSharedPtr> Exp3d(nfields3d);
    MultiRegions::ExpList3DHomogeneous1DSharedPtr Exp3DH1;
    // Define Homogeneous expansion
    int nplanes;
    //vSession3d->LoadParameter("HomModesZ",nplanes,field3ddef[0]->m_numModes[2]);
    nplanes = field3ddef[0]->m_numModes[2];
    cout<< nplanes << endl;
    // nplanes + 1 points
    const LibUtilities::PointsKey Pkey(nplanes,LibUtilities::ePolyEvenlySpaced);
    const LibUtilities::BasisKey  Bkey(field3ddef[0]->m_basis[2],nplanes,Pkey);
    NekDouble lz = field3ddef[0]->m_homogeneousLengths[0];
    Exp3DH1 = MemoryManager<MultiRegions::ExpList3DHomogeneous1D>::AllocateSharedPtr(vSession3d,Bkey,lz,useFFT,dealiasing,graphShPt3d);
    Exp3d[0] = Exp3DH1;
    for(j = 1; j < nfields3d; ++j)
    {
          Exp3d[j] = MemoryManager<MultiRegions::ExpList3DHomogeneous1D>::AllocateSharedPtr(*Exp3DH1);
    }

    k=0;
    for(j = 0; j < nfields2d; ++j)
    {
        if (j< nfields2d-1)
        {
       		for(int i = 0; i < field2ddata.size(); ++i)
       		{
                   Exp2d[j]->ExtractDataToCoeffs(
                                                field2ddef[i],
		                                field2ddata[i],
		                                field2ddef[i]->m_fields[j],
		                                Exp3d[j]->GetPlane(k)->UpdateCoeffs());
        	}
        }
        if (j==nfields2d-1)
        {
		for(int i = 0; i < field2ddata.size(); ++i)
                {
                   Exp2d[j]->ExtractDataToCoeffs(
                                                field2ddef[i],
                                                field2ddata[i],
                                                field2ddef[i]->m_fields[j],
                                                Exp3d[j+1]->GetPlane(k)->UpdateCoeffs());
                }
        }
    }
    Array<OneD, Array<OneD, NekDouble> > fieldcoeffs(vSession3d->GetVariables().size());
    for(j = 0; j < fieldcoeffs.num_elements(); ++j)
    {
        fieldcoeffs[j] = Exp3d[j]->UpdateCoeffs();
        for(int i = 0; i < field3ddef.size(); ++i)
    	{
          Exp3d[0]->AppendFieldData(field3ddef[i], field3ddatanew[i],fieldcoeffs[j]);
    	}
    }
    LibUtilities::Write(datasave,field3ddef,field3ddatanew);
    return 0;
}
// Only for 2d to 2d5 Hui Xu 23 Aug 2013
<|endoftext|>