diff options
Diffstat (limited to 'src')
60 files changed, 3070 insertions, 682 deletions
diff --git a/src/array.c b/src/array.c index 11d14f7..7fb6bd8 100644 --- a/src/array.c +++ b/src/array.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -72,6 +72,14 @@ int int_array_append(int val, Int_Array* output){ return(0); } +// add a value only if it is not already present +int int_array_append_unique(int val, Int_Array* output){ + if(int_array_find(val,*output)<0){ + int_array_append(val,output); + } + return(0); +} + // concatenate int int_array_concat(Int_Array input, Int_Array* output){ int i; @@ -87,6 +95,15 @@ int int_array_concat(Int_Array input, Int_Array* output){ return(0); } +// concat but only add values that are not already present in the array +int int_array_concat_unique(Int_Array input, Int_Array* output){ + int i; + for(i=0;i<input.length;i++){ + int_array_append_unique(input.values[i],output); + } + return(0); +} + // find (does not assume the array is sorted) int int_array_find(int val, Int_Array array){ int i; @@ -199,7 +216,12 @@ int int_array_print(Int_Array array){ for(i=0;i<array.length-1;i++){ printf("%d,",array.values[i]); } - printf("%d)",array.values[array.length-1]); + if(array.length>0){ + printf("%d)",array.values[array.length-1]); + } + else{ + printf(")"); + } return(0); } @@ -334,6 +356,19 @@ int char_array_concat(Char_Array input, Char_Array* output){ return(0); } +// substring +int char_array_substring(Char_Array str, int begin, int end, Char_Array* substr){ + int i; + if(begin>end || begin<0 || end>=str.length){ + fprintf(stderr,"error: cannot extract a substring [%d,%d] from a string of length %d\n", begin, end, str.length); + exit(-1); + } + init_Char_Array(substr,end-begin); + for(i=begin;i<=end;i++){ + char_array_append(str.str[i],substr); + } + return(0); +} // convert to char* @@ -343,7 +378,7 @@ int char_array_to_str(Char_Array input, char** output){ for(i=0;i<input.length;i++){ (*output)[i]=input.str[i]; } - if((*output)[input.length-1]!='\0'){ + if(input.length==0 || (*output)[input.length-1]!='\0'){ (*output)[input.length]='\0'; } return(0); @@ -371,6 +406,34 @@ int str_to_char_array(char* str, Char_Array* output){ return(0); } +// compare char_array's +int char_array_cmp(Char_Array char_array1, Char_Array char_array2){ + int j; + if(char_array1.length!=char_array2.length){ + return(0); + } + for(j=0;j<char_array1.length && j<char_array2.length;j++){ + if(char_array1.str[j]!=char_array2.str[j]){ + return(0); + } + } + return(1); +} + +// compare a char_array and a char* +int char_array_cmp_str(Char_Array char_array, char* str){ + int j; + for(j=0;j<char_array.length && str[j]!='\0';j++){ + if(char_array.str[j]!=str[j]){ + return(0); + } + } + if(j==char_array.length && str[j]=='\0'){ + return(1); + } + return(0); +} + // format strings int char_array_snprintf(Char_Array* output, char* fmt, ...){ diff --git a/src/array.h b/src/array.h index fb74e67..480b589 100644 --- a/src/array.h +++ b/src/array.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -34,8 +34,12 @@ int int_array_resize(Int_Array* array, int newsize); // add a value int int_array_append(int val, Int_Array* output); +// add a value only if it is not already present +int int_array_append_unique(int val, Int_Array* output); // concatenate int int_array_concat(Int_Array input, Int_Array* output); +// concat but only add values that are not already present in the array +int int_array_concat_unique(Int_Array input, Int_Array* output); // find (does not assume the array is sorted) int int_array_find(int val, Int_Array array); @@ -75,6 +79,9 @@ int char_array_append_str(char* str, Char_Array* output); // concatenate int char_array_concat(Char_Array input, Char_Array* output); +// substring +int char_array_substring(Char_Array str, int begin, int end, Char_Array* substr); + // convert to char* int char_array_to_str(Char_Array input, char** output); // noinit (changes the size of input if needed) @@ -82,6 +89,11 @@ char* char_array_to_str_noinit(Char_Array* input); // convert from char* int str_to_char_array(char* str, Char_Array* output); +// compare char_array's +int char_array_cmp(Char_Array char_array1, Char_Array char_array2); +// compare a char_array and a char* +int char_array_cmp_str(Char_Array char_array, char* str); + // format strings int char_array_snprintf(Char_Array* output, char* fmt, ...); diff --git a/src/cli_parser.c b/src/cli_parser.c index bdca700..6012e8a 100644 --- a/src/cli_parser.c +++ b/src/cli_parser.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -121,3 +121,23 @@ int find_str_arg(char* title, Str_Array str_args){ } } +// find a string argument with the specified title +// namespace support +int find_str_arg_ns(char* title, Char_Array namespace, Str_Array str_args){ + Char_Array buffer; + int ret; + + // append namespace to title + char_array_cpy(namespace,&buffer); + char_array_append(':',&buffer); + char_array_append_str(title,&buffer); + + // check whether the namespace entry exists + ret=find_str_arg(char_array_to_str_noinit(&buffer), str_args); + free_Char_Array(buffer); + // if not, use global entry + if(ret==-1){ + return(find_str_arg(title, str_args)); + } + return(ret); +} diff --git a/src/cli_parser.h b/src/cli_parser.h index b050e37..b66608c 100644 --- a/src/cli_parser.h +++ b/src/cli_parser.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -30,6 +30,8 @@ int read_config_file(Str_Array* str_args, const char* file, int read_from_stdin) int get_str_arg_title(Char_Array str_arg, Char_Array* out); // find a string argument with the specified title int find_str_arg(char* title, Str_Array str_args); +// namespace support +int find_str_arg_ns(char* title, Char_Array namespace, Str_Array str_args); #endif diff --git a/src/coefficient.c b/src/coefficient.c index d4cb6eb..1efe8fd 100644 --- a/src/coefficient.c +++ b/src/coefficient.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -202,6 +202,235 @@ int coefficient_simplify(Coefficient* coefficient){ return(0); } +// put all terms under a common denominator and simplify the resulting fraction +int coefficient_simplify_rational(Coefficient constant, Coefficient* coefficient){ + int ret; + Coefficient remainder; + Coefficient quotient; + Coefficient quotient_prev; + Coefficient out; + int power; + int max_power; + + // common denominator + coefficient_common_denominator(constant, coefficient); + + // init + init_Coefficient(&out, COEF_SIZE); + + // simplify, one power at a time + // largest power (larger powers are at the end) + max_power=(*coefficient).denoms[(*coefficient).length-1].power; + + quotient_prev=*coefficient; + for(power=max_power;power>=1;power--){ + ret=coefficient_simplify_fraction(constant, quotient_prev, &remainder, "ient); + + // if fail to simplify, stop + if(ret<0){ + if(power<max_power){ + coefficient_concat_noinit(quotient_prev, &out); + } + else{ + coefficient_concat(quotient_prev, &out); + } + break; + } + + // add to output + coefficient_concat_noinit(remainder, &out); + } + // if the factorization always succeeded + if(max_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;i<max_power-1;i++){ + // start from previous product + if(i==0){ + coefficient_cpy(constant, C_n+i); + } + else{ + coefficient_cpy(C_n[i-1], C_n+i); + } + // multiply by constant + coefficient_prod_chain(constant, C_n+i); + } + + // multiply each term + for (i=0;i<(*coefficient).length;i++){ + init_Coefficient(&tmp, COEF_SIZE); + // start with numerator + coefficient_append_noinit((*coefficient).factors[i], (*coefficient).nums[i], (*coefficient).denoms[i], &tmp); + // multiply + if((*coefficient).denoms[i].power<max_power){ + if((*coefficient).denoms[i].power==max_power-1){ + coefficient_prod_chain(constant, &tmp); + } + else{ + coefficient_prod_chain(C_n[max_power-(*coefficient).denoms[i].power-2], &tmp); + } + } + + // set denom + for(j=0;j<tmp.length;j++){ + tmp.denoms[j].power=max_power; + } + + // add to out + coefficient_concat_noinit(tmp, &out); + } + + // free C_n + for(i=0;i<max_power-1;i++){ + free_Coefficient(C_n[i]); + } + free(C_n); + + // free coefficient vectors + free((*coefficient).factors); + free((*coefficient).nums); + free((*coefficient).denoms); + + // set output + *coefficient=out; + + coefficient_simplify(coefficient); + + return(0); +} + +// simplify coefficient / constant +// returns both the remainder and the quotient +// assumes both coefficient and constant are ordered with the highest order terms last +int coefficient_simplify_fraction(Coefficient constant, Coefficient coefficient, Coefficient* remainder, Coefficient* out){ + Coefficient tmp; + int step_counter=0; + int max_order; + int i,j,k; + Int_Array rfactors; + + if(constant.length==0){ + // nothing to do + return 0; + } + + coefficient_cpy(coefficient, remainder); + init_Coefficient(out, COEF_SIZE); + + // continue until (*remainder) is of lower order than constant + while((*remainder).length>0 && (*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].length<max_order){ + free_Coefficient(*remainder); + free_Coefficient(*out); + return -2; + } + + // check whether the term can be a factor of the last term of the (*remainder) + if(int_array_is_subarray_ordered(constant.factors[i], rfactors)==1){ + // extract the factors that are not in constant + init_Coefficient(&tmp, constant.length); + + // init with one term + tmp.length=1; + init_Int_Array(tmp.factors,MONOMIAL_SIZE); + + for(j=0,k=0;j<rfactors.length;j++){ + // check that index is not in constant + if(k<constant.factors[i].length){ + if(rfactors.values[j]!=constant.factors[i].values[k]){ + int_array_append(rfactors.values[j],tmp.factors); + } + else{ + // move to next term in constant + k++; + } + } + } + + // numerical prefactor: term in the (*remainder) / term in the constant + number_quot((*remainder).nums[(*remainder).length-1], constant.nums[i], tmp.nums); + // denominator (dummy) + tmp.denoms[0]=(*remainder).denoms[(*remainder).length-1]; + + // add to out + coefficient_concat(tmp, out); + + // multiply by -1 + Q minus_1; + minus_1.numerator=-1; + minus_1.denominator=1; + number_Qprod_chain(minus_1, tmp.nums); + + // multiply by constant + coefficient_prod_chain(constant, &tmp); + + // add to remainder + coefficient_concat(tmp, remainder); + + // free memory + free_Coefficient(tmp); + + // simplify + coefficient_simplify(remainder); + + break; + } + } + } + + // success! + // decrease power of constant + for(i=0;i<(*out).length;i++){ + (*out).denoms[i].power=(*out).denoms[i].power-1; + } + + return(0); +} + // sort the terms in an equation (quicksort algorithm) int sort_coefficient(Coefficient* coefficient, int begin, int end){ int i; @@ -251,7 +480,7 @@ int exchange_coefficient_terms(int i, int j, Coefficient* coefficient){ return(0); } -// derive a coefficient with respect to an index +// differentiate a coefficient with respect to an index int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output){ int i,j; // temp list of indices @@ -325,7 +554,7 @@ int coefficient_deriv(Coefficient input, int index, Coefficient* output){ } /* -// derive a coefficient with respect to an index (as a polynomial) (does not derive the 1/(1+C)^p ) +// differentiate a coefficient with respect to an index (as a polynomial) (does not differentiate the 1/(1+C)^p ) int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output){ int i; // temp list of indices @@ -365,7 +594,7 @@ int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output){ return(0); } -// derive a monomial with respect to an index +// 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; @@ -414,14 +643,14 @@ int coefficient_prod(Coefficient coef1, Coefficient coef2, Coefficient* output){ int_array_concat(coef2.factors[j],&factor); // don't throw an error if the power is 0 - if(coef2.denoms[i].power==0){ - coef2.denoms[i].index=coef1.denoms[i].index; + if(coef2.denoms[j].power==0){ + coef2.denoms[j].index=coef1.denoms[i].index; } else if(coef1.denoms[i].power==0){ - coef1.denoms[i].index=coef2.denoms[i].index; + coef1.denoms[i].index=coef2.denoms[j].index; } if(coef1.denoms[i].index!=coef2.denoms[j].index){ - fprintf(stderr,"error: cannot multiply flow equations with different constants\n"); + fprintf(stderr,"error: cannot multiply flow equations with different constants: got %d and %d\n", coef1.denoms[i].index, coef2.denoms[j].index); exit(-1); } denom=coef1.denoms[i]; diff --git a/src/coefficient.h b/src/coefficient.h index 43dd313..f8a813a 100644 --- a/src/coefficient.h +++ b/src/coefficient.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -48,12 +48,20 @@ int coefficient_concat_noinit(Coefficient input, Coefficient* output); // simplify a Coefficient int coefficient_simplify(Coefficient* coefficient); + +// put all terms under a common denominator and simplify the resulting fraction +int coefficient_simplify_rational(Coefficient constant, Coefficient* coefficient); +// put all terms under a common denominator +int coefficient_common_denominator(Coefficient constant, Coefficient* coefficient); +// simplify coefficient / constant +int coefficient_simplify_fraction(Coefficient constant, Coefficient coefficient, Coefficient* remainder, Coefficient* out); + // sort the terms in an equation (quicksort algorithm) int sort_coefficient(Coefficient* coefficient, int begin, int end); // exchange two terms (for the sorting algorithm) int exchange_coefficient_terms(int i, int j, Coefficient* coefficient); -// derive a coefficient with respect to an index (as a polynomial) (does not derive the 1/(1+C)^p ) +// differentiate a coefficient with respect to an index (as a polynomial) (does not differentiate the 1/(1+C)^p ) int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output); int coefficient_deriv(Coefficient input, int index, Coefficient* output); diff --git a/src/definitions.cpp b/src/definitions.cpp index 30f021f..db09e57 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -33,10 +33,16 @@ limitations under the License. #define EQUATION_SIZE 20 // number of fields #define FIELDS_SIZE 50 +// number of variables +#define VARIABLES_SIZE 10 // number of elements in numbers #define NUMBER_SIZE 5 // number of elements in a group #define GROUP_SIZE 5 +// number of children per node in a symbol_tree +#define SYMBOL_TREE_SIZE 2 +// size of character string in symbol tree +#define SYMBOL_TREE_LABEL_SIZE 10 // display options @@ -55,6 +61,6 @@ limitations under the License. #define FIELD_PARAMETER 1 #define FIELD_EXTERNAL 2 #define FIELD_INTERNAL 3 -#define FIELD_SYMBOL 4 +#define FIELD_VIRTUAL 4 #endif diff --git a/src/determinant.c b/src/determinant.c new file mode 100644 index 0000000..906c75f --- /dev/null +++ b/src/determinant.c @@ -0,0 +1,93 @@ +#include "determinant.h" + +#include "number.h" +#include "rational.h" +#include "definitions.cpp" + +// determinant of a matrix +// replaces the matrix by its LU decomposition +int determinant_inplace(Number_Matrix M, Number* out){ + int i; + int sign_correction; + + LU_dcmp_inplace(M, &sign_correction); + + if(sign_correction==0){ + *out=number_zero(); + return(0); + } + + *out=number_one(); + if(sign_correction==-1){ + number_Qprod_chain(quot(-1,1), out); + } + + for(i=0;i<M.length;i++){ + number_prod_chain(M.matrix[i][i], out); + } + + return(0); +} + +// LU decomposition +// uses pivoting to avoid dividing by 0 +// the sign_correction should be multiplied to the determinant to obtain the right value +// if dividing by 0 is unavoidable, then the determinant is 0, and sign_correction is set to 0 +int LU_dcmp_inplace(Number_Matrix M, int* sign_correction){ + int i,j,k,pivot; + Number tmp; + + *sign_correction=1; + + for(j=0;j<M.length;j++){ + for(i=0;i<=j;i++){ + for(k=0;k<i;k++){ + // -M[i][k]*M[k][j] + number_prod(M.matrix[i][k], M.matrix[k][j], &tmp); + number_Qprod_chain(quot(-1,1), &tmp); + number_add_chain(tmp, M.matrix[i]+j); + free_Number(tmp); + } + } + for(i=j+1;i<M.length;i++){ + for(k=0;k<j;k++){ + // -M[i][k]*M[k][j] + number_prod(M.matrix[i][k], M.matrix[k][j], &tmp); + number_Qprod_chain(quot(-1,1), &tmp); + number_add_chain(tmp, M.matrix[i]+j); + free_Number(tmp); + } + } + + // pivot if M[j][j]==0 + // find first M[j][j] that is not 0 + for(pivot=j;pivot<M.length && number_is_zero(M.matrix[pivot][j])==1;pivot++){} + + // no non-zero M[j][j] left: return + if(pivot>=M.length){ + *sign_correction=0; + return(0); + } + // pivot if needed + if(pivot!=j){ + for(k=0;k<M.length;k++){ + tmp=M.matrix[j][k]; + M.matrix[j][k]=M.matrix[pivot][k]; + M.matrix[pivot][k]=tmp; + } + *sign_correction*=-1; + + } + + for(i=j+1;i<M.length;i++){ + // do not use the inplace algorithm if M[j][j] has more than one terms, since it would be modified by the inplace function + if(M.matrix[j][j].length<=1){ + number_quot_inplace(M.matrix[i]+j, M.matrix[j]+j); + } + else{ + number_quot_chain(M.matrix[i]+j, M.matrix[j][j]); + } + } + } + return(0); +} diff --git a/src/determinant.h b/src/determinant.h new file mode 100644 index 0000000..613be87 --- /dev/null +++ b/src/determinant.h @@ -0,0 +1,17 @@ +/* + Compute the determinant of a number matrix +*/ + +#ifndef DETERMINANT_H +#define DETERMINANT_H + +#include "types.h" + +// determinant of a matrix +int determinant_inplace(Number_Matrix M, Number* out); + +// LU decomposition +int LU_dcmp_inplace(Number_Matrix M, int* sign_correction); + + +#endif diff --git a/src/expansions.c b/src/expansions.c deleted file mode 100644 index c889829..0000000 --- a/src/expansions.c +++ /dev/null @@ -1,28 +0,0 @@ -/* -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. -*/ - -#include "expansions.h" - -#include <stdio.h> -#include <stdlib.h> -#include "definitions.cpp" -#include "tools.h" -#include "array.h" -#include "polynomial.h" -#include "number.h" -#include "rational.h" - - diff --git a/src/expansions.h b/src/expansions.h deleted file mode 100644 index 85d6c2b..0000000 --- a/src/expansions.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -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. -*/ - -/* -Compute exp(V) and log(1+W) -*/ - -#ifndef EXPANSIONS_H -#define EXPANSIONS_H - -#include "polynomial.h" -#include "fields.h" - -// exp(V) -int expand_exponential(Polynomial input_polynomial,Polynomial* output, Fields_Table fields); - -// log(1+W) -int expand_logarithm(Polynomial input_polynomial, Polynomial* output, Fields_Table fields); - - -#endif diff --git a/src/fields.c b/src/fields.c index bfd1f39..7be84df 100644 --- a/src/fields.c +++ b/src/fields.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -23,6 +23,13 @@ limitations under the License. #include "polynomial.h" #include "array.h" #include "rational.h" +#include "tree.h" + +//--------------------------------------------------------------------- +// +// Fields_Table +// +//--------------------------------------------------------------------- // init and free for Fields_Table int init_Fields_Table(Fields_Table* fields){ @@ -30,7 +37,7 @@ int init_Fields_Table(Fields_Table* fields){ init_Int_Array(&((*fields).external),FIELDS_SIZE); init_Int_Array(&((*fields).internal),FIELDS_SIZE); init_Identities(&((*fields).ids), FIELDS_SIZE); - init_Symbols(&((*fields).symbols), FIELDS_SIZE); + init_Virtual_fields(&((*fields).virtual_fields), FIELDS_SIZE); init_Int_Array(&((*fields).fermions),FIELDS_SIZE); init_Int_Array(&((*fields).noncommuting),FIELDS_SIZE); return(0); @@ -40,7 +47,7 @@ int free_Fields_Table(Fields_Table fields){ free_Int_Array(fields.external); free_Int_Array(fields.internal); free_Identities(fields.ids); - free_Symbols(fields.symbols); + free_Virtual_fields(fields.virtual_fields); free_Int_Array(fields.fermions); free_Int_Array(fields.noncommuting); return(0); @@ -57,11 +64,11 @@ int field_type(int index, Fields_Table fields){ else if(int_array_find(abs(index), fields.internal)>=0){ return(FIELD_INTERNAL); } - else if(intlist_find(fields.symbols.indices, fields.symbols.length, index)>=0){ - return(FIELD_SYMBOL); + else if(intlist_find(fields.virtual_fields.indices, fields.virtual_fields.length, index)>=0){ + return(FIELD_VIRTUAL); } - fprintf(stderr,"error: index %d is neither a parameter nor an external or an internal field, nor a symbol\n",index); + fprintf(stderr,"error: index %d is neither a parameter nor an external or an internal field, nor a virtual field\n",index); exit(-1); } @@ -86,7 +93,11 @@ int is_noncommuting(int index, Fields_Table fields){ } -// ------------------ Identities -------------------- +//--------------------------------------------------------------------- +// +// Identities +// +//--------------------------------------------------------------------- // allocate memory int init_Identities(Identities* identities,int size){ @@ -314,6 +325,11 @@ int int_array_is_subarray_noncommuting(Int_Array input, Int_Array test_array, Fi int match_nc; int first=-1; + // cannot fit + if(test_array.length<input.length){ + return(-1); + } + // bound noncommuting elements while(is_noncommuting(input.values[post_nc], fields)==1){ post_nc++; @@ -324,7 +340,7 @@ int int_array_is_subarray_noncommuting(Int_Array input, Int_Array test_array, Fi match_nc=1; } for(j=1;j<post_nc;j++){ - if(test_array.values[i+j]!=input.values[j]){ + if(i+j>=test_array.length || test_array.values[i+j]!=input.values[j]){ match_nc=0; } } @@ -359,57 +375,61 @@ int int_array_is_subarray_noncommuting(Int_Array input, Int_Array test_array, Fi } -// ------------------ Symbols -------------------- +//--------------------------------------------------------------------- +// +// Virtual_fields +// +//--------------------------------------------------------------------- // allocate memory -int init_Symbols(Symbols* symbols,int size){ - (*symbols).indices=calloc(size,sizeof(int)); - (*symbols).expr=calloc(size,sizeof(Polynomial)); - (*symbols).length=0; - (*symbols).memory=size; +int init_Virtual_fields(Virtual_fields* virtual_fields,int size){ + (*virtual_fields).indices=calloc(size,sizeof(int)); + (*virtual_fields).expr=calloc(size,sizeof(Polynomial)); + (*virtual_fields).length=0; + (*virtual_fields).memory=size; return(0); } // free memory -int free_Symbols(Symbols symbols){ +int free_Virtual_fields(Virtual_fields virtual_fields){ int i; - for(i=0;i<symbols.length;i++){ - free_Polynomial(symbols.expr[i]); + for(i=0;i<virtual_fields.length;i++){ + free_Polynomial(virtual_fields.expr[i]); } - free(symbols.indices); - free(symbols.expr); + free(virtual_fields.indices); + free(virtual_fields.expr); return(0); } // resize -int resize_symbols(Symbols* symbols,int new_size){ - Symbols new_symbols; +int resize_virtual_fields(Virtual_fields* virtual_fields,int new_size){ + Virtual_fields new_virtual_fields; int i; - init_Symbols(&new_symbols,new_size); - for(i=0;i<(*symbols).length;i++){ - new_symbols.indices[i]=(*symbols).indices[i]; - new_symbols.expr[i]=(*symbols).expr[i]; + init_Virtual_fields(&new_virtual_fields,new_size); + for(i=0;i<(*virtual_fields).length;i++){ + new_virtual_fields.indices[i]=(*virtual_fields).indices[i]; + new_virtual_fields.expr[i]=(*virtual_fields).expr[i]; } - new_symbols.length=(*symbols).length; + new_virtual_fields.length=(*virtual_fields).length; - free((*symbols).indices); - free((*symbols).expr); + free((*virtual_fields).indices); + free((*virtual_fields).expr); - *symbols=new_symbols; + *virtual_fields=new_virtual_fields; return(0); } // copy -int symbols_cpy(Symbols input, Symbols* output){ - init_Symbols(output,input.length); - symbols_cpy_noinit(input,output); +int virtual_fields_cpy(Virtual_fields input, Virtual_fields* output){ + init_Virtual_fields(output,input.length); + virtual_fields_cpy_noinit(input,output); return(0); } -int symbols_cpy_noinit(Symbols input, Symbols* output){ +int virtual_fields_cpy_noinit(Virtual_fields input, Virtual_fields* output){ int i; if((*output).memory<input.length){ - fprintf(stderr,"error: trying to copy a symbols collection of length %d to another with memory %d\n",input.length,(*output).memory); + fprintf(stderr,"error: trying to copy a virtual fields collection of length %d to another with memory %d\n",input.length,(*output).memory); exit(-1); } for(i=0;i<input.length;i++){ @@ -421,12 +441,12 @@ int symbols_cpy_noinit(Symbols input, Symbols* output){ return(0); } -// append an element to a symbols -int symbols_append(int index, Polynomial expr, Symbols* output){ +// append an element to a virtual_fields +int virtual_fields_append(int index, Polynomial expr, Virtual_fields* output){ int offset=(*output).length; if((*output).length>=(*output).memory){ - resize_symbols(output,2*(*output).memory+1); + resize_virtual_fields(output,2*(*output).memory+1); } // copy and allocate @@ -436,12 +456,12 @@ int symbols_append(int index, Polynomial expr, Symbols* output){ (*output).length++; return(0); } -// append an element to a symbols without allocating memory -int symbols_append_noinit(int index, Polynomial expr, Symbols* output){ +// append an element to a virtual_fields without allocating memory +int virtual_fields_append_noinit(int index, Polynomial expr, Virtual_fields* output){ int offset=(*output).length; if((*output).length>=(*output).memory){ - resize_symbols(output,2*(*output).memory+1); + resize_virtual_fields(output,2*(*output).memory+1); } // copy without allocating @@ -452,18 +472,22 @@ int symbols_append_noinit(int index, Polynomial expr, Symbols* output){ return(0); } -// concatenate two symbolss -int symbols_concat(Symbols input, Symbols* output){ +// concatenate two virtual_fields +int virtual_fields_concat(Virtual_fields input, Virtual_fields* output){ int i; for(i=0;i<input.length;i++){ - symbols_append(input.indices[i],input.expr[i],output); + virtual_fields_append(input.indices[i],input.expr[i],output); } return(0); } -// ------------------ Groups -------------------- +//--------------------------------------------------------------------- +// +// Groups +// +//--------------------------------------------------------------------- // allocate memory int init_Groups(Groups* groups,int size){ @@ -570,3 +594,164 @@ int find_group(int index, Groups groups){ } return(-1); } + + +//--------------------------------------------------------------------- +// +// Variables +// +//--------------------------------------------------------------------- + +// allocate memory +int init_Variables(Variables* variables,int size){ + (*variables).var_names=calloc(size,sizeof(Char_Array)); + (*variables).symbol_trees=calloc(size,sizeof(Tree)); + (*variables).length=0; + (*variables).memory=size; + return(0); +} + +// free memory +int free_Variables(Variables variables){ + int i; + for(i=0;i<variables.length;i++){ + free_Char_Array(variables.var_names[i]); + free_Tree(variables.symbol_trees[i]); + } + free(variables.var_names); + free(variables.symbol_trees); + return(0); +} + +// resize +int resize_variables(Variables* variables,int new_size){ + Variables new_variables; + int i; + + init_Variables(&new_variables,new_size); + for(i=0;i<(*variables).length;i++){ + new_variables.var_names[i]=(*variables).var_names[i]; + new_variables.symbol_trees[i]=(*variables).symbol_trees[i]; + } + new_variables.length=(*variables).length; + + free((*variables).var_names); + free((*variables).symbol_trees); + + *variables=new_variables; + return(0); +} + +// copy +int variables_cpy(Variables input, Variables* output){ + init_Variables(output,input.length); + variables_cpy_noinit(input,output); + return(0); +} +int variables_cpy_noinit(Variables input, Variables* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a variables collection of length %d to another with memory %d\n",input.length,(*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + char_array_cpy(input.var_names[i], (*output).var_names+i); + tree_cpy(input.symbol_trees[i],(*output).symbol_trees+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a variables collection +int variables_append(Char_Array var_name, Tree symbol_tree, Variables* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_variables(output,2*(*output).memory+1); + } + + // copy and allocate + char_array_cpy(var_name,(*output).var_names+offset); + tree_cpy(symbol_tree,(*output).symbol_trees+offset); + // increment length + (*output).length++; + return(0); +} +// append an element to a variables collection without allocating memory +int variables_append_noinit(Char_Array var_name, Tree symbol_tree, Variables* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_variables(output,2*(*output).memory+1); + } + + // copy without allocating + (*output).var_names[offset]=var_name; + (*output).symbol_trees[offset]=symbol_tree; + // increment length + (*output).length++; + return(0); +} + +// concatenate two variables collections +int variables_concat(Variables input, Variables* output){ + int i; + for(i=0;i<input.length;i++){ + variables_append(input.var_names[i], input.symbol_trees[i], output); + } + return(0); +} + + +// find a variable matching a var_name +int variables_find_var(Char_Array name, Variables variables, Tree* output){ + Char_Array varname; + int i; + + // drop inital '$' + char_array_substring(name, 1, name.length-1, &varname); + for(i=0;i<variables.length;i++){ + if(char_array_cmp(varname, variables.var_names[i])==1){ + tree_cpy(variables.symbol_trees[i], output); + break; + } + } + + // error if no variable was found + if(i==variables.length){ + fprintf(stderr, "error: variable '$%s' not found\n",char_array_to_str_noinit(&varname)); + exit(-1); + } + free_Char_Array(varname); + + return(0); +} + + +// add a polynomials as a new named variable +int add_polynomial_to_variables(char* name, Polynomial polynomial, Variables* variables){ + // save polynomial to string (to convert it to a variable, it must first be a string) + Char_Array poly_str; + Char_Array out_name; + Tree out_tree; + + init_Char_Array(&poly_str, STR_SIZE); + polynomial_sprint(polynomial, &poly_str); + + // convert name to Char_Array + init_Char_Array(&out_name,STR_SIZE); + char_array_append_str(name, &out_name); + + // trivial tree containing the polynomial + init_Tree(&out_tree,0,poly_str.length); + tree_set_label(poly_str, &out_tree); + free_Char_Array(poly_str); + + // add variable + variables_append(out_name, out_tree, variables); + free_Tree(out_tree); + free_Char_Array(out_name); + + return 0; +} diff --git a/src/fields.h b/src/fields.h index b6f05c2..7b7a07a 100644 --- a/src/fields.h +++ b/src/fields.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -21,6 +21,9 @@ limitations under the License. #include "types.h" + +// Fields_Table + // init int init_Fields_Table(Fields_Table* fields); int free_Fields_Table(Fields_Table fields); @@ -33,6 +36,8 @@ int is_fermion(int index, Fields_Table fields); int is_noncommuting(int index, Fields_Table fields); +// Identities + // init int init_Identities(Identities* identities,int size); int free_Identities(Identities identities); @@ -57,25 +62,29 @@ int resolve_ids(Polynomial* polynomial, Fields_Table fields); int int_array_is_subarray_noncommuting(Int_Array input, Int_Array test_array, Fields_Table fields); +// Virtual_fields + // init -int init_Symbols(Symbols* symbols,int size); -int free_Symbols(Symbols symbols); +int init_Virtual_fields(Virtual_fields* virtual_fields,int size); +int free_Virtual_fields(Virtual_fields virtual_fields); // resize -int resize_symbols(Symbols* symbols,int new_size); +int resize_virtual_fields(Virtual_fields* virtual_fields,int new_size); // copy -int symbols_cpy(Symbols input, Symbols* output); -int symbols_cpy_noinit(Symbols input, Symbols* output); +int virtual_fields_cpy(Virtual_fields input, Virtual_fields* output); +int virtual_fields_cpy_noinit(Virtual_fields input, Virtual_fields* output); -// append an element to a symbols -int symbols_append(int index, Polynomial expr, Symbols* output); -int symbols_append_noinit(int index, Polynomial expr, Symbols* output); +// append an element to a virtual_fields +int virtual_fields_append(int index, Polynomial expr, Virtual_fields* output); +int virtual_fields_append_noinit(int index, Polynomial expr, Virtual_fields* output); -// concatenate two symbolss -int symbols_concat(Symbols input, Symbols* output); +// concatenate two virtual_fields +int virtual_fields_concat(Virtual_fields input, Virtual_fields* output); +// Groups + // init int init_Groups(Groups* groups,int size); int free_Groups(Groups groups); @@ -98,5 +107,32 @@ int groups_concat(Groups input, Groups* output); int find_group(int index, Groups groups); +// Variables + +// allocate memory +int init_Variables(Variables* variables,int size); +// free memory +int free_Variables(Variables variables); + +// resize +int resize_variables(Variables* variables,int new_size); + +// copy +int variables_cpy(Variables input, Variables* output); +int variables_cpy_noinit(Variables input, Variables* output); + +// append an element to a variables collection +int variables_append(Char_Array var_name, Tree symbol_tree, Variables* output); +int variables_append_noinit(Char_Array var_name, Tree symbol_tree, Variables* output); + +// concatenate two variables collections +int variables_concat(Variables input, Variables* output); + +// find a variable matching a var_name +int variables_find_var(Char_Array name, Variables variables, Tree* output); + +// add a polynomials as a new named variable +int add_polynomial_to_variables(char* name, Polynomial polynomial, Variables* variables); + #define FIELDS_H_DONE #endif @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -25,14 +25,20 @@ limitations under the License. #include "array.h" #include "coefficient.h" #include "rcc.h" +#include "grouped_polynomial.h" // compute flow numerically, no exponentials -int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, int niter, int display_mode){ +int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Grouped_Polynomial postprocess_flow_equation, Labels labels, int niter, int display_mode){ // running coupling contants RCC rccs=init; + // for printing + RCC rcc_print; int i,j; + // init printing rcc + init_RCC(&rcc_print, rccs.length); + if(display_mode==DISPLAY_NUMERICAL){ // print labels printf("%5s ","n"); @@ -42,9 +48,25 @@ int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, in printf("\n\n"); // print initial values + RCC_cpy_noinit(rccs,&rcc_print); + if(postprocess_flow_equation.length>0){ + // ignore constants + for(j=0;j<rcc_print.length;j++){ + if(rcc_print.indices[j]<0){ + rcc_print.values[j]=1.; + } + } + evaleq(rcc_print, rcc_print, postprocess_flow_equation); + } printf("%5d ",0); - for(j=0;j<rccs.length;j++){ - printf("% 14.7Le ",rccs.values[j]); + for(j=0;j<rcc_print.length;j++){ + // use constants from rcc + if(rcc_print.indices[j]<0){ + printf("% 14.7Le ",rccs.values[j]); + } + else{ + printf("% 14.7Le ",rcc_print.values[j]); + } } printf("\n"); } @@ -52,12 +74,32 @@ int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, in for(i=0;i<niter;i++){ // compute a single step step_flow(&rccs, flow_equation); - // convert ls to alphas + + // print + if(postprocess_flow_equation.length>0){ + RCC_cpy_noinit(rccs,&rcc_print); + // ignore constants + for(j=0;j<rcc_print.length;j++){ + if(rcc_print.indices[j]<0){ + rcc_print.values[j]=1.; + } + } + evaleq(rcc_print, rcc_print, postprocess_flow_equation); + } + else{ + RCC_cpy_noinit(rccs,&rcc_print); + } if(display_mode==DISPLAY_NUMERICAL){ // print the result printf("%5d ",i+1); - for(j=0;j<rccs.length;j++){ - printf("% 14.7Le ",rccs.values[j]); + for(j=0;j<rcc_print.length;j++){ + // use constants from rcc + if(rcc_print.indices[j]<0){ + printf("% 14.7Le ",rccs.values[j]); + } + else{ + printf("% 14.7Le ",rcc_print.values[j]); + } } printf("\n"); } @@ -74,9 +116,24 @@ int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, in } if(display_mode==DISPLAY_FINAL){ - RCC_print(rccs); + if(postprocess_flow_equation.length>0){ + RCC_cpy_noinit(rccs,&rcc_print); + // ignore constants + for(j=0;j<rcc_print.length;j++){ + if(rcc_print.indices[j]<0){ + rcc_print.values[j]=1.; + } + } + evaleq(rcc_print, rcc_print, postprocess_flow_equation); + } + else{ + RCC_cpy_noinit(rccs,&rcc_print); + } + RCC_print(rcc_print); } + free_RCC(rcc_print); + return(0); } @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -24,7 +24,7 @@ Compute flow numerically #include "types.h" // compute flow -int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, int niter, int display_mode); +int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Grouped_Polynomial postprocess_flow_equation, Labels labels, int niter, int display_mode); // single step int step_flow(RCC* rccs, Grouped_Polynomial flow_equation); diff --git a/src/flow_mpfr.c b/src/flow_mpfr.c index e03c130..1701b15 100644 --- a/src/flow_mpfr.c +++ b/src/flow_mpfr.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -32,14 +32,21 @@ limitations under the License. #include "coefficient.h" #include "flow.h" #include "rcc_mpfr.h" +#include "grouped_polynomial.h" // compute flow numerically -int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Labels labels, int niter, int display_mode){ +int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Grouped_Polynomial postprocess_flow_equation, Labels labels, int niter, int display_mode){ // running coupling contants RCC_mpfr rccs=init; int i,j; + // for printing + RCC_mpfr rcc_print; + + + // init printing rcc + init_RCC_mpfr(&rcc_print, rccs.length); if(display_mode==DISPLAY_NUMERICAL){ // print labels @@ -50,9 +57,25 @@ int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Labels printf("\n\n"); // print initial values + RCC_mpfr_cpy_noinit(rccs,&rcc_print); + if(postprocess_flow_equation.length>0){ + // ignore constants + for(j=0;j<rcc_print.length;j++){ + if(rcc_print.indices[j]<0){ + mpfr_set_ui(rcc_print.values[j], 1, MPFR_RNDN); + } + } + evaleq_mpfr(rcc_print, rccs, postprocess_flow_equation); + } printf("%5d ",0); - for(j=0;j<rccs.length;j++){ - mpfr_printf("% 14.7Re ",rccs.values[j]); + for(j=0;j<rcc_print.length;j++){ + // use constants from rcc + if(rcc_print.indices[j]<0){ + mpfr_printf("% 14.7Re ",rccs.values[j]); + } + else{ + mpfr_printf("% 14.7Re ",rcc_print.values[j]); + } } printf("\n"); } @@ -60,12 +83,29 @@ int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Labels for(i=0;i<niter;i++){ // compute a single step step_flow_mpfr(&rccs, flow_equation); - // convert ls to alphas + + // print + RCC_mpfr_cpy_noinit(rccs,&rcc_print); + if(postprocess_flow_equation.length>0){ + // ignore constants + for(j=0;j<rcc_print.length;j++){ + if(rcc_print.indices[j]<0){ + mpfr_set_ui(rcc_print.values[j], 1, MPFR_RNDN); + } + } + evaleq_mpfr(rcc_print, rccs, postprocess_flow_equation); + } if(display_mode==DISPLAY_NUMERICAL){ // print the result printf("%5d ",i+1); - for(j=0;j<rccs.length;j++){ - mpfr_printf("% 14.7Re ",rccs.values[j]); + for(j=0;j<rcc_print.length;j++){ + // use constants from rcc + if(rcc_print.indices[j]<0){ + mpfr_printf("% 14.7Re ",rccs.values[j]); + } + else{ + mpfr_printf("% 14.7Re ",rcc_print.values[j]); + } } printf("\n"); } @@ -82,9 +122,16 @@ int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Labels } if(display_mode==DISPLAY_FINAL){ - RCC_mpfr_print(rccs); + if(postprocess_flow_equation.length>0){ + evaleq_mpfr(rcc_print, rccs, postprocess_flow_equation); + } + else{ + rcc_print=rccs; + } + RCC_mpfr_print(rcc_print); } + free_RCC_mpfr(rcc_print); return(0); } diff --git a/src/flow_mpfr.h b/src/flow_mpfr.h index e06cbd8..203770d 100644 --- a/src/flow_mpfr.h +++ b/src/flow_mpfr.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -25,7 +25,7 @@ Compute flow numerically #include "types.h" // compute flow -int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Labels labels, int niter, int display_mode); +int numerical_flow_mpfr(Grouped_Polynomial flow_equation, RCC_mpfr init, Grouped_Polynomial postprocess_flow_equation, Labels labels, int niter, int display_mode); // single step int step_flow_mpfr(RCC_mpfr* rccs, Grouped_Polynomial flow_equation); diff --git a/src/grouped_polynomial.c b/src/grouped_polynomial.c index 0d4d75d..9e245a8 100644 --- a/src/grouped_polynomial.c +++ b/src/grouped_polynomial.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -205,9 +205,9 @@ int group_polynomial(Polynomial polynomial, Grouped_Polynomial* grouped_polynomi if(index==-2){ fprintf(stderr,"error: monomial ("); - for(j=0;j<polynomial.monomials[i].length;j++){ - fprintf(stderr,"%d", polynomial.monomials[i].values[j]); - if(j<polynomial.monomials[i].length-1){ + for(j=0;j<remainder.monomials[i].length;j++){ + fprintf(stderr,"%d", remainder.monomials[i].values[j]); + if(j<remainder.monomials[i].length-1){ fprintf(stderr,","); } } @@ -436,7 +436,7 @@ int simplify_grouped_polynomial(Grouped_Polynomial* polynomial){ } -// derive a flow equation with respect to an unknown variable +// differentiate a flow equation with respect to an unknown variable // equivalent to DB.dl where dl are symbols for the derivatives of the indices in the flow equation with respect to the unknown variable // indices specifies the list of indices that depend on the variable int flow_equation_derivx(Grouped_Polynomial flow_equation, Int_Array indices, Grouped_Polynomial* dflow){ @@ -487,7 +487,7 @@ int flow_equation_derivx(Grouped_Polynomial flow_equation, Int_Array indices, Gr /* -// derive a flow equation with respect to an index +// 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 @@ -603,7 +603,7 @@ int grouped_polynomial_print(Grouped_Polynomial grouped_polynomial, char lhs_pre init_Char_Array(&buffer, STR_SIZE); coefficient_sprint(grouped_polynomial.coefs[i],&buffer,9,rhs_pre); if(buffer.length>0){ - printf("%s",buffer.str); + printf("%s",char_array_to_str_noinit(&buffer)); } free_Char_Array(buffer); @@ -732,29 +732,33 @@ int char_array_to_Grouped_Polynomial(Char_Array str, Grouped_Polynomial* output) } -// eValuate an equation on a vector -int evaleq(RCC* rccs, Grouped_Polynomial poly){ +// evaluate an equation on a vector +int evaleq(RCC out, RCC in, Grouped_Polynomial poly){ int i; - long double* res=calloc((*rccs).length,sizeof(long double)); + long double* res=calloc(out.length,sizeof(long double)); - if((*rccs).length!=poly.length){ - fprintf(stderr, "error: trying to evaluate an flow equation with %d components on an rcc with %d\n",poly.length,(*rccs).length); + if(in.length!=poly.length){ + fprintf(stderr, "error: trying to evaluate a flow equation with %d components on an rcc with %d\n",poly.length,in.length); + exit(-1); + } + if(out.length!=poly.length){ + fprintf(stderr, "error: trying to write the output of a flow equation with %d components on an rcc with %d\n",poly.length,out.length); exit(-1); } - // initialize vectors to 0 - for(i=0;i<(*rccs).length;i++){ + // initialize vectors to 0 in an auxiliary vector (to allow for out=in without interference) + for(i=0;i<in.length;i++){ res[i]=0.; } // for each equation for(i=0;i<poly.length;i++){ - evalcoef(*rccs, poly.coefs[i], res+i); + evalcoef(in, poly.coefs[i], res+i); } // copy res to rccs - for(i=0;i<(*rccs).length;i++){ - (*rccs).values[i]=res[i]; + for(i=0;i<out.length;i++){ + out.values[i]=res[i]; } // free memory @@ -763,25 +767,29 @@ int evaleq(RCC* rccs, Grouped_Polynomial poly){ } // evaluate an equation on a vector (using mpfr floats) -int evaleq_mpfr(RCC_mpfr* rccs, Grouped_Polynomial poly){ +int evaleq_mpfr(RCC_mpfr out, RCC_mpfr in, Grouped_Polynomial poly){ int i; mpfr_t* res; - if((*rccs).length!=poly.length){ - fprintf(stderr, "error: trying to evaluate an flow equation with %d components on an rcc with %d\n",poly.length,(*rccs).length); + if(in.length!=poly.length){ + fprintf(stderr, "error: trying to evaluate a flow equation with %d components on an rcc with %d\n",poly.length,in.length); + exit(-1); + } + if(out.length!=poly.length){ + fprintf(stderr, "error: trying to write the output of a flow equation with %d components on an rcc with %d\n",poly.length,out.length); exit(-1); } - res=calloc((*rccs).length,sizeof(mpfr_t)); + res=calloc(out.length,sizeof(mpfr_t)); // for each equation for(i=0;i<poly.length;i++){ - evalcoef_mpfr(*rccs, poly.coefs[i], res[i]); + evalcoef_mpfr(in, poly.coefs[i], res[i]); } // copy res to rccs - for(i=0;i<(*rccs).length;i++){ - mpfr_set((*rccs).values[i], res[i], MPFR_RNDN); + for(i=0;i<out.length;i++){ + mpfr_set(out.values[i], res[i], MPFR_RNDN); mpfr_clear(res[i]); } @@ -791,3 +799,85 @@ int evaleq_mpfr(RCC_mpfr* rccs, Grouped_Polynomial poly){ } +// compose two flow equations (replace the rcc's of flow1 by the right hand side of flow2) +int compose_flow_equations(Grouped_Polynomial flow1, Grouped_Polynomial flow2, Grouped_Polynomial* out){ + if(flow1.length!=flow2.length){ + fprintf(stderr, "error: trying to compose two flow equations of different size\n"); + exit(-1); + } + int i,j,k; + Coefficient constant; + + // init + init_Grouped_Polynomial(out, flow1.length); + (*out).length=flow1.length; + + // init constant (so we can tell when the constant was not found) + constant.length=0; + + // loop over rcc's + for(i=0;i<flow1.length;i++){ + // set indices + (*out).indices[i]=flow1.indices[i]; + + // passthrough constant terms + if((*out).indices[i]<0){ + int index=intlist_find_err(flow2.indices,flow2.length,(*out).indices[i]); + coefficient_cpy(flow2.coefs[index], (*out).coefs+i); + constant=flow2.coefs[index]; + continue; + } + + // init + init_Coefficient((*out).coefs+i, COEF_SIZE); + + // loop over terms + for(j=0;j<flow1.coefs[i].length;j++){ + Coefficient tmp_coef; + + // init + init_Coefficient(&tmp_coef, COEF_SIZE); + // init factor + Int_Array tmp_factor; + init_Int_Array(&tmp_factor, MONOMIAL_SIZE); + // init denom + coef_denom denom; + // index should be that appearing in flow2 + if(flow2.coefs[i].length<1){ + fprintf(stderr,"error: composing two flow equations: the %d-th term in the flow equation is empty\n",flow1.indices[i]); + exit(-1); + } + denom.index=flow2.coefs[i].denoms[0].index; + denom.power=0; + // init num + Number tmp_num; + number_cpy(flow1.coefs[i].nums[j], &tmp_num); + + // init coefficient with numerical prefactor + coefficient_append_noinit(tmp_factor, tmp_num, denom, &tmp_coef); + + // loop over factors + for(k=0;k<flow1.coefs[i].factors[j].length;k++){ + // multiply factors together + coefficient_prod_chain(flow2.coefs[intlist_find_err(flow2.indices,flow2.length,flow1.coefs[i].factors[j].values[k])], &tmp_coef); + } + + // add to out + coefficient_concat_noinit(tmp_coef, (*out).coefs+i); + } + + } + + // simplify fractions + if(constant.length!=0){ + for(i=0;i<(*out).length;i++){ + if((*out).indices[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); +} diff --git a/src/grouped_polynomial.h b/src/grouped_polynomial.h index e369721..7d95a2e 100644 --- a/src/grouped_polynomial.h +++ b/src/grouped_polynomial.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -59,7 +59,7 @@ int find_id(Int_Array monomial, Id_Table idtable, int start); // simplify grouped polynomial int simplify_grouped_polynomial(Grouped_Polynomial* polynomial); -// derive a flow equation with respect to an unknown variable +// differentiate a flow equation with respect to an unknown variable int flow_equation_derivx(Grouped_Polynomial flow_equation, Int_Array indices, Grouped_Polynomial* dflow); // print a grouped polynomial @@ -69,8 +69,10 @@ int grouped_polynomial_print(Grouped_Polynomial grouped_polynomial, char lhs_pre int char_array_to_Grouped_Polynomial(Char_Array str, Grouped_Polynomial* output); // evaluate an equation on an RCC -int evaleq(RCC* rccs, Grouped_Polynomial poly); +int evaleq(RCC out, RCC in, Grouped_Polynomial poly); // evaluate an equation on a vector (using mpfr floats) -int evaleq_mpfr(RCC_mpfr* rccs, Grouped_Polynomial poly); +int evaleq_mpfr(RCC_mpfr out, RCC_mpfr in, Grouped_Polynomial poly); +// compose two flow equations (replace the rcc's of flow1 by the right hand side of flow2) +int compose_flow_equations(Grouped_Polynomial flow1, Grouped_Polynomial flow2, Grouped_Polynomial* out); #endif diff --git a/src/idtable.c b/src/idtable.c index fe409c2..fc72f56 100644 --- a/src/idtable.c +++ b/src/idtable.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/idtable.h b/src/idtable.h index 38ab249..aa99dca 100644 --- a/src/idtable.h +++ b/src/idtable.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/istring.c b/src/istring.c index 663c06a..d78f67b 100644 --- a/src/istring.c +++ b/src/istring.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/istring.h b/src/istring.h index 5b47b9b..5027981 100644 --- a/src/istring.h +++ b/src/istring.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/kondo.c b/src/kondo.c index 79b7c56..93318d5 100644 --- a/src/kondo.c +++ b/src/kondo.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -35,7 +35,7 @@ limitations under the License. #define KONDO_SPIN 2 // offsets for indices of A, B, h and t -// order matters for symbols table +// order matters for virtual_fields table #define KONDO_A_OFFSET 1 #define KONDO_B_OFFSET 2 #define KONDO_H_OFFSET 3 @@ -72,6 +72,7 @@ limitations under the License. int kondo_generate_conf(Str_Array* str_args, int box_count){ Str_Array new_args; Fields_Table fields; + Variables variables; Char_Array tmp_str; int arg_index; int i; @@ -83,16 +84,19 @@ int kondo_generate_conf(Str_Array* str_args, int box_count){ kondo_fields_table(box_count, &tmp_str, &fields); str_array_append_noinit(tmp_str, &new_args); - // symbols - kondo_symbols(&tmp_str, box_count, &fields); - arg_index=find_str_arg("symbols", *str_args); + // dummy variables + init_Variables(&variables,1); + + // virtual fields + kondo_virtual_fields(&tmp_str, box_count, &fields); + arg_index=find_str_arg("virtual_fields", *str_args); if(arg_index>=0){ if(tmp_str.length>0){ char_array_snprintf(&tmp_str,",\n"); } char_array_concat((*str_args).strs[arg_index], &tmp_str); } - parse_input_symbols(tmp_str, &fields); + parse_input_virtual_fields(tmp_str, &fields, variables); str_array_append_noinit(tmp_str, &new_args); // identities @@ -104,7 +108,7 @@ int kondo_generate_conf(Str_Array* str_args, int box_count){ } char_array_concat((*str_args).strs[arg_index], &tmp_str); } - parse_input_identities(tmp_str, &fields); + parse_input_identities(tmp_str, &fields, variables); str_array_append_noinit(tmp_str, &new_args); // groups @@ -136,7 +140,7 @@ int kondo_generate_conf(Str_Array* str_args, int box_count){ // copy remaining entries for(i=0;i<(*str_args).length;i++){ get_str_arg_title((*str_args).strs[i], &title); - if(str_cmp(title.str, "symbols")==0 &&\ + if(str_cmp(title.str, "virtual_fields")==0 &&\ str_cmp(title.str, "identities")==0 &&\ str_cmp(title.str, "propagator")==0 &&\ str_cmp(title.str, "input_polynomial")==0 &&\ @@ -149,6 +153,7 @@ int kondo_generate_conf(Str_Array* str_args, int box_count){ } free_Fields_Table(fields); + free_Variables(variables); free_Str_Array(*str_args); *str_args=new_args; @@ -250,15 +255,15 @@ int kondo_fields_table(int box_count, Char_Array* str_fields, Fields_Table* fiel } -// generate Kondo symbols -int kondo_symbols(Char_Array* str_symbols, int box_count, Fields_Table* fields){ +// generate Kondo virtual_fields +int kondo_virtual_fields(Char_Array* str_virtual_fields, int box_count, Fields_Table* fields){ int i,j,k,l; Char_Array tmp_str; Polynomial poly; char letters[3]={'A','B','h'}; - init_Char_Array(str_symbols, STR_SIZE); - char_array_snprintf(str_symbols, "#!symbols\n"); + init_Char_Array(str_virtual_fields, STR_SIZE); + char_array_snprintf(str_virtual_fields, "#!virtual_fields\n"); // loop over box index for(i=1;i<=box_count;i++){ @@ -267,7 +272,7 @@ int kondo_symbols(Char_Array* str_symbols, int box_count, Fields_Table* fields){ // loop over space dimension for(k=0;k<KONDO_DIM;k++){ // write index - char_array_snprintf(str_symbols, "%d=", 100*(10*(KONDO_A_OFFSET+j)+k)+i); + char_array_snprintf(str_virtual_fields, "%d=", 100*(10*(KONDO_A_OFFSET+j)+k)+i); // write the name of the scalar product init_Char_Array(&tmp_str, 6); char_array_snprintf(&tmp_str, "%c%d%d", letters[j], k, i); @@ -275,10 +280,10 @@ int kondo_symbols(Char_Array* str_symbols, int box_count, Fields_Table* fields){ kondo_resolve_ABht(tmp_str.str, &poly, *fields); free_Char_Array(tmp_str); // write to output - polynomial_sprint(poly, str_symbols); + polynomial_sprint(poly, str_virtual_fields); free_Polynomial(poly); // add , - char_array_snprintf(str_symbols,",\n"); + char_array_snprintf(str_virtual_fields,",\n"); } } } @@ -290,46 +295,46 @@ int kondo_symbols(Char_Array* str_symbols, int box_count, Fields_Table* fields){ for(j=0;j<3;j++){ for(k=0;k<3;k++){ // write index - char_array_snprintf(str_symbols, "%d=", 1000*(10*(KONDO_A_OFFSET+j)+KONDO_A_OFFSET+k)+i); + char_array_snprintf(str_virtual_fields, "%d=", 1000*(10*(KONDO_A_OFFSET+j)+KONDO_A_OFFSET+k)+i); for(l=0;l<KONDO_DIM;l++){ - char_array_snprintf(str_symbols, "(1)"); + char_array_snprintf(str_virtual_fields, "(1)"); if(j<2){ - char_array_snprintf(str_symbols,"[f%d]", 100*(10*(KONDO_A_OFFSET+j)+l)+i); + char_array_snprintf(str_virtual_fields,"[f%d]", 100*(10*(KONDO_A_OFFSET+j)+l)+i); } else{ - char_array_snprintf(str_symbols,"[f%d]", 10*(10*(KONDO_A_OFFSET+j)+l)); + char_array_snprintf(str_virtual_fields,"[f%d]", 10*(10*(KONDO_A_OFFSET+j)+l)); } if(k<2){ - char_array_snprintf(str_symbols,"[f%d]", 100*(10*(KONDO_A_OFFSET+k)+l)+i); + char_array_snprintf(str_virtual_fields,"[f%d]", 100*(10*(KONDO_A_OFFSET+k)+l)+i); } else{ - char_array_snprintf(str_symbols,"[f%d]", 10*(10*(KONDO_A_OFFSET+k)+l)); + char_array_snprintf(str_virtual_fields,"[f%d]", 10*(10*(KONDO_A_OFFSET+k)+l)); } if(l<KONDO_DIM-1){ - char_array_append('+',str_symbols); + char_array_append('+',str_virtual_fields); } } // add , - char_array_snprintf(str_symbols,",\n"); + char_array_snprintf(str_virtual_fields,",\n"); } } } // vector products for(i=1;i<=box_count;i++){ - char_array_snprintf(str_symbols, "%d=", 100*(100*(KONDO_A_OFFSET)+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+i); + char_array_snprintf(str_virtual_fields, "%d=", 100*(100*(KONDO_A_OFFSET)+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+i); for(l=0;l<KONDO_DIM;l++){ // remember (-1 %3 = -1) - char_array_snprintf(str_symbols, "(1)[f%d][f%d][f%d]+(-1)[f%d][f%d][f%d]", 100*(10*KONDO_A_OFFSET+((l+1)%KONDO_DIM))+i, 100*(10*KONDO_B_OFFSET+((l+2)%KONDO_DIM))+i, 10*(10*KONDO_H_OFFSET+l), 100*(10*KONDO_A_OFFSET+((l+2)%KONDO_DIM))+i, 100*(10*KONDO_B_OFFSET+((l+1)%KONDO_DIM))+i, 10*(10*KONDO_H_OFFSET+l)); + char_array_snprintf(str_virtual_fields, "(1)[f%d][f%d][f%d]+(-1)[f%d][f%d][f%d]", 100*(10*KONDO_A_OFFSET+((l+1)%KONDO_DIM))+i, 100*(10*KONDO_B_OFFSET+((l+2)%KONDO_DIM))+i, 10*(10*KONDO_H_OFFSET+l), 100*(10*KONDO_A_OFFSET+((l+2)%KONDO_DIM))+i, 100*(10*KONDO_B_OFFSET+((l+1)%KONDO_DIM))+i, 10*(10*KONDO_H_OFFSET+l)); if(l<KONDO_DIM-1){ - char_array_append('+',str_symbols); + char_array_append('+',str_virtual_fields); } } // add , if(i<box_count){ - char_array_snprintf(str_symbols,",\n"); + char_array_snprintf(str_virtual_fields,",\n"); } } @@ -778,13 +783,13 @@ int parse_kondo_polynomial_str(char* str_polynomial, Polynomial* output, Fields_ // if polynomial exists, add to each monomial if(tmp_poly.length>0){ for(i=0;i<tmp_poly.length;i++){ - int_array_append(get_symbol_index(buffer), tmp_poly.monomials+i); + int_array_append(get_virtual_field_index(buffer), tmp_poly.monomials+i); } } // if not, create a new term in the polynomial else{ init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); - int_array_append(get_symbol_index(buffer), &tmp_monomial); + int_array_append(get_virtual_field_index(buffer), &tmp_monomial); init_Int_Array(&dummy_factor, 1); polynomial_append_noinit(tmp_monomial, dummy_factor, number_one(), &tmp_poly); } @@ -1387,8 +1392,8 @@ int get_offsets_index(char* str, int* offset1, int* offset2, int* index){ return(0); } -// get the index of the symbol corresponding to a given string -int get_symbol_index(char* str){ +// get the index of the virtual_field corresponding to a given string +int get_virtual_field_index(char* str){ char* ptr; int offset=-1; int index=0; @@ -1439,7 +1444,7 @@ int get_symbol_index(char* str){ if(offset==-1){ return(-1); } - // no symbol for h or t + // no virtual field for h or t if(offset==KONDO_H_OFFSET || offset==KONDO_T_OFFSET){ return(10*(10*offset+dim)); } diff --git a/src/kondo.h b/src/kondo.h index c534145..18488ae 100644 --- a/src/kondo.h +++ b/src/kondo.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -27,10 +27,10 @@ int kondo_generate_conf(Str_Array* str_args, int box_count); // generate the Kondo fields table int kondo_fields_table(int box_count, Char_Array* str_fields, Fields_Table* fields); -// generate Kondo symbols -int kondo_symbols(Char_Array* str_symbols, int box_count, Fields_Table* fields); -// generate Kondo symbols (older method: one symbol for each scalar product) -int kondo_symbols_scalarprod(Char_Array* str_symbols, int box_count, Fields_Table* fields); +// generate Kondo virtual_fields +int kondo_virtual_fields(Char_Array* str_virtual_fields, int box_count, Fields_Table* fields); +// generate Kondo virtual_fields (older method: one virtual_field for each scalar product) +int kondo_virtual_fields_scalarprod(Char_Array* str_virtual_fields, int box_count, Fields_Table* fields); // generate Kondo groups (groups of independent variables) int kondo_groups(Char_Array* str_groups, int box_count); @@ -71,6 +71,6 @@ int kondo_resolve_scalar_prod_symbols(char* str, Polynomial* output); int get_offset_index(char* str, int* offset, int* index); // get the offsets and index of a scalar product int get_offsets_index(char* str, int* offset1, int* offset2, int* index); -// get the index of the symbol corresponding to a given string -int get_symbol_index(char* str); +// get the index of the virtual_field corresponding to a given string +int get_virtual_field_index(char* str); #endif diff --git a/src/kondo_preprocess.c b/src/kondo_preprocess.c index 3371014..c472e9d 100644 --- a/src/kondo_preprocess.c +++ b/src/kondo_preprocess.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -104,6 +104,11 @@ for(i=1;i<argc;i++){ // number of dimensions else if (flag==CP_FLAG_DIMENSION){ sscanf(argv[i],"%d",&((*opts).dimension)); + // check value of the dimension + if((*opts).dimension<=0 || (*opts).dimension>=4){ + fprintf(stderr,"error: kondo_preprocess only supports dimensions 1, 2 and 3 (got %d)\n",(*opts).dimension); + exit(-1); + } flag=0; } // read file name from command-line @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -30,6 +30,7 @@ As of version 1.0, the mean of a monomial is computed directly #include "array.h" #include "fields.h" #include "number.h" +#include "determinant.h" // mean of a monomial int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Matrix propagator){ @@ -61,10 +62,79 @@ int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Ma // 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){ + int ret; + Number num; + if(internal_plus.length!=internal_minus.length){ fprintf(stderr,"error: monomial contains unmatched +/- fields\n"); exit(-1); } + + ret=mean_determinant(internal_plus, internal_minus, &num, propagator, fields); + // cannot compute the mean as a determinant, use permutations + // can be because some fields are not Fermions + // can be because the propagator has non-numeric values (inverting polynomials is not implemented, and would be required for the computation of the determinant) + if(ret==-1){ + mean_permutations(internal_plus, internal_minus, out, propagator, fields); + } + else{ + polynomial_multiply_scalar(*out, num); + free_Number(num); + } + + return(0); +} + +// compute the mean of a monomial by computing a determinant +// can only be used if all of the propagators are numbers +int mean_determinant(Int_Array internal_plus, Int_Array internal_minus, Number* out, Polynomial_Matrix propagator, Fields_Table fields){ + Number_Matrix M; + int n=internal_minus.length; + int i,j; + int a,b; + int sign; + + init_Number_Matrix(&M,n); + + // extra sign: the monomial is sorted in such a way that minus fields are on the left of plus fields, but the determinant formula requires the fields to be alternated +- + if((n+1)/2%2==1){ + sign=-1; + } + else{ + sign=1; + } + + // construct matrix + for(i=0;i<n;i++){ + a=intlist_find_err(propagator.indices, propagator.length, internal_plus.values[i]); + for(j=0;j<n;j++){ + b=intlist_find_err(propagator.indices, propagator.length, -internal_minus.values[j]); + // ignore 0 + if(propagator.matrix[a][b].length!=0){ + // check whether the fields are Fermions, and whether the entry is a number + if(is_fermion(internal_plus.values[i], fields)==0 || is_fermion(internal_minus.values[j], fields)==0 || polynomial_is_number(propagator.matrix[a][b])==0){ + free_Number_Matrix(M); + return(-1); + } + + number_add_chain(propagator.matrix[a][b].nums[0], M.matrix[i]+j); + } + } + } + + // compute determinant + determinant_inplace(M, out); + + number_Qprod_chain(quot(sign,1), out); + + free_Number_Matrix(M); + + return(0); +} + + +// compute the mean of a monomial by summing over permutations +int mean_permutations(Int_Array internal_plus, Int_Array internal_minus, Polynomial* out, Polynomial_Matrix propagator, Fields_Table fields){ int n=internal_minus.length; // pairing as an array of positions int* pairing=calloc(n,sizeof(int)); @@ -118,7 +188,7 @@ int mean_internal(Int_Array internal_plus, Int_Array internal_minus, Polynomial* pairing_sign=permutation_signature(pairing,n); } - // only simplify in mean_symbols + // only simplify in mean_virtual_fields polynomial_prod_chain_nosimplify(num_summed,out,fields); free_Polynomial(num_summed); free(pairing); @@ -346,10 +416,10 @@ int get_internals(Int_Array monomial, Int_Array* internal_plus, Int_Array* inter } -// compute the mean of a monomial containing symbolic expressions +// compute the mean of a monomial containing virtual fields // 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 mean_virtual_fields(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed){ + Int_Array virtual_field_list; int i; int power; int* current_term; @@ -375,43 +445,43 @@ int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Po } } - init_Int_Array(&symbol_list, monomial.length); + init_Int_Array(&virtual_field_list, monomial.length); init_Int_Array(&base_monomial, monomial.length); - // generate symbols list + // generate virtual_fields list for(i=0;i<monomial.length;i++){ - if(field_type(monomial.values[i], fields)==FIELD_SYMBOL){ - int_array_append(intlist_find_err(fields.symbols.indices, fields.symbols.length, monomial.values[i]), &symbol_list); + if(field_type(monomial.values[i], fields)==FIELD_VIRTUAL){ + int_array_append(intlist_find_err(fields.virtual_fields.indices, fields.virtual_fields.length, monomial.values[i]), &virtual_field_list); } else{ int_array_append(monomial.values[i], &base_monomial); } } - power=symbol_list.length; + power=virtual_field_list.length; // trivial case if(power==0){ mean(monomial, &mean_num, fields, propagator); polynomial_concat_noinit(mean_num, output); - free_Int_Array(symbol_list); + free_Int_Array(virtual_field_list); free_Int_Array(base_monomial); return(0); } else{ // initialize current term to a position that has no repetitions current_term=calloc(power,sizeof(int)); - exists_next=init_prod(current_term, symbol_list, fields, power, base_monomial)+1; + exists_next=init_prod(current_term, virtual_field_list, fields, power, base_monomial)+1; } - // loop over terms; the loop stops when all the pointers are at the end of the first symbol + // loop over terms; the loop stops when all the pointers are at the end of the first virtual field while(exists_next==1){ // construct monomial int_array_cpy(base_monomial, &tmp_monomial); tmp_num=number_one(); for(i=0;i<power;i++){ - int_array_concat(fields.symbols.expr[symbol_list.values[i]].monomials[current_term[i]], &tmp_monomial); - number_prod_chain(fields.symbols.expr[symbol_list.values[i]].nums[current_term[i]], &tmp_num); + int_array_concat(fields.virtual_fields.expr[virtual_field_list.values[i]].monomials[current_term[i]], &tmp_monomial); + number_prod_chain(fields.virtual_fields.expr[virtual_field_list.values[i]].nums[current_term[i]], &tmp_num); } // check whether the monomial vanishes if(check_monomial_match(tmp_monomial, fields)==1){ @@ -432,7 +502,7 @@ int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Po free_Int_Array(tmp_monomial); // next term - exists_next=next_prod(current_term, symbol_list, fields, power, base_monomial)+1; + exists_next=next_prod(current_term, virtual_field_list, fields, power, base_monomial)+1; // simplfiy every 25 steps (improves both memory usage and performance) @@ -451,13 +521,13 @@ int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Po // free memory free(current_term); - free_Int_Array(symbol_list); + free_Int_Array(virtual_field_list); free_Int_Array(base_monomial); return(0); } // first term in product with no repetitions -int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int power, Int_Array base_monomial){ +int init_prod(int* current_term, Int_Array virtual_field_list, Fields_Table fields, int power, Int_Array base_monomial){ // index we want to increment int move=0; // tmp monomial @@ -474,7 +544,7 @@ int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int // loop until move is out of range while(move>=0 && move<power){ // move - current_term[move]=next_term_norepeat(current_term[move], fields.symbols.expr[symbol_list.values[move]], &monomial, fields); + current_term[move]=next_term_norepeat(current_term[move], fields.virtual_fields.expr[virtual_field_list.values[move]], &monomial, fields); // if the next term does not exist, then move previous index if(current_term[move]==-1){ move--; @@ -495,7 +565,7 @@ int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int } // next term in product with no repetitions -int next_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int power, Int_Array base_monomial){ +int next_prod(int* current_term, Int_Array virtual_field_list, Fields_Table fields, int power, Int_Array base_monomial){ // index we want to increment int move=power-1; // tmp monomial @@ -506,13 +576,13 @@ int next_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int init_Int_Array(&monomial, base_monomial.length+5*power); int_array_cpy_noinit(base_monomial, &monomial); for(i=0;i<=move;i++){ - int_array_concat(fields.symbols.expr[symbol_list.values[i]].monomials[current_term[i]],&monomial); + int_array_concat(fields.virtual_fields.expr[virtual_field_list.values[i]].monomials[current_term[i]],&monomial); } // loop until move is out of range while(move>=0 && move<power){ // move - current_term[move]=next_term_norepeat(current_term[move], fields.symbols.expr[symbol_list.values[move]], &monomial, fields); + current_term[move]=next_term_norepeat(current_term[move], fields.virtual_fields.expr[virtual_field_list.values[move]], &monomial, fields); // if the next term does not exist, then move previous index if(current_term[move]==-1){ move--; @@ -623,13 +693,13 @@ int mean_groups(Int_Array monomial, Polynomial* output, Fields_Table fields, Pol int group=-2; int next_group=-2; Polynomial tmp_poly; - int sign; + int sign=1; init_Polynomial(output, MONOMIAL_SIZE); - // check whether there are symbols - // IMPORTANT: the symbols must be at the end of the monomial - if(monomial.length==0 || field_type(monomial.values[monomial.length-1], fields)!=FIELD_SYMBOL){ + // check whether there are virtual fields + // IMPORTANT: the virtual fields must be at the end of the monomial + if(monomial.length==0 || field_type(monomial.values[monomial.length-1], fields)!=FIELD_VIRTUAL){ // mean mean(monomial, &num_mean, fields, propagator); // add to output @@ -650,7 +720,7 @@ int mean_groups(Int_Array monomial, Polynomial* output, Fields_Table fields, Pol } // if group changes, take mean if((i>0 && next_group!=group) || i==monomial.length){ - mean_symbols(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); + mean_virtual_fields(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); // if zero if(polynomial_is_zero(tmp_poly)==1){ // set output to 0 @@ -702,10 +772,11 @@ struct mean_args{ Fields_Table fields; Polynomial_Matrix propagator; Groups groups; + int print_progress; }; // multithreaded -int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads){ +int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, int print_progress){ int i; Polynomial thread_polys[threads]; pthread_t thread_ids[threads]; @@ -720,11 +791,15 @@ int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Pol args[i].fields=fields; args[i].propagator=propagator; args[i].groups=groups; + args[i].print_progress=print_progress; } // split polynomial + // randomly choose the thread + // see random number generator + srand(time(NULL)); for(i=0;i<len;i++){ - polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], thread_polys+(i % threads)); + polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], thread_polys+(rand() % threads)); } // start threads @@ -750,12 +825,12 @@ int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Pol // mean for one of the threads void* polynomial_mean_thread(void* mean_args){ struct mean_args *args=mean_args; - polynomial_mean((*args).polynomial,(*args).fields,(*args).propagator,(*args).groups); + polynomial_mean((*args).polynomial,(*args).fields,(*args).propagator,(*args).groups, (*args).print_progress); return(NULL); } // single threaded version -int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups){ +int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int print_progress){ int i,j; Polynomial output; Polynomial tmp_poly; @@ -769,7 +844,9 @@ int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matr // mean of each monomial for(i=0;i<(*polynomial).length;i++){ - fprintf(stderr,"computing %d of %d means\n",i,(*polynomial).length-1); + if(print_progress==1){ + fprintf(stderr,"computing %d of %d means\n",i,(*polynomial).length-1); + } mean_groups((*polynomial).monomials[i], &tmp_poly, fields, propagator, groups, &computed); // write factors @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -28,6 +28,12 @@ int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Ma // 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); + +// compute the mean of a monomial by computing a determinant +int mean_determinant(Int_Array internal_plus, Int_Array internal_minus, Number* out, Polynomial_Matrix propagator,Fields_Table fields); + +// compute the mean of a monomial by summing over permutations +int mean_permutations(Int_Array internal_plus, Int_Array internal_minus, Polynomial* out, Polynomial_Matrix propagator, Fields_Table fields); // first pairing with a non-vanishing propagator int init_pairing(int* pairing, int* mask, int n, Polynomial_Matrix propagator, int* indices_plus, int* indices_minus); // next pairing with a non-vanishing propagator @@ -43,12 +49,12 @@ int mean_internal_slow(Int_Array internal_plus, Int_Array internal_minus, Number // 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); -// compute the mean of a monomial containing symbolic expressions -int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed); +// compute the mean of a monomial containing virtual fields +int mean_virtual_fields(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed); // first term in product with no repetitions -int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int power, Int_Array base_monomial); +int init_prod(int* current_term, Int_Array virtual_field_list, Fields_Table fields, int power, Int_Array base_monomial); // next term in product with no repetitions -int next_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int power, Int_Array base_monomial); +int next_prod(int* current_term, Int_Array virtual_field_list, Fields_Table fields, int power, Int_Array base_monomial); // find the next term in a polynomial that can be multiplied to a given monomial and add it to the monomial int next_term_norepeat(int start, Polynomial polynomial, Int_Array* monomial, Fields_Table fields); @@ -62,9 +68,9 @@ int sort_fermions(int* array, int begin, int end, int* sign); int mean_groups(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed); // compute the mean of a polynomial -int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups); +int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int print_progress); // multithreaded -int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads); +int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, int print_progress); // single thread mean void* polynomial_mean_thread(void* mean_args); #endif diff --git a/src/meankondo.c b/src/meankondo.c index 1c976d4..8b5c197 100644 --- a/src/meankondo.c +++ b/src/meankondo.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -17,7 +17,7 @@ limitations under the License. /* meankondo -A simple tool to compute the renormalization group flow for Fermionic hierarchical models +A tool to compute the renormalization group flow for Fermionic hierarchical models */ @@ -49,15 +49,19 @@ A simple tool to compute the renormalization group flow for Fermionic hierarchic #include "mean.h" // various string operations #include "istring.h" +// symbolic trees +# include "tree.h" // read cli arguments int read_args_meankondo(int argc,const char* argv[], Str_Array* str_args, Meankondo_Options* opts); // print usage message int print_usage_meankondo(); +// check consistency of options +int check_meankondo_opts(Meankondo_Options opts); // compute flow int compute_flow(Str_Array str_args, Meankondo_Options opts); -// compute the flow equation -int compute_flow_equation(Polynomial init_poly, Id_Table idtable, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, Grouped_Polynomial* flow_equation); +// compute average +int compute_average(Polynomial init_poly, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, int print_progress, Polynomial* exp_poly); int main (int argc, const char* argv[]){ @@ -69,6 +73,9 @@ int main (int argc, const char* argv[]){ // read command-line arguments read_args_meankondo(argc,argv,&str_args,&opts); + // check command-line arguments + check_meankondo_opts(opts); + // warning message if representing rational numbers as floats #ifdef RATIONAL_AS_FLOAT fprintf(stderr,"info: representing rational numbers using floats\n"); @@ -101,6 +108,10 @@ int read_args_meankondo(int argc,const char* argv[], Str_Array* str_args, Meanko (*opts).threads=1; // do not chain (*opts).chain=0; + // do not print progress + (*opts).print_progress=0; + // print the flow equation + (*opts).group_poly=1; // loop over arguments for(i=1;i<argc;i++){ @@ -116,6 +127,13 @@ int read_args_meankondo(int argc,const char* argv[], Str_Array* str_args, Meanko case 'C': (*opts).chain=1; break; + // print progress + case 'p': + (*opts).print_progress=1; + break; + case 'A': + (*opts).group_poly=0; + break; // print version case 'v': printf("meankondo " VERSION "\n"); @@ -147,7 +165,16 @@ int read_args_meankondo(int argc,const char* argv[], Str_Array* str_args, Meanko // print usage message int print_usage_meankondo(){ - printf("\nusage:\n meankondo [-t threads] [-C] <filename>\n\n"); + printf("\nusage:\n meankondo [-t threads] [-C] [-p] [-A] <filename>\n\n"); + return(0); +} + +// check consistency of options +int check_meankondo_opts(Meankondo_Options opts){ + if(opts.chain==1 && opts.group_poly==0){ + fprintf(stderr,"aborting: the '-C' and '-A' options are incompatible\n"); + exit(-1); + } return(0); } @@ -163,6 +190,8 @@ int compute_flow(Str_Array str_args, Meankondo_Options opts){ Fields_Table fields; // their propagator Polynomial_Matrix propagator; + // preprocessor variables + Variables variables; // initial polynomial Polynomial init_poly; // list of rccs @@ -171,6 +200,8 @@ int compute_flow(Str_Array str_args, Meankondo_Options opts){ Groups groups; // flow equation Grouped_Polynomial flow_equation; + // polynomial produced by the averaging operation + Polynomial exp_poly; // parse fields @@ -183,29 +214,38 @@ int compute_flow(Str_Array str_args, Meankondo_Options opts){ parse_input_fields(str_args.strs[arg_index],&fields); } - // parse id table - arg_index=find_str_arg("id_table", str_args); - if(arg_index<0){ - fprintf(stderr,"error: no id table entry in the configuration file\n"); - exit(-1); + // parse variables + // must precede id_table, virtual_fields, identities and input_polynomial + arg_index=find_str_arg("preprocessor_variables", str_args); + if(arg_index>=0){ + parse_input_variables(str_args.strs[arg_index],&variables); } else{ - parse_input_id_table(str_args.strs[arg_index],&idtable, fields); + init_Variables(&variables,1); } - // parse symbols - arg_index=find_str_arg("symbols", str_args); - if(arg_index>=0){ - parse_input_symbols(str_args.strs[arg_index],&fields); + // parse id table + if(opts.group_poly==1){ + arg_index=find_str_arg("id_table", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no id table entry in the configuration file\n"); + exit(-1); + } + else{ + parse_input_id_table(str_args.strs[arg_index],&idtable, fields, variables); + } } - else{ - init_Symbols(&(fields.symbols),1); + + // parse virtual_fields + arg_index=find_str_arg("virtual_fields", str_args); + if(arg_index>=0){ + parse_input_virtual_fields(str_args.strs[arg_index], &fields, variables); } // parse input polynomial arg_index=find_str_arg("input_polynomial", str_args); if(arg_index>=0){ - parse_input_polynomial(str_args.strs[arg_index],&init_poly, fields); + parse_input_polynomial(str_args.strs[arg_index],&init_poly, fields, variables); } else{ fprintf(stderr,"error: no input polynomial entry in the configuration file\n"); @@ -225,41 +265,90 @@ int compute_flow(Str_Array str_args, Meankondo_Options opts){ // parse identities arg_index=find_str_arg("identities", str_args); if(arg_index>=0){ - parse_input_identities(str_args.strs[arg_index],&fields); - } - else{ - init_Identities(&(fields.ids),1); + parse_input_identities(str_args.strs[arg_index],&fields, variables); } - // parse groups + // parse groups (must come after virtual_fields and propagator) arg_index=find_str_arg("groups", str_args); if(arg_index>=0){ - parse_input_groups(str_args.strs[arg_index],&groups); + parse_input_groups(str_args.strs[arg_index],&groups, propagator, fields); } else{ init_Groups(&groups, 1); } - // flow equation - compute_flow_equation(init_poly, idtable, fields, propagator, groups, opts.threads, &flow_equation); + // compute the average + compute_average(init_poly, fields, propagator, groups, opts.threads, opts.print_progress, &exp_poly); + free_Polynomial(init_poly); free_Polynomial_Matrix(propagator); - free_Fields_Table(fields); free_Groups(groups); + // parse postprocessing entry + arg_index=find_str_arg("postprocess_operation", str_args); + if(arg_index>=0){ + add_polynomial_to_variables("OUT", exp_poly, &variables); + // parse postprocess entry + Polynomial postprocess_operation; + parse_input_polynomial(str_args.strs[arg_index], &postprocess_operation, fields, variables); + // replace exp_poly + free_Polynomial(exp_poly); + exp_poly=postprocess_operation; + } + + if(opts.group_poly==1){ + // flow equation + group_polynomial(exp_poly, &flow_equation, idtable, fields); + } + + // postprocess flow equation + arg_index=find_str_arg("postprocess_flow_equation", str_args); + if(arg_index>=0){ + Polynomial flow_polynomial; + // polynomial made of the rcc's multiplied by the corresponding fields (parsed from idtable) + idtable_to_polynomial(idtable, &flow_polynomial); + + // add to variables + add_polynomial_to_variables("FLOW", flow_polynomial, &variables); + free_Polynomial(flow_polynomial); + + // parse postprocess entry + Polynomial postprocess_polynomial; + parse_input_polynomial(str_args.strs[arg_index], &postprocess_polynomial, fields, variables); + + // convert to flow equation + Grouped_Polynomial postprocess_flow_equation; + group_polynomial(postprocess_polynomial, &postprocess_flow_equation, idtable, fields); + free_Polynomial(postprocess_polynomial); + + // apply postprocessing to flow equation + Grouped_Polynomial new_flow; + compose_flow_equations(postprocess_flow_equation, flow_equation, &new_flow); + free_Grouped_Polynomial(postprocess_flow_equation); + + // replace flow_equation + free_Grouped_Polynomial(flow_equation); + flow_equation=new_flow; + } + + // if chain then print config file if(opts.chain==1){ for(i=0;i<str_args.length;i++){ // check whether to print the str_arg get_str_arg_title(str_args.strs[i], &arg_header); if (\ - str_cmp(arg_header.str, "symbols")==0 &&\ + str_cmp(arg_header.str, "variables")==0 &&\ + str_cmp(arg_header.str, "virtual_fields")==0 &&\ str_cmp(arg_header.str, "groups")==0 &&\ str_cmp(arg_header.str, "fields")==0 &&\ str_cmp(arg_header.str, "identities")==0 &&\ str_cmp(arg_header.str, "propagator")==0 &&\ str_cmp(arg_header.str, "input_polynomial")==0 &&\ - str_cmp(arg_header.str, "id_table")==0 ){ + str_cmp(arg_header.str, "id_table")==0 &&\ + str_cmp(arg_header.str, "postprocess_operation")==0 &&\ + str_cmp(arg_header.str, "numerical_postprocess_operation")==0 + ){ printf("%s\n&\n",str_args.strs[i].str); } free_Char_Array(arg_header); @@ -268,34 +357,66 @@ int compute_flow(Str_Array str_args, Meankondo_Options opts){ printf("#!flow_equation\n"); } - // print flow equation - grouped_polynomial_print(flow_equation,'%','%'); + // print result + if(opts.group_poly==1){ + grouped_polynomial_print(flow_equation,'%','%'); + + // free memory + free_Grouped_Polynomial(flow_equation); + } + else{ + polynomial_print(exp_poly); + } // free memory - free_Id_Table(idtable); - free_Grouped_Polynomial(flow_equation); + free_Polynomial(exp_poly); + + // parse numerical_postprocessing entry + arg_index=find_str_arg("numerical_postprocess_operation", str_args); + if(arg_index>=0){ + Polynomial rcc_polynomial; + // polynomial made of the rcc's multiplied by the corresponding fields (parsed from idtable) + idtable_to_polynomial(idtable, &rcc_polynomial); + + // add to variables + add_polynomial_to_variables("RCC", rcc_polynomial, &variables); + free_Polynomial(rcc_polynomial); + + // parse postprocess entry + Polynomial numerical_postprocess_operation; + parse_input_polynomial(str_args.strs[arg_index], &numerical_postprocess_operation, fields, variables); + + // convert to flow equation + Grouped_Polynomial numerical_postprocess_flow_equation; + group_polynomial(numerical_postprocess_operation, &numerical_postprocess_flow_equation, idtable, fields); + free_Polynomial(numerical_postprocess_operation); + + // print postprocessing flow equation + printf("\n&\n#!postprocess_operation\n"); + grouped_polynomial_print(numerical_postprocess_flow_equation,'%','%'); + free_Grouped_Polynomial(numerical_postprocess_flow_equation); + } + + if(opts.group_poly==1){ + free_Id_Table(idtable); + } + free_Fields_Table(fields); + free_Variables(variables); + return(0); } -// compute the flow equation -int compute_flow_equation(Polynomial init_poly, Id_Table idtable, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, Grouped_Polynomial* flow_equation){ - // expectation - Polynomial exp_poly; - - polynomial_cpy(init_poly,&exp_poly); +// compute average +int compute_average(Polynomial init_poly, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, int print_progress, Polynomial* exp_poly){ + polynomial_cpy(init_poly,exp_poly); // average if(threads>1){ - polynomial_mean_multithread(&exp_poly, fields, propagator, groups, threads); + polynomial_mean_multithread(exp_poly, fields, propagator, groups, threads, print_progress); } else{ - polynomial_mean(&exp_poly, fields, propagator, groups); + polynomial_mean(exp_poly, fields, propagator, groups, print_progress); } - - // grouped representation of expanded_poly - group_polynomial(exp_poly,flow_equation,idtable, fields); - free_Polynomial(exp_poly); - return(0); } diff --git a/src/meantools.c b/src/meantools.c index e3e7247..64cf3f1 100644 --- a/src/meantools.c +++ b/src/meantools.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -39,13 +39,13 @@ Utility to perform various operations on flow equations // string functions #include "istring.h" // tools -#include "meantools_exp.h" #include "meantools_deriv.h" #include "meantools_eval.h" +#include "meantools_expand.h" -#define EXP_COMMAND 1 -#define DERIV_COMMAND 2 -#define EVAL_COMMAND 3 +#define DERIV_COMMAND 1 +#define EVAL_COMMAND 2 +#define EXPAND_COMMAND 3 // read cli arguments int read_args_meantools(int argc,const char* argv[], Str_Array* str_args, Meantools_Options* opts); @@ -63,12 +63,12 @@ int main (int argc, const char* argv[]){ read_args_meantools(argc,argv,&str_args, &opts); switch(opts.command){ - case EXP_COMMAND: tool_exp(str_args); - break; case DERIV_COMMAND: tool_deriv(str_args,opts); break; case EVAL_COMMAND: tool_eval(str_args,opts); break; + case EXPAND_COMMAND: tool_expand(str_args,opts); + break; } //free memory @@ -86,11 +86,7 @@ int read_args_meantools(int argc,const char* argv[], Str_Array* str_args, Meanto exit(-1); } - if(str_cmp((char*)argv[1],"exp")==1){ - (*opts).command=EXP_COMMAND; - tool_exp_read_args(argc, argv, str_args); - } - else if(str_cmp((char*)argv[1],"derive")==1){ + if(str_cmp((char*)argv[1],"differentiate")==1){ (*opts).command=DERIV_COMMAND; tool_deriv_read_args(argc, argv, str_args, opts); } @@ -98,6 +94,10 @@ int read_args_meantools(int argc,const char* argv[], Str_Array* str_args, Meanto (*opts).command=EVAL_COMMAND; tool_eval_read_args(argc, argv, str_args, opts); } + else if(str_cmp((char*)argv[1],"expand")==1){ + (*opts).command=EXPAND_COMMAND; + tool_expand_read_args(argc, argv, str_args, opts); + } else{ print_usage_meantools(); exit(-1); @@ -108,9 +108,6 @@ int read_args_meantools(int argc,const char* argv[], Str_Array* str_args, Meanto // print usage message int print_usage_meantools(){ - printf("\nusage:\n meantools exp [config_file]\n meantools derive [-d derivatives] [-V variables] [-C] [config_file]\n meantools eval [-R values] [-P precision] [-E max_exponent] [config_file]\n\n"); + printf("\nusage:\n meantools differentiate [-d derivatives] [-V variables] [-C] [config_file]\n meantools eval [-R values] [-P precision] [-E max_exponent] [config_file]\n meantools expand [-N namespace] [config_file]\n\n"); return(0); } - - - diff --git a/src/meantools_deriv.c b/src/meantools_deriv.c index b096380..3530808 100644 --- a/src/meantools_deriv.c +++ b/src/meantools_deriv.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -42,9 +42,9 @@ int tool_deriv_read_args(int argc, const char* argv[], Str_Array* str_args, Mean char* ptr; // defaults - // derive once + // differentiate once (*opts).deriv_derivs=1; - // derive with respect to all variables + // differentiate with respect to all variables (*opts).deriv_vars.length=-1; // do not chain (*opts).chain=0; @@ -77,7 +77,7 @@ int tool_deriv_read_args(int argc, const char* argv[], Str_Array* str_args, Mean } // variables else if(flag==CP_FLAG_VARS){ - // if the argument is "all" then derive wrt all variables + // if the argument is "all" then differentiate wrt all variables if(str_cmp((char*)argv[i],"all")){ (*opts).deriv_vars.length=-2; } @@ -101,7 +101,7 @@ int tool_deriv_read_args(int argc, const char* argv[], Str_Array* str_args, Mean } -// derive a flow equation +// differentiate a flow equation int tool_deriv(Str_Array str_args, Meantools_Options opts){ // index of the entry in the input file int arg_index; @@ -158,7 +158,7 @@ int tool_deriv(Str_Array str_args, Meantools_Options opts){ get_str_arg_title(str_args.strs[i], &arg_header); if (\ str_cmp(arg_header.str, "flow_equation")==0 &&\ - str_cmp(arg_header.str, "symbols")==0 &&\ + str_cmp(arg_header.str, "virtual_fields")==0 &&\ str_cmp(arg_header.str, "groups")==0 &&\ str_cmp(arg_header.str, "fields")==0 &&\ str_cmp(arg_header.str, "identities")==0 &&\ @@ -208,7 +208,7 @@ int flow_equation_derivative(int n, Int_Array variables, Grouped_Polynomial flow // free tmpflow free_Grouped_Polynomial(tmpflow); - // add the derived indices as variables for the next derivative + // add the differentiated indices as variables for the next derivative for(i=0;i<variables.length;i++){ if(variables.values[i]>=0){ int_array_append((j+1)*DOFFSET+variables.values[i], &indices); diff --git a/src/meantools_deriv.h b/src/meantools_deriv.h index 4ea36a9..7425fd1 100644 --- a/src/meantools_deriv.h +++ b/src/meantools_deriv.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -21,7 +21,7 @@ limitations under the License. // read arguments int tool_deriv_read_args(int argc, const char* argv[], Str_Array* str_args, Meantools_Options* opts); -// derive a flow equation +// differentiate a flow equation int tool_deriv(Str_Array str_args, Meantools_Options opts); // n first derivatives of a flow equation wrt to variables int flow_equation_derivative(int n, Int_Array variables, Grouped_Polynomial flow_equation, Grouped_Polynomial* flow_equation_derivs); diff --git a/src/meantools_eval.c b/src/meantools_eval.c index 4f166cd..027d18d 100644 --- a/src/meantools_eval.c +++ b/src/meantools_eval.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -163,12 +163,12 @@ int tool_eval(Str_Array str_args, Meantools_Options opts){ // evaluate if(mpfr_flag==0){ - evaleq(&rccs, flow_equation); + evaleq(rccs, rccs, flow_equation); RCC_print(rccs); free_RCC(rccs); } else{ - evaleq_mpfr(&rccs_mpfr, flow_equation); + evaleq_mpfr(rccs_mpfr, rccs_mpfr, flow_equation); RCC_mpfr_print(rccs_mpfr); free_RCC_mpfr(rccs_mpfr); } diff --git a/src/meantools_eval.h b/src/meantools_eval.h index 518049d..54f6e51 100644 --- a/src/meantools_eval.h +++ b/src/meantools_eval.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/meantools_exp.c b/src/meantools_exp.c deleted file mode 100644 index 1aca928..0000000 --- a/src/meantools_exp.c +++ /dev/null @@ -1,130 +0,0 @@ -/* -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. -*/ - -#include "meantools_exp.h" - -#include <stdio.h> -#include <stdlib.h> -#include "parse_file.h" -#include "cli_parser.h" -#include "polynomial.h" -#include "fields.h" -#include "grouped_polynomial.h" -#include "idtable.h" - -// read command line arguments -int tool_exp_read_args(int argc, const char* argv[], Str_Array* str_args){ - // file to read the polynomial from in flow mode - const char* file=""; - // whether a file was specified on the command-line - int exists_file=0; - - if(argc>=3){ - file=argv[2]; - exists_file=1; - } - read_config_file(str_args, file, 1-exists_file); - - return(0); -} - - -// compute the exponential of the input polynomial -int tool_exp(Str_Array str_args){ - // index of the entry in the input file - int arg_index; - // list of fields - Fields_Table fields; - // input polynomial - Polynomial poly; - // exp as a polynomial - Polynomial exp_poly; - // list of rccs - Id_Table idtable; - // exp - Grouped_Polynomial exp; - int i,j; - - // parse fields - arg_index=find_str_arg("fields", str_args); - if(arg_index<0){ - fprintf(stderr,"error: no fields entry in the configuration file\n"); - exit(-1); - } - else{ - parse_input_fields(str_args.strs[arg_index],&fields); - } - - // parse id table - arg_index=find_str_arg("id_table", str_args); - if(arg_index<0){ - fprintf(stderr,"error: no id table entry in the configuration file\n"); - exit(-1); - } - else{ - parse_input_id_table(str_args.strs[arg_index],&idtable, fields); - } - - // parse input polynomial - arg_index=find_str_arg("input_polynomial", str_args); - if(arg_index>=0){ - parse_input_polynomial(str_args.strs[arg_index],&poly, fields); - } - else{ - fprintf(stderr,"error: no input polynomial entry in the configuration file\n"); - exit(-1); - } - - // parse symbols - arg_index=find_str_arg("symbols", str_args); - if(arg_index>=0){ - parse_input_symbols(str_args.strs[arg_index],&fields); - } - else{ - init_Symbols(&(fields.symbols),1); - } - - // parse identities - arg_index=find_str_arg("identities", str_args); - if(arg_index>=0){ - parse_input_identities(str_args.strs[arg_index],&fields); - } - else{ - init_Identities(&(fields.ids),1); - } - - // exp(V) - polynomial_exponential(poly,&exp_poly, fields); - // grouped representation - group_polynomial(exp_poly, &exp, idtable, fields); - free_Polynomial(exp_poly); - free_Polynomial(poly); - - // no denominators - for(i=0;i<exp.length;i++){ - for(j=0;j<exp.coefs[i].length;j++){ - exp.coefs[i].denoms[j].power=0; - } - } - - grouped_polynomial_print(exp,'%','%'); - - // free memory - free_Fields_Table(fields); - free_Id_Table(idtable); - free_Grouped_Polynomial(exp); - return(0); -} diff --git a/src/meantools_expand.c b/src/meantools_expand.c new file mode 100644 index 0000000..2586ff5 --- /dev/null +++ b/src/meantools_expand.c @@ -0,0 +1,166 @@ +/* +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 "meantools_expand.h" + +#include <stdio.h> +#include <stdlib.h> +#include "cli_parser.h" +#include "parse_file.h" +#include "polynomial.h" +#include "array.h" +#include "fields.h" + + +#define CP_FLAG_NAMESPACE 1 +// read command line arguments +int tool_expand_read_args(int argc, const char* argv[], Str_Array* str_args, Meantools_Options* opts){ + // file to read the polynomial from in flow mode + const char* file=""; + // whether a file was specified on the command-line + int exists_file=0; + // flag + int flag=0; + int i; + char* ptr; + + // defaults + // no namespace + (*opts).namespace.length=-1; + + + // loop over arguments + for(i=2;i<argc;i++){ + // flag + if(argv[i][0]=='-'){ + for(ptr=((char*)argv[i])+1;*ptr!='\0';ptr++){ + switch(*ptr){ + // number of derivatives + case 'N': + flag=CP_FLAG_NAMESPACE; + break; + } + } + } + // namespace + else if(flag==CP_FLAG_NAMESPACE){ + str_to_char_array((char*)argv[i], &(opts->namespace)); + flag=0; + } + // read file name from command-line + else{ + file=argv[i]; + exists_file=1; + } + } + + read_config_file(str_args, file, 1-exists_file); + + return(0); +} + + +// expand a polynomial +int tool_expand(Str_Array str_args, Meantools_Options opts){ + // index of the entry in the input file + int arg_index; + // input polynomial + Polynomial polynomial; + // fields table + Fields_Table fields; + // preprocessor variables + Variables variables; + + // parse fields + if(opts.namespace.length>=0){ + arg_index=find_str_arg_ns("fields", opts.namespace, str_args); + } + else{ + arg_index=find_str_arg("fields", str_args); + } + if(arg_index<0){ + fprintf(stderr,"error: no fields entry in the configuration file\n"); + exit(-1); + } + else{ + parse_input_fields(str_args.strs[arg_index],&fields); + } + + // parse variables + // must precede id_table, virtual_fields, identities and input_polynomial + if(opts.namespace.length>=0){ + arg_index=find_str_arg_ns("preprocessor_variables", opts.namespace, str_args); + } + else{ + arg_index=find_str_arg("preprocessor_variables", str_args); + } + if(arg_index>=0){ + parse_input_variables(str_args.strs[arg_index],&variables); + } + else{ + init_Variables(&variables,1); + } + + // parse virtual_fields + if(opts.namespace.length>=0){ + arg_index=find_str_arg_ns("virtual_fields", opts.namespace, str_args); + } + else{ + arg_index=find_str_arg("virtual_fields", str_args); + } + if(arg_index>=0){ + parse_input_virtual_fields(str_args.strs[arg_index], &fields, variables); + } + + // parse identities + if(opts.namespace.length>=0){ + arg_index=find_str_arg_ns("identities", opts.namespace, str_args); + } + else{ + arg_index=find_str_arg("identities", str_args); + } + if(arg_index>=0){ + parse_input_identities(str_args.strs[arg_index],&fields, variables); + } + + // parse input polynomial + if(opts.namespace.length>=0){ + arg_index=find_str_arg_ns("input_polynomial", opts.namespace, str_args); + } + else{ + arg_index=find_str_arg("input_polynomial", str_args); + } + if(arg_index>=0){ + parse_input_polynomial(str_args.strs[arg_index], &polynomial, fields, variables); + } + else{ + fprintf(stderr,"error: no input polynomial entry in the configuration file\n"); + exit(-1); + } + + // print polynomial + polynomial_print(polynomial); + + // free memory + free_Variables(variables); + free_Fields_Table(fields); + free_Polynomial(polynomial); + + if(opts.namespace.length>=0){ + free_Char_Array(opts.namespace); + } + return(0); +} diff --git a/src/meantools_exp.h b/src/meantools_expand.h index f3f6666..9d988b1 100644 --- a/src/meantools_exp.h +++ b/src/meantools_expand.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -14,14 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -#ifndef MEANTOOLS_EXP_H -#define MEANTOOLS_EXP_H +#ifndef MEANTOOLS_EXPAND_H +#define MEANTOOLS_EXPAND_H #include "types.h" // read arguments -int tool_exp_read_args(int argc, const char* argv[], Str_Array* str_args); -// compute the exponential of the input polynomial -int tool_exp(Str_Array str_args); +int tool_expand_read_args(int argc, const char* argv[], Str_Array* str_args, Meantools_Options* opts); +// expand a flow equation +int tool_expand(Str_Array str_args, Meantools_Options opts); #endif + + diff --git a/src/number.c b/src/number.c index e63427f..5bc87de 100644 --- a/src/number.c +++ b/src/number.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -27,6 +27,7 @@ limitations under the License. #include "tools.h" #include "rational.h" #include "array.h" +#include "parse_file.h" // init int init_Number(Number* number, int memory){ @@ -271,50 +272,107 @@ Number number_Qprod_ret(Q q, Number x){ return(ret); } -// inverse -int number_inverse_inplace(Number* inout){ - int i; - for(i=0;i<(*inout).length;i++){ - if((*inout).base[i]>0){ - (*inout).scalars[i]=Q_inverse((*inout).scalars[i]); - (*inout).scalars[i].denominator*=(*inout).base[i]; +// quotient of two numbers +// recursively simplify numerator/denominator until denominator only has one term +// the output is set to 'numerator' +// both numerator and denominator may be changed by this function +// this algorithm is not optimal in cases where denominator has several terms, in particular if their bases are large +// it is optimal if denominator only has one term +int number_quot_inplace(Number* numerator, Number* denominator){ + Number tmp; + int i,factor; + + switch((*denominator).length){ + // error + case 0: + fprintf(stderr,"error: attempting to invert 0\n"); + exit(-1); + break; + + // trivial case + case 1: + // trivial base + if((*denominator).base[0]==1){ + number_Qprod_chain(Q_inverse((*denominator).scalars[0]), numerator); } - else if((*inout).base[i]<0){ - (*inout).scalars[i]=Q_inverse((*inout).scalars[i]); - (*inout).scalars[i].denominator*=-(*inout).base[i]; - (*inout).scalars[i].numerator*=-1; + // non-trivial base + else{ + // set tmp=1/denominator + tmp=number_one(); + tmp.base[0]=(*denominator).base[0]; + tmp.scalars[0].denominator=(*denominator).scalars[0].numerator*abs((*denominator).base[0]); + if((*denominator).base[0]>0){ + tmp.scalars[0].numerator=(*denominator).scalars[0].denominator; + } + else if((*denominator).base[0]<0){ + tmp.scalars[0].numerator=-(*denominator).scalars[0].denominator; + } + else{ + fprintf(stderr,"error: attempting to invert 0\n"); + exit(-1); + } + number_prod_chain(tmp, numerator); + } + break; + + default: + // find non-trivial basis + for(i=0;(*denominator).base[i]==1;i++){} + + // smallest prime factor of the base + if((*denominator).base[i]<0){ + factor=-1; + } + else if((*denominator).base[i]==2){ + factor=2; } else{ - fprintf(stderr,"error: attempting to invert 0\n"); - exit(-1); + // COMMENT: this is not optimal, but, provided the basis is not too large, this should not be a problem + for(factor=3;is_factor(factor, (*denominator).base[i])==0;factor=factor+2){} + } + + // tmp is set to ((terms that k does not divide)-(terms that k divides)) + // tmp will be multiplied to numerator and denominator + init_Number(&tmp,(*denominator).length); + + // find all terms whose base is a multiple of k + for(i=0;i<(*denominator).length;i++){ + if(is_factor(factor, (*denominator).base[i])){ + // add to tmp with a - sign + number_add_elem(quot(-(*denominator).scalars[i].numerator,(*denominator).scalars[i].denominator), (*denominator).base[i], &tmp); + } + else{ + // add to tmp + number_add_elem((*denominator).scalars[i], (*denominator).base[i], &tmp); + } } + + number_prod_chain(tmp, numerator); + number_prod_chain(tmp, denominator); + free_Number(tmp); + + // recurse + number_quot_inplace(numerator, denominator); } + return(0); } -// write to output -int number_inverse(Number input, Number* output){ - number_cpy(input,output); - number_inverse_inplace(output); - return(0); -} -// return result -Number number_inverse_ret(Number x){ - Number ret; - number_inverse(x,&ret); - return(ret); -} -// quotient +// not inplace int number_quot(Number x1, Number x2, Number* output){ - Number inv; - number_inverse(x2, &inv); - number_prod(x1, inv, output); - free_Number(inv); + Number numerator, denominator; + number_cpy(x1, &numerator); + number_cpy(x2, &denominator); + number_quot_inplace(&numerator, &denominator); + *output=numerator; + free_Number(denominator); return(0); } -int number_quot_chain(Number x1, Number* inout){ - number_inverse_inplace(inout); - number_prod_chain(x1, inout); +int number_quot_chain(Number* inout, Number x2){ + Number tmp; + number_quot(*inout,x2,&tmp); + free_Number(*inout); + *inout=tmp; return(0); } Number number_quot_ret(Number x1, Number x2){ @@ -419,7 +477,7 @@ int number_print(Number number){ Char_Array buffer; init_Char_Array(&buffer,5*number.length); number_sprint(number, &buffer); - printf("%s",buffer.str); + printf("%s",char_array_to_str_noinit(&buffer)); return(0); } @@ -434,18 +492,54 @@ int str_to_Number(char* str, Number* number){ char* buffer_ptr=buffer; Q num; int base; - // whether there are parentheses in the string - int exist_parenthesis=0; + int ret; + int j; + char* aux_str; + int aux_free=0; init_Number(number, NUMBER_SIZE); + // check whether the string is blank (return 0 in that case) + for(ptr=str;*ptr!='\0';ptr++){ + if(*ptr!=' ' && *ptr!='\n'){ + break; + } + } + // blank string + if(*ptr=='\0'){ + number_add_elem(quot(0,1), 1, number); + free(buffer); + return(0); + } + // init num and base - // init to 0 so that if str is empty, then the number is set to 0 - num=quot(0,1); + num=quot(1,1); base=1; + // check whether the str only contains a rational number, and add parentheses + // keep rtack of the length of str + for(j=0,ptr=str;*ptr!='\0';j++,ptr++){ + if((*ptr<'0' || *ptr>'9') && *ptr!='-' && *ptr!='/'){ + break; + } + } + // only rational + if(*ptr=='\0'){ + aux_str=calloc(j+3,sizeof(char)); + aux_str[0]='('; + for(j=0,ptr=str;*ptr!='\0';ptr++,j++){ + aux_str[j+1]=*ptr; + } + aux_str[j+1]=')'; + aux_str[j+2]='\0'; + aux_free=1; + } + else{ + aux_str=str; + } + mode=PP_NULL_MODE; - for(ptr=str;*ptr!='\0';ptr++){ + for(ptr=aux_str;*ptr!='\0';ptr++){ switch(*ptr){ // read number case '(': @@ -453,7 +547,10 @@ int str_to_Number(char* str, Number* number){ // init base base=1; mode=PP_NUM_MODE; - exist_parenthesis=1; + } + else{ + fprintf(stderr,"syntax error: misplaced '(' in number '%s'\n",str); + exit(-1); } break; case ')': @@ -463,6 +560,10 @@ int str_to_Number(char* str, Number* number){ *buffer_ptr='\0'; mode=PP_NULL_MODE; } + else{ + fprintf(stderr,"syntax error: mismatched ')' in number '%s'\n",str); + exit(-1); + } break; // read sqrt @@ -474,16 +575,26 @@ int str_to_Number(char* str, Number* number){ if(mode==PP_NULL_MODE){ mode=PP_SQRT_MODE; } - // if there is a square root, then do not read a fraction (see end of loop) - exist_parenthesis=1; + else{ + fprintf(stderr,"syntax error: misplaced '{' in number '%s'\n",str); + exit(-1); + } break; case '}': if(mode==PP_SQRT_MODE){ - sscanf(buffer,"%d",&base); + ret=read_int(buffer,&base); + if(ret<0){ + fprintf(stderr,"syntax error: number base should be an integer, got '%s' in '%s'",buffer,str); + exit(-1); + } buffer_ptr=buffer; *buffer_ptr='\0'; mode=PP_NULL_MODE; } + else{ + fprintf(stderr,"syntax error: mismatched '}' in number '%s'\n",str); + exit(-1); + } break; // write num @@ -494,24 +605,40 @@ int str_to_Number(char* str, Number* number){ num=quot(0,1); base=1; } + else{ + fprintf(stderr,"syntax error: misplaced '+' in number '%s'\n",str); + exit(-1); + } break; + // ignore 's', ' ' and '\n' + case 's':break; + case ' ':break; + case '\n':break; default: if(mode!=PP_NULL_MODE){ buffer_ptr=str_addchar(buffer_ptr,*ptr); } + else{ + fprintf(stderr,"syntax error: unrecognized character '%c' in number '%s'\n",*ptr,str); + exit(-1); + } break; } } - // last step if(mode==PP_NULL_MODE){ - if(exist_parenthesis==0){ - str_to_Q(str, &num); - } number_add_elem(num, base, number); } + else{ + fprintf(stderr,"syntax error: mismatched '(' in number '%s'\n",str); + exit(-1); + } + + if(aux_free==1){ + free(aux_str); + } free(buffer); return(0); } diff --git a/src/number.h b/src/number.h index a33d425..5eacdaa 100644 --- a/src/number.h +++ b/src/number.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -78,16 +78,11 @@ int number_Qprod(Q q, Number x, Number* inout); // return result Number number_Qprod_ret(Q q, Number x); -// inverse -int number_inverse_inplace(Number* inout); -// write to output -int number_inverse(Number input, Number* output); -// return result -Number number_inverse_ret(Number x); - -// quotient +// quotient of two numbers +int number_quot_inplace(Number* numerator, Number* denominator); +// not inplace int number_quot(Number x1, Number x2, Number* output); -int number_quot_chain(Number x1, Number* inout); +int number_quot_chain(Number* inout, Number x2); Number number_quot_ret(Number x1, Number x2); // remove 0's diff --git a/src/numkondo.c b/src/numkondo.c index 0568861..91e6be2 100644 --- a/src/numkondo.c +++ b/src/numkondo.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -86,12 +86,6 @@ int read_args_numkondo(int argc,const char* argv[], Str_Array* str_args, Numkond // whether a file was specified on the command-line int exists_file=0; - // if there are no arguments - if(argc==1){ - print_usage_numkondo(); - exit(-1); - } - // defaults // display entire flow (*opts).display_mode=DISPLAY_NUMERICAL; @@ -193,6 +187,8 @@ int numflow(Str_Array str_args, Numkondo_Options opts){ Grouped_Polynomial flow_equation; // whether or not to use mpfr floats int mpfr_flag=0; + // postprocess flow equation + Grouped_Polynomial postprocess_flow_equation; // set mpfr defaults if(opts.mpfr_prec!=0){ @@ -205,7 +201,7 @@ int numflow(Str_Array str_args, Numkondo_Options opts){ } - // parse id table + // parse labels arg_index=find_str_arg("labels", str_args); if(arg_index<0){ fprintf(stderr,"error: no labels entry in the configuration file\n"); @@ -225,6 +221,16 @@ int numflow(Str_Array str_args, Numkondo_Options opts){ char_array_to_Grouped_Polynomial(str_args.strs[arg_index], &flow_equation); } + // parse postprocess operation + arg_index=find_str_arg("postprocess_operation", str_args); + if(arg_index>=0){ + char_array_to_Grouped_Polynomial(str_args.strs[arg_index], &postprocess_flow_equation); + } + else{ + init_Grouped_Polynomial(&postprocess_flow_equation,1); + } + + // initial conditions // check they were not specified on the command line if(opts.eval_rccstring.length==-1){ @@ -252,17 +258,18 @@ int numflow(Str_Array str_args, Numkondo_Options opts){ } if(mpfr_flag==0){ - numerical_flow(flow_equation, init_cd, labels, opts.niter, opts.display_mode); + numerical_flow(flow_equation, init_cd, postprocess_flow_equation, labels, opts.niter, opts.display_mode); free_RCC(init_cd); } else{ - numerical_flow_mpfr(flow_equation, init_cd_mpfr, labels, opts.niter, opts.display_mode); + numerical_flow_mpfr(flow_equation, init_cd_mpfr, postprocess_flow_equation, labels, opts.niter, opts.display_mode); free_RCC_mpfr(init_cd_mpfr); } // free memory free_Labels(labels); + free_Grouped_Polynomial(postprocess_flow_equation); free_Grouped_Polynomial(flow_equation); return(0); } diff --git a/src/parse_file.c b/src/parse_file.c index ae3a9af..e998803 100644 --- a/src/parse_file.c +++ b/src/parse_file.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -30,6 +30,8 @@ limitations under the License. #include "istring.h" #include "tools.h" #include "idtable.h" +#include "tree.h" +#include "symbolic_parser.h" // parsing modes @@ -59,6 +61,70 @@ limitations under the License. #define PP_GROUP_MODE 16 +// read a positive integer from a string +int read_positive_int(char* str, int* out){ + char* ptr; + int res; + for(ptr=str;*ptr!='\0';ptr++){ + if(*ptr-'0'>=10 || *ptr-'0'<0){ + return(-1); + } + } + res=sscanf(str,"%d",out); + if(res!=1){ + return(-2); + } + return(0); +} +// read an integer from a string +int read_int(char* str, int* out){ + char* ptr; + int res; + for(ptr=str;*ptr!='\0';ptr++){ + if((*ptr-'0'>=10 || *ptr-'0'<0) && (*ptr!='-')){ + return(-1); + } + } + res=sscanf(str,"%d",out); + if(res!=1){ + return(-2); + } + return(0); +} +// read an long int from a string +int read_long_int(char* str, long int* out){ + char* ptr; + int res; + for(ptr=str;*ptr!='\0';ptr++){ + if((*ptr-'0'>=10 || *ptr-'0'<0) && (*ptr!='-')){ + return(-1); + } + } + res=sscanf(str,"%ld",out); + if(res!=1){ + return(-2); + } + return(0); +} + +// read a long double +int read_long_double(char* str, long double* out){ + char* ptr; + int res; + for(ptr=str;*ptr!='\0';ptr++){ + if((*ptr-'0'>=10 || *ptr-'0'<0) && (*ptr!='-') && (*ptr!='e') && (*ptr!='E') && (*ptr!='.')){ + return(-1); + } + } + res=sscanf(str,"%Lf",out); + if(res!=1){ + return(-2); + } + return(0); +} + + + // parse fields list int parse_input_fields(Char_Array str_fields, Fields_Table* fields){ // buffer @@ -67,6 +133,8 @@ int parse_input_fields(Char_Array str_fields, Fields_Table* fields){ int i,j; int mode; int comment=0; + int res; + int expect_colon=0; // allocate memory init_Fields_Table(fields); @@ -86,39 +154,100 @@ int parse_input_fields(Char_Array str_fields, Fields_Table* fields){ if(mode==PP_NULL_MODE){ mode=PP_PARAMETER_MODE; } + else{ + fprintf(stderr,"syntax error: fields entry (%d): 'h' should be at the beginning of the line\n",j); + exit(-1); + } + // flag: colon is expected immediately after letter + expect_colon=1; break; // external fields case 'x': if(mode==PP_NULL_MODE){ mode=PP_EXTERNAL_MODE; } + else{ + fprintf(stderr,"syntax error: fields entry (%d): 'x' should be at the beginning of the line\n",j); + exit(-1); + } + // flag: colon is expected immediately after letter + expect_colon=1; break; // internal fields case 'i': if(mode==PP_NULL_MODE){ mode=PP_INTERNAL_MODE; } + else{ + fprintf(stderr,"syntax error: fields entry (%d): 'i' should be at the beginning of the line\n",j); + exit(-1); + } + // flag: colon is expected immediately after letter + expect_colon=1; break; case 'f': if(mode==PP_NULL_MODE){ mode=PP_FERMIONS_MODE; } + else{ + fprintf(stderr,"syntax error: fields entry (%d): 'f' should be at the beginning of the line\n",j); + exit(-1); + } + // flag: colon is expected immediately after letter + expect_colon=1; break; case 'a': if(mode==PP_NULL_MODE){ mode=PP_NONCOMMUTING_MODE; } + else{ + fprintf(stderr,"syntax error: fields entry (%d): 'a' should be at the beginning of the line\n",j); + exit(-1); + } + // flag: colon is expected immediately after letter + expect_colon=1; break; // reset buffer case ':': + // check mode + if(mode==PP_NULL_MODE || expect_colon==0){ + fprintf(stderr,"syntax error: fields entry (%d): ':' must be preceded by 'h', 'x', 'i', 'f', or 'a' on the same line\n",j); + exit(-1); + } + expect_colon=0; buffer_ptr=buffer; *buffer_ptr='\0'; break; // write to fields case ',': - sscanf(buffer,"%d",&i); + res=read_positive_int(buffer,&i); + + // check i + if(res<0){ + fprintf(stderr,"syntax error: fields entry (%d): fields must be non-negative integers, got '%s'\n",j,buffer); + exit(-1); + } + if(mode==PP_PARAMETER_MODE || mode==PP_EXTERNAL_MODE || mode==PP_INTERNAL_MODE){ + if(int_array_find(i,fields->parameter)>=0 || int_array_find(i,fields->external)>=0 || int_array_find(i,fields->internal)>=0){ + fprintf(stderr,"error: fields entry (%d): field %d is already present in the fields table\n",j,i); + exit(-1); + } + } + else if(mode==PP_FERMIONS_MODE){ + if(int_array_find(i,fields->fermions)>=0){ + fprintf(stderr,"error: fields entry (%d): field %d is already present in the Fermions table\n",j,i); + exit(-1); + } + } + else if(mode==PP_NONCOMMUTING_MODE){ + if(int_array_find(i,fields->noncommuting)>=0){ + fprintf(stderr,"error: fields entry (%d): field %d is already present in the noncommuting table\n",j,i); + exit(-1); + } + } + if(mode==PP_PARAMETER_MODE){ int_array_append(i,&((*fields).parameter)); } @@ -134,31 +263,65 @@ int parse_input_fields(Char_Array str_fields, Fields_Table* fields){ else if(mode==PP_NONCOMMUTING_MODE){ int_array_append(i,&((*fields).noncommuting)); } + else{ + fprintf(stderr,"syntax error: fields entry (%d): misplaced ','\n",j); + exit(-1); + } buffer_ptr=buffer; *buffer_ptr='\0'; break; // back to null mode case '\n': - sscanf(buffer,"%d",&i); - if(mode==PP_PARAMETER_MODE){ - int_array_append(i,&((*fields).parameter)); - } - else if(mode==PP_EXTERNAL_MODE){ - int_array_append(i,&((*fields).external)); - } - else if(mode==PP_INTERNAL_MODE){ - int_array_append(i,&((*fields).internal)); - } - else if(mode==PP_FERMIONS_MODE){ - int_array_append(i,&((*fields).fermions)); - } - else if(mode==PP_NONCOMMUTING_MODE){ - int_array_append(i,&((*fields).noncommuting)); + // ignore if in NULL_MODE + if(mode!=PP_NULL_MODE){ + res=read_positive_int(buffer,&i); + // check i + if(res<0){ + fprintf(stderr,"syntax error: fields entry (%d): fields must be non-negative integers, got '%s'\n",j,buffer); + exit(-1); + } + if(mode==PP_PARAMETER_MODE || mode==PP_EXTERNAL_MODE || mode==PP_INTERNAL_MODE){ + if(int_array_find(i,fields->parameter)>=0 || int_array_find(i,fields->external)>=0 || int_array_find(i,fields->internal)>=0){ + fprintf(stderr,"error: fields entry (%d): field %d is already present in the fields table\n",j,i); + exit(-1); + } + } + else if(mode==PP_FERMIONS_MODE){ + if(int_array_find(i,fields->fermions)>=0){ + fprintf(stderr,"error: fields entry (%d): field %d is already present in the Fermions table\n",j,i); + exit(-1); + } + } + else if(mode==PP_NONCOMMUTING_MODE){ + if(int_array_find(i,fields->noncommuting)>=0){ + fprintf(stderr,"error: fields entry (%d): field %d is already present in the noncommuting table\n",j,i); + exit(-1); + } + } + + if(mode==PP_PARAMETER_MODE){ + int_array_append(i,&((*fields).parameter)); + } + else if(mode==PP_EXTERNAL_MODE){ + int_array_append(i,&((*fields).external)); + } + else if(mode==PP_INTERNAL_MODE){ + int_array_append(i,&((*fields).internal)); + } + else if(mode==PP_FERMIONS_MODE){ + int_array_append(i,&((*fields).fermions)); + } + else if(mode==PP_NONCOMMUTING_MODE){ + int_array_append(i,&((*fields).noncommuting)); + } + mode=PP_NULL_MODE; } - mode=PP_NULL_MODE; break; + + // ignore spaces + case ' ':break; // comment case '#': comment=1; @@ -168,57 +331,85 @@ int parse_input_fields(Char_Array str_fields, Fields_Table* fields){ if(mode!=PP_NULL_MODE){ buffer_ptr=str_addchar(buffer_ptr,str_fields.str[j]); } + else{ + fprintf(stderr,"syntax error: fields entry (%d): unrecognized character '%c'\n",j,str_fields.str[j]); + exit(-1); + } + break; + break; } } } free(buffer); + + // check whether there are non-Fermionic internal fields + for(i=0;i<(*fields).internal.length;i++){ + if(is_fermion((*fields).internal.values[i], *fields)==0){ + fprintf(stderr,"warning: some internal fields are not Fermions: means may be computed using sums over permutations rather than the more efficient LU decomposition\n"); + break; + } + } + return(0); } -// parse symbols list +// parse virtual_fields list // write result to fields -int parse_input_symbols(Char_Array str_symbols, Fields_Table* fields){ +int parse_input_virtual_fields(Char_Array str_virtual_fields, Fields_Table* fields, Variables variables){ // buffer - char* buffer=calloc(str_symbols.length+1,sizeof(char)); + char* buffer=calloc(str_virtual_fields.length+1,sizeof(char)); char* buffer_ptr=buffer; Polynomial polynomial; int index; int i,j; int mode; int comment=0; + int res; // loop over input mode=PP_INDEX_MODE; - for(j=0;j<str_symbols.length;j++){ + for(j=0;j<str_virtual_fields.length;j++){ if(comment==1){ - if(str_symbols.str[j]=='\n'){ + if(str_virtual_fields.str[j]=='\n'){ comment=0; } } // stay in polynomial mode until ',' else if(mode==PP_POLYNOMIAL_MODE){ - if(str_symbols.str[j]==','){ + if(str_virtual_fields.str[j]==','){ // parse polynomial - str_to_Polynomial(buffer, &polynomial); + parse_symbolic_expression_str(buffer, *fields, variables, &polynomial); // write index and polynomial - symbols_append_noinit(index, polynomial, &((*fields).symbols)); + virtual_fields_append_noinit(index, polynomial, &((*fields).virtual_fields)); mode=PP_INDEX_MODE; buffer_ptr=buffer; *buffer_ptr='\0'; } + // check there are no '=' signs in polynomial (forgotten ',') + else if(str_virtual_fields.str[j]=='='){ + fprintf(stderr,"syntax error: virtual fields entry (%d): '=' in polynomial '%s'\n",j, buffer); + exit(-1); + } + else if(str_virtual_fields.str[j]=='#'){ + comment=1; + } else{ - buffer_ptr=str_addchar(buffer_ptr,str_symbols.str[j]); + buffer_ptr=str_addchar(buffer_ptr,str_virtual_fields.str[j]); } } else{ - switch(str_symbols.str[j]){ + switch(str_virtual_fields.str[j]){ // polynomial mode case '=': if(mode==PP_INDEX_MODE){ // read index - sscanf(buffer,"%d",&index); + res=read_positive_int(buffer, &index); + if(res<0){ + fprintf(stderr,"syntax error: virtual fields entry (%d): virtual field index must be a non-negative integer, got '%s'\n",j,buffer); + exit(-1); + } // reset buffer buffer_ptr=buffer; *buffer_ptr='\0'; @@ -226,43 +417,53 @@ int parse_input_symbols(Char_Array str_symbols, Fields_Table* fields){ } break; + // misplaced ',' + case ',': + fprintf(stderr,"syntax error: virtual fields entry (%d): misplaced ',' or forgotten virtual field index\n",j); + exit(-1); + break; + + // ignore spaces and newlines + case ' ':break; + case '\n':break; + // comment case '#': comment=1; break; default: - buffer_ptr=str_addchar(buffer_ptr,str_symbols.str[j]); + buffer_ptr=str_addchar(buffer_ptr,str_virtual_fields.str[j]); break; } } } // last step - if(polynomial.length>0){ - str_to_Polynomial(buffer, &polynomial); - symbols_append_noinit(index, polynomial, &((*fields).symbols)); - } + parse_symbolic_expression_str(buffer, *fields, variables, &polynomial); + virtual_fields_append_noinit(index, polynomial, &((*fields).virtual_fields)); // simplify - for(i=0;i<(*fields).symbols.length;i++){ - polynomial_simplify((*fields).symbols.expr+i, *fields); + for(i=0;i<(*fields).virtual_fields.length;i++){ + polynomial_simplify((*fields).virtual_fields.expr+i, *fields); } free(buffer); return(0); } + // parse groups of independent fields -int parse_input_groups(Char_Array str_groups, Groups* groups){ +int parse_input_groups(Char_Array str_groups, Groups* groups, Polynomial_Matrix propagator, Fields_Table fields){ // buffer char* buffer=calloc(str_groups.length+1,sizeof(char)); char* buffer_ptr=buffer; int index; - int j; + int i,j; Int_Array group; int mode; int comment=0; + int res; // alloc init_Groups(groups, GROUP_SIZE); @@ -287,26 +488,60 @@ int parse_input_groups(Char_Array str_groups, Groups* groups){ init_Int_Array(&group, GROUP_SIZE); mode=PP_GROUP_MODE; } + else{ + fprintf(stderr,"syntax error: groups entry (%d): nested parentheses are not allowed in this entry\n",j); + exit(-1); + } break; case')': if(mode==PP_GROUP_MODE){ - sscanf(buffer,"%d",&index); + res=read_positive_int(buffer,&index); + if(res<0){ + fprintf(stderr,"syntax error: groups entry (%d): index must be a non-negative integer, got '%s'\n",j,buffer); + exit(-1); + } + for(i=0;i<groups->length;i++){ + if(int_array_find(index,groups->indices[i])>=0){ + fprintf(stderr,"syntax error: groups entry (%d): index %d is already present in group %d\n",j,index,i); + exit(-1); + } + } + int_array_append(index, &group); groups_append_noinit(group, groups); mode=PP_NULL_MODE; } + else{ + fprintf(stderr,"syntax error: groups entry (%d): extra ')'\n",j); + exit(-1); + } break; // read index case',': if(mode==PP_GROUP_MODE){ - sscanf(buffer,"%d",&index); + res=read_positive_int(buffer,&index); + if(res<0){ + fprintf(stderr,"syntax errorL groups entry (%d): index must be a non-negative integer, got '%s'\n",j,buffer); + exit(-1); + } + for(i=0;i<groups->length;i++){ + if(int_array_find(index,groups->indices[i])>=0){ + fprintf(stderr,"syntax error: groups entry (%d): index %d is already present in group %d\n",j,index,i); + exit(-1); + } + } + int_array_append(index, &group); buffer_ptr=buffer; *buffer_ptr='\0'; } break; + // skip spaces and newlines + case ' ':break; + case '\n':break; + // comment case '#': comment=1; @@ -316,11 +551,204 @@ int parse_input_groups(Char_Array str_groups, Groups* groups){ if(mode!=PP_NULL_MODE){ buffer_ptr=str_addchar(buffer_ptr,str_groups.str[j]); } + else{ + fprintf(stderr,"syntax error: groups entry (%d): unrecognized character '%c'\n",j,str_groups.str[j]); + exit(-1); + } + break; + } + } + } + + // check fields in groups + check_groups(*groups, propagator, fields); + + free(buffer); + return(0); +} + +// check that the members of groups are independent (assuming the virtual fields and propagator were already parsed) +int check_groups(Groups groups, Polynomial_Matrix propagator, Fields_Table fields){ + Int_Array* group_fields=calloc(groups.length,sizeof(Int_Array)); + int i,j,k,l,a,b; + + // get the lists of fields involved in each group + for(i=0;i<groups.length;i++){ + // expand virtual_fields + fields_in_virtual_field_list(groups.indices[i], fields, group_fields+i); + } + + // check whether pairs of fields are present in the propagator + for(i=0;i<groups.length;i++){ + for(j=0;j<group_fields[i].length;j++){ + if(field_type(group_fields[i].values[j], fields)==FIELD_INTERNAL){ + for(k=0;k<groups.length;k++){ + if(k!=i){ + for(l=0;l<group_fields[k].length;l++){ + if(field_type(group_fields[k].values[l], fields)==FIELD_INTERNAL){ + if(group_fields[i].values[j]==group_fields[k].values[l]){ + fprintf(stderr,"error: groups %d and %d both contain internal field %d\n",i,k,group_fields[i].values[j]); + exit(-1); + } + a=intlist_find(propagator.indices, propagator.length, group_fields[i].values[j]); + b=intlist_find(propagator.indices, propagator.length, group_fields[k].values[l]); + if(a>=0 && b>=0 && polynomial_is_zero(propagator.matrix[a][b])==0){ + fprintf(stderr,"error: groups %d and %d are not independent: they contain %d and %d which have a non-vanishing propagator\n",i,k,group_fields[i].values[j], group_fields[k].values[l]); + exit(-1); + } + } + } + } + } + } + } + } + + for(i=0;i<groups.length;i++){ + free_Int_Array(group_fields[i]); + } + free(group_fields); + + return(0); +} + +// list of fields involved in a list of virtual_fields +int fields_in_virtual_field_list(Int_Array indices, Fields_Table fields, Int_Array* output){ + int i,j,k; + Int_Array tmp_array; + + init_Int_Array(output,FIELDS_SIZE); + for(k=0;k<indices.length;k++){ + if(field_type(indices.values[k],fields)!=FIELD_VIRTUAL){ + int_array_append(abs(indices.values[k]), output); + } + else{ + i=intlist_find_err(fields.virtual_fields.indices, fields.virtual_fields.length, indices.values[k]); + for(j=0;j<fields.virtual_fields.expr[i].length;j++){ + fields_in_virtual_field_list(fields.virtual_fields.expr[i].monomials[j], fields, &tmp_array); + int_array_concat_unique(tmp_array, output); + free_Int_Array(tmp_array); + } + } + } + + return(0); +} + + + +// parse variables list +int parse_input_variables(Char_Array str_variables, Variables* variables){ + // buffer + char* buffer=calloc(str_variables.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Tree symbol_tree; + Char_Array varname; + int j; + int mode; + int comment=0; + char* ptr; + + init_Variables(variables,VARIABLES_SIZE); + + // loop over input + mode=PP_INDEX_MODE; + for(j=0;j<str_variables.length;j++){ + if(comment==1){ + if(str_variables.str[j]=='\n'){ + comment=0; + } + } + // stay in polynomial mode until ',' + else if(mode==PP_POLYNOMIAL_MODE){ + if(str_variables.str[j]==','){ + // parse symbol tree + str_to_symbol_tree(buffer, &symbol_tree); + variables_append_noinit(varname , symbol_tree, variables); + mode=PP_INDEX_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + // check there are no '=' signs in polynomial (forgotten ',') + else if(str_variables.str[j]=='='){ + fprintf(stderr,"syntax error: preprocessor_variables entry (%d): '=' in polynomial '%s'\n",j, buffer); + exit(-1); + } + else if(str_variables.str[j]=='#'){ + comment=1; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,str_variables.str[j]); + } + } + else{ + switch(str_variables.str[j]){ + // polynomial mode + case '=': + if(mode==PP_INDEX_MODE){ + if(*buffer=='\0'){ + fprintf(stderr,"syntax error: preprocessor_variables entry (%d): empty variable name\n",j); + exit(-1); + } + for(ptr=buffer;*ptr!='\0';ptr++){ + if(*ptr=='<' || *ptr=='>'){ + fprintf(stderr,"syntax error: preprocessor_variables entry (%d): forbidden '%c' character in variable name '%s'\n",j,*ptr,buffer); + exit(-1); + } + } + str_to_char_array(buffer,&varname); + // check that the variable name is not 'OUT' or 'FLOW' or 'RCC' + if(char_array_cmp_str(varname, "OUT")==1){ + fprintf(stderr,"error: preprocessor_variables entry (%d): variable name cannot be 'OUT' (this name is reserved)\n",j); + exit(-1); + } + if(char_array_cmp_str(varname, "FLOW")==1){ + fprintf(stderr,"error: preprocessor_variables entry (%d): variable name cannot be 'FLOW' (this name is reserved)\n",j); + exit(-1); + } + if(char_array_cmp_str(varname, "RCC")==1){ + fprintf(stderr,"error: preprocessor_variables entry (%d): variable name cannot be 'RCC' (this name is reserved)\n",j); + exit(-1); + } + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_POLYNOMIAL_MODE; + } + break; + + // misplaced ',' + case ',': + fprintf(stderr,"syntax error: preprocessor_variables entry (%d): misplaced ',' or forgotten variable name\n",j); + exit(-1); + break; + + // ignore characters + case ' ':break; + case '\n': break; + + // comment + case '#': + comment=1; + break; + + default: + buffer_ptr=str_addchar(buffer_ptr,str_variables.str[j]); break; } } } + // last step + if(mode==PP_POLYNOMIAL_MODE){ + str_to_symbol_tree(buffer, &symbol_tree); + variables_append_noinit(varname , symbol_tree, variables); + } + else if(*buffer!='\0'){ + fprintf(stderr,"syntax error: preprocessor_variables entry (%d): mismatched variable/polynomial pair, got '%s'\n",j,buffer); + exit(-1); + } + free(buffer); return(0); } @@ -328,7 +756,7 @@ int parse_input_groups(Char_Array str_groups, Groups* groups){ // parse identities between fields // write result to fields -int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ +int parse_input_identities(Char_Array str_identities, Fields_Table* fields, Variables variables){ // buffer char* buffer=calloc(str_identities.length+1,sizeof(char)); char* buffer_ptr=buffer; @@ -339,6 +767,7 @@ int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ int tmp; int mode; int comment=0; + int ret; init_Int_Array(&monomial, MONOMIAL_SIZE); @@ -354,13 +783,21 @@ int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ else if(mode==PP_POLYNOMIAL_MODE){ if(str_identities.str[j]==','){ // parse polynomial - str_to_Polynomial(buffer, &polynomial); + parse_symbolic_expression_str(buffer, *fields, variables, &polynomial); // write monomial and polynomial identities_append_noinit(monomial, polynomial, &((*fields).ids)); // realloc init_Int_Array(&monomial, MONOMIAL_SIZE); mode=PP_NULL_MODE; } + // check there are no '=' signs in polynomial (forgotten ',') + else if(str_identities.str[j]=='='){ + fprintf(stderr,"syntax error: identities entry (%d): '=' in polynomial '%s'\n",j, buffer); + exit(-1); + } + else if(str_identities.str[j]=='#'){ + comment=1; + } else{ buffer_ptr=str_addchar(buffer_ptr,str_identities.str[j]); } @@ -377,20 +814,36 @@ int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: identities entry (%d): misplaced '['\n",j); + exit(-1); + } break; // for notational homogeneity case 'f': if(mode==PP_BRACKET_MODE){ mode=PP_FIELD_MODE; } + else{ + fprintf(stderr,"syntax error: identities entry (%d): misplaced 'f'\n",j); + exit(-1); + } break; // write monomial term case ']': if(mode==PP_FIELD_MODE){ - sscanf(buffer,"%d",&i); + ret=read_int(buffer,&i); + if(ret<0){ + fprintf(stderr,"syntax error: identities entry (%d): field indices must be integers, got '%s'\n",j,buffer); + exit(-1); + } int_array_append(i,&monomial); mode=PP_INDEX_MODE; } + else{ + fprintf(stderr,"syntax error: identities entry (%d): mismatched ']'\n",j); + exit(-1); + } break; // polynomial mode @@ -400,8 +853,22 @@ int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ *buffer_ptr='\0'; mode=PP_POLYNOMIAL_MODE; } + else{ + fprintf(stderr,"syntax error: identities entry (%d): misplaced '='\n",j); + exit(-1); + } break; + // misplaced ',' + case ',': + fprintf(stderr,"syntax error: identities entry (%d): misplaced ',' or forgotten left hand side\n",j); + exit(-1); + break; + + // ignore spaces and newlines + case ' ':break; + case '\n':break; + // comment case '#': comment=1; @@ -411,6 +878,10 @@ int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ if(mode!=PP_NULL_MODE){ buffer_ptr=str_addchar(buffer_ptr,str_identities.str[j]); } + else{ + fprintf(stderr,"syntax error: identities entry (%d): unrecognized character '%c'\n",j,str_identities.str[j]); + exit(-1); + } break; } } @@ -418,9 +889,13 @@ int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ // last step if(mode==PP_POLYNOMIAL_MODE){ - str_to_Polynomial(buffer, &polynomial); + parse_symbolic_expression_str(buffer, *fields, variables, &polynomial); identities_append_noinit(monomial, polynomial, &((*fields).ids)); } + else if(*buffer!='\0'){ + fprintf(stderr,"syntax error: identities entry (%d): mismatched left/right hand side, got '%s'\n",j,buffer); + exit(-1); + } else{ free_Int_Array(monomial); } @@ -451,6 +926,7 @@ int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propaga int index2=-1; int mode; int comment=0; + int ret; // allocate memory init_Polynomial_Matrix(propagator, fields.internal.length); @@ -473,20 +949,36 @@ int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propaga // indices case ';': if(mode==PP_INDEX_MODE){ - sscanf(buffer,"%d",&i); + ret=read_positive_int(buffer,&i); + if(ret<0){ + fprintf(stderr,"syntax error: propagator entry (%d): indices must be non-negative integers, got '%s'\n",j,buffer); + exit(-1); + } index1=intlist_find_err((*propagator).indices, (*propagator).length, i); buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: propagator entry (%d): misplaced ';'\n",j); + exit(-1); + } break; case ':': if(mode==PP_INDEX_MODE){ - sscanf(buffer,"%d",&i); + ret=read_positive_int(buffer,&i); + if(ret<0){ + fprintf(stderr,"syntax error: propagator entry (%d): indices must be non-negative integers, got '%s'\n",j,buffer); + exit(-1); + } index2=intlist_find_err((*propagator).indices, (*propagator).length, i); buffer_ptr=buffer; *buffer_ptr='\0'; mode=PP_POLYNOMIAL_MODE; } + else{ + fprintf(stderr,"syntax error: propagator entry (%d): misplaced ':'\n",j); + exit(-1); + } break; // num @@ -494,12 +986,22 @@ int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propaga if(mode==PP_POLYNOMIAL_MODE && index1>=0 && index2>=0){ free_Polynomial((*propagator).matrix[index1][index2]); str_to_Polynomial(buffer,(*propagator).matrix[index1]+index2); + index1=-1; + index2=-1; buffer_ptr=buffer; *buffer_ptr='\0'; mode=PP_INDEX_MODE; } + else{ + fprintf(stderr,"syntax error: propagator entry (%d): mismatched index/polynomial pair\n",j); + exit(-1); + } break; + // ignore ' 'and newline + case ' ':break; + case '\n':break; + // comment case '#': comment=1; @@ -517,6 +1019,15 @@ int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propaga free_Polynomial((*propagator).matrix[index1][index2]); str_to_Polynomial(buffer,(*propagator).matrix[index1]+index2); } + else if (*buffer!='\0'){ + fprintf(stderr,"syntax error: propagator entry (%d): mismatched index/polynomial pair, got '%s'\n",j,buffer); + exit(-1); + } + + // check whether the polynomial is numeric + if(polynomial_matrix_is_numeric(*propagator)==0){ + fprintf(stderr,"warning: the propagator contains polynomial entries: means may be computed using sums over permutations rather than the more efficient LU decomposition\n"); + } free(buffer); return(0); @@ -524,49 +1035,9 @@ int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propaga // parse input polynomial -int parse_input_polynomial(Char_Array str_polynomial, Polynomial* output, Fields_Table fields){ - int j; - // buffer - char* buffer=calloc(str_polynomial.length+1,sizeof(char)); - char* buffer_ptr=buffer; - Polynomial tmp_poly; - - // allocate memory - init_Polynomial(output,POLY_SIZE); - - for(j=0;j<str_polynomial.length;j++){ - switch(str_polynomial.str[j]){ - case '*': - str_to_Polynomial(buffer, &tmp_poly); - if((*output).length==0){ - polynomial_concat(tmp_poly, output); - } - else{ - polynomial_prod_chain(tmp_poly, output, fields); - } - free_Polynomial(tmp_poly); - - buffer_ptr=buffer; - *buffer_ptr='\0'; - break; - - default: - buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); - break; - } - } - - //last step - str_to_Polynomial(buffer, &tmp_poly); - if((*output).length==0){ - polynomial_concat(tmp_poly, output); - } - else{ - polynomial_prod_chain(tmp_poly, output, fields); - } - free_Polynomial(tmp_poly); - - free(buffer); +int parse_input_polynomial(Char_Array str_polynomial, Polynomial* output, Fields_Table fields, Variables variables){ + parse_symbolic_expression(str_polynomial, fields, variables, output); + polynomial_simplify(output, fields); return(0); } @@ -574,7 +1045,7 @@ int parse_input_polynomial(Char_Array str_polynomial, Polynomial* output, Fields // parse id table // fields argument for sorting -int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table fields){ +int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table fields, Variables variables){ // buffer char* buffer=calloc(str_idtable.length+1,sizeof(char)); char* buffer_ptr=buffer; @@ -583,6 +1054,7 @@ int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table int j; int mode; int comment=0; + int ret; // allocate memory init_Id_Table(idtable,EQUATION_SIZE); @@ -601,24 +1073,40 @@ int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table case ',': // write polynomial if(mode==PP_POLYNOMIAL_MODE){ - str_to_Polynomial(buffer,&polynomial); + parse_symbolic_expression_str(buffer, fields, variables, &polynomial); // add to idtable idtable_append_noinit(index,polynomial,idtable); mode=PP_INDEX_MODE; buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: id_table entry (%d): misplaced ','\n",j); + exit(-1); + } break; case ':': if(mode==PP_INDEX_MODE){ - sscanf(buffer,"%d",&index); + ret=read_positive_int(buffer,&index); + if(ret<0){ + fprintf(stderr,"syntax error: id_table entry (%d): index must be a non-negative integer, got '%s'\n",j,buffer); + exit(-1); + } mode=PP_POLYNOMIAL_MODE; buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: id_table entry (%d): misplaced ':'\n",j); + exit(-1); + } break; + // ignore ' ' and '\n' + case ' ':break; + case '\n':break; + // comment case '#': comment=1; @@ -628,6 +1116,10 @@ int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table if(mode!=PP_NULL_MODE){ buffer_ptr=str_addchar(buffer_ptr,str_idtable.str[j]); } + else{ + fprintf(stderr,"syntax error: id_table entry (%d): unrecognized character '%c'\n",j, str_idtable.str[j]); + exit(-1); + } break; } } @@ -635,9 +1127,13 @@ int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table //last step if(mode==PP_POLYNOMIAL_MODE){ - str_to_Polynomial(buffer,&polynomial); + parse_symbolic_expression_str(buffer, fields, variables, &polynomial); idtable_append_noinit(index,polynomial,idtable); } + else if(*buffer!='\0'){ + fprintf(stderr,"syntax error: id_table entry (%d): mismatched index/polynomial pair, got '%s'\n",j,buffer); + exit(-1); + } // sort for(j=0;j<(*idtable).length;j++){ @@ -658,6 +1154,7 @@ int parse_labels(Char_Array str_labels, Labels* labels){ int j; int mode; int comment=0; + int ret; // allocate memory init_Labels(labels,EQUATION_SIZE); @@ -686,18 +1183,30 @@ int parse_labels(Char_Array str_labels, Labels* labels){ buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: labels entry (%d): mismatched '\"'\n",j); + exit(-1); + } break; case ':': // write if(mode==PP_INDEX_MODE){ sscanf(buffer,"%d",&index); + ret=read_positive_int(buffer,&index); + if(ret<0){ + fprintf(stderr,"syntax error: labels entry (%d): index must be a non-negative integer, got '%s'\n",j,buffer); + exit(-1); + } + } + else{ + fprintf(stderr,"syntax error: labels entry (%d): misplaced ':'\n",j); + exit(-1); } break; // characters to ignore case ' ':break; - case '&':break; case '\n':break; case ',':break; @@ -726,6 +1235,7 @@ int parse_init_cd(Char_Array init_cd, RCC* init, RCC_mpfr* init_mpfr, int mpfr_f int i,j; int comment_mode=0; int dcount=0; + int ret; *buffer_ptr='\0'; // loop over the input @@ -741,7 +1251,11 @@ int parse_init_cd(Char_Array init_cd, RCC* init, RCC_mpfr* init_mpfr, int mpfr_f case ',': // write init if(mpfr_flag==0){ - sscanf(buffer,"%Lf",(*init).values+intlist_find_err((*init).indices,(*init).length,index)); + ret=read_long_double(buffer,(*init).values+intlist_find_err((*init).indices,(*init).length,index)); + if(ret<0){ + fprintf(stderr,"syntax error: initial_condition entry (%d): failed to extract long double from '%s'\n",j,buffer); + exit(-1); + } } else{ mpfr_strtofr((*init_mpfr).values[intlist_find_err((*init_mpfr).indices,(*init_mpfr).length,index)], buffer, &buffer_ptr, 10, MPFR_RNDN); @@ -755,7 +1269,11 @@ int parse_init_cd(Char_Array init_cd, RCC* init, RCC_mpfr* init_mpfr, int mpfr_f // separator case ':': // write index - sscanf(buffer,"%d",&i); + ret=read_int(buffer,&i); + if(ret<0){ + fprintf(stderr,"syntax error: initial_condition entry (%d): index must be an integer, got '%s'\n",j,buffer); + exit(-1); + } if(i<0){ index=i-dcount*DOFFSET; } @@ -772,7 +1290,6 @@ int parse_init_cd(Char_Array init_cd, RCC* init, RCC_mpfr* init_mpfr, int mpfr_f // characters to ignore case ' ':break; - case '&':break; case '\n':break; // comments @@ -790,7 +1307,11 @@ int parse_init_cd(Char_Array init_cd, RCC* init, RCC_mpfr* init_mpfr, int mpfr_f // write init if(mpfr_flag==0){ - sscanf(buffer,"%Lf",(*init).values+intlist_find_err((*init).indices,(*init).length,index)); + ret=read_long_double(buffer,(*init).values+intlist_find_err((*init).indices,(*init).length,index)); + if(ret<0){ + fprintf(stderr,"syntax error: initial_condition entry (%d): failed to extract long double from '%s'\n",j,buffer); + exit(-1); + } } else{ mpfr_strtofr((*init_mpfr).values[intlist_find_err((*init_mpfr).indices,(*init_mpfr).length,index)], buffer, &buffer_ptr, 10, MPFR_RNDN); diff --git a/src/parse_file.h b/src/parse_file.h index 0430763..e22393e 100644 --- a/src/parse_file.h +++ b/src/parse_file.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -23,26 +23,43 @@ Parse the input file #include "types.h" +// read a positive integer from a string +int read_positive_int(char* str, int* out); +// read an integer from a string +int read_int(char* str, int* out); +// read an long int from a string +int read_long_int(char* str, long int* out); +// read a long double +int read_long_double(char* str, long double* out); + + // parse fields list int parse_input_fields(Char_Array str_fields, Fields_Table* fields); -// parse symbols list -int parse_input_symbols(Char_Array str_symbols, Fields_Table* fields); +// parse virtual_fields list +int parse_input_virtual_fields(Char_Array str_virtual_fields, Fields_Table* fields, Variables variables); // parse groups of independent fields -int parse_input_groups(Char_Array str_groups, Groups* groups); +int parse_input_groups(Char_Array str_groups, Groups* groups, Polynomial_Matrix propagator, Fields_Table fields); +// check that the members of groups are independent (assuming the virtual_fields and propagator were already parsed) +int check_groups(Groups groups, Polynomial_Matrix propagator, Fields_Table fields); +// list of fields involved in a list of virtual_fields +int fields_in_virtual_field_list(Int_Array indices, Fields_Table fields, Int_Array* output); + +// parse variables list +int parse_input_variables(Char_Array str_variables, Variables* variables); // parse identities between fields -int parse_input_identities(Char_Array str_identities, Fields_Table* fields); +int parse_input_identities(Char_Array str_identities, Fields_Table* fields, Variables variables); // parse propagator int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propagator, Fields_Table fields); // parse input polynomial -int parse_input_polynomial(Char_Array str_polynomial, Polynomial* output, Fields_Table fields); +int parse_input_polynomial(Char_Array str_polynomial, Polynomial* output, Fields_Table fields, Variables variables); // parse id table -int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table fields); +int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table fields, Variables variables); // parse a list of labels int parse_labels(Char_Array str_labels, Labels* labels); diff --git a/src/polynomial.c b/src/polynomial.c index d082b60..fae0c08 100644 --- a/src/polynomial.c +++ b/src/polynomial.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -27,6 +27,7 @@ limitations under the License. #include "array.h" #include "number.h" #include "fields.h" +#include "parse_file.h" // allocate memory @@ -368,7 +369,7 @@ int polynomial_prod_chain_nosimplify(Polynomial input, Polynomial* inout, Fields Int_Array out_monomial; Int_Array out_factor; Number out_num; - // save length of inout (which changes during the loop + // save length of inout (which changes during the loop) int inout_length=(*inout).length; // first position in input which can multiply a term of inout without vanishing int firstpos; @@ -630,8 +631,8 @@ int remove_unmatched_plusminus(Polynomial* polynomial, Fields_Table fields){ match_internals--; } } - // don't remove a term containing symbols - else if(type==FIELD_SYMBOL){ + // don't remove a term containing virtual_field + else if(type==FIELD_VIRTUAL){ match_internals=0; break; } @@ -1093,7 +1094,7 @@ int polynomial_print(Polynomial polynomial){ Char_Array buffer; init_Char_Array(&buffer, STR_SIZE); polynomial_sprint(polynomial, &buffer); - printf("%s",buffer.str); + printf("%s",char_array_to_str_noinit(&buffer)); free_Char_Array(buffer); return(0); } @@ -1104,7 +1105,7 @@ int polynomial_print(Polynomial polynomial){ #define PP_MONOMIAL_MODE 2 #define PP_FACTOR_MODE 3 #define PP_NUMBER_MODE 4 -int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ +int Char_Array_to_Polynomial(Char_Array str_polynomial, Polynomial* output){ // buffer char* buffer=calloc(str_polynomial.length+1,sizeof(char)); char* buffer_ptr=buffer; @@ -1115,6 +1116,7 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ int comment=0; int i,j; int parenthesis_count=0; + int ret; // allocate memory init_Polynomial(output,POLY_SIZE); @@ -1174,6 +1176,10 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ init_Int_Array(&factor, MONOMIAL_SIZE); num=number_one(); } + else{ + fprintf(stderr,"syntax error: misplaced '+' in polynomial\n"); + exit(-1); + } break; // enter monomial or factor mode @@ -1181,6 +1187,10 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ if(mode==PP_NULL_MODE){ mode=PP_BRACKET_MODE; } + else{ + fprintf(stderr,"syntax error: misplaced '[' in polynomial\n"); + exit(-1); + } break; // factor mode case 'l': @@ -1189,6 +1199,10 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: misplaced 'l' in polynomial\n"); + exit(-1); + } break; // monomial mode case 'f': @@ -1197,16 +1211,30 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ buffer_ptr=buffer; *buffer_ptr='\0'; } + else{ + fprintf(stderr,"syntax error: misplaced 'j' in polynomial\n"); + exit(-1); + } break; // read monomial or factor case ']': sscanf(buffer,"%d",&i); + ret=read_int(buffer,&i); + if(ret<0){ + fprintf(stderr,"syntax error: in polynomial, expected integer field or factor index, got '%s'\n",buffer); + exit(-1); + } + if(mode==PP_FACTOR_MODE){ int_array_append(i,&factor); } else if(mode==PP_MONOMIAL_MODE){ int_array_append(i,&monomial); } + else{ + fprintf(stderr,"syntax error: mismatched ']' in polynomial\n"); + exit(-1); + } // switch back to null mode mode=PP_NULL_MODE; break; @@ -1224,6 +1252,10 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ parenthesis_count++; buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); } + else{ + fprintf(stderr,"syntax error: misplaced '(' in polynomial\n"); + exit(-1); + } break; case ')': if(mode==PP_NUMBER_MODE){ @@ -1240,11 +1272,14 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); } } + else{ + fprintf(stderr,"syntax error: mismatched ')' in polynomial\n"); + exit(-1); + } break; // characters to ignore case ' ':break; - case '&':break; case '\n':break; // comments @@ -1257,6 +1292,10 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ // write to buffer buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); } + else{ + fprintf(stderr,"syntax error: in polynomial, unrecognized character '%c'\n",str_polynomial.str[j]); + exit(-1); + } break; } } @@ -1270,7 +1309,7 @@ int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output){ } // with str input -int str_to_Polynomial(char* str_polynomial,Polynomial* output){ +int str_to_Polynomial(char* str_polynomial, Polynomial* output){ Char_Array buffer; str_to_char_array(str_polynomial, &buffer); Char_Array_to_Polynomial(buffer, output); @@ -1278,6 +1317,15 @@ int str_to_Polynomial(char* str_polynomial,Polynomial* output){ return(0); } +// check whether the polynomial is a constant +int polynomial_is_number(Polynomial poly){ + if(poly.length==0 || (poly.length==1 && poly.monomials[0].length==0 && poly.factors[0].length==0)){ + return(1); + } + else{ + return(0); + } +} // -------------------- Polynomial_Matrix --------------------- @@ -1307,3 +1355,16 @@ int free_Polynomial_Matrix(Polynomial_Matrix matrix){ free(matrix.indices); return(0); } + +// check whether the entries are numbers +int polynomial_matrix_is_numeric(Polynomial_Matrix matrix){ + int i,j; + for(i=0;i<matrix.length;i++){ + for(j=0;j<matrix.length;j++){ + if(polynomial_is_number(matrix.matrix[i][j])==0){ + return(0); + } + } + } + return(1); +} diff --git a/src/polynomial.h b/src/polynomial.h index 6aff76d..f3488f5 100644 --- a/src/polynomial.h +++ b/src/polynomial.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -124,12 +124,18 @@ int replace_factors(Grouped_Polynomial equations, Polynomial* polynomial); int polynomial_sprint(Polynomial polynomial, Char_Array* output); int polynomial_print(Polynomial polynomial); // read a polynomial -int Char_Array_to_Polynomial(Char_Array str_polynomial,Polynomial* output); -int str_to_Polynomial(char* str_polynomial,Polynomial* output); +int Char_Array_to_Polynomial(Char_Array str_polynomial, Polynomial* output); +int str_to_Polynomial(char* str_polynomial, Polynomial* output); + +// check whether the polynomial is a constant +int polynomial_is_number(Polynomial poly); //------------------------ Polynomial_Matrix -------------------------- // init int init_Polynomial_Matrix(Polynomial_Matrix* matrix, int length); int free_Polynomial_Matrix(Polynomial_Matrix matrix); +// check whether the entries are numbers +int polynomial_matrix_is_numeric(Polynomial_Matrix matrix); + #endif diff --git a/src/rational.h b/src/rational.h index 5beab8d..aea0625 100644 --- a/src/rational.h +++ b/src/rational.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/rational_float.c b/src/rational_float.c index d6a6a4c..2538d41 100644 --- a/src/rational_float.c +++ b/src/rational_float.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/rational_float.h b/src/rational_float.h index 02c4a22..ef5541b 100644 --- a/src/rational_float.h +++ b/src/rational_float.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. diff --git a/src/rational_int.c b/src/rational_int.c index 7aab561..f3e5475 100644 --- a/src/rational_int.c +++ b/src/rational_int.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -25,6 +25,7 @@ limitations under the License. #include <mpfr.h> #include "istring.h" #include "array.h" +#include "parse_file.h" Q quot(long int p, long int q){ Q ret; @@ -171,13 +172,18 @@ int str_to_Q(char* str, Q* num){ int mode; char* buffer=calloc(str_len(str)+1,sizeof(char)); char* buffer_ptr=buffer; + int ret; *num=quot(0,1); mode=PP_NUMERATOR_MODE; for(ptr=str;*ptr!='\0';ptr++){ if(*ptr=='/'){ - sscanf(buffer,"%ld",&((*num).numerator)); + ret=read_long_int(buffer,&((*num).numerator)); + if(ret<0){ + fprintf(stderr,"syntax error: numerator should be an integer, got '%s' in '%s'\n",buffer,str); + exit(-1); + } buffer_ptr=buffer; *buffer_ptr='\0'; mode=PP_DENOMINATOR_MODE; @@ -189,10 +195,18 @@ int str_to_Q(char* str, Q* num){ // last step if(mode==PP_NUMERATOR_MODE){ - sscanf(buffer,"%ld",&((*num).numerator)); + ret=read_long_int(buffer,&((*num).numerator)); + if(ret<0){ + fprintf(stderr,"syntax error: numerator should be an integer, got '%s' in '%s'\n",buffer,str); + exit(-1); + } } else if(mode==PP_DENOMINATOR_MODE){ - sscanf(buffer,"%ld",&((*num).denominator)); + ret=read_long_int(buffer,&((*num).denominator)); + if(ret<0){ + fprintf(stderr,"syntax error: numerator should be an integer, got '%s' in '%s'\n",buffer,str); + exit(-1); + } } free(buffer); diff --git a/src/rational_int.h b/src/rational_int.h index a4dd000..1aba15d 100644 --- a/src/rational_int.h +++ b/src/rational_int.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -49,6 +49,13 @@ int RCC_cpy(RCC input,RCC* output){ } return(0); } +int RCC_cpy_noinit(RCC input,RCC* output){ + int i; + for(i=0;i<input.length;i++){ + RCC_set_elem(input.values[i], input.indices[i], output, i); + } + return(0); +} // concatenate rccs int RCC_concat(RCC rccs1, RCC rccs2, RCC* output){ @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -28,6 +28,7 @@ int free_RCC(RCC rccs); int RCC_set_elem(long double value, int index, RCC* rcc, int pos); // copy int RCC_cpy(RCC input,RCC* output); +int RCC_cpy_noinit(RCC input,RCC* output); // concatenate 2 rccs int RCC_concat(RCC rccs1, RCC rccs2, RCC* output); // append an rcc to another diff --git a/src/rcc_mpfr.c b/src/rcc_mpfr.c index 8a362e3..7703b1e 100644 --- a/src/rcc_mpfr.c +++ b/src/rcc_mpfr.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -65,6 +65,13 @@ int RCC_mpfr_cpy(RCC_mpfr input,RCC_mpfr* output){ } return(0); } +int RCC_mpfr_cpy_noinit(RCC_mpfr input,RCC_mpfr* output){ + int i; + for(i=0;i<input.length;i++){ + RCC_mpfr_set_elem(input.values[i], input.indices[i], output, i); + } + return(0); +} // concatenate rcc_mpfr int RCC_mpfr_concat(RCC_mpfr rcc_mpfr1, RCC_mpfr rcc_mpfr2, RCC_mpfr* output){ diff --git a/src/rcc_mpfr.h b/src/rcc_mpfr.h index 18ebed3..940fbb1 100644 --- a/src/rcc_mpfr.h +++ b/src/rcc_mpfr.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -32,6 +32,7 @@ int free_RCC_mpfr(RCC_mpfr rcc_mpfr); int RCC_mpfr_set_elem(mpfr_t value, int index, RCC_mpfr* rcc_mpfr, int pos); // copy int RCC_mpfr_cpy(RCC_mpfr input,RCC_mpfr* output); +int RCC_mpfr_cpy_noinit(RCC_mpfr input,RCC_mpfr* output); // concatenate 2 rcc_mpfr_mpfr int RCC_mpfr_concat(RCC_mpfr rcc_mpfr_mpfr1, RCC_mpfr rcc_mpfr_mpfr2, RCC_mpfr* output); // append an rcc_mpfr to another diff --git a/src/symbolic_parser.c b/src/symbolic_parser.c new file mode 100644 index 0000000..08cae88 --- /dev/null +++ b/src/symbolic_parser.c @@ -0,0 +1,330 @@ +/* +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 "symbolic_parser.h" +#include <stdlib.h> +#include <stdio.h> +#include "tree.h" +#include "definitions.cpp" +#include "array.h" +#include "istring.h" +#include "fields.h" +#include "polynomial.h" + +#define SP_NULL_MODE 0 +#define SP_FUNCTION_MODE 1 + +// parse a symbolic expression from a char_array +int parse_symbolic_expression(Char_Array str, Fields_Table fields, Variables variables, Polynomial* polynomial){ + Tree symbol_tree; + char_array_to_symbol_tree(str, &symbol_tree); + resolve_symbol_tree(symbol_tree, fields, variables, polynomial); + free_Tree(symbol_tree); + return(0); +} +// from char* +int parse_symbolic_expression_str(char* str, Fields_Table fields, Variables variables, Polynomial* polynomial){ + Char_Array char_array; + str_to_char_array(str,&char_array); + parse_symbolic_expression(char_array, fields, variables, polynomial); + free_Char_Array(char_array); + return(0); +} + +// compute the symbol tree from a string +int char_array_to_symbol_tree(Char_Array str, Tree* symbol_tree){ + // buffer + char* buffer=calloc(str.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Tree child; + int match; + Char_Array nodestr; + Char_Array label; + Char_Array str_clean; + int mode; + int comment=0; + int j; + int gotanode=0; + + // allocate memory + init_Tree(symbol_tree,SYMBOL_TREE_SIZE, SYMBOL_TREE_LABEL_SIZE); + + // remove comments, ' ' and '\n' + init_Char_Array(&str_clean,str.length); + for(j=0;j<str.length;j++){ + if(comment==1){ + if(str.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str.str[j]){ + case ' ':break; + case '\n':break; + // comments + case '#': + comment=1; + break; + default: + char_array_append(str.str[j],&str_clean); + break; + } + } + } + + // if the string contains no '<', then trivial tree + for(j=0;j<str_clean.length;j++){ + if(str_clean.str[j]=='<'){ + break; + } + } + // no '<': trivial tree + if(j==str_clean.length){ + tree_set_label(str_clean, symbol_tree); + free(buffer); + free_Char_Array(str_clean); + return(0); + } + + *buffer_ptr='\0'; + // loop over the input string + // start in null mode + mode=SP_NULL_MODE; + for(j=0;j<str_clean.length;j++){ + switch(str_clean.str[j]){ + // new node + case '<': + // find matching bracket + match=matching_bracket(str_clean,j); + // check whether it exists + if(match<0){ + fprintf(stderr,"syntax error: unmatched brackets in %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + // extract substring until bracket + char_array_substring(str_clean,j+1,match-1,&nodestr); + + // check whether node is trivial + if(j==0 && match==str_clean.length-1){ + free_Tree(*symbol_tree); + char_array_to_symbol_tree(nodestr, symbol_tree); + free_Char_Array(nodestr); + j=match; + break; + } + + // parse subexpression + char_array_to_symbol_tree(nodestr, &child); + free_Char_Array(nodestr); + // add child to tree + tree_append_child_noinit(child, symbol_tree); + // boolean indicating a node has been found + gotanode=1; + // set next position after the node + j=match; + + // if function mode, then check that the match is at the end of the node + if(mode==SP_FUNCTION_MODE){ + if(match<str_clean.length-1){ + fprintf(stderr,"syntax error: functions must occupy an entire node (e.g. <%%exp<...>>), got %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + else{ + // set label + str_to_char_array(buffer,&label); + tree_set_label(label,symbol_tree); + free_Char_Array(label); + } + } + break; + + // function + case '%': + if(j>0){ + fprintf(stderr,"syntax error: functions must occupy an entire node (e.g. <%%exp<...>>), got %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + mode=SP_FUNCTION_MODE; + break; + + // product + case '*': + if(gotanode==0){ + fprintf(stderr,"syntax error: '*' is not preceded by a node in %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + if(j>=str_clean.length-1){ + fprintf(stderr,"syntax error: '*' cannot be at the end of an expression, got %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + // set label + init_Char_Array(&label,1); + char_array_append('*',&label); + tree_set_label(label,symbol_tree); + free_Char_Array(label); + // next child + char_array_substring(str_clean,j+1,str_clean.length-1,&nodestr); + // parse subexpression + char_array_to_symbol_tree(nodestr, &child); + free_Char_Array(nodestr); + // append next child + tree_append_child_noinit(child, symbol_tree); + + // make it stop + j=str_clean.length-1; + break; + + // sum + case '+': + if(gotanode==0){ + fprintf(stderr,"syntax error: '+' is not preceded by a node in %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + if(j>=str_clean.length-1){ + fprintf(stderr,"syntax error: '+' cannot be at the end of an expression, got %s\n",char_array_to_str_noinit(&str)); + exit(-1); + } + // set label + init_Char_Array(&label,1); + char_array_append('+',&label); + tree_set_label(label,symbol_tree); + free_Char_Array(label); + // next child + char_array_substring(str_clean,j+1,str_clean.length-1,&nodestr); + // parse subexpression + char_array_to_symbol_tree(nodestr, &child); + free_Char_Array(nodestr); + // append next child + tree_append_child_noinit(child, symbol_tree); + + // make it stop + j=str_clean.length-1; + break; + + default: + if(mode!=SP_NULL_MODE){ + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,str_clean.str[j]); + } + break; + } + } + + free_Char_Array(str_clean); + free(buffer); + return(0); +} +// from char* +int str_to_symbol_tree(char* str, Tree* symbol_tree){ + Char_Array char_array; + str_to_char_array(str,&char_array); + char_array_to_symbol_tree(char_array,symbol_tree); + free_Char_Array(char_array); + return(0); +} + + +// find matching '<' and '>' +int matching_bracket(Char_Array str, int start){ + int bracket_count=0; + int i; + for(i=start;i<str.length;i++){ + if(str.str[i]=='<'){ + bracket_count++; + } + else if(str.str[i]=='>'){ + bracket_count--; + if(bracket_count==0){ + return(i); + } + } + } + // if the function has not returned, then no matching bracket + return(-1); +} + + +// resolve a symbol tree to its corresponding polynomial +int resolve_symbol_tree(Tree symbol_tree, Fields_Table fields, Variables variables, Polynomial* output){ + Polynomial poly; + Tree variable_tree; + + // trivial tree + if(symbol_tree.length==0){ + // variable + if(symbol_tree.root_label.length>0 && symbol_tree.root_label.str[0]=='$'){ + variables_find_var(symbol_tree.root_label, variables, &variable_tree); + resolve_symbol_tree(variable_tree, fields, variables, output); + free_Tree(variable_tree); + } + //polynomial + else{ + Char_Array_to_Polynomial(symbol_tree.root_label, output); + } + } + + // exp + else if (char_array_cmp_str(symbol_tree.root_label,"exp")==1){ + if(symbol_tree.length!=1){ + fprintf(stderr,"syntax error: exp must have 1 argument\n"); + exit(-1); + } + resolve_symbol_tree(symbol_tree.children[0], fields, variables, &poly); + polynomial_exponential(poly, output, fields); + free_Polynomial(poly); + } + + // log + else if (char_array_cmp_str(symbol_tree.root_label,"log_1")==1){ + if(symbol_tree.length!=1){ + fprintf(stderr,"syntax error: log_1 must have 1 argument\n"); + exit(-1); + } + resolve_symbol_tree(symbol_tree.children[0], fields, variables, &poly); + polynomial_logarithm(poly, output, fields); + free_Polynomial(poly); + } + + // product + else if (char_array_cmp_str(symbol_tree.root_label,"*")==1){ + if(symbol_tree.length!=2){ + fprintf(stderr,"syntax error: '*' must have 2 arguments\n"); + exit(-1); + } + resolve_symbol_tree(symbol_tree.children[0], fields, variables, output); + resolve_symbol_tree(symbol_tree.children[1], fields, variables, &poly); + polynomial_prod_chain(poly, output, fields); + free_Polynomial(poly); + } + + // sum + else if (char_array_cmp_str(symbol_tree.root_label,"+")==1){ + if(symbol_tree.length!=2){ + fprintf(stderr,"syntax error: '+' must have 2 arguments\n"); + exit(-1); + } + resolve_symbol_tree(symbol_tree.children[0], fields, variables, output); + resolve_symbol_tree(symbol_tree.children[1], fields, variables, &poly); + polynomial_add_chain_noinit(poly, output, fields); + } + + else{ + fprintf(stderr,"syntax error: unrecognized operation '%s'\n",char_array_to_str_noinit(&(symbol_tree.root_label))); + exit(-1); + } + + return(0); +} diff --git a/src/symbolic_parser.h b/src/symbolic_parser.h new file mode 100644 index 0000000..e91c902 --- /dev/null +++ b/src/symbolic_parser.h @@ -0,0 +1,42 @@ +/* +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. +*/ + +/* + parse symbolic expressions +*/ + +#ifndef SYMBOLIC_PARSER_H +#define SYMBOLIC_PARSER_H + +#include "types.h" + +// parse a symbolic expression from a char_array +int parse_symbolic_expression(Char_Array str, Fields_Table fields, Variables variables, Polynomial* polynomial); +// from char* +int parse_symbolic_expression_str(char* str, Fields_Table fields, Variables variables, Polynomial* polynomial); + +// compute the symbol tree from a string +int char_array_to_symbol_tree(Char_Array str, Tree* symbol_tree); +// from char* +int str_to_symbol_tree(char* str, Tree* symbol_tree); + +// find matching '<' and '>' +int matching_bracket(Char_Array str, int start); + +// resolve a symbol tree to its corresponding polynomial +int resolve_symbol_tree(Tree symbol_tree, Fields_Table fields, Variables variables, Polynomial* output); + +#endif diff --git a/src/tools.c b/src/tools.c index 2b7e85d..5912819 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -140,3 +140,13 @@ int min(int x1, int x2){ return(x2); } } + +// check whether a divides b +int is_factor(int a, int b){ + if(b-a*(b/a)==0){ + return(1); + } + else{ + return(0); + } +} diff --git a/src/tools.h b/src/tools.h index e5f319f..8f29cf8 100644 --- a/src/tools.h +++ b/src/tools.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -46,4 +46,7 @@ int intlist_find_err(int* list, int size, int x); int max(int x1, int x2); int min(int x1, int x2); +// check whether a divides b +int is_factor(int a, int b); + #endif diff --git a/src/tree.c b/src/tree.c new file mode 100644 index 0000000..0edf558 --- /dev/null +++ b/src/tree.c @@ -0,0 +1,117 @@ +/* +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 "tree.h" +#include <stdlib.h> +#include <stdio.h> +#include "array.h" + +// init +int init_Tree(Tree* tree, int memory_children, int memory_label){ + init_Char_Array(&(tree->root_label),memory_label); + (*tree).children=calloc(memory_children,sizeof(Tree)); + (*tree).memory=memory_children; + (*tree).length=0; + return(0); +} +int free_Tree(Tree tree){ + int i; + free_Char_Array(tree.root_label); + for(i=0;i<tree.length;i++){ + free_Tree(tree.children[i]); + } + free(tree.children); + return(0); +} + +// copy +int tree_cpy(Tree input, Tree* output){ + init_Tree(output,input.length, input.root_label.length); + tree_cpy_noinit(input,output); + return(0); +} +int tree_cpy_noinit(Tree input, Tree* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a tree of length %d to another with memory %d\n",input.length, (*output).memory); + exit(-1); + } + char_array_cpy_noinit(input.root_label,&(output->root_label)); + for(i=0;i<input.length;i++){ + tree_cpy(input.children[i],(*output).children+i); + } + + (*output).length=input.length; + return(0); +} + +// resize memory +int tree_resize(Tree* tree, int newsize){ + Tree new_tree; + init_Tree(&new_tree,newsize,tree->root_label.memory); + tree_cpy_noinit(*tree,&new_tree); + free_Tree(*tree); + *tree=new_tree; + return(0); +} + +// set label +int tree_set_label(Char_Array label, Tree* tree){ + if(label.length > tree->root_label.memory){ + char_array_resize(&(tree->root_label),label.length); + } + char_array_cpy_noinit(label,&(tree->root_label)); + return(0); +} + +// add a child to a tree +int tree_append_child(Tree child, Tree* output){ + if((*output).length>=(*output).memory){ + tree_resize(output,2*(*output).memory+1); + } + tree_cpy(child,(*output).children+(*output).length); + (*output).length++; + return(0); +} +// add a child to a tree without allocating memory for the new child +int tree_append_child_noinit(Tree child, Tree* output){ + if((*output).length>=(*output).memory){ + tree_resize(output,2*(*output).memory+1); + } + (*output).children[(*output).length]=child; + (*output).length++; + return(0); +} + +// concatenate the children of two trees +int tree_concat_children(Tree input, Tree* output){ + int i; + for(i=0;i<input.length;i++){ + tree_append_child(input.children[i],output); + } + return(0); +} +// noinit +int tree_concat_children_noinit(Tree input, Tree* output){ + int i; + for(i=0;i<input.length;i++){ + tree_append_child_noinit(input.children[i],output); + } + // free input array + free(input.children); + return(0); +} + diff --git a/src/tree.h b/src/tree.h new file mode 100644 index 0000000..60b222c --- /dev/null +++ b/src/tree.h @@ -0,0 +1,48 @@ +/* +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. +*/ + +/* Trees */ + +#ifndef TREE_H +#define TREE_H + +#include "types.h" + +int init_Tree(Tree* tree, int memory_children, int memory_label); +int free_Tree(Tree tree); + +// copy +int tree_cpy(Tree input, Tree* output); +int tree_cpy_noinit(Tree input, Tree* output); + +// resize memory +int tree_resize(Tree* tree, int newsize); + +// set label +int tree_set_label(Char_Array label, Tree* tree); + +// add a child to a tree +int tree_append_child(Tree tree, Tree* output); +// add a child to a tree without allocating memory for the new child +int tree_append_child_noinit(Tree tree, Tree* output); + +// concatenate the children of two trees +int tree_concat_children(Tree input, Tree* output); +// noinit +int tree_concat_children_noinit(Tree input, Tree* output); + +#endif + diff --git a/src/types.h b/src/types.h index d30840e..00a34ac 100644 --- a/src/types.h +++ b/src/types.h @@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -71,6 +71,15 @@ typedef struct Str_Array{ int memory; } Str_Array; +// tree +typedef struct Tree Tree; +struct Tree{ + Char_Array root_label; + Tree* children; + int length; + int memory; +}; + // polynomial typedef struct Polynomial{ Int_Array* monomials; @@ -133,13 +142,21 @@ typedef struct Identities{ int memory; } Identities; -// symbolic expressions -typedef struct Symbols{ +// virtual_fields +typedef struct Virtual_fields{ int* indices; Polynomial* expr; int length; int memory; -} Symbols; +} Virtual_fields; + +// variables used in symbolic expressions +typedef struct Variables{ + Char_Array* var_names; + Tree* symbol_trees; + int length; + int memory; +} Variables; // groups of independent fields typedef struct Groups{ @@ -159,10 +176,10 @@ typedef struct Fields_Table{ // identities between fields Identities ids; // symbolic expressions (commuting) - Symbols symbols; - // list of anti-commuting variables (fields or symbols) + Virtual_fields virtual_fields; + // list of anti-commuting variables Int_Array fermions; - // list of non-commuting variables (fields or symbols) + // list of non-commuting variables Int_Array noncommuting; } Fields_Table; @@ -187,6 +204,8 @@ typedef struct Id_Table{ typedef struct Meankondo_Options{ int threads; int chain; + int print_progress; + int group_poly; } Meankondo_Options; typedef struct Numkondo_Options{ @@ -203,6 +222,7 @@ typedef struct Meantools_Options{ Int_Array deriv_vars; Char_Array eval_rccstring; int chain; + Char_Array namespace; mpfr_prec_t mpfr_prec; mpfr_exp_t mpfr_emax; } Meantools_Options; |