/src/reduction.c

https://bitbucket.org/maciekpacut/lpp · C · 89 lines · 68 code · 17 blank · 4 comment · 10 complexity · 1c36dc3b582d12483f91e111318a1750 MD5 · raw file

  1. #include "reduction.h"
  2. float** bezier_reduction_matrix(int n, int m)
  3. {
  4. assert(n > m);
  5. float (*psi)[n+1] = malloc(sizeof(float) * (m + 1) * (n + 1));
  6. float C = factrl(n)*up_power(1-n, m)
  7. / (factrl(m)*up_power(m+2, n));
  8. // 0,0
  9. {
  10. psi[0][0] = 0;
  11. for(int h = 0; h <= m; ++h)
  12. {
  13. float t = bico(m,h) * up_power(m+2,h) / ((h-n)*factrl(h));
  14. if(h % 2 != 0)
  15. t *= -1;
  16. psi[0][0] += t;
  17. }
  18. psi[0][0] *= -n*C;
  19. }
  20. // 0,1
  21. {
  22. psi[0][1] = (m+1)*C;
  23. if(m%2 != 0)
  24. psi[0][1] *= -1;
  25. }
  26. // first row
  27. {
  28. for(int j = 1; j <= n - 1; ++j)
  29. {
  30. float F = ((float)((j-1)*(n-j+1)))/((float) ((n-j)*(j+1)));
  31. float E = 1. + F - ((float)(m*(m+2)))/((float) ((n-j)*(j+1)));
  32. psi[0][j+1] = E*psi[0][j] - F*psi[0][j-1];
  33. }
  34. }
  35. // rest of matrix
  36. {
  37. for(int i = 0; i <= m - 1; ++i)
  38. {
  39. for(int j = 0; j <= n; ++j)
  40. {
  41. float Anj = j*(j-n-1);
  42. float Ami = i*(i-m-1);
  43. float Bnj = (j-n)*(j+1);
  44. float Bmi = (i-m)*(i+1);
  45. float Cnj = Anj + Bnj;
  46. float Cmi = Ami + Bmi;
  47. float pp0m1 = ((j - 1) < 0) ? 0 : psi[i][j-1];
  48. float pp0p0 = psi[i][j];
  49. float pm1p0 = ((i - 1) < 0) ? 0 : psi[i-1][j];
  50. float pp0p1 = ((j + 1) > n) ? 0 : psi[i][j+1];
  51. psi[i+1][j] = (Anj*pp0m1 + (Cmi-Cnj)*pp0p0 +
  52. Bnj*pp0p1 - Ami*pm1p0) / Bmi;
  53. }
  54. }
  55. }
  56. return (float**)psi;
  57. }
  58. Bezier* bezier_degree_reduction(Bezier* c, int m, float **reduction_matrix)
  59. {
  60. int n = c->n;
  61. float (*psi)[n+1] = (float(*)[])reduction_matrix;
  62. float (*e) = malloc(sizeof(float) * (n + 1));
  63. for(int i = 0; i <= m; ++i)
  64. {
  65. e[i] = 0;
  66. for(int j = 0; j <= n; ++j)
  67. e[i] += c->c[j]*psi[i][j];
  68. }
  69. Bezier* low = bezier_create_with_coeffs(m, e);
  70. low->dom = interval_copy(c->dom);
  71. return low;
  72. }