/* Copyright: (c) 1997-2003 James A.D.W. Anderson. All rights reserved. > File: $useperspex/lib/transrational.p > Release: Persepx version 1, Pop11. > Purpose: Provides transrational numbers as in the following paper. > Extends the definition of sign, parity, and absolute value to > strictly transrational numbers. > Documentation: http://www.bookofparagon.btinternet.co.uk/Mathematics/SPIE.2002.Exact.pdf > Comments "EQN N" refer to equation number N in the above paper. > Related Files: none. > Note: Pop11's built in, arithmetical procedures do a great > deal of type checking, so little extra checking is > needed here. */ ;;; Compiler settings for this file. compile_mode :pop11 +strict; section $-library => transrational nullity infinity constransrational desttransrational numeratortransrational denominatortransrational isstrictlytransrational istransrational negatetransrational signtransrational paritytransrational abstransrational |- ||+ ||- |/ ||* ||/ ||> ||>= ||= ||/= ||< ||<= ; ;;; Declare existance of library for 'uses'. vars transrational = true; section transrational => nullity infinity constransrational desttransrational numeratortransrational denominatortransrational isstrictlytransrational istransrational negatetransrational signtransrational paritytransrational abstransrational |- ||+ ||- |/ ||* ||/ ||> ||>= ||= ||/= ||< ||<= ; /*********************************************************************** * Constants * ***********************************************************************/ ;;; EQN 3: constants. constant nullity = consword('0_/0'), infinity = consword('1_/0'); /*********************************************************************** * Constructor, Destructor and Recogniser * ***********************************************************************/ ;;; Return a transrational number given the numerator, n, and ;;; denominator, d. define constransrational(n, d); lvars n, d; unless isintegral(n) then mishap('INTEGER NEEDED', [^n]) endunless; unless isintegral(d) then mishap('INTEGER NEEDED', [^d]) endunless; if d = 0 then if n = 0 then nullity else infinity endif; else n/d endif; enddefine; ;;; desttransrational(ratio) -> (n,d) define desttransrational(ratio); lvars ratio; if ratio == nullity then 0,0 elseif ratio == infinity then 1, 0 else destratio(ratio) endif; enddefine; define numeratortransrational(ratio) -> n; lvars n, d, ratio; desttransrational(ratio) -> (n,d); enddefine; define denominatortransrational(ratio) -> d; lvars n, d, ratio; desttransrational(ratio) -> (n,d); enddefine; ;;; EQN 3: return true if num is strictly transrational and false otherwise. define isstrictlytransrational(num); lvars num; num == nullity or num == infinity enddefine; ;;; EQN 3: return true if num is transrational and false otherwise. define istransrational(num); lvars num; isrational(num) or isstrictlytransrational(num) enddefine; /*********************************************************************** * Arithmetic Procedures * ***********************************************************************/ ;;; EQN 6: return the negation of a transrational number. ;;; Note that strictly transrational numbers are self-negative. define negatetransrational(ratio); lvars ratio; if isstrictlytransrational(ratio) then ratio elseif isrational(ratio) then negate(ratio) else mishap('TRANSRATIONAL NUMBER NEEDED', [^ratio]) endif; enddefine; ;;; Extension to definition before EQN 1: return sign of transrational ;;; number. define signtransrational(ratio); lvars ratio; if ratio == nullity then nullity else sign(numeratortransrational(ratio)) endif; enddefine; ;;; Extension to definition before EQN 1: return parity of a ;;; transrational number. define paritytransrational(ratio); lvars ratio; if ratio = 0 then 1 else signtransrational(ratio) endif; enddefine; ;;; Return absolute value of a transrational number. define abstransrational(ratio); lvars n, d, ratio; desttransrational(ratio) -> (n,d); constransrational(abs(n), d); enddefine; ;;; EQN 4: return ratio1 plus ratio2. define addtransrational(ratio1, ratio2); lvars n1, n2, d1, d2, ratio1, ratio2; desttransrational(ratio1) -> (n1,d1); desttransrational(ratio2) -> (n2,d2); constransrational(n1*d2 + n2*d1, d1*d2); enddefine; ;;; EQN 5: return ratio1 minus ratio2 . define subtracttransrational(ratio1, ratio2); lvars ratio1, ratio2; addtransrational(ratio1, negatetransrational(ratio2)); enddefine; ;;; Return the reciprocal of a transrational number. ;;; Note: zero (0/1) and infinity (1/0) are reciprocals. ;;; Note: nullity (0/0) is self-reciprocal. define reciprocaltransrational(ratio); lvars n, d, ratio; desttransrational(ratio) -> (n,d); constransrational(d, n); enddefine; ;;; EQN 7: return the product of two transrational numbers. define multiplytransrational(ratio1, ratio2); lvars n1, n2, d1, d2, ratio1, ratio2; desttransrational(ratio1) -> (n1,d1); desttransrational(ratio2) -> (n2,d2); constransrational(n1*n2, d1*d2); enddefine; ;;; Return ratio1 divided by ratio2. define dividetransrational(ratio1, ratio2); lvars ratio1, ratio2; multiplytransrational(ratio1, reciprocaltransrational(ratio2)); enddefine; /*********************************************************************** * Arithmetic Operators * ***********************************************************************/ ;;; The vertical bar "|" is chosen as a symbol meaning "ratio", beause ;;; it is shown on keyboards as a broken vertical line. This is ;;; reminiscent of the numerator and denominator in a fraction. However, ;;; on some displays and printers it prints as a vertical line. This is ;;; potentially confusable with the digit 1. It would be possible to ;;; avoid this confusion by overloading the standard operators, but this ;;; would severly reduce performance. All of the printable symbols are ;;; used in Pop11, so there is no obvious, alternative candidate to ;;; signify ratios. ;;; ;;; Note: transrational operators have the same precedence as the ;;; corresponding Pop11 operators. However, the transrational reciprocal ;;; operator |/ has no corresponding Pop11 operator and is set to a ;;; very low precedence, so that it generraly computes the reciprocal ;;; of text to its right. For example: |/ 1/3 = 3. Whereas: ;;; 1 / 1 / 3 = 1/3 define 1 |- (ratio); lvars ratio; negatetransrational(ratio); enddefine; define 5 ||+ (ratio1, ratio2); lvars ratio1, ratio2; addtransrational(ratio1, ratio2); enddefine; define 5 ||- (ratio1, ratio2); lvars ratio1, ratio2; subtracttransrational(ratio1, ratio2); enddefine; define 6 |/ (ratio); lvars ratio; reciprocaltransrational(ratio); enddefine; define 4 ||* (ratio1, ratio2); lvars ratio1, ratio2; multiplytransrational(ratio1, ratio2); enddefine; define 4 ||/ (ratio1, ratio2); lvars ratio1, ratio2; dividetransrational(ratio1, ratio2); enddefine; /*********************************************************************** * Relational Operators * ***********************************************************************/ ;;; Note: rational arithmetic obeys the triality axiom: a number can be ;;; greater than, equal to, or less than zero. But transrational ;;; arithmetic obeys the quadrality axiom - a number can be equal to ;;; nullity or else it can be: greater than, equal to, or less than ;;; zero. That is, there is one extra case to consider in transrational ;;; arithmetic. ;;; EQN 8, 9: return true if ratio1 > ratio2, otherwise return false. define greatertransrational(ratio1, ratio2); lvars ratio1, ratio2; ;;; All cases involving nullity. if ratio1 == nullity or ratio2 == nullity then return(false) endif; ;;; All cases involving infinity. if ratio1 == infinity and ratio2 == infinity then return(false) endif; if ratio1 == infinity then return(true) endif; if ratio2 == infinity then return(false) endif; ;;; All rational cases. ratio1 - ratio2 > 0 enddefine; define 6 ||> (ratio1, ratio2); lvars ratio1, ratio2; greatertransrational(ratio1, ratio2); enddefine; define 6 ||>= (ratio1, ratio2); lvars ratio1, ratio2; ratio1 ||> ratio2 or ratio1 = ratio2; enddefine; define 7 ||= (ratio1, ratio2); lvars ratio1, ratio2; ratio1 = ratio2 enddefine; define 7 ||/= (ratio1, ratio2); lvars ratio1, ratio2; ratio1 /= ratio2; enddefine; define 6 ||< (ratio1, ratio2); lvars ratio1, ratio2; ratio2 ||> ratio1; enddefine; define 6 ||<= (ratio1, ratio2); lvars ratio1, ratio2; ratio2 ||>= ratio1; enddefine; section_cancel(current_section); endsection; endsection;