File:  [CENS] / python / pyGiNaC / wrappers4 / aux.cpp
Revision 1.8: download - view: text, annotated - select for diffs - revision graph
Mon Nov 26 22:37:44 2001 UTC (15 years, 11 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
See NEWS.txt (impl. matrix)

/*
  This file is part of the PyGiNaC package.
  http://cens.ioc.ee/projects/pyginac/

  $Revision: 1.8 $
  $Id: aux.cpp,v 1.8 2001-11-26 22:37:44 pearu Exp $
 
  Copyright 2001 Pearu Peterson all rights reserved,
  Pearu Peterson <pearu@cens.ioc.ee>
  Permission to use, modify, and distribute this software is given under the
  terms of the LGPL.  See http://www.fsf.org
 
  NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
*/

#ifndef PYGINAC_AUX_CPP
#define PYGINAC_AUX_CPP
/* prototypes */

PyObject* extract_archived(const GiNaC::ex &, signed);
void to_context_file(const GiNaC::ex &, PyObject*, const std::string &, unsigned);
std::string to_context_str(const GiNaC::ex &, const std::string &, unsigned);
unsigned get_precedence(const GiNaC::ex & expr);
std::string get_class_name(const GiNaC::ex & expr);
GiNaC::ex get_slice(const GiNaC::ex & e,PyObject *index);
void set_slice(GiNaC::ex & self,PyObject *index,const GiNaC::ex & other);

#else
#ifndef PYGINAC_AUX_CPP_1
#define PYGINAC_AUX_CPP_1
/* definitions */

ex_class.def(extract_archived, "extract_archived");
ex_class.def(to_context_str, "to_context_str");
ex_class.def(to_context_file, "to_context_file");
ex_class.def(get_precedence, "get_precedence");
ex_class.def(get_class_name, "get_class_name");
ex_class.def(get_slice, "get_slice");
ex_class.def(set_slice, "set_slice");

#else
/* implementation */

unsigned get_precedence(const GiNaC::ex & expr) {
  return GiNaC::ex_to<GiNaC::basic>(expr).precedence();
}

std::string get_class_name(const GiNaC::ex & expr) {
  return GiNaC::ex_to<GiNaC::basic>(expr).class_name();
}

void to_context(const GiNaC::ex & expr, std::ostream & os, const std::string & context, unsigned level) {
  if (context == "context")
    expr.print(GiNaC::print_context(os),level);
  else if (context == "latex")
    expr.print(GiNaC::print_latex(os),level);
  else if (context == "python")
    expr.print(GiNaC::print_python(os),level);
  else if (context == "python_repr")
    expr.print(GiNaC::print_python_repr(os),level);
  else if (context == "csrc")
    expr.print(GiNaC::print_csrc(os),level);
  else if (context == "csrc_float")
    expr.print(GiNaC::print_csrc_float(os),level);
  else if (context == "csrc_double")
    expr.print(GiNaC::print_csrc_double(os),level);
  else if (context == "csrc_cl_N")
    expr.print(GiNaC::print_csrc_cl_N(os),level);
  else if (context == "tree") {
    if ((signed)level < 0) {
      PyErr_SetString(PyExc_ValueError, "to_context(): level must be positive");
      throw py::error_already_set();
    }
    expr.print(GiNaC::print_tree(os),level);
  }
  else {
    PyErr_SetString(PyExc_ValueError,(std::string("context must be context|latex|python|python_repr|csrc|csrc_float|csrc_double|csrc_cl_N|tree but got ")+context).c_str());
    throw py::error_already_set();
  }
}

void to_context_file(const GiNaC::ex & expr, PyObject* fp, const std::string & context, unsigned level)
{
  if (!PyFile_Check(fp)) {
    PyErr_SetString(PyExc_TypeError, (std::string("to_context_file(): expected file but got ")+PyString_AsString(PyObject_Repr(PyObject_Type(fp)))).c_str());
    throw py::error_already_set();
  }
  FILE* f = PyFile_AsFile(fp);
  ostdiostream os(f);
  to_context(expr, os, context, level);
}

std::string to_context_str(const GiNaC::ex & expr, const std::string & context, unsigned level)
{
  std::ostringstream os;
  to_context(expr, os, context, level);
  return os.str();
}

PyObject* archive_to_dict(const GiNaC::archive_node & n,const GiNaC::lst & sym_lst, signed level) {
  PyObject* dict = PyDict_New();
  GiNaC::archive_node::propinfovector p;
  n.get_properties(p);
  unsigned num = p.size();
  for (unsigned i=0; i<num; ++i) {
    const std::string &name = p[i].name;
    unsigned count = p[i].count;
    PyObject* l = PyList_New(count);
    for (unsigned j=0; j<count; ++j) {
      switch (p[i].type) {
      case GiNaC::archive_node::PTYPE_BOOL: {
	bool x;
	n.find_bool(name, x, j);
	PyList_SetItem(l,j,Py_BuildValue("i",(x ? 1 : 0)));
	break;
      }
      case GiNaC::archive_node::PTYPE_UNSIGNED: {
	unsigned x;
	n.find_unsigned(name, x, j);
	PyList_SetItem(l,j,PyLong_FromUnsignedLong(x));
	break;
      }
      case GiNaC::archive_node::PTYPE_STRING: {
	std::string x;
	n.find_string(name, x, j);
	PyList_SetItem(l,j,Py_BuildValue("s",x.c_str()));
	break;
      }
      case GiNaC::archive_node::PTYPE_NODE: {
	if (level==0) {
	  GiNaC::ex e;
	  n.find_ex(name,e,sym_lst,j);
	  PyList_SetItem(l,j,BOOST_PYTHON_CONVERSION::to_python(e));
	  break;
	}
	const GiNaC::archive_node &x = n.find_ex_node(name, j);
	PyList_SetItem(l,j,archive_to_dict(x,sym_lst,level-1));
	break;
      }
      }
      if (count==1 && (name=="class" || name=="name" || name=="TeX_name" \
		       || name=="number" || name=="overall_coeff" \
		       || name=="rh" || name=="lh" || name=="op" )) {
	if (PyDict_SetItemString(dict,(char *)name.c_str(),PyList_GetItem(l,0)))
	  throw py::error_already_set();
      } else {
	if (PyDict_SetItemString(dict,(char *)name.c_str(),l))
	  throw py::error_already_set();
      }
    }
  }
  return dict;
}

void get_symbols(const GiNaC::ex & expr, GiNaC::lst & sym_lst) {
  unsigned n = expr.nops();
  for (unsigned i=0;i<n;++i) {
    const GiNaC::ex & e = expr.op(i);
    if (GiNaC::is_a<GiNaC::symbol>(e)) {
      if (!sym_lst.has(e))
	sym_lst.append(e);
    }
    else
      get_symbols(e, sym_lst);
  }
}

PyObject* extract_archived(const GiNaC::ex & expr, signed level) {
  GiNaC::archive a(expr);
  GiNaC::lst sym_lst = GiNaC::lst();
  if (level>=0)
    get_symbols(expr, sym_lst);
  return archive_to_dict(a.get_top_node(0),sym_lst,level);
}

GiNaC::ex get_slice(const GiNaC::ex & self,PyObject *index) {
  int start, step_size, n_steps;
  start = parse_subindex(index, &step_size, &n_steps, self.nops());
  if (start < 0)
    throw py::error_already_set();
  if (n_steps==PseudoIndex || n_steps==RubberIndex) {
    PyErr_SetString(PyExc_NotImplementedError, "get_slice() for PseudoIndex|RubberIndex");
    throw py::error_already_set();
  }
  if (n_steps==SingleIndex)
    return self.op(start);
  if (GiNaC::is_a<GiNaC::lst>(self)) {
    GiNaC::lst v;
    int k = start, l=self.nops();
    for (int i=0; i<n_steps; ++i,k += step_size)
      v.append(self.op((k==l)?0:k));
    return v;
  }
  PyErr_SetString(PyExc_NotImplementedError, (std::string("get_slice() for ")+self.bp->class_name()).c_str());
  throw py::error_already_set();  
}



void set_slice(GiNaC::ex & self,PyObject *index,const GiNaC::ex & other) {
  int start, step_size, n_steps;
  start = parse_subindex(index, &step_size, &n_steps, self.nops());
  if (start < 0)
    throw py::error_already_set();
  if (n_steps==PseudoIndex || n_steps==RubberIndex) {
    PyErr_SetString(PyExc_NotImplementedError, "set_slice() for PseudoIndex|RubberIndex");
    throw py::error_already_set();
  }
  if (n_steps==SingleIndex) {
    self.let_op(start) = other;
    return;
  }
  if (GiNaC::is_a<GiNaC::lst>(self)) {
    int n = other.nops();
    int l = self.nops();
    int k = start; 
    if (n==0) {
      for (int i=0; i<n_steps; ++i,k += step_size)
	 self.let_op((k==l)?0:k) = other;
      return;
    }
    if (n!=n_steps) {
      PyErr_SetString(PyExc_IndexError, "set_slice(): not matching index vectors");
      throw py::error_already_set();
    }
    for (int i=0; i<n_steps; ++i,k += step_size)
      self.let_op((k==l)?0:k) = other.op(i);
    return;
  }
  PyErr_SetString(PyExc_NotImplementedError, (std::string("set_slice() for ")+self.bp->class_name()).c_str());
  throw py::error_already_set();
}

#endif
#endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>