Operations with real values in Rigal ======================================= NOTE: This description presents implementation of operations with real values in Rigal in MS-DOS (Turbo-Pascal based) and UNIX (C - based) variants, starting from Rigal V.2.34 and UNIX Rigal V.4.45. Read carefully parts regarding UNIX and MS-DOS. Old such description was for MS-DOS version only. Unix description exists only starting from version 4.45. Limitations of Turbo Pascal =========================== MS-DOS Rigal is implemented via Pascal real run time library. The following sequence of characters is accepted by Pascal VAL procedure as a real number: (* space *) [ (+!-) ] (* digits1 *) [ '.' (* digit2 *) ] [ (e!E) [ (+!-) ] (* digit3 *) ] The context constraints are that: digit1+digit2<37 ( limited number of digits ) The absolute value of digits1.digits2E[-]digits3 must be in 2.9e-39 ... 1.7e38 We assume that UNIX C has no such constraints. Input real number from lexical analyzer ======================================= We call real numbers stored in Rigal memory as #FATOMs. Use built-in Rigal predicate #FATOM to recognize them. They can be read by the lexical analyzer from its input as sequences of characters that must match following grammar rule (+ digits1 +) ( '.' (* digit2 *) [ (e!E) [ (+!-) ] (* digit3 *) ] ! (e!E) [ (+!-) ] (* digit3 *) ) and it must be acceptable by procedure VAL (see above). IN MS-DOS: ========= If #FATOM is read then it is stored in 8-byte-length atom, 6 bytes are occupied by standard representation of REAL type in Pascal. In other two bytes number of digits before dot and number of digits after the dot are stored. If the input number was in exponential form then these bytes contain zeros. IN UNIX: ======= If #FATOM is read then it is stored in 8-byte-length atom, assuming that sizeof(double)=8. The information about the number of digits before the dot and number of digits after the dot are _NOT_ stored. Since standard 6 (or 8)-byte representation is stored, only 10 (13) digits are valid. Non-matching in MS-DOS scaner ============================= If the input value matches grammar and does not match "VAL rules" then atom with type #KEYWORD is produced (it is used for diagnostic purposes). Normally #FATOM is produced. Output of real numbers ====================== Statements PRINT, <<, ,<], built-in rules #IMPLODE and #EXPLODE output real numbers in "exponential" form, like the %E format in UNIX, or simple WRITE() in Pascal. Sd.ddddddddddEZdd S is space or '-' d are digits (exactly 10 digits after dot) E is character 'E' Z is '+' or '-' Real numbers in traditional operators ===================================== If you use real numbers in traditional arithmetical operators and comparisons, all #FATOMs are accepted the same way as NULL. It corresponds to 0 value. If you compare #FATOMs with '=', their internal representation (with 6 or 8 bytes long code) will be compared. Therefore, there is no sense in such operations. Ways to create #FATOM ===================== #CALL_PAS(80 S any_string) returns #FATOM if the string value matches "VAL rule". Otherwise NULL is returned. #CALL_PAS(80 I integer) returns #FATOM. Integer value can be arbitrary. Ways to get information from #FATOM =================================== ( THIS APPLIES TO MS_DOS VARIANT ONLY !) ====================================== #CALL_PAS(80 D #FATOM) returns pair (. digits_before digits_after .) for FATOM values that were entered through the lexical analyzer. If the number was entered in exponential style (with character, 'E'), value (. 0 0 .) is returned. If the value was obtained by #CALL_PAS(80..), NULL is returned. There is no other ways to create #FATOM. NOTE: If you have entered #FATOM to variable $X via lexical analyzer, you can output it with the same number of digits before and after the point (if it was not exponential style) as it was read by lexical analyser: $D:=#CALL_PAS(80 D $X); IF $D AND ($D[1]+$D[2]>0) -> $REZ:=#CALL_PAS(80 Z $X ($D[1]+$D[2]+1)*100+$D[2]) ELSIF T-> $REZ:=#CALL_PAS(80 V $X) FI; Conversions (MS-DOS VARIANT ONLY) ================================= #CALL_PAS(80 T #FATOM) returns #NUMBER - whole part of real value. If the number is not in -2147483648..2147483647 then NULL is returned. #CALL_PAS(80 Z #FATOM D*100+A) returns formatted string with the value of the real number. "A" can be positive or negative. If "A" is arbitrary NEGATIVE number then exponential form is produced in following form: Sd.dEZdd (e.g. -7.7E01) S is space or '-' Z is '-' or '+' If D>=9 then additional digits are added after the point, but not more than 10 digits. If "A" is 0 then integer value is produced, possible with '-'. If "A" is positive, it specifies number of digits after the point. Non-exponential form is produced. Zeros are appended after point if necessary. The number of digits after the point cannot be larger than 11. After all cases discussed above, if "D" is larger than the new string, RIGAL adds spaces from the left side of the string. The result string length is not less than "D". #CALL_PAS(80 R #FATOM p) - returns rounded value of real number. The number is rounded such way that digits after p-th position after the dot must be set to zeros. E.g. 23.1415 rounded at 2 nd position must be 23.140000. If p is not positive, it is accepted as 0. If absolute value of real*(10 in p-th degree) is larger than 1e37 then NULL is returned. #CALL_PAS(80 V #FATOM) - creates string from real number in form [-]d.ddddddddddESdd S is '+' or '-' Conversions (UNIX VARIANT ONLY) ================================= #CALL_PAS(80 F #FATOM FORMAT_STRING) returns formatted string with UNIX C the _arbitrary_ format (allowed in UNIX C sprintf function) you specified, for example #CALL_PAS(80 F $A 'A=%.9e'); Note, however, that this option is _not_ ported to MS-DOS. #CALL_PAS(80 Z #FATOM D*100+A) returns formatted string with the value of the real number. "A" _must_ be positive. If "A" is 0 then integer value is produced, possible with '-'. If "A" is positive, it specifies number of digits after the point. Non-exponential form is produced. Zeros are appended after point if necessary. The number of digits after the point cannot be larger than 11. After all cases discussed above, if "D" is larger than the new string, RIGAL adds spaces from the left side of the string. The result string length is not less than "D". #CALL_PAS(80 V #FATOM) returns formatted string with UNIX C %E format. Mathematical operations ======================= #CALL_PAS(80 op #FATOM #FATOM) Operations "op" can be '+','-', '*','/', '<','>', '<=','>=', '<>','=' In MS-DOS if '+' or '-' applied, absolute value of the arguments must be less than 6.2e37 otherwise NULL is returned. In MS-DOS if '*' or '-' applied, absolute value of the result must be between 1.6e-38..6.2e37 and the second argument of '/' is not 0, otherwise NULL is returned. If '<','>','<=','>=','<>','=' are applied, one of the arguments is returned to indicate 'true', NULL is returned to indicate 'false' Note that it is BAD and DANGEROUS STYLE to check the results of real arithmetic using '=' or '<>' operations, because the computer never calculates precise results. You can compare two real numbers only after some conversion, e.g. using #CALL_PAS(80 V ...). #CALL_PAS(80 Q #FATOM) returns square root if argument is not negative, NULL otherwise. #CALL_PAS(80 X #FATOM) returns exponential ( e in r-th degree) of the argument. #CALL_PAS(80 L #FATOM) returns natural logarithm if the argument is positive, otherwise NULL. Mathematical operations for UNIX only ===================================== #CALL_PAS(80 op #FATOM) where op = tSIN, tCOS, tTAN, tASIN, tACOS, tATAN. call corresponding functions from UNIX libm library. Common note about #CALL_PAS(80..). ================================= It has no run time diagnostic. If wrong types of arguments of wrong number of arguments or wrong operation name is given, NULL is returned. If #CALL_PAS(80...) produces a #FATOM, it is 6 (or 8) bytes long and it has _no_ information about the digits before and after the dot. You can learn more details about #CALL_PAS(80) from source files USE80.PAS and SERVICES.PAS in MS-DOS, usemod.c, sevice.c in UNIX C.