/* * surf - visualizing algebraic curves and algebraic surfaces * Copyright (C) 1996-1997 Friedrich-Alexander-Universitaet * Erlangen-Nuernberg * 1997-2000 Johannes Gutenberg-Universitaet Mainz * Authors: Stephan Endrass, Hans Huelf, Ruediger Oertel, * Kai Schneider, Ralf Schmitt, Johannes Beigel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef TREEPOLYNOM_H #define TREEPOLYNOM_H #include #include "defs.h" #include "debug.h" #include "RBTree.h" #include "RefCounter.h" template class TreePolynomNode : public RBNode { public: Monom monom; static void free (RBNode *node) {delete ((TreePolynomNode*)node);}; static void copy (RBNode *dst, const RBNode *node) { ((TreePolynomNode*)dst)->monom=((TreePolynomNode*)node)->monom; }; static RBNode *newNode () {return new TreePolynomNode();}; }; template class TreePolynom : public RefCounter { public: TreePolynom() {root=NIL;}; ~TreePolynom(){freeNodes ((TreePolynomNode *)root);}; void addMonom(const Monom &mon); void subMonom(const Monom &mon); void mulMonom(const Monom &mon); void addPoly(const TreePolynom &tp); void subPoly(const TreePolynom &tp); const Monom &lmonom() const; TreePolynom *clone() const; int degreeInVariable (int var) { RBNode *it; int degree=-1; iteratorInit(it, root); while (iteratorIsValid(it)) { TreePolynomNode *node = (TreePolynomNode*) it; int tmp; if ((tmp = node->monom.getExponent(var)) > degree) degree=tmp; iteratorNext(it); } return degree; } void swapVariables(int var1, int var2) { RBNode *it; iteratorInit(it, root); while(iteratorIsValid(it)) { TreePolynomNode *node = (TreePolynomNode*) it; swap(node->monom.getExponent(var1), node->monom.getExponent(var2)); iteratorNext(it); } }; int _isNull() const {return root == NIL;}; void print (ostream &os) const; static TreePolynom* multiply (TreePolynom *tp1, TreePolynom *tp2); void withMonomsPerform ( void (*action) (Monom *, void *), void *data) { RBNode *it; iteratorInit(it, root); while(iteratorIsValid(it)) { TreePolynomNode *node = (TreePolynomNode*) it; action(&node->monom, data); iteratorNext(it); } }; void withAllMonomsPerform ( void (*action) (Monom *) ) { RBNode *it; iteratorInit(it, root); while(iteratorIsValid(it)) { TreePolynomNode *node = (TreePolynomNode*) it; action(&node->monom); iteratorNext(it); } }; protected: RBNode *root; void freeNodes(TreePolynomNode *node) { if (node == NIL) return; freeNodes ((TreePolynomNode *)node->left); freeNodes ((TreePolynomNode *)node->right); delete node; } }; template void TreePolynom::addMonom (const Monom &mon) { int cmp=0; // FIXME...just to suppress compiler warnings TreePolynomNode *current=(TreePolynomNode *) root; TreePolynomNode *parent=0; while (current != NIL) { cmp = mon.lexcmp(current->monom); if (cmp == 0) { current->monom += mon; if (isNull(current->monom)) { deleteNode(current, root, TreePolynomNode::copy, TreePolynomNode::free); } return; } parent=current; current = (TreePolynomNode*)(cmp < 0 ? current->left : current->right); } TreePolynomNode *x = new TreePolynomNode(); x->monom = mon; if (parent) { // cmp might not be used uninitialized, because if parent != 0 we made a // call to cmp = lexorder(mon, current->monom) (see above) if (cmp<0) parent->left = x; else parent->right = x; } else { root = x; } x->parent = parent; // x->left = NIL; // x->right = NIL; // x->color = RED; insertFixup(x, root); } template void TreePolynom::subMonom (const Monom &mon) { int cmp=0; // FIXME ...no compiler warnings TreePolynomNode *current=(TreePolynomNode *) root; TreePolynomNode *parent=0; while (current != NIL) { cmp = mon.lexcmp(current->monom); if (cmp == 0) { current->monom -= mon; if (isNull(current->monom)) { deleteNode(current, root, TreePolynomNode::copy, TreePolynomNode::free); } return; } parent=current; current = (TreePolynomNode*)(cmp < 0 ? current->left : current->right); } TreePolynomNode *x = new TreePolynomNode(); x->monom = mon; negate(x->monom); if (parent) { // cmp might not be used uninitialized, because if parent != 0 we made a // call to cmp = lexorder(mon, current->monom) (see above) if (cmp<0) parent->left = x; else parent->right = x; } else { root = x; } x->parent = parent; // x->left = NIL; // x->right = NIL; // x->color = RED; insertFixup(x, root); } template void TreePolynom::mulMonom(const Monom &mon) { RBNode *it; iteratorInit (it, root); while (iteratorIsValid(it)) { TreePolynomNode *node = (TreePolynomNode *)it; node->monom *= mon; iteratorNext(it); } } template void TreePolynom::addPoly (const TreePolynom &tp) { RBNode *it; iteratorInit (it, tp.root); while (iteratorIsValid(it)) { addMonom( ((TreePolynomNode*)it)->monom); iteratorNext(it); } } template void TreePolynom::subPoly (const TreePolynom &tp) { RBNode *it; iteratorInit (it, tp.root); while (iteratorIsValid(it)) { subMonom( ((TreePolynomNode*)it)->monom); iteratorNext(it); } } template const Monom & TreePolynom::lmonom() const { RBNode *it; iteratorInit(it, root); assert(iteratorIsValid(it)); return ((TreePolynomNode *) it)->monom; } template TreePolynom * TreePolynom::clone() const { TreePolynom *tp = new TreePolynom(); tp->root = cloneTree(root, 0, TreePolynomNode::newNode, TreePolynomNode::copy); return tp; } template void TreePolynom::print (ostream &os) const { RBNode *it; iteratorInit (it, root); if (!iteratorIsValid(it)) { os << "0"; return; } while (iteratorIsValid(it)) { TreePolynomNode *node = (TreePolynomNode *)it; os << node->monom; iteratorNext(it); if (iteratorIsValid(it)) os << "+"; } } template ostream & operator << (ostream &os, const TreePolynom &tp) { tp.print(os); return os; } template TreePolynom * TreePolynom::multiply (TreePolynom *tp1, TreePolynom *tp2) { assert(tp1); assert(tp2); TreePolynom *result = new TreePolynom(); RBNode *it1, *it2; iteratorInit(it1, tp1->root); while (iteratorIsValid(it1)) { iteratorInit(it2, tp2->root); Monom &it1mon = ((TreePolynomNode *)it1)->monom; while (iteratorIsValid(it2)) { Monom m (it1mon); m *= ((TreePolynomNode*)it2)->monom; result->addMonom(m); iteratorNext(it2); } iteratorNext(it1); } return result; } template TreePolynom * multiply (TreePolynom *tp1, TreePolynom *tp2) { return TreePolynom::multiply (tp1, tp2); } template class TreePoly { public: TreePoly(TreePolynom *p) : poly(p) {}; TreePoly() : poly(new TreePolynom()) {}; TreePoly(const TreePoly &tp) : poly(tp.poly) {retain(poly);}; ~TreePoly() {release(poly);}; TreePoly & operator = (const TreePoly &tp) {assert(&tp!=this);release(poly); poly=tp.poly; retain(poly); return *this;}; TreePoly clone() const {return TreePoly(poly->clone());}; TreePoly operator += (const TreePoly p) {poly->addPoly(*p.poly); return *this;}; TreePoly operator -= (const TreePoly p) {poly->subPoly(*p.poly); return *this;}; TreePoly operator + (const TreePoly &p) const { TreePolynom *result = poly->clone(); result->addPoly(*p.poly); return result; }; TreePoly operator - (const TreePoly &p) const { TreePolynom *result = poly->clone(); result->subPoly(*p.poly); return result; }; TreePoly operator * (const TreePoly &p) const { TreePolynom *retval = multiply(poly, p.poly); return retval; } void addMonom(const Monom &mon) {poly->addMonom(mon);}; int degreeInVariable(int var) {return poly->degreeInVariable(var);}; void swapVariables(int var1, int var2) {poly->swapVariables(var1, var2);}; const Monom &lmonom () const {return poly->lmonom();}; // friend class ostream &operator<<(ostream &os, const TreePoly &tp); int _isNull () const {return poly->_isNull();}; void withAllMonomsPerform ( void (*action) (Monom *) ) {poly->withAllMonomsPerform(action);}; void withMonomsPerform ( void (*action) (Monom *, void *), void *data ) {poly->withMonomsPerform(action,data);}; void print (ostream &os) const { os << *poly;} protected: TreePolynom *poly; }; template int isNull (const TreePoly &tp) { return tp._isNull(); } template void setNull (TreePoly &tp) { // todo } template ostream &operator<<(ostream &os, const TreePoly &tp) { tp.print(os); return os; //return os << *tp.poly; } template TreePoly divide (TreePoly f, TreePoly g) { TreePoly result; while (!isNull(f)) { Monom m = f.lmonom(); m /= g.lmonom(); result.addMonom(m); TreePoly tmp; tmp.addMonom(m); f = f-g*tmp; } return result; } #endif