From 2125f01f97abfe343fc5e0cc078bf1d081b2e441 Mon Sep 17 00:00:00 2001 From: Ian Jauslin Date: Fri, 20 May 2016 20:30:15 +0000 Subject: Initial commit --- src/polynomial_base.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 src/polynomial_base.c (limited to 'src/polynomial_base.c') diff --git a/src/polynomial_base.c b/src/polynomial_base.c new file mode 100644 index 0000000..1b4137d --- /dev/null +++ b/src/polynomial_base.c @@ -0,0 +1,337 @@ +/* +Copyright 2016 Ian Jauslin + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* + Base functions for real polynomials + + see polynomial_*.h for the values taken by POLYNOMIAL_FUNC, etc... +*/ + + +// init +int POLYNOMIAL_FUNC(init) (POLYNOMIAL_TYPENAME* poly, unsigned int memory){ + POLYNOMIAL_COEFSARRAY_FUNC(init) (&(poly->coefficients), memory); + POLYNOMIAL_ORDERSARRAY_FUNC(init) (&(poly->orders), memory); + return(0); +} +int POLYNOMIAL_FUNC(free) (POLYNOMIAL_TYPENAME poly){ + POLYNOMIAL_COEFSARRAY_FUNC(free) (poly.coefficients); + POLYNOMIAL_ORDERSARRAY_FUNC(free) (poly.orders); + return(0); +} + +// resize memory +int POLYNOMIAL_FUNC(resize) (POLYNOMIAL_TYPENAME* poly, unsigned int newsize){ + POLYNOMIAL_COEFSARRAY_FUNC(resize) (&(poly->coefficients), newsize); + POLYNOMIAL_ORDERSARRAY_FUNC(resize) (&(poly->orders), newsize); + return(0); +} + +// add a monomial +int POLYNOMIAL_FUNC(add_monomial) (POLYNOMIAL_COEF_TYPE val, POLYNOMIAL_ORDER_TYPE order, POLYNOMIAL_TYPENAME* output){ + unsigned int i; + if((output->coefficients.length != output->orders.length) || (output->coefficients.memory != output->orders.memory)){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + // check whether the order already exists in the polynomial + for(i=0;i< output->coefficients.length;i++){ + if(POLYNOMIAL_ORDER_CMP(order, output->orders.values[i])==0){ + POLYNOMIAL_COEF_ADD(output->coefficients.values[i], output->coefficients.values[i], val); + return(0); + } + } + // if the order does not already exist + if(output->coefficients.length >= output->coefficients.memory){ + POLYNOMIAL_FUNC(resize) (output,2*output->coefficients.memory+1); + } + POLYNOMIAL_COEF_CPY(val, output->coefficients.values[output->coefficients.length]); + POLYNOMIAL_ORDER_CPY(order, output->orders.values[output->coefficients.length]); + output->coefficients.length++; + output->orders.length++; + return(0); +} +// from a double-valued coefficient and an unsigned int order +int POLYNOMIAL_FUNC(add_monomial_dui) (double val, unsigned int order, POLYNOMIAL_TYPENAME* output){ + unsigned int i; + if((output->coefficients.length != output->orders.length) || (output->coefficients.memory != output->orders.memory)){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + // check whether the order already exists in the polynomial + for(i=0;i< output->coefficients.length;i++){ + if(POLYNOMIAL_ORDER_CMP_UI(output->orders.values[i], order)==0){ + POLYNOMIAL_COEF_ADD_D(output->coefficients.values[i], output->coefficients.values[i], val); + return(0); + } + } + // if the order does not already exist + if(output->coefficients.length >= output->coefficients.memory){ + POLYNOMIAL_FUNC(resize) (output,2*output->coefficients.memory+1); + } + POLYNOMIAL_COEF_CPY_D(val, output->coefficients.values[output->coefficients.length]); + POLYNOMIAL_ORDER_CPY_UI(order, output->orders.values[output->coefficients.length]); + output->coefficients.length++; + output->orders.length++; + return(0); +} + +// copy +int POLYNOMIAL_FUNC(cpy) (POLYNOMIAL_TYPENAME input, POLYNOMIAL_TYPENAME* output){ + POLYNOMIAL_COEFSARRAY_FUNC(cpy) (input.coefficients, &(output->coefficients)); + POLYNOMIAL_ORDERSARRAY_FUNC(cpy) (input.orders, &(output->orders)); + return(0); +} +int POLYNOMIAL_FUNC(cpy_noinit) (POLYNOMIAL_TYPENAME input, POLYNOMIAL_TYPENAME* output){ + int ret; + ret=POLYNOMIAL_COEFSARRAY_FUNC(cpy_noinit) (input.coefficients, &(output->coefficients)); + if(ret<0){ + return(ret); + } + POLYNOMIAL_ORDERSARRAY_FUNC(cpy_noinit) (input.orders, &(output->orders)); + return(ret); +} + +// add +int POLYNOMIAL_FUNC(add_inplace) (POLYNOMIAL_TYPENAME poly1, POLYNOMIAL_TYPENAME* poly2){ + unsigned int i; + if(poly1.coefficients.length != poly1.orders.length){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + for(i=0;icoefficients.length != poly->orders.length){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + for(i=0;icoefficients.length;i++){ + POLYNOMIAL_COEF_MUL(poly->coefficients.values[i], poly->coefficients.values[i], x); + } + return(0); +} +int POLYNOMIAL_FUNC(mul_scalar) (POLYNOMIAL_COEF_TYPE x, POLYNOMIAL_TYPENAME poly, POLYNOMIAL_TYPENAME* output){ + int ret; + POLYNOMIAL_FUNC(cpy) (poly, output); + ret=POLYNOMIAL_FUNC(mul_scalar_inplace) (x, output); + return(ret); +} + +// multiply by a monomial +int POLYNOMIAL_FUNC(mul_monomial_inplace) (POLYNOMIAL_COEF_TYPE x, POLYNOMIAL_ORDER_TYPE order, POLYNOMIAL_TYPENAME* poly){ + unsigned int i; + if(poly->coefficients.length != poly->orders.length){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + for(i=0;icoefficients.length;i++){ + POLYNOMIAL_COEF_MUL(poly->coefficients.values[i], poly->coefficients.values[i], x); + POLYNOMIAL_ORDER_ADD(poly->orders.values[i], poly->orders.values[i], order); + } + return(0); +} +int POLYNOMIAL_FUNC(mul_monomial) (POLYNOMIAL_COEF_TYPE x, POLYNOMIAL_ORDER_TYPE order, POLYNOMIAL_TYPENAME poly, POLYNOMIAL_TYPENAME* output){ + int ret; + POLYNOMIAL_FUNC(cpy) (poly,output); + ret=POLYNOMIAL_FUNC(mul_monomial_inplace) (x, order, output); + return(ret); +} + +// multiply two polynomials +int POLYNOMIAL_FUNC(mul_inplace) (POLYNOMIAL_TYPENAME poly1, POLYNOMIAL_TYPENAME* poly2){ + unsigned int i; + int ret; + if(poly1.coefficients.length != poly1.orders.length){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + for(i=0;icoefficients.length != poly->orders.length){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + for(i=0;icoefficients.length;i++){ + if(POLYNOMIAL_ORDER_CMP_UI(poly->orders.values[i], 0)>0){ + POLYNOMIAL_COEF_MUL_ORDER(poly->coefficients.values[i], poly->coefficients.values[i], poly->orders.values[i]); + POLYNOMIAL_ORDER_SUB_UI(poly->orders.values[i], poly->orders.values[i], 1); + } + else{ + // remove the term by setting it to the last term and reducing the length + #ifdef POLYNOMIAL_COEF_FREE + POLYNOMIAL_COEF_FREE(poly->coefficients.values[i]); + #endif + #ifdef POLYNOMIAL_ORDER_FREE + POLYNOMIAL_ORDER_FREE(poly->orders.values[i]); + #endif + if(icoefficients.length-1){ + POLYNOMIAL_COEF_SET(poly->coefficients.values[i], poly->coefficients.values[poly->coefficients.length-1]); + POLYNOMIAL_ORDER_SET(poly->orders.values[i], poly->orders.values[poly->coefficients.length-1]); + i--; + } + poly->coefficients.length--; + poly->orders.length--; + } + } + return(0); +} +int POLYNOMIAL_FUNC(derive) (POLYNOMIAL_TYPENAME poly, POLYNOMIAL_TYPENAME* output){ + int ret; + POLYNOMIAL_FUNC(cpy) (poly, output); + ret=POLYNOMIAL_FUNC(derive_inplace) (output); + return(ret); +} + +// evaluate +int POLYNOMIAL_FUNC(evaluate) (POLYNOMIAL_COEF_TYPE* out, POLYNOMIAL_COEF_TYPE x, POLYNOMIAL_TYPENAME poly){ + unsigned int i; + POLYNOMIAL_COEF_TYPE tmp; + + #ifdef POLYNOMIAL_COEF_INIT + POLYNOMIAL_COEF_INIT(tmp); + #endif + + if(poly.coefficients.length != poly.orders.length){ + return(LIBINUM_ERROR_SIZE_MISMATCH); + } + + POLYNOMIAL_COEF_SET_UI(*out, 0); + for(i=0;i0){ + printf("+ "); + } + POLYNOMIAL_COEF_PRINT(poly.coefficients.values[j]); + printf(" x^"); + POLYNOMIAL_ORDER_PRINT(poly.orders.values[j]); + printf("\n"); + } + + return(0); +} + + +// n-th Legendre polynomial +int POLYNOMIAL_FUNC(legendre) (unsigned int n, POLYNOMIAL_TYPENAME* output){ + POLYNOMIAL_TYPENAME prevpoly, tmppoly; + unsigned int i; + int j; + POLYNOMIAL_COEF_TYPE tmp; + POLYNOMIAL_ORDER_TYPE tmp_o; + + if(n==0){ + POLYNOMIAL_FUNC(init) (output, 1); + POLYNOMIAL_FUNC(add_monomial_dui) (1., 0, output); + return(0); + } + else if(n==1){ + POLYNOMIAL_FUNC(init) (output, n); + POLYNOMIAL_FUNC(add_monomial_dui) (1., 1, output); + return(0); + } + + #ifdef POLYNOMIAL_COEF_INIT + POLYNOMIAL_COEF_INIT(tmp); + #endif + #ifdef POLYNOMIAL_ORDER_INIT + POLYNOMIAL_ORDER_INIT(tmp_o); + #endif + + // init: prevpoly=1 + POLYNOMIAL_FUNC(init) (&prevpoly, n-1); + POLYNOMIAL_FUNC(add_monomial_dui) (1., 0, &prevpoly); + // init: output=x + POLYNOMIAL_FUNC(init) (output, n); + POLYNOMIAL_FUNC(add_monomial_dui) (1., 1, output); + + // implement i*p_i=(2*i-1)*p_{i-1}-(i-1)*p_{i-2} + for(i=2;i<=n;i++){ + // save current poly to copy it to prevpoly at the end of the loop + POLYNOMIAL_FUNC(cpy) (*output, &tmppoly); + + // (2*i-1)/i*p_{i-1} + POLYNOMIAL_COEF_SET_UI(tmp, 2*i-1); + POLYNOMIAL_COEF_DIV_UI(tmp, tmp, i); + POLYNOMIAL_ORDER_SET_UI(tmp_o, 1); + POLYNOMIAL_FUNC(mul_monomial_inplace) (tmp, tmp_o, output); + + // -(i-1)/i*p_{i-2} + // copy i to a signed int + j=i; + POLYNOMIAL_COEF_SET_SI(tmp, -j+1); + POLYNOMIAL_COEF_DIV_UI(tmp, tmp, i); + POLYNOMIAL_FUNC(mul_scalar_inplace) (tmp, &prevpoly); + + // add it to p_n + POLYNOMIAL_FUNC(add_inplace) (prevpoly, output); + + // replace prevpoly + POLYNOMIAL_FUNC(free) (prevpoly); + prevpoly=tmppoly; + } + + POLYNOMIAL_FUNC(free) (prevpoly); + #ifdef POLYNOMIAL_COEF_FREE + POLYNOMIAL_COEF_FREE(tmp); + #endif + #ifdef POLYNOMIAL_ORDER_FREE + POLYNOMIAL_ORDER_FREE(tmp_o); + #endif + + return(0); +} + -- cgit v1.2.3-70-g09d2