# fixed

#### Fixed point number package

```\ FIXED.SCR                                  hhh 12:30 02/09/97
written using LMI PC/FORTH 3.2
Heinrich Hohl, Lucent Technologies

This package facilitates the use of fixed point double length
numbers (fd). These are double length numbers containing an
implied decimal point at a known, fixed position. The following
words allow easy handling of fixed point numbers:

PLACES ................ determine position of decimal point
(FD.) FD. FD.R ........ used to display fd numbers
FIXED ................. convert any input d number to fd number
D+ D- D* D/ ........... calculate with d or fd numbers
T* T/ TU* TU/ TU// .... basic triple length number operators
D*/ DU*/ DU*// ........ scale d or fd numbers; triple length
intermediate results are used
\ load screen                                hhh 14:16 02/08/97
FORTH DEFINITIONS  DECIMAL
BSTART OVERLAY
2 ?SCREENS 1- THRU

FORTH DEFINITIONS  DECIMAL
BSTART OVERLAY
2 ?SCREENS 1- THRU

BSAVE OVERLAY FIXED
0 RETURN

\ variables                                  hhh 14:02 02/08/97
VARIABLE places \ number of digits behind decimal point

\ number input                               hhh 14:00 02/08/97
: PLACES ( n -- )  0 MAX  places ! ;
\ specify number of places behind the decimal point

: DSHIFT ( d n -- d')
DUP 0<
IF    NEGATE
0 ?DO 10 D/  LOOP
ELSE  0 ?DO 10 D*  LOOP  THEN ;
\ decimal left shift (n<0 shifts |n| digits to the right)

: FIXED ( d -- fd)
places @  DPL @ 0 MAX -  DSHIFT ;
\ convert double length number to fd considering DPL

\ formatted output                           hhh 13:58 02/08/97
: (FD.) ( fd -- addr len)
TUCK DABS
<#  places @ 0 ?DO # LOOP  ASCII . HOLD  #S  ROT SIGN  #> ;
\ convert fixed point double length number to formatted string

: FD. ( fd -- )  (FD.) TYPE SPACE ;
\ display fixed point double length number

: FD.R ( fd width -- )  >R  (FD.)  R> OVER - SPACES  TYPE ;
\ display number right justified in a field of specified width

\ extended arithmetics                           12:31 02/09/97
: UM/ ( ud u -- u')  UM/MOD NIP ;

: T* ( d v -- t)  TUCK M* >R >R UM* 0 R> R> D+ ;
: T/ ( t v -- d)  DUP >R M/MOD -ROT R> UM/ SWAP ;
\ multiply or divide signed long number by 0 <= v <= 7FFF

: TU* ( ud u -- ut)  TUCK UM* >R >R UM* 0 R> R> D+ ;
: TU/ ( ut u -- ud)  DUP >R UM/MOD -ROT R> UM/ SWAP ;
\ multiply or divide unsigned long numbers by unsigned number

: TU// ( ut ud -- u)
DUP 1+
DUP >R UM/ R> SWAP >R TU/ R> UM/ ;
\ divide ut number by ud number

\ scaling                                    hhh 14:05 02/08/97
: D*/ ( d v1 v2 -- d')  >R T* R> T/ ;
\ scale double length number d according to the unsigned
\ numbers v1 and v2 of range 0 <= v <= 7FFF: (d*v1)/v2 = d'

: DU*/ ( ud u1 u2 -- ud')  >R TU* R> TU/ ;
\ scale unsigned double length number ud according to the
\ unsigned numbers u1 and u2: (ud*u1)/u2 = ud'

: DU*// ( u ud1 ud2 -- u')  >R >R ROT TU* R> R> TU// ;
\ scale unsigned number u according to the unsigned double
\ length numbers ud1 and ud2: (u*ud1)/ud2 = u'

\ tip: avoid fussy stack operations by using basic triple
\ length arithmetic operators for scaling instead of the
\ scaling operators shown in this screen
\ excise headers                             hhh 13:33 02/08/97
EXCISE places places
EXCISE DSHIFT DSHIFT
EXCISE UM/ UM/

```