"Fossies" - the Fresh Open Source Software Archive 
Member "mapm_4.9.5a/DOCS/README" (21 Feb 2010, 29090 Bytes) of package /linux/misc/old/mapm-4.9.5a.tar.gz:
As a special service "Fossies" has tried to format the requested text file into HTML format (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1 **************************************************************************
2
3 MAPM
4
5 Version 4.9.5a
6
7 February 21, 2010
8
9 Michael C. Ring
10
11 ringx004@umn.edu
12
13 Latest release will be available at
14 http://tc.umn.edu/~ringx004
15
16 ***************************************************************************
17 * *
18 * Copyright (C) 1999 - 2010 Michael C. Ring *
19 * *
20 * This software is Freeware. *
21 * *
22 * Permission to use, copy, and distribute this software and its *
23 * documentation for any purpose with or without fee is hereby granted, *
24 * provided that the above copyright notice appear in all copies and *
25 * that both that copyright notice and this permission notice appear *
26 * in supporting documentation. *
27 * *
28 * Permission to modify the software is granted. Permission to distribute *
29 * the modified code is granted. Modifications are to be distributed by *
30 * using the file 'license.txt' as a template to modify the file header. *
31 * 'license.txt' is available in the official MAPM distribution. *
32 * *
33 * To distribute modified source code, insert the file 'license.txt' *
34 * at the top of all modified source code files and edit accordingly. *
35 * *
36 * This software is provided "as is" without express or implied warranty. *
37 * *
38 ***************************************************************************
39
40 ---------------------------------------
41 Mike's Arbitrary Precision Math Library
42 ---------------------------------------
43
44 Mike's Arbitrary Precision Math Library is a set of functions that
45 allow the user to perform math to any level of accuracy that is
46 desired. The inspiration for this library was Lloyd Zusman's similar
47 APM package that was released in ~1988. I borrowed some of his ideas
48 in my implementation, creating a new data type (MAPM) and how the data
49 type was used by the user. However, there were a few things I wanted
50 my library to do that the original library did not :
51
52 1) Round a value to any desired precision. This is very handy when
53 multiplying for many iterations. Since multiplication guarantees an
54 exact result, the number of digits will grow without bound. I wanted
55 a way to trim the number of significant digits that were retained.
56
57 2) A natural support for floating point values. From most of the other
58 libraries I looked at, they seem to have a preference for integer
59 only type math manipulations. (However, this library will also do
60 integer only math if you desire).
61
62 And if a library can only do integers, it can't do ...
63
64 3) Trig functions and other common C math library functions. This library
65 will perform the following functions to any desired precision level :
66 SQRT, CBRT, SIN, COS, TAN, ARC-SIN, ARC-COS, ARC-TAN, ARC-TAN2, LOG,
67 LOG10, EXP, POW, SINH, COSH, TANH, ARC-SINH, ARC-COSH, ARC-TANH, and
68 also FACTORIAL. The full 'math.h' is not duplicated, though I think
69 these are most of the important ones. My definition of what's important
70 is what I've actually used in a real application.
71
72 **************************************************************************
73
74 NOTE:
75
76 There is a COMPILER BUG in Microsoft's Visual C++ 7.x (VS.NET 2003) which
77 prevents a C++ MAPM application from compiling.
78
79 This only affects C++ applications. C applications are OK.
80
81 The compiler bug creates an error C2676 similar to this:
82
83 <path>...\mapm-49\M_APM.H(###) : error C2676: binary operator '-': 'MAPM'
84 doesn't define this operator or a conversion to a suitable type for the
85 predefined operator.
86
87 To work around this bug, go to http://www.microsoft.com
88
89 In the upper right corner of web page, search for "814455".
90
91 The results of the search will point you to an article on how to work
92 around the problem.
93
94 **************************************************************************
95
96 NOTE: MAPM Library History can now be found in 'history.txt'
97
98 **************************************************************************
99
100 ANOTHER NOTE: For the Windows/DOS distribution, the filename convention
101 will always be in 8.3 format. This is because there are some users who
102 still use 16 bit DOS ....
103
104 (I really wasn't sure what to call this library. 'Arbitrary Precision Math'
105 is a defacto standard for what this does, but that name was already taken,
106 so I just put an 'M' in front of it ...)
107
108 **************************************************************************
109
110 MAPM LIBRARY NUMERICAL LIMITATIONS:
111
112 A general floating point number is of the form:
113
114 Sn.nnnnnnnnE+yyyy ex: -4.318384739357974916E+6215
115 Sn.nnnnnnnnE-yyyy ex: +8.208237913789131096523645193E-12873
116
117 'S' is the sign, + or -.
118
119 In MAPM, a number (n.nnnn...) may contain up to ( INT_MAX - 1 ) digits.
120
121 For example, an MAPM number with a 16 bit integer may contain 2^15 or 32,767
122 digits. An MAPM number with a 32 bit integer may contain 2^31 or 2,147,483,647
123 digits. All MAPM numbers are stored in RAM, there is no "data on disk" option.
124 So to represent the maximum number of digits on a 32 bit CPU will require
125 greater than 2 Gig of RAM.
126
127 If you have a CPU with 64 bit ints, then the limitation is 2^63 or
128 9,223,372,036,854,775,807. It should be a very long time before computers
129 have this much RAM in them.
130
131 For the exponent (yyyy), the limitations are also INT_MAX and INT_MIN.
132
133 For a 16 bit CPU, the largest number you can represent is approx
134 0.9999999....E+32767. (H)
135
136 For a 16 bit CPU, the smallest number you can represent (other than 0)
137 is approx 0.1E-32767. (L)
138
139 For a 32 bit CPU, the largest number you can represent is approx
140 0.9999999....E+2147483647. (H)
141
142 For a 32 bit CPU, the smallest number you can represent (other than 0)
143 is approx 0.1E-2147483647. (L)
144
145 The limitations for negative numbers are the same as positive numbers.
146
147
148 Real Number Axis
149
150 +------------------------+ --- +--------------------------+
151 | | | | |
152 -H -L 0.0 +L +H
153
154
155
156 MAPM can represent real numbers from -H to -L, 0.0, +L to +H.
157
158 The number of significant digits is typically only limited by available RAM.
159
160 In MAPM, numerical overflows and underflows are not handled very well
161 (actually not at all). There really isn't a clean and portable way to
162 detect integer overflow and underflow. Per K&R C, the result of integer
163 overflow/underflow is implementation dependent. In assembly language, when
164 you add two numbers, you have access to a "carry flag" to see if an overflow
165 occurred. C has no analogous operator to a carry flag.
166
167 It is up to the user to decide if the results are valid for a given operation.
168 In a 32 bit environment, the limit is so large that this is likely not an
169 issue for most typical applications. However, it doesn't take much to overflow
170 a 16 bit int so care should taken in a 16 bit environment.
171
172 The reaction to an integer overflow/underflow is unknown at run-time:
173
174 o) adding 2 large positive numbers may silently roll over to a
175 negative number.
176 o) in some embedded applications an integer overflow/underflow triggers
177 a hardware exception.
178
179 Since I don't have control over where this library could possibly run,
180 I chose to ignore the problem for now. If anyone has some suggestions
181 (that's portable), please let me know.
182
183 **************************************************************************
184
185 KNOWN BUGS : (Other than integer overflow discussed above....) None
186
187 **************************************************************************
188
189 IF YOU ARE IN A HURRY ...
190
191 UNIX: (assumes gcc compiler)
192
193 run make (build library + 4 executables)
194
195 run make -f makefile.osx (for MAC OSX)
196
197 --- OR ---
198
199 run: mklib (this will create the library, lib_mapm.a)
200
201 run: mkdemo (this will create 4 executables, 'calc', 'validate',
202 'primenum', and 'cpp_demo')
203
204
205 DOS / Win NT/9x (in a DOS window for NT/9x):
206
207 see the file 'README.DOS' for instructions.
208
209
210 **************************************************************************
211
212 calc: This is a command line version of an RPN calculator. If you are
213 familiar with RPN calculators, the use of this program will be
214 quite obvious. The default is 30 decimal places but this can be
215 changed with the '-d' command line option. This is not an
216 interactive program, it just computes an expression from the command
217 line. Run 'calc' with no arguments to get a list of the operators.
218
219 compute : (345.2 * 87.33) - (11.88 / 3.21E-2)
220
221 calc 345.2 87.33 x 11.88 3.21E-2 / -
222 result: 29776.22254205607476635514018692
223
224
225 compute PI to 70 decimal places : (6 * arcsin(0.5))
226
227 calc -d70 6 .5 as x
228 result :
229 3.1415926535897932384626433832795028841971693993751058209749445923078164
230
231 calc -d70 -1 ac (arccos(-1) for fastest possible way)
232
233 validate : This program will compare the MAPM math functions to the C
234 standard library functions, like sqrt, sin, exp, etc. This
235 should give the user a good idea that the library is operating
236 correctly. The program will also perform high precision math
237 using known quantities like PI, log(2), etc.
238
239 'validate' also attempts to obtain as much code coverage of the
240 library as is practical. I used 'gcov' (available with the gcc
241 distribution) to test the code coverage. 100% coverage is not
242 obtained, compromises must be made in order to have the program
243 run in a reasonable amount of time.
244
245 primenum: This program will generate the first 10 prime numbers starting
246 with the number entered as an argument.
247
248 Example: primenum 1234567890 will output (actually 1 per line):
249 this took ~3 sec on my Linux PC, a 350MHz PII.
250
251 1234567891, 1234567907, 1234567913, 1234567927, 1234567949,
252 1234567967, 1234567981, 1234568021, 1234568029, 1234568047
253
254
255 **************************************************************************
256
257 To use the library, simply include 'm_apm.h' and link your program
258 with the library, libmapm.a (unix) or mapm.lib (dos).
259
260 Note: If your system creates libraries with a '.a' extension, then the
261 library will be named libmapm.a. (This conforms to typical unix naming
262 conventions).
263
264 Note: If your system creates libraries with a '.lib' extension, then the
265 library will be named mapm.lib.
266
267 For unix builds, you also may need to specify the math library (-lm) when
268 linking. The reason is some of the MAPM functions use an iterative algorithm.
269 When you use an iterative solution, you have to supply an initial guess. I
270 use the standard math library to generate this initial guess. I debated
271 whether this library should be stand-alone, i.e. generate it's own initial
272 guesses with some algorithm. In the end, I decided using the standard math
273 library would not be a big inconvienence and also it was just too tempting
274 having an immediate 15 digits of precision. When you prime the iterative
275 routines with 15 accurate digits, the MAPM functions converge faster.
276
277 See the file 'algorithms.used' to see a description of the algorithms I
278 used in the library. Some I derived on my own, others I borrowed from people
279 smarter than me. Version 2 of the library supports a 'fast' multiplication
280 algorithm. The algorithm used is described in the algorithms.used file. A
281 considerable amount of time went into finding fast algorithms for the
282 library. However, some could possibly be even better. If anyone has a
283 more efficient algorithm for any of these functions, I would like to here
284 from you.
285
286 See the file 'function.ref' to see a description of all the functions in
287 the library and the calling conventions, prototypes, etc.
288
289 See the file 'struct.ref' which documents how I store the numbers internally
290 in the MAPM data structure. This will not be needed for normal use, but it
291 will be very useful if you need to change/add to the existing library.
292
293 **************************************************************************
294
295 USING MAPM IN A MULTI-THREADED APPLICATION :
296
297 Note that the default MAPM library is NOT thread safe. MAPM internal data
298 structures could get corrupted if multiple MAPM functions are active at the
299 same time. The user should guarantee that only one thread is performing
300 MAPM functions. This can usually be achieved by a call to the operating
301 system to obtain a 'semaphore', 'mutex', or 'critical code section' so the
302 operating system will guarantee that only one MAPM thread will be active
303 at a time.
304
305 The necessary function wrappers for thread safe operation can be found in
306 the sub-directory 'multi_thread' (unix) or 'multithd' (Win/Dos). For now,
307 only Microsoft Visual C++ 6.0 is supported.
308
309 **************************************************************************
310
311 QUICK TEMPLATE FOR NORMAL USE :
312
313 The MAPM math is done on a new data type called "M_APM". This is
314 actually a pointer to a structure, but the contents of the structure
315 should never be manipulated: all operations on MAPM entities are done
316 through a functional interface.
317
318 The MAPM routines will automatically allocate enough space in their
319 results to hold the proper number of digits.
320
321 The caller must initialize all MAPM values before the routines can
322 operate on them (including the values intended to contain results of
323 calculations). Once this initialization is done, the user never needs
324 to worry about resizing the MAPM values, as this is handled inside the
325 MAPM routines and is totally invisible to the user.
326
327 The result of a MAPM operation cannot be one of the other MAPM operands.
328 If you want this to be the case, you must put the result into a
329 temporary variable and then assign (m_apm_copy) it to the appropriate operand.
330
331 All of the MAPM math functions begin with m_apm_*.
332
333 There are some predefined constants for your use. In case it's not obvious,
334 these should never appear as a 'result' parameter in a function call.
335
336 The following constants are available : (declared in m_apm.h)
337
338 MM_Zero MM_One MM_Two MM_Three
339 MM_Four MM_Five MM_Ten
340 MM_PI MM_HALF_PI MM_2_PI MM_E
341 MM_LOG_E_BASE_10 MM_LOG_10_BASE_E MM_LOG_2_BASE_E MM_LOG_3_BASE_E
342
343
344 The non-integer constants above (PI, log(2), etc) are accurate to 128
345 decimal places. The file mapmcnst.c contains these constants. I've
346 included 512 digit constants in this file also that are commented out.
347 If you need more than 512 digits, you can simply use the 'calc' program
348 to generate more precise constants (or create more precise constants at
349 run-time in your app). The number of significant digits in the constants
350 should be 6-8 more than the value specified in the #define.
351
352
353 Basic plan of attack:
354
355 (1) get your 'numbers' into M_APM format.
356 (2) do your high precision math.
357 (3) get the M_APM numbers back into a format you can use.
358
359
360 -------- (1) --------
361
362 #include "m_apm.h" /* must be included before any M_APM 'declares' */
363
364 M_APM area_mapm; /* declare your variables */
365 M_APM tmp_mapm;
366 M_APM array_mapm[10]; /* can use normal array notation */
367 M_APM array2d_mapm[10][10];
368
369 area_mapm = m_apm_init() /* init your variables */
370 tmp_mapm = m_apm_init();
371
372 for (i=0; i < M; i++) /* must init every element of the array */
373 array_mapm[i] = m_apm_init();
374
375 for (i=0; i < M; i++)
376 for (j=0; j < N; j++)
377 array2d_mapm[i][j] = m_apm_init();
378
379 /*
380 * there are 3 ways to convert your number into an M_APM number
381 * (see the file function.ref)
382 *
383 * a) literal string (exponential notation OK)
384 * b) long variable
385 * c) double variable
386 */
387
388 m_apm_set_string(tmp_mapm, "5.3286E-7");
389 m_apm_set_long(array_mapm[6], -872253L);
390 m_apm_set_double(array2d_mapm[3][7], -529.4486711);
391
392
393 -------- (2) --------
394
395 do your math ...
396
397 m_apm_add(cc_mapm, aa_mapm, MM_PI);
398 m_apm_divide(bb_mapm, DECIMAL_PLACES, aa_mapm, MM_LOG_2_BASE_E);
399 m_apm_sin(bb_mapm, DECIMAL_PLACES, aa_mapm);
400 whatever ...
401
402
403 -------- (3) --------
404
405 There are 5 total functions for converting an M_APM number into something
406 useful. (See the file 'function.ref' for full function descriptions)
407
408 For these 5 functions, M_APM number -> string is the conversion
409
410 ===================
411 ==== METHOD 1 ==== : floating point values (m_apm_to_string)
412 ===================
413
414 the format will be in scientific (exponential) notation
415
416 output string = [-]n.nnnnnE+x or ...E-x
417
418 where 'n' are digits and the exponent will be always be present,
419 including E+0
420
421 it's easy to convert this to a double:
422
423 double dtmp = atof(out_buffer);
424
425
426 ===================
427 ==== METHOD 2 ==== : floating point values (m_apm_to_fixpt_string)
428 =================== (m_apm_to_fixpt_stringex)
429 (m_apm_to_fixpt_stringexp)
430 the format will be in fixed point notation
431
432 output string = [-]mmm.nnnnnn
433
434 where 'm' & 'n' are digits.
435
436
437 ===================
438 ==== METHOD 3 ==== : integer values (m_apm_to_integer_string)
439 ===================
440
441 the format will simply be digits with a possible leading '-' sign.
442
443 output string = [-]nnnnnn
444
445 where 'n' are digits.
446
447 it's easy to convert this to a long :
448 long mtmp = atol(out_buffer);
449
450 ... or an int :
451 int itmp = atoi(out_buffer);
452
453 Note that if the M_APM number has a fractional portion, the fraction
454 will be truncated and only the integer portion will be output.
455
456
457 char out_buffer[1024];
458
459 m_apm_to_string(out_buffer, DECIMAL_PLACES, mapm_number);
460
461 m_apm_to_fixpt_string(out_buffer, DECIMAL_PLACES, mapm_number);
462
463 m_apm_to_integer_string(out_buffer, mapm_number);
464
465
466 **************************************************************************
467
468 *********************************************************
469 **** NOTES on the fixed point formatting functions ****
470 *********************************************************
471
472 Assume you have the following code:
473
474
475 --> m_apm_set_string(aa_mapm, "2.0E18");
476 --> m_apm_sqrt(bb_mapm, 40, aa_mapm);
477
478 --> m_apm_to_string(buffer, 40, bb_mapm);
479 --> fprintf(stdout,"[%s]\n",buffer);
480
481 --> m_apm_to_fixpt_string(buffer, 40, bb_mapm);
482 --> fprintf(stdout,"[%s]\n",buffer);
483
484
485 It is desired to compute the sqrt(2.0E+18) to
486 40 significant digits. You then want the result
487 output with 40 decimal places. But the output
488 from above is :
489
490 [1.4142135623730950488016887242096980785697E+9]
491 [1414213562.3730950488016887242096980785697000000000]
492
493
494 Why are there 9 '0' in the fixed point formatted string??
495
496 The sqrt calculation computed 40 significant digits relative
497 to the number in EXPONENTIAL format. When the number is
498 output in exponential format, the 40 digits are as expected
499 with an exponent of 'E+9'.
500
501 The same number formatted as fixed point appears to be an
502 error. Remember, we computed 40 significant digits. However,
503 the result has an exponent of '+9'. So, 9 of the digits are
504 needed *before* the decimal point. In our calculation, only
505 31 digits of precision remain from our original 40. We then
506 asked the fixed point formatting function to format 40 digits.
507 Only 31 are left so 9 zeros are used as pad at the end to
508 fulfill the 40 places asked for.
509
510 Keep this in mind if you truly desire more accurate results
511 in fixed point formatting and your result contains a large
512 positive exponent.
513
514 **************************************************************************
515
516 MAPM C++ WRAPPER CLASS:
517
518 Orion Sky Lawlor (olawlor@acm.org) has added a very nice C++ wrapper
519 class to m_apm.h. This C++ class will have no effect if you just use
520 a normal C compiler. The library will operate as before with no user
521 impacts.
522
523 For now, I recommend compiling the library as 'C'. The library will
524 compile as a C++ library, but then it is likely that you would not
525 be able to use the library in a straight C application. Since the C++
526 wrapper class works very nicely as is, there is no pressing need to compile
527 the library as C++.
528
529 See the file 'cpp_function.ref' to see a description of how to use
530 the MAPM class.
531
532 To compile and link the C++ demo program: (assuming the library is
533 already built)
534
535 UNIX:
536
537 g++ cpp_demo.cpp lib_mapm.a -s -o cpp_demo -lm
538
539 GCC for DOS: (gxx (or g++) is the C++ compiler)
540
541 gxx cpp_demo.cpp lib_mapm.a -s -o cpp_demo.exe -lm
542
543
544 Using the C++ wrapper allows you to do things like:
545
546 // Compute the factorial of the integer n
547
548 MAPM factorial(MAPM n)
549 {
550 MAPM i;
551 MAPM product = 1;
552 for (i=2; i <= n; i++)
553 product *= i;
554 return product;
555 }
556
557
558 The syntax is the same as if you were just writing normal code, but all
559 the computations will be performed with the high precision math library,
560 using the new 'datatype' MAPM.
561
562 The default precision of the computations is as follows:
563
564 Addition, subtraction, and multiplication will maintain ALL significant
565 digits.
566
567 All other operations (divide, sin, etc) will use the following rules:
568
569 1) if the operation uses only one input value [y = sin(x)], the result 'y'
570 will be the same precision as 'x', with a minimum of 30 digits if 'x' is
571 less than 30 digits.
572
573 2) if the operation uses two input values [z = atan2(y,x)], the result 'z'
574 will be the max digits of 'x' or 'y' with a minimum of 30.
575
576 The default precision is 30 digits. You can change the precision at
577 any time with the function 'm_apm_cpp_precision'. (See function.ref)
578
579 ----> m_apm_cpp_precision(80);
580
581 will result in all operations being accurate to a minimum of 80 significant
582 digits. If any operand contains more than the minimum number of digits, then
583 the result will contain the max number of digits of the operands.
584
585
586 NOTE!: Some real life use with the C++ wrapper has revealed a certain
587 tendency for a program to become quite slow after many iterations
588 (like in a for/while loop). After a little debug, the reason
589 became clear. Remember that multiplication will maintain ALL
590 significant digits :
591
592 20 digit number x 20 digit number = 40 digits
593 40 digit number x 40 digit number = 80 digits
594 80 digit number x 80 digit number = 160 digits
595 etc.
596
597 So after numerous iterations, the number of significant digits
598 was growing without bound. The easy way to fix the problem is
599 to simply *round* your result after a multiply or some other
600 complex operation. For example:
601
602 #define MAX_DIGITS 256
603
604 p1 = (p0 * sin(b1) * exp(1 + u1)) / sqrt(1 + b1);
605 p1 = p1.round(MAX_DIGITS);
606
607 If you 'round' as shown here, your program will likely be
608 nearly as fast as a straight 'C' version.
609
610
611 NOTE #2!
612
613 Reference the following code snippet:
614
615 ...
616
617 MAPM pi1, pi2;
618 char obuf[256];
619
620 m_apm_cpp_precision(62);
621
622 pi1 = 2 * asin("1");
623 pi2 = 2 * asin(1.0);
624
625 pi1.toString(obuf, 60); printf("PI1 = [%s] \n",obuf);
626 pi2.toString(obuf, 60); printf("PI2 = [%s] \n",obuf);
627
628 ...
629
630 On my system, the output is :
631
632 PI1 = [3.141592653589793238462643383279502884197169399375105820974945E+0]
633 PI2 = [3.141592653589790000000000000000000000000000000000000000000000E+0]
634
635
636 PI2 only has 15 significant digits! This is due to how the second
637 asin is called. It is called with a 'double' as the argument, hence
638 the compiler will use the default double asin function from the
639 standard library. This is likely not the intent but this would be
640 easy to miss if this was a complex calculation and we didn't know
641 the 'right' answer.
642
643 In order to force the use of the overloaded MAPM functions, call the
644 MAPM functions with a quoted string as the argument (if the argument
645 is a constant and not a variable).
646
647 This would also work (though it seems less elegant ...) :
648
649 MAPM t = 1;
650 pi2 = 2 * asin(t);
651
652 -----------
653
654 If you have any questions or problems with the C++ wrapper, please let
655 me know. I am not very C++ proficient, but I'd still like to know about any
656 problems. Orion Sky Lawlor (olawlor@acm.org) is the one who implemented
657 the MAPM class, so he'll have to resolve any real hardcore problems, if you
658 have any.
659
660 **************************************************************************
661
662 TESTING :
663
664 Testing the library was interesting. How do I know it's right? Since I
665 test the library against the standard C runtime math library (see below)
666 I have high confidence that the MAPM library is giving correct results.
667 The logic here is the basic algorithms are independent of the number of
668 digits calculated, more digits just takes longer.
669
670 The MAPM library has been tested in the following environments :
671
672 Linux i486 / gcc 2.7.2.3, gcc 2.95.2
673 Linux i586 / gcc 2.95.3, gcc 3.3.6
674 Linux i686 / gcc 2.91.66, gcc 2.95.2, gcc 2.95.3, gcc 3.0.4, gcc 3.2.3
675 Linux i686 / gcc 3.3.6, gcc 3.4.6, gcc 4.2.4
676 Linux i686 / Intel Linux C/C++ Compiler Verison 7.0 / 8.1
677 FreeBSD 4.1 / gcc 2.95.1
678 FreeBSD 4.8 / gcc 2.95.4
679 FreeBSD 5.x / gcc 2.95.2, gcc 2.95.3
680 Redhat Linux 8.2 / gcc 3.2
681 RHEL4 / gcc 3.4.3
682 HP-UX 9.x /gcc 2.5.8
683 HP-UX 10.x / gcc 2.95.2
684 Sun 5.5.1 (output from uname), gcc 3.1.1
685 Sun Solaris 2.6 / gcc 2.95.1, gcc 2.95.3, gcc 3.2.3
686 MAC OSX / gcc ?
687 DOS 5.0 using GCC 2.8.1 for DOS
688 DOS 5.0 using GCC 2.95.2 for DOS
689 DOS ??? using Borland Turbo C++ 3.0
690 WIN NT+SP5 using Borland C++ 5.02 IDE, 5.2 & 5.5 command line.
691 WIN 2000 using National Instruments LabWindows CVI 6.0
692 WIN98 using Borland C++ 5.5 command line.
693 WIN98 & NT & 2000 & XP using LCC-WIN32 Ver 3.2, 3.3
694 WIN98 & NT using Watcom C 11.x
695 WIN95 & NT using Open Watcom 1.0
696 WIN95 & WIN98 using MINGW-32 version mingw-1.0.1-20010726
697 WIN95 & WIN2000 using DEV-CPP 5.0 Beta 8, 4.9.8.0
698 MINGW-32 with gcc 3.2 (mingw special 20020817-1)
699 MINGW-32 with gcc 3.2.3 (mingw special 20030504-1)
700 WINXP & MINGW-32 with gcc 3.4.5
701 WINXP & Digital Mars Compiler 8.49
702 WIN?? using Metrowerks CodeWarrior Pro 7.0 for Windows
703 DOS 5.0 using Microsoft C 5.1 and 8.00c (16 bit EXEs)
704 WIN98 & NT using Microsoft Visual C++ 6.0
705 WIN98 & NT using Microsoft Visual C++ 7.x (VS.NET 2003 except for
706 known compiler bug C2676)
707
708
709
710 As a general rule, when calculating a quantity to a given number of decimal
711 places, I calculated 4-6 extra digits and then rounded the result to what was
712 asked for. I decided to be conservative and give a correct answer rather than
713 to be faster and possibly have the last 2-3 digits in error. Also, some of
714 the functions call other functions (calculating arc-cos will call cos, log
715 will call exp, etc.) so I had to calculate a few extra digits in each iteration
716 to guarantee the loops terminated correctly.
717
718 1) I debugged the 4 basic math operations. I threw numerous test cases at
719 each of the operations until I knew they were correct.
720
721 Also note that the math.h type functions all call the 4 basic operations
722 numerous times. So if all the math.h functions work, it is highly
723 probable the 4 basic math operations work also.
724
725 2) 'math.h' type functions.
726
727 SQRT: Not real hard to check. Single stepping through the iterative
728 loop showed it was always converging to the sqrt.
729
730 CBRT: Similar to sqrt, single stepping through the iterative loop
731 showed it was always converging to the cube root.
732
733 EXP: I wrote a separate algorithm which expanded the Taylor series
734 manually and compared the results against the library.
735
736 POW: Straightforward since this just calls 'EXP'.
737
738 LOG: I wrote a separate algorithm which expanded the Taylor series
739 manually and compared the results against the library. This
740 took a long time to execute since the normal series converges
741 VERY slowly for the log function. This is why the LOG function
742 uses an iterative algorithm.
743
744 LOG10: Straightforward since this just calls 'LOG'.
745
746 SIN/COS: I wrote a separate algorithm which expanded the Taylor series
747 manually and compared the results against the library.
748
749 TAN: Straightforward since this just calls 'SIN' and 'COS'.
750
751 ARC-x: Single stepping through the iterative loop showed the arc
752 family of functions were always converging. Also used these
753 to compute PI. The value of PI is now known to many, many
754 digits. I computed PI to 1000+ digits by computing:
755
756 6 * arcsin(0.5) and 4 * arctan(1) and 3 * arccos(0.5)
757
758 and compared the output to the published 'real' values of PI.
759
760 The arc family of functions exercise considerable portions
761 of the library.
762
763 HYPERBOLIC: The hyperbolic functions just use exp, log, and the 4 basic
764 math operations. All of these functions simply use other
765 existing functions in the library.
766
767 FINALLY: Run the program 'validate'. This program compares the first
768 13-14 significant digits of the standard C library against
769 the MAPM library. If this program passes, you can feel
770 confident that the MAPM library is giving correct results.
771
772 **************************************************************************