/* 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 "grouped_polynomial.h" #include #include #include "definitions.cpp" #include "rational.h" #include "istring.h" #include "coefficient.h" #include "polynomial.h" #include "array.h" #include "number.h" #include "tools.h" // allocate memory int init_Grouped_Polynomial(Grouped_Polynomial* gpolynomial, int size){ (*gpolynomial).coefs=calloc(size,sizeof(Coefficient)); (*gpolynomial).indices=calloc(size,sizeof(int)); (*gpolynomial).length=0; (*gpolynomial).memory=size; return(0); } // free memory int free_Grouped_Polynomial(Grouped_Polynomial gpolynomial){ int i; for(i=0;i=(*output).memory){ resize_grouped_polynomial(output,2*(*output).memory+1); } // copy and allocate (*output).indices[offset]=index; coefficient_cpy(coef, (*output).coefs+offset); //increment length (*output).length++; return(0); } // append an element to a grouped_polynomial without allocating memory int grouped_polynomial_append_noinit(int index, Coefficient coef, Grouped_Polynomial* output){ int offset=(*output).length; if((*output).length>=(*output).memory){ resize_grouped_polynomial(output,2*(*output).memory+1); } // copy without allocating (*output).indices[offset]=index; (*output).coefs[offset]=coef; // increment length (*output).length++; return(0); } // concatenate two grouped_polynomials int grouped_polynomial_concat(Grouped_Polynomial input, Grouped_Polynomial* output){ int i; for(i=0;i0){ // stop if the number of iterations exceeds 100 times the length of the polynomial if(security >= 100*polynomial.length){ fprintf(stderr,"error: polynomial could not be grouped in less than %d groupings\n", 100*polynomial.length); exit(-1); } security++; // index of the last element i=remainder.length-1; // find entry if(remainder.monomials[i].length==0){ // constant index=-1; } else{ // loop over entries for(j=0,index=-2;j=0){ ratio=number_quot_ret(remainder.nums[i],idtable.polynomials[index].nums[pos]); factor=remainder.factors[i]; // add to coefficient denom.index=-1; denom.power=1; coefficient_append(factor, ratio, denom, (*grouped_polynomial).coefs+index+1); // remove from remainder free_Int_Array(remainder.monomials[i]); // do not free factor yet free_Number(remainder.nums[i]); remainder.length--; // add terms from idtable with minus sign for(j=0;j=0){ // a vector in which to store the indices that were masked init_Int_Array(&mask_tmp_flips,idtable.polynomials[index].length); // loop over all monomials in that entry of the idtable for(j=0;j=0){ (*dflow).indices[i]=flow_equation.indices[i]+DOFFSET; } else{ (*dflow).indices[i]=flow_equation.indices[i]-DOFFSET; } init_Coefficient((*dflow).coefs+i, COEF_SIZE); // for each index for(j=0;j=0){ int_array_append(DOFFSET + indices.values[j], tmp_coef.factors+k); } // constants are offset with -doffset (so that the derivatives of constants also have a negative index) else{ int_array_append(-DOFFSET + indices.values[j], tmp_coef.factors+k); } } } // add to output coefficient_concat_noinit(tmp_coef, (*dflow).coefs+i); } } (*dflow).length=flow_equation.length; return(0); } /* // differentiate a flow equation with respect to an index int flow_equation_deriv(Grouped_Polynomial flow_equation, int index, Grouped_Polynomial* output){ int i,k; // temp list of indices Int_Array factor; // number of times index was found int match_count; coef_denom denom; // store the computation of the derivative of the constant int previous_constant_index=0; Coefficient dC; Coefficient tmp_coef; init_Grouped_Polynomial(output, flow_equation.length); // loop over equations for(k=0;k0){ coefficient_append_noinit(factor,number_Qprod_ret(quot(match_count,1),flow_equation.coefs[k].nums[i]), flow_equation.coefs[k].denoms[i], (*output).coefs+k); } else{ free_Int_Array(factor); } // derivative of the denominator if(flow_equation.coefs[k].denoms[i].power>0){ // check whether the derivative was already computed if(flow_equation.coefs[k].denoms[i].index!=previous_constant_index){ // if not first, then free if(previous_constant_index!=0){ free_Coefficient(dC); previous_constant_index=0; } init_Coefficient(&dC,COEF_SIZE); coefficient_deriv_noinit(flow_equation.coefs[intlist_find_err(flow_equation.indices, flow_equation.length, flow_equation.coefs[k].denoms[i].index)], index, &dC); previous_constant_index=flow_equation.coefs[k].denoms[i].index; } init_Coefficient(&tmp_coef, dC.length); coefficient_append(flow_equation.coefs[k].factors[i], number_Qprod_ret(quot(-flow_equation.coefs[k].denoms[i].power,1), flow_equation.coefs[k].nums[i]), flow_equation.coefs[k].denoms[i], &tmp_coef); (tmp_coef.denoms[0].power)++; coefficient_prod_chain(dC, &tmp_coef); coefficient_concat_noinit(tmp_coef, (*output).coefs+k); } } // memory safe if((*output).coefs[k].length>0){ coefficient_simplify((*output).coefs+k); } 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).coefs+k); } } free_Coefficient(dC); return(0); } */ // print a grouped polynomial // prepend the indices on the left side with lhs_pre, and those on the right by rhs_pre int grouped_polynomial_print(Grouped_Polynomial grouped_polynomial, char lhs_pre, char rhs_pre){ int i,j; Char_Array buffer; int dcount; // for each equation for(i=0;i=0){ // reduce them to a common denominator (not much is gained from trying to simplify them) coefficient_common_denominator(constant, (*out).coefs+i); //coefficient_simplify_rational(constant, (*out).coefs+i); } } } return(0); }