home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / math / ultra101 / ultracod.inc < prev    next >
Encoding:
Text File  |  1992-03-26  |  12.0 KB  |  432 lines

  1. ; This file is included in after a header file which defines
  2. ; language dependent elements. (see ultra.doc for details)
  3. ;
  4. ; Specifically it expects the following items to be defined:
  5. ;
  6. ;       RinitProcStart  FillProcStart   EnterProcedure
  7. ;       RinitProcEnd    FillProcEnd     ExitProcedure
  8. ;       DwordFn         WordFn          ByteFn
  9. ;       RealFn          DoubleFn
  10. ;
  11. ;       The DATA and STACK segments.
  12. ;
  13.  
  14. cong  macro     ; Congruential generator ==============================
  15. ;
  16. ; argument in dx:ax
  17. ; result   in dx:ax = low32bits of 69069 * arg
  18. ; clobbered   bx
  19. ;
  20. ; We need the lower 32 bits of 69069 * dx:ax
  21. ; Since we only have 16 bit multiplys with 32 bit answers,
  22. ; we use long multiplication. Let (a,b) represent a*2^16 + b.
  23. ;
  24. ;            69069 =                      (  1, 3533)
  25. ;            dx:ax =                 x    ( hi, lo  )
  26. ;                                 -------------------
  27. ;                     3533 * lo =         ( a1, a2  )
  28. ;                     3533 * hi =     ( b1, b2 )
  29. ;                        1 * lo =     (  0, lo )
  30. ;                                 -------------------
  31. ;            low 32 bits of answer = (a1+b2+lo, a2  )         
  32. ;
  33.       mov  bx,ax
  34.       mov  ax,3533
  35.       mul  dx                     ; dx:ax = b1,b2 = 3533*hi
  36.       xchg bx,ax
  37.       add  bx,ax                  ; bx = b2+lo;     ax = lo;
  38.       mov  dx,3533
  39.       mul  dx                     ; dx:ax = a1,a2 = 3533*lo
  40.       add  dx,bx                  ; dx = a1+b2+lo
  41.       endm
  42.  
  43. shreg macro     ; Shift register sequence =============================
  44. ;
  45. ;  argument is dx:ax
  46. ;  result   in dx:ax
  47. ;  clobbered   bx
  48. ;
  49. ;  consider the ax register as one sign bit `as' and the rest `a..r'
  50. ;  similarly decompose dx. The operation we want to do is:
  51. ;
  52. ;          x = x xor (x shr 15);
  53. ;          x = x xor (x shl 17);
  54. ;
  55. ;  Which can be shown in terms of the decomposed registers as:
  56. ;
  57. ;     x        = ds, d..r, as, a..r
  58. ;     x shr 15 =       ds, d..r  as
  59. ;                ------------------
  60. ;     x        = ds, d..r, as, a..r
  61. ;     x shl 17 = a..r   0
  62. ;                ------------------
  63. ;
  64. ;  The above operation is equivalent to:
  65. ;
  66. ;           ax = ax xor [d..r,as]
  67. ;           dx = dx xor [a..r,ds]
  68. ;
  69.       mov  bh,ah
  70.       shl  bh,1                 ; mov as into carry
  71.       mov  bx,dx
  72.       rcl  bx,1                 ; bx = [d..r,as]
  73.       pushf                     ; save carry flag (=ds)
  74.       xor  ax,bx                ; ax = ax xor bx
  75.       popf                      ; restore the carry
  76.       mov  bx,ax
  77.       rcl  bx,1                 ; bx = [a..r,ds]
  78.       xor  dx,bx                ; dx = dx xor bx
  79.       endm
  80.  
  81. RinitProcStart         ; INITIALIZE SEED ARRAY =======================
  82. ;
  83. ; On exit:
  84. ;    The x array is set using the McGill Super-Duper generator,
  85. ;    which is a mix of a congruential and shift-register sequence.
  86. ;    Flags and counters are reset.
  87. ;
  88. ; Registers Clobbered:  AX,BX,CX,DX,SI,DI.
  89. ;
  90. ; Algorithm:
  91. ;    Starting from lsm of x[0] to the msb of x[N-1], each bit is
  92. ;    formed using the sign bit of the xor of a congruential generator
  93. ;    with seed ConX and a shift register sequence with seed ShrX.
  94. ;
  95. ; Register usage
  96. ;   cx contains count for two loops
  97. ;      ch counts the outer loop (for each byte of the array x)
  98. ;      cl counts for each bit of x[i]
  99. ;   bl contains the bits until eight of them are gathered
  100. ;   es:di point to where x[i] 
  101. ;   dx:ax are used for computations
  102. ;
  103.     mov ch,N*4
  104.     mov di,offset x     ; do loop for x[0], ... , x[4*n] (bytes)
  105. nextbyte:
  106.     mov bl,0        ; 8 bits of bl are made bit by bit
  107.     mov cl,8        
  108. nextbit:    push bx                     ; compute the cong and the sh-reg
  109.         mov  ax,conglo              ; generators in place
  110.         mov  dx,conghi
  111.         cong
  112.         mov  conglo,ax
  113.         mov  conghi,dx
  114.         mov  ax,shrglo
  115.         mov  dx,shrghi
  116.         shreg
  117.         mov  shrglo,ax
  118.         mov  shrghi,dx
  119.         pop  bx 
  120.  
  121.         xor  dh,byte ptr conghi+1   ; xor the top byte of arg1 and arg2
  122.         rcl  dh,1           ; move the sign bit into the carry
  123.         rcr  bl,1           ; shift it into bl
  124.     dec cl
  125.     jnz nextbit
  126.     mov al,bl
  127.     stosb               ; Store the answer in x[i]
  128.     dec ch
  129.     jnz nextbyte
  130. ;
  131. ; reset all counters, flags etc. and return.
  132. ;
  133.     mov swbn,0
  134.     mov nbits,0
  135.     mov flags,0
  136. RinitProcEnd
  137.  
  138. FillProcStart           ; SUBTRACT-WITH-BORROW ========================
  139. ;
  140. ;  On Entry:
  141. ;     DS should point to the data segment.
  142. ;
  143. ;  On Exit:
  144. ;     The x array contains all new values computed by the
  145. ;     subtract-with-carry generator. The CARRY byte contains the
  146. ;     state of the carry flag due to the last subtraction.
  147. ;
  148. ;  Registers Clobbered: AX,BX,CX,DX,SI,DI
  149. ;
  150. ;  Algorithm:
  151. ;     The following subtractions are performed from right to left.
  152. ;     The carry propagates as though these were two long numbers,
  153. ;     with each x[i] being a `digit' in base 2^32.
  154. ;
  155. ;        x[12] ...  x[ 0]      x[36] ...  x[13]
  156. ;       -x[36] ... -x[24]     -x[23] ... -x[ 0]
  157. ;       ---------------------------------------
  158. ;        x[36] ...  x[24]      x[23] ...  x[ 0]
  159. ;
  160. ;     The x's also could be considered as pairs of base 16 digits,
  161. ;     so that x[i] is the pair y[2i+1]y[2i]. This allows us to use
  162. ;     only 16 bit subtractions with carry, perfectly suited for all
  163. ;     80x86 processors. The same idea could be extended for machines
  164. ;     with only eight bit, or even only 1 bit arithmetic.
  165. ;
  166.     mov ah,byte ptr flags   ; set carry flag to what it was the
  167.     sahf                    ; last time we exited this routine
  168.  
  169.     mov cx,24*2             ; will do first loop 48 times
  170.     mov si,offset(x)+13*4   ; set up ds:si -> x[13]
  171.     mov di,offset(x)        ; set up es:di -> x[0]
  172.  
  173. loop1:  ; On a 8086, the instructions `lodsw', `stosw' and `loop'
  174.     ; all change registers automatically as noted in parentheses
  175.  
  176.     lodsw                   ;    ax = y[i+26]     ( si = si+2 )
  177.     sbb ax,[di]             ;    ax = ax-y[i]-carry
  178.     stosw                   ;    y[i] = ax        ( di = di+2 )
  179.     loop loop1              ; loop for i=0..47    ( cx = cx-1 )
  180.  
  181.     mov cx,13*2             ; will do next loop 26 times
  182.     mov si,offset(x)        ; set up ds:si -> y[0]
  183.                 ; es:di is already set up
  184. loop2:
  185.     lodsw                   ;    ax = y[i-48]     ( si = si+2 )
  186.     sbb ax,[di]             ;    ax = ax-y[i]-carry
  187.     stosw                   ;    x[i] = ax        ( di = di+2 )
  188.     loop loop2              ; loop for i=48..73   ( cx = cx-1 )
  189.  
  190.     lahf
  191.     mov byte ptr flags,ah   ; save carry flag for next time
  192. ;
  193. ; XOR the elements of x with a congruential generator and put the
  194. ; result in swbx
  195. ;
  196.     mov  cx,N
  197.     mov  si,offset(x)
  198.     mov  di,offset(swbx)
  199.     mov  ax,conglo
  200.     mov  dx,conghi
  201. loopc:  cong
  202.     mov  bx,ax
  203.     lodsw
  204.     xor  ax,bx
  205.     stosw
  206.     lodsw
  207.     xor  ax,dx
  208.     stosw
  209.     mov  ax,bx
  210.     loop loopc
  211.     mov  conglo,ax
  212.     mov  conghi,dx
  213.  
  214. FillProcEnd
  215.  
  216. ; Random Number procedures ============================================
  217. ;
  218. ; The following procedures all rely on one table SWBX, and a count
  219. ; SWBN. The count is negative of the number of bytes remaining.
  220. ; The array SWBNEG is defined so that 
  221. ;   SWBNEG[-4N] is equivalenced to SWBX[0]
  222. ;   SWBNEG[ -1] is equivalenced to SWBX[4N-1]
  223. ; Thus SWBNEG[SWBN] is the index of the first free byte.
  224. ; In FORTRAN, you could think of it as:
  225. ;   Dimension SWBX(0:4n-3), SWBNEG(-4n:-1)
  226. ;   equivalence(SWBX,SWBNEG)
  227. ; This odd setup is so that we can test SWBN against 0, to check
  228. ; for exhausting the array, and yet still use the array entries
  229. ; in the order that they are stored in the array.
  230. ;
  231. ; All the routines first increment SWBN by the amount of bytes they
  232. ; intend to use. Then they check SWBN. If it has become positive,
  233. ; the array is to be refilled, and SWBN set to indicate 4n-nbytes.
  234. ;
  235. ; If there are enough bytes in the array, they are returned as
  236. ; the function value.
  237.  
  238. BitProc MACRO nbits
  239.   local ok
  240.   nbytes=(nbits+1) shr 3
  241.   i&nbits&bit proc
  242.     EnterProcedure
  243.     mov  bx,swbn
  244.   if nbytes eq 1
  245.     inc  bx
  246.   else
  247.     add  bx,nbytes
  248.   endif                         ; -bl is n. of bytes free after this
  249.     jle   ok                ; if bx>0, nbytes bytes are not remaining
  250.     call fillswb            ; so refill table
  251.     mov  bx,-(N*4-nbytes)   ; and set swbn to  -(N*4-nbytes)
  252.   ok:   mov  swbn,bx
  253. ENDM
  254.  
  255. EndProc MACRO nbits
  256.     ExitProcedure
  257.   i&nbits&bit endp
  258. ENDM
  259.  
  260. BitProc 32
  261.     mov  ax,swbneg[bx-4]
  262.     mov  dx,swbneg[bx-2]
  263.     DwordFn
  264. EndProc 32
  265.  
  266. BitProc 31
  267.     mov  ax,swbneg[bx-4]
  268.     mov  dx,swbneg[bx-2]
  269.     and  dh,7Fh
  270.     DwordFn
  271. EndProc 31
  272.  
  273. BitProc 16
  274.     mov  ax,swbneg[bx-2]
  275.     WordFn
  276. EndProc 16
  277.  
  278. BitProc 15
  279.     mov  ax,swbneg[bx-2]
  280.     and  ah,7Fh
  281.     WordFn
  282. EndProc 15
  283.  
  284. BitProc 8
  285.     mov  al,byte ptr swbneg[bx-1]
  286.     ByteFn
  287. EndProc 8
  288.  
  289. BitProc 7
  290.     mov  al,byte ptr swbneg[bx-1]
  291.     and  al,7Fh
  292.     ByteFn
  293. EndProc 7
  294.  
  295. i1bit proc
  296.     EnterProcedure
  297.  
  298.     dec  nbits
  299.     jge  ok02
  300.  
  301.     mov  bx,swbn
  302.     inc  bx
  303.     jle  ok01
  304.     call fillswb
  305.     mov  bx,-(N*4-1)
  306. ok01:   mov  swbn,bx
  307.  
  308.     mov  ah,byte ptr swbneg[bx-1]
  309.     mov  nbits,7
  310.     jmp  short ok03
  311.  
  312. ok02:   mov  ah,bits
  313.  
  314. ok03:   mov  al,1
  315.     and  al,ah
  316.         shr  ah,1
  317.     mov  bits,ah
  318.  
  319.     and  ax,1
  320.     ByteFn
  321.     ExitProcedure
  322. i1bit endp
  323.  
  324. uni proc
  325.     EnterProcedure
  326.  
  327.     fild scale31
  328.     mov  bx,swbn
  329.     add  bx,4
  330.     jle  uchecklead
  331.     call fillswb                     ; refill the table
  332.     mov  bx,-N*4+4
  333. uchecklead:
  334.     mov  swbn,bx             ; set the counter correctly
  335.     and  byte ptr swbneg[bx-1],07Fh  ; if leading byte is zero
  336.     jz   uprecise                    ; then increase precision
  337.                      ; else
  338.     fild dword ptr swbneg[bx-4]      ; load the 32-bit number
  339. uscale_n_exit:
  340.     fscale                           ; scale the integer by the exponent
  341.     fstp st(1)                       ; dump the exponent from the fpp
  342.     RealFn
  343.     ExitProcedure
  344.  
  345. uprecise:
  346.     mov  ax,word ptr swbneg[bx-4]
  347.     mov  shrglo,ax
  348.     mov  al,byte ptr swbneg[bx-2]
  349.     mov  byte ptr shrghi,al          ; and carry along the three lsb's.
  350. ugetleadbyte:
  351.     fisub seven                      ; decrease exponent by seven
  352.     call i8bit                       ; and get 7 new leading bytes.
  353.     and  al,07Fh
  354.     jz   ugetleadbyte
  355.     mov  byte ptr shrghi[1],al
  356.     fild shrgx
  357.     jmp  uscale_n_exit
  358. uni endp
  359.  
  360. vni proc
  361.     EnterProcedure
  362.  
  363.     fild scale31
  364.     mov  bx,swbn
  365.     add  bx,4
  366.     jle  vchecklead
  367.     call fillswb                     ; refill the table
  368.     mov  bx,-N*4+4
  369. vchecklead:
  370.     mov  swbn,bx             ; set the counter correctly
  371.     mov  al,byte ptr swbneg[bx-1]    ; if leading byte is 0 or -1
  372.     cbw
  373.     cmp  ah,al
  374.     je   uprecise                    ; then increase precision
  375.                      ; else
  376.     fild dword ptr swbneg[bx-4]      ; load the 32-bit number
  377. vscale_n_exit:
  378.     fscale                           ; scale the integer by the exponent
  379.     fstp st(1)                       ; dump the exponent from the fpp
  380.     RealFn
  381.     ExitProcedure
  382.  
  383. vprecise:
  384.     mov  ax,word ptr swbneg[bx-4]
  385.     mov  shrglo,ax
  386.     mov  al,byte ptr swbneg[bx-2]
  387.     mov  byte ptr shrghi,al          ; and carry along the three lsb's.
  388. vgetleadbyte:
  389.     fisub seven                      ; decrease exponent by seven
  390.     call i8bit                       ; and get 7 new leading bytes.
  391.     cbw
  392.     cmp  al,ah
  393.     je   vgetleadbyte
  394.     mov  byte ptr shrghi[1],al
  395.     fild shrgx
  396.     jmp  vscale_n_exit
  397. vni endp
  398.  
  399. dUVniProc MACRO nbits,name
  400.   local foundit
  401.   name proc
  402.     EnterProcedure
  403.  
  404.     fild scale63
  405.     mov  bx,swbn
  406.     add  bx,8
  407.     jle  foundit            ; check table if empty
  408.     call fillswb                ; refill table
  409.     mov  bx,-N*4+8
  410.   foundit:
  411.   if     nbits eq 63
  412.     and  byte ptr swbneg[bx-1],07Fh     ; knock off sign bit for duni
  413.   endif
  414.     fild qword ptr swbneg[bx-8] ; load the 64-bit number
  415.     mov  swbn,bx                ; set the counter correctly
  416.     fscale                      ; scale the integer by the exponent
  417.     fstp st(1)                  ; dump the exponent from the fpp
  418.     DoubleFn
  419.     ExitProcedure
  420.   name endp
  421. ENDM
  422.  
  423. dUVniProc 63,duni
  424. dUVniProc 64,dvni
  425.  
  426. swbfill proc
  427.     EnterProcedure
  428.     call fillswb
  429.     ExitProcedure
  430. swbfill endp
  431.