polynomial_adt.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include "polynomial_adt.h"
  2. PolyAdt *create_adt(int hp)
  3. {
  4. PolyAdt *pAdt = malloc(sizeof(PolyAdt));
  5. assert(pAdt != NULL);
  6. pAdt->head = NULL;
  7. pAdt->terms = 0;
  8. pAdt->hp = hp;
  9. return pAdt;
  10. }
  11. void insert_term(PolyAdt *pAdt, float c, int e)
  12. {
  13. assert(pAdt != NULL); //assume client code didnt call create_adt()
  14. Node *n = malloc(sizeof(Node));
  15. if(pAdt->head == NULL)
  16. pAdt->head = create_node(c, e, pAdt->head);
  17. else
  18. for(n = pAdt->head; n->next != NULL; n = n->next); //go to the end of list
  19. n->next = create_node(c, e, NULL);
  20. pAdt->terms++;
  21. }
  22. PolyAdt *polyImage(const PolyAdt *orig)
  23. {
  24. PolyAdt *img = create_adt(orig->hp);
  25. Node *origHead = orig->head;
  26. for(; origHead; origHead = origHead->next)
  27. insert_term(img, origHead->coeff, origHead->exp);
  28. return img;
  29. }
  30. PolyAdt *add(const PolyAdt *a, const PolyAdt *b)
  31. {
  32. PolyAdt *sum;
  33. Node *n, *np;
  34. int state = 1;
  35. assert(a != NULL && b != NULL);
  36. int hpow = max(a->hp, b->hp);
  37. sum = create_adt(hpow); //create space for it
  38. /* using state machine to compare the poly with the most terms to
  39. ** the poly with fewer, round robin type of effect comparison of
  40. ** exponents => 3 Cases: Equal, Less, Greater
  41. */
  42. n = a->head; np = b->head;
  43. while(state) {
  44. /* compare the exponents */
  45. if(n->exp == np->exp){
  46. insert_term(sum, n->coeff + np->coeff, n->exp);
  47. n = n->next;
  48. np = np->next;
  49. }
  50. else if(n->exp < np->exp){
  51. insert_term(sum, np->coeff, np->exp);
  52. np = np->next; //move to next term of b
  53. }
  54. else { //greater than
  55. insert_term(sum, n->coeff, n->exp);
  56. n = n->next;
  57. }
  58. /* check whether at the end of one list or the other */
  59. if(np == NULL && state){ //copy rest of a to sum
  60. for(; n != NULL; n = n->next)
  61. insert_term(sum, n->coeff, n->exp);
  62. state = 0;
  63. }
  64. if(n == NULL && state){
  65. for(; np != NULL; np = np->next)
  66. insert_term(sum, np->coeff, np->exp);
  67. state = 0;
  68. }
  69. }
  70. return sum;
  71. }
  72. PolyAdt *subtract(const PolyAdt *a, const PolyAdt *b)
  73. {
  74. assert(a != NULL && b != NULL);
  75. PolyAdt *tmp = create_adt(b->hp);
  76. Node *bptr;
  77. for(bptr = b->head; bptr != NULL; bptr = bptr->next)
  78. insert_term(tmp,-bptr->coeff,bptr->exp); //negating b's coeffs
  79. return add(a,tmp);
  80. }
  81. PolyAdt *multiply(const PolyAdt *a, const PolyAdt *b)
  82. {
  83. assert(a != NULL && b != NULL);
  84. //the polys are inserted in order for now
  85. PolyAdt *prod = create_adt(a->head->exp + b->head->exp);
  86. Node *n = a->head, *np = b->head;
  87. Node *t = b->head;
  88. if(a->terms < b->terms){
  89. n = b->head;
  90. np = t = a->head;
  91. }
  92. for(; n != NULL; n = n->next){
  93. np = t; //reset to the beginning
  94. for(; np != NULL; np = np->next){ //always the least term in this loop
  95. insert_term(prod, n->coeff * np->coeff, n->exp + np->exp);
  96. }
  97. }
  98. return prod;
  99. }
  100. PolyAdt *derivative(const PolyAdt *a)
  101. {
  102. assert(a != NULL);
  103. PolyAdt *deriv = create_adt(a->head->exp - 1);
  104. Node *n = a->head;
  105. for(; n != NULL; n = n->next){
  106. if(n->exp == 0) break;
  107. insert_term(deriv, n->coeff * n->exp, n->exp-1);
  108. }
  109. return deriv;
  110. }
  111. PolyAdt *integrate(const PolyAdt *a)
  112. {
  113. assert(a != NULL);
  114. PolyAdt *integrand = create_adt(a->head->exp + 1);
  115. Node *n;
  116. for(n = a->head; n != NULL; n = n->next) //very simple term by term
  117. insert_term(integrand, (float)n->coeff/(n->exp+1.0F), n->exp + 1);
  118. return integrand;
  119. }
  120. void quadratic_roots(const PolyAdt *a, float *real, float *cplx)
  121. {
  122. assert(a != NULL);
  123. float dscrmnt, _a, b, c;
  124. float u, v;
  125. Node *n = a->head;
  126. _a = n->coeff; b = n->next->coeff; c = n->next->next->coeff;
  127. dscrmnt = (b*b) - 4*_a*c;
  128. u = -b/(2*_a); v = sqrt((double)fabs(dscrmnt))/(2*_a);
  129. if((real && !cplx) || (!real && cplx))
  130. assert(1);
  131. if(real == NULL && cplx == NULL){
  132. if(a->hp != 2 && a->terms < 3){
  133. printf("Invalid Quadratic*, A and B must be non-zero");
  134. return;
  135. }
  136. if(dscrmnt != 0)
  137. printf("X = %.2f +/- %.2f%c\n",u,v,dscrmnt < 0 ? 'I':' ');
  138. else{
  139. printf("(X %c %.2f)(X %c %.2f)\n",sgn(u),fabs(u),sgn(u),fabs(u));
  140. printf("X1,2 = %.2f\n",u);
  141. }
  142. }
  143. //save values in pointers
  144. else {
  145. if(dscrmnt < 0){ //x = u +/- vI Re(x) = u, Im(x) = +v
  146. *real = u;
  147. *cplx = v; //understand +/- is not representable
  148. }
  149. else if(dscrmnt == 0){
  150. *real = u;
  151. *cplx = 0.00F;
  152. }
  153. else{
  154. *real = u + v;
  155. *cplx = u - v;
  156. }
  157. }
  158. }
  159. PolyAdt *exponentiate(const PolyAdt *a, int n)
  160. {
  161. assert(a != NULL);
  162. PolyAdt *expn = create_adt(a->hp * n);
  163. PolyAdt *aptr = polyImage(a);
  164. int hl = n / 2;
  165. //check default cases before calculation
  166. if(n == 0){
  167. insert_term(expn, 1, 0);
  168. return expn;
  169. }
  170. else if(n == 1){
  171. return aptr;
  172. }
  173. for(; hl ; hl--)
  174. aptr = multiply(aptr, aptr);
  175. if(n % 2) //odd exponent do a^(n-1) * a = a^n
  176. expn = multiply(aptr, a);
  177. else
  178. expn = aptr;
  179. return expn;
  180. }
  181. PolyAdt *compose(const PolyAdt *p, const PolyAdt *q)
  182. {
  183. assert(p && q);
  184. PolyAdt *comp = create_adt(p->head->exp * q->head->exp);
  185. PolyAdt *exp;
  186. Node *pp = p->head;
  187. Node *qq = q->head;
  188. int swap = 0;
  189. if(p->terms < q->terms){
  190. pp = q->head;
  191. qq = p->head;
  192. swap = 1;
  193. }
  194. /* going through, exponentiate each term with the exponent of p */
  195. for(; pp != NULL; pp = pp->next){
  196. exp = exponentiate(swap ? p: q, pp->exp);
  197. insert_term(comp, pp->coeff * exp->head->coeff, exp->head->exp);
  198. }
  199. return comp;
  200. }
  201. void destroy_poly(PolyAdt *poly)
  202. {
  203. Node *ps = poly->head;
  204. Node *tmp = NULL;
  205. while(ps != NULL){
  206. tmp = ps;
  207. free(tmp);
  208. ps = ps->next;
  209. }
  210. poly->hp = poly->terms = 0;
  211. poly->head = NULL;
  212. }
  213. void display_poly(const PolyAdt *a)
  214. {
  215. assert(a != NULL);
  216. Node *n;
  217. for(n = a->head; n != NULL; n = n->next){
  218. n->coeff < 0 ? putchar('-') : putchar('+');
  219. if(n->exp == 0)
  220. printf(" %.2f ",fabs(n->coeff));
  221. else if(n->coeff == 1)
  222. printf(" X^%d ",n->exp);
  223. else if(n->exp == 1)
  224. printf(" %.2fX ",fabs(n->coeff));
  225. else if(n->coeff == 0)
  226. continue;
  227. else
  228. printf(" %.2fX^%d ",fabs(n->coeff),n->exp);
  229. }
  230. printf("\n\n");
  231. }