/* Copyright 2015-2022 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. */ #include "coefficient.h" #include #include #include // define MPFR_USE_VA_LIST to enable the use of mpfr_inits and mpfr_clears #define MPFR_USE_VA_LIST #include #include "definitions.cpp" #include "rational.h" #include "istring.h" #include "array.h" #include "number.h" #include "tools.h" // allocate memory int init_Coefficient(Coefficient* coef,int size){ (*coef).factors=calloc(size,sizeof(Int_Array)); (*coef).nums=calloc(size,sizeof(Number)); (*coef).denoms=calloc(size,sizeof(coef_denom)); (*coef).length=0; (*coef).memory=size; return(0); } // free memory int free_Coefficient(Coefficient coef){ int i; for(i=0;i(*output).memory){ resize_Coefficient(output,input.length); } for(i=0;i=(*output).memory){ resize_Coefficient(output,2*(*output).memory+1); } // copy and allocate int_array_cpy(factor,(*output).factors+offset); number_cpy(num,(*output).nums+offset); (*output).denoms[offset]=denom; // increment length (*output).length++; return(0); } // append an element to a coefficient without allocating memory int coefficient_append_noinit(Int_Array factor, Number num, coef_denom denom, Coefficient* output){ int offset=(*output).length; if((*output).length>=(*output).memory){ resize_Coefficient(output,2*(*output).memory+1); } // copy without allocating (*output).factors[offset]=factor; (*output).nums[offset]=num; (*output).denoms[offset]=denom; // increment length (*output).length++; return(0); } // concatenate coefficients and simplify result int coefficient_concat(Coefficient input, Coefficient* output){ int i; for(i=0;i=1;power--){ ret=coefficient_simplify_fraction(constant, quotient_prev, &remainder, "ient); // if fail to simplify, stop if(ret<0){ if(power=1 && power==0){ coefficient_concat_noinit(quotient, &out); } coefficient_simplify(&out); // set coefficient to out free_Coefficient(*coefficient); *coefficient=out; return 0; } // put all terms under a common denominator // only supports coefficients with only one constant int coefficient_common_denominator(Coefficient constant, Coefficient* coefficient){ int max_power; int i,j; Coefficient tmp; Coefficient out; Coefficient* C_n; init_Coefficient(&out, COEF_SIZE); // largest power (larger powers are at the end) max_power=(*coefficient).denoms[(*coefficient).length-1].power; // store powers of the constant C_n=calloc(sizeof(Coefficient), max_power-1); for(i=0;i0 && (*remainder).factors[(*remainder).length-1].length>=constant.factors[constant.length-1].length){ step_counter++; // interrupt if too long if(step_counter>=coefficient.length*100){ free_Coefficient(*remainder); free_Coefficient(*out); return -1; } // try to find a term in the constant that divides the last term of the (*remainder) rfactors=(*remainder).factors[(*remainder).length-1]; // highest order in constant max_order=constant.factors[constant.length-1].length; // start from one of the highest order term and look for a common factor for(i=constant.length-1; i>=0; i--){ // fail: no highest order terms have been matched if(constant.factors[i].length0){ at_least_one=1; coefficient_append_noinit(factor,number_Qprod_ret(quot(match_count,1),input.nums[i]), input.denoms[i],output); } else{ free_Int_Array(factor); } } if(at_least_one>0){ coefficient_simplify(output); } else{ // add a trivial element to the coefficient init_Int_Array(&factor,0); denom.index=-1; denom.power=0; coefficient_append_noinit(factor,number_zero(),denom,output); } return(0); } // differentiate a monomial with respect to an index int monomial_deriv(Int_Array factor, int index, Int_Array* out_factor, int* match_count){ int j; init_Int_Array(out_factor,factor.length); // init match count *match_count=0; // loop over indices for(j=0;jdenom2.index){ return(-1); } if(denom1.powerdenom2.power){ return(1); } return(0); } // evaluate a coefficient on a vector int evalcoef(RCC rccs, Coefficient coef, long double* out){ int i,j; long double num_factor; *out=0.; // for each monomial for(i=0;i0){ num_factor/=dpower(rccs.values[intlist_find_err(rccs.indices,rccs.length,coef.denoms[i].index)],coef.denoms[i].power); } *out+=num_factor*number_double_val(coef.nums[i]); } return(0); } // evaluate a coefficient on a vector (using mpfr floats) int evalcoef_mpfr(RCC_mpfr rccs, Coefficient coef, mpfr_t out){ int i,j; mpfr_t num_factor; // tmp number (do not initialize Z) mpfr_t x, y, Z; // init numbers mpfr_inits(num_factor, x, y, (mpfr_ptr) NULL); mpfr_init(out); mpfr_set_zero(out, 1); // for each monomial for(i=0;i0){ mpfr_pow_si(y, rccs.values[intlist_find_err(rccs.indices,rccs.length,coef.denoms[i].index)], coef.denoms[i].power, MPFR_RNDN); mpfr_div(x, num_factor, y, MPFR_RNDN); mpfr_set(num_factor, x, MPFR_RNDN); } number_mpfr_val(Z, coef.nums[i]); mpfr_mul(x, num_factor, Z, MPFR_RNDN); mpfr_add(y, x, out, MPFR_RNDN); mpfr_set(out, y, MPFR_RNDN); mpfr_clear(Z); } // free numbers mpfr_clears(num_factor, x, y, (mpfr_ptr)NULL); return(0); }