/* 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 "parse_file.h" #include #include #include #include "array.h" #include "fields.h" #include "rational.h" #include "number.h" #include "polynomial.h" #include "rcc.h" #include "rcc_mpfr.h" #include "definitions.cpp" #include "istring.h" #include "tools.h" #include "idtable.h" #include "tree.h" #include "symbolic_parser.h" // parsing modes #define PP_NULL_MODE 0 // when reading a factor #define PP_FACTOR_MODE 1 // reading a monomial #define PP_MONOMIAL_MODE 2 // reading a numerator and denominator #define PP_NUMBER_MODE 3 // types of fields #define PP_FIELD_MODE 6 #define PP_PARAMETER_MODE 7 #define PP_EXTERNAL_MODE 8 #define PP_INTERNAL_MODE 9 #define PP_FERMIONS_MODE 10 #define PP_NONCOMMUTING_MODE 11 // indices #define PP_INDEX_MODE 12 // factors or monomials #define PP_BRACKET_MODE 13 // labels #define PP_LABEL_MODE 14 // polynomial #define PP_POLYNOMIAL_MODE 15 // group #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 char* buffer=calloc(str_fields.length+1,sizeof(char)); char* buffer_ptr=buffer; int i,j; int mode; int comment=0; int res; int expect_colon=0; // allocate memory init_Fields_Table(fields); // loop over input mode=PP_NULL_MODE; for(j=0;jparameter)>=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)); } 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': // 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; } break; // ignore spaces case ' ':break; // comment case '#': comment=1; break; default: 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 virtual_fields list // write result to fields int parse_input_virtual_fields(Char_Array str_virtual_fields, Fields_Table* fields, Variables variables){ // buffer 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;jlength;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){ 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;ilength;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; break; default: 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=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'){ 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); } // parse identities between fields // write result to 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; Int_Array monomial; Polynomial polynomial; int i,j; int sign; int tmp; int mode; int comment=0; int ret; init_Int_Array(&monomial, MONOMIAL_SIZE); // loop over input mode=PP_NULL_MODE; for(j=0;j=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; break; default: buffer_ptr=str_addchar(buffer_ptr,str_propagator.str[j]); break; } } } // last step if(mode==PP_POLYNOMIAL_MODE){ 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); } // parse input polynomial 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); } // parse id table // fields argument for sorting 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; int index; Polynomial polynomial; int j; int mode; int comment=0; int ret; // allocate memory init_Id_Table(idtable,EQUATION_SIZE); // loop over input mode=PP_INDEX_MODE; for(j=0;j-DOFFSET){ (*init).values[i]=1.; } else{ (*init).values[i]=0.; } } return(0); } // set indices and length of init for RCC_mpfr int prepare_init_mpfr(int* indices, int length, RCC_mpfr* init){ int i; init_RCC_mpfr(init, length); for(i=0;i-DOFFSET){ mpfr_set_ui((*init).values[i],1,MPFR_RNDN); } else{ mpfr_set_zero((*init).values[i],1); } } return(0); }