<commit_before>//
// Created by necator on 8/4/17.
//

#include <iostream>
#include "chat_channel.h"

#include "easylogging++.h"

#include "chat_user.h"
#include "chat_server.h"

chat_channel::chat_channel(chat_server &server, chat_user_manager &manager, const std::string &name) :
        server_(server),
        manager_(manager),
        name_(name) {
    LOG(INFO) << "channel: " << name_ << " is created.";
}

void chat_channel::publish(const message &msg) {
    LOG(INFO) << "publish: " + msg.debug_string();

    for (auto u : users_)
        u->write(msg);
}

std::string chat_channel::name() const {
    return name_;
}

std::vector<std::string> chat_channel::user_names() const {
    std::vector<std::string> ret;

    std::transform(users_.begin(), users_.end(), std::back_inserter(ret), [](const chat_user_ptr u) {
        return u->name();
    });

    return ret;
}

void chat_channel::join(chat_user_ptr c) {
    LOG(INFO) << "user: " << c->name() << " joined: " << name_;
    users_.insert(c);
}

void chat_channel::leave(chat_user_ptr c) {
    LOG(INFO) << "user: " << c->name() << " left: " << name_;
    users_.erase(c);

    if (users_.empty()) {
        server_.remove_channel(name_);
    }
}

void chat_channel::leave_all() {
    if(!users_.empty()) {
        LOG(INFO) << name_ << " all users are forced to leave.";

        users_.clear();

        server_.remove_channel(name_);
    }
}

<commit_msg>added chan id to debug msg<commit_after>//
// Created by necator on 8/4/17.
//

#include <iostream>
#include "chat_channel.h"

#include "easylogging++.h"

#include "chat_user.h"
#include "chat_server.h"

chat_channel::chat_channel(chat_server &server, chat_user_manager &manager, const std::string &name) :
        server_(server),
        manager_(manager),
        name_(name) {
    LOG(INFO) << "channel: " << name_ << " is created.";
}

void chat_channel::publish(const message &msg) {
    LOG(INFO) << "channel: " << name_ << "publish: " << msg;

    for (auto u : users_)
        u->write(msg);
}

std::string chat_channel::name() const {
    return name_;
}

std::vector<std::string> chat_channel::user_names() const {
    std::vector<std::string> ret;

    std::transform(users_.begin(), users_.end(), std::back_inserter(ret), [](const chat_user_ptr u) {
        return u->name();
    });

    return ret;
}

void chat_channel::join(chat_user_ptr c) {
    LOG(INFO) << "user: " << c->name() << " joined: " << name_;
    users_.insert(c);
}

void chat_channel::leave(chat_user_ptr c) {
    LOG(INFO) << "user: " << c->name() << " left: " << name_;
    users_.erase(c);

    if (users_.empty()) {
        server_.remove_channel(name_);
    }
}

void chat_channel::leave_all() {
    if(!users_.empty()) {
        LOG(INFO) << name_ << " all users are forced to leave.";

        users_.clear();

        server_.remove_channel(name_);
    }
}

<|endoftext|>


<commit_before>/********************************************************************
 * AUTHORS: Trevor Hansen, Vijay Ganesh
 *
 * BEGIN DATE: July, 2009
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/
// -*- c++ -*-

#include "printers.h"
#include <cassert>
#include <cctype>

// Outputs in the SMTLIB format. If you want something that can be parsed by other tools call
// SMTLIB_PrintBack(). SMTLIB_Print() prints just an expression.
// Wierdly is seems that only terms, not formulas can be LETized.

namespace printer
{

  using std::string;
  using namespace BEEV;

  string functionToSMTLIBName(const BEEV::Kind k);
  void SMTLIB_Print1(ostream& os, const BEEV::ASTNode n, int indentation,	bool letize);
  void printVarDeclsToStream(ASTNodeSet& symbols, ostream& os);

  static string tolower(const char * name)
  {
    string s(name);
    for (size_t i = 0; i < s.size(); ++i)
      s[i] = ::tolower(s[i]);
    return s;
  }

//Map from ASTNodes to LetVars
ASTNodeMap NodeLetVarMap;

//This is a vector which stores the Node to LetVars pairs. It
//allows for sorted printing, as opposed to NodeLetVarMap
std::vector<pair<ASTNode, ASTNode> > NodeLetVarVec;

//a partial Map from ASTNodes to LetVars. Needed in order to
//correctly print shared subterms inside the LET itself
ASTNodeMap NodeLetVarMap1;

  // Initial version intended to print the whole thing back.
void SMTLIB_PrintBack(ostream &os, const ASTNode& n)
{
    os << "(" << endl;
    os << "benchmark blah" << endl;
	os << ":logic QF_AUFBV" << endl;
	ASTNodeSet visited, symbols;
	buildListOfSymbols(n, visited, symbols);
	printVarDeclsToStream(symbols, os);
	os << ":formula ";
    SMTLIB_Print(os, n, 0);
    os << ")" << endl;
  }

void printVarDeclsToStream(ASTNodeSet& symbols, ostream& os)
{
	for (ASTNodeSet::const_iterator i = symbols.begin(), iend = symbols.end(); i
			!= iend; i++)
	{
      const BEEV::ASTNode& a = *i;

      // Should be a symbol.
      assert(a.GetKind()== SYMBOL);

		switch (a.GetType())
		{
      case BEEV::BITVECTOR_TYPE:

        os << ":extrafuns (( ";
        a.nodeprint(os);
        os << " BitVec[" << a.GetValueWidth() << "]";
        os << " ))" << endl;
        break;
      case BEEV::ARRAY_TYPE:
        os << ":extrafuns (( ";
        a.nodeprint(os);
        os << " Array[" << a.GetIndexWidth();
        os << ":" << a.GetValueWidth() << "] ))" << endl;
        break;
      case BEEV::BOOLEAN_TYPE:
        os << ":extrapreds (( ";
        a.nodeprint(os);
        os << "))" << endl;
        break;
      default:
        BEEV::FatalError("printVarDeclsToStream: Unsupported type",a);
        break;
      }
    }
  } //printVarDeclsToStream

  void outputBitVec(const ASTNode n, ostream& os)
  {
	const Kind k = n.GetKind();
    const ASTVec &c = n.GetChildren();
    ASTNode op;

    if (BITVECTOR == k)
      {
        op = c[0];
      }
    else if (BVCONST == k)
      {
        op = n;
      }
    else
      FatalError("nsadfsdaf");

    // CONSTANTBV::BitVector_to_Dec returns a signed representation by default.
    // Prepend with zero to convert to unsigned.

    os << "bv";
	CBV unsign = CONSTANTBV::BitVector_Concat(
			n.GetSTPMgr()->CreateZeroConst(1).GetBVConst(), op.GetBVConst());
    unsigned char * str = CONSTANTBV::BitVector_to_Dec(unsign);
    CONSTANTBV::BitVector_Destroy(unsign);
    os << str << "[" << op.GetValueWidth() << "]";
    CONSTANTBV::BitVector_Dispose(str);
  }

  void SMTLIB_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
  {
    //os << spaces(indentation);
    //os << endl << spaces(indentation);
    if (!n.IsDefined())
      {
        os << "<undefined>";
        return;
      }

    //if this node is present in the letvar Map, then print the letvar
    //this is to print letvars for shared subterms inside the printing
    //of "(LET v0 = term1, v1=term1@term2,...
	if ((NodeLetVarMap1.find(n) != NodeLetVarMap1.end()) && !letize)
      {
		SMTLIB_Print1(os, (NodeLetVarMap1[n]), indentation, letize);
        return;
      }

    //this is to print letvars for shared subterms inside the actual
    //term to be printed
	if ((NodeLetVarMap.find(n) != NodeLetVarMap.end()) && letize)
      {
		SMTLIB_Print1(os, (NodeLetVarMap[n]), indentation, letize);
        return;
      }

    //otherwise print it normally
	const Kind kind = n.GetKind();
    const ASTVec &c = n.GetChildren();
    switch (kind)
      {
      case BITVECTOR:
      case BVCONST:
        outputBitVec(n, os);
        break;
      case SYMBOL:
        n.nodeprint(os);
        break;
      case FALSE:
        os << "false";
        break;
      case NAND: // No NAND in smtlib format.
    	  assert(c.size() ==2);
    	  os << "(" << "not ";
    	  os << "(" << "and ";
    	  SMTLIB_Print1(os, c[0], 0, letize);
    	  os << " " ;
    	  SMTLIB_Print1(os, c[1], 0, letize);
    	  os << "))";
    	  break;
      case TRUE:
        os << "true";
        break;
      case BVSX:
      case BVZX:
        {
          unsigned int amount = GetUnsignedConst(c[1]);
          if (BVZX == kind)
            os << "(zero_extend[";
          else
            os << "(sign_extend[";

		os << (amount - c[0].GetValueWidth()) << "]";
          SMTLIB_Print1(os, c[0], indentation, letize);
          os << ")";
        }
        break;
      case BVEXTRACT:
        {
          unsigned int upper = GetUnsignedConst(c[1]);
          unsigned int lower = GetUnsignedConst(c[2]);
          assert(upper >= lower);
          os << "(extract[" << upper << ":" << lower << "] ";
          SMTLIB_Print1(os, c[0], indentation, letize);
          os << ")";
        }
        break;
  	default:
  	{
  		// SMT-LIB only allows arithmetic functions to have two parameters.
  		if (BVPLUS == kind && n.Degree() > 2)
  		{
  			string close = "";

  			for (int i =0; i < c.size()-1; i++)
  			{
  				os << "(" << functionToSMTLIBName(kind);
  				os << " ";
  				SMTLIB_Print1(os, c[i], 0, letize);
  				os << " ";
  				close += ")";
  			}
  			SMTLIB_Print1(os, c[c.size()-1], 0, letize);
  			os << close;
  		}
  		else
  		{
  			os << "(" << functionToSMTLIBName(kind);

  			ASTVec::const_iterator iend = c.end();
  			for (ASTVec::const_iterator i = c.begin(); i != iend; i++)
  			{
  				os << " ";
  				SMTLIB_Print1(os, *i, 0, letize);
  			}

  			os << ")";
  		}
  	}
      }
  }

void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet)
{
	const Kind kind = n.GetKind();

	if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
		return;

	const ASTVec &c = n.GetChildren();
	for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
	{
		const ASTNode& ccc = *it;

		const Kind k = ccc.GetKind();
		if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
			continue;

		if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
		{
			//If branch: if *it is not in NodeSet then,
			//
			//1. add it to NodeSet
			//
			//2. Letize its childNodes
			PLPrintNodeSet.insert(ccc);
			LetizeNode(ccc, PLPrintNodeSet);
		}
		else
		{
			//0. Else branch: Node has been seen before
			//
			//1. Check if the node has a corresponding letvar in the
			//1. NodeLetVarMap.
			//
			//2. if no, then create a new var and add it to the
			//2. NodeLetVarMap
			if (ccc.GetType() == BITVECTOR_TYPE && NodeLetVarMap.find(ccc)
					== NodeLetVarMap.end())
			{
				//Create a new symbol. Get some name. if it conflicts with a
				//declared name, too bad.
				int sz = NodeLetVarMap.size();
				ostringstream oss;
				oss << "?let_k_" << sz;

				ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
						oss.str().c_str());
				CurrentSymbol.SetValueWidth(n.GetValueWidth());
				CurrentSymbol.SetIndexWidth(n.GetIndexWidth());
				/* If for some reason the variable being created here is
				 * already declared by the user then the printed output will
				 * not be a legal input to the system. too bad. I refuse to
				 * check for this.  [Vijay is the author of this comment.]
				 */

				NodeLetVarMap[ccc] = CurrentSymbol;
				std::pair<ASTNode, ASTNode>
						node_letvar_pair(CurrentSymbol, ccc);
				NodeLetVarVec.push_back(node_letvar_pair);
			}
		}
	}
} //end of LetizeNode()

  // copied from Presentation Langauge printer.
  ostream& SMTLIB_Print(ostream &os, const ASTNode n, const int indentation)
  {
    // Clear the maps
	NodeLetVarMap.clear();
	NodeLetVarVec.clear();
	NodeLetVarMap1.clear();

    //pass 1: letize the node
	{
		ASTNodeSet PLPrintNodeSet;
		LetizeNode(n, PLPrintNodeSet);
	}

    //pass 2:
    //
    //2. print all the let variables and their counterpart expressions
    //2. as follows (LET var1 = expr1, var2 = expr2, ...
    //
    //3. Then print the Node itself, replacing every occurence of
    //3. expr1 with var1, expr2 with var2, ...
    //os << "(";
	if (0 < NodeLetVarMap.size())
      {
		std::vector<pair<ASTNode, ASTNode> >::iterator it =
				NodeLetVarVec.begin();
		const std::vector<pair<ASTNode, ASTNode> >::iterator itend =
				NodeLetVarVec.end();

		os << "(let (";
        //print the let var first
        SMTLIB_Print1(os, it->first, indentation, false);
		os << " ";
        //print the expr
        SMTLIB_Print1(os, it->second, indentation, false);
		os << " )";

        //update the second map for proper printing of LET
		NodeLetVarMap1[it->second] = it->first;

		string closing = "";
        for (it++; it != itend; it++)
          {
			os << " " << endl;
			os << "(let (";
            //print the let var first
            SMTLIB_Print1(os, it->first, indentation, false);
			os << " ";
            //print the expr
            SMTLIB_Print1(os, it->second, indentation, false);
			os << ")";
            //update the second map for proper printing of LET
			NodeLetVarMap1[it->second] = it->first;
			closing += ")";
          }

		os << " ( " << endl;
        SMTLIB_Print1(os, n, indentation, true);
		os << closing;
		os << " ) ) ";

      }
    else
      SMTLIB_Print1(os, n, indentation, false);

    os << endl;
    return os;
  }

  string functionToSMTLIBName(const Kind k)
  {
    switch (k)
      {
      case AND:
      case BVAND:
      case BVNAND:
      case BVNOR:
      case BVOR:
      case BVSGE:
      case BVSGT:
      case BVSLE:
      case BVSLT:
      case BVSUB:
      case BVXOR:
      case ITE:
      case NAND:
      case NOR:
      case NOT:
      case OR:
      case XOR:
      case IFF:
      case IMPLIES:
	{
        return tolower(_kind_names[k]);
	}

      case BVCONCAT:
        return "concat";
      case BVDIV:
        return "bvudiv";
      case BVGT:
        return "bvugt";
      case BVGE:
        return "bvuge";
      case BVLE:
        return "bvule";
      case BVLEFTSHIFT:
        return "bvshl";
      case BVLT:
        return "bvult";
      case BVMOD:
        return "bvurem";
      case BVMULT:
        return "bvmul";
      case BVNEG:
        return "bvnot"; // CONFUSSSSINNG. (1/2)
      case BVPLUS:
        return "bvadd";
      case BVRIGHTSHIFT:
        return "bvlshr"; // logical
      case BVSRSHIFT:
        return "bvashr"; // arithmetic.
      case BVUMINUS:
        return "bvneg"; // CONFUSSSSINNG. (2/2)
      case EQ:
        return "=";
      case READ:
        return "select";
      case WRITE:
        return "store";
      case SBVDIV:
        return "bvsdiv";
      case SBVREM:
        return "bvsrem";

      default:
        {
          cerr << "Unknown name when outputting:";
          FatalError(_kind_names[k]);
          return ""; // to quieten compiler/
        }
      }
  }

}
<commit_msg>When outputting to SMTLIB format handle properly some cases when the number of arguments > 2.<commit_after>/********************************************************************
 * AUTHORS: Trevor Hansen, Vijay Ganesh
 *
 * BEGIN DATE: July, 2009
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/
// -*- c++ -*-

#include "printers.h"
#include <cassert>
#include <cctype>

// Outputs in the SMTLIB format. If you want something that can be parsed by other tools call
// SMTLIB_PrintBack(). SMTLIB_Print() prints just an expression.
// Wierdly is seems that only terms, not formulas can be LETized.

namespace printer
{

  using std::string;
  using namespace BEEV;

  string functionToSMTLIBName(const BEEV::Kind k);
  void SMTLIB_Print1(ostream& os, const BEEV::ASTNode n, int indentation,	bool letize);
  void printVarDeclsToStream(ASTNodeSet& symbols, ostream& os);

  static string tolower(const char * name)
  {
    string s(name);
    for (size_t i = 0; i < s.size(); ++i)
      s[i] = ::tolower(s[i]);
    return s;
  }

//Map from ASTNodes to LetVars
ASTNodeMap NodeLetVarMap;

//This is a vector which stores the Node to LetVars pairs. It
//allows for sorted printing, as opposed to NodeLetVarMap
std::vector<pair<ASTNode, ASTNode> > NodeLetVarVec;

//a partial Map from ASTNodes to LetVars. Needed in order to
//correctly print shared subterms inside the LET itself
ASTNodeMap NodeLetVarMap1;

  // Initial version intended to print the whole thing back.
void SMTLIB_PrintBack(ostream &os, const ASTNode& n)
{
    os << "(" << endl;
    os << "benchmark blah" << endl;
	os << ":logic QF_AUFBV" << endl;
	ASTNodeSet visited, symbols;
	buildListOfSymbols(n, visited, symbols);
	printVarDeclsToStream(symbols, os);
	os << ":formula ";
    SMTLIB_Print(os, n, 0);
    os << ")" << endl;
  }

void printVarDeclsToStream(ASTNodeSet& symbols, ostream& os)
{
	for (ASTNodeSet::const_iterator i = symbols.begin(), iend = symbols.end(); i
			!= iend; i++)
	{
      const BEEV::ASTNode& a = *i;

      // Should be a symbol.
      assert(a.GetKind()== SYMBOL);

		switch (a.GetType())
		{
      case BEEV::BITVECTOR_TYPE:

        os << ":extrafuns (( ";
        a.nodeprint(os);
        os << " BitVec[" << a.GetValueWidth() << "]";
        os << " ))" << endl;
        break;
      case BEEV::ARRAY_TYPE:
        os << ":extrafuns (( ";
        a.nodeprint(os);
        os << " Array[" << a.GetIndexWidth();
        os << ":" << a.GetValueWidth() << "] ))" << endl;
        break;
      case BEEV::BOOLEAN_TYPE:
        os << ":extrapreds (( ";
        a.nodeprint(os);
        os << "))" << endl;
        break;
      default:
        BEEV::FatalError("printVarDeclsToStream: Unsupported type",a);
        break;
      }
    }
  } //printVarDeclsToStream

  void outputBitVec(const ASTNode n, ostream& os)
  {
	const Kind k = n.GetKind();
    const ASTVec &c = n.GetChildren();
    ASTNode op;

    if (BITVECTOR == k)
      {
        op = c[0];
      }
    else if (BVCONST == k)
      {
        op = n;
      }
    else
      FatalError("nsadfsdaf");

    // CONSTANTBV::BitVector_to_Dec returns a signed representation by default.
    // Prepend with zero to convert to unsigned.

    os << "bv";
	CBV unsign = CONSTANTBV::BitVector_Concat(
			n.GetSTPMgr()->CreateZeroConst(1).GetBVConst(), op.GetBVConst());
    unsigned char * str = CONSTANTBV::BitVector_to_Dec(unsign);
    CONSTANTBV::BitVector_Destroy(unsign);
    os << str << "[" << op.GetValueWidth() << "]";
    CONSTANTBV::BitVector_Dispose(str);
  }

  void SMTLIB_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
  {
    //os << spaces(indentation);
    //os << endl << spaces(indentation);
    if (!n.IsDefined())
      {
        os << "<undefined>";
        return;
      }

    //if this node is present in the letvar Map, then print the letvar
    //this is to print letvars for shared subterms inside the printing
    //of "(LET v0 = term1, v1=term1@term2,...
	if ((NodeLetVarMap1.find(n) != NodeLetVarMap1.end()) && !letize)
      {
		SMTLIB_Print1(os, (NodeLetVarMap1[n]), indentation, letize);
        return;
      }

    //this is to print letvars for shared subterms inside the actual
    //term to be printed
	if ((NodeLetVarMap.find(n) != NodeLetVarMap.end()) && letize)
      {
		SMTLIB_Print1(os, (NodeLetVarMap[n]), indentation, letize);
        return;
      }

    //otherwise print it normally
	const Kind kind = n.GetKind();
    const ASTVec &c = n.GetChildren();
    switch (kind)
      {
      case BITVECTOR:
      case BVCONST:
        outputBitVec(n, os);
        break;
      case SYMBOL:
        n.nodeprint(os);
        break;
      case FALSE:
        os << "false";
        break;
      case NAND: // No NAND, NOR in smtlib format.
      case NOR:
    	  assert(c.size() ==2);
    	  os << "(" << "not ";
    	  if (NAND == kind )
    		  os << "(" << "and ";
    	  else
    		  os << "(" << "or ";
    	  SMTLIB_Print1(os, c[0], 0, letize);
    	  os << " " ;
    	  SMTLIB_Print1(os, c[1], 0, letize);
    	  os << "))";
    	  break;
      case TRUE:
        os << "true";
        break;
      case BVSX:
      case BVZX:
        {
          unsigned int amount = GetUnsignedConst(c[1]);
          if (BVZX == kind)
            os << "(zero_extend[";
          else
            os << "(sign_extend[";

		os << (amount - c[0].GetValueWidth()) << "]";
          SMTLIB_Print1(os, c[0], indentation, letize);
          os << ")";
        }
        break;
      case BVEXTRACT:
        {
          unsigned int upper = GetUnsignedConst(c[1]);
          unsigned int lower = GetUnsignedConst(c[2]);
          assert(upper >= lower);
          os << "(extract[" << upper << ":" << lower << "] ";
          SMTLIB_Print1(os, c[0], indentation, letize);
          os << ")";
        }
        break;
  	default:
  	{
  		// SMT-LIB only allows these functions to have two parameters.
  		if ((BVPLUS == kind || kind == BVOR || kind == BVAND)  && n.Degree() > 2)
  		{
  			string close = "";

  			for (int i =0; i < c.size()-1; i++)
  			{
  				os << "(" << functionToSMTLIBName(kind);
  				os << " ";
  				SMTLIB_Print1(os, c[i], 0, letize);
  				os << " ";
  				close += ")";
  			}
  			SMTLIB_Print1(os, c[c.size()-1], 0, letize);
  			os << close;
  		}
  		else
  		{
  			os << "(" << functionToSMTLIBName(kind);

  			ASTVec::const_iterator iend = c.end();
  			for (ASTVec::const_iterator i = c.begin(); i != iend; i++)
  			{
  				os << " ";
  				SMTLIB_Print1(os, *i, 0, letize);
  			}

  			os << ")";
  		}
  	}
      }
  }

void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet)
{
	const Kind kind = n.GetKind();

	if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
		return;

	const ASTVec &c = n.GetChildren();
	for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
	{
		const ASTNode& ccc = *it;

		const Kind k = ccc.GetKind();
		if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
			continue;

		if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
		{
			//If branch: if *it is not in NodeSet then,
			//
			//1. add it to NodeSet
			//
			//2. Letize its childNodes
			PLPrintNodeSet.insert(ccc);
			LetizeNode(ccc, PLPrintNodeSet);
		}
		else
		{
			//0. Else branch: Node has been seen before
			//
			//1. Check if the node has a corresponding letvar in the
			//1. NodeLetVarMap.
			//
			//2. if no, then create a new var and add it to the
			//2. NodeLetVarMap
			if (ccc.GetType() == BITVECTOR_TYPE && NodeLetVarMap.find(ccc)
					== NodeLetVarMap.end())
			{
				//Create a new symbol. Get some name. if it conflicts with a
				//declared name, too bad.
				int sz = NodeLetVarMap.size();
				ostringstream oss;
				oss << "?let_k_" << sz;

				ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
						oss.str().c_str());
				CurrentSymbol.SetValueWidth(n.GetValueWidth());
				CurrentSymbol.SetIndexWidth(n.GetIndexWidth());
				/* If for some reason the variable being created here is
				 * already declared by the user then the printed output will
				 * not be a legal input to the system. too bad. I refuse to
				 * check for this.  [Vijay is the author of this comment.]
				 */

				NodeLetVarMap[ccc] = CurrentSymbol;
				std::pair<ASTNode, ASTNode>
						node_letvar_pair(CurrentSymbol, ccc);
				NodeLetVarVec.push_back(node_letvar_pair);
			}
		}
	}
} //end of LetizeNode()

  // copied from Presentation Langauge printer.
  ostream& SMTLIB_Print(ostream &os, const ASTNode n, const int indentation)
  {
    // Clear the maps
	NodeLetVarMap.clear();
	NodeLetVarVec.clear();
	NodeLetVarMap1.clear();

    //pass 1: letize the node
	{
		ASTNodeSet PLPrintNodeSet;
		LetizeNode(n, PLPrintNodeSet);
	}

    //pass 2:
    //
    //2. print all the let variables and their counterpart expressions
    //2. as follows (LET var1 = expr1, var2 = expr2, ...
    //
    //3. Then print the Node itself, replacing every occurence of
    //3. expr1 with var1, expr2 with var2, ...
    //os << "(";
	if (0 < NodeLetVarMap.size())
      {
		std::vector<pair<ASTNode, ASTNode> >::iterator it =
				NodeLetVarVec.begin();
		const std::vector<pair<ASTNode, ASTNode> >::iterator itend =
				NodeLetVarVec.end();

		os << "(let (";
        //print the let var first
        SMTLIB_Print1(os, it->first, indentation, false);
		os << " ";
        //print the expr
        SMTLIB_Print1(os, it->second, indentation, false);
		os << " )";

        //update the second map for proper printing of LET
		NodeLetVarMap1[it->second] = it->first;

		string closing = "";
        for (it++; it != itend; it++)
          {
			os << " " << endl;
			os << "(let (";
            //print the let var first
            SMTLIB_Print1(os, it->first, indentation, false);
			os << " ";
            //print the expr
            SMTLIB_Print1(os, it->second, indentation, false);
			os << ")";
            //update the second map for proper printing of LET
			NodeLetVarMap1[it->second] = it->first;
			closing += ")";
          }

		os << " ( " << endl;
        SMTLIB_Print1(os, n, indentation, true);
		os << closing;
		os << " ) ) ";

      }
    else
      SMTLIB_Print1(os, n, indentation, false);

    os << endl;
    return os;
  }

  string functionToSMTLIBName(const Kind k)
  {
    switch (k)
      {
      case AND:
      case BVAND:
      case BVNAND:
      case BVNOR:
      case BVOR:
      case BVSGE:
      case BVSGT:
      case BVSLE:
      case BVSLT:
      case BVSUB:
      case BVXOR:
      case ITE:
      case NAND:
      case NOR:
      case NOT:
      case OR:
      case XOR:
      case IFF:
      case IMPLIES:
	{
        return tolower(_kind_names[k]);
	}

      case BVCONCAT:
        return "concat";
      case BVDIV:
        return "bvudiv";
      case BVGT:
        return "bvugt";
      case BVGE:
        return "bvuge";
      case BVLE:
        return "bvule";
      case BVLEFTSHIFT:
        return "bvshl";
      case BVLT:
        return "bvult";
      case BVMOD:
        return "bvurem";
      case BVMULT:
        return "bvmul";
      case BVNEG:
        return "bvnot"; // CONFUSSSSINNG. (1/2)
      case BVPLUS:
        return "bvadd";
      case BVRIGHTSHIFT:
        return "bvlshr"; // logical
      case BVSRSHIFT:
        return "bvashr"; // arithmetic.
      case BVUMINUS:
        return "bvneg"; // CONFUSSSSINNG. (2/2)
      case EQ:
        return "=";
      case READ:
        return "select";
      case WRITE:
        return "store";
      case SBVDIV:
        return "bvsdiv";
      case SBVREM:
        return "bvsrem";

      default:
        {
          cerr << "Unknown name when outputting:";
          FatalError(_kind_names[k]);
          return ""; // to quieten compiler/
        }
      }
  }

}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2019 Intel Corporation. All Rights Reserved.

#include <fstream>
#include "../common/decompress-huffman.h"
#include "proc/depth-decompress.h"
#include "environment.h"

namespace librealsense
{
    depth_decompression_huffman::depth_decompression_huffman():
        functional_processing_block("Depth Huffman Decoder", RS2_FORMAT_Z16, RS2_STREAM_DEPTH, RS2_EXTENSION_DEPTH_FRAME)
    {
        get_option(RS2_OPTION_STREAM_FILTER).set(RS2_STREAM_DEPTH);
        get_option(RS2_OPTION_STREAM_FORMAT_FILTER).set(RS2_FORMAT_Z16H);
    };

    void depth_decompression_huffman::process_function(byte* const dest[], const byte* source, int width, int height, int actual_size, int input_size)
    {
        if (!unhuffimage4(reinterpret_cast<uint32_t*>(const_cast<byte*>(source)), uint32_t(input_size >> 2), width << 1, height, const_cast<byte*>(*dest)))
        {
            std::stringstream ss;
            ss << "Depth_huffman_decode_error_input_ts_" << static_cast<uint64_t>(environment::get_instance().get_time_service()->get_time()) << "_"
                <<  input_size << "_output_" << actual_size << ".raw";
            std::string filename = ss.str().c_str();

            LOG_ERROR("Depth decompression error, binary dump: " << filename);
            std::ofstream file(filename, std::ios::binary | std::ios::trunc);
            if (!file.good())
                throw std::runtime_error(to_string() << "Invalid binary file specified " << filename << " verify the target path and location permissions");
            file.write((const char*)source, input_size);
        }
    }
}
<commit_msg>Remove debugging section<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2019 Intel Corporation. All Rights Reserved.

#include <fstream>
#include "../common/decompress-huffman.h"
#include "proc/depth-decompress.h"
#include "environment.h"

namespace librealsense
{
    depth_decompression_huffman::depth_decompression_huffman():
        functional_processing_block("Depth Huffman Decoder", RS2_FORMAT_Z16, RS2_STREAM_DEPTH, RS2_EXTENSION_DEPTH_FRAME)
    {
        get_option(RS2_OPTION_STREAM_FILTER).set(RS2_STREAM_DEPTH);
        get_option(RS2_OPTION_STREAM_FORMAT_FILTER).set(RS2_FORMAT_Z16H);
    }

    void depth_decompression_huffman::process_function(byte* const dest[], const byte* source, int width, int height, int actual_size, int input_size)
    {
        if (!unhuffimage4(reinterpret_cast<uint32_t*>(const_cast<byte*>(source)), uint32_t(input_size >> 2), width << 1, height, const_cast<byte*>(*dest)))
        {
            LOG_WARNING("Depth decompression failed, ts: " << static_cast<uint64_t>(environment::get_instance().get_time_service()->get_time())
                        << " , compressed size: " << input_size);
        }
    }
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2018 Intel Corporation. All Rights Reserved.

#include "../include/librealsense2/rs.hpp"
#include "../include/librealsense2/rsutil.h"

#include "proc/synthetic-stream.h"
#include "proc/occlusion-filter.h"
#include  "../../common/tiny-profiler.h"
#include <vector>
#include <cmath>

#define ROTATION_BUFFER_SIZE 8
#define VERTICAL_SCAN_WINDOW_SIZE 64
#define DEPTH_OCCLUSION_THRESHOLD 1

namespace librealsense
{
    occlusion_filter::occlusion_filter() : _occlusion_filter(occlusion_monotonic_scan) , _occlusion_scanning(horizontal)
    {
    }

    void occlusion_filter::set_texel_intrinsics(const rs2_intrinsics& in)
    {
        _texels_intrinsics = in;
        _texels_depth.resize(_texels_intrinsics.value().width*_texels_intrinsics.value().height);
    }

   void occlusion_filter::process(float3* points, float2* uv_map, const std::vector<float2> & pix_coord, const rs2::depth_frame& depth) const
    {
        switch (_occlusion_filter)
        {
        case occlusion_none:
            break;
        case occlusion_monotonic_scan:
            monotonic_heuristic_invalidation(points, uv_map, pix_coord, depth);
            break;
        default:
            throw std::runtime_error(to_string() << "Unsupported occlusion filter type " << _occlusion_filter << " requested");
            break;
        }
    }

    template<size_t SIZE>
    void rotate_image_counterclockwise(byte* dest[], const byte* source, int width, int height)
    {
        {
            scoped_timer t1("Rotation Time - counterclockwise");
            auto width_out = height;
            auto height_out = width;

            auto out = dest[0];
            byte buffer[ROTATION_BUFFER_SIZE][ROTATION_BUFFER_SIZE * SIZE]; // = { 0 };
            for (int i = 0; i <= height - ROTATION_BUFFER_SIZE; i = i + ROTATION_BUFFER_SIZE)
            {
                for (int j = 0; j <= width - ROTATION_BUFFER_SIZE; j = j + ROTATION_BUFFER_SIZE)
                {
                    for (int ii = 0; ii < ROTATION_BUFFER_SIZE; ++ii)
                    {
                        auto out_index = (((height_out - ROTATION_BUFFER_SIZE - j + 1) * width_out) - i - ROTATION_BUFFER_SIZE + (ii)*width_out);
                        memcpy(&(buffer[ii]), &source[(out_index)*SIZE], ROTATION_BUFFER_SIZE * SIZE);
                    }
                    for (int ii = 0; ii < ROTATION_BUFFER_SIZE; ++ii)
                    {
                        for (int jj = 0; jj < ROTATION_BUFFER_SIZE; ++jj)
                        {
                            auto source_index = ((j + jj) + (width * (i + ii))) * SIZE;
                            memcpy(&out[source_index], (void*)(&buffer[ROTATION_BUFFER_SIZE - 1 - jj][(ROTATION_BUFFER_SIZE - 1 - ii) * SIZE]), SIZE);
                        }
                    }

                }
            }
        }
    }
    // IMPORTANT! This implementation is based on the assumption that the RGB sensor is positioned strictly to the left of the depth sensor.
    // namely D415/D435 and SR300. The implementation WILL NOT work properly for different setups
    // Heuristic occlusion invalidation algorithm:
    // -  Use the uv texels calculated when projecting depth to color
    // -  Scan each line from left to right and check the the U coordinate in the mapping is raising monotonically.
    // -  The occlusion is designated as U coordinate for a given pixel is less than the U coordinate of the predecessing pixel.
    // -  The UV mapping for the occluded pixel is reset to (0,0). Later on the (0,0) coordinate in the texture map is overwritten
    //    with a invalidation color such as black/magenta according to the purpose (production/debugging)
    void occlusion_filter::monotonic_heuristic_invalidation(float3* points, float2* uv_map, const std::vector<float2>& pix_coord, const rs2::depth_frame& depth) const
    {
        float occZTh = 0.1f; //meters
        int occDilationSz = 1;
        auto points_width = _depth_intrinsics->width;
        auto points_height = _depth_intrinsics->height;
        auto pixels_ptr = pix_coord.data();
        auto points_ptr = points;
        auto uv_map_ptr = uv_map;
        float maxInLine = -1;
        float maxZ = 0;

        auto frame_size = static_cast<int>(_depth_intrinsics->width * _depth_intrinsics->height);
        std::allocator<byte> alloc;
        byte* depth_planes[1];

        if (_occlusion_scanning == horizontal)
        {

            {
                scoped_timer t1("Horizontal Scan");
                for (size_t y = 0; y < points_height; ++y)
                {

                    maxInLine = -1;
                    maxZ = 0;
                    int occDilationLeft = 0;

                    for (size_t x = 0; x < points_width; ++x)
                    {
                        if (points_ptr->z)
                        {
                            //Occlusion detection
                            if (pixels_ptr->x < maxInLine || (pixels_ptr->x == maxInLine && (points_ptr->z - maxZ) > occZTh))
                            {
                                *points_ptr = { 0, 0, 0 };
                                occDilationLeft = occDilationSz;
                            }
                            else
                            {
                                maxInLine = pixels_ptr->x;
                                maxZ = points_ptr->z;
                                if (occDilationLeft > 0)
                                {
                                    *points_ptr = { 0, 0, 0 };
                                    occDilationLeft--;
                                }
                            }
                        }
                        ++points_ptr;
                        ++uv_map_ptr;
                        ++pixels_ptr;
                    }
                }
            }
        }
        else if (_occlusion_scanning == vertical)
        {
            depth_planes[0] = (byte*)alloc.allocate(depth.get_bytes_per_pixel() * frame_size);
            int bpp = depth.get_bytes_per_pixel();
            rotate_image_counterclockwise<2>(depth_planes, (const byte*)(depth.get_data()), points_width, points_height);

            // scan depth frame after clockwise rotation: check if there is a significant jump between adjacen pixels in Z-axis (depth), it means there could be occlusion.
            // scan over a small window so that points depth is the same
            // save suspected points and run occlusion-invalidation vertical scan only on them
            // after rotation : height = points_width , width = points_height

            auto rotated_depth_width = _depth_intrinsics->height;
            auto rotated_depth_height = _depth_intrinsics->width;

            for (int i = 0; i < rotated_depth_height; i++)
            {
                for (int j = 0; j < rotated_depth_width - VERTICAL_SCAN_WINDOW_SIZE; j = j + VERTICAL_SCAN_WINDOW_SIZE)
                {
                    // before rotation: occlusion detected in the positive direction of Y
                    // after counterclockwise rotation : scan from right to left (positive direction of X) to detect occlusion
                    // compare depth each pixel only with the pixel on its right (i,j+1)
                    auto index = i * rotated_depth_width + j;
                    auto uv_i = j;
                    auto uv_j = rotated_depth_height - i;
                    auto uv_index = uv_i * rotated_depth_height + uv_j; // 90 degrees rotation transform from rotated depth
                    auto index_right = index + 1;
                    float diff_right = abs((depth_planes[0])[index] - (depth_planes[0])[index_right]);

                    if ((diff_right > DEPTH_OCCLUSION_THRESHOLD))
                    {
                        pixels_ptr = pix_coord.data() + uv_index;
                        points_ptr = points + uv_index;
                        uv_map_ptr = uv_map + uv_index;
                        maxInLine = -1;
                        maxZ = 0;
                        int occDilationUp = 0;

                        for (size_t y = 0; y <= VERTICAL_SCAN_WINDOW_SIZE; ++y)
                        {
                            if (((pixels_ptr + y * points_width)->y < maxInLine))
                            {
                                *(points_ptr + y * points_width) = { 0.f, 0.f, 0.f };
                            }
                            else
                            {
                                maxInLine = (pixels_ptr + y * points_width)->y;
                            }

                        }
                    }
                }
            }
        }
    }
    // Prepare texture map without occlusion that for every texture coordinate there no more than one depth point that is mapped to it
    // i.e. for every (u,v) map coordinate we select the depth point with minimum Z. all other points that are mapped to this texel will be invalidated
    // Algo input data:
    // Vector of 3D [xyz] coordinates of depth_width*depth_height size
    // Vector of 2D [i,j] coordinates where the val[i,j] stores the texture coordinate (s,t) for the corresponding (i,j) pixel in depth frame
    // Algo intermediate data:
    // Vector of depth values (floats) in size of the mapped texture (different from depth width*height) where
    // each (i,j) cell holds the minimal Z among all the depth pixels that are mapped to the specific texel
    void occlusion_filter::comprehensive_invalidation(float3* points, float2* uv_map, const std::vector<float2> & pix_coord) const
    {
        auto depth_points = points;
        auto mapped_pix = pix_coord.data();
        size_t mapped_tex_width = _texels_intrinsics->width;
        size_t mapped_tex_height = _texels_intrinsics->height;
        size_t points_width = _depth_intrinsics->width;
        size_t points_height = _depth_intrinsics->height;

        static const float z_threshold = 0.05f; // Compensate for temporal noise when comparing Z values

        // Clear previous data
        memset((void*)(_texels_depth.data()), 0, _texels_depth.size() * sizeof(float));

        // Pass1 -generate texels mapping with minimal depth for each texel involved
        for (size_t i = 0; i < points_height; i++)
        {
            for (size_t j = 0; j < points_width; j++)
            {
                if ((depth_points->z > 0.0001f) &&
                    (mapped_pix->x > 0.f) && (mapped_pix->x < mapped_tex_width) &&
                    (mapped_pix->y > 0.f) && (mapped_pix->y < mapped_tex_height))
                {
                    size_t texel_index = (size_t)(mapped_pix->y)*mapped_tex_width + (size_t)(mapped_pix->x);

                    if ((_texels_depth[texel_index] < 0.0001f) || ((_texels_depth[texel_index] + z_threshold) > depth_points->z))
                    {
                        _texels_depth[texel_index] = depth_points->z;
                    }
                }

                ++depth_points;
                ++mapped_pix;
            }
        }

        mapped_pix = pix_coord.data();
        depth_points = points;
        auto uv_ptr = uv_map;

        // Pass2 -invalidate depth texels with occlusion traits
        for (size_t i = 0; i < points_height; i++)
        {
            for (size_t j = 0; j < points_width; j++)
            {
                if ((depth_points->z > 0.0001f) &&
                    (mapped_pix->x > 0.f) && (mapped_pix->x < mapped_tex_width) &&
                    (mapped_pix->y > 0.f) && (mapped_pix->y < mapped_tex_height))
                {
                    size_t texel_index = (size_t)(mapped_pix->y)*mapped_tex_width + (size_t)(mapped_pix->x);

                    if ((_texels_depth[texel_index] > 0.0001f) && ((_texels_depth[texel_index] + z_threshold) < depth_points->z))
                    {
                        *uv_ptr = { 0.f, 0.f };
                    }
                }

                ++depth_points;
                ++mapped_pix;
                ++uv_ptr;
            }
        }
    }
}
<commit_msg>L500 oclusion invalidation performance improvement<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2018 Intel Corporation. All Rights Reserved.

#include "../include/librealsense2/rs.hpp"
#include "../include/librealsense2/rsutil.h"

#include "proc/synthetic-stream.h"
#include "proc/occlusion-filter.h"
#include  "../../common/tiny-profiler.h"
#include <vector>
#include <cmath>

#define ROTATION_BUFFER_SIZE 8
#define VERTICAL_SCAN_WINDOW_SIZE 64
#define DEPTH_OCCLUSION_THRESHOLD 1

namespace librealsense
{
    occlusion_filter::occlusion_filter() : _occlusion_filter(occlusion_monotonic_scan) , _occlusion_scanning(horizontal)
    {
    }

    void occlusion_filter::set_texel_intrinsics(const rs2_intrinsics& in)
    {
        _texels_intrinsics = in;
        _texels_depth.resize(_texels_intrinsics.value().width*_texels_intrinsics.value().height);
    }

   void occlusion_filter::process(float3* points, float2* uv_map, const std::vector<float2> & pix_coord, const rs2::depth_frame& depth) const
    {
        switch (_occlusion_filter)
        {
        case occlusion_none:
            break;
        case occlusion_monotonic_scan:
            monotonic_heuristic_invalidation(points, uv_map, pix_coord, depth);
            break;
        default:
            throw std::runtime_error(to_string() << "Unsupported occlusion filter type " << _occlusion_filter << " requested");
            break;
        }
    }

    template<size_t SIZE>
    void rotate_image_counterclockwise(byte* dest[], const byte* source, int width, int height)
    {
        {
            scoped_timer t1("Rotation Time - counterclockwise");
            auto width_out = height;
            auto height_out = width;

            auto out = dest[0];
            byte buffer[ROTATION_BUFFER_SIZE][ROTATION_BUFFER_SIZE * SIZE];
            for (int i = 0; i <= height - ROTATION_BUFFER_SIZE; i = i + ROTATION_BUFFER_SIZE)
            {
                for (int j = 0; j <= width - ROTATION_BUFFER_SIZE; j = j + ROTATION_BUFFER_SIZE)
                {
                    for (int ii = 0; ii < ROTATION_BUFFER_SIZE; ++ii)
                    {
                        auto out_index = (((height_out - ROTATION_BUFFER_SIZE - j + 1) * width_out) - i - ROTATION_BUFFER_SIZE + (ii)*width_out);
                        memcpy(&(buffer[ii]), &source[(out_index)*SIZE], ROTATION_BUFFER_SIZE * SIZE);
                    }
                    for (int ii = 0; ii < ROTATION_BUFFER_SIZE; ++ii)
                    {
                        for (int jj = 0; jj < ROTATION_BUFFER_SIZE; ++jj)
                        {
                            auto source_index = ((j + jj) + (width * (i + ii))) * SIZE;
                            memcpy(&out[source_index], (void*)(&buffer[ROTATION_BUFFER_SIZE - 1 - jj][(ROTATION_BUFFER_SIZE - 1 - ii) * SIZE]), SIZE);
                        }
                    }

                }
            }
        }
    }
    // IMPORTANT! This implementation is based on the assumption that the RGB sensor is positioned strictly to the left of the depth sensor.
    // namely D415/D435 and SR300. The implementation WILL NOT work properly for different setups
    // Heuristic occlusion invalidation algorithm:
    // -  Use the uv texels calculated when projecting depth to color
    // -  Scan each line from left to right and check the the U coordinate in the mapping is raising monotonically.
    // -  The occlusion is designated as U coordinate for a given pixel is less than the U coordinate of the predecessing pixel.
    // -  The UV mapping for the occluded pixel is reset to (0,0). Later on the (0,0) coordinate in the texture map is overwritten
    //    with a invalidation color such as black/magenta according to the purpose (production/debugging)
    void occlusion_filter::monotonic_heuristic_invalidation(float3* points, float2* uv_map, const std::vector<float2>& pix_coord, const rs2::depth_frame& depth) const
    {
        float occZTh = 0.1f; //meters
        int occDilationSz = 1;
        auto points_width = _depth_intrinsics->width;
        auto points_height = _depth_intrinsics->height;
        auto pixels_ptr = pix_coord.data();
        auto points_ptr = points;
        auto uv_map_ptr = uv_map;
        float maxInLine = -1;
        float maxZ = 0;

        auto frame_size = static_cast<int>(_depth_intrinsics->width * _depth_intrinsics->height);
        std::allocator<byte> alloc;
        byte* depth_planes[1];

        if (_occlusion_scanning == horizontal)
        {

            {
                scoped_timer t1("Horizontal Scan");
                for (size_t y = 0; y < points_height; ++y)
                {

                    maxInLine = -1;
                    maxZ = 0;
                    int occDilationLeft = 0;

                    for (size_t x = 0; x < points_width; ++x)
                    {
                        if (points_ptr->z)
                        {
                            //Occlusion detection
                            if (pixels_ptr->x < maxInLine || (pixels_ptr->x == maxInLine && (points_ptr->z - maxZ) > occZTh))
                            {
                                *points_ptr = { 0, 0, 0 };
                                occDilationLeft = occDilationSz;
                            }
                            else
                            {
                                maxInLine = pixels_ptr->x;
                                maxZ = points_ptr->z;
                                if (occDilationLeft > 0)
                                {
                                    *points_ptr = { 0, 0, 0 };
                                    occDilationLeft--;
                                }
                            }
                        }
                        ++points_ptr;
                        ++uv_map_ptr;
                        ++pixels_ptr;
                    }
                }
            }
        }
        else if (_occlusion_scanning == vertical)
        {
            depth_planes[0] = (byte*)alloc.allocate(depth.get_bytes_per_pixel() * frame_size);
            int bpp = depth.get_bytes_per_pixel();
            rotate_image_counterclockwise<2>(depth_planes, (const byte*)(depth.get_data()), points_width, points_height);

            // scan depth frame after clockwise rotation: check if there is a significant jump between adjacen pixels in Z-axis (depth), it means there could be occlusion.
            // scan over a small window so that points depth is the same
            // save suspected points and run occlusion-invalidation vertical scan only on them
            // after rotation : height = points_width , width = points_height

            auto rotated_depth_width = _depth_intrinsics->height;
            auto rotated_depth_height = _depth_intrinsics->width;

            for (int i = 0; i < rotated_depth_height; i++)
            {
                for (int j = 0; j < rotated_depth_width - VERTICAL_SCAN_WINDOW_SIZE; j = j + VERTICAL_SCAN_WINDOW_SIZE)
                {
                    // before rotation: occlusion detected in the positive direction of Y
                    // after counterclockwise rotation : scan from right to left (positive direction of X) to detect occlusion
                    // compare depth each pixel only with the pixel on its right (i,j+1)
                    auto index = i * rotated_depth_width + j;
                    auto uv_i = j;
                    auto uv_j = rotated_depth_height - i;
                    auto uv_index = uv_i * rotated_depth_height + uv_j; // 90 degrees rotation transform from rotated depth
                    auto index_right = index + 1;
                    float diff_right = abs((depth_planes[0])[index] - (depth_planes[0])[index_right]);

                    if ((diff_right > DEPTH_OCCLUSION_THRESHOLD))
                    {
                        pixels_ptr = pix_coord.data() + uv_index;
                        points_ptr = points + uv_index;
                        uv_map_ptr = uv_map + uv_index;
                        maxInLine = -1;
                        maxZ = 0;
                        int occDilationUp = 0;

                        for (size_t y = 0; y <= VERTICAL_SCAN_WINDOW_SIZE; ++y)
                        {
                            if (((pixels_ptr + y * points_width)->y < maxInLine))
                            {
                                *(points_ptr + y * points_width) = { 0.f, 0.f, 0.f };
                            }
                            else
                            {
                                maxInLine = (pixels_ptr + y * points_width)->y;
                            }

                        }
                    }
                }
            }
        }
    }
    // Prepare texture map without occlusion that for every texture coordinate there no more than one depth point that is mapped to it
    // i.e. for every (u,v) map coordinate we select the depth point with minimum Z. all other points that are mapped to this texel will be invalidated
    // Algo input data:
    // Vector of 3D [xyz] coordinates of depth_width*depth_height size
    // Vector of 2D [i,j] coordinates where the val[i,j] stores the texture coordinate (s,t) for the corresponding (i,j) pixel in depth frame
    // Algo intermediate data:
    // Vector of depth values (floats) in size of the mapped texture (different from depth width*height) where
    // each (i,j) cell holds the minimal Z among all the depth pixels that are mapped to the specific texel
    void occlusion_filter::comprehensive_invalidation(float3* points, float2* uv_map, const std::vector<float2> & pix_coord) const
    {
        auto depth_points = points;
        auto mapped_pix = pix_coord.data();
        size_t mapped_tex_width = _texels_intrinsics->width;
        size_t mapped_tex_height = _texels_intrinsics->height;
        size_t points_width = _depth_intrinsics->width;
        size_t points_height = _depth_intrinsics->height;

        static const float z_threshold = 0.05f; // Compensate for temporal noise when comparing Z values

        // Clear previous data
        memset((void*)(_texels_depth.data()), 0, _texels_depth.size() * sizeof(float));

        // Pass1 -generate texels mapping with minimal depth for each texel involved
        for (size_t i = 0; i < points_height; i++)
        {
            for (size_t j = 0; j < points_width; j++)
            {
                if ((depth_points->z > 0.0001f) &&
                    (mapped_pix->x > 0.f) && (mapped_pix->x < mapped_tex_width) &&
                    (mapped_pix->y > 0.f) && (mapped_pix->y < mapped_tex_height))
                {
                    size_t texel_index = (size_t)(mapped_pix->y)*mapped_tex_width + (size_t)(mapped_pix->x);

                    if ((_texels_depth[texel_index] < 0.0001f) || ((_texels_depth[texel_index] + z_threshold) > depth_points->z))
                    {
                        _texels_depth[texel_index] = depth_points->z;
                    }
                }

                ++depth_points;
                ++mapped_pix;
            }
        }

        mapped_pix = pix_coord.data();
        depth_points = points;
        auto uv_ptr = uv_map;

        // Pass2 -invalidate depth texels with occlusion traits
        for (size_t i = 0; i < points_height; i++)
        {
            for (size_t j = 0; j < points_width; j++)
            {
                if ((depth_points->z > 0.0001f) &&
                    (mapped_pix->x > 0.f) && (mapped_pix->x < mapped_tex_width) &&
                    (mapped_pix->y > 0.f) && (mapped_pix->y < mapped_tex_height))
                {
                    size_t texel_index = (size_t)(mapped_pix->y)*mapped_tex_width + (size_t)(mapped_pix->x);

                    if ((_texels_depth[texel_index] > 0.0001f) && ((_texels_depth[texel_index] + z_threshold) < depth_points->z))
                    {
                        *uv_ptr = { 0.f, 0.f };
                    }
                }

                ++depth_points;
                ++mapped_pix;
                ++uv_ptr;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: outline.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:55:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _OUTLINE_HXX
#define _OUTLINE_HXX

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif

#ifndef _SV_MENU_HXX //autogen
#include <vcl/menu.hxx>
#endif

#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif

#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif

#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif

#ifndef _FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif

#include "swtypes.hxx"      //fuer MAXLEVEL
#ifndef _NUMPREVW_HXX
#include <numprevw.hxx>
#endif
#ifndef _NUMBERINGTYPELISTBOX_HXX
#include <numberingtypelistbox.hxx>
#endif

class SwWrtShell;
class SwTxtFmtColl;
class SwNumRule;
class SwChapterNumRules;

/* -----------------07.07.98 13:38-------------------
 *
 * --------------------------------------------------*/
class SwOutlineTabDialog : public SfxTabDialog
{
    static     USHORT    nNumLevel;

    String              aNullStr;
    String              aCollNames[MAXLEVEL];
    PopupMenu           aFormMenu;

    SwWrtShell&         rWrtSh;
    SwNumRule*          pNumRule;
    SwChapterNumRules*  pChapterNumRules;

    BOOL                bModified : 1;

    protected:
    DECL_LINK( CancelHdl, Button * );
    DECL_LINK( FormHdl, Button * );
    DECL_LINK( MenuSelectHdl, Menu * );

        virtual void    PageCreated(USHORT nPageId, SfxTabPage& rPage);
        virtual short   Ok();

    public:
        SwOutlineTabDialog(Window* pParent,
                    const SfxItemSet* pSwItemSet,
                    SwWrtShell &);
        ~SwOutlineTabDialog();

    SwNumRule*          GetNumRule() {return pNumRule;}
    USHORT              GetLevel(const String &rFmtName) const;
    String*             GetCollNames() {return aCollNames;}

    static USHORT       GetActNumLevel() {return nNumLevel;}
    static void         SetActNumLevel(USHORT nSet) {nNumLevel = nSet;}
};
/* -----------------07.07.98 13:47-------------------
 *
 * --------------------------------------------------*/
class SwOutlineSettingsTabPage : public SfxTabPage
{
    ListBox         aLevelLB;
    FixedLine       aLevelFL;

    FixedText       aCollLbl;
    ListBox         aCollBox;
    FixedText       aNumberLbl;
    SwNumberingTypeListBox  aNumberBox;
    FixedText       aCharFmtFT;
    ListBox         aCharFmtLB;
    FixedText       aAllLevelFT;
    NumericField    aAllLevelNF;
    FixedText       aDelim;
    FixedText       aPrefixFT;
    Edit            aPrefixED;
    FixedText       aSuffixFT;
    Edit            aSuffixED;
    FixedText       aStartLbl;
    NumericField    aStartEdit;
    FixedLine        aNumberFL;
    NumberingPreview aPreviewWIN;

    String              aNoFmtName;
    String              aSaveCollNames[MAXLEVEL];
    SwWrtShell*         pSh;
    SwNumRule*          pNumRule;
    String*             pCollNames;
    USHORT              nActLevel;

    DECL_LINK( LevelHdl, ListBox * );
    DECL_LINK( ToggleComplete, NumericField * );
    DECL_LINK( CollSelect, ListBox * );
    DECL_LINK( CollSelectGetFocus, ListBox * );
    DECL_LINK( NumberSelect, SwNumberingTypeListBox * );
    DECL_LINK( DelimModify, Edit * );
    DECL_LINK( StartModified, NumericField * );
    DECL_LINK( CharFmtHdl, ListBox * );

    void    Update();

    void    SetModified(){aPreviewWIN.Invalidate();}
    void    CheckForStartValue_Impl(sal_uInt16 nNumberingType);

public:
    SwOutlineSettingsTabPage(Window* pParent, const SfxItemSet& rSet);
    ~SwOutlineSettingsTabPage();

    void SetWrtShell(SwWrtShell* pShell);

    virtual void        ActivatePage(const SfxItemSet& rSet);
    virtual int         DeactivatePage(SfxItemSet *pSet);
    virtual BOOL        FillItemSet( SfxItemSet& rSet );
    virtual void        Reset( const SfxItemSet& rSet );
    static SfxTabPage*  Create( Window* pParent,
                                const SfxItemSet& rAttrSet);
};
#endif
<commit_msg>INTEGRATION: CWS writercorehandoff (1.5.156); FILE MERGED 2005/09/13 17:38:36 tra 1.5.156.2: RESYNC: (1.5-1.6); FILE MERGED 2005/06/07 14:15:46 fme 1.5.156.1: #i50348# General cleanup - removed unused header files, functions, members, declarations etc.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: outline.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-14 17:44:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _OUTLINE_HXX
#define _OUTLINE_HXX

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif

#ifndef _SV_MENU_HXX //autogen
#include <vcl/menu.hxx>
#endif

#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif

#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif

#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif

#ifndef _FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif

#include "swtypes.hxx"      //fuer MAXLEVEL
#ifndef _NUMPREVW_HXX
#include <numprevw.hxx>
#endif
#ifndef _NUMBERINGTYPELISTBOX_HXX
#include <numberingtypelistbox.hxx>
#endif

class SwWrtShell;
class SwNumRule;
class SwChapterNumRules;

/* -----------------07.07.98 13:38-------------------
 *
 * --------------------------------------------------*/
class SwOutlineTabDialog : public SfxTabDialog
{
    static     USHORT    nNumLevel;

    String              aNullStr;
    String              aCollNames[MAXLEVEL];
    PopupMenu           aFormMenu;

    SwWrtShell&         rWrtSh;
    SwNumRule*          pNumRule;
    SwChapterNumRules*  pChapterNumRules;

    BOOL                bModified : 1;

    protected:
    DECL_LINK( CancelHdl, Button * );
    DECL_LINK( FormHdl, Button * );
    DECL_LINK( MenuSelectHdl, Menu * );

        virtual void    PageCreated(USHORT nPageId, SfxTabPage& rPage);
        virtual short   Ok();

    public:
        SwOutlineTabDialog(Window* pParent,
                    const SfxItemSet* pSwItemSet,
                    SwWrtShell &);
        ~SwOutlineTabDialog();

    SwNumRule*          GetNumRule() {return pNumRule;}
    USHORT              GetLevel(const String &rFmtName) const;
    String*             GetCollNames() {return aCollNames;}

    static USHORT       GetActNumLevel() {return nNumLevel;}
    static void         SetActNumLevel(USHORT nSet) {nNumLevel = nSet;}
};
/* -----------------07.07.98 13:47-------------------
 *
 * --------------------------------------------------*/
class SwOutlineSettingsTabPage : public SfxTabPage
{
    ListBox         aLevelLB;
    FixedLine       aLevelFL;

    FixedText       aCollLbl;
    ListBox         aCollBox;
    FixedText       aNumberLbl;
    SwNumberingTypeListBox  aNumberBox;
    FixedText       aCharFmtFT;
    ListBox         aCharFmtLB;
    FixedText       aAllLevelFT;
    NumericField    aAllLevelNF;
    FixedText       aDelim;
    FixedText       aPrefixFT;
    Edit            aPrefixED;
    FixedText       aSuffixFT;
    Edit            aSuffixED;
    FixedText       aStartLbl;
    NumericField    aStartEdit;
    FixedLine        aNumberFL;
    NumberingPreview aPreviewWIN;

    String              aNoFmtName;
    String              aSaveCollNames[MAXLEVEL];
    SwWrtShell*         pSh;
    SwNumRule*          pNumRule;
    String*             pCollNames;
    USHORT              nActLevel;

    DECL_LINK( LevelHdl, ListBox * );
    DECL_LINK( ToggleComplete, NumericField * );
    DECL_LINK( CollSelect, ListBox * );
    DECL_LINK( CollSelectGetFocus, ListBox * );
    DECL_LINK( NumberSelect, SwNumberingTypeListBox * );
    DECL_LINK( DelimModify, Edit * );
    DECL_LINK( StartModified, NumericField * );
    DECL_LINK( CharFmtHdl, ListBox * );

    void    Update();

    void    SetModified(){aPreviewWIN.Invalidate();}
    void    CheckForStartValue_Impl(sal_uInt16 nNumberingType);

public:
    SwOutlineSettingsTabPage(Window* pParent, const SfxItemSet& rSet);
    ~SwOutlineSettingsTabPage();

    void SetWrtShell(SwWrtShell* pShell);

    virtual void        ActivatePage(const SfxItemSet& rSet);
    virtual int         DeactivatePage(SfxItemSet *pSet);
    virtual BOOL        FillItemSet( SfxItemSet& rSet );
    virtual void        Reset( const SfxItemSet& rSet );
    static SfxTabPage*  Create( Window* pParent,
                                const SfxItemSet& rAttrSet);
};
#endif
<|endoftext|>


<commit_before>/**
 * @author : xiaozhuai
 * @date   : 17/1/3
 */

#include "UrlEncode.h"

namespace CXXUrl {

unsigned char UrlEncode::ToHex(unsigned char x) {
    return  x > 9 ? x + 55 : x + 48;
}

unsigned char UrlEncode::FromHex(unsigned char x) {
    unsigned char y;
    if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
    else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
    else if (x >= '0' && x <= '9') y = x - '0';
    else assert(0);
    return y;
}

std::string UrlEncode::encode(const std::string &str) {
    std::string strTemp;
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (isalnum((unsigned char)str[i]) ||
            (str[i] == '-') ||
            (str[i] == '_') ||
            (str[i] == '.') ||
            (str[i] == '~'))
            strTemp += str[i];
        else if (str[i] == ' ')
            strTemp += "+";
        else
        {
            strTemp += '%';
            strTemp += ToHex((unsigned char)(str[i] >> 4));
            strTemp += ToHex((unsigned char)(str[i] % 16));
        }
    }
    return strTemp;
}

std::string UrlEncode::decode(const std::string &str) {
    std::string strTemp;
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (str[i] == '+') strTemp += ' ';
        else if (str[i] == '%')
        {
            assert(i + 2 < length);
            unsigned char high = FromHex((unsigned char)str[++i]);
            unsigned char low = FromHex((unsigned char)str[++i]);
            strTemp += high*16 + low;
        }
        else strTemp += str[i];
    }
    return strTemp;
}

}<commit_msg>fix a bug in urlencode<commit_after>/**
 * @author : xiaozhuai
 * @date   : 17/1/3
 */

#include "UrlEncode.h"

namespace CXXUrl {

unsigned char UrlEncode::ToHex(unsigned char x) {
    return  x > 9 ? x + 55 : x + 48;
}

unsigned char UrlEncode::FromHex(unsigned char x) {
    unsigned char y;
    if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
    else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
    else if (x >= '0' && x <= '9') y = x - '0';
    else assert(0);
    return y;
}

std::string UrlEncode::encode(const std::string &str) {
    std::string strTemp;
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (isalnum((unsigned char)str[i]) ||
            (str[i] == '-') ||
            (str[i] == '_') ||
            (str[i] == '.') ||
            (str[i] == '~'))
            strTemp += str[i];
        else if (str[i] == ' ')
            strTemp += "+";
        else
        {
            strTemp += '%';
            strTemp += ToHex((unsigned char)str[i] >> 4);
            strTemp += ToHex((unsigned char)str[i] % 16);
        }
    }
    return strTemp;
}

std::string UrlEncode::decode(const std::string &str) {
    std::string strTemp;
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (str[i] == '+') strTemp += ' ';
        else if (str[i] == '%')
        {
            assert(i + 2 < length);
            unsigned char high = FromHex((unsigned char)str[++i]);
            unsigned char low = FromHex((unsigned char)str[++i]);
            strTemp += high*16 + low;
        }
        else strTemp += str[i];
    }
    return strTemp;
}

}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: PositionAndSizeHelper.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2007-05-22 18:08:29 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "PositionAndSizeHelper.hxx"
#include "macros.hxx"
#include "ChartModelHelper.hxx"
#include "ControllerLockGuard.hxx"

#ifndef _COM_SUN_STAR_CHART2_LEGENDPOSITION_HPP_
#include <com/sun/star/chart2/LegendPosition.hpp>
#endif

#ifndef _COM_SUN_STAR_CHART2_RELATIVEPOSITION_HPP_
#include <com/sun/star/chart2/RelativePosition.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART2_RELATIVESIZE_HPP_
#include <com/sun/star/chart2/RelativeSize.hpp>
#endif
#include "chartview/ExplicitValueProvider.hxx"

// header for class Rectangle
#ifndef _SV_GEN_HXX
#include <tools/gen.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

bool PositionAndSizeHelper::moveObject( ObjectType eObjectType
                , const uno::Reference< beans::XPropertySet >& xObjectProp
                , const awt::Rectangle& rNewPositionAndSize
                , const awt::Rectangle& rPageRectangle
                )
{
    if(!xObjectProp.is())
        return false;
    Rectangle aObjectRect( Point(rNewPositionAndSize.X,rNewPositionAndSize.Y), Size(rNewPositionAndSize.Width,rNewPositionAndSize.Height) );
    Rectangle aPageRect( Point(rPageRectangle.X,rPageRectangle.Y), Size(rPageRectangle.Width,rPageRectangle.Height) );

    if( OBJECTTYPE_TITLE==eObjectType )
    {
        //@todo decide wether x is primary or secondary
        chart2::RelativePosition aRelativePosition;
        aRelativePosition.Anchor = drawing::Alignment_TOP;
        //the anchor point at the title object is top/middle
        Point aPos = aObjectRect.TopLeft();
        aRelativePosition.Primary = (double(aPos.X())+double(aObjectRect.getWidth())/2.0)/double(aPageRect.getWidth());
        aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );
    }
    else if(OBJECTTYPE_LEGEND==eObjectType)
    {
        LegendPosition ePos = LegendPosition_LINE_END;
        xObjectProp->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos;
        chart2::RelativePosition aRelativePosition;
        Point aAnchor = aObjectRect.TopLeft();

        switch( ePos )
        {
            case LegendPosition_LINE_START:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_LEFT;
                    aAnchor = aObjectRect.LeftCenter();
                }
                break;
            case LegendPosition_LINE_END:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_RIGHT;
                    aAnchor = aObjectRect.RightCenter();
                }
                break;
            case LegendPosition_PAGE_START:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_TOP;
                    aAnchor = aObjectRect.TopCenter();
                }
                break;
            case LegendPosition_PAGE_END:
                //@todo language dependent positions ...
                {
                    aRelativePosition.Anchor = drawing::Alignment_BOTTOM;
                    aAnchor = aObjectRect.BottomCenter();
                }
                break;
            case LegendPosition_CUSTOM:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
                }
                break;
            case LegendPosition_MAKE_FIXED_SIZE:
                OSL_ASSERT( false );
                break;
        }
        aRelativePosition.Primary =
            static_cast< double >( aAnchor.X()) /
            static_cast< double >( aPageRect.getWidth() );
        aRelativePosition.Secondary =
            static_cast< double >( aAnchor.Y()) /
            static_cast< double >( aPageRect.getHeight());

        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );
    }
    else if(OBJECTTYPE_DIAGRAM==eObjectType || OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType)
    {
        //@todo decide wether x is primary or secondary

        //xChartView

        //set position:
        chart2::RelativePosition aRelativePosition;
        aRelativePosition.Anchor = drawing::Alignment_CENTER;

        Point aPos = aObjectRect.Center();
        aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getWidth());
        aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );

        //set size:
        RelativeSize aRelativeSize;
        //the anchor points for the diagram are in the middle of the diagram
        //and in the middle of the page
        aRelativeSize.Primary = double(aObjectRect.getWidth())/double(aPageRect.getWidth());
        aRelativeSize.Secondary = double(aObjectRect.getHeight())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aRelativeSize) );
    }
    else
        return false;
    return true;
}

bool PositionAndSizeHelper::moveObject( const rtl::OUString& rObjectCID
                , const uno::Reference< frame::XModel >& xChartModel
                , const awt::Rectangle& rNewPositionAndSize
                , const awt::Rectangle& rPageRectangle
                , uno::Reference< uno::XInterface > xChartView
                )
{
    ControllerLockGuard aLockedControllers( xChartModel );

    awt::Rectangle aNewPositionAndSize( rNewPositionAndSize );

    uno::Reference< beans::XPropertySet > xObjectProp = ObjectIdentifier::getObjectPropertySet( rObjectCID, xChartModel );
    ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
    if(OBJECTTYPE_DIAGRAM==eObjectType || OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType)
    {
        xObjectProp = uno::Reference< beans::XPropertySet >( ObjectIdentifier::getDiagramForCID( rObjectCID, xChartModel ), uno::UNO_QUERY );
        if(!xObjectProp.is())
            return false;

        //add axis title sizes to the diagram size
        aNewPositionAndSize = ExplicitValueProvider::calculateDiagramPositionAndSizeInclusiveTitle(
            xChartModel, xChartView, rNewPositionAndSize );
    }
    return moveObject( eObjectType, xObjectProp, aNewPositionAndSize, rPageRectangle );
}

//.............................................................................
} //namespace chart
//.............................................................................
<commit_msg>INTEGRATION: CWS chart17 (1.5.66); FILE MERGED 2007/10/12 12:35:08 bm 1.5.66.1: #i7998# equations for regression curves<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: PositionAndSizeHelper.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-23 11:55:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "PositionAndSizeHelper.hxx"
#include "macros.hxx"
#include "ChartModelHelper.hxx"
#include "ControllerLockGuard.hxx"

#ifndef _COM_SUN_STAR_CHART2_LEGENDPOSITION_HPP_
#include <com/sun/star/chart2/LegendPosition.hpp>
#endif

#ifndef _COM_SUN_STAR_CHART2_RELATIVEPOSITION_HPP_
#include <com/sun/star/chart2/RelativePosition.hpp>
#endif
#ifndef _COM_SUN_STAR_CHART2_RELATIVESIZE_HPP_
#include <com/sun/star/chart2/RelativeSize.hpp>
#endif
#include "chartview/ExplicitValueProvider.hxx"

// header for class Rectangle
#ifndef _SV_GEN_HXX
#include <tools/gen.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

bool PositionAndSizeHelper::moveObject( ObjectType eObjectType
                , const uno::Reference< beans::XPropertySet >& xObjectProp
                , const awt::Rectangle& rNewPositionAndSize
                , const awt::Rectangle& rPageRectangle
                )
{
    if(!xObjectProp.is())
        return false;
    Rectangle aObjectRect( Point(rNewPositionAndSize.X,rNewPositionAndSize.Y), Size(rNewPositionAndSize.Width,rNewPositionAndSize.Height) );
    Rectangle aPageRect( Point(rPageRectangle.X,rPageRectangle.Y), Size(rPageRectangle.Width,rPageRectangle.Height) );

    if( OBJECTTYPE_TITLE==eObjectType )
    {
        //@todo decide wether x is primary or secondary
        chart2::RelativePosition aRelativePosition;
        aRelativePosition.Anchor = drawing::Alignment_TOP;
        //the anchor point at the title object is top/middle
        Point aPos = aObjectRect.TopLeft();
        aRelativePosition.Primary = (double(aPos.X())+double(aObjectRect.getWidth())/2.0)/double(aPageRect.getWidth());
        aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );
    }
    else if( OBJECTTYPE_DATA_CURVE_EQUATION==eObjectType )
    {
        //@todo decide wether x is primary or secondary
        chart2::RelativePosition aRelativePosition;
        aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
        //the anchor point at the title object is top/middle
        Point aPos = aObjectRect.TopLeft();
        aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getWidth());
        aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );
    }
    else if(OBJECTTYPE_LEGEND==eObjectType)
    {
        LegendPosition ePos = LegendPosition_LINE_END;
        xObjectProp->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos;
        chart2::RelativePosition aRelativePosition;
        Point aAnchor = aObjectRect.TopLeft();

        switch( ePos )
        {
            case LegendPosition_LINE_START:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_LEFT;
                    aAnchor = aObjectRect.LeftCenter();
                }
                break;
            case LegendPosition_LINE_END:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_RIGHT;
                    aAnchor = aObjectRect.RightCenter();
                }
                break;
            case LegendPosition_PAGE_START:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_TOP;
                    aAnchor = aObjectRect.TopCenter();
                }
                break;
            case LegendPosition_PAGE_END:
                //@todo language dependent positions ...
                {
                    aRelativePosition.Anchor = drawing::Alignment_BOTTOM;
                    aAnchor = aObjectRect.BottomCenter();
                }
                break;
            case LegendPosition_CUSTOM:
                {
                    //@todo language dependent positions ...
                    aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
                }
                break;
            case LegendPosition_MAKE_FIXED_SIZE:
                OSL_ASSERT( false );
                break;
        }
        aRelativePosition.Primary =
            static_cast< double >( aAnchor.X()) /
            static_cast< double >( aPageRect.getWidth() );
        aRelativePosition.Secondary =
            static_cast< double >( aAnchor.Y()) /
            static_cast< double >( aPageRect.getHeight());

        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );
    }
    else if(OBJECTTYPE_DIAGRAM==eObjectType || OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType)
    {
        //@todo decide wether x is primary or secondary

        //xChartView

        //set position:
        chart2::RelativePosition aRelativePosition;
        aRelativePosition.Anchor = drawing::Alignment_CENTER;

        Point aPos = aObjectRect.Center();
        aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getWidth());
        aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );

        //set size:
        RelativeSize aRelativeSize;
        //the anchor points for the diagram are in the middle of the diagram
        //and in the middle of the page
        aRelativeSize.Primary = double(aObjectRect.getWidth())/double(aPageRect.getWidth());
        aRelativeSize.Secondary = double(aObjectRect.getHeight())/double(aPageRect.getHeight());
        xObjectProp->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aRelativeSize) );
    }
    else
        return false;
    return true;
}

bool PositionAndSizeHelper::moveObject( const rtl::OUString& rObjectCID
                , const uno::Reference< frame::XModel >& xChartModel
                , const awt::Rectangle& rNewPositionAndSize
                , const awt::Rectangle& rPageRectangle
                , uno::Reference< uno::XInterface > xChartView
                )
{
    ControllerLockGuard aLockedControllers( xChartModel );

    awt::Rectangle aNewPositionAndSize( rNewPositionAndSize );

    uno::Reference< beans::XPropertySet > xObjectProp = ObjectIdentifier::getObjectPropertySet( rObjectCID, xChartModel );
    ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
    if(OBJECTTYPE_DIAGRAM==eObjectType || OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType)
    {
        xObjectProp = uno::Reference< beans::XPropertySet >( ObjectIdentifier::getDiagramForCID( rObjectCID, xChartModel ), uno::UNO_QUERY );
        if(!xObjectProp.is())
            return false;

        //add axis title sizes to the diagram size
        aNewPositionAndSize = ExplicitValueProvider::calculateDiagramPositionAndSizeInclusiveTitle(
            xChartModel, xChartView, rNewPositionAndSize );
    }
    return moveObject( eObjectType, xObjectProp, aNewPositionAndSize, rPageRectangle );
}

//.............................................................................
} //namespace chart
//.............................................................................
<|endoftext|>


<commit_before>// -*- C++ -*-

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

#include "ChebyshevDifferentiate.hpp"

namespace CS
{
///
/// as \f$T_n(\cos\theta)=\cos n\theta\f$, then
///
/// \f[
/// 	\frac{T'_{n+1}(x)}{n+1}-\frac{T'_{n-1}(x)}{n-1}=\frac2{c_n}T_n(x)
/// 	\quad(n>=0)
/// \f]
///
/// where \f$c_0=2,\,c_n=1\,(n\le1)\f$ and \f$T'_0=T'_{-1}=0\f$, implies if
///
/// \f[
/// 	\frac d{dx}\sum^N_{n=0}a_nT_n(x)=\sum^N_{n=0}b_nT_n(x)
/// \f]
///
/// then
///
/// \f{align*}{
/// 	\sum^N_{n=0}a_nT'_n(x)
/// 		&=\sum^N_{n=0}c_nb_n\left[T_n(x)
/// 		\frac{T'_{n+1}(x)}{n+1}-\frac{T'_{n-1}(x)}{n-1}\right]\\
/// 		&=\sum^{N+1}_{n=0}[c_{n-1}b_{n-1}-b_{n+1}]T'_n(x)/n
/// \f}
///
/// equating \f$T'_n(x)\f$ for \f$n=1,\dots,N+1\f$
/// we derive recurrent equations for Chebyshev polynomials derivatives
///
/// \f{alignat*}{{2}
///        c_{n-1}b_{n-1}-b_{n+1} &= 2na_n &&\quad(1\le n\le N)\\
///                           b_n &=0      &&\quad(n\ge N)
/// \f}
///
/// if approximate solution is at each collocation point \f$(x_j)\f$
///
/// \f[
///     u(x,t) = \sum_{k=1}^{N+1}a_{k}T_{k-1}(x)
/// \f]
///
/// then, in particular, spatial derivatives can be defined directly in terms
/// of undifferentiated Chebyshev polynomials, i.e.
///
/// \f[
///     \frac{\partial{u}}{\partial{x}} = \sum_{k=1}^{N}a_{k}^{(1)}T_{k-1}(x)
/// \f]
///
/// and
///
/// \f[
///     \frac{\partial^2{u}}{\partial{x^2}} = \sum_{k=1}^{N-1}a_{k}^{(2)}T_{k-1}(x)
/// \f]
///
/// Specifically, the following recurrence relations permit all
/// the \f$a_k^{(1)}, a_k^{(2)}\f$ coefficients to be obtained in \f$O(N)\f$ operations
///
/// \f{alignat*}{{2}
///     a_k^{(1)} &= a_{k+2}^{(1)} + 2k a_{k+1}       &&\quad(2\le k\le N)\\
///     a_k^{(2)} &= a_{k+2}^{(2)} + 2k a_{k+1}^{(1)} &&\quad(2\le k\le N-1)\\
/// \f}
///
/// and \f$\qquad a_1^{(1)} = 0.5 a_3^{(1)} + 2k a_2, \quad a_1^{(2)} = 0.5 a_3^{(2)} + 2k a_2^{(1)}\f$
///
/// and \f$\qquad a_{N+1}^{(1)} = a_{N+2}^{(1)} = 0, \quad a_{N}^{(2)} = a_{N+1}^{(2)} = 0\f$

void spectral_differentiate(size_t n,
                            Eigen::Ref<RowVectorXd> in,
                            Eigen::Ref<RowVectorXd> out,
                            double span)
{
    double temp1 = in[n-1],
           temp2 = in[n-2];

    out[n-1] = 2.0 *  n    * in[n] * span;
    out[n-2] = 2.0 * (n-1) * temp1 * span;
    for (size_t j = n-3; j>0; j--) {
        temp1  = in[j];
        out[j] = out[j+2] + 2.0 * (j+1) * temp2 * span;
        temp2  = temp1;
    }
    out[0] = 0.5 * out[2] + temp2 * span;
    out[n] = 0.0;
}

/// as \f$T_n(\cos\theta)=\cos n\theta\f$, then
///
/// \f[
/// 	\frac{T'_{n+1}(x)}{n+1}-\frac{T'_{n-1}(x)}{n-1}=\frac2{c_n}T_n(x)
/// 	\quad(n>=0)
/// \f]
///
///  From boundary conditions and Chebyshev polynomials traits \f$T_n(\pm1)=(\pm1)^n\f$ we derive
/// \f{alignat}{{3}
/// 	\sum^N_{p=0 \quad p\equiv0\pmod2} a_{mp} &=
/// 	\sum^N_{p=1 \quad p\equiv1\pmod2} a_{mp} &= 0 &&
/// 	\qquad 0\le m\le M\\
/// 	\sum^N_{q=0 \quad q\equiv0\pmod2} a_{qn} &=
/// 	\sum^N_{q=1 \quad q\equiv1\pmod2} a_{qn} &= 0 &&
/// 	\qquad 0\le n\le N
/// \f}
void homogeneous_boundary(size_t m, size_t n,
                          Eigen::Ref<RowMatrixXd> in,
                          Eigen::Ref<RowMatrixXd> out)
{
    if (out != in) {
        out = in;
    }

    double evens, odds;
    for (size_t i=0; i<=m-2; ++i) {
        evens = odds = 0.0;
        for (size_t j=1; j<n-2; j+=2) {
            odds  -= out(i, j);
            evens -= out(i, j+1);
        }
        out(i, n-1) = odds;
        out(i, n)   = evens - out(i, 0);
    }

    for (size_t i=0; i<=n-2; ++i) {
        evens = odds = 0.0;
        for (size_t j=1; j<m-2; j+=2) {
            odds  -= out(j,   i);
            evens -= out(j+1, i);
        }
        out(n-1, i) = odds;
        out(n,   i) = evens - out(0, i);
    }

    evens = odds = 0.0;
    for (size_t j=1; j<n-2; j+=2) {
        odds  -= out(n-1, j);
        evens -= out(n-1, j+1);
    }
    out(n-1, n-1) = odds;
    out(n-1, n)   = evens - out(n-1, 0);

    evens = odds = 0.0;
    for (size_t i=0; i<m; i+=2) {
        odds  -= out(i, n-1);
        evens -= out(i, n);
    }
    out(n, n-1) = odds;
    out(n, n)   = evens;
}

void second_derivative(size_t m, size_t n,
                       Eigen::Ref<RowMatrixXd> in,
                       Eigen::Ref<RowMatrixXd> out)
{
    homogeneous_boundary(m, n, in, out);
    for (size_t i = 0; i <= m; ++i) {
        spectral_differentiate(n, out.row(i), out.row(i));
        spectral_differentiate(n, out.row(i), out.row(i));
    }
}

} // namespace CS
<commit_msg>one more fix in `homogeneous_boundary`<commit_after>// -*- C++ -*-

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

#include "ChebyshevDifferentiate.hpp"

namespace CS
{
///
/// as \f$T_n(\cos\theta)=\cos n\theta\f$, then
///
/// \f[
/// 	\frac{T'_{n+1}(x)}{n+1}-\frac{T'_{n-1}(x)}{n-1}=\frac2{c_n}T_n(x)
/// 	\quad(n>=0)
/// \f]
///
/// where \f$c_0=2,\,c_n=1\,(n\le1)\f$ and \f$T'_0=T'_{-1}=0\f$, implies if
///
/// \f[
/// 	\frac d{dx}\sum^N_{n=0}a_nT_n(x)=\sum^N_{n=0}b_nT_n(x)
/// \f]
///
/// then
///
/// \f{align*}{
/// 	\sum^N_{n=0}a_nT'_n(x)
/// 		&=\sum^N_{n=0}c_nb_n\left[T_n(x)
/// 		\frac{T'_{n+1}(x)}{n+1}-\frac{T'_{n-1}(x)}{n-1}\right]\\
/// 		&=\sum^{N+1}_{n=0}[c_{n-1}b_{n-1}-b_{n+1}]T'_n(x)/n
/// \f}
///
/// equating \f$T'_n(x)\f$ for \f$n=1,\dots,N+1\f$
/// we derive recurrent equations for Chebyshev polynomials derivatives
///
/// \f{alignat*}{{2}
///        c_{n-1}b_{n-1}-b_{n+1} &= 2na_n &&\quad(1\le n\le N)\\
///                           b_n &=0      &&\quad(n\ge N)
/// \f}
///
/// if approximate solution is at each collocation point \f$(x_j)\f$
///
/// \f[
///     u(x,t) = \sum_{k=1}^{N+1}a_{k}T_{k-1}(x)
/// \f]
///
/// then, in particular, spatial derivatives can be defined directly in terms
/// of undifferentiated Chebyshev polynomials, i.e.
///
/// \f[
///     \frac{\partial{u}}{\partial{x}} = \sum_{k=1}^{N}a_{k}^{(1)}T_{k-1}(x)
/// \f]
///
/// and
///
/// \f[
///     \frac{\partial^2{u}}{\partial{x^2}} = \sum_{k=1}^{N-1}a_{k}^{(2)}T_{k-1}(x)
/// \f]
///
/// Specifically, the following recurrence relations permit all
/// the \f$a_k^{(1)}, a_k^{(2)}\f$ coefficients to be obtained in \f$O(N)\f$ operations
///
/// \f{alignat*}{{2}
///     a_k^{(1)} &= a_{k+2}^{(1)} + 2k a_{k+1}       &&\quad(2\le k\le N)\\
///     a_k^{(2)} &= a_{k+2}^{(2)} + 2k a_{k+1}^{(1)} &&\quad(2\le k\le N-1)\\
/// \f}
///
/// and \f$\qquad a_1^{(1)} = 0.5 a_3^{(1)} + 2k a_2, \quad a_1^{(2)} = 0.5 a_3^{(2)} + 2k a_2^{(1)}\f$
///
/// and \f$\qquad a_{N+1}^{(1)} = a_{N+2}^{(1)} = 0, \quad a_{N}^{(2)} = a_{N+1}^{(2)} = 0\f$

void spectral_differentiate(size_t n,
                            Eigen::Ref<RowVectorXd> in,
                            Eigen::Ref<RowVectorXd> out,
                            double span)
{
    double temp1 = in[n-1],
           temp2 = in[n-2];

    out[n-1] = 2.0 *  n    * in[n] * span;
    out[n-2] = 2.0 * (n-1) * temp1 * span;
    for (size_t j = n-3; j>0; j--) {
        temp1  = in[j];
        out[j] = out[j+2] + 2.0 * (j+1) * temp2 * span;
        temp2  = temp1;
    }
    out[0] = 0.5 * out[2] + temp2 * span;
    out[n] = 0.0;
}

/// as \f$T_n(\cos\theta)=\cos n\theta\f$, then
///
/// \f[
/// 	\frac{T'_{n+1}(x)}{n+1}-\frac{T'_{n-1}(x)}{n-1}=\frac2{c_n}T_n(x)
/// 	\quad(n>=0)
/// \f]
///
///  From boundary conditions and Chebyshev polynomials traits \f$T_n(\pm1)=(\pm1)^n\f$ we derive
/// \f{alignat}{{3}
/// 	\sum^N_{p=0 \quad p\equiv0\pmod2} a_{mp} &=
/// 	\sum^N_{p=1 \quad p\equiv1\pmod2} a_{mp} &= 0 &&
/// 	\qquad 0\le m\le M\\
/// 	\sum^N_{q=0 \quad q\equiv0\pmod2} a_{qn} &=
/// 	\sum^N_{q=1 \quad q\equiv1\pmod2} a_{qn} &= 0 &&
/// 	\qquad 0\le n\le N
/// \f}
void homogeneous_boundary(size_t m, size_t n,
                          Eigen::Ref<RowMatrixXd> in,
                          Eigen::Ref<RowMatrixXd> out)
{
    if (out != in) {
        out = in;
    }

    double evens, odds;
    for (size_t i=0; i<=m-2; ++i) {
        evens = odds = 0.0;
        for (size_t j=1; j<=n-2; j+=2) {
            odds  -= out(i, j);
            evens -= out(i, j+1);
        }
        out(i, n-1) = odds;
        out(i, n)   = evens - out(i, 0);
    }

    for (size_t i=0; i<=n-2; ++i) {
        evens = odds = 0.0;
        for (size_t j=1; j<m-2; j+=2) {
            odds  -= out(j,   i);
            evens -= out(j+1, i);
        }
        out(m-1, i) = odds;
        out(m,   i) = evens - out(0, i);
    }

    evens = odds = 0.0;
    for (size_t j=1; j<n-2; j+=2) {
        odds  -= out(m-1, j);
        evens -= out(m-1, j+1);
    }
    out(m-1, n-1) = odds;
    out(m-1, n)   = evens - out(n-1, 0);

    evens = odds = 0.0;
    for (size_t i=0; i<m; i+=2) {
        odds  -= out(i, n-1);
        evens -= out(i, n);
    }
    out(m, n-1) = odds;
    out(m, n)   = evens;
}

void second_derivative(size_t m, size_t n,
                       Eigen::Ref<RowMatrixXd> in,
                       Eigen::Ref<RowMatrixXd> out)
{
    homogeneous_boundary(m, n, in, out);
    for (size_t i = 0; i <= m; ++i) {
        spectral_differentiate(n, out.row(i), out.row(i));
        spectral_differentiate(n, out.row(i), out.row(i));
    }
}

} // namespace CS
<|endoftext|>