SCHOONSCHIP (*) A Program For Symbol Handling. M. Veltman 0. DIFFERENCES WITH OLDER VERSIONS 1. INTRODUCTION 2. BASICS 3. INPUT FACILITIES 4. TYPE DEFINITION 5. X, D AND T EXPRESSIONS 6. FILES 7. PRINT OPTIONS 8. END LINE OPTIONS 9. SUBSTITUTIONS 10. PATTERNS 11. CONDITIONAL SUBSTITUTIONS 12. COMMANDS 13. PARTICLE PHYSICS 14. INTERNAL PROCEDURES 15. CHARACTER SUMMATION 16. GAMMA ALGEBRA 17. R-INPUT 18. STATEMENTS. CONDITIONAL INPUT READING. 19. LARGE PROBLEM HANDLING 20. FILE HANDLING COMMANDS 21. SUMMARY APPENDIX A. COMMAND LINE OPTIONS APPENDIX B. COMPATIBILITY First version: January 1964. Current version: June 1991. *) Copyright (C) 1991 by Martinus J. G. Veltman. This version of the Schoonschip manual may be freely copied on a not-for-profit basis. All rights to other versions of the Schoonschip manual are reserved. A more extensive, printed manual and updated information are available from: David N. Williams 1238 Westport Ann Arbor, MI 48103 Email: 75706.3124@CompuServe.com 0. DIFFERENCES WITH OLDER VERSIONS. This version of Schoonschip (Jan 1, 1989) differs considerably from the previous versions. Every effort has been made to avoid changing code that has been shown to work correctly, and also upward compatibility was considered very important. To be able to run known problems and to compare the results is an invaluable and very unique part of Schoonschip. In this way 25 years of experience are still very much part of this version. Modern users tackle ever larger problems, and improvement of Schoonschip with respect to handling large problems was a high priority. There are several aspects to this situation. First, new methods to present and formulate a problem had to be considered. This has led to the introduction of a new concept, namely character summation. This allows very efficient generation of diagrams. As yet the main application seems to be high energy physics, but the concept appears to be of larger generality. More specific to high energy physics is gamma matrix algebra. Efficient methods to deal with gamma matrices in other then four dimensions have been incorporated. This allows application of dimensional regularization to problems with fermions. Another important tool in handling large problems is the Freeze command. It existed in CDC versions of Schoonschip, and has now been implemented also in this version. Last but not least the output sorting methods of Schoonschip have been vastly improved. The previous versions tended to generate very large disk files and consequently were quite time consuming. This seriously limited the magnitude of the problems that could be treated, especially on relatively small systems (PC's). It must be well understood: in principle there is no reason why Schoonschip should not run equally well on PC's as compared to mainframes. Of course, there is a difference due to the different CPU speeds, but that is often more then compensated by the fact that mainframes usually must deal with a multitude of users. And disk file handling is not necessarily slower on a PC. The main difference is that mainframes have essentially infinite disk space, but that advantage is rapidly disappearing as larger and larger disk systems become available to PC users. Right now the standard is about 20 Mb, but there are already very good and inexpensive systems with capacities in the 100 Mb range. The new sorting methods give an improvement of one or two orders of magnitude in time and disk space for large problems (producing more then 1 Mb of disk files). Of course, 'reasonable' default parameters are build in, but for truly large problems things must be tailored to the specifics of the problem. It is suggested that the section on large files is read at least once, such as to give an idea of the situation; if the need arises one can go back and get the details. Several new statements and commands have been implemented. Some of them replace older, more cumbersome forms. New statements: Anti Beep Directory Digits Dostop Dryrun External Fortran Freeze Large Maximum Overflow Precision Progress Rationalize Round Silence Showl Synonym Nshow Traditional Conditional input reading statements: Goto Gotoif Gotoifn New commands: Absol Anti All Beep Dostop Expand Extern Gammas (=old Trick,Trace) Iall Ndotpr Order Print Stats Slight modification: Integ on CDC versions of Schoonschip truncated the numbers. Later versions rounded to nearest integer. The truncation has been re-instated, but the statement 'Round on' may be used to obtain rounding to nearest integer. B list may now have vector names. All dot-products or vector components relating to that vector are factored out. In addition the Exclusive option is now available. If the first argument in the B-list is the keyword Excl then the subsequent names will be the only quantities that will be factored out. In this case function names may appear in this B-list. A function not mentioned in the list will not be factored out. Thus then functions may appear inside the brackets in the output. This Excl option has been provided in connection with the Freeze command. Here a word of caution: avoid situations where a twice occurring index becomes 'split', i.e. one appears outside and one appears inside the brackets. In that case be sure that such an index is not a created index. A word of caution: using the Excl option functions may become reordered. A D function with or without dummy arguments may now appear in the left hand side of a substitution, although not combined with other factors. The Count command has been slightly enhanced, allowing multiple counts with one command. The Symme and Asymm commands have been slightly enhanced, allowing handling of groups of arguments. The Spin command allows now vectors as arguments to identify spinors. The substitution types Id,Funct,a=... Id,Funct,p(mu~)=... may now have function names inbetween the keyword and the last argument. Then only those functions are considered. Example: Id,Funct,Epf,p(mu~) = k(mu) + q(mu) All statements are summarized in the section on Statements. Commands are discussed in the section on Commands. New notation: Long names containing special symbols such as +, - etc may now be used for algebraic symbols. They must be enclosed in square brackets. Example: [a+2/3*b] is seen as a symbol with that name. Entirely rewritten: section on Conditional substitutions. new sections are: Character summation Gamma algebra R-input Statements. Conditional input reading. Large problem handling File handling commands It is suggested that one reads (or tries to read) them at least once, to have some idea as to what is available. Schoonschip has not been known to be so-called "user friendly", whatever that may mean. This concerns error reporting as well as syntax. Some, but not much has been done on error reporting. While important, and this is well recognized, it is not considered the highest priority. Concerning the syntax, a number of improvements has been made. There are a few minor incompatibilities with older versions. Square brackets [] now have a new function, and cannot be used any more as regular brackets. The statements DELETE (for deleting blocks) and Printer (to request for line printer type output, i.e. longer line length) have been replaced by Bdelete and Lprinter. This because now no difference is made been between lower and upper case symbols for commands etc. Also, it has been attempted to make the commands recognizable by the first few (four at most) characters. The condition code system has been thoroughly reviewed. Although quite powerful it was too cumbersome to handle. Instead there is now a system employing familiar concepts: IF, AND, OR, NOT, ELSE and ENDIF. The handling of exponents has been modified. Before the addition was circular through 128 to -128. Now this is no more true. The result will be an overflow error message that can however be switched off (Overflow off statement). Further there is a new, alternative, notation for gamma matrices. Acknowlegements. Thanks are due to Drs. E. Remiddi and J. Vermaseren for inspiring several of the improvements incorporated in this (and older !) Schoonschip versions. 1. INTRODUCTION. Schoonschip is a program written in assembler language intended to help handling large algebraic expressions. Very little is build-in in the sense of function properties, or integral tables etc, but it offers many facilities to operate on expressions. Thus if the user knows the type of integrands that can occur it is easy to let the program do the actual integrations. Schoonschip never tries to think for the user, it just makes it possible to use the computer as a tool when doing algebra. There are provisions for building up a library of Schoonschip statements. Blocks of statements, performing well defined operations (such as for example differentiation or integration) may be defined, stored, and when needed recalled with a single line. In this way a user can build up to his own needs. In principle the system works as follows. An expression is given to Schoonschip and subsequently one gives instructions as to what to do. In first instance Schoonschip works out the given expression term by term, and next each term passes a series of levels. At each level the user has an opportunity to work on that term. The result is collected in an output storage area and identical terms are added. The result can be handled in a variety of ways: it can be returned to the input for a new round, or it can be written to disk for later use, etc. Of course, the result is normally printed as well. This manual explains the available features by way of examples. Some knowledge of the way that Schoonschip works is of advantage, and at various points some details will be given. The manual is meant to be read having at the same type the file with examples at hand. This file is supposedly named Examples.e. To see then how example 5 works one types Schip +5 Examples.e If the output is larger than one screenful one may also specify an output file, either by the >fnam option or also by simply giving the name as second argument: Schip +5 Examples.e outp The file outp can then afterwards be inspected. Below the input text of these examples is reproduced also. 2. BASICS. The first example shows what is meant by working out the initial expression. The expression must be given on a line wich has a Z in the first column. The general convention is that a line with a blank or tab in column one is a continuation of the previous line. Now the first example: Example 1. Z XX = (a + b)^2 The notation ^ implies exponentiation. Also ** (as in Fortran) may be used. XX is an invented name that identifies the expression if it is to be re-used, or written to disk etc. It may be part of another expression in later problems. All that Schoonschip does now is to work this out to a series of terms: a^2, a*b, b*a and b^2. Thus if nothing else is done this is what will go to the output. For algebraic variables (as a and b are taken to be by default) commutation is assumed, thus a*b is recognized to be the same as b*a. The way Schoonschip handles this is by rearranging every term, setting symbols in an internally well defined order. For quantities of the same kind this is generally the same order as that in which they appear in the input. At this point no further instructions are given, and the program may proceed to do this work. To signal that all has been said a line with an * in column one must be given. The further content of the line instructs Schoonschip what to do next after this task has been performed. Right now the idea is to go on to another example, and the word 'begin' leads to this action. After this a, b and XX are lost. *begin For massive expressions it is often desirable to group terms in the output. For instance, they may be grouped with respect to the variable a and the exponent whith which it may occur. The way to do this is to give a list of quantities to be factored out on a line with as first character a B. At most 130 quantities allowed. B a Z XX= (a + b)^2 *end This is about all control that the user has on the output format. Some additional facilities concern the way numbers are printed. By default Schoonschip tries to write every number as a rational fraction, but this is not always possible. Internally all numbers are represented as floating point numbers, with a 14 bit exponent and a 96 bit fraction. When printing Schoonschip tries to convert to a rational, using 70 bits as input. Then the rational is reconverted to a floating point number, and agreement to 84 bits is required. If that works the number is printed as a rational, otherwise as an integer or floating point number depending on the number. If printing as a floating point number the user has control over the number of decimal digits to be printed. Also the rationalization procedure can be influenced. This is done by means one or more of three statements: Precision # Rationalization # Digits # As often in the Schoonschip syntax only the first three (if no confusion possible two) characters of these statements are significant, and they may be in upper or lower case. Thus PRE # is acceptable instead of Precision. The # represent numbers specifying decimal digits. If none is given the default is used. The number following Digits specifies the number of digits to be printed for floating point numbers. Default is 5. The number following Rationalization specifies how many decimal digits should be used (sum of numerator plus denominator digits) when attempting rationalization. Default is 22. If 0 is specified no rationalization attempt is made. For other then the default value no check on the remaining digits is done. This may be used to find a rational approximation for some number. Numbers are always a problem in symbol handling programs, and the approach chosen in Schoonschip has come out of many years of trying various possibilities. As already noted above, every number is put in a floating point format with a fraction of about 29 decimal digits (96 bits) and 14 bit exponent. In the course of the calculation one will loose precision and stray bits will accumulate in the least significant part of the number. Consequently cancellations will in general not be exact. Schoonschip assumes that two quantities cancel if 25 decimal digits (80 bits) of the coefficients cancel. This number can be changed by means of the Precision statement where # is the desired number of decimal digits. To be precise: 1.E15 + 1 - 1.E15 is 0 if 15 is specified, and is 1 if 16 is given. The above makes clear to what extend numbers are handled precisely. In general rationals will be converted properly if the sum of the decimal digits in numerator and denominator is less than 21. A number may be given in various ways: - without exponent or fraction: 1230, 17893 - with fraction: 1.978, 33.127 - with (signed) exponent: 12E13, 178E-17 - with (signed) exponent and fraction: 23.47E15, 18.49E-200 - in hexadecimal notation: 0x10ABC, 0xA4FFF The latter two are the same as 68284 and 675839. The hexadecimal notation is actually needed in certain statements (the Directory statement). Schoonschip will work out multiplications and divisions of numbers directly, thus 2/3 is immediately converted to 0.6666666... The effect of the above statements as well as some other features are shown in the following example. An expression is given, printed, and re-directed to the input, and new instructions are given. Normally, when re-routing an expression to the input no output is printed, and one must explicitly asked for that by means of a line having a P in column one. Schoonschip reproduces such a line with an additional > sign. The re-direction is by means of the word 'yep' on the * line. Also the way comments may be given is illustrated. A ! implies simply end of line, and has no further effect. Also it should be noted that blanks and tabs are generally ignored (except for their function as first column character to indicate continuation). Example 2. P output !Only the first two characters of 'output' are significant. Digits 3 Rationalization 3 ! 0 leads to no rationalization attempt. Z XX=3.14 + 1/3*a1 + 7.1357689E20*a2 !E20 or E+20 implies 10^20. *yep Digits !This restores to the default option, 5 digits. Rationalization !Default: 22 digits, with check. *end The *end line implies termination after the problem has been worked out. As with most Schoonschip input, the * lines are format free, except that the * must be in column 1. But one may write for example * en d . 3. INPUT FACILITIES. While little can be done to the output, there is great flexibility concerning input. Two basic features are available: BLOCK's and DO loops. A block is a set of lines that may recur with minor variations and that can be called with a single line. The structure is very much as macro's in assemblers. The DO-loops are similar to Fortran do-loops. A block is delimited by two lines. The first line contains the word BLOCK in columns 1-5 followed by a name followed by arguments separa- ted by comma's and enclosed in curly brackets. The last line must contain the word ENDBLOCK in columns 1-8. When calling the block arguments are substituted, provided they were enclosed in quotation marks in the block definition. A block name may have 1-6 characters. Example 3. BLOCK text{xx,yy} C This argument is substituted in a call: 'xx'. This not: xx. Arguments can be glued together: 'xx''yy'. ENDBLOCK To call a block simply give the name with the arguments to be substituted. Be sure to start in column one, and to enclose arguments in curly brackets. An example of a call: text{yes,sir} A block remains known over *begin lines. It can be deleted by means of a line having the word BDELETE (four, if no confusion possible three characters significant, lower case accepted also) starting in column 1 followed by the name of the block to be deleted. BDELETE text Blocks are stored on disk in a file called tape9, and recalled as needed. Schoonschip keeps a list of names in memory. There is a simple way to delete entire lines when calling a block. A line with the character ~ in column one is totally ignored by Schoonschip, not even printed. Suppose we want in one case lines 1 and 2 of a block, and line 3 in another case. Example: BLOCK lines{A,B} 'A'C line 1 'A' line 2 'B' line 3 ENDBLOCK Now call the blocks and use ~ to delete lines: lines{,~} lines{~,} Note that an empty argument leads to an empty substitution. Actually if the final argument(s) are empty it is not even necessary to type comma's. Thus lines{~} gives the same as the last example. It may happen that one wants to call a block with some of the arguments containing a comma. In that case enclose that argument in curly brackets {}. When substituting Schoonschip peels away the outer layer of curly brackets. For example, text{{a, b}, and c} leads to: C This argument is substituted in a call: a, b. This not: xx. Arguments can be glued together: a, b and c. DO-loops are also delimited by two lines. The first line must have DO in columns 1-2 followed by name=#,#,# . The word 'name' may have (as is generally the case with names in Schoonschip) up to 6 characters. The three numbers represent a range of numbers to be substituted for 'name' in the rest of the DO loop. The first two specify the range, the last the increment. The DO loop is terminated by a line containing the word ENDDO in columns 1-5. As in the case of blocks substitution is done if 'name' occurs enclosed in quotation marks: DO var=1,7,2 P input !Normally only the first DO round is printed. C value of var: 'var' ENDDO The numbers may also take negative values. Schoonschip handles this by attaching the prefix % to the number, which is interpreted as an intrinsic minus sign when encountered in front of a number. If it occurs elsewhere this % sign is part of whatever it occurs with. DO var=-1,1 !The third number is 1 by default. P input C value of var: 'var'. C This may be part of a name, for example XX'var', or an index, for example YY(3+'var'). In the last case Schoonschip will interpret the % sign as minus and correctly work out the number. ENDDO The exit of a DO-loop may be forced prematurely at execution time, by means of the command Dostop (see substitutions and commands). This is a somewhat tricky affair, due to the fact that DO-loop expansion is strictly on the input level, while the Dostop command functions during execution, i.e. after input has been read up to a line with an * in column 1. Thus a Dostop command will have effect only after such a line. Therefore, normally, a forced exit should be effected only for DO-loops that have a line with an * as the last statement. There exists also a Dostop statement which is effective just before execution. It serves to preset the Dostop flag, and at execution time the thus forced DO-exit may be nullified or set. Again, a *-line should be the last before the ENDDO. The syntax of this statement is: Dostop on or Dostop off This sets or clears the forced DO-loop exit flag. Both Dostop statement and command should normally occur within the same DO-loop. The statement should preferably occur just before the first substitution or command of the set in which the Dostop command occurs. Blocks and DO loops may be nested, up to 10 levels deep. As is evident from the above, all this is strictly on the input level, and just pure character substitution (apart from the % sign). It is up to the user to make sure that sensible Schoonschip input results. Use the statements P input and P ninput to see or to suppress the actually generated text. Since the same blocks may occur in many different problems it is useful to have the blocks stored in some file, and to let Schoonschip read them in before starting on some problem. This is possible, and is in fact not restricted to blocks. A line with the word Read in columns 1-4 followed by a file name causes Schoonschip to open that file and read it as normal input. As soon as a line with the word End in columns 1-3 is encountered Schoonschip switches back to the normal input file, specified in the call statement. Other files may be read subsequently, Schoonschip reads all blocks and whatever else, simply switching input. All blocks read are stored in tape9 and may be used in all subsequent problems. Restriction: a Read within a Read file is not allowed. 4. TYPE DEFINITION. In algebraic expressions different types of symbols may occur. The user must specify beforehand these symbols. The following types may occur: Algebraic symbols, Indices, Vectors, Functions and Expressions. These are defined on lines having A I V F or X in column one. Actually there are additional types of expressions, characterized by D or T in column 1, but we will discuss them later. Names may have up to six characters, both upper and lower case and numers allowed, although a name should be distinguishable from a number. Also the character _ (underscore) may be used in names. If it is not the first it is not included in the count. The underscore has a function in certain contexts, to be explained later. A limited facility is present to handle large names. Sometimes large names containing other then the characters mentioned may be very useful by way of mnemonics. Such names can be used, but they must be enclosed in square brackets. They may contain just about any character except control characters (such as tab or linefeed) or square brackets themselves. Futhermore they can only be used for algebraic symbols. Examples: Abcd abc_def 12A3 12_ab f1 f2 [a + b/3] Illegal names: Abcdefg 12E3 The last name would actually be understood as a number: 12 * 10^3. Generally, symbols are simple commuting variables that may have an exponent. Such exponents must be short integers, that is integers in the range -128 to +127 inclusive. The extreme values are taken in case of overflow, if error trapping on that has been suppressed with the Overflow statement. Indices may occur as algebraic variables, but are really meant to be vector indices, or function arguments. Functions are non-commuting quantities, with or without arguments. Of course, if they are commuting that can be handled too. But if they represent matrices (with or without indices as arguments) then they must be considered as non-commuting. In short, functions may be used to represent anything that is not any of the other types of symbols. Whatever calculational rules they obey must be given by the user. Vectors are handled according to the standard rules of vector algebra. To achieve this dot-products may be formed, denoted by a capital D inbetween two vector names. Thus, if p and q are vectors then pDq denotes the dot-product between p and q. ASchoonschip follows the usual summation convention that twice occuring indices imply summation: p(i1)*p(i1) is interpreted by Schoonschip as pDq. Also the Kronecker delta is available: it is the special function D which is build-in. Here an example showing various rules: Example 4. A a1,a2,a3 !Algebraic symbol list. F f1,f2,f3 !Functions. I mu,nu !Indices. V p,q,k !Vectors. Z XX = p(mu)*{ a3^-20*a1*q(mu) + a2*a1^7*D(mu,nu)*k(nu) + a3*f2(mu,k,q)*f1} !Note the use of {}. + q(mu)*{a3*a2*a1 + f3*f2*f1} *end Note that functions are always treated as if they are on the B list. Also vectors not part of a dotproduct are factorized. Note also the re-arrangement of the symbols a1, a2 and a3, which is not done for functions such as f1, f2 and f3. Note also that Schoonschip pays no attention to the fact that f2 occurred both with and without arguments. As shown curly brackets may be used instead of the usual brackets, but they must be paired. Also the user must make sure that they cannot be confused with BLOCK definitions and calls. If some special character such as * + , etc occurs in front of the { no problem arises. Functions and vectors may not have exponents. For functions this a mild restriction, because one can always add on an argument, and consider that to be the exponent. Vectors may have a numerical arguments, for example p(3). This is taken to mean the third component of p, but only in some really formal sense, and Schoonschip has no objections against for example p(-3). The only restriction is that the number must be a short-short number, i.e. less then 32. These numbers are treated modulo 32, ranging from 0 to 31. Thus p(-3) becomes p(29). In the following something like p(3) will be called a vector component. If an index occurs all by itself, not as argument of a vector or function, it is treated as an algebraic symbol. Thus one could have mu^3. Also vector components and dot-products may have an exponent. Like Fortran, Schoonschip has default assignments for names not mentioned in any list. Things are pretty obvious in a case such as ff(a1,a2); but it is ambigous for a case like p(k). Is p a function or a vector? Again, like in Fortran, the default assignment for xx in a case like f(a1,xx) is an index if the first character of xx is in the range I-N or i-n, and else an algebraic symbol. It is always possible to see what Schoonschip guessed using the P list command. This causes a print-out of all the lists of all quantities in a given problem, but more about these commands later. The rules for algebraic symbols are the usual ones. They are supposed to commute with themselves and everything else, including functions. They may appear with or without an exponent (must be short number), and may be preceeded by a /. This simply implies a reversal of sign of the exponent. Thus a/b^3 = a*b^-3. The exponent may also be an expression in brackets, provided this expression, when encountered while working out the problem evaluates to a number. This number is then truncated and rounded to the nearest short integer. Thus b^(2-2/3) becomes b^1 = b. Overflow occurs ff the exponent of an algebraic expression exceeds 127 or is less than -128. In that case Schoonschip generates en error message. This may be suppressed with the Overflow statement: Overflow off In that case Schoonschip creates in the case of overflow (or underflow) the exponent 127 (or -128) representing infinity. The error trapping can be turned on again with the statement: Overflow on The Overflow statement may be given in the *fix section and the option given is then the default. The rules for dot-products, vector components and indices not vector or function argument are precisely those of algebraic symbols. The lists are also used to assign some further properties to the various objects. If complex conjugation occurs in a problem then the reality properties must be known. An algebraic symbol may be real (default), imaginary or complex. If it is complex then its complex conjugate must be designated. All this is done in the A-list. If a symbol in the A-list is followed by =i it is taken to be imaginary and the conjugate of the symbol is minus that symbol. A symbol may also be explicitly designated to be real by the assignment =r. If the symbol is followed by =c it is assumed that this is a complex symbol, and Schoonschip creates a new name, by appending C (capital C), and places this directly after this symbol: A a1,a2=i,a3=c implies a1 is real, a2 is imaginary (Conjg(a2)=-a2), a3 is complex, i.e. Conjg(a3)=a3C and Conjg(a3C)=a3. The symbol a3C is created by Schoonschip. If so desired it may be renamed by means of the statement Oldnew a2C=xxx where xxx stands for the new name. The Oldnew statement may actually be used to change any existing name, including the build-in names. Indices, vector components and dot-products are taken to be real. Functions may also be real, imaginary or complex, and in addition "undefined", which will be explained below. Except for =c the definitions can be overwritten, the last definition holds. This is useful with respect to build-in quantities of which one wishes to change the reality properties. Overriding with =c leads to the fact that the following symbol in the list is considered as the conjugate, which is fine if it was not defined something else before. On the other hand, redefining an =c assignment leaves its conjugate symbol as real, so that must then be redefined explicitly also if not real. In addition one may assign a number to an algebraic symbol. This number must be between -32 and +32, and its function is to facilitate working with power series. If one assigns for example the number 4 to a symbol then it is assumed that powers of this symbol of 4 or higher can be ignored, and if a term containing the symbol to such a power is seen it is immediately set to zero. This is extremely useful if not indispensable when substituting series into series. Somewhat similar one may assign z to a vector; if then that vector occurs in a dot-product, with an index, or as vector-component it is also immediately set to zero. Such facilities are very important when dealing with large expressions. Function arguments are not considered with respect to zero setting. This is somewhat ambiguous for a case such as p(mu)*f1(...,mu,..) = f1(...,p,..); this ambiguity is to be resolved by the user, and seems not to offer any difficulties. Warning. Assigning a number to a symbol in order to speed up things is not to be used if both negative and positive powers appear. Something like a^3 may be deleted before being multiplied with, say, a^-2 in case the number 2 was assigned to a. Example 5. A a1,a2=i,a3=c,a4=c,a5=i=3 V p,q=z,k Z XX = Conjg(a1 + a2 + a3 + a4 + a5) Z YY = Conjg(a3C + a4C) Z ZZ = (a1 + a5)^5 Z AA = p(mu)*{p(mu) + q(mu)} + D(mu,3)*{p(mu) + q(mu)} + pDk Oldnew a4C=b4,k=K *end Note how a5^3 and higher has been eliminated. Note also that the vector k is replaced by K. The notation D(mu,3) is explained below. The vector algebra rules are: p(mu)*q(mu) = pDq p(mu)*D(mu,nu)=p(nu) D(mu,nu)*D(nu,la) = D(mu,la) D(mu,mu) = n In the above mu, nu and la are supposedly indices defined in an I-list. The quantity n is the range of the indices, and may be a number, but also can be symbolic. Thus when working in 3-dimensional space n would be 3, in four dimensions n = 4. The default value is 4, since 1905. The way to specify this value is in the I-list. One writes the number behind the index: I mu=3,nu=3,la=3 Obviously one is supposed not to mix indices of different range in a D-function. Schoonschip makes no check for that. If Schoonschip encounters D(mu,mu) the number found in the I-list is substituted. Also a symbol may be used, but it is restricted by the requirement that it may be only one character in length. When encounterd in an I list Schoonschip will immediately enter that symbol in the algebraic symbol list, and in addition the character followed by an underscore is entered. I mu=N,nu=N,la=N If Schoonschip now encounters for example D(mu,mu)*D(la,la) the result is N^2. The names N and N_ are entered in the symbol table. The name N_ is used extensively in Gamma algebra involving indices of range N. As an extension of these well-known rules there is the additional convention that numbers and vectors may occur whenever indices may occur. Thus, p(q) D(p,q) D(p,3) D(3,4) are perfectly legal and they are worked out as one might guess: p(q) = pDq, D(p,q) = pDq, D(p,3) = p(3), and finally, if n1 and n2 are numbers then D(n1,n2) = 1 if n1 = n2, and = 0 if n1 not equal to n2. These conventions imply a rule for D, namely that D(-x,y)=-D(x,y). If an index occurs as argument of a function the treatment is conventional: D(mu,nu)*f(...,nu,..) = f(...,mu,..) where now mu may be index, vector or number, and the logical extension: p(mu)*f(...,nu,..) = f(...,p,..), etc. Despite this simplicity there is a complication that is really quite a a problem. Consider the following expression: D(mu,nu)*f1(...,mu,..)*f2(...,nu,..) There are two possible answers, namely f1(...,mu,..)*f2(...,mu,..) and f1(...,nu,..)*f2(...,nu,..) The answer is clearly not well defined. They should in fact be identified. If two such terms arrive in the output Schoonschip should add them up, to obtain 2*f1(...)*f2(...). The solution to this problem is a renaming of indices. Indices that are summation indices appearing twice, and whose name is not really relevant may be declared in a Sum list: Sum mu,nu Now Schoonschip will in both cases rename the indices in the same way, and the result is identical. The Sum list must occur after the I-list. It is best placed near the line with an * in the first column. The indices appearing in a Sum list must be defined before, but not in the *fix section (explained later). The following example illustrates the Sum command: Example 6. I mu,nu,la,ka Z XX = D(mu,nu)*f1(a1,a2,mu)*f2(a3,a4,nu) + f1(a1,a2,mu)*f2(a3,a4,nu)*D(mu,nu) Z YY = D(la,ka)*f1(a1,a2,la)*f2(a3,a4,ka) + f1(a1,a2,la)*f2(a3,a4,ka)*D(la,ka) Sum,la,ka *end Note how the indices la and ka are replaced by the invented name Naa. Now functions. Functions may have arguments, which must be single quantities separated by comma's. There is an extension involving tables, explained later. An expression in brackets is also allowed as argument. As a special facility functions may have characters as argument. Only single characters are legal, and they are recognized by preceeding them with a ". Thus f1("A,"s) is legal. See for example section 3.4, Compo for applications. Finally one may have essentially numerical expressions. An essentially numerical expression is an expression that works out to a number at execution time. It may include most anything that works out to a number; it may even contain previously evaluated expressions, but such expressions must be 'Keep' files, enclosed in brackets, and be just one number. The number obtained will be truncated and rounded to the nearest short number. A function containing an expression in brackets as argument must somehow be replaced before it reaches the output store, because that is how long Schoonschip retaines the definition of expressions in brackets. This means that there must be an equation (rather, a substitution as they will be called) leading to a replacement of such a function before the line with a * in column one. Example of a function with legal arguments: f1(a1,p,q(3),"X,pDq,17-22,(23*a5-b5),f2) This function must be replaced before the * line because of last but one argument. This is no such problem in the following case: f2(a3,7-2,pDq,"A) It is not legal to start with numbers exceeding 127 in absolute value occurring all by themselves: f1(1E25) is illegal and produces an error. But f1(2.34) is accepted and changed into f1(2). And f1(1-7E25) is accepted but gives an overflow message at execution time. This is pretty academic, and it is mentioned only for completeness. For a full understanding it is necessary to know what is really going on inside Schoonschip. Numbers in a function argument must be short integers (in the range -128, 127). Thus if numerical expressions occur as function arguments they must be "integerized". There is an operational symbol for that, namely Integ. At input time Schoonschip analyzes this situation only very superficially, and when in doubt adds the Integ operator to the argument. This happens as soon as a / or * etc is seen. Thus f1(1E25-1) is translated to f1(Integ(1E25-1)). When this expression is seen at execution time the argument is normally rounded and truncated. Overflow occurs if the number is outside the range mentioned. Integ will by default truncate the number towards 0, i.e. 1.9 becomes 1 and -1.9 becomes -1. Optionally this may be changed with the Round statement: Round on In that case the number is rounded to the nearest integer (i.e. 1.9 becomes 2, -1.9 beomes -2). The statement Round off resets to the default option, truncate. In all cases the floating point number is first rounded in the very last 10 bits, to allow for stray bits. The consequence of this is that composite non-numerical arguments are to be avoided, for example f1(3-a) gives an error report, not at input time, but when executing. As it may well happen that the symbol a is a dummy to be replaced by a number to be specified during the calculation it must be treated this way, and can not be flagged at input time. This will become clear later. With respect to complex conjugation the following rules are build in. When conjugating a product of functions Schoonschip reverses the order of all functions; conjugates those quantities whose reality properties are known, including the function arguments; postpones complex conjugation of functions that have been classified as u (for undefined) in the F-list. In this context an expression in brackets is considered a u-function. Example 7. A a1,a2=i,a3=c F f1,f2=i,f3=c,f4=u Z xx=Conjg{ f1(a1,a2,a3)*f2(a1,a2,a3,f3)*f4(a1,a2,a3) } *end A particular problem arises if an expression in brackets occurs as argument of a non-u-function. In such cases the expressions in brackets are conjugated, that is the operator Conjg is attached to such expressions. Unfortunately that is not possible for other types of symbols, thus if a u-function occurs as argument of a non-u-function subject to complex conjugation then Schoonschip stops. In such cases the function of which the u-function is an argument must be made u-type too, which is after all quite logical. A u-function will generally be replaced by something else later on, and then the complex conjugation can be worked out. A number of functions is build-in, including their reality properties, and here a particular problem arises. The Epf function (the totally anti-symmetric Weyl tensor) is real in 3 dimensions, where it represents the cross-product of vectors, but it must be considered as imaginary in 4-dimensional Minkowski space (because one of the components must be 4). Generally, the default situation in Schoonschip is 4 dimensions, and thus Epf is considered as imaginary. This may be changed by mentioning Epf in the F-list with the option =r. X-expressions are always considered as undefined with respect to complex conjugation. They are discussed later. The build-in quantities are: Algebraic symbols: i=i. This is the usual i, and the relation i^2=-1 is build in, although it is not always applied instanteneously. Functions: D,Epf=i,G=i,Gi,G5=i,G6=c,G7,Ug=c,Ubg, DD,DB,DT,DS,DX,DK,DP,DF=u and DC. Special rules are build-in for these functions. Some of these functions must not be used, because they serve special purposes. The function DD is used internally for all kinds of things. The function D is the Kronecker delta function and has been explained before. The Epf is the Weyl tensor, and it may have any number of arguments. If it has 6 arguments it is assumed to be this tensor in 6-dimensional space. A special command that reduces products of Epf to at most one Epf is build in. Furthermore it is assumed that Epf is totally anti-symmetric in all its arguments, and also it is supposed to commute with all other functions. Both the D and Epf function are taken to be linear in their arguments, that is D(-x,y)=D(x,-y)=-D(x,y) and similarly for Epf. The functions G, Gi, G5, G6, G7, Ug and Ubg refer to gamma matrices and Dirac-spinors as occurring in relativistic quantum-mechanics. They will be discussed in a special section. Users not interested in that subject may forget about them. Inside Schoonschip they account for about 8% of the code, not worth removing. The functions DB, DT, DP, DK and DC are numerical functions that are very useful in many situations. DB with one argument is the factorial, and DB with two arguments is the binomial function. The definition is: DB(n) = n! DB(n,m) = n! /{m!(n-m)!} Internally the calculation of the binomial function is word (=16 bits) bound, and fails for DB(19,m), m=8,9,... and higher up. The function DT is the theta-function, and is very useful to switch terms on and off. It may have any number of numerical arguments and is 1 if all arguments are positive including zero, and else is zero: DT(n1,n2,...) = 0 if one or more n1 negative, else DT =1. The function DP is the permutation symbol. The arguments are permuted till they are in ascending order, and the value of DP is zero if two arguments are equal, and else +1 or -1 depending on the sign of the permutation: DP(n1,n2,n3,...) = +1, -1 or 0. Zero if two numbers equal; 1 if permutation to smallest first is even; -1 if that permutation is odd. For example, DP(2,1) = -1. The function DK is something like a numerical Kronecker delta. It is 1 if the arguments are equal, else it is zero: DK(n1,n2) = 1 if n1=n2, else =0. The fact that it is explicitly a numerical function makes it different from the D function. For instance, DK may be part of a function argument expression as in f1(...,4-2*DK(n1,n2),..) The function DC is 1 if the sum of the arguments (it may have any number of arguments) is zero, and else DC is zero. It is primarily intended for situations where one has some conservation rule. It is also used in connection with character handling, and then there are various rules. The function DS is the summation function. Its application for character summation will be explained in another section. Other than that it must appear in the form: DS(J,J1,J2,( F(J) ),( H(J) ) ) or DS(J,J1,J2,( F(j) ) ) In here F and H are expressions that may depend on J. The quantities J1 and J2 must be numerical, and H must be a numerical expression. H is not limited to short numbers. When working out this function Schoonschip makes J run from J1 to J2 inclusive, and creates a sum of terms. Each term is of the form F(J)*G(J) where G(J) is defined by the first G to be one (thus G(J1)=1), and subsequent G are equal to the product of the previous G and the numerical expression H for that value of J. This sounds complicated, but is not. The expression H simply defines a recurrence relation between the coefficients of the sum. For example, 21 terms of series for e^x are given by: DS(J,0,20,(x^J),(1/J)) The recurrence relation G(J)=G(J-1)*H(J) for the coefficients gives 1/J! as coefficient G(J) of the J'th term. This is a better way of handling the factorial, both from an economical and numerical point of view, than writing 1/J!, that is 1/(DB(J)). There is an important restriction. If more than one DS function occurs in an expression one must use different names for the summation variable (J in the above example). Thus use J1, J2, etc. Example 8. Digits 20 Ratio 0 Z xx = DS(J,0,20,(1.),(1/J)) *begin Digits Ratio Z yy = DS(J,0,4,(X^J),(1/J)) *end 5. X, D AND T EXPRESSIONS. So far only Z-expressions occurred in the examples. These expressions are to be evaluated by Schoonschip. Other expressions may be defined and may be called when they are needed. Such expressions are X and D expressions. One may have up to 500 X expressions. As a simple example take the series for cos(x). The equation for cos(x) is: cos(x) = { exp(i*x) + exp(-i*x) }/2 This series may be obtained as follows. First define exp(y) and then write cos(x) in terms of this exponential (arbitrarily 6 terms are kept): Example 9. X EXP(y) = DS(J,0,6,(y^J),(1/J)) Z COS = { EXP{ (i*x) } + EXP{ -(i*x) } }/2 *end Important rule: any X-expression must have been defined before it can be referred to. It is permissible to have X-expressions appearing in an X- expression provided that they were defined before. The rules for arguments of X-expressions are the same as for functions, which is why the argument i*x is enclosed in brackets. Here we see how this is replaced in the right hand side of the EXP definition, so that indeed this expression in brackets no more appears as function argument. This method of defining COS may seem to be a waste, but in practice this is used to define COS once and for all. It is namely possible to specify an argument for the Z-expression, and to tell to Schoonschip not to throw away this expression after printing it; then later on one may refer to COS(x) as if it were also an X-expression. That will be discussed in the section on files. Arguments as appearing in the X-expression definition will often be called dummies in the rest of this manual. They are to be replaced by the arguments found in the call (in the Z-expression) at execution time. In other situations some of the arguments may be dummies, others not, as we will see. In those situations a dummy is to be followed by a wiggle: ~. In X and D expressions and also in tables (T) all arguments are dummies and the wiggle needs not to be given. D-expressions are arrays of X-expressions. This may for example be used to specify matrices. Everything is the same as for X-expressions, except for the first argument. In calling a D-expression this argument must be a number, and this number is then used to select the expression from the array. Since the expressions in a X or D-expression may again be X or D-expressions the possibilities are quite extensive. For example, let there be a 3x3 matrix with the elements (a11,a12,a13),(a21,a22,a23),(a31,a32,a33) in rows one, two and three. The first part of the following example produces the determinant of that matrix: Example 10. B a11,a21,a31 D rc(n)=a11,a12,a13, a21,a22,a23, a31,a32,a33 X matrix(n,m)=rc(3*n+m-3) Z xxx = DS{J1,1,3,(DS{J2,1,3,(DS{J3,1,3, { DP(J1,J2,J3)*matrix(J1,1)*matrix(J2,2)*matrix(J3,3) } } ) } ) } *begin As shown, an X or D-expression can have many arguments. In fact, X or D-expressions may be arguments of X or D-expressions. Here one must follow an important rule. To make it possible for Schoonschip to analyze the right hand side of some expression correctly dummies must be of the same kind as later the argument replacing the dummy is going to be. The same kind means generally speaking one of the four cases: symbols with or without exponent, vectors functions or Tables. Thus functions and expressions (and later files) are of the same kind. Algebraic symbols must be used as standin for dotproducts, vector-components and also for short numbers (less than 128 in magnitude, the same kind that may appear as function argument). Functions may stand for X or D-expressions, as shown also in the second part of this example. It is best to play this for sure, and use as dummies really the same kind, i.e. X-expression type for X-expressions or D-expressions, functions for functions etc. In the example below the use of for instance ra instead of f1 in the definition of the X-expression matrix is advised. Vector-components, dotproducts and numbers are illegal as dummy. If they are to be substituted in an X-expression use some algebraic symbol to represent them, as we did using n and m in these examples. In the second part of example 10 we define a general X-expression for a determinant that may be called to compute the determinant of any matrix occurring in a problem. Two determinants are computed. F f1 B a11,a21,a31,b11,b21,b31 D ra(n)=a11,a12,a13, a21,a22,a23, a31,a32,a33 D rb(n)=b11,b12,b13, b21,b22,b23, b31,b32,b33 X matrix(n,m,f1)=f1(3*n+m-3) X DET(f1) = DS{J1,1,3,(DS{J2,1,3,(DS{J3,1,3, { DP(J1,J2,J3)*matrix(J1,1,f1)*matrix(J2,2,f1)*matrix(J3,3,f1) } } ) } ) } Z detb=DET(rb) Z deta=DET(ra) *begin In the third part of this example it is shown how the X-expression DET can be made into a D-expression giving determinants for 1x1, 2x2 and 3x3 matrices. C Example 10. F f1 B b11,b21,b31 D ra(n)=(a1-a2),0, 0,(a1+a2) D rb(n)=b11,b12,b13, b21,b22,b23, b31,b32,b33 D rc(n)=c11 X matrix(k,n,m,f1)=f1(k*n+m-k) D DET(n,f1) = f1(1) , DS{J1,1,2,(DS{J2,1,2, { DP(J1,J2)*matrix(n,J1,1,f1)*matrix(n,J2,2,f1) } } ) } , DS{K1,1,3,(DS{K2,1,3,(DS{K3,1,3, { DP(K1,K2,K3)*matrix(n,K1,1,f1)*matrix(n,K2,2,f1)*matrix(n,K3,3,f1) } } ) } ) } Z deta=DET(2,ra) Z detb=DET(3,rb) Z detc=DET(1,rc) *end Several remarks are in order. First, note how items in a D-expression array must be enclosed in brackets if the expression contains more than one term. The rule is that each entry must be one term only (an expression is a sum of terms, each term is a product of factors). An expression enclosed in brackets counts as one factor in a term. Secondly, there is the question of DS arguments. For the first argument, the summation index, one must use different variables for each DS function. Thus J1, J2 and J3 must not be used more than once. This was mentioned before, and in this example it is relevant. T-expressions or better Tables are for use as function arguments. There are also 'character tables' to be discussed elsewhere. Tables represent an array of quantities that may be selected as function argument and at execution time the appropriate argument is selected on the basis of the value of the first argument. The following example shows a complicated way of obtaining f(a) + f(b) + f(c) : Example 11. T List(n)=a,b,c F f Z compl = DS(J,1,3,{ f(List(J)) } ) *begin This is really the idea: to enable summing over a series of arguments that can then be listed using a Table. The rules for entries in a Table are simple: they must be valid function arguments. Tables can be nested, allowing essentially matrices of arguments. The first argument of the Table in the call selects an item from the corresponding Table list. If that item is again a Table, then the second Table list is looked up with the second argument determining which argument to take. And so on. All arguments are treated as dummies, and Table entries may depend on them. Since an expression enclosed in brackets may appear in the Table list that allows for complicated constructions. If such expressions are essentially numerical, and they must ultimately be converted to a short number the oprator Integ must be placed in front of them. Also Conjg is allowed. A x=c T r1(n)=a11,a12,a13 T r2(n)=a21,a22,a23 T r3(n)=a31,a32,a33 T matr(n,m)=r1,r2,r3 T weird(n,a1,a2)=Conjg(a1+a2),Integ(3*a2) X XX(a1,a2)=a2*a1 Z sqa13 = DS(J,1,3,{f1(matr(1,J))*f1(matr(J,3)} ) Z weirdo=XX(weird(1,x,7),weird(2,x,7)) *end There is a subtlety here. Whatever follows Conjg, enclosed in brackets, is considered an expression. It must not survive as function argument beyond the * line. Thus if in weirdo we would have had f1 instead of the X-expression XX then this would be illegal here. General rule: anything that can occur as function argument can occur as element in a Table list. This includes for example characters (notation: "X is the character X). Be careful with numbers: they are treated like function arguments, and non-integers are truncated. 6. FILES. Files very much resemble X-expressions, but there is one important difference. A file contains the result of some Schoonschip calculation. A Z-line defines a file, with the name as given on that line. A file may have arguments, can be stored in a variety of ways, and can be part of a problem just as any X-expression. Schoonschip has been made with the assumption that files tend to be large. Elaborate measures have been taken to handle the largest files. The number of files that can be handled at any one time is limited to about 200. To begin with, files are divided in local and common files. All the Z-expressions that have been shown sofar are local. Local files are normally lost over a * line, except over a *yep. A local file may be kept over a * line provided that the word next is on that line, and provided that the file was mentioned in a Keep list: Z xxx(a,b)=(a+b)^2 Keep xxx *next Z yyy=xxx(c,d) *begin After a *begin the local files are all lost. Schoonschip treats local files as efficiently as possible. They are kept in memory if there is room, if they are too big they are stored on disk and recalled if needed. Common files are kept untill explicitly deleted or till the *end line. They can be written to disk for use in a later session. Schoonschip keeps all common files in a sequential file on disk. Great care has been taken that such expressions, when needed in a problem, are read with the least amount of input/output activity. The user will normally see nothing of these read/ write activities, but should still be aware of it when handling large problems. Computer handled problems have the tendency to become large, that is simply in the nature of the subject. Except for the simplest cases it is really quite impossible for a computer to simplify an expression. While it is trivial to simplify a^2+2*a*b+b^2 to (a+b)^2, it becomes an entirely different matter when dealing with 1000 or more terms. Of course, with a little help from the user, simplification can be done, on a rather primitive level. If one recognizes a pattern such as shown above one substitutes a^2=apb^2-b^2-2*a*b, and the output collapses to apb^2. In addition to the classification local and common, files may be indexed or non-indexed. This makes it possible to have arrays of files, much like D-expressions. The way a file is defined to be indexed is as follows: - A local file is defined to be indexed if on the defining Z-line the first argument of that file is a number in the range 0-32767. There are provisions for situations where this number is an expression, involving for instance DO-loop or BLOCK variables, but at execution time such expressions must work out to a number. Only numbers and DO-loop or block variables may appear in these expressions, and for these latter variables numbers must be substituted. - A common file is defined to be indexed if it appears in the Common list with a subscript, preferably the number 0. The implication of that is not the existence of the file with the particular index zero, but rather that this filename represents a class of subscripted files. Thus: Common abc,Xyz,fgh(0),jkl defines abc, Xyz, fgh and jkl to be common files, and fgh is an indexed files. When in a subsequent Z-line such a filename occurs it is recognized and at the end of the calculation the file is written to disk. For local files the command Keep is of interest: Keep aaa,bbb,ccc(1),eee This line, which should occur shortly before a *next line, leads to keeping of the files mentioned over the *next. For an indexed file one may either explicitly mention an index (such as for ccc here) and then only that file is kept. If there are several ccc files to be kept it is sufficient to mention ccc without any index and then all ccc files are kept. There are several other commands that relate to files. First, common files may be written to a named disk file for use in a later problem. This may be done with the command Write xxx All common files that exist at that moment are written (sequentially) to a file named xxx. Thus xxx will in general contain many files. This statement must be all by itself, and not be embedded in some problem. In other words, before and after this Write line there must be a * line not containing yep or next. When one or more of the common files contained in xxx are needed one may enter these files: Enter xxx This statement should preferably be the first statement of a Schoonschip program. It must be before a *fix line, explained below. Schoonschip opens the file xxx and enters all names in the common file table, and the files themselves are copied to a diskfile local to Schoonschip (tape7). One may have several Enter and Write statements. Note: do not confuse Enter and Read. The latter is for reading normal Schoonschip text from some external file. Common files may be deleted: Delete abc,Xyz,fgh(3) Again, the mentioning of fgh without any index leads to deletion of all fgh files. As the reader may guess it is quite a problem to keep all namelists straight when common files are entered. Normally Schoonschip treats this problem only when encountering such files in a given problem. Usually that will give no problems, but difficulties may arise in connection with summation indices (see Sum declaration). For this reason it may be necessary to enter the names contained in that file before actually starting on the problem. The statement Names abc,Xyz,... is meant for this purpose. If this directive is not given, and Schoonschip runs into problems then an error exit is taken, asking for the Names line. Example 12 shows some very simple case. Note that the local file xxx is lost over the *begin line, and xxx is taken to be a function. Similarly for common file ccc after a delete. When this problem is run the file fileC is created. Make sure that there is not already some file by that name. Example 12. P lists Common yyy,ccc(0) Z xxx(a,b)=(a+b)^2 Z ccc(3,a,b)=(a+b)^3 Z ccc(4,a,b)=(a+b)^4 Keep xxx *next F f1,f2 V p Z yyy(p)=xxx(c,d) + p(nu)*f2(mu) Sum mu,nu *begin Write fileC *begin V q Z zzz=a1*yyy(q) Z Abc=xxx(a,b) Delete ccc,yyy !The actual delete occurs when this section is done. *begin Z xyz=ccc(3,e,f) *end The statement P lists at the beginning causes Schoonschip to print all symbols known before execution. Also details such as reality properties or dimensionality of indices is shown. For X, D, T expressions the type as well as the nesting depth is shown. Also brackets count in this respect. At this point it must once more be emphasized to be conscious of the use of local and especially common files in a problem. If for example yyy is a rather lengthy common file then things such as (yyy)^4 may lead to very lengthy calculations. If yyy has 100 terms this gives rise to (100)^4 terms, i.e. 100 million terms that must be sorted. This will fill up all available disk-space, to name something. And 100 terms is really not that much as these things go. Just to avoid this kind of disaster Schoonschip has an output limit build in of about 0.5 Megabyte per file used by Schoonschip. This limit may be changed by means of the statement Outlimit,# where # is the new limit in bytes. What to do if really big expressions must be evaluated will be discussed later. In this context an expression is called big when it exceeds 50,000 terms. 7. PRINT OPTIONS. The following directives influence output. Only the first two characters of the word following P are releveant. P brackets print working out of brackets P heads print in the output only the factors outside brackets (B-line) P input print input lines (default) P lists print lists of all symbols (vectors, functions etc.) P ninput do not print input lines P nlists do not print lists (default) P noutput print no output (default in *yep cases) P nstats print no statistics (default) P output print output (default, except in case of *yep) P stats print statistics In addition the following directives affect output format: Screen try to keep lines less than 80 characters long (default) Lprinter go up to 130 characters/line Printing of the individual files may be affected as well, but only if they are currently being processed: Print xxx,yyy,... print files xxx,yyy,... Nprint xxx,yyy,... do not print xxx,yyy,... Punch xxx,yyy,... write xxx,yyy,... to a file named tape8 in fortran compatible form. This last directive is useful if the output is to be used for further numerical output in a fortran program, or for curve plotting etc. Normally print options stay in effect untill cancelled. Exception: P heads. The P output option, often used to force output printing in a *yep situation, survives only one *yep. 8. END LINE OPTIONS. For the * line the following possibilities exist: *fix Do not start execution. All names and expressions defined before this statement remain valid till the *end line. *yep Start execution. Write the output to disk and feed in again as input. *next Start execution. Keep all namelists, and those local files mentioned in Keep lists. A Keep list extends over one *next only. *begin Start execution. After this start new problem. Disregard all names except those mentioned in the *fix section. *end Start execution. Stop after completion. Not explained so far is the *fix option. This is used whenever names or X, D or T expressions are to be defined that are valid for all following problems, including those after a *begin. This *fix section must be the very first section, and must not contain any Z expressions. If common files are to be entered it must be in this section. The sequence shown above reflects the general structure of any Schoonschip program. First there is a *fix section, and then there may be several *yep, *next and *begin lines before the final *end is encountered. The *yep command is extremely useful, but can only be explained properly later, after discussing substitutions. It is rather unique to Schoonschip, and of crucial importance when dealing with large problems. 9. SUBSTITUTIONS. Most things discussed up to now essentially help to define expressions, but do not really work on those expressions. The main tools for work on expressions are what will be called substitutions and commands. A substitution basically amounts to looking at an expression term-by-term, and if certain patterns match something may be removed from the term, and something else substituted. This basic tool, for the first time introduced in the 1964 Schoonschip version, is the essential ingredient of symbol manipulation. Thus in the first place there is pattern recognition, and secondly there is a substitution. In this version (1984+), optionally, these two aspects can be separated. One can first look for a pattern, set some flag indicating the result of the inspection, and then at a later stage act on that flag. Commands define certain operations to be done on the terms, and that are of sufficient generality to warrant building in. For instance, there is a command that allows the user to specify which functions are commuting with each other. Schoonschip acts on that by setting these functions in an internally well defined order, so that terms differing only by functions being placed in different order become equal. Such an operation can also be done with substitutions, but is more tedious. An important concept in substitutions is the use of dummies. These quantities have already been introduced before in connection with X, D and T expressions, and here they become even more useful. Let us start with a simple example. Imagine that some polynomial in x must be integrated, and let this polynomial be quadratic: a*x^2 + b*x to be integrated from x1 to x2. This integration amounts to using the rule x^n => x^(n+1)/(n+1), and then putting the integration limits. This may be done as a substitution. First look for x to any power (this is the pattern). Then remove x and substitute by the appropriate expression which is the integral of that x. The following example shows how this can be done: Example 13. Z integr = a*x^2 +b*x Id,x^n~ = x2^(n+1)/(n+1) - x1^(n+1)/(n+1) *begin Schoonschip looks for the pattern "x to any power", and if found removes that x and instead substitutes the right hand side of this substitution. The value of the power found is substituted for n in that expression. Here n is a dummy. To let Schoonschip know that it is a dummy the wiggle ~ must follow directly behind it. The notation Id refers to a name used often in the past for this operation, namely "identity". The matter to be discussed now is what kind of patterns can be specified. As an example of the sort of complication that can arise take this integral again. Suppose there had been a term without any x. What should Schoonschip do? In this case that should be treated as x^0, but in many other cases such terms must not be worked on. In the spirit of pattern recognition a term without x is taken not to fit the pattern specified here, and such a term is thus not worked on. But how now to go about that? A classic way to do that is to use an extra symbol, that we will call dx here: Z integr = (a*x^2 + b*x + c)*dx Id,x^n~*dx = x2^(n+1)/(n+1) - x1^(n+1)/(n+1) Al,dx = x2 - x1 *end What happens is that if dx and as well x to any power excluding zero is encountered then the first substitution is done. This leads also to the removal of dx. If a term without any x (the c term) passes by the first substitution is not done, and the dx survives. But then the second substitution is performed. The notation Al is an abbreviation of "also", but there is more to it, which will be explained below. Generally, Al can be used with advantage for mutually exclusive patterns. One can not use Al in case that the first substitution generates a pattern that the second may have to act on. Since there is a limit on the number of Id statements it is often necessary to use Al, and its use should be well understood. There is an equivalent notation to Al, namely placing that substitution on the same line preceeded by a semicolon (;): Id,x^n~*dx = x2^(n+1)/(n+1) - x1^(n+1)/(n+1) ;dx = x2 - x1 There may be several such 'also' statements on one line, but lines should not exceed 150 characters. This example shows really most that there is to it. Of course, more complicated patterns than just an algebraic symbol to some power can be specified, but that is really just an extension of the same principle. There are substitutions that are performed if certain functions with certain arguments are present, and one may specify if the order of these functions is important or not; one may operate on function arguments, on vectors in a dotproduct etc. Basically, through the years, things that may be needed have been implemented. As it happens most of these are quite natural, barely needing a manual, such as the one above. Let us give another example, to show a number of applications. In the above integral more complicated things could have occurred, for instance terms such as x^3*cos(x). To evaluate these one must first do partial integrations: x^3*cos(x) = x^3 * d/dx{sin(x)} = d/dx{x^3*sin(x)} - 3*x^2*sin(x) Thus, before doing the x-integration one must first do these partial integra- tions, and that as many times as needed given the highest power of x that occurs. Assuming that at most x^10 occurs one would write: Id,10,x^n~*cos(x) = x2^n*sin(x2) - x1^n*sin(x1) - n*x^(n-1)*sin(x) Al,10,x^n~*sin(x) = - x2^n*cos(x2) + x1^n*cos(x1) + n*x^(n-1)*cos(x) There are more elegant ways to do this, using X-expressions, but that is not the point here. That general method is shown anyway, as last part of Example 13. The above implies doing these substitutions on ten subsequent Levels, and substitution will be done as long as x to some power occurs. The final step, to be taken if no more x present would be the integration of cos(x) or sin(x): Id,sin(x) = cos(x2) - cos(x1) ;cos(x) = - sin(x2) + sin(x1) If also x to negative powers would occur one would have to treat that separately. This is where the conditional substitutions comes in handy. One may test for the presence of negative exponents, and set a flag depending on the outcome of such a test: IF Multi,x^-1 This tests for exponents that are a multiple of the exponent shown, here -1. If so a flag is set. Subsequent substitutions will be done if that flag is set until an ELSE is encountered. The then following substitutions will be done if the flag was not set. An ENDIF statement terminates the conditional substitutions. The typical sequence would be here: IF Multi,x^-1 Substitutions to treat x^-n type terms. ELSE Substitutions to treat x^+n type terms. ENDIF A NOT following the IF is recognized, and the following sequence gives identical results: IF NOT Multi,x^-1 Substitutions to treat x^+n type terms. ELSE Substitutions to treat x^-n type terms. ENDIF IF's may be nested, up to 8 deep. A futher extension uses AND and OR statements, possibly combined with NOT. For example, if there are also terms without sin or cos: IF cos(x) OR sin(x) ..IF Multi,x^-1 ..Substitutions to treat x^-n type terms. ..ELSE ..Substitutions to treat x^+n type terms. ..ENDIF ELSE Substitutions to deal with x^n without sin or cos. ENDIF A new notation, purely for readability, has been introduced. A . in column one causes Schoonschip to skip all following periods. In this way one may indent the nested IF's to show IF depth. See the section on conditional substitutions for more details. A few patterns as can appear in the left hand side of a substitution have been introduced above. The need for those patterns are clear, once one starts on this kind of problem. Along these same lines a set of patterns has been defined that appears to be adequate to deal with things as they arise in practice. It is somewhat difficult to give a complete description, but it has to be done. Let us do this in two rounds, namely first somewhat sloppy, and then precise. As long as one deals with a single quantity (including exponent or index or arguments) one has various options specified by keywords. One such keyword appeared already above, namely Multi. For algebraic symbols the following substitution patterns are possible: Id,a=... Substitute n times if a^n encountered, n positive. Id,a^n=... Substitute once if precisely a^n encountered. Id,a^n~=... Substitute once for a, any non-zero exponent Id,Multi,a^n=... Substitute m/n times if a^m encountered, and m has the same sign as n; leave rest. Id,Once,a^n=... Substitute once if a^m encountered, m/n ge 1; leave rest. Id,Funct,a=.... Substitute for a if appearing as function argument. The action taken is to enclose the expression on the right hand side in brackets and place it instead of the argument a. Remarks concerning expressions in brackets as function arguments apply here. Such functions may not cross * lines and must be subject to some substitution before that. Id,Funct,f1,f2,...,a=... Same, but only in the specific functions mentioned Thus Id,Once,a^2=... when encountering a^7 leads to one substitution, and a^5 is left. Of course, Al (or ; and on the same line) may occur instead of Id. In the above n is a number, except in the third case where it is a dummy. Similar things may be written down for dotproducts or vector-components. For single functions one may specify the function including the arguments, but some or all may be dummies, and one may also have repetitive dummies. For example: Id,f1(a~,b,c,a~)=... leads to a substitution if the function f1 is encountered with as second and third argument b and c, while any argument on the first or fourth place will do provided they are the same. Here a is a repetitive dummy. One could have specified another dummy for the last place: Id,f1(a~,b,c,d~)=... and then the substitution is done for any argument on the first or fourth place, including equal arguments. The build-function D is special insofar that it is generally not allowed as part of a substitution pattern. It may however appear all by itself with or without dummies. Examples: Id,D(al,be) = .... Id,D(al~,be) = ... For single functions one keyword may appear. If a function has nothing but dummies as arguments, and if the keyword Always appears, then the substitution will be done even if the argument count is not the same. Thus Id,Always,f1(a~,b~)=... is applied also when encountering f1(xx,yy,zz). The argument zz is then simply dropped. Make sure that the case that there are more dummies than arguments can not occur. Finally one may even specify a dummy function: Id,f1~(a,b,c~,...)=... The substitution is done for any function whose arguments and argument count agree. For vectors a number of different possibilities exist: Id,p(mu)=... Substitute for p(mu). Id,p(mu~)=... Substitute for p with any index. Id,Dotpr,p(mu~)=... Substitute for p if appearing in dotproduct or as vector-component. Id,Dotpr,f1,f2,..,p(mu~)=... Same, but only in the specific functions mentioned. Id,Funct,p(mu~)=... Substitute if p appears as function argument. Id,Funct,f1,f2,..,p(mu~)=... Same, but only in the specific functions mentioned. In the last cases things are done as expected for vectors. In all but the first case it is assumed that the right hand side depends on the index mu. For example, typically, one could have Id,Dotpr,p(mu~)=k(mu)+q(mu) . Suppose now pDq is encountered. Schoonschip reads this as p(q), and substitutes q for the index mu, which leads to kDq+qDq, as should be. If pDp is seen then Schoonschip invents an index, say Naa, substitutes this index for mu and writes: { k(Naa) + q(Naa) } * { k(Naa) + q(Naa) } A similar thing is done if p is encountered as function argument in case of the Funct type substitutions: f1(...,p,...) becomes f1(...,Naa,...)*{ k(Naa) + q(Naa) } which leads to f1(...,k,...) + f1(...,q,...). Thus linearity of f1 in p is supposed here. This substitution should therefore not be applied if that is not the case. For any other pattern involving more than one quantity substitutions are straightforward. The only extra options that one has here is that the ordering of functions may be specified. The keyword Adiso (allow disorder) indicates that substitution must be done no matter the ordering of the functions. The keyword Ainbe (allow inbetween) implies that the substitution must be done if the functions are in the same order, even if there are some other functions inbetween. If none of these keywords is present then the substitution is done only if exactly the same pattern is found. The pattern may involve dummies for exponents, vectors, indices, functions and function arguments, and one may have repetitive dummies. As a special option one may also have factors xx^0 where xx is an algebraic symbol, vector-component or dot-product. Schoonschip requires in that case that specifically xx is not there. ++++++++ We stress here that for dummies one must (repeat: must) use the same kind of symbol as that what replaces it at execution time. See the discussion on this subject in the section on X-expressions. ++++++++ Forty substitution Levels are available. If more Levels are needed a line with *yep must be inserted. The Level count is printed by Schoonschip next to every substitution. More levels are needed for a given substitution as the bracket depth is larger. It is often advantegeous not to use brackets if not strictly necessary. For example, it is better to write Id,x^n~ = x2^(n+1)/(n+1) - x1^(n+1)/(n+1) which needs two levels rather then Id,x^n~ = (x2^(n+1) - x1^(n+1)) /(n+1) which needs three levels. Schoonschip generates a substitution for every bracket pair. If you want to see what Schoonschip does use the option P brackets. 10. PATTERNS. In this section a more precise discussion of the substitution patterns is given. For a first reading this section may be skipped, it is really there only for reference, in case something special is going on. The way things are organized in Schoonschip there is a classification in about 17 classes. In practice one will rarely realize what class a given pattern belongs to, but for completeness we will discuss possible patterns on the basis of this classification. We will also indicate what action is taken once the pattern is found to be present, although that may be influenced, postponed or even inhibited by means of conditional flags. The classification is on the basis of what occurs on the left hand side of the = sign on an Id or Al line. Only products of factors may occur (thus no + or - sign except in exponents or function arguments), and no brackets other than associated with a function and its arguments or a vector and its index. Thus something like a+b or a*(c+d) is illegal. Furthermore, a keyword may be given, and that influences the way Schoonschip reacts to a pattern. Finally one will encounter the word repetitive dummy. That is when the same dummy appears two or more times in the left hand side of a substitution. In that case Schoonschip verifies that in the pattern the same thing appears in both places, although the thing itself may be anything. Here are the various classes, examples will be given later. Below a,b,.. stand for algebraic symbols, n,m,.. for short numbers, p,q,.. for vectors, f1,f2,.. for functions etc. 0. f1(a~,b~,...) Function, all arguments non-rep. dummies. Optional Keyword: Always Action: substitute for every such function found provided the number of arguments agrees. If the keyword Always is given then substitute irrespective of the number of arguments in the function found. It is up to the user to see to it that the number of arguments equals or exceeds the number of arguments actually appearing in the right hand side of the substitution. 1. a^n Symbol with exponent, no dummy. Keyword: Multi Action: when encountering a^m divide m by n, and if the result, truncated to an integer, comes out to be 1 or more, substitute that many times. The remaining exponent is put back. Thus a^2 applied to a^7 leads to 3 substitutions and one factor a is left. The exponent may be negative: a^-2 applied to a^-7 leads to 3 substitutions and a remainder a^-1. If n and m have opposite sign no substitution is done. If the exponent n is absent the keyword Multi is understood, and an exponent 1 used. 2. pDq^n Dotproduct with exponent, no dummy. Keyword: Multi Action: same as in class 1. 3. a^n Symbol with exponent, no dummy. Action: substitute once if exactly a^n found. 4. pDq^n Dotproduct with exponent, no dummy. Action: see class 3. 5. p(mu) Vector with index, no dummy. Action: substitute once if p(mu) found. 6. p(mu~) Vector with dummy index. Action: substitute for every p(..) for any index. The substitution applies not if the vector p appears as factor in a dot-product or as function argument, and also not to vector components such as p(3) (i.e. if the index is a number). 7. a or mu or pDq or p(n) Symbol (index, dotproduct, vector component) Keyword: Funct Action: replace a (or mu etc) when occurring as function argument. Note: such functions must be substituted for before the * line, because an expression as function argument can not survive a *. If functions are mentioned between the keyword and the argument then only those functions will be considered. 8. a^n or pDq^n Symbol or dotproduct with exponent. Keyword: Once Action: substitute once if a^m encountered if m/n positive and equal or larger than one. Keep the remainder. Thus a^2 when encountering a^7 leads to one substitution and a^5 remains. 9. a^n*...f1(mu,b,..) One function and anything else. 10. f1(mu,a,b~,..) One function. 11. Anything Keyword: Adiso Action: substitute if all factors found even if the functions found are not in the same order as in the left hand side of the substitution. Note: Adiso stands for Allow disorder. Note: the expression is put at the location of the first function removed. 12. Anything Keyword: Ainbe Action: substitute if all factors found, with the functions in the same order, although there may be other functions inbetween. Note: Ainbe stands for Allow inbetween. Note: the expression is put at the location of the first function removed. 13. Anything Action: substitute if all factors found, with the functions in the same order and no other functions inbetween. Note: the expression is put at the location of the first function removed. 14. Not used. 15. p(mu~) Vector with dummy index. Keyword: Dotpr Action: substitute for p if p part of a dotproduct appearing with a positive exponent. 16. p(mu~) Vector with dummy index. Keyword: Funct Action: substitute if the vector p is found as function argument. If one or more function names are mentioned between the keyword and p(mu~) then the substitution will be done only in the specific function(s) mentioned. All of this may sound a lot more complicated than it is, all these classes are really such that they cover most cases that one can imagine. The user needs not to know to which class a given substitution belongs, and most substitutions are natural in the sense that it is obvious what action is to be taken. We will now give examples, essentially going through all possibilities. The same starting expression will be used in all cases, and we will use a *fix section to specify that expression. Then many cases follow, all separated by a *begin implying a fresh start. Example 14. V p,q A a,b,c,d,e,f,g,h I mu,nu F f1,f2,f3 X expr=f1(a,b,p)*f2(a,c,q)*f3(d,e)*f1(g,h)* { a^7 + a^-7 + a^2 + pDq^2 + pDp + p(mu) + p(nu) } *fix C Class 0, no keyword. Z xxx=expr Id,f1(a1~,a2~)=a1^10*a2^20 *begin C Class 0, keyword Always. Z xxx=expr Id,Always,f1(a1~,a2~)=a1^10*a2^20 *begin C Class 1, keyword Multi. Z xxx=expr Id,Multi,a^3 = xyz + hij *begin C Class 2, exponent 1, no keyword. Z xxx=expr Id,pDq = XYZ + HIJ *begin C Class 3, no keyword. Z xxx=expr Id,a^2 = a1^7/15 *begin C Class 5. Z xxx=expr Id,p(mu) = - q(mu) *begin C Class 6. Z xxx=expr Id,p(mu~) = - q(mu) *begin C Class 7, keyword Funct. Z xxx=expr Id,Funct,a = a27 Id,f1(a1~,a2~,a3~) = 200*a1*a2*a3 Al,f2(a1~,a2~,a3~) = a1^10*a2^11*a3^12 *begin C Class 8, keyword Once. Z xxx=expr Id,Once,a^2 = XXX *begin C Class 9. Z xxx=expr Id,a^2*f2(a1~,c,p~) = F2(a1,c,p) *begin C Class 10. Z xxx=expr Id,f1~(a,b~,p~) = F(a,b,p) *begin C Class 11, keyword Adiso. Z xxx = expr Id,Adiso,f1(g,h)*f1(a~,b~,c~) = F1(a,b,c,g,h) *begin C Class 12, keyword Ainbe. Z xxx=expr Id,Ainbe,f1(g,h)*f1(a~,b~,c~) = F1(a,b,c,g,h) Id,Ainbe,f1(a~,b~,c~)*f1(g,h) = F2(a,b,c,g,h) *begin C Class 13. Z xxx=expr Id,f1(x~,b,p)*f2(x~,c,q) = F(x,b,p,c,q) *begin C Class 15, keyword Dotpr. Z xxx=expr Id,Dotpr,p(mu~) = - q(mu) *begin C Class 16, keyword Funct. Z xxx=expr Id,Funct,p(mu~) = - F1(a,b,mu) *end 11. CONDITIONAL SUBSTITUTIONS. In the foregoing IF, AND, OR and ELSE have been introduced already. The general structure is: IF pattern Substitutions ELSE Substitutions ENDIF There may be no ELSE. The IF statement may be followed by AND and/or OR statements. IF, AND or OR may be followed by NOT which inverts the action. Finally, the pattern may optionally be followed by an = symbol and an expression. In such a case the substitution is actually done if the pattern fits. The pattern may be any of the classes discussed in the previous section. Inside Schoonschip IF's etc set or clear some bit. One bit is reserved for any given IF depth. Nesting up to eight deep is allowed, there are eight bits provided. Here are the rules for bit setting: A succesful IF (or unsuccesful IF NOT) leads to setting of the bit. An AND (or AND NOT) statement will be inspected only if the bit is set. If succesful (or not succesful if AND NOT) the bit remains, else it is cleared. An OR (or OR NOT) statement will be inspected if the bit is not set. If succesful (or not succesful if OR NOT) it sets the bit. The substitutions or commands following such a sequence will be inspected if the bit is set. After an ELSE the substitutions or commands will be inspected if the bit is cleared. Do not put any substitutions or commands inbetween the IF, AND or OR statements if there is an ELSE. The reason is that substitutions and commands following an ELSE are on the same level as those following the preceeding IF, AND, OR group. The ELSE becomes ambiguous in such a case. Also, no AND or OR after an ELSE, which is also ambiguous. The fact that an expression may be given on the IF, AND, OR lines allows very compact code. For example, to integrate any polynomium in x (see Example 15): IF NOT x^-1 = [Log(x)] AND NOT x^n~ = x^(n+1)/(n+1) Al,Addfa,x ENDIF The command Addfa attaches the factor given, here x. That command will be executed only if none of the two previous substitutions applied. Note the use of Al (rather than Id) for the Addfa statement. This may be done because this statement is not using anything that might be produced by the previous IF and AND statements. Note the symbol (we stress, the symbol) [Log(x)]. Here some comments about level assignments. Schoonschip assigns all IF, AND and OR statements to the same substitution level. IF is as Id, OR and AND as the Al type assignement. A later ELSE is assigned to the same level as the associated IF. The first substitution following an IF, AND, OR sequence may have Id or Al; the level assigned is as usual. If none of the IF etc substitutions actually perform substitutions then one should use Al. However, if that substitution needs the completion of the previous IF etc substitutions then Id should be used. The same holds after an ELSE, where Id must be used for the first substitution following that ELSE if that substitution needs the completion of the IF etc substitutions. Note that these latter substitutions may be way up. If an AND or OR substitution depends on the result of previous IF etc substitutions then it should not have an Al type assignment as Schoonschip would use. To force level alignment for such a case simple put a line with Id before the AND or OR statement, like IF a1=2*(a1+a2) Id AND a1=(a4+a5) Example: L 1 IF a3=2*(a1+a2) L 1 AND a7=5*a1*(a7+a8) L 3 Id,a1=0 L 4 Id,Count,x,a1,1 : L 1 ELSE L 3 Id,a1=3 ENDIF L 5 Id,... The last level shown (L 5) is the maximum of (level when reaching ELSE, level when reaching ENDIF). Compare with Al use: L 1 IF a3=2*(a1+a2) L 1 AND a7=5*a1*(a7+a8) L 1 Al,a1=0 L 3 Id,Count,x,a1,1 : L 1 ELSE L 1 Al,a1=3 ENDIF L 4 Id,... 12. COMMANDS. Sometimes certain operations are difficult or impossible to do with substitutions, and a number of facilities have been build in that deal with specific situations. They are generally called commands, and they perform actions at the Level that they have been placed. They generally need at least one level, and sometimes the number of levels to be used influences the performance. The general syntax of a command is: Id,Keyword,parameters separated by commas in which case Schoonschip uses a number of levels depending on the command. Alternatively, with # some number < 40: Id,#,Keyword,parameters separated by commas in which case Schoonschip sets aside # levels for this command. There is one command for which this is quite relevant, namely Gammas. Now to more specifics. Suppose that some function is symmetric in its arguments, say f1(a,b,c)=f1(b,a,c)=... In such a case one would like the arguments to be arranged always in the same order. The command Id,Symme,f1 causes Schoonschip to inspect every function f1 that passes by at this Level, and arguments are re-arrangered in a well defined way (first defined symbols first). This is of course much easier than the perhaps very long set of substitutions that would do the same thing. One would have to know beforehand what arguments could appear, and then go through all combinations. For commands the first four, if no confusion possible the first three characters are relevant. The may be in upper or lower case. The following commands are available: Absol Make the sign of the numerical coefficient plus Addfa Add factor Anti Inspects functions for characters with an _ Asymm Function anti-symmetric under interchange of arguments All Rounds up all appearances of a vector, or appearances of all vectors in a specified function. Beep Sent Control-G to the terminal (which normally beeps at that) Coef Inspect numerical coefficient Commu Re-arrange commuting functions Compo Compose names from characters Count Count certain occurrences Cyclic Function invariant under cyclic permutation of arguments Dostop Clears, sets or tests the forced DO-loop exit flag. Epfred Reduce products of Epf functions Even Function even in sign of arguments Expand Expand frozen files Extern Call user defined subroutine Gammas Throw the book at Gamma matrices Iall Inverse of All Numer Insert numerical values Ndotpr Construct anomalous dot-products (for use with Gammas) Odd Function odd in sign of arguments Order Order functions as based on the first two arguments Print Prints message Ratio Rationalize Spin Sum over spins of spinor functions Ug, Ubg Stats Counts how often this command is called Symme Function symmetric under interchange of arguments We will discuss them one by one. First the general format is shown, and then some example is given. Commands may also occur in IF etc statements, but often it is not well defined what means succes or failure. As a rule succes is defined as 'some action has been taken'. For example, Addfa will always give succes. Ordering inside Schoonschip is always done on the basis of 'smallest first', not only for the purposes of the commands of this section, but also for output printing of the quantitities not mentioned in the B-list. This means the following ordering for quantities of different kind: Index, Vector, Function, Algebraic symbol, Characters, Number (short numbers), Vector-component, Dot-product. For quantities of the same kind the ordering is according to the moment at which the quantity was encountered first. For dot-products the earliest defined vector counts first. To guarantee a certain ordering the quantities can be given in the appropriate list in the desired order. With respect to numbers the counting is not entirely as one might expect: 0 before positive numbers up to 127, then 128=-128, -127, -126,..., -1. This is because of the two's complement notation for numbers. *** Id,Absol The coefficient of the term inspected is forced positive. This command needs no levels. *** Id,Addfa,expression The expression specified is attached as a factor. This command is mainly intended for use with conditional statements; the expression can be attached depending on previous actions. There are no particular limitations on the sort of expression that can occur here; anything allowed in a Z expression or in the right hand side of a substitution is allowed here, although here no dummies can be specified. Example 15. Integration of polynomium. A a,b,c,d,e,x Z xxx = a*x^2 + b*x + c + d/x + e/x^2 IF NOT x^-1=[Log(x)] AND NOT x^n~=x^(n+1)/(n+1) Id,Addfa,x ENDIF *end The command All (and the associated Iall) has two different syntaxes. In the first syntax the first argument is a vector (must have been defined before): *** Id,All,p,N,F Optionally this list may be followed by the character arguments "F_, "D_ or "V_ (always separated by commas), and possibly an index list, see below. For the second syntax the first argument is a function (must have been defined before): *** Id,All,Fx,N,F The parameters p,N and F must have been defined previously as vector, algebraic symbol (it must be a one character symbol) and function. The parameter N may be absent. First syntax: All occurrences of the vector p are considered. If any qualifying p found the function F is appended. Next this function obtains arguments reflecting the p found: - If p(mu) with mu any index is seen this p is removed and the argument mu is added to the argument list of F. - If pDq with any q and a positive exponent (say pDq^n) then the argument q is added n times. - If pDp with a positive power (say n) is seen then a new index is created. This index is added 2*n times. - If p is seen as argument of any function then an index is created. This created index replaces p as function argument, and furthermore the index is added to the arguments of F. In the above work, whenever an index is created, it is given the symbolic dimension N, or the default dimension (=4) if no N specified. The main use of this command is to facilitate integration with the vector p as integration variable. Optionally character arguments may be specified after the list shown above. The allowed characters are: "F_ "D_ "V_ If "F_ seen no function arguments will be inspected. "D_ inhibits dot-product inspection, "V_ single vectors. Example: Id,All,p,N,F,"F_,"V_ Only dot-products are considered. Second syntax: All arguments of the funtion Fx are considered. If a given argument is a vector then that vector is replaced by a created index. The function Fq obtains two new arguments, namely the vector and the created index. In the final result the arguments of Fq are: first all vectors, then the corresponding indices. For example, All,Fx,N,Fq applied to Fx(p,k,q) gives Fx(Naa,Nab,Nac)*Fq(p,k,q,Naa,Nab,Nac). It is clear that the All command will in general give rise to created indices. Such indices are often renamed by Schoonschip, in order to achive a well defined result in the output. This renaming may sometimes be undesirable, in particular there may be undesirable consequences when later a Freeze command is issued; the Freeze command may offer trouble if a created index appears in a pair, one outside and one inside the brackets. To handle such cases one may assign to the All command a list of indices after the last function (and the possible V_ etc). These indices must be defined in the I list, with the same dimension as that specified in the All command, and they will be used rather then newly created indices. Example: I al1=N,al2=N,al3=N : : Id,All,p,N,Fx,D_,al1,al2,al3 It may be that more indices are needed then provided in the list. There are two options here. If the command is as above, and if the list is exhausted then Schoonschip will issue an error message. If the list is terminated with the character C: Id,All,p,N,Fx,D_,al1,al2,al3,"C then Schoonschip will, after using up al1-al3, create further indices as needed. C Example 16. V p,q F F I mu=N,nu=N Z xx= pDp^2 * pDq^3 * F1(p,p,q,p) * p(mu) * q(nu) Id,All,p,N,F P output *yep C Showing the dimensionality of the created indices: Id,F(i1~,i2~,i3~,i4~,i5~,i6~,i7~,i8~,i9~,i10~,i11~)= F(i1,i2,i3,i6,i7,i8,i9,i10,i11)*D(i4,i5) *begin C A more realistic example. I al,be,mu,nu A N,N_ V p,k F F,F20,F22 Z xx = G(1,1,al,be,p,al,be,p) Id,All,p,N,F P output *yep Id,F(i1~,i2~) = D(i1,i2)*F20(k) + k(i1)*k(i2)*F22(k) *end *** Id,Anti,TA All function arguments are inspected for character arguments ("X). If a character with underscore is seen the character table TA is consulted. If that character appears in that table the underscore is removed. This command will be discussed further in the section on character manipulations. *** Id,Asymm,F1,2,3,4,F2,F3,4,5 This command specifies that f1 is anti-symmetric in arguments 2,3 and 4, f2 in all arguments and f3 in arguments 4 and 5. If the arguments are not in the 'first defined first' order the arguments are permuted. If the permutation is odd a minus sign is attached. If a number in the list is larger then the number of function arguments that number is ignored. There is a second syntax for this command that can be used if the arguments occur in groups: *** Id,Asymm,F1:2,3,4:7,8,9:12,13,14: The groups of numbers within colons denote argument groups. They need not to be sequential. Only the first argument of a group is used in the comparison. However, if an interchange is needed both groups are interchanged as a whole. For example, if in the above case argument 7 is to placed before argument 2 than 2 is interchanged with 7, 3 with 8 and 4 with 9. If the arguments are sequential an even shorter syntax is allowed: *** Id,Asymm,F1:1-3:7-9:12-14: The number of arguments in each group must of course be the same. Note: for symmetric functions see command Symme. Example 17. V p,q,k I mu A a,b,c,d,e,f,g,h F F1,F2,F3 Z xx = F1(e,d,c,b,a) + F2(e,d,c,b,a) + F3(e,d,c,b,a) + F2(-125,-30,-1,0,30,125) + F2(pDq,pDk,kDq,p(3),q(2),F2,7,mu,p,a) + f1(e,f,g,d,a,b,c,h,k) Id,Asymm,F1,2,3,4,F2,F3,4,5 Al,Asymm,f1:1-3:5-7: *end The command *** Id,Beep,# sends a Control-G to the terminal. This normally results in a beep. It may be used to signal audibly certain occurrences. Be careful though; one quickly gets a lot of noise. The number # limits that: at most # beeps will be issued. The number # must be positive and less than 128. Example: IF a^10 Al,Beep,3 ENDIF The Beep statement (not this command) may be used to generate some noise at termination, or if an error occurs. The command Coef essentially inspects the numerical coefficient of any term passing by, and here specifically use with conditional substitutions is intended. The syntax is: *** IF Coef,option Of course, this command can also be used with AND or OR, with ot witthout a NOT. The possible options are: pl plus ng negative eq,# equal lt,# less than gt,# greater than ib,#,# inbetween Here # represents a number (any number, not just short numbers). When a term passes by the coefficient is inspected or compared, and the IF bit is set or cleared depending on the result. Concerning equal, two numbers are considered equal if they agree within the number of decimal digits specified by the Precision statement (25 default). The naming of the options corresponds closely to the way the IF bit is set: y set IF bit (or clear if IF NOT) If Coef,option n clear IF bit (or set if IF NOT) C Example 18. A a1,a2,a3,a4,alt1,agt2,aeq15,ai12 Z xxx= 0.5*a1 + 1.5*a2 + 2.5*a3 + 1.E-20*a4 IF Coef,lt,1. !Add factor alt1 if coefficient < 1. Id,Addfa,alt1 ENDIF IF Coef,gt,2. !Add factor agt2 if coefficient > 1. Id,Addfa,agt2 ENDIF IF Coef,eq,1.5 !Add factor aeq15 if coefficient = 1.5 Id,Addfa,aeq15 ENDIF IF Coef,ib,1,2 !Add factor ai12 if coefficient inbetween 1 and 2. Id,Addfa,ai12 ENDIF IF Coef,lt,1E-15 !Delete the term if coefficient < 1E-15. Id,Addfa,0 ENDIF *end As shown, this command can be used effectively to eliminate 'dirt'. The command Commu is used for ordering commuting functions. The ordering is done (i) with respect to the name of the function (smallest first, see the introduction of this section) (ii) number of arguments (iii) arguments. *** Id,Commu,F1,F2,F3,... If the commuting functions occur nested between other functions then they are taken out and placed behind these other functions. Thus the Commu command may be of consequence even if there is only one function named, and if that function occurs at most once in a given term. Example 19. A a1,a2,a3,a4,a5 F F1,F2,F3 Z xx = F3(a1,a2)*F1(a1,a2,a3)*F1(a4,a5) + F1(a1,a2,a4)*F2(a1,a2,a3)*F1(a1,a2,a3) + F3(a1,a4)*F2(a1,a2,a3)*F1(a1,a2,a4)*F2(a3,a4,a5) Id,Commu,F1,F3 *end The IF bit is set if any of the named functions is present. The Compo command is quite complicated, and realistic application are not well suited for description in this manual. We will nevertheless give a complete description of this command. It involves character manipulation and may lead to the generation of new symbols including functions. There is a way to correlate the created name of a function with the arguments specified. Combined with the use of Tables (Tables can also have characters in the list) this is a very powerful tool to generate many symbols or also functions reflecting a topology. For a very simple application see also the example demonstrating the command Count, Example 21. *** Id,Compo,"X,TA,,F1,F2,,F3,F4,.. The character argument "X may be absent, or it may be "S or "S_. The character table argument TA may be absent. If present it specifies characters for which "X_="X (anti-particle = particle). If not given the default is used, which may be none, or one defined by means of the Anti statement. Briefly, Compo takes the character arguments found in F1 etc, permutes them into a well defined order (unless "S_ is specfied for "X) and at the same time permutes argument groups in F1. The characters are then glued together and either identified with an existing name, or if not existing the name is entered in some name list, or the term is discarded depending on the options specified. The functions F1,F2,... are inspected. The arguments are expected to have the following structure: F1(c1,c2,c3,..,cn,/,d1,d2,..,dm,*,arg1a,arg1b,.,*,arg2a,arg2b, ..,*,argka,argkb,..) In here c1..cn and d1...dm are characters, with the notation ". Legal are: upper and lower case characters and number characters possibly followed by an underscore. They may also be vectors, in which case the character(s) of the vector name are used. Either n or m may be zero, but not both. If m is zero the / needs not to be given. The arguments arg1a,arg1b etc correspond to character c1, arg2a,arg2b etc to character c2 and so on. The sum of n and m must not exceed 6 (not counting the underscores), and not 2 if the name to be constructed is to be a vector name. The characters c1-cn are subject to the ordering process, the d1-dm not. Concerning the argument groups (arg1a,arg1b,..),(arg2a,arg2b,...),..., (argka,argkb,...) the following: - an argument group may be empty. This corresponds to two successive * separated by a comma; - the number of argument groups may be less then the number of characters c (i.e. k less than n). In that case argument groups k+1, k+2,.. are considered empty; - the number of argument groups may be larger then the number of characters c (i.e. k larger than n). Access groups are not considered in the actions described below and are simply reproduced. When encountering such a function Schoonschip inspects the characters and permutes them according to the standard character ordering (A-Z, a-z, 0-9; characters followed by an underscore are ordered just before the corresponding character without underscore: A,B,C_,C etc). The sets of arguments arg1a,arg1b,.., arg2a,arg2b,.. are permuted in tune with this. Thus if for example only c1 and c2 are exchanged then the argument list reads afterwards: *,arg2a,arg2b,..,*,arg1a,arg1b,..,*,arg3a,... No permutation is done with respect to the characters d1,d2,... No permutation is done if the character variable "S_ (no symmetrization) was given in the argument list of Compo. Next all characters are glued together, thus forming a name. This name is searched for in the lists mentioned in 'options'; if found that name is identified with that variable. If not found the action taken depends again on the option specification. If a list is mentioned twice then the new name is added to that list and new occurrences will be identified with that name. If no list is specified twice in options then the whole term is discarded. In the option list, enclosed between < >, the characters X A F V I may appear once, the characters A F V and I also twice. Thus no new entries can be made to X-expressions, but the X table (which includes also D and T expressions and files) can be searched. At most one character can occur twice. There is a default option: meaning search all lists, and if not found insert in algebraic symbol list. After identification of the name the corresponding symbol is made to be the first argument of the function, replacing all c and d characters and the optional /. Then all * are removed. The result is a function with as first argument the constructed symbol, and the following arguments is what results after the permutations among the argument groups. In subsequent substitutions one may work this function out to whatever is required. C Example 20. F F1,F2 A a,b,c,d Z xx = F1("c,"b,"a,/,"e,*,a1,a2) + F1("c,"b,"a,/,"e,*,a1,a2,*,xy) + F1("c,"b,"a,/,"e,*,a1,a2,*,xy,*,a2) + F1("c,"b,"a,/,"e,*,a1,a2,*,xy,*,b2,*,xz) + F2("a,"b,/,"F,*,x,*,y,*,z1) + F2("b,"a,/,"F,*,x,*,y,*,z1) + F2("F,"c,"b,"a,*,*,z,*,y,*,x) + F2("F,"c,"b,"a,*,*,z,*,yp,*,x) Id,Compo,,F1,,F2 Id,Always,F2(F1~,a~,b~,c~,d~,e~) = F1(a,b,c) Id,F1~(a~,b~,z1) = F1(a,b) *begin Notes: concerning the first group, F1, various possibilities concerning number of argument groups are demonstrated. The option specified for this in the Compo command is actually the default option and could have been omitted. In the second group it is shown how various functions with arguments can be created, even with different number of arguments. To this purpose the fake argument z1 was introduced in the first two cases. The function substitution for F2 works no matter how many arguments, but one must take care that in the right hand side no undefined quantities appear. This means that the function F2 should not occur with less than 3 arguments. Unfortunately it is not possible to handle empty arguments here. The fake argument z1 is removed in the last substitution. Note also dummy use in the substitutions. For function dummies we used a function symbol defined in the F-list (F1 in this case). Disaster may result if this is not done. It is extremely difficult to analyze for all possible cases that may occur if that type of error is made, and many cases will lead to cryptic error messages seemingly unrelated to this. A second example shows the use of Compo together with Tables. It is a rather artificial example, but it shows the main ideas. Suppose an electric circuit must be build up from 4 three-pole elements connected by diodes, in the configuration shown: j1 i1 ---0-------0--- i3 j4 | |j2 | | i2 ---0-------0--- i4 j3 The currents i1 and i2 are flowing inwards, i3 and i4 outwards. j1-j4 are taken to flow clockwise. The 3-pole elements have three external connections called A, B and C. The connecting elements are diodes, the connections are called B and C. B of a diode may be connected to a B from a 3-pole, C to the C of a 3-pole. One might think here of emitter and collector of a transistor. The main object is now to generate all possible configurations, which is very simple in this case, one may either have all the diodes oriented clock-wise, or all oriented counter-clock-wise. Also one wants to exhibit the currents flowing through the various objects. Once the expression involving all elements with the currents is obtained explicitly one can go on and work out whatever is wanted. If the connecting elements are for instance a diode, resistor and battery in series one can compute all currents as function of the input/output currents i1-i4, but we will leave this to the imagination of the reader. In the example below the function v3 represents the 3-pole. The only combination to be recognized is the combination ABC. Thus only the function ABC is defined, and in the options of Compo the F-list is mentioned only once. Things like AAB or ACC will then be thrown away. Below we simply sum over all possibilities for the connecting lines (i.e. AA, BC and CB) leaving it to Compo to keep only those combinations that contain exclusively the functions ABC and BC. A new feature in this example is the occurrence of characters in the lists for the Tables Ch and Cg. While not exhibited here there is another facility build in. Normally one refers to a table-element by means of the table name followed by a number. One may also refer to table elements by means of the table name followed by a character. Then the number associated with that character (given above) is used to pick out the correct element. This is useful if certain properties have to be associated with a character. T Ch(n)="A,"B,"C T Cg(n)="A,"C,"B F BC,ABC A i1,i2,i3,i4,j1,j2,j3,j4 Z solu = square("A,"A,"A,"A) Id,square(c1~,c2~,c3~,c4~) = DS{L1,1,3,(DS{L2,1,3, (DS{L3,1,3,(DS{L4,1,3,( v3(c1,Ch(L1),Cg(L4),*,i1,*,-j1,*,j4)* con(Ch(L1),Cg(L1),*,j1,*,-j1)* v3(c3,Cg(L1),Ch(L2),*,-i3,*,j1,*,-j2)* con(Ch(L2),Cg(L2),*,j2,*,-j2)* v3(c4,Cg(L2),Ch(L3),*,-i4,*,j2,*,-j3)* con(Ch(L3),Cg(L3),*,j3,*,-j3)* v3(c2,Cg(L3),Ch(L4),*,i2,*,j3,*,-j4)* con(Ch(L4),Cg(L4),*,j4,*,-j4) ) } ) } ) } ) } Id,Compo,,v3,con Id,v3(f1~,a1~,a2~,a3~) = f1(a1,a2,a3) Al,con(f1~,a1~,a2~) = f1(a1) *end The command Count has grown out of the need to have a facility that selects terms on the basis of certain asymptotic properties. One may know of various functions and other quantities how they behave as function of some variable for certain limiting values of that variable (like for example behaviour as function of x for very large x). With Count one can for instance select terms that behave for large x as x^n with n larger then some given number. This is the most typical application. But the command allows many other things, here is the description. *** Id,Count,xxx,arg1,#,arg2,#,.... In case that xxx is a function or X-expression the format is: *** Id,Count,Fx,arg1,#,arg2,#,...,# : arg3,#,...,# : arg4,#,... The colon's separate groups of arguments. Optionally, function names preceeded by "F may be specified directly after the first argument of Count or after the semicolons, if any: *** Id,Count,Fx,"F,Fy,"F,Fz,arg1,#,arg2,#,...,# :"F,Fc,arg3,#,...,# In here arg1, arg2 etc may be indices, vectors, algebraic symbols or functions. As a first step, investigating a term, a number is constructed. This number is the sum of numbers obtained for individual factors. The number for an individual factor is the exponent of that factor (if applicable) multiplied by the number following the corresponding argument in the Count list. Thus if in the Count list x,7 occurs than a x^3 in a term leads to a contribution of 21 to the number being constructed. If no exponent (as would be the case for a function or vector) the number from the list is added once. The contribution of vector-components or dot-products is computed on the basis of the value assigned to the corresponding vectors in the list. Thus p,2,q,5 leads to 21 for pDq^3 and 10 for q(3)^2. In constructing the number function arguments or vector indices are not investigated. However, function argumnts of functions specified with the "F option are counted as single occurences. Thus, the statement Id,Count,xxx,"F,Fa,a,35,b,1 leads to the count 38 for the term b^2*Fa(a,b,c). The action taken next depends on what occurs as first argument in the Count list (i.e. xxx above): - If xxx is a number then the constructed number is compared with xxx. If the constructed number is equal or larger than xxx the term is kept Else the term is deleted. - If xxx is an algebraic symbol, vector component or dot-product the constructed number is made to be the exponent of that symbol and the combination is attached to the term. - If xxx is a function or X-expression then the number is made to be the argument of that function or X-expression and the combination is attached to the term. A multiple count can be made. The occurrence of a colon (:) in the count list signals that subsequent counts must be put in subsequent function arguments. Thus if two colons occur a three argument function is created. The list up to the first colon is used to compute the value of the first argument, the argument list between first and second colon determines the value of the second argument, etc. Example: consider the term a^3*b^2*pDk with p and k vectors. The command Id,Count,Fc,a,1,b,2 : p,2,k,3 (Fc defined before to be a function) generates a two argument function Fc: Fc(7,5)*a^3*b^2*pDk The fact that Fc may also be an X or D-expression allows for very compact but quite complicated counting. If Fc is a non-numeric X or D expression then possibly several substitution levels are needed to work out the result, and in this case Schoonschip does not automatically count that. For purely numeric X and D expressions only one level is needed. To insure proper level spacing in case of non-numeric Fc write a dummy substitution involving Fc directly before the Count command and use Al for the Count command: Id,XxxX=Fc Al,Count,Fc,a,1,b,2 : p,2,k,3 where XxxX is not occurring anywhere else. In the following example we do not only demonstrate Count, but show also some other application of Compo. The coefficients a1-a5 are constructed and entered in the A-list (remember default options Compo is ). Also the use of Keep and *next is shown. Example 21. A x,y T tt(n) = "1,"2,"3,"4,"5 C Here a complicated way to make C pow(x) = a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5. Z pow(x) = DS(J,1,5,{f1(/,"a,tt(J))*x^J}) Id,Compo,f1 Id,f1(y~) = y Keep pow *next Z xx = pow(x) Id,Count,3,x,1 Keep pow *next Z xx = pow(y) Id,Count,f1,y,2,a3,10 Keep pow *next V p,q A AA Z xx = pow(y)*f1(a2,a3)*pDq^2 Id,Count,AA,y,2,f1,-4,p,1,q,3 *end The commands Cyclic and Symme are analogous to Asymm, except that invariance under cyclic permutation or simply exchange of arguments is implied. *** Id,Cyclic,F1,2,3,4,F2,F3,4,5 *** Id,Symme,F1,2,3,4,F2,F3,4,5 For the command Symme the alternative syntaxes used to denote groups of arguments can be used: *** Id,Symme,F1:2,3,4:7,8,9:12,13,14: *** Id,Symme,F1:1-3:7-9:12-14: As to Cyclic, the arguments are permuted following the pattern specified in the Cyclic list, which may make things pretty obscure as the following example shows. The arguments specified are permuted till 'smallest first'. Example 22. A a,b,c,d,e Z xxx = f1(e,d,c,b,a) + f2(e,d,c,b,a) + f3(e,d,c,b,a) Id,Cyclic,f1,2,5,4 Id,Symme,f2,f3,2,3,4 *end *** Id,Dostop,on *** Id,Dostop,off *** Id,Dostop The command Dostop may be used to set, clear or test the forced DO-loop exit flag. If this flag is set then the next ENDDO encountered is taken to be satisfied. This command may be used to execute a set of substitutions and commands followed by a *yep repeatedly till some condition is satified. Here a typical example: Z xx = a^10 DO J=1,100 Dostop off Id,a1^n~=a1^(n-1)*b IF NOT a1 ..Id,Dostop,on ENDIF *yep ENDDO *end The DO-loop sequence will be re-executed 100 times or till no more a1 present. In the case shown the cycle is run 10 times and the result is b^10. Note that: - The Dostop statement and command are within the same program segment (i.e. there is no line with an * inbetween); - The last line of the DO-sequence contains an * in column 1. Refer to the remarks on the Dostop statement for more details. The Dostop command may have other or no parameters: Id,Dostop,off Id,Dostop In the last case the Dostop flag is tested, but not modified. The command may be used in conjunction with an IF: IF Dostop ... ENDIF A set flag implies 'yes'. The command Epfred leads to reduction of products of Epf with equal number of arguments to one Epf. *** Id,Epfred The simplest case is for two arguments: Epf(i1,i2)*Epf(i3,i4) = D(i1,i3)*D(i2,i4) - D(i1,i4)*D(i2,i3) In three dimensions this is the equation that rewrites the product of two cross products in terms of dot-products. If p, q and k are vectors, than the pseudo-scalar (k.pxq) is given by Epf(k,p,q). If pp, qp and kp are also vectors then the product (k.pxq)*(kp.ppxqp) can be rewritten in terms of dot- products. Similar relations hold in higher dimensions. Note: the product of two Epf of different dimension is not reduced. Example 23. V p,q,k,pp,qp,kp Z xxx = Epf(k,p,q)*Epf(kp,pp,qp) + Epf(i1,i2,i3,i4)*Epf(i1,i2,j3,j4) Id,Epfred *end The commands Even and Odd specify that some function is even or odd with respect to change of sign of certain arguments. Minus signs of such arguments are removed. *** Id,Even,f1,2,3,4,f2,f3,4,5 *** Id,Odd,f1,2,3,4,f2,f3,4,5 Example 24. F f1,f2,f3,f4 Z xxx = f1(-a1,-a2,a3,-a4) + f2(-a1,-a2,a3,-a4) + f3(-a1,-a2,a3,-a4) + f4(-a1,-a2,a3,-a4) Id,Even,f1,2,3,f2 Id,Odd,f3,2,3,f4 *end The command Expand occurs in combination with frozen files. See the section on freezing a file. Syntax: *** Id,Expand,fname In here fname is the name of a frozen file. All frozen subfiles referred to through the function DF or expanded. *** Id,Extern,arg1,arg2,... The command Extern allows entering an of external routine as integral part of Schoonschip. First one needs the statement External: External filename The statement External, specifying an external file, leads to loading of that file in working space. The command Extern leads, at execution time, to a jump to the first location of that file. If that file contains position independent executable code then manipulations on expressions can be performed. This requires an understanding of the formats used inside Schoonschip, and supposes the ability to generate such a file. The interface provides acces to all arrays, and also utilities such as print routines etc inside Schoonschip can be used. The information will not be given here, but is available. Roughly speaking, a whole series of addresses is passed on as a structure on the stack. The arguments are passed on in the form of an array. In principle this facility allows the creation of special packages designated for specific problems. *** Id,Iall,p,F *** Id,Iall,F Inverse of All for the two possible syntaxes. Do not use Iall if the indices that occur as argument may have dimensional restrictions (Dim_N or Dim_4) as created when doing gamma algebra, command Gammas. The command Ndotpr is to be used in such cases. *** Id,Gammas, loop indices + options, Trace, loop indices + options This command will be discussed in a separate section: Gamma algebra. The command Numer can be used if numerical values must be inserted for certain quantities. The format is: *** Id,Numer,arg1,#,arg2,#,... The numbers need not to be short numbers, they can be anything. Function arguments are not considered. The arguments may be algebraic symbols, vector components or dot-products. Example 25. V p,q Z xxx = a1^2*pDq^3/p(4) Id,Numer,a1,2,pDq,1.E10,p(4),1.E5 *end The command *** Id,Ndotpr,F1 is closely related to the Gammas command and will be discussed in the section on Gamma algebra. *** Id,Order,F1,F2,... This command searches for the functions F1, F2.... and builds a chain on the basis of the first two arguments. First the function F1 is searched. The second argument is taken, and looked for in other functions. If found, the new function is chained to the previous. Etc. One index is kept in the collected Faa, namely the first seen. There are two additional options for this command. Specifying the character "C (for collect) as first arguments leads to collection of all arguments except the first two into one function. Specifying a number as first argument gives that number as first argument to the collected functions of the first chain collected, that number+1 to the second, etc. The option "C may be combined with this. If the number given is zero no first argument is kept. Examples (the output is reproduced here): Z x1 = Faa(4,5,ddd)*Faa(2,3,bbb)*Faa(1,2,aaa)*Faa(3,4,ccc) Id,Order,Faa x1 = + Faa(1,aaa)*Faa(1,bbb)*Faa(1,ccc)*Faa(1,ddd) + 0. Z x1 = Faa(4,5,ddd)*Faa(2,3,bbb)*Faa(1,2,aaa)*Faa(3,4,ccc) Id,Order,"C,Faa x1 = + Faa(1,aaa,bbb,ccc,ddd) + 0. Z x1 = Faa(4,5,ddd)*Faa(2,3,bbb)*Faa(1,2,aaa)*Faa(3,4,ccc) Id,Order,90,Faa x1 = + Faa(90,aaa)*Faa(90,bbb)*Faa(90,ccc)*Faa(90,ddd) + 0. Z x1 = Faa(4,5,ddd)*Faa(2,3,bbb)*Faa(1,2,aaa)*Faa(3,4,ccc) Id,Order,90,"C,Faa x1 = + Faa(90,aaa,bbb,ccc,ddd) + 0. Z x1 = Faa(4,5,ddd)*Faa(2,3,bbb)*Faa(1,2,aaa)*Faa(3,4,ccc) Id,Order,0,Faa x1 = + Faa(aaa)*Faa(bbb)*Faa(ccc)*Faa(ddd) + 0. Z x1 = Faa(4,5,ddd)*Faa(2,3,bbb)*Faa(1,2,aaa)*Faa(3,4,ccc) Id,Order,0,"C,Faa x1 = + Faa(aaa,bbb,ccc,ddd) + 0. *** Id,Print,#,Message This command can be used to print a message at execution time. The number # limits the number of times the message is printed. Everything after the third comma, including blanks, up till the end of the line is printed when this command is encountered at execution time. Example: Id,2,Print, Hello world. The message " Hello world." is printed at most twice. The command Ratio is specifically there to facilitate integrations. It is used to rationalize a product of factors that are linear in the integration variable. The simplest case is: 1/(x+a) * 1/(x+b) = {1/(x+a) - 1/(x+b)}/(b-a) Since in Schoonschip expressions cannot have a negative exponent (except when they are purely numerical) one cannot directly write such things. The way to do that is to introduce a symbol to represent an expression appearing with negative exponent, for example xpa = x+a. Then the equation becomes: xpa^-1*xpb^-1 = {xpa^-1 - xpb^-1}*bma^-1 Here the [] notation for symbols comes in very conveniently. One may write: [x+a]^-1 * [x+b]^-1 = {[x+a]^-1 - [x+b]^-1}/[b-a] If the exponents are large this becomes quite complicated, and that is where Ratio comes in. In the command one must specify the two factors and their difference, in the case mentioned one would write: *** Id,Ratio,[x+a],[x+b],[b-a] Ratio works for all cases of exponents that may occur, positive or negative. C Example 26. A a1,a2,a2ma1 F f1 B b2,b3,b4,b5 Z xx=f1(8,4) Id,f1(n~,m~)= { b2*a1^n*a2^m + b3*a1^-n*a2^m + b4*a1^n*a2^-m + b5*a1^-n*a2^-m } Id,Ratio,a1,a2,a2ma1 *begin C Here the use of Ratio with [] names. B [b-a] Z xxx = 1/[x+a]^3 * 1/[x+b]^2 Id,Ratio,[x+a],[x+b],[b-a] P output *yep C Just checking... Id,[x+a]^n~ = (x+a)^(3+n)*(x+b)^2/[x+a]^3/[x+b]^2 Al,[x+b]^n~ = (x+a)^3*(x+b)^(2+n)/[x+a]^3/[x+b]^2 Id,b = [b-a] + a *end *** Id,Spin,loop indices or momenta This command is discussed in the section on particle physics. *** Id,Stats,# This commands provides for some statistics. The counts are printed at conclusion of a section (delimited by a * type line). Four counts may be kept, specified by the number # which may be absent implying 0, or one of numbers 1, 2 or 3. No error message is given if the number exceeds 3 or is negative; Schoonschip takes the number modulo 4. Every time this command executes one is added to the appropiate count. Example: IF a^3 Id,Stats,2 ENDIF This construction counts the number of terms with a^3. The result is printed at termination. 13. PARTICLE PHYSICS. There are a few build-in facilities that are particularly useful to particle physics. We refer here to gamma-matrices and traces of products of gamma matrices. The special functions G,Gi,G5,G6,G7,Ug and Ubg are reserved to denote gamma matrices and spinors. Since in a given calculation more than one loop of gamma-matrices can occur all functions have a loop index. Gamma's with different loop indices are supposed to commute. The relation to the standard notation for these quantities is (old notation): G(L,mu) gamma-matrix with index mu of loop L. Gi(L) the identity matrix of loop L. G5(L) = G(L,1)*G(L,2)*G(L,3)*G(L,4). G6(L) = Gi(L) + G5(L). G7(L) = Gi(L) - G5(L). Ug(L,m,p) spinor loop L, particle mass m, momentum p, spin 1/2. Ubg(L,m,p) Conjg{Ug(L,m,p)}*G(L,4). Ug(L,mu,m,p) spin 3/2 spinor. Ubg(L,mu,m,p) Conjg{Ug(L,mu,m,p)}*G(L,4) With the Schoonschip version of Jan 1, 1989 new notations have been introduced for the gamma matrices. The above notation is still accepted, but the new is more flexible and we will use that. In this new notation gammas have two loop indices. They may also have more than one index. The order of these two-index gammas is immaterial; at some point, when traces or spin summation or whatever is to be done (usually with the command Gammas) the gammas are chained on the basis of these two loop indices. Example: Ug(i3,M,q)*G(i1,i2,mu)*G6(i0,i1)*Ubg(i0,m,p)*G(i2,i3,nu,al) This will be chained into one gamma string (called G-string in the following): Ubg(i0,m,p)*G(i0,"s,"6,mu,nu,al)*Ug(i0,M,q) equivalent to the old sequence Ubg(i0,m,p)*G6(i0)*G(i0,mu)*G(i0,nu)*G(i0,al)*Ug(i0,M,q) This takes the pain out of the process of ordering the gammas. Inside G-strings "4, "5, "6 and "7 may occur next to Gi, G5, G6 and G7 but they mean the same. An anti-particle spinor may be represented as a particle spinor with -m instead of m. The G's satisfy the rule: G(L,"s,"4,...,mu,nu,..) = - G(L,"s,"4,...,nu,mu,..) + 2*D(mu,nu)*G(L,"s,"4,.....) which is the usual anti-commutation rule. All G are treated by Schoonschip as imaginary, which corresponds to a hermitean set. In complex conjugation the order of the G is to be reversed (i.e. the order inside a G-string is reversed). G5 is imaginary, G6 and G7 are each others complex conjugate. The commands Gammas and Spin allow for reduction of a product of G's to at most 2 G's, Trace taking and Spin-summation. The build-in equations can handle 4-dimensional and N-dimensional situations, with ot without G5's. The command *** Id,Spin,L1,p,... leads to spin summation. Schoonschip looks for pairs of spinors Ug and Ubg with the same arguments except the loop index (one of the loop indices must be mentioned in the list), and replaces such pairs by the appropriate combination. Instead of a loop index also vectors may serve as identification. With the command Id,Spin,p or Id,Spin,L1 the expression Ug(L1,m,p)*Ubg(K1,m,p) is replaced by - i*G(L1,K1,p) + m*Gi(L1,K1) Similarly for spin 3/2 spinors: Ug(L1,mu,m,p)*Ubg(K1,nu,m,p) is replaced by: { D(mu,nu) - 1/3*i*G(L1,K1,mu)*p(nu)/m + 1/3*i*G(L1,K1,nu)*p(mu)/m - 1/3*G(L1,K1,mu,nu) + 2/3*Gi(L1,K1)*p(mu)*p(nu)/m^2 } * { - i*G(L1,K1,p) + m*Gi(L1,K1) } The command Gammas can be used to do work on G-strings. See the section on gamma algebra. Example 27 gives the complete calculation for muon decay in the V-A theory. It is not repreduced here. The Compo command is very useful if one wants to calculate diagrams. The possible vertices can be given in terms of X-expressions. For a given topology one sums over all possible propagators. Separate examples exist for such cases. 14. INTERNAL PROCEDURES. Some insight in how all this actually works inside Schoonschip is really indispensible, and this section provides for some details. An example (Example 28 followed by Example 29) shows how to do a problem that could easily explode if not worked out carefully. Consider the expression: Z XX = (a*x^2 + b*x)*dx The process starts with reading the input. The input is encoded, and placed into memory. Names are placed in arrays. This encoding stops when the line with the * is encountered. Then Schoonschip starts working out the Z expressions, one after the other. This happens at Level 0. At Level 1 one term after the other passes by. In this case the first term passing by is the the term a*x^2*dx. No new term is emitted then till this term has passed 40 Levels, and at each Level the user has the opportunity to work on that term. Then this term is collected in the output store, a large area of more than 40 kbytes. There are provisions for handling overflow of that area, but more about that later. Only when that term is stored is the next term issued, here b*x*dx. The advantage of this procedure is that virtually no storage is needed for the intermediate results. Often symbolic programs work out the whole expression before going to the next level. Then one finds inside the initial expression, the expression as it becomes after the first Level, and so on. The same expression, in various stages of processing may then be found many times in memory. This leads very quickly to memory overflow, which is not easily manageable. On the other hand, when collecting terms in the output store a substantial reduction in the number of terms may take place. For instance, to take a very trivial example, the initial expression (a+b)^2 leads to 4 terms, and all of these 4 terms go through all 40 Levels (actually Schoonschip notes how many Levels are active, and skips the empty Levels). If one were to collect these terms immediately after the first Level there will then only be three terms: a^2 + 2*a*b + b^2. That is what happens at the output store: identical terms are recognized, and the coefficients are added rather then keeping the terms separately (here that applies to a*b). Thus term collecting will in general lead to a reduction in number of terms, and in fact this is usually very substantial. This fact was of course quickly realized, and an option is available to do this term collecting at any time inbetween the substitutions and commands. This is done through the *yep line. When encountering this line Schoonschip processes all substitutions up to that point and then collects all terms in the output store. Next this output store is emptied on the disk, and then read in again, term by term. Again each term then passes through all Levels, possibly to another *yep, till all substitutions have been exhausted. It is up to the user to put these *yep lines judiciously in case of a large problem. As may be clear from the above this procedure has the added advantage that after a *yep the full 40 Levels can be used again. Thus there is basically no limit on the amount of substitution and commands that can be done. The assignment of substitutions and commands is essentially automatic. The user has a number of options here. Putting Id in columns 1-2 of a substitution assigns that substitution to the next Level. The characters Al put the corresponding substitution on the same Level. Thus substitutions that do not interfere with each other can so be put on the same Level: the first has Id, the second Al in columns 1-2. Also, one may want some substitution to be done at a number of consecutive Levels. In such cases one simply places a number after the Id or Al. Thus Id,7,... implies that the corresponding substitution is inspected for at 7 consecutive Levels. When reading the input Schoonschip prints the associated Level in front of the line. To understand this numbering it must be realized that working out brackets requires Levels, namely one Level per nesting. Thus in the last example the first substitution is put at Level 2, because Level one is used to work out the brackets. In fact, working out the brackets is very much like a substitution; the initial expression is translated to something like $AAA^2, where $AAA is a symbol invented for this purpose, and at Level 1 the substitution Id,$AAA = a+b is placed. For this reason the $ symbol must not be used in names. This process may be seen in detail by requesting printing of these $ expressions by means of a P brackets directive. Also X-expressions may require Levels, they are like build-in substitutions. As soon as an X-expression materializes at some Level Schoonschip substitutes its definition. To make the whole process transparant we will here reproduce the contents of memory for a simple case somewhere in the middle of a calculation. Consider: Z xxx = (a*x + b)*dx Id,x*dx = (x2^2 - x1^2)/2 *end Typically at some point the following may be found in memory: Level 0: $AAA*dx Level 1: dx and a*x + b Level 2: dx*a*x Level 3: a and $AAB/2 Level 4: 0.5*a and x2^2 - x1^2 Level 5: - 0.5*a*x1^2 Levels 6-40: skipped In output store: 0.5*a*x2^2 At this point the action is at Level 5. A little time later the term -0.5*a*x1^2 will arrive at the output store, and that exhausts the work at Level 4. Then Schoonschip goes back to Level 1 and produces the next term, b*dx. After that has passed to the output store (for simplicity we have not included the substitution for this one) Schoonschip goes all the way back to Level 0, finds that the problem is all done, and passes to the next stage, namely printing of the contents of the output store. This rather complicated procedure has the great advantage that only very little memory is used at any one time. One finds bits and pieces all the way down from Level 0 to the output store, and Schoonschip keeps on climbing up and down all Levels till all work at all Levels is exhausted. In dealing with large problems one must have some idea of this procedure in order to organize the calculation in the most efficient way. Any substitution with more than one term in the right hand side leads to multiplication of the number of terms generated with some factor, depending on how many terms occur in that right hand side, and also on how often the sustitution is actually done. To see how much work is done by Schoonschip use the directive P stats. Then some statistics are printed, of which in this context the most interes- ting ones are the number of multiplications and the number of terms. One multiplication is counted for every time two terms (not factors) are multiplied together. Thus (a*x + b)*(c*x + d) implies four multiplications. Often the count comes out higher than expected at first sight due to for instance the way brackets are worked out. The number of terms is simply a count of the terms that arrive at the output store. That would be 4 in this case. Another example: (a + b)^4 leads to 2^4=16 multiplications, and then to 16 terms, and after sorting in the output store one will have 5 terms. In actual fact, the count for multiplications comes in this case to 81, but we will not bore the reader to explain this in detail. Mainly this is because Schoonschip begins by setting a 1 before getting to the actual expression. In practice the number of terms and also the number of multiplications are a good indication of the complexity of a problem, and the time needed is roughly proportional to these numbers. For large expressions with many terms most time is spent sorting the terms in the output store. Try to avoid more than 100,000 terms. If one gets in this kind of situation it is necessary to examine in detail the organization of the problem, and the separation in various parts using *yep. See also the sections on large problem handling and file handling commands. The largest calculation done so far involved as many as 1,000,000 terms, but it is not known how much diskspace was used. The present version needs about 20 seconds for 10,000 terms or 100,000 multiplications, but this must be seen as a very rough low estimate. If diskwriting is involved times may increase drastically. The calculation mentioned used 20 minutes on a CDC 7600, but that was counting only cpu time, not actual time. It would probably take many hours on a 68000, assuming enough diskspace. The important point is of course that at least there is no limitation due to Schoonschip itself, and given time and diskspace it will work its way through. If P stats is specified it will print statistics every time 8192 (= 2^13) terms have passed through, so that one can see some action. In particular series expansions where the argument expanded in is again a series can very easily lead to an enormous number of terms. Suppose some function, f(y), is given in terms of a series expansion, and suppose also y is a series expansion in terms of a variable x. Now suppose that the series expansion of f in terms of x up to x^10 must be found. If y is a polynomium involving up to x^9, thus 10 terms, then substitution of this in y^10 leads to 10^10 terms, which would take roughly 20*10^6 seconds if nothing else would grow out of bounds. Such problems must be worked out really carefully, and in Examples 28, 29 we have reproduced a substantial part of such a problem, enough to understand the principle. 15. CHARACTER SUMMATION. Characters have become quite useful in generating diagrams. Typically a character is associated with every particle in the theory. Anti-particles have the same character as the particles but appended with an underscore (_). Certain particles are their own anti-particle. There is a way to let Schoonschip know which particles are their own anti-particle. In generating diagrams one must first have a list of vertices. The name for a vertex is composed of the characters that correspond to the particles entering that vertex. In that name the characters must be ordered in a well defined way: alphabetically, upper case before lower case before numbers, characters with an underscore before those without an underscore. Thus: A_AB_BC_C......Z_Za_ab_b...1_12_2... Here some examples: AWW Aww U_U AG_G Ue_e Ubt_ U_b_t U Vertices have indices and momenta as parameters. Four particle vertices have no momentum dependence. The list of vertices must be given in terms of X-expressions. Each vertex must have sufficient parameters to cover all cases. For a given particle one may have momentum, vector index and spinor index. Even if the vector and spinor index will normally not occur simultaneously they need to be carried along. A 3-vertex will thus have 9 parameters. Examples: X U_UW(AL,al,P,BE,be,Q,GA,ga,K) = C*D(AL,BE)*(Q(GA)-P(GA)) + C*D(AL,GA)*(P(BE)-K(BE)) + C*D(BE,GA)*(K(AL)-Q(AL)) This is a vertex for three vector particles. The spinor indices al, be, ga are not used. Here two spinor vertices: X Ubt_(AL,al,P,BE,be,Q,GA,ga,k) = i*G(ga,be,AL) + avc*i*G(ga,be,AL,G5) X Ue1_(AL,al,P,BE,be,Q,GA,ga,k) = i*G(ga,be,AL,G6) Note that spinor indices usually appear in reverse order. This is the vertex for a vector particle (charged W) coupling to a fermion and an anti-fermion (bottom and top or electron-neutrino 1). Here a fermion propagator: X t_t(L1,l1,L2,l2,K)=NOM(K,Mt)*G(l2,l1,K) + NOM(K,Mt)*Gi(l2,l1)*Mt NOM is the usual propagator factor, 1/[KDK + Mt^2]. In this way all vertices and propagators must be defined. Now suppose some diagram must be calculated, say W selfenergy (the charged W's are represented by U and U_). After the type declarations all vertices and propagators must be given in terms of X-functions: C Calculation of charged vector boson (U, U_) self-energy. F Fx,F2,B22,B21,B1,B0,VE3,PROP I AL=N,al,BE=N,be,GA=N,ga,MU=N,mu,NU=N,nu,MUP=N,mup,NUP=N,nup, L1=N,l1,L2=N,l2,L3=N,l3,L4=N,l4,L5=N,l5,L6=N,l6,L7=N,l7,L8=N,l8, L9=N,l9,L0=N,l0 I Mu4,Nu4 V P,Q,K C The use of these character tables, the Anti statement and the G line will be C explained below. T TAP: W,Z T TFE: t,b Anti,TAP G 1 X t_t(L1,l1,L2,l2,K)= i*NOM(K,Mt)*G(l2,l1,K) + NOM(K,Mt)*Gi(l2,l1)*Mt X b_b(L1,l1,L2,l2,K)= i*NOM(K,Mb)*G(l2,l1,K) + NOM(K,Mb)*Gi(l2,l1)*Mb G 3 X Ubt_(AL,al,P,BE,be,Q,GA,ga,K)= i*G(ga,be,AL,G6) X U_b_t(AL,al,P,BE,be,Q,GA,ga,K)= i*G(be,ga,AL,G6) X Wt_t(AL,al,P,BE,be,Q,GA,ga,K)= i*[1-8/3s^2]*G(be,ga,AL) + i*G(be,ga,AL,G5) X Wb_b(AL,al,P,BE,be,Q,GA,ga,K)= i*[4/3s^2-1]*G(be,ga,AL) - i*G(be,ga,AL,G5) G C First establish the topology, for example the simple two 3-vertex, two C propagator diagram. Note that no _ may be used in file names. Z IUUB=SELF("U,"U_) C Now a character summation. I1 is the given input character, C in this case the "U representing the positively charged W. C The sum in DS goes over all characters J1 and J2 such that the name C U J1 J2 properly symmetrized corresponds to some X-expression. C In this case that will only be some b, b_, t, t_ combinations for J1, J2. C The symbol 'Sym' implies symmtrization factor based on the characters C following. If they are identical (will not happen here) a factor C 1/2! will be added. C The subsequent numbers, 2,3,5,6, imply that only X-expressions in C groups 2,3,5 and 6 will be inspected. That is then the meaning of C the G lines above: they specify a group number for the X-expressions C following. Default is 0, and if no groups have been specified all C will be considered. C Whenever a match is found a term in the summation arises: the C function DIB with the characters I1, J1, J2 and I2 as arguments. C The function DC is used for various purposes; here it provides C a factor -1^1 if both characters J1 and J2 appear in table TFE. C If one uses "F_ rather then "F the factor is provided none of the C characters appear in the table TFE. C The second number 1, the exponent, may be omitted and is then 1. C This is the factor -1 for a fermion loop. The "F in the DC function C stands for factor. C Other uses for DC are summarized later. Id,SELF(I1~,I2~)= DS(I1;J1;J2;Sym;J1;J2,2,3,5,6,(DIB(I1,J1,J2,I2) *DC("F,TFE,-1,1,J1,J2) )) C This is essentially the diagram. Mu4 and Nu4 are the external U and U_ C indices, P is the loop momentum, Q is the U momentum and K = P + Q. C The * are used by the command Compo. In for example VE3 that command C re-arranges the characters I1, K1 and K2 in the character order defined C before. Every interchange also gives rise to an interchange of the C argument groups delimited by the *. Id,DIB(I1~,K1~,K2~,I2~)= VE3(I1,K1,K2,*,Mu4,mu,Q,*,L1,l1,-K,*,L3,l3,P)* VE3(-K1,I2,-K2,*,L2,l2,K,*,Nu4,nu,-Q,*,L4,l4,-P)* PROP(K1,-K1,*,L1,l1,K,*,L2,l2,K)* PROP(K2,-K2,*,L3,l3,P,*,L4,l4,P) C Compo searches the X-expression list for the names composed of the first C few characters that appear as arguments of the functions VE3 etc. and if C found keeps the term, else makes it zero. Id,Compo,,VE3,PROP C Compo has now composed the name and performed the necessary symmetrization. C Now the functions themselves can be substituted. AA is a dummy name here. Id,VE3(AA~,MU~,mu~,P0~,L2~,l2~,Q~,L1~,l1~,P~)= AA(MU,mu,P0,L2,l2,Q,L1,l1,P) Al,PROP(AA~,L4~,l4~,Q~,L3~,l3~,P~)=AA(L4,l4,L3,l3,Q) C At this point the full expression for the diagram has been obtained. C The next step is to do the loop integral. The loop momentum appears C in the propagators through the functions NOM, and as arguments in the C Gamma matrices. Id,Commu,NOM Id,NOM(P,M~)*NOM(K,M0~)=F2(M,M0) Id,Gammas,"C C Remove K as G argument, replacing it by the four dimensional Q C and the loop momentum P. No index is created by this work, and the C dimensionality of MU is irrelevant. Id,Funct,K(MU~)=P(MU)+Q(MU) C Now collect all P in the function Fx. Id,All,P,N,Fx *yep C The P-integration can be done: Id,F2(M~,M0~)*Fx(MU~,NU~) = D(MU,NU)*B22(M,M0) + Q(MU)*Q(NU)*B21(M,M0) Al,F2(M~,M0~)*Fx(MU~) = Q(MU)*B1(M,M0) Al,F2(M~,M0~)=B0(M,M0) C Do Anomalous traces. Id,Gammas,"A *end In this case only one diagram is evaluated simply because there are no more vertices listed. If a complete set of vertices is given the complete result obtains. Character tables. Character tables are distinguished from other tables (that can be used as function arguments) by means of the colon (:) following the name. To every character possible there corresponds a location in the table, zero by default. Any character mentioned gives a 1 and a -1 in the location for its antiparticle (denoted by a appended underscore). Specific numbers may be assigned, for example T TAB: A=3:5,B=7,a,z=3 This assigns 3 to A, 5 to A_, 7 to B, -7 to B_, 1 to a, -1 to a_, 3 to z and -3 to z_. Important: all numbers appearing in character tables must be short integers (-129 < # <128). The function DC uses such tables. Other character manipulations often need a table to specify which particles are their own anti-particles. Except for DC calculations such an anti-particle table may be given before a *fix, and is then the default for the character function DS and the command Compo for example. In all cases one may specify a particular anti-particle table for the specific case: for DS as an argument before the group numbers, for Compo anywhere in the list. Anti statement and command. The Anti statement Anti,TAA establishes character table TAA as the default anti-particle table. This is used by default by DS and Compo work. The statement may be given in the fix section and is then valid by default for all other sections. The command: Id,Anti,TXX leads to inspection of all function arguments. The table TXX is used to determine which particles are their own anti particles, and correspondingly a possible appended undescore is removed. Character summation function DS. General format: DS(C1;C2;C3;..;Sym;C4;C5,..,TX,#1,#2,...,(Expression) ) ^--^---^--^ ^ ^ ^ The ^ indicate optional arguments. The characters C1, C2 etc must be followed by a semicolom; they may be characters, or else they are taken as dummies. A preceeding - sign adds or removes an underscore. The summation goes over all names that fit the name of an X-expression. For example, if C1="A and there are two additional dummies mentioned then DS searches for all X-expressions with a name of three characters of which one is an A. C2 and C3 become then the other two characters and may as such be used in the Expression. If the symbol Sym is mentioned then a symmetrization factor is provided based on the characters following this symbol. If a table TX is mentioned it is taken to be the antiparticle table, listing all characters X for which X=X_. If group numbers are specified only X-expressions in the groups mentioned are considered. Example: DS("A;J3;-J3;"B;Sym;J3,-J3,2,(Dic("A,J3,"B) ) Every X-expression name containing characters of the form AXX_B (or AX_XB) leads to a term in the sum. For example the following names fit the pattern twice: AEBE_ (with J3="E and J3="E_) Z_ZAB (with J3="Z and J3="Z_) The order of the characters in the name is not of importance here. This order is however important when using the command Compo. That command orders the characters before searching the namelists. The character function DC. DC always equals some numerical factor depending on the character arguments. DC("F,TFE,#1,#2,C1,C2,...) DC("F_,TFE,#1,#2,C1,C2,...) The value of the DC is #1^#2 (if #2 absent is taken to be 1) provided all characters C1,C2 etc appear in the table TX. Else it is 0. For "F_ the other way around. Here an example of a character table TX: T TFE: t,b DC("P,TX,#,C1,C2,...) Compute and multiply with a permutational factor determined by the occurence of identical characters in C1, C2 etc. The number # is used as exponent. For example, with the value 2 for # and the characters "A "A "A "B "B the value (3!*2!)^2 obtains. The table TX lists particles that are their own anti-particles (X_ = X). Here an example of such a character table: T TAP: W,Z DC("C,TX,C1,C2,...) DC("C_,TX,C1,C2,...) DC("T,TX,C1,C2,...) DC("T_,TX,C1,C2,...) Compute the sum of the 'charges' of C1,C2,.. as listed in table TX. If zero DC is 1, else 0. If the character "C_ is used the opposite. If the character "T is used keep the term if the sum is positive including zero. If "T_ is used keep if < 0. Here an example of such a character table: 1 is assigned to particle Z, and also 1 to its antiparticle Z_. If the second 1 is not given it is taken to be the opposite of the first one (thus here -1) for the antiparticle. T TX: Z=1:1 16. GAMMA ALGEBRA. The equations and algoritms used in this section will not be derived here. The derivations can be found in a publication (M. Veltman, Gammatrica, 1989, to be submitted to either Nuclear Physics or Computer Physics Communications). The treatment of gammas has become quite complicated, but things have been organized in such a way that for most cases the default options will do the necessary. Essentially, other then four dimensional gamma algebra can be done. It is nonetheless essential that a number of things are well understood. The only quantities for which other than four dimensionality can be specified are indices. There is no way to specify the dimensionality of a vector, or of a dotproduct. In doing gamma matrix manipulations Schoonschip takes vectors to be four dimensional, i.e. G(L,p) contains only G(L,1) to G(L,4). That might be seen as a restriction, but it is not. Refer to the "C option discussed below. The type of non-four dimensional vectors in the sense just mentioned occurring in practice are loop momenta. There are several ways to deal with that. The easiest way seems to be to first do the loop integrations before doing the gamma algebra. First all gamma's are collected using the "C option (see below), and then occurring loop momenta are replaced by four- dimensional momenta or index pairs with N dimensional range. These can be handled properly. For the moment it will be assumed then that all momenta occurring as arguments of the gammas matrices are four dimensional, but that indices may either be four or N-dimensional. No provisions have been made to consider indices with ranges other then these two, although one may use any algebraic symbol instead of N. New notations have been implemented. Instead of one loop index the gamma's may now have two loop indices. This very much eases the task of ordering the gamma's properly when generating them by means of some automatic procedure. Gamma's can be rounded up and put in the proper sequence on the basis of the indices. The notation is: G(i1,i2,mu), Gi(i1,i2), G5(i1,i2), G6(i1,i2), G7(i1,i2) Gi is the unit matrix. The meaning of G6 and G7 is as before: G6 = Gi + G5, G7 = Gi - G5. The ordering is based on the indices: G(i1,i2,mu) * G(i3,i4,nu) * G(i2,i3,al) = G(i1,i4,mu,al,nu) which is about the same as the old notation G(L,mu)*G(L,al)*G(L,nu) One may in fact directly use the multi-index notation G(i1,i3,mu,al,nu). It actually was used internally (but with only one loop index) since a long time. Also Gi, G5, G6 and G7 may appear in that list: G(i1,i2,mu,G5,al,be,G6,ga,Gi,la,G7) A string is called a trace if the first and second index are the same. Otherwise the expression is called a gamma string, or shortly string. A string may be odd or even depending on the number of arguments not counting Gi, G5, G6 and G7. Thus the last shown is an odd string. Traces of odd strings are always zero. To avoid prolifiration of indices one may preferably use integer numbers instead. For example: G(1,2,mu) * G(3,4,nu) * G(2,3,al) = G(1,4,mu,al,nu) When dealing with more then one string number ranges may be reserved for the different strings, thus avoiding confusion. Example: X Vert(n,mu) = G(n,n+1,mu,G6) Z xx = Ubg(1,mm,p)*Vert(1,mu)*G(2,3,nu)*Ug(3,mn,q) * Ubg(10,mn,k)*Vert(10,mu)*Ug(11,me,qq) When starting work on gamma matrices Schoonschip begins by rounding up the gammas. For two index gammas the ordering is determined by the indices. For gammas with one index (the old notation) the ordering is based on the order in which they appear in the expression considered. By default the strings are normalized, i.e. direct neigbour equal arguments are eliminated ( G(....,X,X,...) = D(X,X)*G(........) ) and traces of an odd number of gammas (not counting G5 etc) are set to zero. Optionally that normalization may be suppressed. After rounding up the strings and traces appear with only one loop index. The index is chosen from the indices seen: the smallest number (or earliest mentioned index) is taken. Indices are 'smaller' then numbers. G(1,2,mu,al) * G(3,4,nu,G5) * G(2,3,la) => G(1,"s,"4,mu,al,nu,G5,la) The character argument "s indicates a string rather then a trace. The "4 is the unit G matrix, the need for this argument will become clear below. The 1 is now the loop index. Another example: G(i1,2,mu,al) * G(3,i1,p,G5) * G(2,3,la) => G(i1,"t,"4,mu,al,p,G5,la) For brevity these objects will be called G-strings in the following. The arguments may be indices, vectors or Gi-G7. At this point there are now two types of G strings, namely "s or "t strings. This very first phase of the work is called collecting. Normalization is optional. Optionally one may stop the work at this point. The next step is to apply all the known algorithms to these objects. Optionally one may specify which strings should be worked on, either by a specific loop index or by number range. More about that below. Schoonschip starts by considering all arguments in the G-string. If all indices have the (default) range 1-4 then the string becomes a four- dimensional G-string. Occurring vectors are considered four dimensional. If a string becomes four dimensional the character argument "s or "t is changed in "S or "T. Some work is done on the strings: - adjacent identical arguments are eliminated. This includes for traces first and last argument. - for "S and "T strings the G5, G6 and G7 are anti-commuted to the left and the result is placed instead of the "4 argument. - simple cases such as the trace of the identity are completely worked out. Examples: I mu,nu,al=N,be=N G(1,"s,"4,mu,nu,al) => unchanged. G(1,"t,"4,mu,nu,al) => 0 (odd trace). G(1,"s,"4,mu,al,al,nu) => N * G(1,"S,"4,mu,nu) G(1,"t,"4,mu,al,be,mu) => 4 * G(1,"t,"4,al,be) G(1,"t,"4,G5,mu,G6,nu) => G(1,"T,"6,mu,nu) => 4 * D(mu,nu) G(1,"s,"4,G5,mu,G6,nu) => G(1,"S,"6,mu,nu) => G(1,"S,"4,mu,nu) + G(1,"S,"5,mu,nu) The last step belongs also to the class of doing simple cases. The expansion of G6 would not have been done if there had been more index arguments. Optionally one may stop the work here. The next step is sum-splitting. N-indices in "s or "t strings are split in a four dimensional and an N-4 dimensional part. As a convention the quantity N_ is understood and used as N-4. Here are the equations for the case of two index pairs: I mu,nu,al=N,be=N G(1,"s,mu,nu,al,be,..,al,be) => G(1,"S,mu,nu,al,be,..,al,be) +/- G(1,"s,"_,be) * G(1,"S,mu,nu,al,..,al) +/- G(1,"s,"_,al) * G(1,"S,mu,nu,be,..,be) +/- G(1,"s,"_,al,be,al,be) * G(1,"S,mu,nu,..) The sign is determined by the convention that the indices to be split are first moved to the very left. They are taken to anticommute with all four-dimensional indices and vectors, and to commute with G5, G6 and G7. Optionally, for traces containing an even number of G5 or for strings independent of the number of G5 one may specify anticommutation with G5. In that case G6 and G7 are expanded before the sum-splitting is done. For traces with an odd number of G5 commutation is used even if the anticommutation option is specified, simply because the trace is otherwise not well defined. The outcome would not be invariant for a cyclic rotation of the arguments. Note the "_ character argument. The range of the indices in an "_ string is from 4 to N. Both the string and trace of the unit "_ are one: G(1,"s,"_) = 1 G(1,"t,"_) = 1 Other then that "_ strings are treated as the other non-four dimensional strings. For example elimination of a direct pair: G(1,"s,"_,...,al,al,...) = N_ * G(1,"s,"_,.....) Sum-splitting requires that all N-indices occur in pairs. This no real restriction as the pairs need not to occur in one and the same string, but for example one index may occur in a string and the other in another string or even some other function. If a string contains only N-range indices then it is called pure, and no sum-splitting is done. Index pair eleimination and trace evaluation are done directly on such a string. Sum-splitting is done by default. Optionally work may be stopped here. The next step is the unification of G-strings. By default this is not done, because it is not always advantegeous, and because it may be necessary to indicate explicitly which strings are to be unified. The unification is based on the Chisholm's equation: G(1,"X,a1,a2,...,mu,b1,b2,...) * G(2,"T,mu,c1,c2,...,cn) = 2 * G(1,"X,a1,a2,...,c1,c2,...,cn,b1,b2,...) + 2 * G(1,"X,a1,a2,...,cn,...,c2,c1,b1,b2,...) where "X may be "S or "T. The application requires - the G-strings involved must be four-dimensional. - they must have one index in common (mu in the above). - at least one of them must be a trace. The general rule is that it is advantageous if the G-strings have other arguments then the explicitly shown index in common. That may be either vectors or indices. Thus there is an advantage if for example c1 and b1 are the same, because in the second term that can be worked out. This work is called unification, and optionally one may stop the work here. The next step is to eliminate index pairs in the G-strings. For four- dimensional strings there is the Kahane algorithm which eliminates all pairs in a given string in one sweep, for "s and "t strings there is a single pair algorithm that can be applied repeatedly. This is done by default. One may specifically allow or inhibit index pair elimination in _ type strings seperately. Optionally one may stop the work here. The next step is the elimitation of vector pairs in four dimensional strings. This is also a single pair algorithm that can be applied repeatedly. It is called the P-algorithm. Optionally one may stop the work here. The final step is to actually evaluate the traces, and to reduce the four dimensional strings to a standard form. This is called the W-operation (for final work). In summary, the following is done: - Rounding up of all strings. This step cannot be avoided. All occurring G are rounded up, even those that are not to be worked on. By default the strings are normalized. - Sum-splitting. By default. With optionally Anticommuting G5 if an even number of G5 present. - Unification. Not done by default. - Index pair elimination, also for pairs in _ type strings (the latter may be inhibited with the i-option) Done by default. - P-algorithm for four dimensional strings. By default. - Work: final traces and reduction for four dimensional strings. The options are characterized by a character, namely N, A, S, U, I, P and W. The command for all this is Id,Gammas By default work is done on all occurring strings. For most cases, using the two-index G notation this will do. If there are single index G's (the old notation) then it must be possible to specify which are strings and which traces. By default they are taken to be strings. If a trace is intended loop indices must be mentioned: Id,Gammas,Trace,i3,i4 In strings i3 and i4 the "s is replaced by "t. As soon as one or more specific index is mentioned in the Gammas command only loops with the loop indices as occurring in the list will be worked upon. For any individual loop index options may be specified. Options may be on or off. The are turned on by the appropriate character argument, and turned off if the argument is followed by an undersore (_). Furthermore one may, in case numbers are used as loop indices, indicate a range of loop numbers. Here is the syntax: Id,Gammas,C1,C2,i1,1-4:C3,C4,Trace,i2:C4,C5,i3,9-10 C1, C2 etc are character arguments, either one of these: "N "N_ "A "A_ "S "S_ "U "U_ "I "I_ "P "P_ "W "W_ "i "i_ In addition there is the option "C. It is synonym for turning all options except "N off, i.e. only collecting and normalization is done, with the further difference that no specialization to four dimensions is ever done. This is very essential if there is some integration vector where this vector is not four dimensional. Typically, if n-dim integration is to be done one first collects all G with the "C option, then the integrations are done, and after that the remaining work can be done through another Gammas command. To avoid normalization specify "N_ in addition to "C. The first mentioned character arguments define the default. If none is mentioned the default is "N,"A_,"S,"U_,"I,"P,"W,"i. The "i refers to index pairs in N_ (i.e. "_) type strings. G strings with loop indices mentioned after the Trace argument are forced to be traces ("t). A loop index may also be specified by a number range. Any G-string with a loop index within the range (inclusive the values mentioned) are considered. If the loop index or the range is followed by a colon then the following character arguments define the options for specific loop. Those options override the default options. Example: Id,Gammas,"A,"U,1-9:"A_,10-20:"U_,"I_ Strings with loop indices 1-9 and 10-20 are considered. Unification is attempted on loops 1-9. Loops 1-9 have commuting G5 with respect to sum-splitting, 10-20 anticommuting for traces with an even number of G5 or strings for any number of G5. No index pair elimination is attempted on 10-20 loops, but index pairs in N_ type strings are still worked on. To inhibit that a "i must be mentioned in addition. Please note the use of the colon (:). This is because at least in principle it is not excluded to also use character arguments as loop indices for two-index G (they are inbetween numbers and indices with respect to ordering). Several characters are illegal in this respect: "S,"T,"s and "t, at least if they occur as the second argument in a two-index G. As noted before, in all gamma operations all vectors are considered four- dimensional. There are at least two ways to handle things. Commands to simplify the work have been introduced. Consider a case in which there occurs some momentum p is to be integrated over N-space, and suppose this p occurs as G argument: G(1,2,al,be,p,al,be,p) (the two index notation is and will be used from now on). The first step is to get the p out. A new command, essentially a combination of existing commands can be used here: Id,All,p,N,F In this command p is a vector, N is an optional argument specifying the range of the indices to be created, and F is a function defined in an F-list. This command rounds up all p, also those occurring in functions and dot-products, and collects them in the function F. Example: V p F F S N Z xx = pDq*pDp*F1(aa,bb,p)*p(mu) Id,All,p,N,F *end This is the output: xx = + F1(aa,bb,Naa)*F(Naa,mu,q,Nab,Nab) + 0. In here the quantities Naa and Nab are created indices with range N. If one substitutes F(i1~,i2~,i3~,i4~,i5~) = p(i1)*p(i2)*p(i3)*p(i4)*p(i5) then the original expression re-emerges. This may actually be done more easily with the command Iall, the inverse of All: Id,Iall,p,F searches for F and restores to the original expression. Both All and Iall have also another syntax, see the description elsewhere as well as the example further down. The All command may now be used to eliminate the p from the G-string. Next integration may be done, for example: Id,F(i1~,i2~) = D(i1,i2)*F20(k) + k(i1)*k(i2)*F22(k) where k is a four-dimensional vector. After this gamma work may be done. Here is the full example with output: I al,be,mu,nu S N,N_ V p,k F F,F20,F22 Z xx = G(1,1,al,be,p,al,be,p) Id,All,p,N,F Id,F(i1~,i2~) = D(i1,i2)*F20(k) + k(i1)*k(i2)*F22(k) Id,Gammas *end xx = + F20(k) * ( 64 - 32*N_ ) + F22(k) * ( 16*kDk ) It should be emphasized that the symbol N, occurring in the All command must be defined in the symbol list, together with the symbol N_. If such a symbol occurs already as range in an index list this is done automatically, but in this case that did not happen. The command All will not work otherwise. Also p and F must have been defined before, either implicit or explicit. N cannot be defined implicit, because it would be taken as an index rather then an algebraic symbol. Again, N_ is supposed to be N-4. The command All is really a combination of three existing substitutions, namely Id,p(mu~) = ... Id,Dotpr,p(mu~) = ... Id,Funct,p(mu~) = ... In addition All handles the creation of the function F with its undetermined number of arguments smoothly. The substitutions shown have been modified slightly. Now the range of the index mu is taken into account. If an index is created in the course of the work for these substitutions it is given the range of mu. The second method for dealing with vectors in G-strings is as follows. Let there be a string containing several vectors as aguments: G(1,1,mu,G5,p,q,nu,G5,q,p) Now use command All specifying the function G rather then the vector p: Id,All,G,N,F Again, N, N_ and F must have been defined before. This command takes out all vectors from the specific function mentioned (here G) and collects them, together with the indices created, into the function F1: F F1 I mu,nu V p,q Z ft = G(1,1,mu,G5,p,q,nu,G5,q,p) Id,All,G,N,F1 *end The result is: ft = + G(1,1,mu,G5,Naa,Nab,nu,G5,Nac,Nad)*F1(p,q,q,p,Naa,Nab,Nac,Nad) Now the gamma work can be done. The result is rather messy, and it is displayed here (slightly edited) for a simpler case: F F1 I mu,nu V p,q A N,N_ Z ft = G(1,1,mu,G5,p,nu,G5,q) Id,All,G,N,F1 P output *yep ft = + G(1,1,mu,G5,Naa,nu,G5,Nab)*F1(p,q,Naa,Nab) Id,Gammas P output *yep ft = + 4*F1(p,q,Dim_N_,Naa,Dim_N_,Naa)*D(mu,nu) + 4*F1(p,q,Dim_4,mu,Dim_4,nu) + 4*F1(p,q,Dim_4,nu,Dim_4,mu) - 4*F1(p,q,Dim_4,Naa,Dim_4,Naa)*D(mu,nu) + 0. As is clear Schoonschip has added on prefixes to the indices inside the function F1 to show the range. The function F1 with those prefixes cannot be handled by any substitution or command except the command Ndotpr, specially created for this situation. It works out the F1 arguments and creates various symbols analogous to dotproducts (but they are not, they are symbols) showing the summation range: Id,Ndotpr,F1 P output *end ft = 4*p(mu)*q(nu) + 4*q(mu)*p(nu) + D(mu,nu) * ( 4*pq_ - 4*pq4 ) + 0. In here pq_ means the dotproduct of p and q but only components 4 to N enter in the dotproduct. Similarly pq4 denotes a dotproduct with only the first four components entering. Obviously pq4 + pq_ = pDq, where pDq is the normal dotproduct. The symbols pq_ and pq4 are algebraic symbols. They are created during execution, and if a symbol list is asked for in a subsequent section (after another *yep for example) the A-list would be: A i=i, N, N_, pq_, pq4 Just for curiosity: if the A option had been specified in the Gammas command the term pq_ would have come out with the opposite sign. That is because there is one G5 inbetween p and q. Here is once more the example, but without the intermediate printing: F F1 I mu,nu V p,q A N,N_ Z ft = G(1,1,mu,G5,p,nu,G5,q) Id,All,G,N,F1 Id,Gammas,"A Id,Ndotpr,F1 *end ft = 4*p(mu)*q(nu) + 4*q(mu)*p(nu) + D(mu,nu) * ( - 4*pq_ - 4*pq4 ) This concludes the discussion. For the rest of this section some more examples. C G collection including spinors. I mu=N,nu=N V p,q Z xx = G(i1,i2,mu)*G(i2,i3,nu)*Ubg(i1,M,p)*Ug(i3,M,q) Id,Gammas,"C *end xx = + Ubg(i1,M,p)*G(i1,"s,"4,mu,nu)*Ug(i1,M,q) + 0. C No problems with complex conjugation: I mu=N,nu=N V p,q Z xx = Conjg( G6(i0,i1)*G(i1,i2,mu)*G(i2,i3,nu)*Ubg(i0,M,p)*Ug(i3,M,q)) Id,Gammas,"C *end xx = + Ubg(i3,M,q)*G(i3,"s,"4,nu,mu,G7)*Ug(i3,M,p) + 0. where a G6 was included. A string containing only N-indices is called pure. All index pairs can be eliminated, and traces can be evaluted completely. Here an example involving a string and a trace: I mu=N, nu=N, al=N, be=N, ga=N Z xx = G(i1,i2,mu,ga,nu,al,be,ga) + G(i1,i1,mu,ga,nu,al,be,ga) Id,Gammas,"C P output *yep xx = + G(i1,"s,"4,mu,ga,nu,al,be,ga) + G(i1,"t,"4,mu,ga,nu,al,be,ga) Id,Gammas *end xx = + D(mu,nu)*D(al,be) * ( 8 - 4*N ) + D(mu,al)*D(nu,be) * ( - 8 + 4*N ) + D(mu,be)*D(nu,al) * ( 8 - 4*N ) + G(i1,"s,"4,mu,nu,al,be) * ( - N_ ) - 2*G(i1,"s,"4,mu,be,al,nu) + 0. Except the pair elimination nothing has been done about the string. One could actually bring the strings into some normal form, but the advantages of that are unclear, and it is also dubious as to what is the best normal form. The work involved and the number of terms generated is considerable. For this reason nothing has been implemented. But a possible way will be discussed now. Define the function AG to be totally antisymmetric in all its arguments except the first which is the loop index. If the number of arguments beyond the first is m it is equal to the totally antisymmetric combinations of m gammas divided by m!. Examples: AG(L) = Gi(L) AG(L,mu) = G(L,mu) AG(L,mu,nu) = 1/2 * { G(L,mu)*G(L,nu) - G(L,nu)*G(L,mu) } AG(L,mu,nu,al) = 1/6 * { G(L,mu)*G(L,nu)*G(L,al) - .... } : : Any string can be written as a linear combination of such functions AG: G(L,"s,m1,m2,m3,...) = a0*AG(L) + a1*AG(L,n1) + a2*AG(L,n1,n2) + ... For example: G(L,"s,"4,mu,nu) = D(mu,nu)*AG(L) + AG(L,mu,nu) For the case of three indices: G(L,"s,"4,mu,nu,al) = D(nu,al)*AG(L,mu) - AG(L,nu)*D(mu,al) + AG(L,al)*D(mu,nu) + AG(L,mu,nu,al) The number of terms increases faster then the number of terms for a trace. For four indices the number of terms is 10 (3 for a trace), for five it is 11 and for six it is 76 (15). Here a program that computes this expansion for the case of four indices (where only a0, a2 and a4 are non-zero): I mu=N, nu=N, al=N, be=N, b1=N, b2=N, b3=N, b4=N Z xx = { 1/(4*DB(4)) * G(L,"t,"4,mu,nu,al,be,b1,b2,b3,b4)} * AG(L,b4,b3,b2,b1) + 1/(4*DB(2)) * G(L,"t,"4,mu,nu,al,be,b1,b2) * AG(L,b2,b1) + 1/4 * G(L,"t,"4,mu,nu,al,be) * AG(L) Id,Gammas Id,Asymm,AG,2,3,4,5,6 *end Note that AG was specified to be anti symmetric in more arguments then actually occur. The excess is simply ignored by Schoonschip. The time involved is considerable because of the large traces to be computed. For six indices the time to evaluate AG is about 150 seconds (M68000). The method shown is however not the most efficient. 17. R-INPUT. Sometimes it is desirable to work on a very large input expression, larger than Schoonschip can accomodate in its input space. The R-input facility is designed specifically for this purpose. More precisely, it is geared towards input that is exactly of the form as normal Schoonschip output. Put an R in column 1 of the line with the file name; Schoonschip will read the subsequent input and transform it into the same format that is used in *yep situations. After a subsequent *yep the expression can be worked on. As an example consider a case given before producing the output xxx = + [b-a]^-1 * ( [x+a]^-1 - [x+b]^-1 ) + 0. To be sure that all symbols have the same meaning specify the P lists option in the problem that produces that output, and include these lists in the new input. Then put an R in column 1 and a blank in column 2 of the line with xxx: A i=i, [b-a], [x+a], [x+b] F D, Epf=i, G=i, Gi, G5=i, G6=c, G7, Ug=c, Ubg, DD, DB, DT, DS, DX, DK, DP, DF=u, DC R xxx = + [b-a]^-1 * ( [x+a]^-1 - [x+b]^-1 ) + 0. *yep Id,[b-a]^-1=bma *end There is no limit on the length of the expression other than available disk space. R-input can be very useful if one wants to edit expressions or process parts of large expressions. It may also be used effictively to compare outputs. To this purpose put the secons expression behind the first but put an M (for minus) in column 1 rather then an R: A i=i, [b-a], [x+a], [x+b] F D, Epf=i, G=i, Gi, G5=i, G6=c, G7, Ug=c, Ubg, DD, DB, DT, DS, DX, DK, DP, DF=u, DC R xxx = + [b-a]^-1 * ( [x+a]^-1 - [x+b]^-1 ) + 0. M xxx = + [b-a]^-1 * ( [x+a]^-1 - [x+b]^-1 ) + 0. *yep B [b-a] *end 18. STATEMENTS. CONDITIONAL INPUT READING. Several statements have already been mentioned before. Here is the complete list. Showl Show some statistics of large disk files being written. Nshow Switches Showl off. Write fname Write all common files to disk file fname. Enter fname Enter common files from disk file fname. Bdelete b1,.. Delete blocks Read fname Start reading external file fname. End End of an external file. Screen Print in output lines up to 80 characters (default). Lprinter Print in output lines up to 130 characters. Anti TX Defines character table TX to contain the default anti- particle list. May appear in *fix section. Beep options If no options all beep requests are cleared. If #,t issue # beeps at termination. If #,* issue # beeps when concluding a section (* delimited). If #,e issue # beeps in case of an error. Common ... Common declaration. Delete ... Delete files. Directory Defines directories to be used for large files. See section on file handling. Digits Defines number of digits to be printed for floating point numbers. Dryrun # Do a 'dry run'. Print at most # terms at completion. External fnam Read fnam into memory. Command Extern executes that file. Fortran type output has been shown to need often considerable editing. The section of Schoonschip producing this has been rewritten. By default the fortran output has only complete terms on any given line (if possible) rather then the compressed form desirable in the old days when cards were used. The compressed form is still available though. In addition, one may specify how many continuation lines any given statement may have. Also one may direct Schoonschip to place brackets around negative exponents. Finally one may optionally direct Schoonschip to supplement every integer with a decimal point, as some Fortran compilers require this. All this may be achieved with the Fortran command. Every item is optional, the defaults being: no compression, 9 continuation lines/statement, no brackets, no . in integers, fortan type output. Fortran #,Brackets,Compression,.,A Only the first character of Brackets and Compression is significant and may be lower or upper case. A minus sign in front of Brackets, Compression or . switches back to the default, for example Fortran -Brackets instructs Schoonschip not to put brackets around negative exponents. The exponent of a number is normally shown using the character E (e.g. 1.23E+10). If a number of digits (Digit statement) larger than 5 has been specified then D will be used instead (1.23D+10). Finally, to specify output for the A-compiler mention the character A on the Fortran statement. Freeze xfile Freezes file xfile. See section on large problem handling. Keep fil1,... Keep files over a *next Large # # is a number in the range 1 to 5 inclusive. Default is 2. It specifies the number of intermediate output files to be used for large file sorting. See section on file handling commands. Maximum # Specifies the maximum size of intermediate output subfiles. Default is 110 000. See section on file handling commands. Names fname Enter names of a common file. Nprint fil1,.. Do not print file1,.. Oldnew xx=yy Renames a quantity. Outlimit # Sets a limit of # bytes on disk usage. In case of large file usage this sets the limit on total disk space used for the intermediate output files. Default: 500 000 = 0.5 Mb. Overflow off Suppresses short number (exponents, function arguments) overflow error trapping. May appear in *fix section. Overflow on Reactivates overflow error trapping. Print ... Specifies files to be printed. Precision # This specifies the precision required for dealing with numbers. This number # applies internally at various instances. In the output two terms are taken to cancel if the addition gives a cancellation up to # digits. Comparing numbers with the Coef command uses the precision criterium. Also, when writing terms to disk every number is truncated to 10 digits if # above is 9 or less. This saves considerably on disk space. The default is 22 digits. Progress In case of no output to the terminal print a . to the terminal every 128 terms to show progress. Punch ... Specifies files for which fortran output must be made. Rationalize # Schoonschip by default tries to rationalize numbers. The number # specifies to how many digits the numbers must agree. For example, Schoonschip will rationalize Pi = 3.141592654.. to 22/7 = 3.142857143... if 3 is specified. Specifying 5 gives 355/113 = 3.14159292... which actually agrees 7 digits. It should perhaps be noted that after every rationalization Schoonschip actually performs the division and compares the result with the input number, just to be sure. If 0 is put for # no rationalization is done. The default is 22 digits, with check up to 26 digits. Round on Numerical expressions as function arguments to be converted to short integers are normally obtained by truncation. If Round on the number is rounded to nearest integer. Round off resets to the default, truncation. Silence Instructs Schoonschip not to print "Ready" to the screen and wait for an answer for certain PC's that normally clear the screen immediately at termination. Sum ... Specifies indicies to be summation indices. Synonym name1=name2 Every occurrence of name1 between single quotes is replaced by name2. This is very much like replacements of BLOCK arguments, except that it is not limited to a block. The end of the range of validity of some set of synonyms is defined by the synonym statement without any arguments. At most 16 synonyms allowed. Traditional Do traditional sorting. See section on file handling commands. The conditionional input reading statements may be used to formulate small variations on a given problem. The idea is to define some parameters in the beginning of a problem, and then to read input as a function of those parameters. Many variations upon a given problem can then be run simply by changing a few parameters in the beginning. The parameters are called _Sw0 to _Sw9 and their default values are 0. The initial value of the parameter _Sw0 may actually be set on the command line when invoking Schoonschip. To this purpose use the notation S=#, where # must be a number in byte range (-128, 127). Example: Schip S=7 Ifile The initial value of _Sw0 will be 7. The _Swx may be changed by means of a Set statement. The syntax is: Set _Sw? = expr with ? a number in the range 0 - 9, and expr a simple numerical expression (see below) in byte range, i.e. -128, 127. Example: Set _Sw3 = 7 Every occurrence of _Sw3 is replaced by the number 7. This includes actual occurences within any given expression, for example ... a^_Sw3 ... is read as a^7. Other example: Set _Sw5 = _Sw5 + 1 In addition the variables _Sw0 - _Sw9 may occur in a Gotoif (or Gotoifn) statement. Here is the syntax: Gotoif expr1, expr2 ? expr3 Expressions expr1, expr2 and expr3 must be simple numerical expressions, defined below. They evaluate to a number. Expr1 must evaluate to a number in the range 0 - 99. The other two expressions are evaluted on a 16 bit basis (range -32000, 32000). The question mark ? may be >, < or =. The expressions are compared and if the condition is true all following lines are skipped until a line with an @ symbol in column 1 is seen. This @ symbol may be followed by a number, and if this number is equal to the value of expr1 the skipping stops, else continues. If there is no number after the @ symbol the skipping stops always. The statement Gotoifn expr1, expr2 ? expr3 is analagous to the above except that the skipping starts if the condition is not true. Finally Goto expr1 leads to an unconditional start of skipping. The expressions may contain numbers separated by the operators + - | & * and /. The operator | stands for logical OR and & is the logical AND. Precedence: + etc as usual, | as +, & as *. The division is integer division, for example 3/2 equals 1. Furthermore the variables _Sw0 to _Sw9 are considered to be numbers with whatever value that they have been set to (zero initially). Here is a simple example, showing also the use of the Synonym statement: Synonym Xxx = _Sw0 Set _Sw9 = 3 Set _Sw1 = 2-3*(22/2-4) Set _Sw2 = 2-(22&2-4)*_Sw9 Set _Sw3 = 6 Set _Sw4 = 1 | 0x20 Z xx = (a + b) ^ 3 + a0^'Xxx' + a1^_Sw1 + a2^_Sw2 + a3^_Sw3 + a4*_Sw4 Gotoif 20, _Sw3 > 5 Id, b = 20*c Goto 21 @20 Id,b = a + c @21 *begin Here is the output in case the value 62 was specified as initial value for _Sw0, by means of a command line specification: Schip S=62 ... If no S=# parameter present on the command line the value of _Sw0 would have been 0 giving 1 instead of a0^62. xx = a0^62 + a1^-19 + a2^8 + a3^6 + 3*a4 + 6*a*c^2 + 12*a^2*c + 8*a^3 + c^3 Note the notation for a hexadecimal number, 0x20 (= 32 decimal). An OR with 1 produces 0x21, i.e. 33 decimal. The AND of 2 with 22 is 2 (in hexadecimal 22 = 0x16, which gives 0x02 when AND'ed with 0x02). In the above case, since the condition is true, skipping starts immediately after the Gotoif statement, and continues till the line with @20 is met. Thus the problem reads: Z xx = (a + b) ^ 3 + ... Id,b = a + c *begin If _Sw3 is not set, or set to some value equal or less than 5 the problem will be read as Z xx = (a + b) ^ 3 + ... Id, b = 20*c *begin Use of Gotoifn 20, _Sw3 < 6 instead of the earlier Gotoif statement would give the same results. If no skipping is going on lines with an @ in column 1 are ignored. 19. LARGE PROBLEM HANDLING. Considerable attention has been focussed on the question of large output. The traditional output sorting method of Schoonschip is inadequate for truly large problems, with more then 50 0000 terms in the output. Moreover, as small computer systems do not have infinite large disk space (typically 20 Mb) a method economizing on that is important. The traditional system works as follows. Generated terms arrive at the sorting routine and are compared with the terms already present in the output store. If found, coefficients are added. If not found, and there is space left the term is entered in the output store. Else the term is simply written to disk, and further adding of terms to the output store is inhibited. This method is quite wasteful as far as disk space is concerned. The timing depends crucially on the disk system, and is generally slow. The new method uses up to five output files. If the output store is full the content of the output store is dumped on, say, file1, and sorting resumes. If again the output is full the store is dumped on, say, file2, etc. If the maximum number of files is reached then merging is done rather then straight dumping. Assume for example that a maximum of three output files has been specified. Assume now that already three files, file1, file2 and file3 have been created. At this point, when the output store is again full, a merge takes place. The smallest file (say file2) is selected, and merged with the contents of the output store to a new file, called file2a (for example, naming conventions are given below). And so on. When the whole problem is finished there are then three possibly very large files. As a final step these three files are piecewise merged into the output store and printed etc. With this method the disk usage is already considerably less than with the traditional method, because only sorted expressions are written to disk. Still, the disk use may be quite more than the final size of the result; each of the above three files may well be of the order of magnitude of the final size. If disk space is really crucial then the above method may be used specifying usage of only one file. The first overflow produces the file. The second produces a merging of the file and storage, giving rise to a new file. Disk usage is maximum at the moment that the last part of the original file is read, and the new file is almost written out. That disk usage is then about twice the size of the final result. To deal with this final factor of two a fractured file system has been implemented. A fractured file is a file split up in smaller files. Each of these smaller files is a normal file to the operating system; only one at the time is opened for reading or writing. Moreover, after reading they are immediately deleted. In the case described one would for example produce file1, fractured up into five files called file1_0 to file_5. When merging this with the output store file2, fractured into file1a_0 to file1a_7 (for example) is created. At the moment that the last subfiles are being created most of the subfiles of file1 will have been deleted. The maximum disk space used with this method is usually about equal to the size of the final file plus an overshoot. This overshoot may be one extra subfile size. In addition of course the overshoot is problem dependent; computing the difference of two large but equal expressions leads to a final size of zero, but the intermediate result may at one point be as large as that of one expression alone. Schoonschip assumes that an overshoot at least as large as the size of the output memory is allowed. This is used to skip the last merging, thus dumping the last output store onto file2 and then merging (possibly very large) file1 with this much smaller file2 while printing. This method appears to be the best one can do concerning disk usage. The timing is reasonable, but goes up quadratically with the size of the final file. To give an idea, a 6 Megabyte final result takes about 6000 seconds merging time, depending on the system (M68000 assumed). If space is no issue then more then one dump file may be specified. The sorting time decreases roughly linearly with the number of files. This is of course very problem dependent. A very important factor is also output memory size. Sorting time decreases roughly linearly with increasing memory size. To allow for adaption to particular systems the size of the output memory may now be specified on the command line when calling Schoonschip. However, be careful with systems having dynamic memory management such as the Sun. If to much memory is specified then the system will accept that and swap memory onto disk as needed. This is of course very counterproductive. It would bring Schoonschip virtually to a halt. Also the format of numbers plays a role. Integers (limit 2 000 000 000) take less space on the disk then most other numbers (6 versus 14 bytes for anyone term). Thus if all numbers can be made integer by means of some overall factor then that will improve both speed and output size. The factor can be divided out later, or whatever. If a precision of less then 9 digits is specified (N 9 or Precision 9) then all numbers written to disk will be rounded such as to fit in 6 bytes. Of importance is the way an expression is factored. This factorization is under control of the user through the use of the B-list. In the output store the terms are stored precisely as they are printed: head1 * ( tail11 + tail12 + ...) + head2 * (tail21 + ...) + ... Without factoring much more space would be used: head1*tail11 + head1*tail12 + ... Too much factoring is also wasteful: head1 * (tail1) + head2 * (tail2) + .... To adequately allow tailoring of a problem a number of facilities have been provided. Notably, for a large problem, a "dry run" may be executed. If that is specified then Schoonschip will not write any file, but simply discard any full output store. An estimate of the time and disk space needed will be made and printed. The estimate is for minimum disk space (i.e. only one output file to be used). Optionally a limited number of terms in the output will be printed, to inspect for optimal factorization. If more then one device is available for storage then it might be desirable to split up the output files over different devices or directories. Also this may be done. Finally the maximum size of the subfiles may be specified. The naming of the files is as follows. All names are of the form TAPxyyyL where x and yyy are hexadecimal numbers. The equivalent of file1_0, file1_1...file1_10,... etc. above is TAP6000L, TAP6001L ... TAP600AL,.... The equivalent of file1a_0 etc is TAPB000L etc. File2_0 is TAP7000L, file2a_0 is TAPC000L, etc. Thus the two groups of output files are TAP6 through TAPA and TAPB through TAPF. File TAP6 when merged with storage produces file TAPB and conversely. Also the "Yep" file has been made into a fractured file. The name used is TAP4yyyL, with yyy starting at 000. In this way the disk usage is minimized in the case of a *Yep. A useful tool in handling large problems is the Freeze command. Suppose there exits a large common file that must be worked on further. In particular, suppose that work must be done on certain factors. If the file has, say, 10000 terms then that work must be done 10000 times. To cut down on the work as well on the size of the problem the following may be done. First, when producing the file specify on the B-list those factors on which the work must be done. For example, if an expression must be integrated over some variable x, with X1, X2 and X3 denoting x dependent factors: Common xfile B x,X1,X2,X3 Z xfile = .... Substitutions, commands *begin The result will be of the form: xfile = x * (terms1...) + x^2 * (terms2...) + X1 * (terms3...) etc. There may be many terms inside the brackets. As the file must be a common file it now resides on disk. The subsequent command (after the *begin) Freeze xfile produces the following result. The file xfile is read and split up in one main file and possibly many 'frozen' subfiles. The main file will still be called xfile, and is as follows: xfile = x * DF(xfile,1) + x^2 * DF(xfile,2) + X1 * DF(xfile,3) etc. The subfiles are denoted as x_file: x_file(1) = terms1 x_file(2) = terms2 x_file(3) = terms3 : : The frozen subfiles are not directly accesible like other files. They may be referred to only by means of the DF function. There is a command, Expand, that allows substution of the subfile for the DF function. For example, Z xx = DF(xfile,3) Id,Expand,xfile *end will produce for xx the contents of x_file(3). This may also be used to restore the file to its original shape: Common xfilp B x,X1,X2 Z xfilp = xfile Id,Expand,xfile Delete xfile *begin The new file xfilp will be precisely as the original xfile. Deleting (but not replacing) a frozen main file leads to deletion of all frozen subfiles. It is clear that the work on the frozen main file xfile will be much less voluminous since it will have many less terms. After the work has been done one may re-establish the complete file using the Expand command. Freeze is a very powerful tool. It must however be used with some care. Most importantly: file arguments are not, repeat not, transferred to the subfiles. For example, defining Z xfile(a1,a2) = ... and subsequently freezing xfile leads to a number of subfiles. Using now xfile with some other arguments, Z ha = xfile(mu,nu) and subsequently expanding the subfiles will not lead to the replacement of a1 and a2 in the subfiles by mu and nu. Thus as a general rule a file to be frozen should not have arguments. Particularly tricky are created indices here. If such indices are summation indices then it may happen that of such a pair of indices one appears outside parenthesis, and one inside, and thus may become part of a frozen subfile. Since Schoonschip often renames summation indices there may then result a situation where the index outside is renamed, while that inside remains the same. See the discussion at the All command. 20. FILE HANDLING COMMANDS. This section assumes that the reader is familiar with the section on large file handling. The commands may be in upper or lower case, and only the first two (three if confusion possible) characters are significant. To specify Traditional sorting: Traditional Whatever the default is and will be is a matter of time and experience. The specify the new method: Large # where # is a number in the range 1 to 5 inclusive. Default is 2. It specifies the number of output files to be used. To specify the maximum size of the subfiles: Maximum # where # is the maximum size of the subfiles in bytes. Default is 110 000. For each of the subfiles a prefix (directory) may be specified. One may either specify a collective prefix for all subfiles regardless of the first number (6-F), and/or specify individual prefixes. Here is the syntax: Directory #,prefix1,#,prefix2,#,prefix3,... For any subfile the number designating the subfile is compared with the chain. The prefix inbetween two numbers (including the first but not the second) that have a range including the file number will be used. If the number is less than 1000 hex (=4096) then only the last three hexadecimal digits of the file number are used, else all. The prefix is simply glued in front of the name TAP... as described before. The special notation . (just one period) designates no prefix. It should be noted that Schoonschip accepts hexadecimal numbers with the notation 0x... where ... are hexadecimal digits. For example 0x100 is the same as 256. Here some examples. Directory 0,/usr/tmp/,10,/user1/tmp/,100,. The numbers must be in ascending order. This statement must be the very first in any Schoonschip program, and it must be in a *Fix section. Files TAPx000L through TAPx009L are prefixed with /usr/tmp/: /usr/tmp/TAP6000L for example. Files TAPx00AL through TAPx063L are prefixed with /usr1/tmp/. Files TAPx0064L and up get no prefix. There is collective sharing of directories, for example TAP6001L and TAPB001L get the same prefix. Directory 0x4000,/usr/tmp/,0x6000,.,0xB000,/usr/tmp1/ The prefix /usr/tmp/ is assigned to files TAP4yyyL and TAP5yyyL. Files TAP6yyyL through TAPAyyyL get no prefix, and files TAPB000L up get /usr/tmp1/. Files TAP0yyyL through TAP3yyyL (not yet used) get no prefix. Default: no prefix. The old statement Outlimit # specifies in all cases the maximum number of bytes that can be written. Default: 500 000. To obtain information on the size of the various files being written use the statement Showlength It causes Schoonschip to print the total size and the name of the last subfile after completion of that file. The statement Nshow Switches it off. The statement Dryrun # causes Schoonschip to do a dry run as described before. The number # specifies the maximum number of terms that will be printed. This statement may appear also after a yep for example. If # is 0 or absent no dry run is made. 21. SUMMARY. Lines with a C in column one (excluding Common) are comment lines. Lines with a blank in column one are taken to be continuation lines (also for C-line continuations). Lines with a ~ in column one are ignored. A ! signals the start of comments on a line, but otherwise is seen as end-of-line. Print options: P brackets First 2 characters significant. P heads First 2 characters significant. P input First 2 characters significant. P lists First 2 characters significant. P ninput First 2 characters significant. P nlists First 2 characters significant. P noutput First 2 characters significant. P nstatistics First 2 characters significant. P output First 2 characters significant. P statistics First 2 characters significant. Lprinter Print output lines till 130 characters. Screen Print output lines till 80 characters. External file reading: Read fname Start reading from external file fname. In fname no Read statements allowed. End Switch back to normal input and close the file. A subsequent reading of that same file starts again at the begin. Common file manipulations: Enter Cfile Enter common files contained in file Cfile. Must be in first section, terminated by *fix There may be several Enter statements in that section. Write Cfile Write common files to file Cfile. Blocks and DO-loops: BLOCK Name{arg1,...} Defines Block Name. In text arguments between ''. Call: Name{brg1,...} Name must start in col 1. If an argument contains comma's this argument must be enclosed in {}. Concerning nesting: Schoonschip strips away one layer of {} at a time. ENDBLOCK DELETE Name1,Name2,... Delete blocks Name1,... DO L1=n1,n2,n3 Optional n3. If absent is taken to be 1. In text ENDDO argument L1 between ''. File related statements: Common Name1,Name2(0),Name3,.. Defines common files. Delete Name1,Name2(5),Name3,.. Delete files. Keep Name1,Name2(5),Name3,.... Keep local files over a *next. Names Name1,Name2(5),Name3,... Enter namelists of these files. Nprint Name1,Name2(5),Name3,.. Do not print these Z-expressions. Print Name1,Name2(5),Name3,... Print these Z-expressions. Punch Name1,Name2(5),Name3,... Write to tape8 in Fortran compatible form. In certain lists the name of an indexed file may appear without index. In that case the command applies to all files with that name. This holds for Delete, Keep, Nprint, Print and Punch. Various 'first-column' types: * Start execution or go on to next section. Options: fix yep next begin end The *fix section must be the first section. All names, but not expressions in brackets are kept over a *yep. *next as *yep, except that local files not mentioned in a Keep list are deleted. All except fixed quantities and common files are deleted over a *begin. *end signals end of input file. A a1,a2=x,.. Algebraic symbol list. If x is a number then powers of a2 equal or higher than x are set to zero. Alternatively x may be c, r or i, denoting reality properties. Default is r. Constructions such as a2=3=c are allowed. Al Substitution or command on same Level. On a line starting with Id subsequent ; are read as Al, B b1,b2,.. List of symbols to be factored out in output. Legal: symbols, vectors, dotproducts, vector comp. If a vector name is mentioned all dotproducts and vector components referring to that vector are factored out. D Name(n,..)=xpr,xpr,.. Data expression. Expressions must be single terms. F f1,f2=x,.. Function list. Reality properties may be specified through x, legal are i,c,r and u. Default is r. I i1,i2=x,.. Index list. The dimension x may be a number or a single character algebraic variable, defined before in an A-list. Id Substitution or command on next free Level. See Al. Oldnew a1=b1,a2=... Change name a1 into b1 etc. Outlimit # Change output byte limit. Default: 500 000. Sum i1,i2,.. Declares i1,i2,.. to be summation indices. This is not related to the summation indices of the DS function, but indices appearing twice according to the Einstein summation convention. Indices in this list must have been defined before. T Name(n,,,)=sy1,sy2,.. Table. T Name: "X=1:1,.. Character table. V p1,p2=z,.. Vector list. Names of 1 or 2 characters. The optional z implies that p2 is to be set to zero as soon as it occurs, also in vector-component or dot-product. X Name(arg,..)=xpr X-expression. Z Name(arg1,...)=xpr Z-expression. If arg1 is a number or simple numerical expression Name is a subscripted file. The number must be in the range 0-32767. Here a simple numerical expression may contain numbers, or block or DO-loop arguments that become numbers, separated by +-* or /. The general structure of a substitution or command involves several elements that can be separated in groups. All groups and elements must be separated by comma's. The first group is the Id or Al itself (with possibly ; instead of Al,) optionally followed by a number: Id, Al, ; Id,#, Al,#, ;#, The number specifies on how many Levels the substitution or command is to be applied. The next group may contain one item, namely a keyword. This only for substitutions, not commands. Valid keywords are: Multi Funct Dotpr Ainbe Adiso Always Once This group may be empty. The next group either defines a pattern followed by a = sign or is a command followed by arguments separated by comma's (if any). Patterns are products of factors, with dummies designated by a ~ following the symbol. Not all factors can be dummies. See section 10. The available commands and their formats are: Absol Force coefficien positive. Addfa Add factor. Id,Addfa,expression All Collect vectors p into function F. Created indices may be assigned a dimension. First syntax: Id,All,p,N,F possibly followed by the character arguments "F_, "D_, and/or "V_ which inhibit function argument, dot-product or single vector inspection (example: Id,All,p,N,F,"F_). Second syntax: Id,All,F1,N,F Collect all vectors of function F1 into F. Substitute a created index in F1, and also as additional argument of F. Anti Check function arguments for characters, and if _ present remove that if character mentioned in anit-particle chcracter table. Id,Anti,TA Asymm Re-arrange arguments of anti-symmetric function. Id,Asymm,f1,2,3,4,f2,f3,4,5 Id,Asymm,F1:2,3,4:7,8,9:12,13,14: Id,Asymm,F1:1-3:7-9:12-14: Beep Generate a beep on the terminal. Id,Beep Coef Inspect numerical coefficient. IF Coef,option options: pl plus ng negative eq,# equal lt,# less than gt,# greater than ib,#,# inbetween Commu Re-arrange commuting functions. Id,Commu,f1,f2,f3,... Compo Compose names. Id,Compo,,f1,f2,,f3,f4,.. options: AFIVX with AFV possibly twice. Optionally "S_ suppresses symmetrization of the name. Optionally a character table may be specified, to be used if characters with an underscore appear. Count Count certain occurrences with certain weigths. Id,Count,xxx,arg1,#,arg2,#,.... If xxx number then term kept if count equal or larger than xxx. If xxx symbol or vector-component or dot-product xxx^# is made. If xxx function or X,D expression then xxx(#) is made. In that case a multiple count can be made: Id,Count,Fx,arg1,#,..,# : arg2,#,..,# : arg3,#,... Now Fx(#1,#2,#3,...) is made with #1 determined by the arguments up till the first colon, #2 by the arguments between first and second colon etc. Cyclic Function invariant under cyclic permutation of the arguments. Id,Cyclic,f1,2,3,4,f2,f3,4,5 Dostop Set, clear or test Dostop flag. Id,Dostop,X where X = On, off or test. Default test. Epfred Reduce products of Epf functions. Even Function even in sign of arguments. Id,Even,f1,2,3,4,f2,f3,4,5 Expand Expand frozen subfiles (appearing as DF(fname,#) ). Id,Expand,fname Extern Jump to user defined routine. Id,Extern,arg1,arg2,... Iall Inverse of All. Id,Iall,p,F Id,Iall,F Numer Insert numerical values. Id,Numer,arg1,#,arg2,#,... Odd Function odd in sign of arguments. Id,Odd,f1,2,3,4,f2,f3,4,5 Order Order functions on the basis of their first two arguments. Id,Order,F1,F2,... Print Print a message, maximally # times. Id,Print,#,Message Ratio Rationalize. Id,Ratio,xpa,xpb,bma Stats Count passage in one of four counters (0-3). Result printed at end. Id,Stats,# Symme Re-arrange arguments of symmetric function. Id,Symme,f1,2,3,4,f2,f3,4,5 Id,Symme,F1:2,3,4:7,8,9:12,13,14: Id,Symme,F1:1-3:7-9:12-14: Three commands are special to problems of relativistic quantum mechanics: Gammas Collect, Reduce and/or take trace of products of G's. Id,Gammas,options,L1,L2-L3:options,Trace,L3,L4-L5:options,... options are designated by characters: "C collect only, "A anomalous trace, "S do spinsum, "U unify strings, "I do index pair reduction, "i do index pairs in _-type strings, "P do P-tricks, "W do final work. All options except "C may be followed by an underscore, implying switching off. The "C option when not combined with anything else gives normalization, however without ever specialization to four dimensions (essential if there are non-four-dimensional vectors) Default: "A_,"S,"U_,"I,"i,"P,"W Spin Replace pairs of Ug,Ubg by spin-summation expression. The spinors may be defined by loop indices or vectors. Id,Spin,L1,p,... Ndotpr Create special dot-products. Closely related to Gammas command. Id,Ndotpr,F1 A number of special functions is build in. They are: D Delta function. Epf Anti-symmetric Weyl tensor. May have any number of arguments. DD Internal purposes (used to represent X and D expressions and files). DS Summation function. Format: DS(J1,#,#,(xpr1),(xpr2)) xpr2 numeric, optional. The sum over the given range is constructed. The numerical coefficient is by recursion, using xpr2. The first coefficient is 1. Example: e^x = DS(J,0,20,(x^J),(1/J)) + O(x^21). Caution: summation symbols such as J may be used only once in a given expression. Character summation: DS(C1;C2;..;Sym;C3;C4;TX,..,2:4,7,(xpr)) Numerical functions (may be part of expressions that must be numerical such as for instance expressions occurring as exponents, or with a negative exponent, but not of simple numerical expressions such as Z-expression index): DB DB(n) = n! DB(n,m) = n!/{m! (n-m)!} DB with two arguments is word-bound, fails if n=19, m=8,9,.. DT DT(n1,n2,..) 1 if all arguments positive or zero, else 0. DK DK(n1,n2) 1 if n1=n2, else 0. DP DP(n1,n2,..) 1 if permutation to smallest first is even, else 0. Order normal: -127,..,0,...,+127. 0 if two arguments equal. DF DF(xfile,#) or DF(xfile,#1,#2) The last case is equivalent to the first with # = 100*#1 + #2. DC DC(n1,n2,..) 1 if sum of all arguments is 0, else 0. DC("X,.....) "X is option character. May be "C, "F, "T with or without underscore following. Special functions relevant to particle physics are: G(L,mu) Gi(L) G5(L) G6(L)=Gi(L)+G5(L) G7(L)=Gi(L)-G5(L) Ug(L,m,p) Ug(L,mu,m,p) Ubg(L,m,p) Ubg(L,mu,m,p) Use -m for anti-particle spinors. New notation: G(i1,i2,mu,nu,..,G6,..) Gi(i1,i2) G5(i1,i2) G6(i1,i2) G7(i1,i2) Internally generated G-strings: G(L1,"s,"4,mu,nu,..,G5,..) General 4 and N dim mixture. G(L1,"t,"4,mu,nu,..,G5,..) General 4 and N dim mixture. G(L1,"S,"X,mu,nu,........) 4-dim. "X may be "4, "5, "6 or "7. G(L1,"T,"X,mu,nu,........) 4-dim. "X may be "4, "5, "6 or "7. G(L1,"s,"_,mu,nu,........) N-4 dim. G(L1,"t,"_,mu,nu,........) N-4 dim. APPENDIX A. COMMAND LINE OPTIONS. The standard usage is: Schip file1 file2 options Schoonschip input is supposedly contained in file1, the output is written to file2. Fortran compatible output (directive Punch) is written to tape8. If file2 absent then the output is written to standard output, i.e. the screen. If in addition file1 absent then the standard input (the keyboard) is used as input. When doing that remember that *end terminates the run. Also errors lead to termination. Normally Schoonschip echo's the input lines back to the screen. Alternatively input, output and punch file (tape8 by default) can be designated by means of the notations i=, o= or f= (the f stands for Fortran compatible; upper case accepted as well): Schip i=file1 o=file2 f=file3 This cannot be combined with the first method. All options are optional. First one may specify certain options by preceeding them with a - sign. These options are: s For Schoonschip versions running on a PC with bitmap screen. The "Ready" line and the requested keyboard input are suppressed if s (for silence) specified. b Certain Fortran compilers do not accept negative exponents without brackets (for example A**-3). If b specified brackets are written. The default is no brackets. p Show progress by printing a point (.) to standard output every 128 terms. . Place a . after every integer in the output. Some Fortran compilers insist on this. Also upper case characters may be used. Example: Schip file1 file2 -b.p Options b, . and p apply. These options may also be selected inside a Schoonschip program by means of the statements Silence Fortran options Progress on Progress off These statements are discussed elsewhere (section Miscellaneous). Another option leads to noise (Control-G is sent to the terminal) upon completion. This may be specified as b=# where # is the number of beep's the terminal is to receive. The option S=# where # is a number in the range -128, 127 inclusive implies setting of the initial value of the parameter _Sw0 to the value #. Example: Schip file1 file2 b=10 s=19 Upon completion 10 beeps will be sent to the terminal (with some interval). The initial value of _Sw0 is 19. Most important, one may now specify memory usage to Schoonschip. There are two large storage areas used during execution, called the input space and the output space. The input space contains the expressions, substitutions, etc. The output space is where the final result is collected. Performance in case of large expressions is very sensitive to the size of the output store. The larger the better. As an heritage of the old CDC days Schoonschip has always been very frugal in memory usage. The build-in size of in- and output space used to be 20 Kb and 50 Kb respectively. Given that nowadays few machines have less than 1 Mb of memory that seems to frugal. The version of Jan 1, 1989 is more expansive. To begin with an amount of about 80 Kb is used separately for buffers etc. This used to be much less. Default sizes for in- and out space are machine dependent, but typically 100 Kb and 250 Kb are taken. The total memory usage (excluding Schoonschip itself, which is about 100 Kb) comes then to about 450 Kb. The in- and out sizes may now be specified on the command line. To this purpose one uses the notation IS=# and OS=# (lower case accepted also) where the # stand for number specifying magnitude in Kb. Thus the old situation is obtained with this command line: Schip file1 file2 IS=20 OS=50 Finally a number # preceeded by a + sign can be specified on the command line. Then Schoonschip skips the first # problems on the input file. Every occurrence of a *end line counts as one problem. Example: Schip +5 Varia Out Problem five in file Varia is executed. Some other examples: Schip Infil Outfil -bp The file Infil is taken to contain the input, output is written to Outfil. Dots are printed when starting a problem, and further every 128 terms. Brackets are placed around negative exponents. Schip +1 i=Varia o=Vario -p Problem 1 of Varia is executed, the output is written to Vario and meanwhile dots on the screen show progress. APPENDIX B. COMPATIBILITY. Programs working with older 68000 versions will work provided the square brackets [] are taken out and replaced by for example curly brackets. In addition there is a slight change in Integ (evalution of numerical expressions as function arguments). It now truncates, rather then rounding to nearest integer. The statement 'Round on' may be used to re-instate rounding (CDC versions of Schoonschip truncated). The command Trick is now called Gammas, but will still be accepted. The block delete command, DELETE (all upper case) has been replaced by BDELETE (case insensitive, only the first four characters significant). The rarely used statement 'Printer' has been replaced by Lprint. Programs that executed on previous (CDC) versions of Schoonschip will also run with this version with minor, mainly cosmetic modifications. The main differences are in the use of lower case characters in this version, and furthermore different notations for BLOCK and DO-loop arguments. - Block arguments in the text of the block must be embedded in quotes. The same holds for DO arguments. These latter can now take negative values in all cases. Use of {} obligatory. Block arguments, in a call, may now have comma's provided they are enclosed in {}. The word COPY is no more needed when calling a block. Block names may at most be 6 characters in length. - The complex variable I is now written as i. If needed the statement Oldnew i=I takes care of this. - The S-list is now the A-list. However, S is still accepted. - ID and AL are now Id and Al. However, both are accepted. - GI is now Gi. - CONJG and INTEG are now Conjg and Integ. - Various keywords and commands have sometimes slightly different spelling, ODDXX is now Odd. - The Print options have different format. For example, PRINT INPUT is now P input. - Dummies are now characterized by a following ~ instead of a +. - An exponent may now also be denoted by ^ instead of **. - The special function DX is no more implemented. It is used internally for purposes relating to the Gammas command. - Characters as function argument are denoted by "X instead of =X.