Annotation of Examples/AppKit/Graph/Expression.h, revision 1.1

1.1     ! root        1: 
        !             2: #import <objc/Object.h>
        !             3: #import <objc/hashtable.h>
        !             4: #import <appkit/errors.h>
        !             5: 
        !             6:  /*
        !             7:   * An Expression object parses and evaluates the text of a mathematical
        !             8:   * expression.  The expression text may contain numbers, variables,
        !             9:   * arithmetic operations and program defined functions.  For example,
        !            10:   * an Expression object can parse the string "a+b*c", and if told
        !            11:   * values for a, b and c, can calculate the value of the expression.
        !            12:   *
        !            13:   * This ability to parse and evaluate expressions at runtime makes it
        !            14:   * easy for simple mathmatical programs to move beyond having canned example
        !            15:   * functions compiled into their executables, and instead allow the user
        !            16:   * to enter novel equations.  New formulas can be tried without recompiling
        !            17:   * the application.
        !            18:   * 
        !            19:   * Typically an Expression is created and then told to parse some text
        !            20:   * entered by the user.  The result of the parse is a parse tree, which is
        !            21:   * then used by the Expression to evaluate the expression, given a set
        !            22:   * of values for the expression's variables.  Variables can have either a
        !            23:   * single value, or can be made to take on a series of values ("vector
        !            24:   * variables").  For example, if you were graphing "A*x^2", you might
        !            25:   * make A have a single value, but let x run over a range of
        !            26:   * values that you would like to plot.
        !            27:   *
        !            28:   * The values of these vector variables can be set in two ways.  In the
        !            29:   * first way, a list of values is passed in using the setVar:vector:numVals: 
        !            30:   * method.  In the second way, the variable is given a range for its
        !            31:   * values with the setVar:min:max: method.  The actual values are then
        !            32:   * interpolated within that range.  The resolution of the expression
        !            33:   * determines how many values are calculated.  If you mix these two styles
        !            34:   * of vector variables, you must ensure that the number of explicitly
        !            35:   * set values assigned to any variables matches the resolution of the
        !            36:   * Expression.
        !            37:   *
        !            38:   * If there are more than one range-style vector variables in an Expression
        !            39:   * they may be interpolated together or orthogonally, creating
        !            40:   * multi-dimensional domains.  You can set the total number of dimensions over
        !            41:   * which the expression is evaluated, and then set the dimension of each
        !            42:   * vector variable that is being interpolated.
        !            43:   *
        !            44:   * Expressions always operate lazily, meaning that results are never
        !            45:   * calculated until they are needed (usually when result values are asked
        !            46:   * for). This means just changing the values of variables is inexpensive.
        !            47:   *
        !            48:   * Expressions have methods which allow an application to enumerate the
        !            49:   * names of all the variables found by the parse.  This can be used to verify
        !            50:   * that the expression is valid, beyond whether it was parsable.  For
        !            51:   * example, in a certain context there may be a fixed set of variable names
        !            52:   * that may be used.  After a successful parse, the application can run
        !            53:   * through the names of all variables found, and ensure that they are all
        !            54:   * appropriate.
        !            55:   *
        !            56:   * Expressions understand the arithmetic operators +, -, *, /.  % is used
        !            57:   * for modulus (as in C) and ^ means is used to raise a quantity to a power.
        !            58:   * Parentheses can be used for grouping.
        !            59:   *
        !            60:   * Expressions have certain "built in" functions (e.g., sin()) that are
        !            61:   * understood.  It is also possible for applications to extend this default
        !            62:   * set of functions.  New functions are registered with the name of the
        !            63:   * function, the allowable number of arguments (can be variable), and a C
        !            64:   * procedure to call to perform the evaluation.  The built in functions are:
        !            65:   *
        !            66:   *    sin(x), cos(x), tan(x)          - elementary trig
        !            67:   *    asin(x), acos(x), atan(x)       - inverse elementary trig
        !            68:   *    exp(x), ln(x)                   - exponential and natural log
        !            69:   *    sqrt(x)                         - square root
        !            70:   *
        !            71:   * The constants "pi" and "e" are also built in.
        !            72:   */
        !            73: 
        !            74: /* function supplied by term implementor for evaluation */
        !            75: typedef float EXPTermEvalFunc(int numArgs, float *args);
        !            76: 
        !            77: /* enumeration state used to loop through all the variable names */
        !            78: typedef void *EXPEnumState;
        !            79: 
        !            80: /* private type for representing terms */
        !            81: typedef struct _EXPTerm *EXPTermPtr;
        !            82: 
        !            83: @interface Expression : Object {
        !            84:     char *text;                        /* text of the expression */
        !            85:     NXHashTable *varTerms;     /* terms of variables */
        !            86:     EXPTermPtr parseTree;      /* terms from the parse */
        !            87:     NXHashTable *validFuncs;   /* functions we know how to evaluate */
        !            88:     int resolution;            /* number of points to calc for range vars */
        !            89:     BOOL resultsValid;         /* are the results up to date? */
        !            90:     short dimensions;          /* #axes of evaluation, defaults to 1 */
        !            91:     float *results;            /* results of evaluation */
        !            92:     float resultsMin;          /* min of all results */
        !            93:     float resultsMax;          /* max of all results */
        !            94: }
        !            95: 
        !            96: - init;
        !            97:  /*
        !            98:   * Initialize an Expression that was just created via "allocFromZone:".  You
        !            99:   * cannot use a "+new" method to create Expression objects.  Below are some
        !           100:   * examples of creating Expressions.  The first expression goes in the 
        !           101:   * default malloc zone, the second is allocated in the same zone as
        !           102:   * otherObject.
        !           103:   *
        !           104:   *    id myExp1, myExp2;
        !           105:   *    myExp1 = [[Expression alloc] init];
        !           106:   *    myExp2 = [[Expression allocFromZone:[otherObject zone]] init];
        !           107:   *
        !           108:   */
        !           109: 
        !           110: - free;
        !           111:  /*
        !           112:   * Frees the Expression, including any array of results returned by
        !           113:   * the resultsVector:numVals: method.
        !           114:   */
        !           115: 
        !           116: - (BOOL)parse:(const char *)expressionString;
        !           117:  /*
        !           118:   * Parses the text of an expression.  A parse tree of terms is built up as
        !           119:   * a result of parsing expressionString.  The method returns whether the
        !           120:   * string was a legal expression.  expressionString is copied and retained
        !           121:   * within the Expression.
        !           122:   */
        !           123: 
        !           124: - (const char *)text;
        !           125:  /*
        !           126:   * Returns the last text parsed by the Expression.
        !           127:   */
        !           128: 
        !           129: - setResolution:(int)count;
        !           130:  /*
        !           131:   * Sets the resolution at which variables with a min and max range will
        !           132:   * be subdivided.  All vectors in the Expression must have the same
        !           133:   * number of values, which must be equal to the resolution of the
        !           134:   * Expression, at the time the Expression is evaluated.  Note that setting
        !           135:   * the list of values of a vector variable also changes the Expression's
        !           136:   * resolution.
        !           137:   */
        !           138: 
        !           139: - (int)resolution;
        !           140:  /*
        !           141:   * Returns the resolution of the Expression.
        !           142:   */
        !           143: 
        !           144: - setVar:(const char *)varName value:(float)val;
        !           145:  /*
        !           146:   * Sets the value of the variable named varName to val.  The variable
        !           147:   * will have that value as a constant throughout subsequent evaluations.
        !           148:   */
        !           149: 
        !           150: - (float)varValue:(const char *)varName;
        !           151:  /*
        !           152:   * Returns the value of the variable varName.  If the variable is being
        !           153:   * used as a vector, then its first value is returned.
        !           154:   */
        !           155: 
        !           156: - setVar:(const char *)varName vector:(float *)vals numVals:(int)count;
        !           157:  /*
        !           158:   * Sets the values of the variable named varName to be the array
        !           159:   * vals.  Count is the number of values in the vector.  This method
        !           160:   * also sets the resolution of the Expression to be count.
        !           161:   * All vectors in the Expression must have the same number of values,
        !           162:   * which must be equal to the resolution of the Expression, at the
        !           163:   * time the Expression is evaluated.  The list of vals should be a block
        !           164:   * of floats returned from malloc.  It is NOT copied, but will be freed by
        !           165:   * the Expression as part of its own free method.
        !           166:   */
        !           167: 
        !           168: - varVector:(const char *)varName vector:(float **)vals numVals:(int *)count;
        !           169:  /*
        !           170:   * Returns the vector of values of the variable varName by setting
        !           171:   * vals to point to the vector.  Count is set to the number of values.
        !           172:   */
        !           173: 
        !           174: - setVar:(const char *)varName min:(float)minVal max:(float)maxVal;
        !           175:  /*
        !           176:   * Sets the range of the variable varName to run from minVal to maxVal.
        !           177:   * The variables values will be determined by interpolating points
        !           178:   * within this range.  The resolution of the Expression determines the
        !           179:   * number of points that are taken within the range.
        !           180:   */
        !           181: 
        !           182: - setVar:(const char *)varName dimension:(short)dimensionNum;
        !           183:  /*
        !           184:   * Sets the dimension within which the variable will vary.  The given value
        !           185:   * must be between 0 and [expression dimensions]-1.
        !           186:   */
        !           187: 
        !           188: - var:(const char *)varName dimension:(short *)dimensionNum;
        !           189:  /*
        !           190:   * Returns the dimension within which the variable will vary.
        !           191:   */
        !           192: 
        !           193: - var:(const char *)varName min:(float *)minVal max:(float *)maxVal;
        !           194:  /*
        !           195:   * Returns the smallest and largest value of the variable varName by setting
        !           196:   * minVal and maxVal.
        !           197:   */
        !           198: 
        !           199: - (float)resultValue;
        !           200:  /*
        !           201:   * Returns the value of the Expression when evaluated with its current
        !           202:   * attributes.  If there are vector variables in the Expression, it
        !           203:   * returns the result using the first value of all vectors.
        !           204:   */
        !           205: 
        !           206: - resultsVector:(float **)vals numVals:(int *)count;
        !           207:  /*
        !           208:   * Returns the values of the Expression when evaluated with its current
        !           209:   * attributes, by setting vals to point to the vector of results.  count
        !           210:   * is set to the number of results.  The number of results returned will be
        !           211:   * resolution^dimensions.  If there are no vector variables in the
        !           212:   * Expression, a single result is returned.
        !           213:   */
        !           214: 
        !           215: - resultsMin:(float *)minVal max:(float *)maxVal;
        !           216:  /*
        !           217:   * Returns the smallest and largest value of the results by setting
        !           218:   * minVal and maxVal.
        !           219:   */
        !           220: 
        !           221: - setDimensions:(short)count;
        !           222:  /*
        !           223:   * Sets the number of evaluation dimensions.  The number of values in the
        !           224:   * results vector is resolution^dimensions.  A given variable varies in one
        !           225:   * dimension, as set by setVar:dimension:.
        !           226:   */
        !           227: 
        !           228: - (short)dimensions;
        !           229:  /*
        !           230:   * Returns the number of evaluation dimensions.
        !           231:   */
        !           232: 
        !           233: - (EXPEnumState)beginVariableEnumeration;
        !           234: - (const char *)nextVariable:(EXPEnumState)state;
        !           235: - (void)endVariableEnumeration:(EXPEnumState)state;
        !           236:  /*
        !           237:   * Used to walk through the names of all variables parsed.  Example:
        !           238:   *    EXPEnumState state = [myExp beginVariableEnumeration];
        !           239:   *    const char *varName;
        !           240:   *    while (varName = [myExp nextVariable:state])
        !           241:   *        printf("A variable named %s was parsed.\n", varName);
        !           242:   *    [myExp endVariableEnumeration:state];
        !           243:   */
        !           244: 
        !           245: - addFuncTerm:(const char *)name minArgs:(int)min maxArgs:(int)max
        !           246:                                        evalFunc:(EXPTermEvalFunc *)func;
        !           247:  /*
        !           248:   * Adds a function to the set of functions this Expression can parse.
        !           249:   * Functions look like "name(arg1, arg2,...)" in the text that is
        !           250:   * parsed.  At evaluation time the C function func() will be called with
        !           251:   * the values of the arguments.  The arguments are passed in an array of
        !           252:   * floats(see the EXPTermEvalFunc typedef above).  Func must return the value
        !           253:   * of the function with those arguments. min and max determine how many
        !           254:   * arguments the function can accept.  For example, min=1, max=1 means
        !           255:   * the function takes one argument.  A max value of -1 means an unbounded
        !           256:   * number of arguments is allowed.
        !           257:   */
        !           258: 
        !           259: - removeFuncTerm:(const char *)name;
        !           260:  /*
        !           261:   * Removes a function from the set of functions this Expression can parse.
        !           262:   * Be careful not to send this to an Expression that has already parsed
        !           263:   * text which made use of this function, since a reference to this FuncTerm
        !           264:   * will be left dangling in the parse tree.
        !           265:   */
        !           266: 
        !           267: @end
        !           268: 
        !           269: /* Error codes we raise */
        !           270: 
        !           271: typedef enum {
        !           272:     expErrInvalidVarName = NX_APPBASE + 10000,
        !           273:       /* An argument was passed referring to a variable whose name did not exist in the expression parsed. */
        !           274:     expErrInvalidVarType,
        !           275:       /* A variable was used in a way inconsistent with its type. */
        !           276:     expErrMinMax,
        !           277:       /* A min parameter was not less that its accompanying max parameter. */
        !           278:     expErrNoText,
        !           279:       /* A method could not complete because no expression had been parsed. */
        !           280:     expErrResolutionMismatch,
        !           281:       /* The number of points in the vector terms and the resolution of the Expression are inconsistent. */
        !           282:     expFuncTypeInUse,
        !           283:       /* A message was sent attempting to add a function which has already been declared. */
        !           284:     expInvalidDimension
        !           285:       /* A invalid value for a var's dimension was passed. */
        !           286: } EXPError;
        !           287: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.