home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / documentation / documents / a252div < prev    next >
Internet Message Format  |  1999-04-27  |  20KB

  1. From: chughes@maths.tcd.ie (Conrad Hughes)
  2. Subject: Re: fast divide
  3. Date: 31 Oct 91 13:15:24 GMT
  4.  
  5. DEFFNdiv(A,B,C,R):LOCALA%:[OPTpass:MOVS C,A,LSR#31:RSBNE A,A,#0
  6.  :ADDS C,C,A,LSL#16:MOV A,A,LSR#16:ADDS A,B,A:SUBCC A,A,B:]
  7.   FORA%=1TO31:[OPTpass:ADCS C,C,C:ADCS A,B,A,LSL#1:SUBCC A,A,B:]NEXT
  8. [OPTpass:ADCS R,C,C:RSBCC R,R,#0:]=0
  9.  
  10. This is the BASIC assembler code to do the division.. Use it this way:
  11.  
  12. FNdiv(reg_top,reg_bot,reg_misc,reg_res)
  13.  
  14. while in the BASIC assembler.. It inlines the code. Register reg_res
  15. contains 32768*(reg_top/reg_bot); reg_bot _must_ be negative (if you
  16. don't know what sign it'll be, tack the following in at the beginning:
  17.  
  18. CMP B,#0:RSBPL B,B,#0:RSBPL A,A,#0
  19.  
  20. ...) , and reg_top can be either sign.. If you need slightly higher
  21. accuracy (I think I can increase the accuracy by half a bit) and
  22. don't worry about registers, tell me.  reg_res can be any register,
  23. including reg_top, reg_bot or reg_misc.
  24.  
  25. If you want to turn it into a loop, do so.. But remember that the
  26. fundamental unit of of the routine takes 3 clock counts, a branch-loop
  27. takes five! Also, it'll be straightforward enough to turn into a
  28. subroutine..
  29.  
  30. If you need any clarification of it, ask me...
  31.  
  32. Someone posted another version which is faster for a logarithmic
  33. distribution of numbers, with 0 and 1 occuring most frequently; I
  34. haven't got it to hand, but could dig it up if nobody else posts
  35. it.
  36.  
  37.  Conrad
  38.  
  39.  
  40.  
  41. From: torbenm@diku.dk (Torben AEgidius Mogensen)
  42. Date: 31 Oct 91 15:34:21 GMT
  43. Subject: Re: fast divide
  44. Sender: torbenm@freke.diku.dk
  45.  
  46. Here is one I cooked up. It is from memory, so there might be slight
  47. errors. The comparisons before the first SUB ensure that no overflow
  48. happens on the ASL. Worst case time is 5 cycles per bit.
  49.  
  50. Arguments in p,q.
  51. on exit, r = p div q, p = p mod q
  52.  
  53. .div
  54.  MOV r,#0
  55.  CMP p,q
  56.  BLT nodiv
  57.  CMP p,q ASL #1
  58.  BLT div0
  59.  CMP p,q ASL #2
  60.  BLT div1
  61.  ...            \ repeat for 3..30
  62.  CMP p,q ASL #31
  63.  SUBGE p,q ASL #31
  64.  ADDGE r,#2^31
  65.  CMP p,q ASL #30
  66. .div30
  67.  SUBGE p,q ASL #30
  68.  ADDGE r,#2^30
  69.  CMP p,q ASL #29
  70. .div29
  71.  ...            \ repeat for 29..1
  72. .div0
  73.  SUBGE p,q ASL #0    \ equiv. to SUBGE p,q
  74.  ADDGE r,#2^0
  75. .nodiv
  76.  MOV PC,Link
  77.  
  78.  
  79.  
  80.  
  81.  
  82. From: gcwillia@daisy.waterloo.edu (Graeme Williams)
  83. Date: 2 Nov 91 20:13:28 GMT
  84. Subject: Re: fast divide
  85. Organization: University of Waterloo
  86.  
  87. Ok, here is the fastest unsigned divide routine I know of. The 3 instruction
  88. loop (unrolled) wasn't my idea - but the piece of code that figures out
  89. whereabouts to jump into the unrolled loop is.
  90.  
  91. On entry d and n should be both +ve.
  92.  
  93. CMP d,#0 : BEQ end% ; Remove zero divisors
  94. CMP d,n : MOVGT m,n : MOVGT n,#0 : BGT end% ; Exit if denominator > numerator
  95.  
  96. ; This next bit of code figures out roughly how many bits the quotient is
  97. ; going to have and hence how many times you need to run through the
  98. ; divide loop proper - its only worth finding out to the nearest 4 times
  99.  
  100. .start%
  101. MOV cnt,#28 : MOV m,n,LSR#4
  102. CMP d,m,LSR#12 : SUBLE cnt,cnt,#16 : MOVLE m,m,LSR#16
  103. CMP d,m,LSR#4  : SUBLE cnt,cnt,#8  : MOVLE m,m,LSR#8
  104. CMP d,m        : SUBLE cnt,cnt,#4  : MOVLE m,m,LSR#4
  105.  
  106. MOV n,n,LSL cnt
  107. ADDS n,n,n : RSB d,d,#0 ; Have to flip the sign of d for the divide loop
  108. ADD cnt,cnt,cnt,LSL#1  ; Multiply cnt by 3
  109. ADD pc,pc,cnt,LSL#2    ; Jump cnt instructions
  110. MOV R0,R0              ; Dummy instruction to take care of pipelining
  111.  
  112. 32 copies of { ADCS m,d,m,LSL#1 : SUBCC m,m,d : ADCS n,n,n }
  113.  
  114. .end%
  115.  
  116. The best times occur when the numerator and denominator of your division
  117. are of similar size. The worst times when the numerator is very large
  118. and the denominator small. (The case where the denominator is larger than
  119. the numerator is killed off very early.)
  120.  
  121. Suppose one has a distribution of numbers wherein the highest bit of
  122. the numbers is equally distributed between bit 0 and bit 31, that is,
  123. there is the same number of numbers between 2^n and 2^(n+1) for every n.
  124. (I think this is actually the case for most purposes)
  125.  
  126. Now if a numerator and denominator are selected at random from this
  127. distribution subject only to the requirement that denom <= numer
  128. then the above routine will execute on average in 58.25 cycles
  129. (from the point start% in the code).
  130.  
  131. The worst case is 116 cycles (top bit of quotient is bit 28 or higher)
  132. the best case is 32 cycles (top bit of quotient is bit 0 to 3)
  133. The inbetween cases get 12 cycles worse for every 4 extra bits in the
  134. quotient.
  135.  
  136. Note that the average case isn't the simple average of the various cases
  137. but has to be weighted toward the better cases - this is because there
  138. are more ways (27) for numer and denom to differ by say 5 bits than there
  139. are (7) for them to differ by say 25 bits.
  140.  
  141. Have fun.
  142.  
  143. Graeme Williams
  144.  
  145.  
  146.  
  147. From: zrzm0370@rusmv1.rus.uni-stuttgart.de (Joerg Scheurich)
  148. Subject: integer division
  149. Date: 10 Jun 91 11:25:36 GMT
  150.  
  151. Hi 
  152.  
  153. So i know, there is no Assembler-command for integer-division in the 
  154. ARM. Therefor a fast division-routine is a thing of common interest.
  155.  
  156. In a earlier Posting i wrote about the bad quick hacked division-routine
  157. for the demo of my formula-tool (math. formula ==> assemblermacros).
  158.  
  159. Now i wrote a better routine, but i don't know, if there is a better 
  160. algorithm.
  161.  
  162. The shorter and slower 32-Bit/32-Bit-division-routine requires
  163. 382     Cycles in 100 Bytes, with usage of 4 32-Bit-registers and 4 Byte memory.
  164. With unrolling the loop,
  165. the faster  and longer 32-Bit/32-Bit-division-routine requires 
  166. 182     Cycles in 692 Bytes, with usage of 4 32-Bit-registers.
  167.   
  168. This is very faster then the old routine (which requires 2**33 Cycles in 
  169. worst case and requires all time of the universe, if there is a division
  170. by zero ... )
  171.  
  172. Cause the INTERNAL-assembler-command of the INTEL 8086
  173. for a                  32-Bit/16-Bit-division  requires
  174. 165-184 Cycles in 2-4 Bytes, with usage of 3  16-Bit-registers,
  175. i think, the result is ok.   
  176.  
  177. The result is nothing against the INTERNAL-assembler-command of the ARM
  178. for a                  32-Bit*32-Bit-multiplication which  requires
  179. 17     Cycles in    4 Bytes, with usage of 1-3 32-Bit-registers,
  180. but my Professor in digital electronics used to say:
  181. "If a program contain much divisions, the programmer is a idiot" ...
  182.  
  183. Know someone a better (faster or shorter) algorithm ?
  184.  
  185. so long
  186. MUFTI
  187.  
  188. ( internet:    zrzm0111@helpdesk.rus.uni-stuttgart.de
  189.   ( from janet: zrzm0111%de.uni-stuttgart.rus.helpdesk@NFS-RELAY )
  190.   bitnet:      ZRZM  AT DS0RUS1I )
  191.  
  192. div-fast:
  193. ---------
  194. ; division routine
  195. ; 1. calculate flag if result is negate and convert operands to positiv
  196. ; 2. second "divide" with unsigned suczessive Approximation  
  197. ; 3. fix the sign of result 
  198.  
  199.         .MACRO INTdivide
  200.          LDR R2,%2
  201.          LDR R3,%3 
  202.  
  203.          MOV R0,#0
  204.          CMP R2,#0
  205.           RSBLT R2,R2,#0
  206.           SUBLT R0,R0,#1
  207.          CMP R3,#0
  208.           RSBLT R3,R3,#0
  209.           MVNLT R0,R0
  210.  
  211.          MOV  R1,#0
  212.  
  213.          ADDS R2,R2,R2
  214.          ADCS R1,R1,R1
  215.          CMP  R1,R3
  216.          SUBGE  R1,R1,R3
  217.          ADDGE  R2,R2,#1         
  218. \l2
  219.          ADDS R2,R2,R2
  220.          ADCS R1,R1,R1
  221.          CMP  R1,R3
  222.          SUBGE  R1,R1,R3
  223.          ADDGE  R2,R2,#1         
  224. \l3
  225.          ADDS R2,R2,R2
  226.          ADCS R1,R1,R1
  227.          CMP  R1,R3
  228.          SUBGE  R1,R1,R3
  229.          ADDGE  R2,R2,#1         
  230. \l4
  231.          ADDS R2,R2,R2
  232.          ADCS R1,R1,R1
  233.          CMP  R1,R3
  234.          SUBGE  R1,R1,R3
  235.          ADDGE  R2,R2,#1         
  236. \l5
  237.          ADDS R2,R2,R2
  238.          ADCS R1,R1,R1
  239.          CMP  R1,R3
  240.          SUBGE  R1,R1,R3
  241.          ADDGE  R2,R2,#1         
  242. \l6
  243.          ADDS R2,R2,R2
  244.          ADCS R1,R1,R1
  245.          CMP  R1,R3
  246.          SUBGE  R1,R1,R3
  247.          ADDGE  R2,R2,#1         
  248. \l7
  249.          ADDS R2,R2,R2
  250.          ADCS R1,R1,R1
  251.          CMP  R1,R3
  252.          SUBGE  R1,R1,R3
  253.          ADDGE  R2,R2,#1         
  254. \l8
  255.          ADDS R2,R2,R2
  256.          ADCS R1,R1,R1
  257.          CMP  R1,R3
  258.          SUBGE  R1,R1,R3
  259.          ADDGE  R2,R2,#1         
  260. \l9
  261.          ADDS R2,R2,R2
  262.          ADCS R1,R1,R1
  263.          CMP  R1,R3
  264.          SUBGE  R1,R1,R3
  265.          ADDGE  R2,R2,#1         
  266. \l10
  267.          ADDS R2,R2,R2
  268.          ADCS R1,R1,R1
  269.          CMP  R1,R3
  270.          SUBGE  R1,R1,R3
  271.          ADDGE  R2,R2,#1         
  272. \l11
  273.          ADDS R2,R2,R2
  274.          ADCS R1,R1,R1
  275.          CMP  R1,R3
  276.          SUBGE  R1,R1,R3
  277.          ADDGE  R2,R2,#1         
  278. \l12
  279.          ADDS R2,R2,R2
  280.          ADCS R1,R1,R1
  281.          CMP  R1,R3
  282.          SUBGE  R1,R1,R3
  283.          ADDGE  R2,R2,#1         
  284. \l13
  285.          ADDS R2,R2,R2
  286.          ADCS R1,R1,R1
  287.          CMP  R1,R3
  288.          SUBGE  R1,R1,R3
  289.          ADDGE  R2,R2,#1         
  290. \l14
  291.          ADDS R2,R2,R2
  292.          ADCS R1,R1,R1
  293.          CMP  R1,R3
  294.          SUBGE  R1,R1,R3
  295.          ADDGE  R2,R2,#1         
  296. \l15
  297.          ADDS R2,R2,R2
  298.          ADCS R1,R1,R1
  299.          CMP  R1,R3
  300.          SUBGE  R1,R1,R3
  301.          ADDGE  R2,R2,#1         
  302. \l16
  303.          ADDS R2,R2,R2
  304.          ADCS R1,R1,R1
  305.          CMP  R1,R3
  306.          SUBGE  R1,R1,R3
  307.          ADDGE  R2,R2,#1         
  308. \l17
  309.          ADDS R2,R2,R2
  310.          ADCS R1,R1,R1
  311.          CMP  R1,R3
  312.          SUBGE  R1,R1,R3
  313.          ADDGE  R2,R2,#1         
  314. \l18
  315.          ADDS R2,R2,R2
  316.          ADCS R1,R1,R1
  317.          CMP  R1,R3
  318.          SUBGE  R1,R1,R3
  319.          ADDGE  R2,R2,#1         
  320. \l19
  321.          ADDS R2,R2,R2
  322.          ADCS R1,R1,R1
  323.          CMP  R1,R3
  324.          SUBGE  R1,R1,R3
  325.          ADDGE  R2,R2,#1         
  326. \l20
  327.          ADDS R2,R2,R2
  328.          ADCS R1,R1,R1
  329.          CMP  R1,R3
  330.          SUBGE  R1,R1,R3
  331.          ADDGE  R2,R2,#1         
  332. \l21
  333.          ADDS R2,R2,R2
  334.          ADCS R1,R1,R1
  335.          CMP  R1,R3
  336.          SUBGE  R1,R1,R3
  337.          ADDGE  R2,R2,#1         
  338. \l22
  339.          ADDS R2,R2,R2
  340.          ADCS R1,R1,R1
  341.          CMP  R1,R3
  342.          SUBGE  R1,R1,R3
  343.          ADDGE  R2,R2,#1         
  344. \l23
  345.          ADDS R2,R2,R2
  346.          ADCS R1,R1,R1
  347.          CMP  R1,R3
  348.          SUBGE  R1,R1,R3
  349.          ADDGE  R2,R2,#1         
  350. \l24
  351.          ADDS R2,R2,R2
  352.          ADCS R1,R1,R1
  353.          CMP  R1,R3
  354.          SUBGE  R1,R1,R3
  355.          ADDGE  R2,R2,#1         
  356. \l25
  357.          ADDS R2,R2,R2
  358.          ADCS R1,R1,R1
  359.          CMP  R1,R3
  360.          SUBGE  R1,R1,R3
  361.          ADDGE  R2,R2,#1         
  362. \l26
  363.          ADDS R2,R2,R2
  364.          ADCS R1,R1,R1
  365.          CMP  R1,R3
  366.          SUBGE  R1,R1,R3
  367.          ADDGE  R2,R2,#1         
  368. \l27
  369.          ADDS R2,R2,R2
  370.          ADCS R1,R1,R1
  371.          CMP  R1,R3
  372.          SUBGE  R1,R1,R3
  373.          ADDGE  R2,R2,#1         
  374. \l28
  375.          ADDS R2,R2,R2
  376.          ADCS R1,R1,R1
  377.          CMP  R1,R3
  378.          SUBGE  R1,R1,R3
  379.          ADDGE  R2,R2,#1         
  380. \l29
  381.          ADDS R2,R2,R2
  382.          ADCS R1,R1,R1
  383.          CMP  R1,R3
  384.          SUBGE  R1,R1,R3
  385.          ADDGE  R2,R2,#1         
  386. \l30
  387.          ADDS R2,R2,R2
  388.          ADCS R1,R1,R1
  389.          CMP  R1,R3
  390.          SUBGE  R1,R1,R3
  391.          ADDGE  R2,R2,#1         
  392. \l31
  393.          ADDS R2,R2,R2
  394.          ADCS R1,R1,R1
  395.          CMP  R1,R3
  396.          SUBGE  R1,R1,R3
  397.          ADDGE  R2,R2,#1         
  398. \l32
  399.          ADDS R2,R2,R2
  400.          ADCS R1,R1,R1
  401.          CMP  R1,R3
  402.          SUBGE  R1,R1,R3
  403.          ADDGE  R2,R2,#1         
  404.     
  405.          CMP R0,#0
  406.          RSBNE R2,R2,#0 
  407.          STR R2,%1
  408.         .ENDM 
  409.  
  410. div-short:
  411. ----------
  412. ; division routine
  413. ; 1. calculate flag if result is negate and convert operands to positiv
  414. ; 2. second "divide" with unsigned suczessive Approximation  
  415. ; 3. fix the sign of result 
  416.  
  417.         .MACRO INTdivide
  418.          LDR R2,%2
  419.          LDR R3,%3 
  420.  
  421.          MOV R0,#0
  422.          CMP R2,#0
  423.           RSBLT R2,R2,#0
  424.           SUBLT R0,R0,#1
  425.          CMP R3,#0
  426.           RSBLT R3,R3,#0
  427.           MVNLT R0,R0
  428.          STR R0,minusflag
  429.  
  430.          MOV  R0,#32.
  431.          MOV  R1,#0
  432. \loop    ADDS R2,R2,R2
  433.          ADCS R1,R1,R1
  434.          CMP  R1,R3
  435.          SUBGE  R1,R1,R3
  436.          ADDGE  R2,R2,#1         
  437.          SUB  R0,R0,#1
  438.          CMP  R0,#0
  439.          BNE  \loop        
  440.     
  441.          LDR R0,minusflag
  442.          CMP R0,#0
  443.          RSBNE R2,R2,#0 
  444.          STR R2,%1
  445.         .ENDM 
  446.  
  447.  
  448.  
  449. From: chughes@maths.tcd.ie (Conrad Hughes)
  450. Subject: Re: integer division
  451. Date: 11 Jun 91 14:10:31 GMT
  452.  
  453. zrzm0370@rusmv1.rus.uni-stuttgart.de (Joerg Scheurich) writes:
  454. >382     Cycles in 100 Bytes, with usage of 4 32-Bit-registers
  455. >and 4 Byte memory.
  456. >With unrolling the loop,
  457. >the faster  and longer 32-Bit/32-Bit-division-routine requires 
  458. >182     Cycles in 692 Bytes, with usage of 4 32-Bit-registers.
  459.  
  460. This divides a 64bit number by a 32bit one, with 32bit result, in 97
  461. instructions/388 bytes/97 clock cycles..
  462.  
  463. Entry: A=MSW of 64bit no., B=LSW of 64bit no., C=32bit no.
  464.     C _must_ be negative (if it's positive, RSB C,C,#0),
  465.     A _must_ be positive (if not, RSBS B,B,#0:RSC A,A,#0)
  466. ADDS B,B,B
  467. ADCS A,C,A,LSL#1:SUBCC A,A,C:ADCS B,B,B [repeat these three 32 times]
  468. Exit: A=Remainder of division, B=result, C unchanged.
  469.     ..if you don't need the remainder, get rid of the last
  470.     SUBCC A,A,C.
  471.     The result will be unsigned, and flags will (obviously)
  472.     reflect the last addition.
  473. Adjust as you will to get 32/32 division (Initialise A to 0, or AB
  474. = numerator shifted some way) or any other variety you like..
  475. Rolling up the loop it could get slightly complicated since every
  476. instruction requires flag information from the previous one ;-)
  477. Something like SUB count,count,#1:TEQ count,#0:BNE loop with count
  478. initialised to #32 might do the trick, but it'll slow it down to at
  479. least 288 cycles (so what if it only uses 32 bytes?? ;-}), which is
  480. pretty unacceptable unless you're on an ARM3..
  481.  
  482. This is off the top of my head and I'm nowhere near the Arc, so if
  483. it doesn't work (it should - I've typed it in enough times now..)
  484. flame me..
  485.  
  486. Conrad
  487.  
  488.  
  489.  
  490. From: gcwillia@daisy.waterloo.edu (Graeme Williams)
  491. Subject: Re: really FAST integer division
  492. Summary: Avg. exec. time < 60 cycles    - the fastest div in the West?
  493. Date: 28 Jun 91 19:07:58 GMT
  494. Organization: University of Waterloo
  495.  
  496. Following several posts regarding division routines, in particular one
  497. with a lovely 3 instr. central loop I modified my old division routine
  498. into the following (supersonic, lightning fast, ZR rated, :-) )
  499. 32bit routine:
  500.  
  501. ;Essentially what's happening here is we are figuring out how far left
  502. ;we can shift the numerator before any actual dividing begins and thus save
  503. ;a significant number of useless trips through the (unrolled) 3 instr. loop.
  504. ; - Note we only go to the nearest 4 bits, trying to save another 2 bits
  505. ;   results in 3 extra instrs. for a saving of 6 instrs. half the time
  506. ;   and 0 instrs. the other half -  i.e. no nett benefit.
  507.  
  508. MOV cnt,#28 : MOV mod,num,LSR#4
  509. CMP den,mod,LSR#12 : SUBLE cnt,cnt,#16 : MOVLE mod,mod,LSR#16
  510. CMP den,mod,LSR#4 : SUBLE cnt,cnt,#8 : MOVLE mod,mod,LSR#8
  511. CMP den,mod : SUBLE cnt,cnt,#4 : MOVLE mod,mod,LSR#4
  512. MOV num,num,LSL cnt : RSB den,den,#0
  513.  
  514. ADDS num,num,num
  515. ;Now skip over cnt copies of the 3 instr. loop.
  516. ADD cnt,cnt,cnt,LSL#1 : ADD pc,pc,cnt,LSL#2 : MOV R0,R0
  517.  
  518. {ADCS mod,den,mod,LSL#1 : SUBLO mod,mod,den : ADCS num,num,num} x 32 copies
  519.  
  520.  
  521. The routine behaves as follows:
  522. On Entry:  num - is a signed numerator A (but +ve)
  523.            den - is a signed denominator B (but non-zero and +ve)
  524. On Exit:   mod - contains A MOD B
  525.            num - contains A DIV B
  526.  
  527. The routine requires 4 registers and 452 bytes of memory.
  528.  
  529. Execution time:
  530.   Given numbers A and B (both +ve) chosen at random from a distribution in
  531.   which the most significant bit of the numbers is uniformly distributed
  532.   between bits 0 and 31 (i.e. the density of numbers goes as roughly log n)
  533.   then the average execution time is:
  534.  
  535.        For A < B :  32 cycles      (no division actually required)
  536.        For A >= B:  58.25 cycles
  537.  
  538.        The best and worst cases are 32 cycles and 116 cycles respectively.
  539.  
  540.  
  541. Have fun. (Stuff like this ought to be worth good money!)
  542.  
  543. Graeme Williams
  544. gcwillia@daisy.waterloo.edu
  545.  
  546. P.S. With any luck there's only a couple of typos :-).
  547.  
  548.  
  549.  
  550. From: dseal@armltd.uucp (David Seal)
  551. Subject: Re: Dividing
  552. Date: 5 Mar 91 19:47:12 GMT
  553.  
  554. In article <8828@castle.ed.ac.uk> ecwu61@castle.ed.ac.uk (R Renwick) writes:
  555.  
  556. >    Can anyone help me with this problem:
  557. >In my super-duper, wire-frame model animating 'C' program, I represent 
  558. >floating point numbers as 4-byte integers. This I do by shifting the number
  559. >being represented by 15 bits (multiply by 32768) in order that I can keep a
  560. >track of the fractional part. The reason for doing this is that I want
  561. >to make sure my program runs as fast as possible by not using floating
  562. >point arithmetic...
  563. >
  564. >    What I want to do is do a divide a number by another number
  565. >and not lose alot of the precision.
  566. >    The way I do this at the moment is by
  567. >         result=((a/b)<<15)
  568. >But if a and b are close together then (a/b) loses alot of precison
  569. >(since the result is an int).
  570. >
  571. >Does anyone know how I could do an integer division without losing
  572. >precision. I cannot use result=(((a<<8)/b)<<7) or any other tricks
  573. >because a may be close to 32768<<15 already...
  574. >Perhaps if I can find the reciprocal of b in the above representation
  575. >and multiply it by a then I'll not lose the as much precision, but I
  576. >don't know how to do this (find the reciprocal) :-(
  577.  
  578. Two quick suggestions:
  579.  
  580. (1) The basic problem is that integer division stops when it determines the
  581.     bit in the units place, whereas you want it to go on and calculate
  582.     another 15 fractional binary places. So rather than using C's integer
  583.     divide operator, write a long division routine using subtractions and
  584.     shifts and force it to go on 15 iterations longer than normal. (This
  585.     won't be much slower than C's integer divide, which essentially uses a
  586.     long division routine anyway).
  587.  
  588.     If speed is very important, you'll probably want to either (a) write a
  589.     well-optimised assembler routine; or (b) write it as a C macro, so that
  590.     the compiler includes it inline. In the latter case, you may want to
  591.     look carefully at the assembler produced by the compiler for an instance
  592.     of your macro and experiment a bit - careful choice of the details of
  593.     the long division algorithm can make a significant difference to the
  594.     speed of the division.
  595.  
  596.     Incidentally, you may want to watch out for significant bits being lost
  597.     during the last 15 iterations: this is perfectly possible and means that
  598.     your result has overflowed.
  599.  
  600. (2) Use a Newton-Raphson iteration to find the reciprocal of your divisor
  601.     and then multiply - this presupposes that you've got an efficient way to
  602.     do multiplications, both for the Newton-Raphson iteration and for the
  603.     final multiplication. The iteration to find the reciprocal of a number A
  604.     is (in pseudo-code - you'll have to translate to C):
  605.  
  606.        newx = initial approximation to reciprocal;
  607.        repeat
  608.          x = newx;
  609.          newx = x * (2 - A*x);
  610.        until x and newx sufficiently close together;
  611.  
  612.     The main thing to beware of in this is that your initial approximation
  613.     must be reasonably close to the reciprocal - it must be greater than 0
  614.     and less than twice the reciprocal. Such an approximation can be found
  615.     by finding the most significant 1 in A and choosing a value based on
  616.     this - e.g. if A lies in the range 1.0 <= A < 2.0, its most significant
  617.     1 is at bit position 16, and a suitable starting point for the iteration
  618.     would be 0.75. This gives us:
  619.  
  620.     Most sign. bit position      Range for A        Suitable starting point
  621.     -----------------------------------------------------------------------
  622.               :
  623.               :
  624.               9              2^(-7) <= A < 2^(-6)       1.5*2^6
  625.              10              2^(-6) <= A < 2^(-5)       1.5*2^5
  626.              11              2^(-5) <= A < 2^(-4)       1.5*2^4
  627.              12              2^(-4) <= A < 2^(-3)       1.5*2^3
  628.              13              2^(-3) <= A < 2^(-2)       1.5*2^2
  629.              14              2^(-2) <= A < 2^(-1)       1.5*2^1
  630.              15              2^(-1) <= A < 2^0          1.5*2^0
  631.              16                 2^0 <= A < 2^1          1.5*2^(-1)
  632.              17                 2^1 <= A < 2^2          1.5*2^(-2)
  633.              18                 2^2 <= A < 2^3          1.5*2^(-3)
  634.              19                 2^3 <= A < 2^4          1.5*2^(-4)
  635.              20                 2^4 <= A < 2^5          1.5*2^(-5)
  636.              21                 2^5 <= A < 2^6          1.5*2^(-6)
  637.              22                 2^6 <= A < 2^7          1.5*2^(-7)
  638.              :
  639.              :
  640.  
  641.     Watch out for very big values - e.g. 2^16 is representable in this
  642.     number system, but 2^(-16) isn't!
  643.  
  644. Hope these suggestions help.
  645.  
  646. David Seal
  647. dseal@acorn.co.uk or dseal@armltd.uucp
  648.  
  649.