/usr/share/yacas/include/mathuserfunc.h is in yacas 1.3.3-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | #ifndef __mathuserfunc_h__
#define __mathuserfunc_h__
#include "yacasbase.h"
#include "lispuserfunc.h"
#include "grower.h"
#include "patternclass.h"
/// A mathematical function defined by several rules.
/// This is the basic class which implements functions in Yacas.
/// Evaluation is done by consulting a set of rewriting rules. The
/// body of the first rule that matches, is evaluated and this gives
/// the result of evaluating the function.
class BranchingUserFunction : public LispArityUserFunction
{
public:
/// Structure containing name of parameter and whether it is put on hold.
class BranchParameter : public YacasBase
{
public:
BranchParameter(LispString * aParameter = NULL, LispInt aHold=LispFalse)
: iParameter(aParameter), iHold(aHold) {}
LispString * iParameter;
LispInt iHold;
};
/// Abstract base class for rules.
class BranchRuleBase : public YacasBase
{
public:
virtual ~BranchRuleBase();
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments) = 0;
virtual LispInt Precedence() const = 0;
virtual LispPtr& Body() = 0;
};
/// A rule with a predicate.
/// This rule matches if the predicate evaluates to #LispTrue.
class BranchRule : public BranchRuleBase
{
public:
virtual ~BranchRule();
BranchRule(LispInt aPrecedence,LispPtr& aPredicate,LispPtr& aBody) : iPrecedence(aPrecedence),iBody(aBody),iPredicate(aPredicate)
{
}
/// Return true if the rule matches.
/// #iPredicate is evaluated in \a Environment. If the result
/// IsTrue(), this function returns true.
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments);
/// Access #iPrecedence.
virtual LispInt Precedence() const;
/// Access #iBody.
virtual LispPtr& Body();
protected:
BranchRule() : iPrecedence(0),iBody(),iPredicate() {};
protected:
LispInt iPrecedence;
LispPtr iBody;
LispPtr iPredicate;
};
/// A rule that always matches.
class BranchRuleTruePredicate : public BranchRule
{
public:
BranchRuleTruePredicate(LispInt aPrecedence,LispPtr& aBody)
{
iPrecedence = aPrecedence;
iBody = (aBody);
}
/// Return #LispTrue, always.
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments);
};
/// A rule which matches if the corresponding PatternClass matches.
class BranchPattern : public BranchRuleBase
{
public:
/// Destructor.
/// This function contains no code.
virtual ~BranchPattern();
/// Constructor.
/// \param aPrecedence precedence of the rule
/// \param aPredicate generic object of type \c Pattern
/// \param aBody body of the rule
BranchPattern(LispInt aPrecedence,LispPtr& aPredicate,LispPtr& aBody) : iPrecedence(aPrecedence),iBody(aBody),iPredicate(aPredicate),iPatternClass(NULL)
{
GenericClass *gen = aPredicate->Generic();
DYNCAST(PatternClass,"\"Pattern\"",pat,gen)
Check(pat,KLispErrInvalidArg);
iPatternClass = pat;
}
/// Return true if the corresponding pattern matches.
virtual LispBoolean Matches(LispEnvironment& aEnvironment, LispPtr* aArguments);
/// Access #iPrecedence
virtual LispInt Precedence() const;
/// Access #iBody
virtual LispPtr& Body();
private:
BranchPattern(const BranchPattern& aOther) : iPrecedence(0),iBody(),iPredicate(),iPatternClass(NULL)
{
// copy constructor not written yet, hence the assert
LISPASSERT(0);
}
BranchPattern& operator=(const BranchPattern& aOther)
{
// copy constructor not written yet, hence the assert
LISPASSERT(0);
return *this;
}
protected:
/// The precedence of this rule.
LispInt iPrecedence;
/// The body of this rule.
LispPtr iBody;
/// Generic object of type \c Pattern containing #iPatternClass
LispPtr iPredicate;
/// The pattern that decides whether this rule matches.
PatternClass *iPatternClass;
};
/// Constructor.
/// \param aParameters linked list constaining the names of the arguments
///
/// #iParamList and #iParameters are set from \a aParameters.
BranchingUserFunction(LispPtr& aParameters);
/// Destructor.
/// There is no code inside this function.
virtual ~BranchingUserFunction();
/// Evaluate the function on given arguments.
/// \param aResult (on output) the result of the evaluation
/// \param aEnvironment the underlying Lisp environment
/// \param aArguments the arguments to the function
///
/// First, all arguments are evaluated by the evaluator associated
/// to \a aEnvironment, unless the \c iHold flag of the
/// corresponding parameter is true. Then a new LispLocalFrame is
/// constructed, in which the actual arguments are assigned to the
/// names of the formal arguments, as stored in \c iParameter. Then
/// all rules in #iRules are tried one by one. The body of the
/// first rule that matches is evaluated, and the result is put in
/// \a aResult. If no rule matches, \a aResult will recieve a new
/// expression with evaluated arguments.
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
/// Put an argument on hold.
/// \param aVariable name of argument to put un hold
///
/// The \c iHold flag of the corresponding argument is set. This
/// implies that this argument is not evaluated by Evaluate().
virtual void HoldArgument(LispString * aVariable);
/// Return true if the arity of the function equals \a aArity.
virtual LispInt IsArity(LispInt aArity) const;
/// Return the arity (number of arguments) of the function.
LispInt Arity() const;
/// Add a BranchRule to the list of rules.
/// \sa InsertRule()
virtual void DeclareRule(LispInt aPrecedence, LispPtr& aPredicate, LispPtr& aBody);
/// Add a BranchRuleTruePredicate to the list of rules.
/// \sa InsertRule()
virtual void DeclareRule(LispInt aPrecedence, LispPtr& aBody);
/// Add a BranchPattern to the list of rules.
/// \sa InsertRule()
void DeclarePattern(LispInt aPrecedence, LispPtr& aPredicate, LispPtr& aBody);
/// Insert any BranchRuleBase object in the list of rules.
/// This function does the real work for DeclareRule() and
/// DeclarePattern(): it inserts the rule in #iRules, while
/// keeping it sorted. The algorithm is \f$O(\log n)\f$, where
/// \f$n\f$ denotes the number of rules.
void InsertRule(LispInt aPrecedence,BranchRuleBase* newRule);
/// Return the argument list, stored in #iParamList
virtual LispPtr& ArgList();
protected:
/// List of arguments, with corresponding \c iHold property.
CArrayGrower<BranchParameter, ArrOpsPOD<BranchParameter> > iParameters;
/// List of rules, sorted on precedence.
CDeletingArrayGrower<BranchRuleBase*, ArrOpsDeletingPtr<BranchRuleBase> > iRules;
/// List of arguments
LispPtr iParamList;
};
class ListedBranchingUserFunction : public BranchingUserFunction
{
public:
ListedBranchingUserFunction(LispPtr& aParameters);
virtual LispInt IsArity(LispInt aArity) const;
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
};
class MacroUserFunction : public BranchingUserFunction
{
public:
MacroUserFunction(LispPtr& aParameters);
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
};
class ListedMacroUserFunction : public MacroUserFunction
{
public:
ListedMacroUserFunction(LispPtr& aParameters);
virtual LispInt IsArity(LispInt aArity) const;
virtual void Evaluate(LispPtr& aResult,LispEnvironment& aEnvironment, LispPtr& aArguments);
};
#endif
|