home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsm / numbers / !NumModTxt / NumModTxt < prev    next >
Encoding:
Text File  |  1995-09-19  |  21.2 KB  |  608 lines

  1. NUMBERS MODULE version 0.12
  2.  
  3. (C) Copyright Nick Craig-Wood 1992-3
  4.  
  5. The module “Numbers” and this documentation “NumModTxt” are freeware.  
  6. They remain copyright Nick Craig-Wood at all times.  You may use and 
  7. distribute them freely provided that the following conditions are 
  8. adhered to
  9.  1) both files are always kept and distributed together
  10.  2) the files are not altered in any way
  11.  3) no profit is made from any distribution with any of the files in
  12. If you wish to break any of these conditions get in touch with me at the 
  13. address below first.
  14.  
  15. Under no circumstances shall the author be liable for any damage, loss 
  16. of profits, time or data or any indirect or consequential loss arising 
  17. out of the use of this software or inability to use this software or 
  18. documentation.
  19.  
  20. The software and documentation was first published in BBC Acorn User 
  21. Magazine, September 1992, and for more information see that issue.
  22.  
  23. INTRODUCTION
  24.  
  25. These routines started life in 1989 written in C on the university 
  26. mainframe in response to a  “Numbers Count” puzzle in PCW.  The problem 
  27. (or part of it) was to calculate the biggest prime you could find of the 
  28. form N!+1.   However the routines did not get finished in time  for the 
  29. puzzle deadline.   In the quest for speed I converted the routines to 
  30. 68000 code for my  Atari ST, and then a year later into ARM code.  With 
  31. an ARM3 the routines run at the same speed as they did on the mainframe!
  32.  
  33. Numbers are held in application memory area in a heap, and maintained by 
  34. OS_Heap.  Before the module can be used, it must be told about this heap 
  35. with Num_HeapInit.  Numbers come in two pieces, the head and the tail.   
  36. All numbers have a head, but need not have a tail.  The head of the 
  37. number is a short block in the heap, which points to the tail and keeps 
  38. the length and sign of the number, and various other things.  Numbers 
  39. are passed by reference only, as pointers to the head of the number.  
  40. These are referred to as NUMs.  For example NUM r0 indicates that r0 is 
  41. a pointer to the head of a number.
  42.  
  43. Since NUMs are passed by reference only, if you pass them into 
  44. procedures and then alter the values of the input parameters, you are 
  45. actually altering the NUM.  So to avoid problems, if you write a 
  46. procedure which takes NUMs as parameters for both input and output, it 
  47. is best to define some temporary NUMs using Num_Init for the output, and 
  48. then at the end Num_Swap the results into the correct place, and 
  49. Num_Remove the temporary variables.  All the internal routines of the 
  50. module work like this, so there is never any problem with passing the 
  51. same NUM as input and output.
  52.  
  53. Some of the routines take either NUMs or scalars as arguments.  Scalars 
  54. are normal signed or unsigned 32 bit numbers.  All routines expect NUMs 
  55. to be tidy (except Num_Tidy).  (A num is tidy if its most significant 
  56. digit is non-zero, and if it is zero, then it is positive, and of length 
  57. 1.  Num_Tidy accomplishes this.  It is unlikely that a user will need 
  58. this function.)
  59.  
  60. The numbers module checks the type of any parameters passed to any of 
  61. its SWIs quite carefully.  The NUM parameters are checked by looking for 
  62. a special word in the NUM header block.  The heap pointers are checked 
  63. in a similar way.  The pointers to memory are checked to see whether 
  64. they point to logical memory above &8000 (the system workspace).  This 
  65. checking takes very little time, and increases the reliability of the 
  66. module enormously, especially when developing new programs.
  67.  
  68. Any error from the numbers module will be prefixed with “Numbers: ”.  
  69. For a full list see the ERRORS section.  For a short example program see 
  70. the EXAMPLE section.
  71.  
  72. If you find any bugs, have any comments or queries or wish to use the 
  73. module in commercial software please write to
  74.  
  75. Nick Craig-Wood
  76. 26 Wodeland Avenue
  77. Guildford
  78. Surrey
  79. GU2 5JZ
  80.  
  81. e-mail: ncw@axis.demon.co.uk
  82.  
  83.  
  84. NUMBERS SWI
  85.  
  86. On Entry:       r0-r3 are parameters
  87. On Exit:        r0-r3 are returned as results or corrupted
  88.                 r4-r14 are preserved
  89.  
  90. Interrupts:     Interrupts are enabled
  91.                 Fast interrupts are enabled
  92.  
  93. Processor mode: Processor is in SVC mode
  94.  
  95. Re-entrancy:    SWIs are not re-entrant
  96.  
  97. Use:            See QUICK REFERENCE, and DEFINITIONS for details
  98.                 All SWIs that are capable of looping respond to 
  99. ESCAPE
  100.                 See ERRORS section for details of errors returned
  101.  
  102. QUICK REFERENCE
  103.  
  104. NUMBERS HEAP:   area in application workspace where all the numbers 
  105.                 are kept
  106. HEAD:           16 byte parameter block in the numbers heap pointing 
  107.                 to
  108. TAIL:           variable length block containing the value of the 
  109.                 number
  110. NUM:            meaning a 32 bit integer pointing to a HEAD
  111. INT:            meaning a 32 bit integer
  112. SCALAR:         meaning a 32 bit integer
  113. FLAG:           is either 0 for false, or 1 for true
  114. STRING:         a pointer to a 0 terminated ASCII string
  115.  
  116. a,b,c,d         represent pointers to NUMs
  117. i,j,k           represent SCALARS
  118. p,q             represent a pointer to memory
  119. f               represents a FLAG
  120. h               represents a HeapPointer as returned by Num_HeapInit 
  121.                 in r0
  122.           
  123. SWI     Params  Results Comments
  124.  
  125. Num_Author      -       -       Prints out some info
  126. Num_HeapInit    p,i     h,a,b,c h<-HeapPointer, a<-0, b<-1, c<-2
  127. Num_MakeSmallPrimes i   j       Makes primes up to i, # found to j
  128.  
  129.         (All the SWIs below need a valid NUM or HeapPointer in r0)
  130.  
  131. Num_Allocate    a,i     -       Allocates i words to TAIL of a
  132. Num_Deallocate  a       -       Removes the TAIL of a
  133. Num_Set         a,i     -       Sets a to signed i
  134. Num_USet        a,i     -       Sets a to unsigned i
  135. Num_Init        h       a       Makes a HEAD and TAIL and pointer a
  136. Num_Remove      a       -       Removes the HEAD and TAIL of a
  137. Num_Equals      a,i     f       Returns truth of a = i
  138. Num_Swap        a,b     -       Swaps a and b.  This is quick.
  139. Num_Move        a,b     -       Sets b to a.  Not so quick.
  140. Num_Clear       a       -       Sets TAIL of a to all zeros
  141. Num_Tidy        a       -       Reduces a to shortest length
  142. Num_UCmp        a,b     i       Unsigned compare of a-b to i
  143. Num_Cmp         a,b     i       Returns the sign of a-b to i
  144. Num_ScalarCmp   a,i     j       Returns the sign of a-i to j
  145. Num_ScalarAdd   a,i,c   -       c <- a + i
  146. Num_ScalarSub   a,i,c   -       c <- a - i
  147. Num_ScalarMul   a,i,c   -       c <- a * i
  148. Num_ScalarDiv   a,i,c   j       c <- a / i, j <- a MOD i
  149. Num_ScalarMod   a,i     j       j <- a MOD i
  150. Num_SmallFactorN a,i    k       k=smallest factor of a or 0, try i
  151. Num_SmallFactor a       k       k=smallest factor of a or 0, try all
  152. Num_Add         a,b,c   -       c <- a + b
  153. Num_Sub         a,b,c   -       c <- a - b
  154. Num_Mul         a,b,c   -       c <- a * b
  155. Num_Div         a,b,c,d -       c <- a / b, d <- a MOD b
  156. Num_Mod         a,b,c   -       c <- a MOD b
  157. Num_Dump        a       -       Prints a in hex, and other info
  158. Num_ToString    a       p,q,b   Makes STRING of a to p, end=q
  159.                                 After use do SYS “Num_Remove”,b
  160. Num_Print       a       -       Prints a in the current base
  161. Num_FromString  a,p     f       Converts STRING at p to a, f=ok
  162. Num_Input       a       f       Gets a input in current base to a, f=ok
  163. Num_Info        h       -       Prints memory usage info
  164. Num_RndScalar   h       i       Makes a random number 0-&FFFFFFFF
  165. Num_SetSeed     h,i     -       Sets seed of rnd generator
  166. Num_Rnd         a,b     -       Makes random number to b, 0 <= a < b
  167. Num_Gcd         a,b,c   -       c <- greatest common divisor a,b
  168. Num_Sqr         a,b     -       b <- square root of a
  169. Num_Pow         a,b,c   -       c <- a ^ b (a to the power b)
  170. Num_PowMod      a,b,c,d -       d <- (a^b) MOD c
  171. Num_Factorial   a,b     -       b <- a! = a*(a-1)*(a-1)*..*3*2*1
  172. Num_Inv         a,b,c,d -       Finds c,d: a*c MOD b=d & d=GCD(a,b)
  173. Num_FermatTest  a,i     j       Computes truth of i^(a-1) MOD a = 1 to j
  174. Num_ProbablyPrime a     j       j <- 0 if not prime, 1 probablyprime
  175. Num_Base        h,i     j       Sets base to i, old base in j
  176. Num_ToMem       a,p,i,f -       Converts Nums to Memory
  177. Num_FromMem     a,p,i,f -       Converts Memory to Nums
  178.  
  179.  
  180. DEFINITIONS
  181.  
  182. Num_HeapInit
  183.  
  184. This expects r0 as a pointer to a block of memory to be used as a heap, 
  185. and r1 as the length of this memory in bytes. This returns a pointer to 
  186. the heap in r0 and some NUMs which are useful constants.  NUM r1 <- 
  187. zero, NUM r2 <- one, NUM r3 <- two.  The HeapPointer returned in r0 is 
  188. required by some of the other routines.
  189.  
  190. Num_Allocate
  191.  
  192. This updates NUM r0 to point to a new area of memory of length r1 (in 
  193. 32-bit words).  This memory is not initialised.
  194.  
  195. Num_Deallocate
  196.  
  197. This releases the memory used by a NUM (tail), and sets its pointers to 
  198. NULL.
  199.  
  200. Num_Set
  201.  
  202. This sets the NUM supplied in r0 to the signed scalar supplied in r1.
  203.  
  204. Num_Uset
  205.  
  206. This sets the NUM supplied in r0 to the unsigned scalar supplied in r1.
  207.  
  208. Num_Init
  209.  
  210. Expects r0=HeapPointer.  This returns the address of a new NUM in r0.   
  211. For creating new or LOCAL variables.
  212.  
  213. Num_Remove
  214.  
  215. This removes the allocation for NUM r0 and removes NUM r0.  For removing 
  216. LOCAL variables.
  217.  
  218. Num_Equals
  219.  
  220. This function returns TRUE in r0 if NUM r0 is equal to the SCALAR 
  221. supplied in r1
  222.  
  223. Num_Swap
  224.  
  225. This swaps the two NUMs in r0 and r1.  It is a fast way of getting 
  226. information out of temporary variables, before destroying them
  227.  
  228. Num_Move
  229.  
  230. This moves NUM r0 to NUM r1.  It does this by actually copying the NUM.  
  231. It is slow compared to Num_Swap.
  232.  
  233. Num_Clear
  234.  
  235. This clears the tail of NUM r0 to all zeros.  This might be useful for 
  236. security.
  237.  
  238. Num_Tidy
  239.  
  240. This makes the NUM r0 use as few digits as possible by removing all the 
  241. leading zeros.  All numbers should be tidied.
  242.  
  243. Num_UCmp
  244.  
  245. This returns an unsigned comparison between NUM r0 and NUM r1 in r0 This 
  246. is the SGN(NUM r0 - NUM r1)
  247.  
  248. Num_Cmp
  249.  
  250. This function returns a signed comparison between NUM r0 and NUM r1 It 
  251. returns SGN(NUM r0 - NUM r1)
  252.  
  253. Num_ScalarCmp
  254.  
  255. This function returns a signed comparison between NUM r0 and SCALAR r1 
  256. It returns SGN(NUM r0 - NUM r1)
  257.  
  258. Num_ScalarAdd
  259.  
  260. This adds NUM r0 to (signed int) r1 into NUM r2.
  261.  
  262. Num_ScalarSub
  263.  
  264. This subtracts NUM r0 - (signed int) r1 into NUM r2.
  265.  
  266. Num_ScalarMul
  267.  
  268. This multiplies NUM r0 by (unsigned int) r1 into NUM r2.
  269.  
  270. Num_ScalarDiv
  271.  
  272. This divides NUM r0 by (unsigned int) r1 into NUM r2, remainder 
  273. (unsigned int) r0.
  274.  
  275. Num_ScalarMod
  276.  
  277. This divides NUM r0 by (unsigned int) r1 returning the (unsigned int) 
  278. remainder in r0.
  279.  
  280. Num_Mul
  281.  
  282. NUM r0 * NUM r1 -> NUM r2
  283.  
  284. Num_Div
  285.  
  286. This divides NUM r0 by NUM r1 to give a quotient NUM r2 remainder NUM 
  287. r3.  It does this using a base 2^32 method for speed.  For “divide and 
  288. correct algorithm” see Knuth “Seminumerical Algorithms” section 4.3.1.
  289.  
  290. Num_Mod
  291.  
  292. This divides NUM r0 by NUM r1 to remainder NUM r2.
  293.  
  294. Num_MakeSmallPrimes
  295.  
  296. This makes all the primes up to r0 (using a sieve method), and stores 
  297. them in the RMA pointed to by SmallPrimes.  Thus the SmallPrimes array 
  298. is common to all the users of the numbers module.  NSmallPrimes is set 
  299. to the number of primes found.  It deallocates any old SmallPrimes array 
  300. so this may be called more than once.  It returns the number of 
  301. smallprimes found in r0, and a pointer to the array in r1.  If there are 
  302. already more than enough SmallPrimes in the RMA then this will not 
  303. recalculate.
  304.  
  305. Num_Dump
  306.  
  307. This dumps the number supplied in r0 in Hexadecimal, for debugging, 
  308. along with some other information.
  309.  
  310. Num_ToString
  311.  
  312. This converts the number pointed to by r0 into a string in the current 
  313. base pointed to by r0.  It returns the position of the null at the end 
  314. of the string in r1 and the pointer to the num in r2.  When finished, 
  315. this memory should be released with SYS “Num_Remove”,r2
  316.  
  317. Num_Print
  318.  
  319. This prints out the number supplied in r0 (in the current base).  It 
  320. prints no spaces or newlines.
  321.  
  322. Num_Info
  323.  
  324. Expects r0 = HeapPointer.  This prints information on the numbers 
  325. module, and current heap.
  326.  
  327. Num_FromString
  328.  
  329. This converts a ASCII number in the current base pointed to by r1 into 
  330. the NUM pointed to by r0, until a character which is not valid in the 
  331. current base is reached.  If this is a control char then true is 
  332. returned otherwise false is returned.  It deals with leading “+”,“-”,“ 
  333. ”.  r1 is updated to point to the last unconverted character.
  334.  
  335. Num_Input
  336.  
  337. Inputs a number in the current base to NUM r0.  Returns r0 flagging ok 
  338. conversion (1 => good conversion, 0 => bad conversion).
  339.  
  340. Num_RndScalar
  341.  
  342. Expects r0 = HeapPointer.  Produces a random number into (unsigned int) 
  343. r0 from Seed, and updates Seed, in the range 0-&FFFFFFFF.  It works 
  344. using the algorithm x(n+1)=(1664525 * x(n) + 907633393) MOD 2^32 It is 
  345. known that the least significant bits are not as random as the most 
  346. significant bits, so two consecutive random numbers are generated, and 
  347. combined with EOR after having been rotated by 16 bits with respect to 
  348. each other.  This halves the period.  Reference: Knuth, Seminumerical 
  349. Algorithms 3.3 p102 p84 This is Line 26, with the best spectral co-
  350. efficients for a MOD 2^32 generator, listed in Knuth.  This form is 
  351. especially easy to calculate with the ARMs mul instruction. The A term 
  352. is calculated as the nearest prime to (1/2-1/3*SQR(3))*2^32.
  353.  
  354. Num_SetSeed
  355.  
  356. Expects r0 = HeapPointer.  This sets the internal 32-bit random number 
  357. generator to the seed supplied in (unsigned int) r1.
  358.  
  359. Num_Rnd
  360.  
  361. This generates a random number 0 <= rnd < NUM r0 to NUM r1.
  362.  
  363. Num_Gcd
  364.  
  365. This finds the GCD(NUM r0, NUM r1) -> r2 using Euclid’s algorithm.  GCD 
  366. is the greatest common divisor, that is the largest number which divides 
  367. exactly into NUM r0 and NUM r1.
  368.  
  369. Num_Sqr
  370.  
  371. This takes the square root of NUM r0 to NUM r1.  It uses a second order 
  372. Newton-Raphson convergence.  This doubles the number of significant 
  373. figures on each iteration.  Square root of a negative number is returned 
  374. as 0.  It returns the number of iterations in r0.
  375.  
  376. Num_Pow
  377.  
  378. This finds NUM r0 to the power of NUM r1 to NUM r2.
  379.  
  380. Num_PowMod
  381.  
  382. This finds NUM r0 to the power of NUM r1 MOD NUM r2 to NUM r3.
  383.  
  384. Num_Factorial
  385.  
  386. This finds NUM r0 factorial to NUM r1 if NUM r0 <=1 then NUM r1=0.
  387.  
  388. Num_SmallFactorN
  389.  
  390. This sees whether NUM r0 has any small factors.  It requires 
  391. Num_MakeSmallPrimes to have been called.  It tests r1 small primes.  It 
  392. returns either the factor found, or 0 to show none found in r0.
  393.  
  394. Num_SmallFactor
  395.  
  396. This sees whether NUM r0 has any small factors.  It requires 
  397. Num_MakeSmallPrimes to have been called.  It tests all the small primes 
  398. that have been made.  It returns either the factor found, or 0 to show 
  399. none found in r0.
  400.  
  401. Num_Inv
  402.  
  403. This finds NUM r2 such that r0*r2 MOD r1=r3 AND r3=GCD(r0,r1) so if 
  404. GCD(r0,r1)=1 (for instance if r1 is prime) then this will compute the 
  405. inverse MOD r1. This is adapted from Knuth: Seminumerical Algorithms 
  406. 4.5.2 pp325
  407.  
  408. Num_FermatTest
  409.  
  410. This finds whether NUM r0 is a prime with respect to SCALAR r1, using 
  411. the fermat test.  That is r0 is not a prime if r1^(r0-1) MOD r0 <> 1 IF 
  412. r1^(r0-1) MOD r0=1 THEN r0 may be a prime. r1 must be prime for the test 
  413. to work. IE this test returns false if r0 is not prime, or true if r0 
  414. might be prime.  This test is less reliable than Num_ProbablyPrime and 
  415. takes about the same time to execute.
  416.  
  417. Num_ProbablyPrime
  418.  
  419. This tests whether r0 is prime or not.  The function returns (in r0) 
  420. false if the number is not prime, and true if the number is probably 
  421. prime. The algorithm will return true with r0 composite with a 
  422. probability of less than 0.25.  This algorithm is as in Knuth - 
  423. Seminumerical algorithms 4.5.4P
  424.  
  425. Num_Base
  426.  
  427. This sets the current base to that supplied in r1.  r0 should be 
  428. supplied as the HeapPointer or a valid NUM.  That base will be used for 
  429. Num_ToString, Num_FromString, Num_Input and Num_Print.  r1 can be from 2 
  430. to 32.  If it is outside that range then this SWI will not change the 
  431. base.  The old base will be returned in r0.  If you want to know the 
  432. current base then pass a 0 to Num_Base in r1.
  433.  
  434. Num_ToMem 
  435.  
  436. This converts variable length NUMs into fixed length integers in memory.  
  437. The numbers in memory are assumed to unsigned.  If the NUM is too long 
  438. for the fixed space the most significant digits will be truncated.
  439. r0 is pointer to NUM to be converted
  440. r1 is the pointer to the memory space for the fixed integer
  441. r2 is the length in words of the memory integer
  442. r3 = 0 means lsw first, 1 = msw first
  443.  
  444. Num_FromMem
  445.  
  446. This converts fixed length integers in memory into variable length NUMs.  
  447. The numbers in memory are assumed to unsigned.
  448. r0 is pointer to NUM to be converted
  449. r1 is the pointer to the memory space for the fixed integer
  450. r2 is the length in words of the fixed space
  451. r3 = 0 means lsw first, 1 = msw first
  452.  
  453.  
  454. EXAMPLE
  455.  
  456. In the spirit of an illustration is worth 1000 words, here is an example 
  457. BASIC program using the numbers module.  It tries to find any primes of 
  458. the form 111...111 (these are called rep-units).
  459.  
  460. REM Check to see we have the numbers module
  461. *RMEnsure Numbers 0.0 RMLoad Numbers
  462. *RMEnsure Numbers 0.0 Error 1 Numbers module not found
  463.  
  464. REM put aside some BASIC memory for the Numbers Heap
  465. HeapSize=64*1024
  466. DIM Numbers HeapSize
  467.  
  468. REM Initialise the Heap
  469. SYS “Num_HeapInit”,Numbers,HeapSize TO hp%,zero%,one%,two%
  470.  
  471. REM Make some small primes for finding small factors
  472. SYS “Num_MakeSmallPrimes”,5000 TO a%
  473. PRINT ;a%;“ small primes found”
  474.  
  475. REM This is the number of times we will run Num_ProbablyPrime to be sure
  476. REM a repunit is prime
  477. timestotest=20
  478.  
  479. REM Make the NUM repunit% and start it off at 1
  480. SYS “Num_Init”,hp% TO repunit%
  481. SYS “Num_Set”,repunit%,1
  482.  
  483. FOR n%=2 TO 100000
  484.   REM repunit=10*repunit+1, ie add 1 digit to the repunit
  485.   SYS “Num_ScalarMul”,repunit%,10,repunit%
  486.   SYS “Num_ScalarAdd”,repunit%,1,repunit%
  487.  
  488.   PRINT “.”;
  489.   REM try to find a small factor of repunit%
  490.   SYS “Num_SmallFactor”,repunit% TO composite
  491.   IF composite=0 THEN
  492.    composite=timestotest
  493.    WHILE composite>0
  494.     PRINT “|”;
  495.     REM test the primality of repunit% timestotest times
  496.     SYS “Num_ProbablyPrime”,repunit% TO pprime
  497.     IF pprime THEN
  498.      composite-=1
  499.     ELSE
  500.      REM if the number is composite but passes a test, this is unusual
  501.      IF composite<>timestotest THEN PRINT “Unusual prime: ”;FNprint(repunit%)
  502.      composite=-1
  503.     ENDIF
  504.    ENDWHILE
  505.   ENDIF
  506.   REM print out a prime if we have found one
  507.   IF composite=0 THEN PRINT “R(”;n%;“) = ”;FNprint(repunit%);“ is prime”
  508. NEXT n%
  509. END
  510.  
  511. REM This prints NUM a% returning a null string
  512.  
  513. DEF FNprint(a%): SYS “Num_Print”,a%: =“”
  514.  
  515. ERRORS
  516.  
  517. The following errors are unique to the Numbers module.  However the 
  518. numbers Module will return any OS errors (such as OS_Heap errors) 
  519. unchanged, except for the addition of a prefix of “Numbers: ”
  520.  
  521. Numbers module has become corrupted
  522. Returned on initialisation if the Numbers code has been changed (say by 
  523. a virus or by a disk error).
  524.  
  525. Numbers: Unknown Operation
  526. Returned when an unimplemented numbers SWI is called.
  527.  
  528. Numbers: Escape
  529. Returned when the user pressed Escape in a Looping SWI.
  530.  
  531. Numbers: Invalid Heap Pointer
  532. Returned when a bad heap pointer is passed to a SWI or possibly if a NUM 
  533. header has become corrupt.
  534.  
  535. Numbers: Invalid Number Pointer
  536. Returned if a bad NUM pointer was passed to a SWI.
  537.  
  538. Numbers: Invalid Pointer
  539. Returned if a pointer was passed to a SWI which was not in logical 
  540. memory above &8000 (system workspace).
  541.  
  542. Numbers: Divide by 0 in Num_ScalarDiv
  543.  
  544. Numbers: Divide by 0 in Num_Div
  545.  
  546. Numbers: N > NSmallPrimes in Num_SmallFactorN
  547. Returned when you ask for more SmallPrimes than have been calculated by 
  548. Num_MakeSmallPrimes.
  549.  
  550. Numbers: Internal: Bad Validation Character
  551. Numbers: Internal: Addback Failed in Num_Div
  552. Numbers: Internal: Trial quotient wrong in Num_Div
  553. These errors should never occur.  If they do, I would be interested to 
  554. know!
  555.  
  556. HISTORY
  557.  
  558. Version 0.08, 01 Aug 92
  559.  
  560. First release, published in Acorn User magazine, September 1992.
  561.  
  562. Version 0.10, 15 Oct 92
  563.  
  564. SWI argument validation was added.  This means all arguments to the SWIs 
  565. are checked as rigorously as possible to catch mistakes (for example 
  566. passing an integer rather that a pointer to a num) when writing programs 
  567. with the numbers module.  It makes debugging a lot easier, takes very 
  568. little time and ensures the numbers module won’t crash if you pass the 
  569. wrong thing to it.  Special words were put in the various blocks in the 
  570. heap to enable checking.  The errors “Bad Validation Character”, 
  571. “Invalid Heap Pointer”, “Invalid Number Pointer” and “Invalid Pointer” 
  572. were added for this purpose.
  573.  
  574. Though popular request the following SWIs were added:
  575.  
  576. Num_Base: To allow number IO to be in any base 2-36.  Required a major 
  577. re-write of the conversion routines.
  578.  
  579. Num_ToMem: To allow numbers to be put into the heap in a user friendly 
  580. way for putting to a file or other manipulation.  Also capability for 
  581. LSW or MSW first added for compatibility with other programs.
  582.  
  583. Num_FromMem: To allow numbers to be got from the heap in a user friendly 
  584. way.
  585.  
  586. Version 0.11, 07 Sep 93
  587.  
  588. A bug in Num_Div normalisation routines removed.  It only showed itself 
  589. when the divisor was longer than 1 word and the top word was &FFFFFFFF.  
  590. A new error “Internal: Trial quotient wrong in Num_Div” and checking 
  591. (very quick) added to Num_Div to catch any further bugs in Num_Div 
  592. (should there be any!). 
  593.  
  594. Version 0.12, 23 Sep 93
  595.  
  596. Conditions of use changed slightly.
  597. Bug in documentation corrected.
  598.  
  599. REFERENCES
  600.  
  601. Books I have found useful whilst writing this module
  602.  
  603. “SemiNumerical Algorithms” (2nd Edition) D.E.Knuth, Addison-Wesley
  604. “Elementary Number Theory” D.M.Burton, Allyn and Bacon
  605. “Cryptography: an introduction to computer security” J.Seberry, Prentice 
  606. Hall
  607.  
  608.