home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 600-699 / ff695.lha / ICalc / Docs / AdvancedGuide next >
Text File  |  1992-07-13  |  16KB  |  549 lines

  1. =============================================================================
  2.  
  3.     icalc - a complex-number expression parser
  4.  
  5.     by Martin W Scott
  6.  
  7.     Version 2.0
  8.  
  9. =============================================================================
  10.  
  11.     Advanced Guide
  12.  
  13. =============================================================================
  14.  
  15. This document describes the more advanced features of icalc, including
  16. programming constructs and array manipulation, as well as some information
  17. that was left out of the User Guide for clarity and continuity.
  18.  
  19. The syntax used in icalc is closely related to that of C, with many
  20. exceptions. Information/warnings specifically for people who are familiar
  21. with C will be indicated by lines prefixed with 'C:'.
  22.  
  23. Parentheses and braces will sometimes be used in examples where they don't
  24. strictly need to be, due to operator precedence rules. They are included for
  25. clarity. (NB: A table detailing relative precedences is in Appendix 1 of
  26. the User Guide.)
  27.  
  28.  
  29.  
  30. Principal value ranges (PVRs)
  31. -----------------------------
  32. The PVRs are defined for the inverse trigonometric functions as follows:
  33.  
  34.     asin:    if u + iv = asin(z), then
  35.         -PI/2 <= u <= PI/2    if v >= 0
  36.         -PI/2  < u  < PI/2    if v < 0
  37.  
  38.     acos:    if u + iv = acos(z), then
  39.         0 <= u <= PI    if v >= 0
  40.         0  < u  < PI    if v < 0
  41.  
  42.     atan:    if u + iv = atan(z), then
  43.         -PI/2 < u < PI/2    
  44.  
  45.  
  46.  
  47. Additional assignment operators
  48. -------------------------------
  49. As well as the standard = operator, icalc comes with some others both to
  50. improve readability and efficiency of functions. They are:
  51.  
  52.     a += b        equivalent to    a = a+b
  53.     a -= b        equivalent to    a = a-b
  54.     a *= b        equivalent to    a = a*b
  55.     a /= b        equivalent to    a = a/b
  56.  
  57. It is faster to use these operators rather than the explicit operations.
  58.  
  59. C: The ++ and -- operators are not included, since the evaluation method
  60. C: cannot handle pre- and post- operations rigorously.
  61.  
  62.  
  63.  
  64. Relational operators
  65. --------------------
  66. These operators allow comparisons between two values. Of course, the set of
  67. complex numbers has no logical ordering; all relational comparisons are
  68. done with real parts only, but equivalence comparisons are done on both
  69. real and imaginary parts. This system allows for people who are writing
  70. real-number applications to once again completely ignore complex numbers. 
  71. To use relational operators on imaginary parts, you must use Im().
  72.  
  73. Relational operators are used in BOOLEAN expressions; these expressions can
  74. take one of two values: TRUE (1.0) and FALSE (0.0). In the table below, a and
  75. b represent numerical expressions, and E and F represent boolean expressions.
  76.  
  77.  
  78.    BOOLEAN EXPRESSION        TRUE if and only if
  79.  
  80.     a == b            a has same value as b 
  81.     a != b            a has different value to b
  82.     a > b            value of a greater than that of b
  83.     a >= b            value of a greater than or equal to that of b
  84.     a < b            value of a less than that of b
  85.     a <= b            value of a less than or equal to that of b
  86.  
  87.     E && F            E is TRUE and F is TRUE
  88.     E || F            E is TRUE or F is TRUE
  89.  
  90. Examples:
  91.  
  92.     5 > 3            TRUE
  93.     2 != 2            FALSE
  94.     2 + 10i >= 20 + i    FALSE  (imaginary parts are ignored)
  95.     3 > 2i            TRUE   (2i has real part 0.0)
  96.     -3 > 2i            FALSE
  97.  
  98. and as always, consider rounding errors when comparing:
  99.  
  100.     PI == atan(1)*4        FALSE
  101.  
  102.  
  103. The logical operators && and || use short-circuit evaluation. This means
  104. that they only evaluate their right-hand argument if the result of the
  105. operation is still undetermined. An example will clarify.
  106.  
  107.     (5 > 3) && (6 < 8)    Needs to evaluate E and F
  108.        E          F
  109.  
  110.     (5 > 8) && (6 < 8)    E evaluates to FALSE, so expression is false,
  111.        E          F        and so F is not evaluated.
  112.  
  113. This has some important implications, for example if (boolean) expression F
  114. contained an assignment expression, then it might not be evaluated
  115. depending on expression E.
  116.  
  117. I have found that short-circuit evaluation is the most convenient way of
  118. handling && and ||. Some languages don't guarantee even order of evaluation
  119. (e.g. Pascal) and this can sometimes create harder to read programs.
  120.  
  121. One other operator is present in icalc, as a shorthand for if-then-else
  122. statements, the ternary operator, '?:'. This has the form
  123.  
  124.     E ? a : b
  125.  
  126. and reads as "if E is true then the value of the ternary operator is a,
  127. otherwise it's b". Only one of a or b is evaluated. An example will clarify:
  128.  
  129.     (x >= 2) ? (x -= 1) : (x = 100)
  130.  
  131. means "If x is greater than 2, then subtract one from x, otherwise assign the
  132. value 100 to x".
  133.  
  134. Numerical expressions can stand in for boolean expressions. A numerical
  135. expression has boolean value TRUE if its real part is non-zero, and FALSE
  136. if it is zero.  So, for example, if x is purely real,
  137.  
  138.     y = (x ? 1 : 0)                    (*)
  139.  
  140. is equivalent to
  141.  
  142.     y = (x != 0 ? 1 : 0)                (**)
  143.  
  144. and assigns 1 to y if x is non-zero, and 0 to y if x is zero.
  145.  
  146. Do remember that imaginary parts are ignored in comparisons. In x were
  147. purely imaginary, (*) and (**) would assign 1 and 0 respectively to y (i.e.
  148. they would behave differently).
  149.  
  150.  
  151.  
  152. Arrays 
  153. ------
  154. icalc has simple one-dimensional arrays, which can only be declared outside
  155. function definitions. Array elements are referenced using square brackets,
  156. and the first element has index 1.
  157.  
  158. C: This is in contrast to C, where indices start at zero. The System used in
  159. C: icalc is more suited to many mathematical applications, although I may
  160. C: add a facility to choose starting index in future.
  161.  
  162. To create an array a, use the statement
  163.  
  164.     array a[dimension]    # creates cleared array
  165.  
  166. The dimension should be a positive integer. It may be an expression, which
  167. will have its imaginary part discarded, and rounded DOWN to an integer.
  168. All elements initially hold the value zero.  You may optionally pre-assign
  169. the array at creation by using
  170.  
  171.     array a[dimension] = { expr1, expr2, ... exprP }
  172.  
  173. This second form allows pre-initialization of elements 1 to P;
  174. P must be <= dimension (so can partially initialise array).
  175.  
  176. Arrays are referenced by a[expr], the index being calculated as the
  177. real part of <expr> rounded down to an integer (ie. floor(Re(expr))).
  178.  
  179. Range checking is performed, and user will be informed of invalid array
  180. references. 
  181.  
  182. As already mentioned, arrays must be created at the top level, ie. NOT in
  183. function definitions.  In this version, there are NO local (to function)
  184. arrays.
  185.  
  186. There are a few builtin functions to help you manuipulate arrays:
  187.  
  188.     sizeof(a)    returns number of elements in a,
  189.     resize(a,n)    resizes a to n elements,
  190.     display(a)    prints a list of elements in a.
  191.  
  192. The latter two return a value 1 by convention. If you resize() an array to
  193. make it larger, the new elements created will NOT be set to zero.
  194.  
  195. Here is a small example session to demonstrate some features:
  196.  
  197.     >  array a[3] = { 1, 2, 3 }
  198.     >  display(a)
  199.         a[1] =  1
  200.         a[2] =  2
  201.         a[3] =  3
  202.          1
  203.     >  a[2] = 12
  204.         12
  205.     >  a[3] < a[2] ? x = 3 : x = 2
  206.         3
  207.     >  sizeof(a)
  208.         3
  209.     >  resize(a,4)        # a[4] will contain garbage
  210.         1
  211.     >  a[4] = 4
  212.         4
  213.     >  display(a)
  214.         a[1] =  1 
  215.         a[2] =  12
  216.         a[3] =  3 
  217.         a[4] =  4 
  218.          1        
  219.     >  resize(a,2)
  220.         1
  221.     >  display(a)
  222.         a[1] =  1 
  223.         a[2] =  12
  224.  
  225.  
  226.  
  227. Blocks
  228. ------
  229. Blocks are a way to group expressions so they are treated as one big
  230. expression. They have the form
  231.  
  232.     { expr1; expr2; ... exprN; }
  233.  
  234. and the value of a block is the value of its last expression, exprN.  The
  235. expressions may also be separated by newlines (as many as you like)instead.
  236. Blocks can have as little as one expression, which is sometimes useful for
  237. easier-to-read source code.
  238. Examples:
  239.  
  240.     >  { a=3;b=2;a*b;}
  241.         6
  242.     >  {
  243.     >    a = 2
  244.     >    b = 3
  245.     >    c = 4; d = 5
  246.     >    a*b*c*d
  247.     >  }
  248.         120
  249.  
  250. Blocks are principally of use with control-flow constructs, and further
  251. (more useful) examples are given below.
  252.  
  253.  
  254.  
  255. Control-flow constructs
  256. -----------------------
  257. A number of control-flow constructs are available, closely modelled on those
  258. of the C language.
  259.  
  260. C: C is a free-form language, and spacing can appear anywhere in C source.
  261. C: icalc however, is free-form only per-line, due to its interactive nature;
  262. C: icalc must be able to determine when an expression stops, so that it knows
  263. C: when to print a result. Care should be taken to follow icalc's conventions.
  264.  
  265. Where newlines are shown, they are optional; where they are not shown, they
  266. are not permitted, and will either cause a syntax error, or incorrect
  267. behaviour. All horizontal spacing is optional, and used for clarity.
  268.  
  269. Below, Bexpr denotes a boolean expression, Texpr is the expression
  270. evaluated if Bexpr is TRUE, and Fexpr the expression evaluated if Bexpr is
  271. FALSE.
  272.  
  273. if-else
  274. -------
  275. A construct common to almost all programming languages is the if-statement.
  276. In icalc, it has the form
  277.  
  278.     if (Bexpr)
  279.         Texpr
  280.  
  281. or with an else-clause,
  282.  
  283.     if (Bexpr) 
  284.         Texpr else
  285.             Fexpr 
  286.  
  287. Note that 'else' keyword must be on same line as Texpr. If it were allowed
  288. on the next line, non-else-clause if-statements would cause problems in
  289. interactive use. It sometimes looks ungainly, but blocks may be used to
  290. spread it over lines, as shown below.
  291. Some examples:
  292.  
  293.     if (a == 2)
  294.         b = a+1
  295.  
  296.     if (a == 2)
  297.         b = a+1 else b = a-1
  298.  
  299.     if (a == 2) {
  300.         b = a+1
  301.     } else {
  302.         b = a-1
  303.     }
  304.  
  305. while-loop
  306. ----------
  307. This is an iteration construct, of the form
  308.  
  309.     while (Bexpr)
  310.         Texpr
  311.  
  312. and reads as "while the boolean expression Bexpr evaluates to TRUE, evaluate
  313. Texpr".  The following example calculates n!, where n is an integer:
  314.  
  315.     f = 1; n = 10;        # initialize f, n
  316.     while (n > 0)        # n not yet zero, so still work to do
  317.     {
  318.         f *= n        # multiply f by n
  319.         n -= 1        # decrement n
  320.     } 
  321.     # f now holds value of 10!
  322.  
  323. do-while-loop
  324. -------------
  325. This is another iteration construct, closely related to a while-loop, with
  326. the distinction that the loop-test (the boolean expression governing the
  327. loop's operation) is performed AFTER the body of the loop. It has the form
  328.  
  329.     do 
  330.         Texpr
  331.     while (Bexpr)
  332.  
  333. Texpr is evaluated first; then, if Bexpr is TRUE, Texpr is re-evaluated and
  334. Bexpr tested again; and so on...
  335.  
  336. Whereas with a while-loop, the Texpr may never be evaluated (if Bexpr
  337. evaluates to FALSE initially), in a do-while-loop, Texpr is always
  338. evaluated at least once.
  339. An example -- sin() applied five times to a value x:
  340.  
  341.     n = 5; s = x        # n is number of times to apply sin()
  342.     do {
  343.         s = sin(s)    # apply sin()
  344.         n -= 1        # decrement n
  345.     } while (n >= 1)    # more to do?
  346.  
  347.     # s has value sin(sin(sin(sin(sin(x)))))    (sin 5 times)
  348.  
  349. for-loop
  350. --------
  351. The for-loop in icalc is like that of the C language, and has the form
  352.  
  353.     for (initexpr; condexpr; incexpr)
  354.         expr
  355.  
  356. initexpr, condexpr and incexpr are all optional (but semi-colons ; are not).
  357. The for loop is a shorthand for
  358.  
  359.     initexpr
  360.     while (condexpr)
  361.     {
  362.         expr
  363.         incexpr
  364.     }
  365.  
  366. Example:
  367.     array a[100]
  368.     for (n = sizeof(a); n > 0; n -= 1)
  369.         a[n] = 1
  370.  
  371.     # all elements of a are 1.
  372.  
  373. C: icalc's for-loop is not as flexible as C's; there is no comma operator,
  374. C: and initexpr, condexpr and incexpr can only be simple (not blocks).
  375.  
  376.  
  377.  
  378. Function definitions
  379. --------------------
  380. The User Guide explains how to define simple functions. As mentioned there,
  381. you can use a block as the body of a function (e.g. rec2pol definition).  
  382. There are more sophisticated facilities available, which provide a similar
  383. functionality to that of C. However, for a number of reasons, the syntax
  384. used in icalc differs widely from C's.
  385.  
  386. Function parameters may be one of four types:
  387.  
  388.     VALUE:        These are the normal parameters that we've been using
  389.             all along.
  390.  
  391.     POINTER:    These are like variable parameters in Pascal.
  392.             Denoted in parameter list by *.
  393.  
  394.     ARRAY:        These are passed by reference, NOT value, as in C
  395.             Denoted by @.
  396.  
  397.     EXPR:        Strange one this. It's like a pointer to a function,
  398.             but more/less flexible depending on how you look
  399.             at it. Example below will clarify.
  400.             Denoted by ~.
  401.  
  402. Note that, although a function cannot have local arrays, the array
  403. reference parameter IS local, and completely independent of arrays defined
  404. globally.
  405.  
  406. Functions may also have local variables, introduced by a statement
  407.  
  408.     local v1,v2,v3,...,vN
  409.  
  410. within the function body.  There can be as many local declarations as you
  411. like. All local variables behave like VALUE variables - there are no local
  412. pointers or arrays as yet.
  413.  
  414. C: local declarations apply to the function they appear in; there are no
  415. C: block-local variables.
  416.  
  417. The following small suite of functions demostrate the ideas above.
  418.  
  419.     # swaps values in variables a and b.
  420.     func swap(*a,*b) = {    # a and b are pointers
  421.         local tmp    # only expressions in swap() know about tmp
  422.  
  423.         tmp = a
  424.         a = b
  425.         b = tmp
  426.     }
  427.  
  428.     x = 5; y = 7
  429.     swap(x,y)    # x now holds 7, y holds 5
  430.  
  431.  
  432.     # nexpr is an expression in (global) variable n
  433.     # a is an (arbitrary) array.
  434.     # fill evaluates Nexpr for every index n of array a, and places
  435.     # result in a[n].
  436.     func fill(@a, ~nexpr) = {
  437.         for (n = sizeof(a); n > 0; n -= 1)
  438.             a[n] = nexpr;    # just referencing nexpr causes
  439.                     # it to be evaluated.
  440.     }
  441.  
  442. I'm sure you will agree that these mechanisms allow many sophisticated
  443. operations to be performed by user-functions. The examples in this document
  444. are simple-minded for the most part, to give you the bare facts about what
  445. can be done. I have included many sample script-files containing one or more
  446. function definitions which are useful to a varying degree, and in some
  447. cases add very powerful extensions to icalc.
  448.  
  449. The script files include:
  450.  
  451.     array.ic    - utility routines for arrays
  452.     arraytest.ic    - tests routines defined in array.ic
  453.     bern.ic        - computes Bernoulli numbers
  454.     cheby.ic    - computes coefficients for Chebychev polynomials
  455.     gamma.ic    - gamma and related functions
  456.     gl.ic        - integration by 10-pt Gauss-Legendre quadrature
  457.     loop.ic        - demonstrates all looping constructs
  458.     poly.ic        - polynomial support routines
  459.     root.ic        - root-finding of functions
  460.     sort.ic        - routine to perform Shell sort on arrays
  461.     trig.ic        - some rarely used trig-functions
  462.  
  463.  
  464.  
  465. Undocumented commands
  466. ---------------------
  467. There is a 'clear' command, which deletes from memory a variable, array or
  468. function. However, care MUST be taken, since icalc does not check that the
  469. object being deleted is not referenced elsewhere (in a function). If it is
  470. referenced after it has been deleted, the system will more than likely
  471. crash. The command was only really added to delete large arrays which take
  472. up a lot of memory. You have been warned...  
  473.  
  474.     clear <symbol>
  475.  
  476.  
  477.  
  478. Caveats
  479. -------
  480. Assignment
  481. ----------
  482. When assigning variables within another expression, it is safer to
  483. enclose the assignment in parentheses, to ensure that the expression
  484. is evaluated correctly.
  485.  
  486. Defining functions in terms of other functions
  487. ----------------------------------------------
  488. A function is stored internally as a structure, and a reference to
  489. a function, f, from another, g, creates a pointer to the structure
  490. for f. Thus, changing f changes g also.
  491. An example will illuminate this:
  492.  
  493.     >  func f(x) = x*x
  494.     >  func g(x) = f(2*x)
  495.     >  f(4)
  496.         16
  497.     >  g(4)
  498.         64
  499.     >  func f(x) = sqrt(x)        # changes behaviour of g
  500.     >  f(4)
  501.         2
  502.     >  g(4)
  503.         2.82842712
  504.  
  505. Therefore, you cannot use function definitions as a kind of function
  506. assignment.
  507.  
  508. Comparisons
  509. -----------
  510. Due to the inexactness of computer calculations, you must be careful
  511. when using comparison operators. Again, an example will illuminate:
  512.  
  513.     > j = 12*PI
  514.         37.69911184
  515.     > while j != 0 do [print(j), j = j-PI]
  516.         37.69911184
  517.         34.55751919
  518.              :
  519.         3.14159265
  520.         -3.5527136e-15      <--- not quite zero
  521.         -3.14159265
  522.              :
  523.     etc.
  524.  
  525. The arrow points to the position where, because of rounding errors,
  526. j is not exactly zero, and the loop never terminates, since the
  527. condition j != 0 is always satisfied.
  528.  
  529. There are two ways to get round problems like this. You can use a >=
  530. operator, or, if comparison is with (theoretically) integral values,
  531. the int() function, which rounds its argument to the NEAREST integer.
  532.  
  533.  
  534.  
  535. Questions
  536. ---------
  537. I've tried to cover everything in a clear and precise way, but almost
  538. certainly have failed in some areas. If you have any questions about icalc,
  539. write to me and I'll respond as soon as I can. Addresses are in the User
  540. Guide.
  541.  
  542. Also, if you write any scripts which you feel other users may find useful
  543. (for example, routines applying to physics or astronomy calculations)
  544. please send them to me for inclusion with the next release of icalc.
  545.  
  546. Enjoy,
  547.  
  548.     Martin Scott.
  549.