euclid.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* euclid.c
  2. *
  3. * Rational arithmetic routines
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. *
  10. * typedef struct
  11. * {
  12. * double n; numerator
  13. * double d; denominator
  14. * }fract;
  15. *
  16. * radd( a, b, c ) c = b + a
  17. * rsub( a, b, c ) c = b - a
  18. * rmul( a, b, c ) c = b * a
  19. * rdiv( a, b, c ) c = b / a
  20. * euclid( &n, &d ) Reduce n/d to lowest terms,
  21. * return greatest common divisor.
  22. *
  23. * Arguments of the routines are pointers to the structures.
  24. * The double precision numbers are assumed, without checking,
  25. * to be integer valued. Overflow conditions are reported.
  26. */
  27. #include <math.h>
  28. #ifdef ANSIPROT
  29. extern double fabs ( double );
  30. extern double floor ( double );
  31. double euclid( double *, double * );
  32. #else
  33. double fabs(), floor(), euclid();
  34. #endif
  35. extern double MACHEP;
  36. #define BIG (1.0/MACHEP)
  37. typedef struct
  38. {
  39. double n; /* numerator */
  40. double d; /* denominator */
  41. }fract;
  42. /* Add fractions. */
  43. void radd( f1, f2, f3 )
  44. fract *f1, *f2, *f3;
  45. {
  46. double gcd, d1, d2, gcn, n1, n2;
  47. n1 = f1->n;
  48. d1 = f1->d;
  49. n2 = f2->n;
  50. d2 = f2->d;
  51. if( n1 == 0.0 )
  52. {
  53. f3->n = n2;
  54. f3->d = d2;
  55. return;
  56. }
  57. if( n2 == 0.0 )
  58. {
  59. f3->n = n1;
  60. f3->d = d1;
  61. return;
  62. }
  63. gcd = euclid( &d1, &d2 ); /* common divisors of denominators */
  64. gcn = euclid( &n1, &n2 ); /* common divisors of numerators */
  65. /* Note, factoring the numerators
  66. * makes overflow slightly less likely.
  67. */
  68. f3->n = ( n1 * d2 + n2 * d1) * gcn;
  69. f3->d = d1 * d2 * gcd;
  70. euclid( &f3->n, &f3->d );
  71. }
  72. /* Subtract fractions. */
  73. void rsub( f1, f2, f3 )
  74. fract *f1, *f2, *f3;
  75. {
  76. double gcd, d1, d2, gcn, n1, n2;
  77. n1 = f1->n;
  78. d1 = f1->d;
  79. n2 = f2->n;
  80. d2 = f2->d;
  81. if( n1 == 0.0 )
  82. {
  83. f3->n = n2;
  84. f3->d = d2;
  85. return;
  86. }
  87. if( n2 == 0.0 )
  88. {
  89. f3->n = -n1;
  90. f3->d = d1;
  91. return;
  92. }
  93. gcd = euclid( &d1, &d2 );
  94. gcn = euclid( &n1, &n2 );
  95. f3->n = (n2 * d1 - n1 * d2) * gcn;
  96. f3->d = d1 * d2 * gcd;
  97. euclid( &f3->n, &f3->d );
  98. }
  99. /* Multiply fractions. */
  100. void rmul( ff1, ff2, ff3 )
  101. fract *ff1, *ff2, *ff3;
  102. {
  103. double d1, d2, n1, n2;
  104. n1 = ff1->n;
  105. d1 = ff1->d;
  106. n2 = ff2->n;
  107. d2 = ff2->d;
  108. if( (n1 == 0.0) || (n2 == 0.0) )
  109. {
  110. ff3->n = 0.0;
  111. ff3->d = 1.0;
  112. return;
  113. }
  114. euclid( &n1, &d2 ); /* cross cancel common divisors */
  115. euclid( &n2, &d1 );
  116. ff3->n = n1 * n2;
  117. ff3->d = d1 * d2;
  118. /* Report overflow. */
  119. if( (fabs(ff3->n) >= BIG) || (fabs(ff3->d) >= BIG) )
  120. {
  121. mtherr( "rmul", OVERFLOW );
  122. return;
  123. }
  124. /* euclid( &ff3->n, &ff3->d );*/
  125. }
  126. /* Divide fractions. */
  127. void rdiv( ff1, ff2, ff3 )
  128. fract *ff1, *ff2, *ff3;
  129. {
  130. double d1, d2, n1, n2;
  131. n1 = ff1->d; /* Invert ff1, then multiply */
  132. d1 = ff1->n;
  133. if( d1 < 0.0 )
  134. { /* keep denominator positive */
  135. n1 = -n1;
  136. d1 = -d1;
  137. }
  138. n2 = ff2->n;
  139. d2 = ff2->d;
  140. if( (n1 == 0.0) || (n2 == 0.0) )
  141. {
  142. ff3->n = 0.0;
  143. ff3->d = 1.0;
  144. return;
  145. }
  146. euclid( &n1, &d2 ); /* cross cancel any common divisors */
  147. euclid( &n2, &d1 );
  148. ff3->n = n1 * n2;
  149. ff3->d = d1 * d2;
  150. /* Report overflow. */
  151. if( (fabs(ff3->n) >= BIG) || (fabs(ff3->d) >= BIG) )
  152. {
  153. mtherr( "rdiv", OVERFLOW );
  154. return;
  155. }
  156. /* euclid( &ff3->n, &ff3->d );*/
  157. }
  158. /* Euclidean algorithm
  159. * reduces fraction to lowest terms,
  160. * returns greatest common divisor.
  161. */
  162. double euclid( num, den )
  163. double *num, *den;
  164. {
  165. double n, d, q, r;
  166. n = *num; /* Numerator. */
  167. d = *den; /* Denominator. */
  168. /* Make numbers positive, locally. */
  169. if( n < 0.0 )
  170. n = -n;
  171. if( d < 0.0 )
  172. d = -d;
  173. /* Abort if numbers are too big for integer arithmetic. */
  174. if( (n >= BIG) || (d >= BIG) )
  175. {
  176. mtherr( "euclid", OVERFLOW );
  177. return(1.0);
  178. }
  179. /* Divide by zero, gcd = 1. */
  180. if(d == 0.0)
  181. return( 1.0 );
  182. /* Zero. Return 0/1, gcd = denominator. */
  183. if(n == 0.0)
  184. {
  185. /*
  186. if( *den < 0.0 )
  187. *den = -1.0;
  188. else
  189. *den = 1.0;
  190. */
  191. *den = 1.0;
  192. return( d );
  193. }
  194. while( d > 0.5 )
  195. {
  196. /* Find integer part of n divided by d. */
  197. q = floor( n/d );
  198. /* Find remainder after dividing n by d. */
  199. r = n - d * q;
  200. /* The next fraction is d/r. */
  201. n = d;
  202. d = r;
  203. }
  204. if( n < 0.0 )
  205. mtherr( "euclid", UNDERFLOW );
  206. *num /= n;
  207. *den /= n;
  208. return( n );
  209. }