www.pudn.com > calc.rar > i5R.c


/* i5R.c */ 
/* programs for doing arithmetic with MPR's. */ 
 
#include  
#include  
#include  
#include "integer.h" 
#include "fun.h" 
 
#ifdef DEBUG 
extern long int nettbytes; 
#endif 
 
MPR *BUILDMPR( ) 
/* 
 * mallocs space for an MPR. 
 */ 
{ 
	MPR *Mptr; 
 
	Mptr = (MPR *)mmalloc((USL)sizeof(MPR)); 
	return (Mptr); 
} 
 
void FREEMPR(MPR *Mptr) 
/* 
 * deallocates the space alloted for the MPR Mptr. 
 */ 
{ 
	if (Mptr == NULL) 
		return; 
	FREEMPI(Mptr->N); 
	FREEMPI(Mptr->D); 
	ffree ((char *)Mptr, sizeof(MPR)); 
	return; 
} 
 
MPR *COPYR(MPR *Aptr) 
/* 
 * returns a pointer to a copy of *Aptr. 
 */ 
{ 
	MPR *Bptr; 
	Bptr = BUILDMPR(); 
	Bptr->N = COPYI(Aptr->N); 
	Bptr->D = COPYI(Aptr->D); 
	return (Bptr); 
} 
 
unsigned int EQUALR(MPR *Aptr, MPR *Bptr) 
/* 
 * returns 1 if *Aptr = *Bptr, 0 otherwise. 
 */ 
{ 
	if (EQUALI(Aptr->N, Bptr->N) * EQUALI(Aptr->D, Bptr->D)) 
		return (1); 
	else 
		return (0); 
} 
 
MPR *MINUSR(MPR *Aptr) 
/* 
 * *Bptr = -(*Aptr). 
 */ 
{ 
	MPR *Bptr; 
 
	Bptr = BUILDMPR(); 
	Bptr->N = MINUSI(Aptr->N); 
	Bptr->D = COPYI(Aptr->D); 
	return (Bptr); 
} 
 
MPR *RATIOI(MPI *Aptr, MPI *Bptr) 
/* 
 * *Cptr = (*Aptr) / (*Bptr). 
 */ 
{ 
	MPI *G; 
	MPR *Cptr; 
 
	Cptr = BUILDMPR(); 
	G = GCD(Aptr, Bptr); 
	Cptr->N = INT(Aptr, G); 
	Cptr->D = INT(Bptr, G); 
	if ((Cptr->D)->S == -1) 
	{ 
		(Cptr->D)->S = 1; 
		(Cptr->N)->S = -((Cptr->N)->S); 
	} 
	FREEMPI(G); 
	return (Cptr); 
} 
 
unsigned long LENGTHR(MPR *Mptr) 
/* 
 * returns the sum of the lengths of numerator and denominator + 1, 
 * if Mptr is not an integer, otherwise returns the length of *Mptr. 
 */ 
{ 
	if ((Mptr->D)->D || (Mptr->D)->V[0] > 1) 
		return (LENGTHI(Mptr->N) + LENGTHI(Mptr->D) + 1); 
	else 
		return (LENGTHI(Mptr->N)); 
} 
 
MPR *FINPUTR(FILE *f, unsigned int *uptr) 
/* 
 * Converts the ratio of two decimal inputs from stream into an MPR.  
 * *uptr =  0 if input fails, 1 if successful. 
 */ 
{ 
	int t,  c; 
	MPI *G, *H; 
	MPR *Aptr; 
 
	G = FINPUTI(f, uptr); 
	if (*uptr == 0) 
	{ 
		FREEMPI(G); 
		return ZEROR(); 
	} 
	t = c = fgetc(f); 
	while (c == ' ') 
		c = fgetc(f); 
	if (c != '\n' && c != '/' && c != 'i'  && c != '+' && c != '-' && (c < '0' || c > '9')) 
	{ 
		printf("inside INPUTSR: illegal character %c encountered:\n", c); 
		FREEMPI(G); 
		*uptr = 0; 
		return ZEROR(); 
	} 
	if (c == '/') 
        { 
	 	H = FINPUTI(f, uptr); 
		if (*uptr == 0) 
		{ 
			FREEMPI(G); 
			FREEMPI(H); 
			return ZEROR(); 
		} 
		else if (H->S == 0) 
		{ 
			printf("zero denominator entered\n"); 
			*uptr = 0; 
			FREEMPI(G); 
			FREEMPI(H); 
			return ZEROR(); 
		} 
		else 
		{ 
			Aptr = RATIOI(G, H); 
			FREEMPI(G); 
			FREEMPI(H); 
			c = fgetc(f); 
			if (c != '\n') 
				ungetc(c, f); 
		} 
	} 
        else  
	{ 
		if (c != '\n' || t == ' ') 
			ungetc(c, f); 
		Aptr = BUILDMPR(); 
		Aptr->N = G; 
		Aptr->D = ONEI(); 
	} 
	return (Aptr); 
} 
 
MPR *INPUTR(unsigned int *uptr) 
{ 
	return FINPUTR(stdin, uptr); 
} 
 
MPR *INPUTSR(char **ptr, unsigned int *uptr) 
/* 
 * Converts the ratio of two decimal inputs from stream into an MPR.  
 * *uptr = 0 if input fails, 1 if successful. For use with complex rationals. 
 */ 
{ 
	char t; 
	MPI *G, *H; 
	MPR *Aptr; 
 
	G = INPUTSI(ptr, uptr); 
	if (*uptr == 0)  
	{ 
		FREEMPI(G); 
		return ZEROR(); 
	} 
	t = **ptr; 
	while (**ptr == ' ') 
		(*ptr)++; 
	if (**ptr != '\0' && **ptr != '/' && **ptr != 'i'  && **ptr != '+' && **ptr != '-' && (**ptr < '0' || **ptr > '9')) 
	{ 
		printf("inside INPUTSR: illegal character %c entered:\n", **ptr); 
		*uptr = 0; 
		FREEMPI(G); 
		return ZEROR(); 
	} 
	else if (**ptr == '/') 
	{ 
		(*ptr)++; 
		H = INPUTSI(ptr, uptr); 
		if (*uptr == 0) 
		{ 
			FREEMPI(G); 
			FREEMPI(H); 
			return ZEROR(); 
		} 
		else if (H->S == 0) 
		{ 
			printf("zero denominator entered\n"); 
			*uptr = 0; 
			FREEMPI(G); 
			FREEMPI(H); 
			return ZEROR(); 
		} 
		else 
		{ 
			Aptr = RATIOI(G, H); 
			FREEMPI(G); 
			FREEMPI(H); 
		} 
	} 
	else 
	{ 
		if (t == ' ') 
			(*ptr)--; 
		Aptr = BUILDMPR(); 
		Aptr->N = G; 
		Aptr->D = ONEI(); 
	} 
	return (Aptr); 
} 
 
void FPRINTR(FILE *outfile, MPR *Aptr) 
/* 
 * prints the MPR *Aptr as (Aptr->N)/(Aptr->D).  
 */ 
{ 
	FPRINTI(outfile, Aptr->N); 
	if ((Aptr->D)->D || (Aptr->D)->V[0] > 1) 
	{ 
		fprintf(outfile, "/"); 
		FPRINTI(outfile, Aptr->D); 
	} 
	return; 
} 
 
void PRINTR(MPR *Aptr) 
{ 
	FPRINTR(stdout, Aptr); 
	return; 
} 
 
MPR *ZEROR() 
/* 
 * Returns the MPR ZERO. 
 */ 
{ 
	MPR *Eptr; 
 
	Eptr = BUILDMPR(); 
	Eptr->N = ZEROI(); 
	Eptr->D = ONEI(); 
	return Eptr; 
} 
 
MPR *ONER() 
/* 
 * Returns the MPR ONE. 
 */ 
{ 
	MPR *Eptr; 
 
	Eptr = BUILDMPR(); 
	Eptr->N = ONEI(); 
	Eptr->D = ONEI(); 
	return Eptr; 
} 
 
MPR *TWOR() 
     /* Returns the MPR TWO */ 
{ 
  MPR *Eptr; 
  Eptr = BUILDMPR(); 
  Eptr->N = TWOI(); 
  Eptr->D = ONEI(); 
  return Eptr; 
} 
MPR *MINUS_ONER() 
/* 
 * Returns the MPR MINUS_ONE. 
 */ 
{ 
	MPR *Eptr; 
 
	Eptr = BUILDMPR(); 
	Eptr->N = MINUS_ONEI(); 
	Eptr->D = ONEI(); 
	return (Eptr); 
} 
 
void SPRINTR(char *buffer, MPR *Aptr) 
/* 
 * prints the MPR *Aptr as (Aptr->N)/(Aptr->D).  
 */ 
{ 
	SPRINTI(buffer, Aptr->N); 
	if ((Aptr->D)->D || (Aptr->D)->V[0] > 1) 
	{ 
		buffer += strlen(buffer); 
		sprintf(buffer, "/"); 
		SPRINTI(buffer + 1, Aptr->D); 
	} 
	return; 
} 
 
void FPRINTDR(FILE *outfile, unsigned int d, MPR *Mptr) 
/* 
 * prints *Mptr truncated to d (>= 1) decimal places to outfile. 
 */ 
{ 
	int s; 
	unsigned int i; 
	unsigned long l; 
	MPI *F, *G, *TempI; 
	MPR *X, *TempR; 
 
	s = (Mptr->N)->S; 
	X = COPYR(Mptr); 
	if (s == -1) 
	{ 
		TempR = X; 
		X = MINUSR(X);	 
		FREEMPR(TempR); 
	} 
	G = INT0(X->N, X->D); 
	if (s == -1) 
		fprintf(outfile, "-"); 
	FPRINTI(outfile, G); 
	fprintf(outfile, "."); 
	FREEMPI(G); 
	G = MOD0(X->N, X->D); 
	F = POWER_I(10L, d); 
	TempI = F; 
	F = MULTI(F, G); 
	FREEMPI(TempI); 
	TempI = G; 
	G = INT0(F, X->D); 
	FREEMPI(F); 
	FREEMPI(TempI); 
	l = LENGTHI(G); 
	for (i = 1; i <= d - l; i++) 
		fprintf(outfile, "0"); 
	FPRINTI(outfile, G); 
	FREEMPI(G); 
	FREEMPR(X); 
	return; 
} 
 
void PRINTDR(unsigned int d, MPR *Mptr) 
/* 
 * prints *Mptr truncated to d (>= 1) decimal places to stdout. 
 */ 
{ 
	FPRINTDR(stdout, d, Mptr); 
	return; 
} 
 
void SPRINTDR(char *buffer, unsigned int d, MPR *Mptr) 
/* 
 * prints *Mptr truncated to d (>= 1) decimal places to buffer. 
 */ 
{ 
	int s; 
	unsigned int i; 
	unsigned long l; 
	MPI *F, *G, *TempI; 
	MPR *X, *TempR; 
 
	s = (Mptr->N)->S; 
	X = COPYR(Mptr); 
	if (s == -1) 
	{ 
		TempR = X; 
		X = MINUSR(X);	 
		FREEMPR(TempR); 
	} 
	G = INT0(X->N, X->D); 
	if (s == -1) 
	{ 
		sprintf(buffer, "-"); 
		buffer++; 
	} 
	SPRINTI(buffer, G); 
	buffer += strlen(buffer); 
	sprintf(buffer, "."); 
	buffer++; 
	FREEMPI(G); 
	G = MOD0(X->N, X->D); 
	F = POWER_I(10L, d); 
	TempI = F; 
	F = MULTI(F, G); 
	FREEMPI(TempI); 
	TempI = G; 
	G = INT0(F, X->D); 
	FREEMPI(TempI); 
	FREEMPI(F); 
	l = LENGTHI(G); 
	for (i = 1; i <= d - l; i++) 
	{ 
		sprintf(buffer, "0"); 
		buffer++; 
	} 
	SPRINTI(buffer, G); 
	FREEMPI(G); 
	FREEMPR(X); 
} 
 
unsigned long LENGTHDR(unsigned int d, MPR *Mptr) 
/* 
 * returns LENGTHI(int(*Mptr)) + d + 1, if *Mptr >= 0. 
 * returns LENGTHI(int(abs(*Mptr))) + d + 2, if *Mptr < 0. 
 */ 
{ 
	int s; 
	unsigned long l; 
	MPI *G; 
	MPR *X, *TempR; 
 
	s = (Mptr->N)->S; 
	X  = COPYR(Mptr); 
	if (s == -1) 
	{ 
		TempR = X; 
		X = MINUSR(X);	 
		FREEMPR(TempR); 
	} 
	G = INT0(X->N, X->D); 
	l = LENGTHI(G); 
	FREEMPR(X); 
	FREEMPI(G); 
	if (s == -1) 
		return (l + d + (USL)2); 
	else 
		return (l + d + (USL)1); 
} 
 
MPR *RECIPROCAL(unsigned long n) 
/* 
 * input: unsigned int n, 0 < n < R0, output:  MPR *Aptr = 1 / n.  
 */ 
{ 
	MPR *Aptr; 
 
	Aptr = BUILDMPR(); 
	Aptr->N = ONEI(); 
	Aptr->D = CHANGE(n); 
	return (Aptr); 
} 
 
MPR *ADDR(MPR *Aptr, MPR *Bptr) 
/* 
 * *Eptr = *Aptr + *Bptr. 
 * P. Henrici's method: see Computer Algebra Symbolic and Algebraic 
 * Computation, Springer 1982,p. 200. 
 */ 
{ 
	MPI *D, *E, *R, *S, *T1, *T2, *X, *Y; 
	MPR *Eptr; 
 
	if ((Aptr->N)->S == 0) 
		return COPYR(Bptr); 
	else if ((Bptr->N)->S == 0) 
		return COPYR(Aptr); 
	else 
	{ 
		D = GCD(Aptr->D, Bptr->D);	 
		if (EQONEI(D)) 
		{ 
			FREEMPI(D); 
			X = MULTI(Aptr->N, Bptr->D); 
			Y = MULTI(Aptr->D, Bptr->N); 
			Eptr = BUILDMPR();	 
			Eptr->N = ADDI(X, Y); 
			Eptr->D = MULTI(Aptr->D, Bptr->D); 
			FREEMPI(X); 
			FREEMPI(Y); 
			return (Eptr); 
		}	 
		else 
		{ 
			R = INT0(Aptr->D, D); 
			S = INT0(Bptr->D, D); 
			X = MULTI(Aptr->N, S); 
			Y = MULTI(Bptr->N, R); 
			T1 = ADDI(X, Y); 
			T2 = MULTI(Aptr->D, S); 
			FREEMPI(R); 
			FREEMPI(S); 
			FREEMPI(X); 
			FREEMPI(Y); 
			if (T1->S == 0) 
			{ 
				FREEMPI(D); 
				FREEMPI(T1); 
				FREEMPI(T2); 
				return ZEROR(); 
			} 
			else 
			{ 
				Eptr = BUILDMPR();	 
				E = GCD(T1, D);				 
				FREEMPI(D); 
				if (EQONEI(E)) 
				{ 
					FREEMPI(E); 
					Eptr->N = T1; 
					Eptr->D = T2; 
					return (Eptr); 
				} 
				else 
				{ 
					Eptr->N = INT(T1, E); 
					Eptr->D = INT(T2, E); 
					FREEMPI(E); 
					FREEMPI(T1); 
					FREEMPI(T2); 
					return (Eptr); 
				} 
			} 
		} 
	} 
} 
 
MPR *MULTR(MPR *Aptr, MPR *Bptr) 
/* 
 * *Eptr = *Aptr * *Bptr. 
 * P. Henrici's method: see Computer Algebra Symbolic and Algebraic 
 * Computation, Springer 1982,p. 202. 
 */ 
{ 
	MPI *D1=NULL, *D2=NULL, *R1=NULL, *R2=NULL, *S1=NULL, *S2=NULL; 
	MPR *Eptr; 
	if ((Aptr->N)->S == 0 || (Bptr->N)->S == 0) 
		return ZEROR(); 
	else 
	{ 
	  D1 = GCD(Aptr->N, Bptr->D); 
	  D2 = GCD(Bptr->N, Aptr->D); 
	  if (EQONEI(D1)) 
	    { 
	      R1 = COPYI(Aptr->N); 
	      S2 = COPYI(Bptr->D); 
	    } 
	  else 
	    { 
	      R1 = INT(Aptr->N, D1); 
	      S2 = INT0(Bptr->D, D1); 
	    } 
	  if (EQONEI(D2)) 
	    { 
 
	      S1 = COPYI(Bptr->N); 
	      R2 = COPYI(Aptr->D); 
	    } 
	  else 
	    { 
	      S1 = INT(Bptr->N, D2); 
 
	      R2 = INT0(Aptr->D, D2); 
 
 
	    } 
	  Eptr = BUILDMPR(); 
	  Eptr->N = MULTI(R1, S1); 
	  Eptr->D = MULTI(R2, S2); 
	  FREEMPI(D1);  
	  FREEMPI(D2);  
	  FREEMPI(R1);  
	  FREEMPI(R2);  
	  FREEMPI(S1);  
	  FREEMPI(S2);  
 
 
	  return (Eptr); 
	} 
} 
 
MPR *POWERR(MPR *Aptr, unsigned int n) 
/* 
 * *Eptr = (*Aptr) ^ n, where 0 <= n < R0 * R0. 
 */ 
{ 
  MPR *B, *Temp, *Eptr; 
   
  if (n == 0) 
    return ONER(); 
  B = COPYR(Aptr); 
  Eptr = ONER(); 
  while (1) 
    { 
      if (n & 1) 
	{ 
	   
	  Temp = Eptr; 
	  Eptr = MULTR(Eptr, B); 
	  FREEMPR(Temp); 
	  if (n == 1) 
	    { 
	      FREEMPR(B); 
	      return (Eptr); 
	    } 
	} 
      Temp = B; 
      B = MULTR(B, B); 
      FREEMPR(Temp); 
      n = n >> 1; 
    } 
} 
 
/* As above but can find powers of negative numbers */ 
MPR *POWERR_2(MPR *R, int n) 
{ 
  MPR *RETVAL; 
  if (n < 0) { 
    MPR *TMPR; 
    RETVAL= POWERR(R, -n);    
    TMPR=RETVAL; 
    RETVAL=INVERSER(RETVAL); 
    FREEMPR(TMPR); 
  } else { 
    RETVAL = POWERR(R, n); 
  } 
  return RETVAL; 
} 
 
MPR *SUBR(MPR *Aptr, MPR *Bptr) 
/* 
 * *Eptr = *Aptr - *Bptr. 
 */ 
{ 
	MPI *X, *Y, *U, *V, *G; 
	MPR *Eptr; 
 
	X = MULTI(Aptr->N, Bptr->D); 
	Y = MULTI(Aptr->D, Bptr->N); 
	V = MULTI(Aptr->D, Bptr->D); 
	U = SUBI(X, Y); 
	G = GCD(U, V); 
	Eptr = BUILDMPR(); 
	Eptr->N = INT(U, G); 
	Eptr->D = INT(V, G); 
	FREEMPI(X); 
	FREEMPI(Y); 
	FREEMPI(U); 
	FREEMPI(V); 
	FREEMPI(G); 
	return (Eptr); 
} 
 
MPR *INVERSER(MPR *Aptr) 
/* 
 * *Eptr = 1 / *Aptr. 
 */ 
{ 
	MPR *Eptr; 
	int s; 
 
	Eptr = BUILDMPR(); 
	Eptr->D = ABSI(Aptr->N);  
	Eptr->N = COPYI(Aptr->D); 
	s = (Aptr->N)->S; 
	(Eptr->N)->S = ((Eptr->N)->S) * s; 
	return (Eptr); 
} 
  
MPR *RATIOR(MPR *Aptr, MPR *Bptr) 
/* 
 * *Eptr = *Aptr / *Bptr. 
 */ 
{ 
	MPR *X, *Eptr; 
  
	X = INVERSER(Bptr); 
	Eptr = MULTR(Aptr, X); 
	FREEMPR(X); 
	return (Eptr); 
} 
 
MPR *FRAC_PARTR(MPR *Aptr) 
/* 
 * *Bptr = fractional part of *Aptr. 
 */ 
{ 
	MPI *X; 
	MPR *Bptr; 
 
	if (EQONEI(Aptr->D)) 
		Bptr = ZEROR(); 
	else 
	{ 
		X = MOD(Aptr->N, Aptr->D); 
		Bptr = RATIOI(X, Aptr->D); 
		FREEMPI(X); 
	} 
	return (Bptr); 
} 
 
MPR *FRAC_PARTI(MPI *Aptr, MPI *Bptr) 
/* 
 * *Cptr = fractional part of *Aptr/(*Bptr). 
 */ 
{ 
	MPR *C, *Cptr; 
 
	C = RATIOI(Aptr, Bptr); 
	Cptr = FRAC_PARTR(C); 
	FREEMPR(C); 
	return (Cptr); 
} 
 
MPI *NEAREST_INTR(MPR *Aptr) 
/* 
 * *Bptr is the nearest integer to *Aptr. 
 */ 
{ 
	MPI *Y, *Z, *Temp, *Bptr; 
	MPR *X; 
 
	Y = INT(Aptr->N, Aptr->D); 
	X = FRAC_PARTR(Aptr); 
	Z = MULT_I(X->N, 2L); 
	if (RSV(Z, X->D) <= 0) 
		Bptr = Y; 
	else 
	{ 
		Temp = ONEI(); 
		Bptr = ADDI(Y, Temp); 
		FREEMPI(Y); 
		FREEMPI(Temp); 
	} 
	FREEMPR(X); 
	FREEMPI(Z); 
	return (Bptr); 
}  
 
MPI *ABS_NEAREST_INTR(MPR *Aptr) 
/* 
 * *Bptr is the nearest integer to *Aptr, taking the integer closer to 0 
 * if half an odd integer. 
 */ 
{ 
	MPI *Y, *Z, *Bptr, *O; 
	MPR *X; 
	int t; 
 
	Y = INT(Aptr->N, Aptr->D); 
	X = FRAC_PARTR(Aptr); 
	Z = MULT_I(X->N, 2L); 
	t = RSV(Z, X->D); 
	FREEMPR(X); 
	FREEMPI(Z); 
	if (t < 0) 
		Bptr = Y; 
	else if (t == 0) 
	{ 
		if (Y->S >= 0)	 
			Bptr = Y; 
		else 
		{ 
			O = ONEI(); 
			Bptr = ADDI(Y, O); 
			FREEMPI(O); 
			FREEMPI(Y); 
		} 
	} 
	else 
	{ 
		O = ONEI(); 
		Bptr = ADDI(Y, O); 
		FREEMPI(Y); 
		FREEMPI(O); 
	} 
	return (Bptr); 
}  
 
MPI *INPUTSID(char **ptr, unsigned int *uptr) 
/* 
 * For use in converting the decimals after the decimal point to an MPI. 
 * *uptr is the number of decimals met after the decimal point. 
 */ 
{ 
	unsigned int long n; 
	char *t; 
	MPI *Mptr, *Temp; 
 
	Mptr = ZEROI(); 
	t = *ptr; 
	while ((**ptr >= '0' && **ptr <= '9'))  
	{ 
		Temp = Mptr; 
		Mptr = MULT_I(Temp, 10L); 
		FREEMPI(Temp); 
		n = (unsigned long)(**ptr - '0'); 
		Temp = Mptr; 
		Mptr = ADD0_I(Temp, n); 
		FREEMPI(Temp); 
		(*ptr)++; 
	} 
	*uptr = *ptr - t; 
	return (Mptr); 
} 
 
MPR *INPUTSRD(char **ptr) 
/* 
 * Converts a floating point decimal to an MPI. Used in inputting a file of 
 * matrices. 
 */ 
{ 
	unsigned int n, length; 
	MPI *G, *H, *K, *L, *M, *N; 
	MPR *Aptr; 
 
	G = INPUTSI(ptr, &n); 
	if (n == 0)  
	{ 
		FREEMPI(G);/* default - junk at start of number */ 
		return ZEROR(); 
	} 
	else if (**ptr == '.') 
	{ 
		(*ptr)++; 
		H = INPUTSID(ptr, &length); 
		K = POWER_I(10L, length); 
		M = ABSI(G); 
		L = MULTI(M, K); 
		N = ADD0I(L, H); 
		if (G->S == -1) 
			N->S = -(N->S); 
		Aptr = RATIOI(N, K); 
		FREEMPI(H); 
		FREEMPI(K); 
		FREEMPI(M); 
		FREEMPI(L); 
		FREEMPI(N); 
		FREEMPI(G); 
	} 
	else  
	{ 
		Aptr = BUILDMPR(); 
		Aptr->N = G; 
		Aptr->D = ONEI(); 
	} 
	return (Aptr); 
} 
 
void FPRINTMATR(FILE *outfile, USI i1, USI i2, USI j1, USI j2, MPMATR *Mptr) 
/* 
 * Modified 8/1/93 using Peter Adams' improvement from, August 1992. 
 */ 
{ 
	char **str, *buff; 
	unsigned int tmp, i, j, nrow, ncol, len, nstr = 0; 
	int *colwidth; 
	unsigned int ct; 
	 
	nrow = i2 - i1 + 1; 
	ncol = j2 - j1 + 1; 
	str = (char **)mmalloc(nrow * ncol * sizeof(char *)); 
	colwidth=(int *)mmalloc(ncol*sizeof(int)); 
 
	for(i=0; i colwidth[j-j1]) 
				colwidth[j-j1] = len; 
			str[nstr++] = strcpy((char *)mmalloc(len + 1), buff); 
			ffree(buff, tmp * sizeof(char)); 
		} 
	} 
	if (outfile != stdout) 
		fprintf(outfile, "%u %u\n", nrow, ncol); 
	ct=0; 
	for (i = i1; i <= i2; i++) 
	{ 
		for (j = j1; j <= j2; j++) 
		{ 
	    		fprintf(outfile, "%*s ", colwidth[j-j1], str[ct]); 
	    		ffree(str[ct], (unsigned int) (strlen(str[ct]) + 1) * sizeof(char)); 
	    		if ((ct % ncol) == (ncol - 1)) 
				fprintf(outfile, "\n"); 
	    		ct++; 
		} 
	} 
	ffree((char *) str, nrow * ncol * sizeof(char *)); 
	ffree((char *) colwidth, ncol*sizeof(int)); 
	return; 
} 
 
void PRINTMATR(USI i1, USI i2, USI j1, USI j2, MPMATR *Mptr) 
/* 
 * prints *Mptr from rows i1 to i2 and cols j1 to j2. 
 */ 
{ 
	unsigned int i, j; 
 
	i = i2 - i1 + 1; 
	j = j2 - j1 + 1; 
	if (MAX((int)i, (int)j) > 20) 
	{ 
		printf("(The number of rows or columns to be printed exceeds 20;\n"); 
		printf("there is no point in printing this matrix on the screen.)\n"); 
		return; 
	} 
	FPRINTMATR(stdout, i1, i2, j1, j2, Mptr); 
	return; 
} 
 
 
MPR *INTR(MPR *Aptr) 
/* 
 *  Returns the integer part of *Aptr. 
 */ 
{ 
	MPI *X; 
	MPR *Bptr, *Temp; 
 
	if (EQONEI(Aptr->D)) 
		Bptr = COPYR(Aptr); 
	else 
	{ 
		X = MOD(Aptr->N, Aptr->D); 
		Temp = RATIOI(X, Aptr->D); 
		FREEMPI(X); 
		Bptr = SUBR(Aptr, Temp); 
		FREEMPR(Temp); 
	} 
	return (Bptr); 
}