/* 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 "polynomial.h" #include #include #include "definitions.cpp" #include "rational.h" #include "tools.h" #include "mean.h" #include "coefficient.h" #include "istring.h" #include "array.h" #include "number.h" #include "fields.h" #include "parse_file.h" // allocate memory int init_Polynomial(Polynomial* polynomial,int size){ (*polynomial).monomials=calloc(size,sizeof(Int_Array)); (*polynomial).factors=calloc(size,sizeof(Int_Array)); (*polynomial).nums=calloc(size,sizeof(Number)); (*polynomial).length=0; (*polynomial).memory=size; return(0); } // free memory int free_Polynomial(Polynomial polynomial){ int i; for(i=0;i=(*output).memory){ resize_polynomial(output,2*(*output).memory+1); } // copy and allocate int_array_cpy(monomial,(*output).monomials+offset); int_array_cpy(factor,(*output).factors+offset); number_cpy(num,(*output).nums+offset); //increment length (*output).length++; return(0); } // append an element to a polynomial without allocating memory int polynomial_append_noinit(Int_Array monomial, Int_Array factor, Number num, Polynomial* output){ int offset=(*output).length; if((*output).length>=(*output).memory){ resize_polynomial(output,2*(*output).memory+1); } // copy without allocating (*output).monomials[offset]=monomial; (*output).factors[offset]=factor; (*output).nums[offset]=num; // increment length (*output).length++; return(0); } // noinit, and if there already exists an element with the same monomial and factor, then just add numbers int polynomial_append_noinit_inplace(Int_Array monomial, Int_Array factor, Number num, Polynomial* output){ int i; int foundit=0; for(i=0;i<(*output).length;i++){ if(int_array_cmp(monomial, (*output).monomials[i])==0 && int_array_cmp(factor, (*output).factors[i])==0){ number_add_chain(num,(*output).nums+i); foundit=1; free_Number(num); free_Int_Array(monomial); free_Int_Array(factor); break; } } if(foundit==0){ polynomial_append_noinit(monomial, factor, num, output); } return(0); } // concatenate two polynomials int polynomial_concat(Polynomial input, Polynomial* output){ int i; for(i=0;i=input_polynomial.length;i--){ // try to advance pointer (current_term[i])++; // if the step fails, keep on looping, if not, set all the following // pointers to the latest position if(current_term[i]1){ if(power>33){ fprintf(stderr,"error: trying to take a power of a polynomial that is too high (>33)\n"); exit(-1); } // next power polynomial_prod(input_polynomial,previous_power,&tmp_poly, fields); // free free_Polynomial(previous_power); } else{ polynomial_cpy(input_polynomial,&tmp_poly); } // if the power is high enough that V^p=0, then stop if(tmp_poly.length==0){ free_Polynomial(tmp_poly); break; } // copy for next power polynomial_cpy(tmp_poly,&previous_power); // 1/p! polynomial_multiply_Qscalar(tmp_poly,quot(1,factorial(power))); // append tmp to the output polynomial_concat_noinit(tmp_poly,output); // increase power power++; } return(0); } // log(1+W) int polynomial_logarithm(Polynomial input_polynomial,Polynomial* output, Fields_Table fields){ // a buffer for the result of a given power Polynomial tmp_poly; // a buffer for the previous power Polynomial previous_power; // power int power=1; // allocate memory init_Polynomial(output,POLY_SIZE); while(1){ if(power>1){ // next power polynomial_prod(input_polynomial,previous_power,&tmp_poly, fields); // free free_Polynomial(previous_power); } else{ polynomial_cpy(input_polynomial,&tmp_poly); } // if the power is high enough that V^p=0, then stop if(tmp_poly.length==0){ free_Polynomial(tmp_poly); break; } // copy for next power polynomial_cpy(tmp_poly,&previous_power); // (-1)^{p-1}/p polynomial_multiply_Qscalar(tmp_poly,quot(ipower(-1,power-1),power)); // append tmp to the output polynomial_concat_noinit(tmp_poly,output); // increase power power++; } return(0); } // check whether a monomial vanishes int check_monomial(Int_Array monomial, Fields_Table fields){ int i,j; for(i=0;i0){ match++; } else if(monomial.values[i]<0){ match--; } } // check for repetitions if(is_fermion(monomial.values[i], fields)==1){ for(j=i+1;j0){ match_internals++; } else if((*polynomial).monomials[i].values[j]<0){ match_internals--; } } // don't remove a term containing virtual_field else if(type==FIELD_VIRTUAL){ match_internals=0; break; } } if(match_internals==0){ polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], &output); } } free_Polynomial(*polynomial); *polynomial=output; return(0); } // denominator of a multinomal factor: m1!m2!... // requires terms to be sorted int multinomial(int power,int* terms){ int multiple=1; int ret=1; int i; // the number of numbers to be multiplied in the multinomial is // equal to power-1 (the first is 1) for(i=1;i=(*polynomial).length-1 || monomial_cmp!=0 || factor_cmp!=0 ){ // check that the polynomial is not trivial if(number_is_zero(new_num)!=1){ polynomial_append((*polynomial).monomials[i],(*polynomial).factors[i],new_num,&output); } // reset new numerical factor free_Number(new_num); init_Number(&new_num,NUMBER_SIZE); } } free_Number(new_num); free_Polynomial(*polynomial); *polynomial=output; return(0); } // sort a polynomial // requires the monomials and factors to be sorted int polynomial_sort(Polynomial* polynomial, int begin, int end){ int i; int index; int monomial_cmp; int factor_cmp; // the pivot: middle of the array int pivot=(begin+end)/2; // if the array is non trivial if(beginpost_nc;j--){ monomial.values[j]=monomial.values[j-1]; } monomial.values[post_nc]=tmp; post_nc++; } } monomial_sort_nonc(monomial, post_nc, monomial.length-1, fields, sign); return(0); } // without noncommuting terms int monomial_sort_nonc(Int_Array monomial, int begin, int end, Fields_Table fields, int* sign){ int i; int index; // the pivot: middle of the monomial int pivot=(begin+end)/2; // if the monomial is non trivial if(begin type2){ return(1); } if(monomial.values[pos1] < monomial.values[pos2]){ return(-1); } else if (monomial.values[pos1] > monomial.values[pos2]){ return(1); } return(0); } // exchange two fields (with sign) int exchange_monomial_terms(Int_Array monomial, int pos1, int pos2, Fields_Table fields, int* sign){ int tmp=monomial.values[pos1]; int f1,f2; int i; monomial.values[pos1]=monomial.values[pos2]; monomial.values[pos2]=tmp; // sign change // only if the exchange is not trivial if(pos1!=pos2){ f1=is_fermion(monomial.values[pos1],fields); f2=is_fermion(monomial.values[pos2],fields); // if both Fermions then sign if(f1==1 && f2==1){ *sign*=-1; } // if only one of them is a Fermion, then count the number of Fermions between them else if(f1==1 || f2==1){ for(i=min(pos1,pos2)+1;i group2){ return(1); } int type1=field_type(monomial.values[pos1], fields); int type2=field_type(monomial.values[pos2],fields); if(type1 < type2){ return(-1); } else if(type1 > type2){ return(1); } if(monomial.values[pos1] < monomial.values[pos2]){ return(-1); } else if (monomial.values[pos1] > monomial.values[pos2]){ return(1); } return(0); } // convert and idtable to a polynomial int idtable_to_polynomial(Id_Table idtable, Polynomial* polynomial){ int i,j; int start=0; // allocate memory init_Polynomial(polynomial,POLY_SIZE); for(i=0;i0){ // initialize coef to store the product of factors init_Coefficient(&coef, POLY_SIZE); // first term index=intlist_find_err(equations.indices, equations.length, (*polynomial).factors[i].values[0]); if(index>=0){ coefficient_cpy_noinit(equations.coefs[index],&coef); } // other terms for(j=1;j<(*polynomial).factors[i].length;j++){ index=intlist_find_err(equations.indices, equations.length, (*polynomial).factors[i].values[j]); if(index>=0){ coefficient_prod_chain(equations.coefs[index],&coef); } } // new polynomial terms for(j=0;j