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

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