/* Copyright 2015 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. */ /* As of version 1.0, the mean of a monomial is computed directly */ #include "mean.h" #include #include #include #include "definitions.cpp" #include "tools.h" #include "polynomial.h" #include "rational.h" #include "array.h" #include "fields.h" #include "number.h" // mean of a monomial int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Matrix propagator){ int sign=1; // +/- internal fields Int_Array internal_plus; Int_Array internal_minus; // init out *out=polynomial_one(); // sort first monomial_sort(monomial, 0, monomial.length-1, fields, &sign); polynomial_multiply_Qscalar(*out, quot(sign,1)); // get internals // (*out).monomials is the first element of out but it only has 1 element // first, free (*out).monomials[0] free_Int_Array((*out).monomials[0]); get_internals(monomial, &internal_plus, &internal_minus, (*out).monomials, fields); if(internal_plus.length>0 && internal_minus.length>0){ mean_internal(internal_plus, internal_minus, out, propagator, fields); } free_Int_Array(internal_plus); free_Int_Array(internal_minus); return(0); } // compute the mean of a monomial of internal fields (with split + and -) int mean_internal(Int_Array internal_plus, Int_Array internal_minus, Polynomial* out, Polynomial_Matrix propagator, Fields_Table fields){ if(internal_plus.length!=internal_minus.length){ fprintf(stderr,"error: monomial contains unmatched +/- fields\n"); exit(-1); } int n=internal_minus.length; // pairing as an array of positions int* pairing=calloc(n,sizeof(int)); // specifies which indices are available for pairing int* mask=calloc(n,sizeof(int)); // signature of the permutation int pairing_sign; // sign from mixing - and + together int mixing_sign; Polynomial num; Polynomial num_summed=polynomial_zero(); // propagator matrix indices int* indices_minus=calloc(n,sizeof(int)); int* indices_plus=calloc(n,sizeof(int)); int i; // whether the next pairing exists int exists_next=0; // indices for(i=0;i=0 && move=0 && move=0 && start=0;i--){ // move i-th mask[pairing[i]]=0; // search for next possible position for(j=pairing[i]+1;j=n){ break; } } } } // if the next position was found, then don't try to move the previous pairings break; } // if no next position is found, store the pairing outside the array (so the algorithm stops when the first pairing is outside the array) else{ pairing[i]=n; } } } number_prod_chain(num_summed,outnum); free_Number(num_summed); free(pairing); free(mask); return(0); } */ // get lists of internal fields from a monomial (separate + and -) // requires the monomial to be sorted (for the sign to be correct) int get_internals(Int_Array monomial, Int_Array* internal_plus, Int_Array* internal_minus, Int_Array* others, Fields_Table fields){ int i; init_Int_Array(internal_plus, monomial.length); init_Int_Array(internal_minus, monomial.length); init_Int_Array(others, monomial.length); for (i=0;i=0){ // split +/- fields if(monomial.values[i]>0){ int_array_append(monomial.values[i],internal_plus); } else{ int_array_append(monomial.values[i],internal_minus); } } else{ int_array_append(monomial.values[i], others); } } return(0); } // compute the mean of a monomial containing symbolic expressions // keep track of which means were already computed int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed){ Int_Array symbol_list; int i; int power; int* current_term; Polynomial mean_num; Int_Array tmp_monomial; Number tmp_num; Int_Array base_monomial; int sign; // whether or not the next term exists int exists_next=0; // simplify polynomial periodically int simplify_freq=1; Polynomial mean_poly; init_Polynomial(output, POLY_SIZE); // check whether the mean was already computed for(i=0;i<(*computed).length;i++){ if(int_array_cmp((*computed).lhs[i], monomial)==0){ // write polynomial polynomial_concat((*computed).rhs[i], output); return(0); } } init_Int_Array(&symbol_list, monomial.length); init_Int_Array(&base_monomial, monomial.length); // generate symbols list for(i=0;i=0 && move=0 && move=0 && start0){ sign=1; monomial_sort_groups(monomial, 0, monomial.length-1, fields, groups, &sign); } // construct groups and take mean init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); for(i=0;i<=monomial.length;i++){ // new group if(i0 && next_group!=group) || i==monomial.length){ mean_symbols(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); // if zero if(polynomial_is_zero(tmp_poly)==1){ // set output to 0 free_Polynomial(*output); init_Polynomial(output, 1); free_Polynomial(tmp_poly); break; } // add to output if(polynomial_is_zero(*output)==1){ polynomial_concat(tmp_poly, output); } else{ polynomial_prod_chain_nosimplify(tmp_poly, output, fields); } free_Polynomial(tmp_poly); // reset tmp_monomial free_Int_Array(tmp_monomial); init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); } // add to monomial if(i