/*
 * ===========================
 * VDK Visual Development Kit
 * Version 0.5
 * November 1998
 * ===========================
 *
 * Copyright (C) 1998, Mario Motta
 * Developed by Mario Motta <mmotta@guest.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library 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 VDKBTREES_H
#define VDKBTREES_H
#ifdef NULL
#undef NULL
#define NULL 0x0000
#endif
// --------------------------
// Abstract  class template, 
// --------------------------

template<class T, class Node>
class AbstractBinaryNode {
public:
    AbstractBinaryNode() { }
    AbstractBinaryNode(  T& _object, 
               Node *_parent = NULL, 
               Node *_left = NULL, 
               Node *_right = NULL);
    virtual ~AbstractBinaryNode() { }

    // Subtree arrangement
    virtual Node *Clone(Node *_parent)  ;
    virtual void RemoveSubtree();
    virtual Node *LeftRotate(Node *root);
    virtual Node *RightRotate(Node *root);
    virtual int CheckTreeProperties(  Node *);
    virtual int IsLeftChild()  ;
    virtual int IsRightChild()  ;
    // Adding a node and deleting
    virtual Node *add(  T& x);
    virtual Node *unlink(Node *z);

    // Find
    virtual Node *find(  T& x);
    virtual Node *findNearest(  T& x);

    // Tree trasverse
    virtual Node *Minimum();
    virtual Node *Maximum();
    virtual Node *Predecessor();
    virtual Node *Successor();

    // Miscellaneous
    virtual T *Object();

public:
    T object;
    Node *left, *right, *parent;

};

template<class T>
class BinaryNode : public AbstractBinaryNode<T, BinaryNode<T> > {
public:
    //  ructors and destructor
    BinaryNode() { }
    BinaryNode(  T& object, 
               BinaryNode<T> *parent = NULL, 
               BinaryNode<T> *left = NULL, 
               BinaryNode<T> *right = NULL):
        AbstractBinaryNode<T, BinaryNode<T> >(object, parent, left, right) { }
    virtual ~BinaryNode() { }
};

//////////////////////////////////////////////////////
// Iterator class 
    /*!
      \class AbstractBinaryTree::Iterator
      \brief Provides a nlog(n) iterator for AbstractBinaryTree

      Iterator is implementes as a member of AbstractBinaryTree
      rather than an external object.
     */
enum BtreeIteratorMode { BtMinKey, BtRootKey, BtMaxKey };
/*!
  \class AbstractBinaryTree
  \brief provides an abstract class for concrete VDKBtree class
 */
template<class T, class Node>
class AbstractBinaryTree {

public:

    AbstractBinaryTree();
    /*!
      Copy initializer
     */
    AbstractBinaryTree(  AbstractBinaryTree<T, Node>&);
    /*!
      Assignement operator
     */
    AbstractBinaryTree<T, Node>& operator=(  AbstractBinaryTree<T, Node>&);
    virtual ~AbstractBinaryTree();

    /*!
      Adds a type <T> to tree.
    */
    virtual void add(  T&);      // Add a node
    /*!
      Remove a type <T> from the tree
     */
    virtual void unlink(  T&);      // Remove a node
    /*!
      Membership operator, return T* NULL on failure.
     */
    virtual T *find(  T& q);
    /*!
      Return 1 if tree is empty
     */
    virtual int IsEmpty()   { return root == NULL; }

    /*
      \internal
    */
    virtual Node *IteratorRoot()  ;
    /*
      \internal
    */
    virtual Node *IteratorFind(  T& x)  ;
    /*!
      Checks tree integrity (for debugging purposes)
     */
    virtual int CheckTreeProperties();
    /*!
      Returns tree size in nodes.
     */
    unsigned int size() { return count; }

    
    class Iterator {

    public:
      /*!
	  ructor
	 \param tree tree reference
	 \param start where the iterator starts, can be:
	 \arg BtMinKey from lowest key
	 \arg BtRootKey from the tree root
	 \arg BtMaxKey from the highest key
       */
        Iterator(  AbstractBinaryTree<T, Node>& _tree, 
                 enum BtreeIteratorMode start = BtMinKey) 
        {
            tree = (AbstractBinaryTree<T, Node> *) (&_tree);
            StartAt(start);
        }

        /*!
	  Starts iterator over at the minimum, maximum or
	  root node of the binary tree.
	*/
        void StartAt(enum BtreeIteratorMode start) 
        {
            ptr = tree->IteratorRoot();
            if (start == BtMinKey)
                ptr = ptr->Minimum();
            else if (start == BtMaxKey)
                ptr = ptr->Maximum();
        }
	/*!
	  Destructor
	 */
        virtual ~Iterator() { }
	/*!
	  Move iterator to prev key
	*/
        virtual void Previous() 
        {
            if (ptr)
                ptr = ptr->Predecessor();
        }
	/*!
	  Move iterator to next key
	*/
        virtual void Next() 
        {
            if (ptr)
                ptr = ptr->Successor();
        }
	/*!
	  Move iterator to parent node
	*/
        virtual void Parent() 
        {
            if (ptr)
                ptr = ptr->parent;
        }
	/*!
	  \internal
	*/
        virtual void find(  T& x) 
        {
            ptr = tree->IteratorFind(x);
        }
	/*!
	  Returns o if iterator points a non valid node.
	  ie: was moved behind the lowest/highest key
	 */
        virtual operator int()   
        {
            return ptr != NULL;
        }

        /*! 
	  Dereferencing operator returns the object of the
	  node currently pointed to by the iterator.
	*/
        virtual T operator*()   {  return ptr->object; }
	/*! 
	  Dereferencing operator returns the object of the
	  node currently pointed to by the iterator.
	*/
	virtual T current()   {  return ptr->object; }
	/*!
	  \internal
	*/
	virtual Node* current_node()  
	  { return ptr; }
        /*! 
	 returns a pointer to the object of the
         node currently pointed to (as opposed to returning
         a copy of the node, as the dereferencing operator does).
	*/
        virtual   T *RefObject()   
        {
            if (ptr)
                return &ptr->object;
            return (T*) NULL;
        }
        /*! 
	 returns a pointer to the object of the
         node currently pointed to (as opposed to returning
         a copy of the node, as the dereferencing operator does).
	*/
        virtual T *Object() 
        {
            if (ptr)
                return &ptr->object;
            return NULL;
        }
	/*!
	  Move iterator to next key
	*/
        virtual void operator++() { Next(); }
	/*!
	  Move iterator to next key
	*/
        virtual void operator++(int) { Next(); }
	/*!
	  Move iterator to prev key
	*/
        virtual void operator--() { Previous(); }
	/*!
	  Move iterator to prev key
	*/
        virtual void operator--(int) { Previous(); }

    protected:
        Node *ptr;
        AbstractBinaryTree<T, Node> *tree;
    };

protected:
    Node *root;
    unsigned int count;
};

/*
  class BinaryTree
  place holder for others type of binary trees
template<class T>
class BinaryTree : public AbstractBinaryTree<T, BinaryNode<T> > {
public:
    BinaryTree() { }
};
*/


// --------------------------------------------------------
// AbstractBinaryNode implementation.
// --------------------------------------------------------
template<class T, class Node>
AbstractBinaryNode<T, Node>::AbstractBinaryNode(  T& _object, 
                          Node *_parent,
                          Node *_left, 
                          Node *_right) 
{
    object = _object;
    parent = _parent;
    left = _left;
    right = _right;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Clone(Node *_parent)  
{
    Node *ret = new Node( *((Node *) this));
    if (left)
        ret->left = left->Clone(ret);
    if (right)
        ret->right = right->Clone(ret);
    ret->parent = _parent;
    return ret;
}

template<class T, class Node> 
Node *
AbstractBinaryNode<T, Node>::LeftRotate(Node *root)
{
    Node *ret = root;
    Node *y = right;
    right = y->left;
    if (right)
        right->parent = (Node *) this;
    y->parent = parent;
    if (parent) {
        if (this == parent->left)
            parent->left = y;
        else
            parent->right = y;
    }
    else
        ret = y;
    y->left = (Node *) this;
    parent = y;
    return ret;
}

template<class T, class Node> 
Node *
AbstractBinaryNode<T, Node>::RightRotate(Node *root)
{
    Node *ret = root;
    Node *x = left;
    left = x->right;
    if (left)
        left->parent = (Node *) this;
    x->parent = parent;
    if (parent) {
        if (this == parent->left)
          parent->left = x;
        else
          parent->right = x;
    }
    else
        ret = x;
    x->right = (Node *) this;
    parent = x;
    return ret;
}

template<class T, class Node>
int
AbstractBinaryNode<T, Node>::IsLeftChild()  
{
    return (parent && parent->left == (Node *) this);
}

template<class T, class Node>
int
AbstractBinaryNode<T, Node>::IsRightChild()  
{
    return (parent && parent->right == (Node *) this);
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::find(  T& x)
{
    Node *sc = (Node *) this;
    while (sc) {
        if (x == sc->object)
            return sc;
        if (x < sc->object)
            sc = sc->left;
        else
            sc = sc->right;
    }
    return NULL;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::findNearest(  T& x)
{
    Node *sc = (Node *) this;
    Node *prev = NULL;
    while (sc) {
        prev = sc;
        if (x < sc->object)
            sc = sc->left;
        else
            sc = sc->right;
    }
    return prev;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::add(  T& x) 
{
    Node *nearest = findNearest(x);
    if (x < nearest->object)
        nearest->left = new Node(x, nearest);
    else
        nearest->right = new Node(x, nearest);
    return (Node *) this;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::unlink(Node *z)
{
    Node *root = (Node *) this;
    Node *x, *y;
    if (! z)
        return root;
    if (! z->left || ! z->right)
        y = z;
    else
        y = z->Successor();
    if (y->left)
        x = y->left;
    else
        x = y->right;
    if (x)
        x->parent = y->parent;
    if (y->parent) {
        if (y == y->parent->left)
            y->parent->left = x;
        else
            y->parent->right = x;
    }
    else
        root = x;
    if (y != z)
        z->object = y->object;
    delete y;
    return root;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Minimum()
{
    Node *sc = (Node *) this;
    while (sc && sc->left)
        sc = sc->left;
    return sc;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Maximum()
{
    Node *sc = (Node *) this;
    while (sc && sc->right)
        sc = sc->right;
    return sc;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Predecessor()
{
    if (left)
        return left->Maximum();
    Node *x = (Node *) this;
    Node *y = parent;
    while (y && x == y->left) {
        x = y;
        y = y->parent;
    }
    return y;
}

template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Successor() 
{
    if (right)
        return right->Minimum();
    Node *x = (Node *) this;
    Node *y = parent;
    while (y && x == y->right) {
        x = y;
        y = y->parent;
    }
    return y;
}

template<class T, class Node>
void
AbstractBinaryNode<T, Node>::RemoveSubtree()
{
    if (left) {
        left->RemoveSubtree();
        delete  left;
    }
    if (right) {
        right->RemoveSubtree();
        delete right;
    }
}

template<class T, class Node>
T *
AbstractBinaryNode<T, Node>::Object()
{
    return &object;
}

template<class T, class Node>
int
AbstractBinaryNode<T, Node>::CheckTreeProperties(  Node *_parent)
{
    if (parent != _parent)
        return NULL;
    if (left) {
        if (object < left->object)
            return NULL;
        if (! left->CheckTreeProperties((Node *) this))
            return NULL;
    }
    if (right) {
        if (right->object < object)
            return NULL;
        if (! right->CheckTreeProperties((Node *) this))
            return NULL;
    }
    return 1;
}

// --------------------------------------------------------
// AbstractBinaryTree class template implementation.
// --------------------------------------------------------

template<class T, class Node>
AbstractBinaryTree<T, Node>::AbstractBinaryTree()
{
    root = NULL;
    count = NULL;
}

template<class T, class Node>
AbstractBinaryTree<T, Node>::AbstractBinaryTree(  AbstractBinaryTree<T, Node>& x)
{
    if (x.root)
        root = x.root->Clone(NULL);
    else
        root = NULL;
    count = x.count;
}

template<class T, class Node>
AbstractBinaryTree<T, Node>&
AbstractBinaryTree<T, Node>::operator=(  AbstractBinaryTree<T, Node>& x)
{
    if (root) {
        root->RemoveSubtree();
        delete root;
    }
    if (x.root)
        root = x.root->Clone(NULL);
    else
        root = NULL;
    count = x.count;
    return *this;
}

template<class T, class Node>
AbstractBinaryTree<T, Node>::~AbstractBinaryTree()
{
    if (root) {
        root->RemoveSubtree();
        delete root;
    }
} 

template<class T, class Node>
void
AbstractBinaryTree<T, Node>::add(  T& x)
{
  count++;
  if (root == NULL)
    root = new Node(x);
  else
    root = root->add(x);
}

template<class T, class Node>
Node *
AbstractBinaryTree<T, Node>::IteratorRoot()  
{
    return root;
}

template<class T, class Node>
Node *
AbstractBinaryTree<T, Node>::IteratorFind(  T& x)  
{
    return (root) ? root->find(x) : NULL;
}

template<class T, class Node>
void
AbstractBinaryTree<T, Node>::unlink(  T& _x)
{
  count--;
  if (! root)
    return;
  root = root->unlink(root->find(_x));
}

template<class T, class Node>
T *
AbstractBinaryTree<T, Node>::find(  T& q)
{
    Node *p = (root) ? root->find(q) : NULL;
    return (p) ? &p->object : NULL;
}

template<class T, class Node>
int
AbstractBinaryTree<T, Node>::CheckTreeProperties()
{
  if (root->CheckTreeProperties(NULL) == NULL)
    return NULL;
  return 1;
}

/////////////////////////////
// balanced binary trees 
// (using red & black trees)
/////////////////////////////
typedef enum RedBlack { Black, Red };
template<class T, class Node>
class AbstractRedBlackNode : public AbstractBinaryNode<T, Node> {
public:

  RedBlack clr;
  //  ructors.  Node always starts out red.
  AbstractRedBlackNode() { clr = Red; }
  AbstractRedBlackNode(  T& X, 
		       Node *P = NULL,
		       Node *L = NULL,
		       Node *R = NULL):
    AbstractBinaryNode<T, Node>(X, P, L, R) { }
  AbstractRedBlackNode(  T& X, RedBlack Clr, Node *P = NULL,
		       Node *L = NULL, Node *R = NULL):
    AbstractBinaryNode<T, Node>(X, P, L, R), clr(Clr) { }
  virtual ~AbstractRedBlackNode() { }

    // Tree manipulations used during insertion and deletion
    virtual Node *RemoveFixup(Node *x, Node *p);
    
    // Operations defined on binary trees.  All run in O(lgN) time.
    virtual Node *add(  T& AddMe);
    virtual Node *unlink(Node *z);
    
    // Returns NULL if the red-black invariant holds.
    virtual int CheckTreeProperties(  Node *);
};

template<class T>
class RedBlackNode : public AbstractRedBlackNode<T, RedBlackNode<T> > {
public:

    //  ructors.  Node always starts out red.
    RedBlackNode() { }
    RedBlackNode(  T& X, 
                 RedBlackNode<T> *P = NULL,
                 RedBlackNode<T> *L = NULL,
                 RedBlackNode<T> *R = NULL):
        AbstractRedBlackNode<T, RedBlackNode<T> >(X, P, L, R) { }
    RedBlackNode(  T& X, RedBlack Clr, RedBlackNode<T> *P = NULL,
            RedBlackNode<T> *L = NULL, RedBlackNode<T> *R = NULL):
        AbstractRedBlackNode<T, RedBlackNode<T> >(X, Clr, P, L, R) { }
    virtual ~RedBlackNode() { }
};



/*!
  \class AbstractRedBlackTree
  \brief provides an abstract frame class for VDKBTree
 */
template<class T, class Node> 
class AbstractRedBlackTree : public AbstractBinaryTree<T, Node> {
protected:
    virtual Node *FindNode(T q)  
        { return (this->root) ? (Node *) this->root->find(q) : NULL; }
};

/*!
  \class VDKBtree
  \brief provides a templatized binary tree data structure
  
  \par Description
  VDKBtree<T> class has a value semantic, all objects are copied 
  from original values. 
  VDKBtree<T> class implements red/black balanced trees.
  All managed type T objects should provide:
  \arg a default constructor: T::T()
  \arg a copy initializer: T::T(T& t) 
  \arg an assignement operator: T& T::operator=(T& t) 
  \arg an equality and less-than operators:
  \arg bool T::operator==(T& t)
  \arg bool T::operator<(T& t)
  \par Implementation notes
  I suggest to use typedef's like:
  \code
  typedef VDKBtree<someClass> SomeClassBtree;
  \endcode
  \par Programming tips
  Here an example how to construct, fill and trasverse a btree
  \code
  #define LEN 10
  typedef VDKBtree<int> intbt;
  int v[LUNG] = { 3, 5, 7, 2, 1, 4, 45, 6, 23, 6 };
  int main(int , char **) 
  {
   intbt btree;
   // add nodes to tree
   for (t=0; t < LEN ;t++)
     btree.add(v[t]);
   // makes an iterator
   intbt::Iterator iter(btree);
   for (; iter;iter++)
     {
     int i = iter.current();
     // make whatever with i
     }
   // removes all nodes
   for (t=0; t < LEN; t++)
     btree.unlink(v[t]); 
  }
  \endcode
  \par EXAMPLES
  in ./example/template/ttest.cc
 */
template <class T>
class VDKBtree : public AbstractRedBlackTree<T, RedBlackNode<T> > {
public:
  /*!
    Constructor, makes an empty tree
   */
    VDKBtree() { }
};


template<class T, class Node> 
Node *
AbstractRedBlackNode<T, Node>::add(  T& AddMe)
{
    Node *root = (Node *) this;
    Node *x = (Node *) this;
    Node *y = NULL;
    while (x) {
        y = x;
        x = (AddMe < x->object) ? x->left : x->right;
    }
    Node *addme = new Node(AddMe, y);
    if (! y)
        root = addme;
    else {
      if (AddMe < y->object)
          y->left = addme;
      else
          y->right = addme;
    }
    addme->clr = Red;
    while (addme != root && 
           addme->parent->parent && 
           addme->parent->clr == Red) {
        Node *y;

        if (addme->parent == addme->parent->parent->left) {
            y = addme->parent->parent->right;
            if (y && y->clr == Red) {
                // Case 1: x's uncle is red
                addme->parent->clr = Black;
                y->clr = Black;
                addme->parent->parent->clr = Red;
                addme = addme->parent->parent;
            }
            else {
                if (addme == addme->parent->right) {
                    // Case 2: x is a right child
                    // Rotate to transform to case 3
                    addme = addme->parent;
                    root = addme->LeftRotate(root);
                }
                // Case 3: x is a left child
                addme->parent->clr = Black;
                if (addme->parent->parent) {
                    addme->parent->parent->clr = Red;
                    root = addme->parent->parent->RightRotate(root);
                }
                // The while loop will terminate 
                // on the next iteration.
            }
        }
        else {
            y = addme->parent->parent->left;
            if (y && y->clr == Red) {
                addme->parent->clr = Black;
                y->clr = Black;
                addme->parent->parent->clr = Red;
                addme = addme->parent->parent;
            }
            else {
                if (addme == addme->parent->left) {
                  addme = addme->parent;
                  root = addme->RightRotate(root);
                }
                addme->parent->clr = Black;
                if (addme->parent->parent) {
                    addme->parent->parent->clr = Red;
                    root = addme->parent->parent->LeftRotate(root);
                }
            }
        }
    }
    root->clr = Black;
    return root;
}

template<class T, class Node> 
Node *
AbstractRedBlackNode<T, Node>::RemoveFixup(Node *x, Node *p)
{
    Node *root = (Node *) this;

    while (x != root && (! x || x->clr == Black)) {
        Node *w;
        if (x == p->left) {
            if (! p)
                return root;
            w = p->right;
            if (! w)
                return root;
            if (w->clr == Red) {
                w->clr = Black;
                p->clr = Red;
                root = p->LeftRotate(root);
                w = p->right;
                if (! p || ! w)
                    return root;
            }
            if ( ((! w->left) || w->left->clr == Black) &&
                 ((! w->right) || w->right->clr == Black)) {
                  w->clr = Red;
                  x = p;
                  p = p->parent;
                  continue;
            }
            else if ((! w->right) || w->right->clr == Black) {
                w->left->clr = Black;
                w->clr = Red;
                root = w->RightRotate(root);
                w = p->right;
                if (! p || ! w)
                    return root;
            }
            w->clr = p->clr;
            if (p)
                p->clr = Black;
            w->right->clr = Black;
            if (p)
                root = p->LeftRotate(root);
            x = root;
        }
        else {
            if (! p)
                return root;
            w = p->left;
            if (! p || ! w)
                return root;
            if (w->clr == Red) {
                w->clr = Black;
                p->clr = Red;
                root = p->RightRotate(root);
                w = p->left;
                if (! p || ! w)
                    return root;
            }
            if ( ((! w->right) || w->right->clr == Black) &&
                 ((! w->left) || w->left->clr == Black)) {
                w->clr = Red;
                x = p;
                p = p->parent;
                continue;
            }
            else if ((! w->left) || w->left->clr == Black) {
                w->right->clr = Black;
                w->clr = Red;
                root = w->LeftRotate(root);
                w = p->left;
                if (! p || ! w)
                    return root;
            }
            w->clr = p->clr;
            if (p)
                p->clr = Black;
            w->left->clr = Black;
            if (p)
                root = p->RightRotate(root);
            x = root;
        }
    }
    if (x)
        x->clr = Black;
    return root;
}

template<class T, class Node> 
Node *
AbstractRedBlackNode<T, Node>::unlink(Node *z)
{
    Node *root = (Node *) this;
    Node *x, *y;

    if (! z)
        return root;
    y = (! z->left || ! z->right) ? z : (Node *) z->Successor();
    x = (y->left) ? y->left : y->right;

    if (x)
        x->parent = y->parent;

    if (y->parent) {
        if (y == y->parent->left)
            y->parent->left = x;
        else
            y->parent->right = x;
    }
    else
        root = x;
    if (y != z)
        z->object = y->object;
    if (y->clr == Black) {
        if (root)
            root = root->RemoveFixup(x, y->parent);
    }
    delete y;
    return root;
}

template<class T, class Node> 
int
AbstractRedBlackNode<T, Node>::CheckTreeProperties(  Node *_parent)
{
    static int BlackHeight;

    if (_parent == NULL)
        BlackHeight = -1;

    // Check binary tree properties.
    if (this->parent != _parent)
        return NULL;
    if (this->left) {
        if (this->object < this->left->object)
            return NULL;
    }
    if (this->right) {
        if (this->right->object < this->object)
            return NULL;
    }

    // Now check red-black tree properties.

    // If a node is red, then both its children are black
    // (NULL nodes are black).
    if (clr == Red) {
        if ((this->left && this->left->clr != Black) ||
            (this->right && this->right->clr != Black))
            return NULL;
    }

    // The black-heights of all leaf nodes are equal.
    int bh = NULL;

    if ((! this->left) && (! this->right)) {
        // Compute black-height of node
        for (Node *sc = (Node *) this; sc; sc = sc->parent)
            if (sc->clr == Black)
                bh += 1;

        if (BlackHeight == -1) {
            BlackHeight = bh;
        }
        else {
            if (bh != BlackHeight)
                return NULL;
        }
    }
    if (this->left && (! this->left->CheckTreeProperties((Node *) this)))
        return NULL;
    if (this->right && (! this->right->CheckTreeProperties((Node *) this)))
        return NULL;
    return 1;
}
#endif





