[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

*To*: fontinst list <fontinst@cogs.susx.ac.uk>*Subject*: Extended syntax for integer expressions*From*: Lars Hellström <Lars.Hellstrom@math.umu.se>*Date*: Thu, 3 Dec 1998 18:22:18 +0100 (MET)

I do not know how it is for fontinst users in general, but I sometimes find fontinst's syntax for integer expressions a little annoying. It is not that I cannot use it and it is certainly not that I find it inefficient, but I do often have trouble reading the expressions I have written because there are simply too many braces! If my text editor didn't have a "balance" command, I would often be in serious trouble. Thus I began to consider the question of whether one could implement the operations so that they are written between the operands (infix notation) instead of before (prefix notation). It turned out that it wasn't really that hard, so I made the necessary adjustments to my own fontinst, so that I now have the following syntax for an <INTEGER EXPRESSION>: <INTEGER EXPRESSION> is <TERM> or <INTEGER EXPRESSION> \+ <TERM> or <INTEGER EXPRESSION> \- <TERM> <TERM> is <FACTOR> or <TERM> \* <FACTOR> or <TERM> \/ <FACTOR> or <TERM> \% <FACTOR> <FACTOR> is <ANY TeX NUMBER> or \int{<NAME>} or \width{<GLYPH>} or \heigth{<GLYPH>} or \depth{<GLYPH>} or \italic{<GLYPH>} or \kerning{<LEFT>}{<RIGHT>} or \neg{<INTEGER EXPRESSION>} or \add{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \sub{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \mul{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \div{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \scale{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \max{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \min{<INTEGER EXPRESSION>}{<INTEGER EXPRESSION>} or \( <INTEGER EXPRESSION> \) (`is' separates the <...>-quantity being defined from its definition. `or' separates two alternative definitions.) In particular, observe that any standard integer expression will fit these rules, so any old integer expression retains its meaning. The \+, \-, \*, \/, and \% control sequences acts as the addition, subtraction, multiplication, division, and scaling operations respectively---they differ from the \add, \sub, \mul, \div, and \scale operations only in their syntax, not in what they compute. The \( and \) control sequences work as left and right parenthesis respectively, making it possible to change the order in which the operations are performed. A few examples of these extended integer expressions and what they evaluate to: 1\+2\*3 evaluates to 7 1\+2\*\add{3}{4} evaluates to 15 5\+4\*\sub{3}{2\-1} evaluates to 13 ( = 5+4*(3-(2-1)) ) 1\+2\*\(3\+4\*5\) evaluates to 47 ( = 1+2*(3+4*5) ) But why have I written to the fontinst list about this? Simply because I think that this extension of the syntax for integer expressions may be of interest to fontinst users in general and not only to me. It might even be included in the next release of fontinst, it Ulrik so permits. There is however one problem with this extension: It slows down the computation of integer expressions. Since fontinst is already a pretty slow program, I would not be surprised if changes in its more central parts that make it even slower are not appreciated. It therefore seems most natural to me that whether or not fontinst should be equipped for the above extended syntax for integer expressions is decided through a general debate on the subject in the fontinst list. I hereby invite to such a debate. I have made some experiments trying to determine how much slower fontinst becomes from the overhead of handling infix operations, using the latin.mtx and t1.etx from v1.801 fontinst. These experiments indicated that the slackening of the speed was in the order of 1% (but other people's measurements would be highly welcome as I have come to be somewhat sceptical to how precise the "time taken" reports of my TeX really are). It should also be observed that these measurements were for code that used prefix operations (\add,\sub,etc.) throughout and that it should be possible to get back some of the time lost by using infix operations (\+,\-,etc.) instead, as the implementation is made primarily for these. The implementation follows below. Any suggestions on how it can be improved (in particular, how it can be sped up) are of course of interest. The main idea is that the control sequences \calculate_b and \calculate_c are used to hold the commands to perform an operation which could not be performed just yet due to that one of the operands has not yet been computed. Therefore \calculate_c is performed after every <TERM> to take care of any delayed \*, \/, or \% and \calculate_b is performed after every <INTEGER EXPRESSION> to take care of any delayed \+ or \-. \calculate_b may act on \b_count (hence its name) and \result. \calculate_c may act on \c_count and \result. \def\eval_expr#1{ \begingroup \restore_calc_b\restore_calc_c \global\result=#1\relax \calculate_c\calculate_b \endgroup } \def\restore_calc_b{\let\calculate_b\relax} \def\restore_calc_c{\let\calculate_c\relax} \restore_calc_b\restore_calc_c \def\({0\bgroup \restore_calc_b\restore_calc_c \global\result=} \def\){\relax \calculate_c\calculate_b \egroup} \def\+{ \relax \calculate_c\calculate_b \b_count=\result \def\calculate_b{\do_add\restore_calc_b} \global\result= } \def\do_add{\global\advance \result \b_count} \def\-{ \relax \calculate_c\calculate_b \b_count=\result \def\calculate_b{\do_sub\restore_calc_b} \global\result= } \def\do_sub{\advance \b_count -\result \global\result=\b_count} \def\*{ \relax \calculate_c \c_count=\result \def\calculate_c{\do_mul\restore_calc_c} \global\result= } \def\do_mul{\global\multiply \result \c_count} \def\/{ \relax \calculate_c \c_count=\result \def\calculate_c{\do_div\restore_calc_c} \global\result= } \def\do_div{\divide \c_count \result \global\result=\c_count} \def\%{ \relax \calculate_c \c_count=\result \def\calculate_c{\do_scale\restore_calc_c} \global\result= } \def\do_scale{ \global\multiply \result \c_count \global\divide \result \one_thousand } \def\neg#1{\result \eval_expr{#1} \global\result=-\result } \def\add#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \global\advance\result by \a_count } \def\sub#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \advance\a_count by -\result \global\result=\a_count } \def\mul#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \global\multiply\result by \a_count } \def\div#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \divide\a_count by \result \global\result=\a_count } \def\max#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \ifnum\a_count>\result \global\result=\a_count \fi } \def\min#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \ifnum\a_count<\result \global\result=\a_count \fi } \def\scale#1#2{\result \eval_expr{#1} \a_count=\result \eval_expr{#2} \global\multiply\result by \a_count \global\divide\result by \one_thousand } Feature: If you fail to match \( and \) properly, TeX will give you an error message about mismatched groups. TeX's automatic insertion/deletion of tokens will however be the right thing to do to keep your groups properly nested, so you can always continue just by pressing return/enter. Lars Hellström

- Prev by Date:
**Re: Misplaced code** - Next by Date:
**Next fontinst version and code I once sent** - Prev by thread:
**Re: fontnames for Bitstream Univers** - Next by thread:
**Next fontinst version and code I once sent** - Index(es):