dib manual (deer project, 2008, Antonio Maschio @ ) Last updated: July 06, 2009 Version 1.0 This is not a BASIC primer, but the user manual of dib, the Dartmouth BASIC interpreter written in C for the gcc. Index ----- 0. A foreword 1. A bit of personal history as introduction 2. The dib interpreter 2.1 Installing dib 2.2 dib's invoking options 2.1.1 Options explained 2.1.2 Customizable items 2.3 A datum is a datum is a datum... 2.4 Default features 2.5 Extended features 2.6 Error messages 2.6.1 standard error messages 2.6.2 extended error warnings 2.6.3 system error messages 2.7 The examples 2.8 The vim 'bs' syntax file 2.8.1 Installing dib.vim 2.8.2 Mapping the dib syntax 3. Conclusions 4. Bibliography ----------------------------------------------------------------------------- 0. A FOREWORD ---------- Sometimes I read on some mailing list about programming, or on newsgroups dealing with this or that programming language, or on specific programmers' web pages, that "BASIC was a primitive language"; well, this may be true, in some arcane sense, especially if you consider some modern complicated language like java, C++ or Delphi or peculiar languages such as Prolog, Lisp, Forth. But I contest this sentence 1) because BASIC 'was' not, BASIC 'is'; 2) because BASIC is not primitive: it's simple. It's a rather different question. Imagine you have to solve a math problem, say a system of linear equations, and suppose you've got to write a program for this; which language will you choose? Your 'favorite' may be too big for such task. Well, in the best case you know this language very well, and you will end up without spending hours in writing the program, but in the worst case you're lucky if you have not to plunge into a 1000 pages user manual or learn tens of system calls. Why not using Dartmouth BASIC? No more than a bunch of lines (containing even the problem data) and the solution is there. No manuals, no system calls. Yes, BASIC is an unstructured language - and someone said that a programmer exposed to BASIC is likely to never learn well another language (this ain't true, obviously) - so I guess that, if BASIC is unstructured, it expects you to give it a structure. And the structure you create may make it spaghetti-code looking, or make a superb listing of it. Dartmouth BASIC gives you two dozens of statements and a consistent way to use them. It gives you a simple structure for each statement and *you* have to build a wider structure for your program. It's up to you: BASIC has no soul, it waits for you to give it one. After all, BASIC is a language that can be used by anyone, that won't force you to format numbers output, that uses matrices like numbers, that solves systems of equations in a bunch of statements, that remains familiar and usable for years. Some of us wouldn't ask for more. Yes, using such a language today is quite unrealistic. I had to write my own interpreter to do it, and this is not what I call a friendly way. But hail to those guys who conceived such a language in 1964!! 1. A BIT OF PERSONAL HISTORY AS INTRODUCTION ----------------------------------------- It was during my High School days that I met the BASIC language for the first time; it was a schoolmate, who had later to become my best friend, to introduce me to programming, because of his wonderful brand new Commodore 64, he received for Christmas of 1982 or 1983 (memories fade). From this moment on, I kept trying to convince my parents of the extraordinary need I had for a computer like that and that I couldn't even imagine how to get through University without it! Lost words. My father, whose sight was very long, told me he could get his High School degree with a 5 inches slide-rule. Thus, a computer was not a 'need'. What could I do? I spent a lot of time in my friend's room, staring at the wonderful colors of the screen, and learning my first BASIC words while listening to him reading sources and watching him typing commands. Once back home, the only way to relax was playing my guitar, because I had no computer at home, and even my calculator was not programmable. I was in a sort of "need of programming"... Anyway, for my next birthday, my father finally made me the gift I wanted: the CBM64! I wasn't surprised at all, since I think I had stressed him a lot for that. In Italy, those were the days of microcomputers, and first computer magazines - BIT, Microcomputer, and others - each full of listings in BASIC for this or that computer, fighting a sort of battle of the dwarves between the CBM64 and the ZX Spectrum. I was a 64er. In 1983 I was studying my first math function in the cartesian space, so the first thing I wrote was a program to draw a function y=f(x) on the screen, plotted in high resolution (I'm afraid I was not so smart to do it all alone: probably, I took the original source from a magazine and changed it a bit). Anyway, the pride I felt showing the results to my father pushed me to learn more about programming; I bought then the C64 monitor, the 1541 disk drive and [4]. I began studying [4], learning that machine language was available through some hacking, learning about sprites, the three independent music oscillators (a system called SID), and all the peculiar memory addresses, but I didn't go beyond BASIC for two reasons: first, machine language seemed to me too difficult and strange and second, I thought BASIC was a wonderful language to do quite everything (though programs ran slowly!). I bought then [3] and began studying it seriously. The book was very professional, and all (or almost) was applicable to my home computer, so I felt like a very mature programmer! One thing baffled me: the fact that all MAT statements were completely missing from my home computer, while I was sure it was more recent than the one described in the book! In 1985 I began my University years, and for many years I couldn't do anything else with the Commodore unit. I studied Pascal and Fortran 77, using the VAX mainframe of the University Calculus Room, equipped with UNIX (circa 1987-88); much later, I could use PCs with DOS in the computer room of the Engineering University (circa 1990-91, I believe version it was DOS 2.x), and so the CBM64 was left behind, with all its power. At home, abandoned, the C64 went ruined, and one day my mother got rid of it without even telling me. The day I knew what happened was a very sad day! In 1993 my parents bought me a PC with Windows 3.11: it served me to do some word processing for my thesis, but it was also a starting point in serious computing. When I finally got my degree in civil engineering, in 1994, I began my job, and years began to fly. In 1998 I installed linux on my PC and began studying C, bash and prolog, and BASIC was not in my mind. So I lost any contact with it: line numbering, GOTOs, the absence of specific functions and procedure calls, and other minor things, confronted to the "new" languages I was learning, led me to forget BASIC, because it was old. *** *** Time takes its time to work, but it works. In the summer of 2004, I visited Ron Nicholson's site by chance, and discovered his chipmunk basic interpreter. Ah!: BASIC was not dead, after all! Next, reading some documents found in Internet ([1] in particular) I learned that BASIC was born in the Dartmouth College in 1964 (many years before C!), that its first versions were compiled and that they dealt with matrices (a feature that was stripped from all subsequent BASICs). These facts were so appalling that I took the C64 manual and the Gottfried book out of their dust; reading them again revealed me one mere thing: I didn't cease to love BASIC. Next step was conceiving a BASIC interpreter on my own, to be developed on my brand new emac 1.42 equipped with Mac OS X. Why not? There are dozens of compilers and interpreters in the world, one more will do no harm. The reason that led me to forget BASIC is now the reason that leads me to love it: because it's old! 2. THE dib INTERPRETER ------------------- 2.1 INSTALLING dib -------------- Installing dib is easy: it's a matter of 'make' and 'make install'. Simple. First of all copy the tarzipped source file into a safe place where you have writing privileges; then, if the name of the source is for instance 'dib.N.N.N.src.tgz' (where the Ns are placeholders for the version numbers): $ tar zxvf dib.N.N.N.src.tgz or, if your tar program cannot manage the unzipping: $ gunzip dib.N.N.N.src.tgz $ tar xvf dib.N.N.N.src.tar After extraction, you will find a directory named dib.N.N.N.src/. Step into it: $ cd dib.N.N.N.src/ Now, to compile, type: $ make and to install (as root if into system directories): # make install This makes dib available to anyone. To test it's been correctly installed, from your home directory type: $ dib --help To uninstall dib, enter the very same installation directory and type (again as root if from system directories): # make uninstall The directory USER/ contains a lot of examples, ready to be run. 2.2 dib'S INVOKING OPTIONS ---------------------- dib must be invoked with the following syntax: $ dib [options] file Options are: -b Set array base index to 1 (default is 0) -c Continue execution in case of non-blocking errors --conditions Print redistribution conditions from GPL3 -d Activate debug mode -h, --help Display this information and exit -l Display error list and exit -p 'expr' Print BASIC expression 'expr' and exit -s Start executing BASIC program from line -t Print a time report after execution -v, --version Display version and exit --warranty Print warranty conditions from GPL3 -x Toggle extended BASIC features setting (default is off) -z Print numbers lower than 1E-10 as zero A version of this paragraph appears when dib is invoked as dib -h/dib --help. 2.2.1 OPTIONS EXPLAINED ----------------- Note: all options that perform a task and then cause dib to exit, without any file elaboration, are generally unaware of the existence of other options specified on the same command line; thus, these options should be used alone, and they generally don't need a file name to operate. -b: base set option base to 1; at start, dib has a default 0 index base. In extended mode you can set option base to 1 with the OPTION BASE 1 statement, which is not available in default mode. The index is consistent in arrays, matrices and vectors, so you have not to wonder which has what: once you choose an index base, it remains the same for all elements. -c: continue after an error, generally, dib stops and prints a message; if you want it to go on, activate this option, but **at your risk**! In fact, the program may call not instantiated variables, or execute jumps or math expressions with values not correctly initialized, so a system error (like "segmentation fault" or "BUS error") may appear onto you terminal. See paragraph 2.6. -d: debug activate debug mode; when debug mode is on, the current line is printed before it is executed; this of course alters the output behavior, but you can trace the program flow, and maybe understand why your BASIC code is not working. Note: in extended mode, the final line containing END is not required by a source file (see ahead); but, in order for the parser to work, if no END is met into the source code, a superimposed END statement is implicitly put at line 119881 (one above last available line), and this line appears in the debugging session, even if the programmer doesn't expect it. -h; help print the standard UNIX help and exit (also --help). -l: list of errors print the whole error messages list with the relative error code end exit; since a system error causes dib to exit with 100+error code, you can get this exit status in a shell program, and recover the error code active when dib was interrupted. If you forget what error message is associated to a particular error code, here's the -l option coming in handy. No program is executed. -p: print expression print a BASIC expression and exit; this option must be followed by a BASIC expression enclosed in single quotes; by the term I mean anything syntactically suitable for the PRINT statement: strings, calculations, mixed values; of course, variables and matrices cannot be used in this context (it would be a nonsense, since they cannot be initialized into a PRINT statement), but the full power of dib is in action for algebraic expressions, that are always evaluated in extended mode. So, from the command line, invoking: $ dib -p 'expr' is equivalent to the BASIC statement PRINT 'expr'. (All functions in capitals, of course!). The space between -p and the first single quote is optional. -s: starting line this option enables dib to start a program from any line number, rather than from the first available only; I don't know if the original Dartmouth Operating System could do this, but I guess it's a minor point. If the starting line specified in the -s option does not exist, the first valid forward line in the source code will be the starting line; e.g.: if you have a source in file PROG with active code lines between 10-70 and between 100-150, invoking: $ dib -s80 PROG will start execution at line 100. No space is allowed between -s and the number, and if the number is zero or negative, it is automatically promoted to 1. -t: timing after the program is terminated, print a timer report in the form: TIME: N SECS. where N is the number of seconds execution took. It is in the style of the 1964 Dartmouth BASIC manual (see for instance p. 19). The timing measures the real BASIC execution, letting out all dib's initialization routines; this results in a pure "BASIC code execution time". No conversion to minutes or hours is done. -v; version print the standard UNIX version banner, and exit (also --version). -x: x-tended features this option enables the extended features. See paragraph 2.5. -z: zero portrait all numbers lower than 1E-10 are printed as zero, useful when they may clutter the output, e.g. with matrices. In this case, you can distinguish "pure" zeroes from these approximations because the latter are always preceded by their sign, positive or negative; so that: 0 means a zero as calculated by dib, -0 means an approximation downward (for instance -2.3E-14), +0 means an approximation upward (for instance 2.3E-14); you can change the limit of 1E-10 changing the EPSILON constant in dib.h, but a valid number must be greater than ZERO (see par. 2.3). To know terms of warranty and conditions, type 'dib --warranty' and 'dib --conditions' (these commands print extracts of license, as required by the GPL v3). 2.2.2 CUSTOMIZABLE ITEMS ------------------ In file dib.h there are some values you can safely change to suit dib to your needs: - 'ef' is the variable flag that controls the extended features activation; it's FALSE by default; you can turn it to TRUE to have extended features always activated; if you do it, using option -x will disable extended features, rather than enable them. - 'ob' is the option base index; it's by default 0; you can change it to 1 if you want to have option base index always starting from 1; if you do, option -b will have no effect, and the only way to set option base 0 from here is using OPTION BASE 0 in extended mode. - 'false_' (mind the final underscore) is the flag that controls error short-circuit; by default it's TRUE, which means that dib stops at every error met; if you set it to FALSE, dib will stop only when a blocking error is met (see ahead); if you do it, option -c will set false_ to TRUE rather than setting it to FALSE. - 'EPSILON' is the limit for numbers to be printed as zero. By default it is 1E-10, so that all numbers lower than EPSILON are printed as zero; you can put here any value you like, provided it's not smaller than 1E-75, the lowest number dib can read: smaller values are for dib undistinguishable from zero. Don't change other variables, parameters, constants, unless you know very well what's that you're doing: you may mess up things and end up with an useless program. 2.3 A DATUM IS A DATUM IS A DATUM... -------------------------------- Numbers ------- As the original BASIC, dib deals with a single number type: real. Any number is written as an integer if the internal representation of the real is made of all zeroes after the dot; e.g.: 10 PRINT 1.0 will print 1 Notice the space before the number: a place for the sign is always printed in Dartmouth BASIC and, if positive, a space - not a plus - is printed. Sometimes reals behave like integers if they have too many zeroes after the dot and before a non-zero digit; e.g.: 10 PRINT 1.0000002 will print 1. Notice the dot after the number, meaning that the number is not really an integer, but a "masked" real. Any number may be input using the ten digits, the prepended minus, the dot and the letter E for powers of ten (.2 is accepted, 1E2 too, E2 is not). Follow instructions on the 1964 manual at page 8: dib is built on the same basics. Number limits are set as follows: - the max (positive) real is 1E75, identified (in the source) as INFF - the min (negative) real is -1E75, identified as MINFF - the smallest absolute value of a real is 1E-75, identified as ZERO These values have been set after reading on [9], page 5, comma 8, that "The maximum exponent allowable in the GE-235 is 75". There are some issues, here; the INFF/MINFF/ZERO limits are not set into values themselves, but only in printing; so the internal value is preserved for further calculations; this causes dib to be... er... clever than the original (see ahead, errors 30/31). According to [11], the use of booleans was not in the Original Dartmouth BASIC; dib, on the contrary, treats any expression as a truth value, since truth values are simply real numbers (set as TRUE=-1.0 and FALSE=0.0); of course, this is meaningful only if you print out a truth value, e.g. PRINT 3>2 (which is quite useless on its own) or if you use a variable as truth value, e.g. IF A THEN (which was, probably, not available in the original BASIC); in the first case the output will be -1, in the second case, the part after THEN will be executed if A is different than 0 (any value). Remember that this may not be available in other dialects. Variables --------- dib has the standard variable names as the original BASIC, nothing more. So A..Z and A0..Z9 are the ranges of all the available variable names. Double letters or even longer names are forbidden - e.g. AB or TANKVOLUME (but see next subparagraph called "Capitals"). There are no string variables. Arrays ------ dib uses arrays in the same way of the original basic, with a DIM statement to instantiate some memory space for the array; any undeclared array is automatically instantiated to a 10 or 10x10 array (the dimension depends on the array you invoke, that is A(2) will instantiate a vector, while A(2,4) will instantiate a matrix). Of course, any reference to an undeclared array with indexes greater than 10 will raise an error. Note: the automatic instantiation is not taken into account with the MAT commands; when using a MAT command, you have to instantiate the arrays before (this is the same behavior, of course, of the original BASIC - see page 51 of the 1964 manual). The original Dartmouth BASIC had a strange behavior with indexes: arrays and tables (bidimensional arrays) had indexes starting from 0, while matrices (the one to be used with the MAT statement) had indexes starting from 1. dib is more constant, on this regard: all indexes start from 0, but if you set option -b at start, or if you use the OPTION BASE 1 statement in extended mode, indexes will start from 1 both for arrays and matrices. Arrays are always to be read as vertical arrays: to declare a horizontal array you have to dimension a degenerated matrix like DIM A(B,N), where B is 0 or 1 depending on OPTION BASE. Vertical arrays declared with DIM Z(N) or DIM Z(N,B), where B is 0 or 1 according to OPTION BASE (0 or 1), behave in the same way with all commands. In effect, DIM(Z) declares a pure vertical array, while DIM(N,0) declares a degenerated matrix, constituted by a column only. (This kind of vectors are those used for solving equations systems of the kind AX = B, where A is a square matrix, B is the vector of known terms, and X is the solution vector, B and X both vertical and as high as the matrix height (the system is solved premultiplicating both sides by the inverted matrix A-1 (the solutions vector is simply obtained multiplicating the inverse by the knowns vector in this order): -1 -1 -1 ( A )AX = ( A )B => X = ( A )B; Matrix A must be square, size NxN, and B must be a vertical vector of size N. An array declared with DIM Z(B,N) where B is 0 or 1 according to OPTION BASE (0 or 1), is a horizontal array, in effect a degenerated matrix constituted by a row only, which is an object of type "matrix". It can be transposed to a vertical one ("vector" or "matrix") and back, as well as a unidimensional vector (vertical) may be transposed to a horizontal vector. Remember that with OPTION BASE set to 1 (or using the -b option at start), you cannot dimension vectors with indexes starting from 0! A final note: with OPTION BASE set to 0, you may be tempted to dimension peculiar arrays like DIM A(0) or DIM A(0,0); your intention would probably be that of having a degenerated one-element array. Well, this won't work in dib, depending on the particular internal rapresentation of arrays: such an array would be interpreted as an uninstatiated array, and redimensioned to a 10 or 10x10 array the first time A(0) or A(0,0) is invoked; any reference to A(0) or A(0,0) will of course be preserved, but beware when you use MAT PRINT on such arrays! Arrays can be redimensioned, even using different depths, like DIM A(6) before and DIM A(4,4) after in the same program. I don't know if this feature is common in other BASIC interpreters or compilers. In any case, the DTSS emulator by T. Kurtz admits this feature, and so does dib. Arrays cannot contain strings. Precedence ---------- Precedence among all the operators (not all available in default mode - see ahead), is set according to the following schema (higher to lower) level 7: () level 6: NOT level 5: ^ level 4: * / \ MOD level 3: + - level 2: < > = <= >= <> level 1: AND OR XOR level 0: EQV IMP The Original BASIC version II had a bug, causing an expression like -3^2 to yield 9 (as if ^ had a lower precedence than unary minus); version III did correct it, and -3^2 yielded correctly -9). dib, accordingly to version III, yields -9, because ^ has a higher precedence than unary minus. Screen ------ A program line is 75 characters wide and so is screen output; anything beyond the 75th character in program lines will be lost; should they fall beyond the screen limit during output, numbers will be printed on a new line, strings will be cut. Screen columns are numbered 0 to 74, and this is quite different from the underlying screen, which, in any real terminal or terminal emulation is at least 80-characters wide. This reflects the original input space of the Dartmouth BASIC, so you should never use program lines longer that 75 **in all** (line numbers included). Use an editor with characters-count like vim. I took any care to simulate the output **exactly** as in the original BASIC. Some differences arise with calculation results, because modern CPUs behave better than ancient ones... Program lines formatting ------------------------ A program line is a text line with the first character(s) being digits, and followed by a single statement with its arguments. You can put any blank space into the line, even in the middle of a statement: 10 PRINT "HELLO, WORLD!" 10 PRINT "HELLO, WORLD!" 10PR INT"HELLO, WORLD!" 10 P R I N T "HELLO, WORLD!" Previous lines are all equivalent, since all spaces/tabs are discarded during the line processing (of course, not for spaces/tabs into strings!). This said, you can format your listing to make it more readable, like: 10 FOR I=1 TO 10 20 PRINT I; 30 FOR J=1 TO I 40 PRINT "-->";I*J; 50 NEXT J 60 PRINT 70 NEXT I 80 END without any risk of misinterpretation. If you want to use an editor with syntax coloring for BASIC, or use vim with the syntax file dib.vim, though - see par. 3.8 - take care to write all statements with consecutive letters, in order to achieve the colored syntax. PRINT will be colored, PR INT will not (but will work). Moreover, if you want to run your listings under different BASICs, be careful: they may not recognize broken statements. I don't know if the original Dartmouth BASIC could accept broken statements like PR INT instead of PRINT; dib does, anyway. Program lines in a source file have not to be ordered: dib orders lines internally while loading the source. But remember that an unordered source file is also unreadable. Program lines may also be: - void lines (or lines composed by spaces, tabs and blanks), which are simply discarded; - lines with a a line number only, which delete (if present) the stored line with that very line number; in fact, in case of two (or more) lines with the same line number, only the latter is maintained; you can use this trick to do some debugging; simply rewrite at the bottom of the file the lines to be substituted without deleting them really. Use a line number alone to temporarily disable a line. - lines beginning with '#'; they are discarded too, to enable some BASIC scripting; simply copy the following line as the first line in the BASIC source file (this is not an original Dartmouth BASIC feature, of course), whose name, for this example, is : #!/bin/sh dib Put all the options you want. Then type from console: $ chmod +x and from now on you will have a sort of executable in BASIC. Capitals -------- All statements must be written in capitals; PRINT and print are not the same, the second raising an error, but dib, differently than the original BASIC, will gently accept lower letters into strings. The following will behave as expected: 10 PRINT "UPPER LETTERS" 20 PRINT "lower letters" There is even a further note, here. I don't do any check about lower or upper letters for variables, and the variables memory space of dib is enough for all. So A and a are two distinct variables, A(1,1) and a(1,1) are two distinct arrays elements, FNA and FNa are two distinct functions! Take this note with care, I) because this behavior differs from the original BASIC; II) because it may make your listing incompatible for other BASIC interpreters and compilers; this said, you can count on twice the variables number of the original BASIC, twice the number of arrays, twice the number of functions... just in case you need it! Preparsing ---------- As said, dib is an interpreter, not a compiler. Nonetheless, some commands are preparsed before execution: - END statements are checked in default mode for the following conditions: there must be only one END and it must be the last statement in the code; if it's not so, an error will be raised and the program won't be executed. In extended mode, no check is done for END, neither for being unique nor for being the last. - DATA statements are parsed to gather all the data information. Data are sequentially stored into a vector, and READ proceeds reading it from start. RESTORE resets vector pointer to the first element. Thus, during execution, DATA is a statement without effect, and is simply discarded. - DEF FN structures are parsed to gather all functions and all the variables that are used as arguments. Successive calls to the DEF FN function force a parsing of the function expression after instantiating process variables. Thus, during execution, DEF is a statement without effect, and is simply discarded. All errors that have some link with END, DATA or DEF occur even before the first program line is seen by dib. Remarks ------- The syntax that must be observed, apart from inner spaces, is simple, as in the 1964 manual, and may be condensed into this terse sentence: one statement per line The colon to divide multiple instructions on one line is NOT permitted, and this reflects exactly the Dartmouth BASIC original philosophy (this is true for default mode, while extended features permit a limited use of multiple instructions for assignments). Errors in statements, in writing numbers, in functions, in relations and many other syntax errors are exposed ahead. Finally, I like the motto at page 21 of the 1964 manual, here reported: TYPING IS NO SUBSTITUTE FOR THINKING Many programmers (I'm the first) should learn from this. 2.4 DEFAULT FEATURES ---------------- Here you will find the list of all dib's default statements and features: Available statements and specs ----------------------------- - PRINT display strings enclosed into double quotes, or expression built up from numbers, variables and operators; arguments may be followed by comma or semicolon; PRINT accepts even the classic string/value without comma or semicolon) - FOR..TO..STEP/NEXT execute cycles with a depth of 26 levels (the original basic admitted, for version II, 26 FOR cycles in total); NEXT must be followed by the variable name. - IF..THEN (followed by a valid address) executes jumps to a specific address if condition after IF is true. - GOTO jumps to any legal address (jumping out of a FOR cycle with GOTO or IF/THEN causes a cycle break); of course, GO TO is accepted. - GOSUB/RETURN (one level depth) jumps to a subroutine and get back. - LET (required) for single assignments. - END as the last statement, which is required. - INPUT enabled for multiple vars input, but unable to print input strings (e.g. INPUT "Enter a number";N won't work). - DATA/READ/RESTORE (only for numbers), with a maximum of 300 values - REM for comments; of course, REMARK is accepted; the apostrophe as a comment in the middle of the line is available - DEFFN to define a function with one argument (e.g. DEF FNX(A)=...). - PAGE to clear terminal and simulate a new printing page. - STOP which acts as END but may be repeated anywhere. - DIM with one or two dimensions arrays, with A..Z names (A0..Z9 names as array identifiers are not available). Notes: - Line numbers range is 1-99999 - Operators are the classic fab-four (*/+-) plus powering (^) - Relational operators are the classic six (= <> <= >= < >) - A strictly correct syntax is necessary for the parser to work; so (and this is not bad at all) no freedom is left in leaving behind closing parentheses; no doubt: this enhances clarity and eases corrections. - The powering operator may be followed by unary operators - and + (e.g. 12^-1E-2 or 3.2^+4.2 or A^-E1 are allowed); in any case, for a better reading, you may enclose exponent into parenthesis. - DIM A(N) dimensions a unidimensional array, which is by default a vertical array; this easies calculations of matrices by vectors; if you ever want to dimension a N-elements horizontal array, do it through DIM A(0,N-1) with base index set to 0 or DIM A(1,N) with base index set to 1; notice though that DIM A(N) dimensions a vector, while DIM A(0,N) is not a vector but a special case of a matrix. You can mix their use in any type of calculation, anyway. - Variables list in INPUT may be separated by commas or semicolons, and even mixed up (e.g. INPUT A,B,C or INPUT A;B,C). Available functions and specs ----------------------------- - ABS - ATN - COS - EXP (exponential) - INT (integer part) - LOG (neperian base) - RND (with dummy parameter required between parentheses) - SGN - SIN - SQR - TAN Notes: - The trigonometric functions work in radians mode only. Available MAT statements and specs ---------------------------------- - MAT A=B+C, MAT A=B-C, MAT A=B*C (where the lvalue cannot occur after the '=' sign, e.g. MAT A=B*A is not accepted) - MAT ZER - MAT CON - MAT TRN - MAT INV - MAT IDN - MAT PRINT - MAT INPUT (this statement belongs to version IV, to be honest) - MAT READ - MAT A=(k)*B (where the lvalue cannot occur after the '=' sign and k must be enclosed into parenthesis; k may be any valid expression fitting the line). Notes: - A0..Z9 variables cannot be used into matrices - All matrices and vectors must have been declared with DIM, even if smaller in dimension than 10 in either side; this is the restriction n° 1 presented at page 51 of the October 1964 manual for the II edition: "A matrix in a MAT instruction must have had a DIM declared", and I believe this has not changed in the III edition of 1966. The restriction n° 2: "While the same matrix may appear in a MAT statement and in an arithmetic statement, it must occur for the first time in a MAT statement") is not observed by dib. - MAT A=B is not available. Use MAT A=(1)*B in its place. - MAT A=-B is not available; in case you need such an operation, do it as MAT A=(-1)*B. - MAT READ, ZER, CON, IDN may redefine arrays (which, if greater in dimension than 10 in either side, must have already been instantiated with DIM), but only to reduce the array size in either side. - MAT TRN transposes argument matrix, and may be used also with vectors; - MAT INV sets a system var, named DET, which contains the determinant; DET must not be called before a MAT INV, and if it contains zero after an inversion, the matrix is singular. DET value retains its value until next MAT INV statement (it will be replaced by next determinant value) or end of program. - MAT INPUT sets a system var, named NUM, which contains the number of input values (which may differ from the vector/matrix global number of elements); NUM may be called anytime, but it's meaningless if called before a MAT INPUT (i.e. it's null). Besides, if you use the compact form MAT INPUT A,B,C to input values for matrices A, B and C, at the end of the input process, NUM will refer to the last matrix (C here). So, if you input a bunch of numbers to fill A and partly B, NUM will be set to 0, because C received no values. If you need to check NUM for every matrix input, set a MAT INPUT for each matrix. - As a means to understand how good the inversion of a matrix is, multiply the original matrix by its inverse; the closer are diagonal elements to 1 and the closer are all other elements to zero, the better is the inversion; in particular, I observed that if elements that should be zero are in the order of magnitude from 1E-3 to 1E-6, the inversion is not much accurate, but in most cases satisfactory. If the order of magnitude is smaller than 1E-7, the result is good. If order of magnitude is even smaller than 1E-10, no better result can be achieved by dib. - As a final remark, I observe with pride that my inversion algorithm can solve what Valentin Albillo calls "Mean Matrices" (ill-conditioned and unstable matrices that the HP-71B pocket computer cannot completely resolve). See [8]. 2.5 EXTENDED FEATURES ----------------- By invoking dib with the -x option, a number of BASIC extensions are enabled; these extensions want to emulate further versions of the Dartmouth BASIC, but without any specific reference (in particular, strings are not enabled, in this dib's version, while they were in version IV of the Dartmouth BASIC). The extended features are summarized here: Available statements extensions and specs ----------------------------------------- - DIM now allows the dimensioning of arrays with A0..Z9 names - IF..GOTO with the same behavior of IF/THEN (followed by an address) - IF..THEN may be followed by some assignment (with or without LET); multiple assignments must be separated by comma, semicolon or colon, as in the following examples: 10 IF A = 0 THEN A=4;B=6,C=24 10 IF A = 0 THEN A=4,B=6:C=24 - IF..THEN GOTO is admitted - GOSUB/RETURN with an increased level depth (80 by default) - END is not required - LET is not required (even after THEN), and multiple assignments may be done separated by commas or colons or semicolons, as in 10 LET A=3,B=5;C=1 10 A=3: B=5 : C=1 - INPUT may accept a string before the variable list, and followed by comma, semicolon or directly by the list (e.g. INPUT "VALUES";A,B or INPUT "VALUE",A,B or INPUT "VALUE"A,B) - ON..GOTO/ON..THEN both equivalent - OPTION BASE followed by a number (0 sets zero as first index, any other value sets one as first index) - RANDOMIZE - CHANGE..TO which works only from strings to arrays; the string must be explicitly enclosed into double quotes and not contained into a variable - TAB() to set next printing position; as said, columns are numbered from 0 to 74 (i.e. TAB(10) sets column 10, which is the 11th, as next printing position). TAB is a specifier of PRINT, and cannot be used alone or into a math expression. - CHR$() prints the ASCII character of the value calculated into the parenthesis; CHR$ is a specifier of PRINT and cannot be used alone or into a math expression. - RAD set radians mode. Angles in input and output are set in radians, until a successive DEG; this is the default mode. - DEG set degrees mode. Angles in input and output are set in degrees, until a subsequent RAD; Notes: - Line numbers range is now increased to 1-119880 - Some math and logical operators have been added: MOD, \ (integer division), AND, OR, XOR, EQV, IMP (they all behave as infix operators), NOT (it's a unary logical operator that precedes the expression whose truth value must be reversed. Its priority is higher than any other, so NOT A*B is equivalent to (NOT A)*B ). Other logical operators may be obtained in function of existing ones: - NXOR is equivalent to EQV - NAND is NOT AND; e.g.: A NAND B <=> NOT (A AND B) - NOR is NOT OR; e.g.: A NOR B <=> NOT (A OR B) Sometimes I see the XOR operator written as EOR in other BASICs, so this name is enabled into dib's extended features, with the same exact meaning of XOR. - The assignments after IF..THEN in extended mode may be separated by comma or colon, and even mixed; but only the colon may be compatible with other compilers and interpreters; e.g.: 10 IF A = 1 THEN E = 14, T = 45 may be not interpreted correctly by others compilers or interpreters, while 10 IF A = 1 THEN E = 14: T = 45 will be. - INPUT may be followed by a string, which will be printed before asking for variables input; after the string you can put a comma, as in INPUT "ENTER NUMBERS",A,B or a semicolon, as in INPUT "ENTER NUMBERS";A,B or nothing, as in INPUT "ENTER NUMBERS"A,B - CHR$() followed by comma/semicolon and by something else behaves like a normal output of PRINT; if, however, CHR$() is followed by another CHR$, or by comma/semicolon and nothing else, no advancing in the printing position is done, so that CHR$() may be used to build strings. If directly followed by nothing, a Carriage Return will be printed. Available functions extensions and specs ---------------------------------------- - ACS - ACSH - ASC - ASN - ASNH - ATNH - CNORM(A) yields the column norm of matrix A - COSH - COT - DET(A) yields the determinant of argument square matrix A - DOT(A,B) yields the dot product (scalar) between two unidimensional vectors - FIX(A,B) yields number A with B decimals (retaining the sign) - FNORM(A) yields the Frobenius norm of matrix A (a.k.a. Euclidian norm) - FRAC(A) yields the factional part of number A (retaining the sign) - MAX(A,B,...) and MIN(A,B,...) return max/min value from a series - GAMMA - PI returns the Greek pi value (3.14159...) - RND now does not require an argument - RNORM(A) yields the row norm of matrix A - SINH - SPC - TANH Notes: - ASC print the number equivalent to the ASCII character of the first character of the string argument, enclosed or not into parenthesis, i.e. the following lines yield the same value (65): 10 PRINT ASC("ABBA") 20 PRINT ASC(ABBA) The double quotes themselves cannot be used, since dib doesn't recognize any escape character. But if you remember that their ASCII value is 34, you can use it "as is", and print double quotes with CHR$(34). Of course, any character into parenthesis may fit: 30 PRINT ASC(%) is a valid and working statement. - FNORM yields the Frobenius norm, which is the square root of the sum of the squares of all the elements of the argument matrix - RNORM is the row norm, which is the largest sum of the absolute values of the elements in each row of the argument matrix - CNORM is the column norm, which is the largest sum of the absolute values of the elements in each column of the argument matrix - for FNORM, RNORM and CNORM, argument matrix is not required to be square, and also the norm of unidimensional vectors will be calculated. - DET(A) and DET are two different entities; in effect, DET(A) is a function, while DET is a variable. DET holds the determinant after a MAT INV(A) or a DET(A) is performed, and may be used anywhere until a new MAT INV(A) or DET(A) is done. DET(A) recalculates the determinant of the argument matrix regardless of the existence of DET, and with no check about the fact an inversion has been done. In any case, after DET(A), DET is available, because dib performs an implicit inversion to test for determinant existence while calculating it. - DOT(A,B) takes two vectors (a.k.a. lists) as arguments; these vectors may be unidimensional vectors dimensioned with DIM A(N), or unidimensional vectors dimensioned with DIM A(N,B) or DIM (B,N), where B is the OPTION BASE, 0 or 1; the latter may be considered vectors here, for the purpose of the DOT product, but in effect they are degenerated matrices, built up by, respectively one row or one column only. - FIX(N,D) trims number N to D decimals; the trimming is done on the real number, that is the number not in exponential form; for example, 1.23456 may be trimmed down to 0,1,2,3,4 and 5 decimals, but 1.23456E-3 (being in reality 0.00123456) may be trimmed down from 0 to 8 places; of course, positions 0,1 and 2 yield zero. 1.23456E3 (being in reality 1234.56) may be trimmed only in the positions 0,1 and 2. FIX may have no effect: for instance, FIX(1.23,5) will yield the number unchanged). - The trigonometric functions (included the standard ones) work in the mode specified by DEG or RAD. Default mode is anyway RAD. - SPC(N) prints N spaces onto the terminal; this "padding" does not interfere with the zones and minizones of the output flow; it has been inserted to offer a means to add extra spaces to your output and make it clearer (in future versions, where the semicomma separator, according to version IV and beyond, acted a bit differently making the output contiguous, the SPC function will achieve more importance). - MAX and MIN are two functions that take a variable set of arguments, separated by commas, and return the value which is max or min. If one argument only is given, the function will work, but a warning will be issued (there's no sense in calculating the MIN/MAX function from a subset of one element only!). Available MAT extensions and specs ---------------------------------- Notes: - MAT A=B is available - Variables A0..Z9 may be used as matrix names - MAT A may simultaneously occur to the left and to the right of the '=' sign in additions, subtractions, multiplications and scalar multiplications, e.g.: MAT A=B+A, MAT A=A-B, MAT A=B*A, MAT A=(k)*A, or even MAT A=A+A. If you want to use dib's extended features by default, simply set ef=1 in the file dib.h and recompile; from now on, the -x option will "turn off" extended features, rather than enabling them. 2.6 ERROR MESSAGES -------------- dib is, at present, an interpreter, not a compiler. Error treatment thus cannot be the same of a compiler. Basing on this simple fact, I had to reconsider the whole error treatment, since, while a compiler does multiple passes to compile, being one of the first the syntax check, and so being able to print a long listing of error messages, an interpreter should stop after the first error, because going on would mean either instantiating not allocated variables, or calling not existing addresses, or doing useless loops, or something equally bad. I came up to the following decisions: - set up a general error treatment system to stop at the first met error, but capable of reverting to a multiple error generator changing a flag only (use it at your risk!); - use the same error strings of the original compiler, as exposed on [1]; - use an extended set of strings, partly derived from [5], and partly conceived by me, where the original compiler lacked proper messages, or to expand error information to some extent These decisions forced me to recalibrate errors, discerning which one could safely let the program flow and which one had to be considered definitely a stopper. In the following paragraphs, errors recognized by dib and their own stop-code are reported (yes/no means that things are different with extended features enabled). If invoked with option -c, dib won't stop after meeting many errors (not all!), and will continue until a definitely bad thing has happened, writing in the meantime all the detected error messages. Errors which are considered dangerous for the computer memory, or which prevent dib from going on, will immediately stop the interpretation. If invoked with option -l dib will print on standard output the complete list of error codes and their messages. 2.6.1 STANDARD ERROR MESSAGES ----------------------- Standard messages are exactly the same of the original 1964 Dartmouth BASIC, printed both in default and in extended mode. In the following, "stopper" is an error big enough to prevent dib from going on. 0. DIMENSION TOO LARGE [NOT USED] (stopper: no) It occurred in Dartmouth BASIC when the size of an array was too large for the available storage. In practice, this cannot be replicated in dib, because the available memory is predetermined in dib.h, and can be expanded at need (and of course, depending on your system memory). 1. ILLEGAL CONSTANT (stopper: no) It occurs when there's an incorrect form in a number: - more than 9 digits; - other than [+-.0123456789E] in a number. The first condition cannot be observed by dib, which makes use of the strtod() C function, which has higher capabilities than Dartmouth BASIC's original parser. In practice, you'll rarely meet this error, because strtod() is very very clever. 2. ILLEGAL FORMULA (stopper: no) It occurs in case of: - missing (closing) parentheses; - illegal variable names; - missing multiplication operators (implicit multiplication is forbidden); - illegal numbers (in the original Dartmouth System it might not refer to the preceding error 1; probably it occurred during execution in case of overflow; if it's so, I cannot replicate it, due to the way gcc treats overflow). 3. ILLEGAL RELATION [NOT USED] (stopper: no) It occurs when there's not a valid relational expression between IF and THEN; There are some problems in catching this error for dib, because the parser always interpret as wrong numbers what it cannot understand. For example, the following code fragment: 10 PRINT 3<<4 20 IF A=>6 THEN 10 causes dib to emit the ILLEGAL CONSTANT error message at lines 10 and 20, because it interprets the first as 3 < (<4), and <4 is an illegal constant, and the second as A = (>6), and >6 is another illegal constant. So this error message is never issued. 4. ILLEGAL LINE NUMBER (stopper: yes) It occurs when: - the line number is not available or obtainable - the line number is greater than 99999 The second is detected as a superimposed limitation, because the effective memory size may be increased at pleasure for both (to a certain extent); in any case, the limitation is not considered if the extended features are enabled, but the effective increment is low: the limit is set to 109890 (=110x999), of which only the first 99999 are available in standard mode. 5. ILLEGAL INSTRUCTION (stopper: no) It occurs when there's some illegal instruction (not a valid BASIC statement) after the line number or in a formula or in an expression. If you're familiar with Commodore BASIC, you'll remember the ubiquitous ?SYNTAX ERROR; it's the exact correspondent. 6. ILLEGAL VARIABLE (stopper: no) It occurs when an illegal variable is detected (for instance, a two-letters variable name has been used, like AB). 7. INCORRECT FORMAT (stopper: no) It occurs when a wrong statement has been written in FOR..NEXT..STEP or IF..THEN structures. 8. END IS NOT LAST (stopper: yes/no) It occurs when: - END is not in the last line; - there's more than one END statement. Both errors are not highlighted if the extended features are enabled. 9. NO END INSTRUCTION (stopper: yes/no) Self explanatory. Not highlighted if the extended features are enabled. 10. NO DATA (stopper: no) It occurs when: - there's a READ without DATA. - a RESTORE is called without DATA statements. It's perfectly legal having a DATA with no READ/RESTORE. 11. UNDEFINED FUNCTION (stopper: no) It occurs when FNX is called without defining DEF FNX first. A DEF FNX definition may appear anywhere (it's caught before execution), but it *must* appear somewhere, in order for FNX to find what to calculate. 12. UNDEFINED NUMBER (stopper: yes) It occurs when GOSUB, GOTO or THEN are given a non existent destination line number. 13. PROGRAM TOO LONG [NOT USED] (stopper: no) In Dartmouth BASIC, at least first versions, there was a limited number of program lines which were available. When a program reached that length, this error message appeared, maybe in conjunction with error 19 (see ahead). dib uses a huge list of pointers to string lines, whose index is the correspondent line number, so this error is meaningless and never issued. 14. TOO MUCH DATA (stopper: yes) It occurs when there are more values for DATA than those available (this limit is 300 for standard mode, and 999 for extended mode. 15. TOO MANY LABELS [NOT USED] (stopper: no) It occurred in Dartmouth BASIC when there were too many strings in the program (due to memory limitations). I cannot use it, I don't want to use it! 16. TOO MANY LOOPS (stopper: yes) It occurs when there are too nested FOR..NEXT loops than those available (this limit is set to 26). Of course, you can use even thousands of FOR..NEXT loops, if they are not nested! 17. NOT MATCH WITH FOR (stopper: no) It occurs when: - there's a NEXT with a different variable than that used within FOR - there's a wrong NEXT nesting (e.g. FOR A, FOR B, NEXT A, NEXT B) 18. FOR WITHOUT NEXT (stopper: no) The program ends and no NEXT has been found. 19. CUT PROGRAMS OR DIMS [NOT USED] (stopper: no) This error (which looks rather a warning) has some meaning only with tiny resources. Used in Dartmouth BASIC and not in dib. 20. SUBSCRIPT ERROR (stopper: yes) A non existent array index has been called. It may even refer to differences in a DIM declaration or peculiar usages with MAT statements. 21. ILLEGAL RETURN (stopper: no) It occurs when a RETURN not related to any GOSUB is found. 2.6.2 EXTENDED ERROR WARNINGS ----------------------- The following warnings are meant to report odd situations, and don't stop the program flow; they don't appear in the original 1964 BASIC manual, but I reputed them meaningful in a programming environment. Most of them are retrieved from the compiler assembler source, some from the DTSS simulator by T. Kurtz, and some have been invented by me. None of them is a stopper. Numbers not addressed are unused, at present. 22. OUT OF DATA It occurs when READ cannot read DATA values anymore. This is different from the NO DATA error message: the latter means that no data has been found (this may mean no DATA statement at all), while the former means that all data have been read and there's nothing left. As stated at page 7 of the 1964 manual, this causes the program to stop, with no peculiar message. So I enable this (non-stopper) warning only in extended mode. 23. SQUARE ROOT OF NEGATIVE NUMBER 24. LOG OF NEGATIVE NUMBER 25. LOG OF ZERO 26. ABSOLUTE VALUE RAISED TO POWER 27. DIVISION BY ZERO These warnings are shown when you execute an illegal math operation; things are 'adjusted' and the program flow is not interrupted. When I say 'adjusted' I mean: - absolute value of a negative number is taken before performing a square root - the logarithm of zero or a negative number returns the lower value MINFF - a negative real cannot be raised to power, so its absolute value is taken - a division by zero returns the dividend (that is, it's not executed) This behavior reflects the original Dartmouth BASIC one. 30. OVERFLOW 31. UNDERFLOW The first warning appears when a number greater than INFF (or lower than MINFF) is met, either as itself or as a result of a math operation. The second appears when the absolute value of a number is lower than ZERO (but not zero), that is the lower limit of this emulator, either as itself or as a result of a math operation. I said "as a result of a math operation"; to this, I must add that I let the CPU perform all the intermediate calculations, so it's occasionally possible that these warnings don't get printed; for example, if you multiply 1E50*1E50*1E-50 in an expression, the first intermediate result is surely an overflow for dib, but not for a modern CPU; then, when next operation returns a value not overflowing dib's capacity, no warning is issued while evaluating this final result. 32. ZERO TO A NEGATIVE POWER 33. ZERO TO THE ZERO POWER The first warning appears when you try to calculate 0 to the power of a negative number, and the result is set to INFF (which tends to simulate 1/(0^N) or (1/0)^N, with 'N' positive, both leading to infinite). The second appears when both base and exponent are zero, and the result is set to 1 (because the function x^x approaches 1 as x approaches 0 from the right - see [10]). 34. GOSUBS NESTED TOO DEEPLY This warning appears when you go past the GOSUB..RETURN limit for inner subroutines; as default, you cannot perform a GOSUB into another GOSUB; from the Oct. 1964 manual, page 43: "The user must be very careful not to write a program in which a GOSUB appears inside a subroutine which itself is entered via a GOSUB; it just won't work." In extended mode, this limit is increased to 80, but should you go past this limit, the message appears the same. I guess, anyway, you'll NEVER go past 80 levels of GOSUBs! 35. ARRAY INDEX MUST BE GREATER THAN ZERO This warning occurs in case you use index 0 in dimensioning arrays while option base is set to 1; in this case dib prints the usual "SUBSCRIPT ERROR" message plus this warning before exiting. 36. NO MATRIX INVERSION DONE YET Self explanatory. The determinant calculated after this warning (e.g. before a matrix inversion) is meaningless. 37. IGNORING ONE-ELEMENT LIST OR TABLE If you dimension a one-element array (vector or matrix) with option base 0, using DIM A(0) or DIM A(0,0), the interpreter won't see this as a matrix dimensioning, and will set an implicit 10 elements or 10x10 elements array the first time you use a reference to the element; this happens only with option base 0 and you won't lose the object: only be conscious you have a whole array, not just a one-element array. You'll never see this warning with option base 1 if you try do dimension a one-element array with DIM A(1) or DIM A(1,1). 38. ASIN OR ACOS ARGUMENT MUST BE BETWEEN 1 AND -1 39. ACSH ARGUMENT MUST BE GREATER THAN 1 40. COTANGENT OF ZERO These messages catch the violation of the relative math functions domain, without stopping program flow. In case of violation, the yielded result is always zero except for error 40, which yields (of course) INFF. These messages appear only in extended mode, since hyperbolic functions are available only in extended mode. 41. INVERSION OF A SINGULAR MATRIX IS NOT POSSIBLE This warning appears when either the Gauss factorization is not possible, because the matrix is singular, or the determinant is null, again because the matrix is singular. In either case, the determinant is null and the message warns the programmer in order to get rid of the result matrix values. 2.6.3 SYSTEM MESSAGES --------------- Sometimes, things go in such way dib cannot manage them. In such cases, errors are printed in lower letters, preceded by the identifier "dib:", and the program inevitably stops. Here's a list of all the system errors: dib: out of memory for arrays. dib: out of memory for DEF. dib: file not found. dib: unable to close file. dib: line <> is beyond domain. dib: out of memory for line dib: cannot get a valid starting line. dib: -<> is an illegal option. dib: missing file name. dib: out of memory for ultimate END. These error messages are auto-explicative; the <> matches with a value which is calculated or retrieved during execution, and incorporated into the message. You're likely to never see last system error message, unless you're OS has a very very tiny memory. 2.7 THE EXAMPLES ------------ In the package there are four directories of examples: - the directory named 1964/ gathers all the examples featured in the 1964 manual for version II of the Dartmouth BASIC. They are named according to the page number in which they appear. The output of those programs has served as target for refining the dib's PRINT statement. They must be run safely with no options. - the directory named OWN/ gathers all the specific examples I created for dib; the subdirectory EXTEND/ contains examples for the extended version only. - the directory MATRIX/ contains various examples of matrix calculations; the subdirectory EXTEND/ contains examples for the extended version only. - the directory GOTTFR/ gathers all the example of the 1st edition of [3] which could be applied to dib with the -b option, to set option base to 1 (the Pittsburgh machine on which these examples ran used a consistent index for arrays starting from 1); the subdirectory EXTEND/ contains examples for the extended version only. 2.8 THE vim 'dib' SYNTAX FILE ------------------------- In the package you will find the 'dib.vim' file. If you don't use vim, well, skip this paragraph and forget the file. If you use vim as your current editor, here's some instructions for installing the dib file (only for UNIX users). 2.8.1 INSTALLING dib.vim ------------------ Locate the .vim directory under your $HOME. Add the two lines " dib (Dartmouth BASIC) au BufNewFile,BufRead *.dib setf dib to filetype.vim (and create it if it doesn't exist); now step into .vim/syntax and copy here the file dib.vim. Done. 2.8.2 MAPPING THE DIB SYNTAX ---------------------- Of course, you may want to use vim on files created with deer, so the extension is not present. In this case, I map the dib syntax within the vim/gvim resource file (for me $HOME/.gvimrc), adding the following line: :map :set syn=dib Of course you can map any key you want. From now on, load the file and hit F2: the colored syntax will activate. 3. CONCLUSIONS ----------- In the end, there are some people I want to thank, because their work made my job easier (or even possible). The first one is Diomidis Spinellis, the author of dds_basic, the program which gave me the idea and offered me a frame on which basing my code. I learned a lot from his programming style, which is fine, essential, smart. The second one is professor Tao Pang, from UNLV (University of Nevada, Las Vegas), for the book "An Introduction to Computational Physics - 2nd edition", Cambridge ed., 2006, a very useful manual for implementing a lot of scientific and mathematical routines and functions. I thank him again because he made available most of its software through the Internet, and indeed the first implementation of matinvert() was based on his elgs() and migs() functions, before making up my mind and implementing my own. The third one is Jack W. Crenshaw, the author of "Math Toolkit for real-time programming", CPM Books, 2000, an invaluable mine of math tools, humor, style; he's a man with a vivid intelligence, capable of getting into the harder algorithm and turn it into a clear and easy tool. Every programmer should read this book. And figure out: I bought it by chance! Last one is my wife Anna, who supported my absence while I was hidden in my room trying to produce some working code; she complained, from time to time, but she loves me enough to stand it... *** *** I cannot leave without remembering with love professor Kemeny (in memory) and professor Kurtz, who created the BASIC programming language many years ago, an easy and lightweight language, suitable for math and financial subjects, which guaranteed me an entry point in computer science. Thanks and thanks again. *** *** Finally, I propose this new acronym for BASIC: Broad Analysis with Simple and Intuitive Coding I hope you like dib. It's GPL: Enjoy! 4. BIBLIOGRAPHY ------------ The following documents and references played an important role during the design and the coding of dib: [1] "Dartmouth BASIC manual" for version II, October 1964, available as a pdf file at http://www.bitsavers.org/pdf/dartmouth/BASIC_Oct64.pdf [2] "BASIC Sessions", by Thomas E. Kurtz, chapter XI of the book "History of programming languages", about the original BASIC environment, 1977 ca, available as a pdf file of a typewriter transcript (titled "BASIC") at http://delivery.acm.org/10.1145/810000/808376/p103-kurtz.pdf?key1=808376&key2=4039224611&coll=&dl=ACM&CFID=15151515&CFTOKEN=6184618 A pdf file of the chapter XI of the issued volume (which contains the same text) may be obtained through a free subscription at the acm.org portal. [3] "Programming with BASIC", by Byron S. Gottfried, edition 1, 1975 (Italian version, as "Programmare in BASIC", Schaum 1982). [4] "Commodore 64 C= - Reference Guide for the Programmer, 1983 (Italian version, as "Guida di riferimento per il programmatore"), Commodore edition. [5] Listing of the source code for version II of the Dartmouth BASIC compiler available as a pdf file at http://www.dtss.org/scans/BASIC/BASIC%20Compiler.pdf [6] News about John Kemeny may be found at http://cis-alumni.org/JKemeney.html [7] News about Thomas Kurtz may be found at http://cis-alumni.org/TKurtz.html [8] "Mean Matrices", an article by Valentin Albillo on ill-conditioned matrices is available as a pdf file at http://membres.lycos.fr/albillo/calc/pdf/DatafileVA014.pdf [9] "To Potential ALGOL Users", Sept. 29, 1964, a note to Dartmouth ALGOL users by Stephen J, Garland, revised by D. W. Scott March 3, 1965, available as a pdf file at http://bitsavers.vt100.net/pdf/dartmouth/ALGOL_Sep64.pdf [10] Su, Francis E., et al. "Zero to the Zero Power." Mudd Math Fun Facts. http://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml where you can find an explanation to the fact that zero to the zero power is 1. Check also http://mathforum.org/dr.math/faq/faq.0.to.0.power.html where it's stated: "Consensus has recently been built around setting the value of 0^0 = 1". [11] The BASIC entry in http://www.math.bas.bg/~bantchev/place/basic.html states that the Original BASIC didn't treat boolean values, so that it's conceivable that a phrase like "IF A THEN" would issue an error in Dartmouth BASIC. *** *** (written with gvim)