#include <stdio.h>
#include <math.h>
#include <rc/math/polynomial.h>
#include "algebra_common.h"
int rc_poly_print(rc_vector_t v)
{
int i;
static char *super[] = {"\xe2\x81\xb0", "\xc2\xb9", "\xc2\xb2",
"\xc2\xb3", "\xe2\x81\xb4", "\xe2\x81\xb5", "\xe2\x81\xb6",
"\xe2\x81\xb7", "\xe2\x81\xb8", "\xe2\x81\xb9"};
if(unlikely(!v.initialized)){
fprintf(stderr,"ERROR in rc_poly_print, vector not initialized yet\n");
return -1;
}
if(unlikely(v.len>10)){
fprintf(stderr,"ERROR in rc_poly_print, vector length must be <=10\n");
return -1;
}
for(i=0;i<(v.len-2);i++){
printf("%7.4fx%s + ",v.d[i],super[v.len-i-1]);
}
if(v.len>=2) printf("%7.4fx + ",v.d[v.len-2]);
printf("%7.4f\n", v.d[v.len-1]);
return 0;
}
int rc_poly_conv(rc_vector_t a, rc_vector_t b, rc_vector_t* c)
{
int i,j;
if(unlikely(!a.initialized || !b.initialized)){
fprintf(stderr,"ERROR in rc_poly_conv, vector uninitialized\n");
return -1;
}
if(unlikely(rc_vector_zeros(c,a.len+b.len-1))){
fprintf(stderr,"ERROR in rc_poly_conv, failed to alloc vector\n");
return -1;
}
for(i=0;i<a.len;i++){
for(j=0;j<b.len;j++){
c->d[i+j] += a.d[i]*b.d[j];
}
}
return 0;
}
int rc_poly_power(rc_vector_t a, int n, rc_vector_t* b)
{
int i;
rc_vector_t tmp = RC_VECTOR_INITIALIZER;
if(unlikely(!a.initialized)){
fprintf(stderr,"ERROR in rc_poly_power, vector uninitialized\n");
return -1;
}
if(unlikely(n<0)){
fprintf(stderr,"ERROR in rc_poly_power, negative exponents not allowed\n");
return -1;
}
if(n==0){
if(unlikely(rc_vector_alloc(b,1))){
fprintf(stderr,"ERROR in rc_poly_power, failed to alloc vector\n");
return -1;
}
b->d[0] = 1.0f;
return 0;
}
if(unlikely(rc_vector_duplicate(a,b))){
fprintf(stderr,"ERROR in rc_poly_power, failed to duplicate vector\n");
return -1;
}
if(n==1) return 0;
for(i=2;i<=n;i++){
if(unlikely(rc_poly_conv(a,*b,&tmp))){
fprintf(stderr,"ERROR in rc_poly_power, failed to poly_conv\n");
rc_vector_free(&tmp);
rc_vector_free(b);
return -1;
}
rc_vector_free(b);
*b = tmp;
tmp = rc_vector_empty();
}
return 0;
}
int rc_poly_add(rc_vector_t a, rc_vector_t b, rc_vector_t* c)
{
int i, diff;
rc_vector_t longest;
if(unlikely(!a.initialized || !b.initialized)){
fprintf(stderr,"ERROR in rc_poly_add, vector uninitialized\n");
return -1;
}
if(a.len>b.len) longest=a;
else{
longest=b;
b=a;
}
if(unlikely(rc_vector_duplicate(longest,c))){
fprintf(stderr,"ERROR in rc_poly_add, failed to duplicate vector\n");
return -1;
}
diff = c->len-b.len;
for(i=diff;i<c->len;i++) c->d[i]+=b.d[i-diff];
return 0;
}
int rc_poly_add_inplace(rc_vector_t* a, rc_vector_t b)
{
rc_vector_t tmp = RC_VECTOR_INITIALIZER;
if(unlikely(!a->initialized || !b.initialized)){
fprintf(stderr,"ERROR in rc_poly_add_in_place, vector uninitialized\n");
return -1;
}
if(unlikely(rc_poly_add(*a,b,&tmp))){
fprintf(stderr,"ERROR in rc_poly_add_in_place, add failed\n");
return -1;
}
rc_vector_free(a);
*a=tmp;
return 0;
}
int rc_poly_subtract(rc_vector_t a, rc_vector_t b, rc_vector_t* c)
{
int i, diff;
rc_vector_t longest;
if(unlikely(!a.initialized || !b.initialized)){
fprintf(stderr,"ERROR in rc_poly_subtract, vector uninitialized\n");
return -1;
}
if(a.len>b.len) longest=a;
else{
longest=b;
b=a;
}
if(unlikely(rc_vector_duplicate(longest,c))){
fprintf(stderr,"ERROR in rc_poly_subtract, failed to duplicate vector\n");
return -1;
}
diff = c->len-b.len;
for(i=diff;i<c->len;i++) c->d[i]-=b.d[i-diff];
return 0;
}
int rc_poly_subtract_inplace(rc_vector_t* a, rc_vector_t b)
{
rc_vector_t tmp = RC_VECTOR_INITIALIZER;
if(unlikely(!a->initialized || !b.initialized)){
fprintf(stderr,"ERROR in rc_poly_subtract_in_place, vector uninitialized\n");
return -1;
}
if(unlikely(rc_poly_subtract(*a,b,&tmp))){
fprintf(stderr,"ERROR in rc_poly_subtract_in_place, subtract failed\n");
return -1;
}
rc_vector_free(a);
*a=tmp;
return 0;
}
int rc_poly_differentiate(rc_vector_t a, int d, rc_vector_t* b)
{
rc_vector_t tmp = RC_VECTOR_INITIALIZER;
rc_vector_t tmp_r = RC_VECTOR_INITIALIZER;
int i, new_order;
if(unlikely(!a.initialized)){
fprintf(stderr,"ERROR in rc_poly_differentiate, vector uninitialized\n");
return -1;
}
if(unlikely(d<0)){
fprintf(stderr,"ERROR in rc_poly_differentiate, d must be >=0\n");
return -1;
}
if(d>=a.len) return rc_vector_zeros(b,1);
if(d==0) return rc_vector_duplicate(a,b);
new_order = a.len-1;
if(unlikely(rc_vector_alloc(&tmp,new_order))){
fprintf(stderr,"ERROR in rc_poly_differentiate, failed to alloc vector\n");
return -1;
}
for(i=0; i<new_order; i++) tmp.d[i]=a.d[i]*(new_order-i);
if(d==1){
rc_vector_free(b);
*b=tmp;
return 0;
}
if(unlikely(rc_poly_differentiate(tmp,d-1,&tmp_r))){
fprintf(stderr,"ERROR in rc_poly_differentiate, failed to differentiate recursively\n");
rc_vector_free(&tmp);
return -1;
}
rc_vector_free(&tmp);
rc_vector_free(b);
*b=tmp_r;
return 0;
}
int rc_poly_divide(rc_vector_t n, rc_vector_t d, rc_vector_t* div, rc_vector_t* rem)
{
int i, j, diff;
rc_vector_t tmp = RC_VECTOR_INITIALIZER;
if(unlikely(!n.initialized || !d.initialized)){
fprintf(stderr,"ERROR in rc_poly_divide, vector uninitialized\n");
return -1;
}
diff=n.len-d.len;
if(unlikely(diff<0)){
fprintf(stderr,"ERROR in rc_poly_divide, order of num must be >= to den\n");
return -1;
}
if(unlikely(rc_vector_zeros(div,diff+1))){
fprintf(stderr,"ERROR in rc_poly_divide, failed to alloc vector\n");
return -1;
}
if(unlikely(rc_vector_duplicate(n,&tmp))){
fprintf(stderr,"ERROR in rc_poly_divide, failed to duplicate vector\n");
rc_vector_free(div);
return -1;
}
for(i=0;i<=diff;i++){
div->d[i]=tmp.d[i]/d.d[0];
for(j=0;j<d.len;j++){
tmp.d[j+i]-=div->d[i]*d.d[j];
}
}
if(unlikely(rc_vector_alloc(rem,d.len-1))){
fprintf(stderr,"ERROR in rc_poly_divide, failed alloc rem vector\n");
rc_vector_free(&tmp);
return -1;
}
for(i=0;i<d.len-1;i++) rem->d[i]=tmp.d[i+diff+1];
rc_vector_free(&tmp);
return 0;
}
int rc_poly_butter(int N, double wc, rc_vector_t* b)
{
int i;
int ret=0;
rc_vector_t P2 = RC_VECTOR_INITIALIZER;
rc_vector_t P3 = RC_VECTOR_INITIALIZER;
rc_vector_t tmp = RC_VECTOR_INITIALIZER;
if(unlikely(N<1)){
fprintf(stderr,"ERROR in rc_poly_butter, order must be >1\n");
return -1;
}
if(unlikely(rc_vector_ones(b,1))){
fprintf(stderr,"ERROR in rc_poly_butter, failed to alloc vector\n");
return -1;
}
if(unlikely(rc_vector_alloc(&P2,2))){
fprintf(stderr,"ERROR in rc_poly_butter, failed to alloc vector\n");
rc_vector_free(b);
return -1;
}
if(unlikely(rc_vector_alloc(&P3,3))){
fprintf(stderr,"ERROR in rc_poly_butter, failed to alloc vector\n");
rc_vector_free(b);
rc_vector_free(&P2);
return -1;
}
if(N%2 == 0){
P3.d[0] = 1.0/(wc*wc); P3.d[2] = 1.0; for(i=1;i<=N/2;i++){
P3.d[1] = -2.0*cos(((2*i) + (N-1))*M_PI/(2.0*N))/wc;
rc_vector_duplicate(*b,&tmp);
if(unlikely(rc_poly_conv(tmp,P3,b))){
fprintf(stderr,"ERROR in rc_poly_butter, failed to polyconv\n");
ret = -1;
goto POLY_END;
}
}
}
if(N%2 == 1){
P2.d[0] = 1.0/wc;
P2.d[1] = 1.0;
rc_vector_duplicate(*b,&tmp);
if(unlikely(rc_poly_conv(tmp,P2,b))){
fprintf(stderr,"ERROR in rc_poly_butter, failed to polyconv\n");
ret = -1;
goto POLY_END;
}
P3.d[0] = 1.0/(wc*wc);
P3.d[2] = 1.0;
for(i=1;i<=(N-1)/2;i++){
P3.d[1] = -2.0*cos(((2*i) + (N-1))*M_PI/(2.0*N))/wc;
rc_vector_duplicate(*b,&tmp);
if(unlikely(rc_poly_conv(tmp,P3,b))){
fprintf(stderr,"ERROR in rc_poly_butter, failed to polyconv\n");
ret = -1;
goto POLY_END;
}
}
}
POLY_END:
rc_vector_free(&tmp);
rc_vector_free(&P2);
rc_vector_free(&P3);
return ret;
}