This repository has been archived on 2026-03-28. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
eodev/eo/contrib/mathsym/sym/Sym.h
2005-11-24 09:35:34 +00:00

174 lines
5.1 KiB
C++

/*
* Copyright (C) 2005 Maarten Keijzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SYMNODE_H_
#define SYMNODE_H_
#include <cassert>
#if __GNUC__ >= 3
#include <backward/hash_map.h>
#elif __GNUC__ < 3
#include <hash_map.h>
using std::hash_map;
#endif
/* Empty 'extra statistics' structure, derive from this to keep other characteristics of nodes */
struct UniqueNodeStats { virtual ~UniqueNodeStats(){} };
#include "SymImpl.h"
#include "token.h"
#if __GNUC__ == 4
#define USE_TR1 1
#else
#define USE_TR1 0
#endif
#if USE_TR1
#include <tr1/unordered_map>
typedef std::tr1::unordered_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap;
#else
typedef hash_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap;
#endif
typedef SymMap::iterator SymIterator;
/* Sym is the tree, for which all the nodes are stored in a hash table.
* This makes checking for equality O(1) */
class Sym
{
public:
Sym() : node(dag.end()) {}
explicit Sym(token_t token, const SymVec& args);
explicit Sym(token_t token, const Sym& args);
explicit Sym(token_t var);
explicit Sym(SymIterator it) : node(it) { incref(); }
Sym(const Sym& oth) : node(oth.node) { incref(); }
~Sym() { decref(); }
const Sym& operator=(const Sym& oth) {
if (oth.node == node) return *this;
decref();
node = oth.node;
incref();
return *this;
}
/* Unique Stats are user defined */
UniqueNodeStats* extra_stats() const { return empty()? 0 : node->second.uniqueNodeStats; }
int hashcode() const { return node->first.get_hash_code(); } //detail::SymKey::Hash hash; return hash(node->first); }
// Friends, need to touch the node
friend struct detail::SymKey::Hash;
friend struct detail::SymKey;
unsigned refcount() const { return empty()? 0: node->second.refcount; }
bool operator==(const Sym& other) const {
return node == other.node;
}
bool operator!=(const Sym& other) const { return !(*this == other); }
bool empty() const { return node == dag.end(); }
/* Support for traversing trees */
unsigned arity() const { return node->first.arity(); }
token_t token() const { return node->first.token; }
const SymVec& args() const { return node->first.vec(); }
/* size() - depth */
unsigned size() const { return empty()? 0 : node->second.size; }
unsigned depth() const { return empty()? 0 : node->second.depth; }
SymMap::iterator iterator() const { return node; }
/* Statics accessing some static members */
static SymMap& get_dag() { return dag; }
/* This function can be set to create some UniqueNodeStats derivative that can contain extra stats for a node,
* it can for instance be used to create ERC's and what not. */
static void set_factory_function(UniqueNodeStats* (*f)(const Sym&)) { factory=f; }
static void clear_factory_function() { factory = 0; }
static const std::vector<unsigned>& token_refcount() { return token_count; }
unsigned address() const { return reinterpret_cast<unsigned>(&*node); }
private :
// implements getting subtrees
Sym private_get(size_t w) const;
unsigned __unchecked_refcount() const { return node->second.refcount; }
void incref() {
if (!empty()) {
++(node->second.refcount);
++token_count[token()];
}
}
void decref() {
if (!empty()) {
--token_count[token()];
if (--(node->second.refcount) == 0) {
dag.erase(node);
}
}
}
// The one and only data member, an iterator into the static map below
SymIterator node;
// A static hash_map that contains all live nodes..
static SymMap dag;
static std::vector<unsigned> token_count;
// Factory function for creating extra node stats, default will be 0
static UniqueNodeStats* (*factory)(const Sym&);
};
/* Utility hash functor for syms */
class HashSym {
public:
int operator()(const Sym& sym) const { return sym.hashcode(); }
};
/* Utility Functions */
// get_subtree retrieves a subtree by standard ordering (0=root, and then depth first)
Sym get_subtree(const Sym& org, size_t w);
// insert_subtree uses the same ordering as get and inserts the second argument, returning a new tree
Sym insert_subtree(const Sym& org, size_t w, const Sym& nw);
/* Get the successor from the hashtable, no particular purpose other than an interesting way to mutate */
inline Sym next(const Sym& sym) {
SymIterator it = sym.iterator();
++it;
if (it == Sym::get_dag().end()) it = Sym::get_dag().begin();
return Sym(it);
}
#endif