📄 library
字号:
USING THE ARBITRARY PRECISION ROUTINES IN A C PROGRAMPart of the calc release consists of an arbitrary precision math link library.This link library is used by the calc program to perform its own calculations.If you wish, you can ignore the calc program entirely and call the arbitraryprecision math routines from your own C programs.The link library is called libcalc.a, and provides routines to handle arbitraryprecision arithmetic with integers, rational numbers, or complex numbers.There are also many numeric functions such as factorial and gcd, alongwith some transcendental functions such as sin and exp.Take a look at the sample sub-directory. It contains a few simpleexamples of how to use libcalc.a that might be helpful to look atafter you have read this file.------------------FIRST THINGS FIRST------------------................................................................................ .. You MUST call libcalc_call_me_first() prior to using libcalc lib functions! .. ................................................................................The function libcalc_call_me_first() takes no args and returns void. Youneed call libcalc_call_me_first() only once.-------------INCLUDE FILES-------------To use any of these routines in your own programs, you need to include theappropriate include file. These include files are: zmath.h (for integer arithmetic) qmath.h (for rational arithmetic) cmath.h (for complex number arithmetic)You never need to include more than one of the above files, even if you wishto use more than one type of arithmetic, since qmath.h automatically includeszmath.h, and cmath.h automatically includes qmath.h.The prototypes for the available routines are listed in the above includefiles. Some of these routines are meant for internal use, and so aren'tconvenient for outside use. So you should read the source for a routineto see if it really does what you think it does. I won't guarantee thatobscure internal routines won't change or disappear in future releases!When calc is installed, all of libraries are installed into ${LIBDIR}.All of the calc header files are installed under ${INCDIRCALC}.If CALC_SRC is defined, then the calc header files will assume thatthey are in or under the current directory. However, most externalprograms most likely will not be located under calc'c source tree.External programs most likely want to use the installed calc headerfiles under ${INCDIRCALC}. External programs most likely NOT wantto define CALC_SRC.External programs may want to compile with: -L${LIBDIR} -lcalcIf custom functions are also used, they may want to compile with: -L${LIBDIR} -lcalc -lcustcalcThe CALC_SRC symbol should NOT be defined by default. However if you arefeeling pedantic you may want to force CALC_SRC to be undefined: -UCALC_SRCas well.--------------ERROR HANDLING--------------Your program MUST provide a function called math_error. This is called bythe math routines on an error condition, such as malloc failures or adivision by zero. The routine is called in the manner of printf, with aformat string and optional arguments. (However, none of the low level mathroutines currently uses formatting, so if you are lazy you can simply usethe first argument as a simple error string.) For example, one of theerror calls you might expect to receive is: math_error("Division by zero");Your program can handle errors in basically one of two ways. Firstly, itcan simply print the error message and then exit. Secondly, you can makeuse of setjmp and longjmp in your program. Use setjmp at some appropriatelevel in your program, and use longjmp in the math_error routine to returnto that level and so recover from the error. This is what the calc programdoes.For convenience, the link library libcalc.a contains a math_error routine.By default, this routine simply prints a message to stderr and then exits.By simply linking in this link library, any calc errors will result in aerror message on stderr followed by an exit.External programs that wish to use this math_error may want to compile with: -I${LIBDIR} -L${LIBDIR} -lcalcIf one sets up calc_jmp_buf, and then sets calc_jmp to non-zero thenthis routine will longjmp back (with the value of calc_jmp) instead.In addition, the last calc error message will be found in calc_error;this error is not printed to stderr. The calc error message willnot have a trailing newline.For example: #include <setjmp.h> extern jmp_buf calc_jmp_buf; extern int calc_jmp; extern char *calc_error; int error; ... if ((error = setjmp(calc_jmp_buf)) != 0) { /* reinitialize calc after a longjmp */ reinitialize(); /* report the error */ printf("Ouch: %s\n", calc_error); } calc_jmp = 1;---------------OUTPUT ROUTINES---------------The output from the routines in the link library normally goes to stdout. Youcan divert that output to either another FILE handle, or else to a string.Read the routines in zio.c to see what is available. Diversions can benested.You use math_setfp to divert output to another FILE handle. Callingmath_setfp with stdout restores output to stdout.Use math_divertio to begin diverting output into a string. Callingmath_getdivertedio will then return a string containing the output, andclears the diversion. The string is reallocated as necessary, but sinceit is in memory, there are obviously limits on the amount of data that canbe diverted into it. The string needs freeing when you are done with it.Calling math_cleardiversions will clear all the diversions to strings, andis useful on an error condition to restore output to a known state. Youshould also call math_setfp on errors if you had changed that.If you wish to mix your own output with numeric output from the math routines,then you can call math_chr, math_str, math_fill, math_fmt, or math_flush.These routines output single characters, output null-terminated strings,output strings with space filling, output formatted strings like printf, andflush the output. Output from these routines is diverted as described above.You can change the default output mode by calling math_setmode, and you canchange the default number of digits printed by calling math_setdigits. Theseroutines return the previous values. The possible modes are described inzmath.h.--------------USING INTEGERS--------------The arbitrary precision integer routines define a structure called a ZVALUE.This is defined in zmath.h. A ZVALUE contains a pointer to an array ofintegers, the length of the array, and a sign flag. The array is allocatedusing malloc, so you need to free this array when you are done with aZVALUE. To do this, you should call zfree with the ZVALUE as an argument(or call freeh with the pointer as an argument) and never try to free thearray yourself using free. The reason for this is that sometimes the pointerpoints to one of two statically allocated arrays which should NOT be freed.The ZVALUE structures are passed to routines by value, and are returnedthrough pointers. For example, to multiply two small integers together,you could do the following: ZVALUE z1, z2, z3; itoz(3L, &z1); itoz(4L, &z2); zmul(z1, z2, &z3);Use zcopy to copy one ZVALUE to another. There is no sharing of arraysbetween different ZVALUEs even if they have the same value, so you MUSTuse this routine. Simply assigning one value into another will causeproblems when one of the copies is freed. However, the special ZVALUEvalues _zero_ and _one_ CAN be assigned to variables directly, since theirvalues of 0 and 1 are so common that special checks are made for them.For initial values besides 0 or 1, you need to call itoz to convert a longvalue into a ZVALUE, as shown in the above example. Or alternatively,for larger numbers you can use the atoz routine to convert a string whichrepresents a number into a ZVALUE. The string can be in decimal, octal,hex, or binary according to the leading digits.Always make sure you free a ZVALUE when you are done with it or when youare about to overwrite an old ZVALUE with another value by passing itsaddress to a routine as a destination value, otherwise memory will belost. The following shows an example of the correct way to free memoryover a long sequence of operations. ZVALUE z1, z2, z3; z1 = _one_; atoz("12345678987654321", &z2); zadd(z1, z2, &z3); zfree(z1); zfree(z2); zsquare(z3, &z1); zfree(z3); itoz(17L, &z2); zsub(z1, z2, &z3); zfree(z1); zfree(z2); zfree(z3);There are some quick checks you can make on integers. For example, whetheror not they are zero, negative, even, and so on. These are all macrosdefined in zmath.h, and should be used instead of checking the parts of theZVALUE yourself. Examples of such checks are: ziseven(z) (number is even) zisodd(z) (number is odd) ziszero(z) (number is zero) zisneg(z) (number is negative) zispos(z) (number is positive) zisunit(z) (number is 1 or -1) zisone(z) (number is 1) zisnegone(z) (number is -1) zistwo(z) (number is 2) zisabstwo(z) (number is 2 or -2) zisabsleone(z) (number is -1, 0 or 1) zislezero(z) (number is <= 0) zisleone(z) (number is <= 1) zge16b(z) (number is >= 2^16) zge24b(z) (number is >= 2^24) zge31b(z) (number is >= 2^31) zge32b(z) (number is >= 2^32) zge64b(z) (number is >= 2^64)Typically the largest unsigned long is typedefed to FULL. The followingmacros are useful in dealing with this data type: MAXFULL (largest positive FULL value) MAXUFULL (largest unsigned FULL value)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -