Пример #1
0
/** Tree output to stream. */
void basic::do_print_tree(const print_tree & c, unsigned level) const
{
    c.s << std::string(level, ' ') << class_name() << " @" << this
        << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec;
    if (nops())
        c.s << ", nops=" << nops();
    c.s << std::endl;
    for (size_t i=0; i<nops(); ++i)
        op(i).print(c, level + c.delta_indent);
}
Пример #2
0
/** Evaluate sums, products and integer powers of matrices. */
ex basic::evalm() const
{
    if (nops() == 0)
        return *this;
    else
        return map(map_evalm);
}
Пример #3
0
/** Substitute a set of objects by arbitrary expressions. The ex returned
 *  will already be evaluated. */
ex basic::subs(const exmap & m, unsigned options) const
{
    size_t num = nops();
    if (num) {

        // Substitute in subexpressions
        for (size_t i=0; i<num; i++) {
            const ex & orig_op = op(i);
            const ex & subsed_op = orig_op.subs(m, options);
            if (!are_ex_trivially_equal(orig_op, subsed_op)) {

                // Something changed, clone the object
                basic *copy = duplicate();
                copy->setflag(status_flags::dynallocated);
                copy->clearflag(status_flags::hash_calculated | status_flags::expanded);

                // Substitute the changed operand
                copy->let_op(i++) = subsed_op;

                // Substitute the other operands
                for (; i<num; i++)
                    copy->let_op(i) = op(i).subs(m, options);

                // Perform substitutions on the new object as a whole
                return copy->subs_one_level(m, options);
            }
        }
    }

    // Nothing changed or no subexpressions
    return subs_one_level(m, options);
}
Пример #4
0
ex sub_val::op(size_t i) const{
	GINAC_ASSERT(i<nops());
	if(i)
		return val;
	else
		return name;
}
Пример #5
0
/** Evaluate integrals, if result is known. */
ex basic::eval_integ() const
{
    if (nops() == 0)
        return *this;
    else
        return map(map_eval_integ);
}
Пример #6
0
  void StaticDetour::ApplyHook(void* callback) {
    if(mDetoured) {
      return;
    }
    
    size_t allocated;
    void* memory = Memory::Allocate(
      mBytesDisassembled + ARRAY_SIZE(PatchRelative),
      Memory::ReadWriteExecute,
      &allocated);

    // Allocate executable memory to backup the original function (i.e the trampoline)
    mTrampoline.reset(static_cast<byte*>(memory), [allocated](byte* memory) {
      Memory::Free(memory, allocated);
    });

    MemoryRegion region(mTarget, mBytesDisassembled);
    region.ExecuteFunction(Memory::ReadWriteExecute, [this, callback]() {
      // Copy the original function bytes to our trampoline
      std::memcpy(mTrampoline.get(), mTarget, mBytesDisassembled);

      // To avoid any execution of the function whilst it is being modified, we
      // first create the patch in this vector, so we can copy it in one sweep
      std::vector<byte> patch(ARRAY_SIZE(PatchRelative));
      std::memcpy(patch.data(), PatchRelative, patch.size());

      // Calculate the relative address to the callback function from the current EIP
      *reinterpret_cast<uint*>(patch.data() + 0x01) =
        (static_cast<byte*>(callback) - static_cast<byte*>(mTarget)) - patch.size();
  
      // Copy the patch to the original function to detour it!
      std::memcpy(mTarget, patch.data(), patch.size());

      uint delta = mBytesDisassembled - ARRAY_SIZE(PatchRelative);

      if(delta > 0) {
        std::vector<byte> nops(delta);
        std::fill(nops.begin(), nops.end(), 0x90);

        // In case we disassembled more instructions than we've replaced, there might be
        // corrupt ones left in the function. These will never be executed but just because
        // they _might_ be, we replace those invalid instructions with normal 'nops'.
        std::memcpy(static_cast<byte*>(mTarget) + ARRAY_SIZE(PatchRelative), nops.data(), nops.size());
      }

      // If the user wants to execute the original function, we must first execute the bytes
      // that we replaced with the detour, and then jump to the rest of the function. So we
      // do this by adding a relative jump at the end of our trampoline.
      std::memcpy(patch.data(), PatchRelative, patch.size());

      // Calculate the relative address to the callback function (the user provided one) from the current EIP
      *reinterpret_cast<uint*>(patch.data() + 0x01) =
        (static_cast<byte*>(mTarget) - static_cast<byte*>(&mTrampoline.get()[mBytesDisassembled])) - patch.size() + mBytesDisassembled;
      std::memcpy(&mTrampoline.get()[mBytesDisassembled], patch.data(), patch.size());

      // We have successfully hooked the function!
      mDetoured = true;
    });
  }
Пример #7
0
ex& sub_val::let_op(size_t i){
	GINAC_ASSERT(i<nops());
	ensure_if_modifiable();
	if(i)
		return val;
	else
		return name;
}
Пример #8
0
/** Traverse expression tree with given visitor, postorder traversal. */
void ex::traverse_postorder(visitor & v) const
{
	size_t n = nops();
	for (size_t i = 0; i < n; ++i)
		op(i).traverse_postorder(v);

	accept(v);
}
Пример #9
0
/** Expand expression, i.e. multiply it out and return the result as a new
 *  expression. */
ex basic::expand(unsigned options) const
{
    if (nops() == 0)
        return (options == 0) ? setflag(status_flags::expanded) : *this;
    else {
        expand_map_function map_expand(options);
        return ex_to<basic>(map(map_expand)).setflag(options == 0 ? status_flags::expanded : 0);
    }
}
Пример #10
0
/** Default implementation of ex::diff(). It maps the operation on the
 *  operands (or returns 0 when the object has no operands).
 *
 *  @see ex::diff */
ex basic::derivative(const symbol & s) const
{
    if (nops() == 0)
        return _ex0;
    else {
        derivative_map_function map_derivative(s);
        return map(map_derivative);
    }
}
Пример #11
0
ex row_mul::GetSum(int i, int nj) const
{
	ex s = s_taylor;
	if(nj == int(nops() - 1))
		return op(nj).coeff(s, i);
	ex res;
	for(int j = 0; j <= i; j++)
		res += binomial(j,0)*op(nj).coeff(s, j)*binomial(i, j)*GetSum(i - j, nj+1);
	return res;
}
Пример #12
0
size_t ex::nsymbols() const
{
	int res = 0;
	if (is_a<symbol>(*this)) {
		res=1;
	} else {
		for (size_t i=0; i < nops(); i++)
			res += op(i).nsymbols();
	}
	return res;
}
Пример #13
0
/** Test for occurrence of a pattern.  An object 'has' a pattern if it matches
 *  the pattern itself or one of the children 'has' it.  As a consequence
 *  (according to the definition of children) given e=x+y+z, e.has(x) is true
 *  but e.has(x+y) is false. */
bool basic::has(const ex & pattern, unsigned options) const
{
    exmap repl_lst;
    if (match(pattern, repl_lst))
        return true;
    for (size_t i=0; i<nops(); i++)
        if (op(i).has(pattern, options))
            return true;

    return false;
}
Пример #14
0
/** Find all occurrences of a pattern. The found matches are appended to
 *  the "found" list. If the expression itself matches the pattern, the
 *  children are not further examined. This function returns true when any
 *  matches were found. */
bool ex::find(const ex & pattern, exset& found) const
{
	if (match(pattern)) {
		found.insert(*this);
		return true;
	}
	bool any_found = false;
	for (size_t i=0; i<nops(); i++)
		if (op(i).find(pattern, found))
			any_found = true;
	return any_found;
}
Пример #15
0
/** Find all occurrences of a pattern. The found matches are appended to
 *  the "found" list. If the expression itself matches the pattern, the
 *  children are not further examined. This function returns true when any
 *  matches were found. */
bool ex::find(const ex & pattern, lst & found) const
{
	if (match(pattern)) {
		found.append(*this);
		found.sort();
		found.unique();
		return true;
	}
	bool any_found = false;
	for (size_t i=0; i<nops(); i++)
		if (op(i).find(pattern, found))
			any_found = true;
	return any_found;
}
Пример #16
0
/** Evaluate object numerically. */
ex basic::evalf(int level) const
{
    if (nops() == 0)
        return *this;
    else {
        if (level == 1)
            return *this;
        else if (level == -max_recursion_level)
            throw(std::runtime_error("max recursion level reached"));
        else {
            evalf_map_function map_evalf(level - 1);
            return map(map_evalf);
        }
    }
}
Пример #17
0
/** Compute the hash value of an object and if it makes sense to store it in
 *  the objects status_flags, do so.  The method inherited from class basic
 *  computes a hash value based on the type and hash values of possible
 *  members.  For this reason it is well suited for container classes but
 *  atomic classes should override this implementation because otherwise they
 *  would all end up with the same hashvalue. */
unsigned basic::calchash() const
{
    unsigned v = make_hash_seed(typeid(*this));
    for (size_t i=0; i<nops(); i++) {
        v = rotate_left(v);
        v ^= this->op(i).gethash();
    }

    // store calculated hash value only if object is already evaluated
    if (flags & status_flags::evaluated) {
        setflag(status_flags::hash_calculated);
        hashvalue = v;
    }

    return v;
}
Пример #18
0
/** Construct new expression by applying the specified function to all
 *  sub-expressions (one level only, not recursively). */
ex basic::map(map_function & f) const
{
    size_t num = nops();
    if (num == 0)
        return *this;

    basic *copy = NULL;
    for (size_t i=0; i<num; i++) {
        const ex & o = op(i);
        const ex & n = f(o);
        if (!are_ex_trivially_equal(o, n)) {
            if (copy == NULL)
                copy = duplicate();
            copy->let_op(i) = n;
        }
    }

    if (copy) {
        copy->setflag(status_flags::dynallocated);
        copy->clearflag(status_flags::hash_calculated | status_flags::expanded);
        return *copy;
    } else
        return *this;
}
Пример #19
0
/** Check whether the expression matches a given pattern. For every wildcard
 *  object in the pattern, a pair with the wildcard as a key and matching
 *  expression as a value is added to repl_lst. */
bool basic::match(const ex & pattern, exmap& repl_lst) const
{
    /*
    	Sweet sweet shapes, sweet sweet shapes,
    	That's the key thing, right right.
    	Feed feed face, feed feed shapes,
    	But who is the king tonight?
    	Who is the king tonight?
    	Pattern is the thing, the key thing-a-ling,
    	But who is the king of Pattern?
    	But who is the king, the king thing-a-ling,
    	Who is the king of Pattern?
    	Bog is the king, the king thing-a-ling,
    	Bog is the king of Pattern.
    	Ba bu-bu-bu-bu bu-bu-bu-bu-bu-bu bu-bu
    	Bog is the king of Pattern.
    */

    if (is_exactly_a<wildcard>(pattern)) {

        // Wildcard matches anything, but check whether we already have found
        // a match for that wildcard first (if so, the earlier match must be
        // the same expression)
        for (exmap::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
            if (it->first.is_equal(pattern))
                return is_equal(ex_to<basic>(it->second));
        }
        repl_lst[pattern] = *this;
        return true;

    } else {

        // Expression must be of the same type as the pattern
        if (typeid(*this) != typeid(ex_to<basic>(pattern)))
            return false;

        // Number of subexpressions must match
        if (nops() != pattern.nops())
            return false;

        // No subexpressions? Then just compare the objects (there can't be
        // wildcards in the pattern)
        if (nops() == 0)
            return is_equal_same_type(ex_to<basic>(pattern));

        // Check whether attributes that are not subexpressions match
        if (!match_same_type(ex_to<basic>(pattern)))
            return false;

        // Even if the expression does not match the pattern, some of
        // its subexpressions could match it. For example, x^5*y^(-1)
        // does not match the pattern $0^5, but its subexpression x^5
        // does. So, save repl_lst in order to not add bogus entries.
        exmap tmp_repl = repl_lst;
        // Otherwise the subexpressions must match one-to-one
        for (size_t i=0; i<nops(); i++)
            if (!op(i).match(pattern.op(i), tmp_repl))
                return false;

        // Looks similar enough, match found
        repl_lst = tmp_repl;
        return true;
    }
}