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.cpp
2005-11-24 09:35:34 +00:00

155 lines
4.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
*/
#include <sstream>
#include <vector>
#include "Sym.h"
using namespace std;
typedef UniqueNodeStats* (*NodeStatFunc)(Sym&);
UniqueNodeStats* (*Sym::factory)(const Sym&) = 0;
SymMap Sym::dag(100000); // reserve space for so many nodes
std::vector<unsigned> Sym::token_count;
size_t get_size(const SymVec& vec) {
size_t sz = 0;
for (unsigned i = 0; i < vec.size(); ++i) {
sz += vec[i].size();
}
return sz;
}
size_t get_depth(const SymVec& vec) {
size_t dp = 1;
for (unsigned i = 0; i < vec.size(); ++i) {
dp = std::max(dp, vec[i].depth());
}
return dp;
}
Sym::Sym(token_t tok, const SymVec& args_) : node(dag.end())
{
detail::SymKey key(tok, detail::SymArgs(args_));
detail::SymValue val;
node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first;
if (__unchecked_refcount() == 0) { // new node, set some stats
node->second.size = 1 + get_size(args_);
node->second.depth = 1 + get_depth(args_);
// token count
if (tok >= token_count.size()) {
token_count.resize(tok+1);
}
incref();
node->first.fixate();
// call the factory function if available
if (factory) node->second.uniqueNodeStats = factory(*this);
}
else incref();
}
Sym::Sym(token_t tok, const Sym& a) : node(dag.end()) {
SymVec args_; args_.push_back(a);
detail::SymKey key(tok, detail::SymArgs(args_));
detail::SymValue val;
node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first;
if (__unchecked_refcount() == 0) { // new node, set some stats
node->second.size = 1 + get_size(args_);
node->second.depth = 1 + get_depth(args_);
// token count
if (tok >= token_count.size()) {
token_count.resize(tok+1);
}
incref();
node->first.fixate();
// call the factory function if available
if (factory) node->second.uniqueNodeStats = factory(*this);
}
else incref();
}
Sym::Sym(token_t tok) : node(dag.end()) {
detail::SymKey key(tok);
detail::SymValue val;
node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first;
if (__unchecked_refcount() == 0) { // new node, set some stats
node->second.size = 1;
node->second.depth = 1;
// token count
if (tok >= token_count.size()) {
token_count.resize(tok+1);
}
incref();
// call the factory function if available
if (factory) node->second.uniqueNodeStats = factory(*this);
}
else incref();
}
std::pair<Sym,bool> insert_subtree_impl(const Sym& cur, size_t w, const Sym& nw) {
if (w-- == 0) return make_pair(nw, !(nw == cur));
const SymVec& vec = cur.args();
std::pair<Sym,bool> result;
unsigned i;
for (i = 0; i < vec.size(); ++i) {
if (w < vec[i].size()) {
result = insert_subtree_impl(vec[i], w, nw);
if (result.second == false) return std::make_pair(cur, false); // unchanged
break;
}
w -= vec[i].size();
}
SymVec newvec = cur.args();
newvec[i] = result.first;
return make_pair(Sym(cur.token(), newvec), true);
}
Sym insert_subtree(const Sym& cur, size_t w, const Sym& nw) {
return insert_subtree_impl(cur,w,nw).first;
}
Sym get_subtree(const Sym& cur, size_t w) {
if (w-- == 0) return cur;
const SymVec& vec = cur.args();
for (unsigned i = 0; i < vec.size(); ++i) {
if (w < vec[i].size()) return get_subtree(vec[i], w);
w-=vec[i].size();
}
return cur;
}