⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 library

📁 早期freebsd实现
💻
字号:
	USING THE ARBITRARY PRECISION ROUTINES IN A C PROGRAMPart of the calc release consists of an arbitrary precision math library.This 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 library is called libmath.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.-------------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 the include files needed to buildlibcalc.a along with the library itself (and the lint libraryllib-lcalc.ln, if made) are installed into ${LIBDIR}.External programgs may want to compile with:		-I${LIBDIR} -L${LIBDIR} -lcalc--------------ERROR HANDLING--------------You 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.---------------OUTPUT ROUTINES---------------The output from the routines in the 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)There are two types of comparisons you can make on ZVALUEs.  This is whetheror not they are equal, or the ordering on size of the numbers.  The zcmpfunction tests whether two ZVALUEs are equal, returning TRUE if they differ.The zrel function tests the relative sizes of two ZVALUEs, returning -1 ifthe first one is smaller, 0 if they are the same, and 1 if the first oneis larger.---------------USING FRACTIONS---------------The arbitrary precision fractional routines define a structure called NUMBER.This is defined in qmath.h.  A NUMBER contains two ZVALUEs for the numeratorand denominator of a fraction, and a count of the number of uses there arefor this NUMBER.  The numerator and denominator are always in lowest terms,and the sign of the number is contained in the numerator.  The denominatoris always positive.  If the NUMBER is an integer, the denominator has thevalue 1.Unlike ZVALUEs, NUMBERs are passed using pointers, and pointers to them arereturned by functions.  So the basic type for using fractions is not really(NUMBER), but is (NUMBER *).  NUMBERs are allocated using the qalloc routine.This returns a pointer to a number which has the value 1.  Because of thespecial property of a ZVALUE of 1, the numerator and denominator of thisreturned value can simply be overwritten with new ZVALUEs without needingto free them first.  The following illustrates this:	NUMBER *q;	q = qalloc();	itoz(55L, &q->num);A better way to create NUMBERs with particular values is to use the itoq,iitoq, or atoq functions.  Using itoq makes a long value into a NUMBER,using iitoq makes a pair of longs into the numerator and denominator of aNUMBER (reducing them first if needed), and atoq converts a string representinga number into the corresponding NUMBER.  The atoq function accepts input inintegral, fractional, real, or exponential formats.  Examples of allocatingnumbers are:	NUMBER *q1, *q2, *q3;	q1 = itoq(66L);	q2 = iitoq(2L, 3L);	q3 = atoq("456.78");Also unlike ZVALUEs, NUMBERs are quickly copied.  This is because they containa link count, which is the number of pointers there are to the NUMBER.  Theqlink macro is used to copy a pointer to a NUMBER, and simply incrementsthe link count and returns the same pointer.  Since it is a macro, theargument should not be a function call, but a real pointer variable.  Theqcopy routine will actually make a new copy of a NUMBER, with a new linkcount of 1.  This is not usually needed.NUMBERs are deleted using the qfree routine.  This decrements the link countin the NUMBER, and if it reaches zero, then it will deallocate both ofthe ZVALUEs contained within the NUMBER, and then puts the NUMBER structureonto a free list for quick reuse.  The following is an example of allocatingNUMBERs, copying them, adding them, and finally deleting them again.	NUMBER *q1, *q2, *q3;	q1 = itoq(111L);	q2 = qlink(q1);	q3 = qadd(q1, q2);	qfree(q1);	qfree(q2);	qfree(q3);Because of the passing of pointers and the ability to copy numbers easily,you might wish to use the rational number routines even for integralcalculations.  They might be slightly slower than the raw integral routines,but are more convenient to program with.The prototypes for the fractional routines are defined in qmath.h.Many of the definitions for integer functions parallel the ones definedin zmath.h.  But there are also functions used only for fractions.Examples of these are qnum to return the numerator, qden to return thedenominator, qint to return the integer part of, qfrac to return thefractional part of, and qinv to invert a fraction.There are some transcendental functions in the library, such as sin and cos.These cannot be evaluated exactly as fractions.  Therefore, they acceptanother argument which tells how accurate you want the result.  This is an"epsilon" value, and the returned value will be within that quantity ofthe correct value.  This is usually an absolute difference, but for somefunctions (such as exp), this is a relative difference.  For example, tocalculate sin(0.5) to 100 decimal places, you could do:	NUMBER *q, *ans, *epsilon;	q = atoq("0.5");	epsilon = atoq("1e-100");	ans = qsin(q, epsilon);There are many convenience macros similar to the ones for ZVALUEs which cangive quick information about NUMBERs.  In addition, there are some new onesapplicable to fractions.  These are all defined in qmath.h.  Some of thesemacros are:	qiszero(q)	(number is zero)	qisneg(q)	(number is negative)	qispos(q)	(number is positive)	qisint(q)	(number is an integer)	qisfrac(q)	(number is fractional)	qisunit(q)	(number is 1 or -1)	qisone(q)	(number is 1)The comparisons for NUMBERs are similar to the ones for ZVALUEs.  You use theqcmp and qrel functions.There are four predefined values for fractions.  You should qlink them whenyou want to use them.  These are _qzero_, _qone_, _qnegone_, and _qonehalf_.These have the values 0, 1, -1, and 1/2.  An example of using them is:	NUMBER *q1, *q2;	q1 = qlink(&_qonehalf_);	q2 = qlink(&_qone_);---------------------USING COMPLEX NUMBERS---------------------The arbitrary precision complex arithmetic routines define a structurecalled COMPLEX.  This is defined in cmath.h.  This contains two NUMBERsfor the real and imaginary parts of a complex number, and a count of thenumber of links there are to this COMPLEX number.The complex number routines work similarly to the fractional routines.You can allocate a COMPLEX structure using comalloc (NOT calloc!).You can construct a COMPLEX number with desired real and imaginaryfractional parts using qqtoc.  You can copy COMPLEX values using clinkwhich increments the link count.  And you free a COMPLEX value using cfree.The following example illustrates this:	NUMBER *q1, *q2;	COMPLEX *c1, *c2, *c3;	q1 = itoq(3L);	q2 = itoq(4L);	c1 = qqtoc(q1, q2);	qfree(q1);	qfree(q2);	c2 = clink(c1);	c3 = cmul(c1, c2);	cfree(c1);	cfree(c2);	cfree(c3);As a shortcut, when you want to manipulate a COMPLEX value by a real value,you can use the caddq, csubq, cmulq, and cdivq routines.  These accept oneCOMPLEX value and one NUMBER value, and produce a COMPLEX value.There is no direct routine to convert a string value into a COMPLEX value.But you can do this yourself by converting two strings into two NUMBERS,and then using the qqtoc routine.COMPLEX values are always returned from these routines.  To split out thereal and imaginary parts into normal NUMBERs, you can simply qlink thetwo components, as shown in the following example:	COMPLEX *c;	NUMBER *rp, *ip;	c = calloc();	rp = qlink(c->real);	ip = qlink(c->imag);There are many macros for checking quick things about complex numbers,similar to the ZVALUE and NUMBER macros.  In addition, there are someonly used for complex numbers.  Examples of macros are:	cisreal(c)	(number is real)	cisimag(c)	(number is pure imaginary)	ciszero(c)	(number is zero)	cisrunit(c)	(number is 1 or -1)	cisiunit(c)	(number is i or -i)	cisunit(c)	(number is 1, -1, i, or -i)There is only one comparison you can make for COMPLEX values, and that isfor equality.  The ccmp function returns TRUE if two complex numbers differ.There are three predefined values for complex numbers.  You should clinkthem when you want to use them.  They are _czero_, _cone_, and _conei_.These have the values 0, 1, and i.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -