diff options
Diffstat (limited to 'src')
49 files changed, 11482 insertions, 0 deletions
diff --git a/src/array.c b/src/array.c new file mode 100644 index 0000000..11d14f7 --- /dev/null +++ b/src/array.c @@ -0,0 +1,628 @@ +/* +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 "array.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include "istring.h" +#include "definitions.cpp" + +// init +int init_Int_Array(Int_Array* array, int memory){ + (*array).values=calloc(memory,sizeof(int)); + (*array).memory=memory; + (*array).length=0; + return(0); +} +int free_Int_Array(Int_Array array){ + free(array.values); + return(0); +} + +// copy +int int_array_cpy(Int_Array input, Int_Array* output){ + init_Int_Array(output,input.length); + int_array_cpy_noinit(input,output); + return(0); +} +int int_array_cpy_noinit(Int_Array input, Int_Array* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy an array of length %d to another with memory %d\n",input.length, (*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + (*output).values[i]=input.values[i]; + } + (*output).length=input.length; + return(0); +} + +// resize memory +int int_array_resize(Int_Array* array, int newsize){ + Int_Array new_array; + init_Int_Array(&new_array, newsize); + int_array_cpy_noinit(*array,&new_array); + free_Int_Array(*array); + *array=new_array; + return(0); +} + +// add a value +int int_array_append(int val, Int_Array* output){ + if((*output).length>=(*output).memory){ + int_array_resize(output,2*(*output).memory+1); + } + (*output).values[(*output).length]=val; + (*output).length++; + return(0); +} + +// concatenate +int int_array_concat(Int_Array input, Int_Array* output){ + int i; + int offset=(*output).length; + if((*output).length+input.length>(*output).memory){ + // make it longer than needed by (*output).length (for speed) + int_array_resize(output,2*(*output).length+input.length); + } + for(i=0;i<input.length;i++){ + (*output).values[offset+i]=input.values[i]; + } + (*output).length=offset+input.length; + return(0); +} + +// find (does not assume the array is sorted) +int int_array_find(int val, Int_Array array){ + int i; + for(i=0;i<array.length;i++){ + if(array.values[i]==val){ + return(i); + } + } + return(-1); +} +int int_array_find_err(int val, Int_Array array){ + int i; + for(i=0;i<array.length;i++){ + if(array.values[i]==val){ + return(i); + } + } + fprintf(stderr,"error: value %d not found in array\n",val); + exit(-1); +} + +// sort +int int_array_sort(Int_Array array, int begin, int end){ + int i; + int tmp; + int index; + // the pivot: middle of the array + int pivot=(begin+end)/2; + // if the array is non trivial + if(begin<end){ + // send pivot to the end + tmp=array.values[pivot]; + array.values[pivot]=array.values[end]; + array.values[end]=tmp; + + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + if(array.values[i]<array.values[end]){ + // if smaller, exchange with reference index + tmp=array.values[index]; + array.values[index]=array.values[i]; + array.values[i]=tmp; + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + tmp=array.values[end]; + array.values[end]=array.values[index]; + array.values[index]=tmp; + + // recurse + int_array_sort(array, begin, index-1); + int_array_sort(array, index+1, end); + } + return(0); +} + +// compare Int_Array's +int int_array_cmp(Int_Array array1, Int_Array array2){ + int i; + + // compare lengths + if(array1.length<array2.length){ + return(-1); + } + if(array1.length>array2.length){ + return(1); + } + + // compare terms + for(i=0;i<array1.length;i++){ + if(array1.values[i]<array2.values[i]){ + return(-1); + } + if(array1.values[i]>array2.values[i]){ + return(1); + } + } + + // if equal + return(0); +} + +// check whether an array is a sub-array of another +// allows for the elements to be separated by others, but the order must be respected +int int_array_is_subarray_ordered(Int_Array input, Int_Array test_array){ + int i; + int matches=0; + + for(i=0;i<test_array.length && matches<input.length;i++){ + if(input.values[matches]==test_array.values[i]){ + matches++; + } + } + if(matches==input.length){ + return(1); + } + else{ + return(0); + } +} + + +// print array +int int_array_print(Int_Array array){ + int i; + printf("("); + for(i=0;i<array.length-1;i++){ + printf("%d,",array.values[i]); + } + printf("%d)",array.values[array.length-1]); + return(0); +} + +// read array +int int_array_read(Char_Array str, Int_Array* array){ + char* buffer=calloc(str.length+1,sizeof(char)); + char* buffer_ptr=buffer; + int i,j; + int comment_mode=0; + + // alloc + init_Int_Array(array,str.length); + + *buffer_ptr='\0'; + // loop over the input + for(j=0;j<str.length;j++){ + if(comment_mode==1){ + if(str.str[j]=='\n'){ + comment_mode=0; + } + } + else{ + switch(str.str[j]){ + // new term + case ',': + // write + sscanf(buffer,"%d",&i); + int_array_append(i,array); + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + break; + + // ignore + case '(':break; + case ')':break; + // comments + case '#': + comment_mode=1; + break; + + default: + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,str.str[j]); + break; + } + } + } + + // write + sscanf(buffer,"%d",&i); + int_array_append(i,array); + + free(buffer); + return(0); +} + + +// ------------------- CharArray ------------------------ + +// init +int init_Char_Array(Char_Array* array, int memory){ + (*array).str=calloc(memory,sizeof(char)); + (*array).memory=memory; + (*array).length=0; + return(0); +} +int free_Char_Array(Char_Array array){ + free(array.str); + return(0); +} + +// copy +int char_array_cpy(Char_Array input, Char_Array* output){ + init_Char_Array(output,input.length+1); + char_array_cpy_noinit(input,output); + return(0); +} +int char_array_cpy_noinit(Char_Array input, Char_Array* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy an array of length %d to another with memory %d\n",input.length, (*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + (*output).str[i]=input.str[i]; + } + (*output).length=input.length; + return(0); +} + +// resize memory +int char_array_resize(Char_Array* array, int newsize){ + Char_Array new_array; + init_Char_Array(&new_array, newsize); + char_array_cpy_noinit(*array,&new_array); + free_Char_Array(*array); + *array=new_array; + return(0); +} + +// add a value +int char_array_append(char val, Char_Array* output){ + if((*output).length>=(*output).memory){ + char_array_resize(output,2*(*output).memory+1); + } + (*output).str[(*output).length]=val; + (*output).length++; + return(0); +} +// append a string +int char_array_append_str(char* str, Char_Array* output){ + char* ptr; + for (ptr=str;*ptr!='\0';ptr++){ + char_array_append(*ptr, output); + } + return(0); +} + +// concatenate +int char_array_concat(Char_Array input, Char_Array* output){ + int i; + int offset=(*output).length; + if((*output).length+input.length>(*output).memory){ + // make it longer than needed by (*output).length (for speed) + char_array_resize(output,2*(*output).length+input.length); + } + for(i=0;i<input.length;i++){ + (*output).str[offset+i]=input.str[i]; + } + (*output).length=offset+input.length; + return(0); +} + + + +// convert to char* +int char_array_to_str(Char_Array input, char** output){ + int i; + (*output)=calloc(input.length+1,sizeof(char)); + for(i=0;i<input.length;i++){ + (*output)[i]=input.str[i]; + } + if((*output)[input.length-1]!='\0'){ + (*output)[input.length]='\0'; + } + return(0); +} +// noinit (changes the size of input if needed) +char* char_array_to_str_noinit(Char_Array* input){ + if((*input).str[(*input).length-1]!='\0'){ + if((*input).length==(*input).memory){ + char_array_resize(input,(*input).length+1); + } + // add final '\0' + (*input).str[(*input).length]='\0'; + } + return((*input).str); +} + + +// convert from char* +int str_to_char_array(char* str, Char_Array* output){ + char* ptr; + init_Char_Array(output, str_len(str)); + for(ptr=str;*ptr!='\0';ptr++){ + char_array_append(*ptr,output); + } + return(0); +} + + +// format strings +int char_array_snprintf(Char_Array* output, char* fmt, ...){ + size_t size=STR_SIZE; + unsigned int extra_size; + char* out_str=calloc(size,sizeof(char)); + char* ptr; + va_list vaptr; + + // initialize argument list starting after fmt + va_start(vaptr, fmt); + // print format + extra_size=vsnprintf(out_str, size, fmt, vaptr); + va_end(vaptr); + + // if too large + if(extra_size>size){ + // resize + free(out_str); + // +1 for '\0' + size=extra_size+1; + out_str=calloc(size,sizeof(char)); + // read format again + va_start(vaptr, fmt); + vsnprintf(out_str,size,fmt,vaptr); + va_end(vaptr); + } + + // write to char array + for(ptr=out_str;*ptr!='\0';ptr++){ + char_array_append(*ptr, output); + } + + free(out_str); + + return(0); +} + + +// replace '%' with given character +int replace_star(char c, Char_Array str, Char_Array* out){ + int i; + init_Char_Array(out, str.length); + for(i=0;i<str.length;i++){ + if(str.str[i]!='%'){ + char_array_append(str.str[i],out); + } + else{ + char_array_append(c,out); + } + } + return(0); +} + + +// ------------------- Str_Array ------------------------ + +// init +int init_Str_Array(Str_Array* array, int memory){ + (*array).strs=calloc(memory,sizeof(Char_Array)); + (*array).memory=memory; + (*array).length=0; + return(0); +} +int free_Str_Array(Str_Array array){ + int i; + for(i=0;i<array.length;i++){ + free_Char_Array(array.strs[i]); + } + free(array.strs); + return(0); +} + +// copy +int str_array_cpy(Str_Array input, Str_Array* output){ + init_Str_Array(output,input.length); + str_array_cpy_noinit(input,output); + return(0); +} +int str_array_cpy_noinit(Str_Array input, Str_Array* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy an array 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.strs[i],(*output).strs+i); + } + (*output).length=input.length; + return(0); +} + +// resize memory +int str_array_resize(Str_Array* array, int newsize){ + Str_Array new_array; + init_Str_Array(&new_array, newsize); + str_array_cpy_noinit(*array,&new_array); + free_Str_Array(*array); + *array=new_array; + return(0); +} + +// add a value +int str_array_append(Char_Array val, Str_Array* output){ + if((*output).length>=(*output).memory){ + str_array_resize(output,2*(*output).memory+1); + } + char_array_cpy(val, (*output).strs+(*output).length); + (*output).length++; + return(0); +} +int str_array_append_noinit(Char_Array val, Str_Array* output){ + if((*output).length>=(*output).memory){ + str_array_resize(output,2*(*output).memory+1); + } + (*output).strs[(*output).length]=val; + (*output).length++; + return(0); +} + +// concatenate +int str_array_concat(Str_Array input, Str_Array* output){ + int i; + int offset=(*output).length; + if((*output).length+input.length>(*output).memory){ + // make it longer than needed by (*output).length (for speed) + str_array_resize(output,2*(*output).length+input.length); + } + for(i=0;i<input.length;i++){ + char_array_cpy(input.strs[i],(*output).strs+offset+i); + } + (*output).length=offset+input.length; + return(0); +} +int str_array_concat_noinit(Str_Array input, Str_Array* output){ + int i; + int offset=(*output).length; + if((*output).length+input.length>(*output).memory){ + // make it longer than needed by (*output).length (for speed) + str_array_resize(output,2*(*output).length+input.length); + } + for(i=0;i<input.length;i++){ + (*output).strs[offset+i]=input.strs[i]; + } + (*output).length=offset+input.length; + + // free input arrays + free(input.strs); + return(0); +} + + +// ------------------- Labels ------------------------ + +// allocate memory +int init_Labels(Labels* labels,int size){ + (*labels).labels=calloc(size,sizeof(Char_Array)); + (*labels).indices=calloc(size,sizeof(int)); + (*labels).length=0; + (*labels).memory=size; + return(0); +} + +// free memory +int free_Labels(Labels labels){ + int i; + for(i=0;i<labels.length;i++){ + free_Char_Array(labels.labels[i]); + } + free(labels.labels); + free(labels.indices); + + return(0); +} + +// resize the memory allocated to a labels table +int resize_labels(Labels* labels,int new_size){ + Labels new_labels; + int i; + + init_Labels(&new_labels,new_size); + for(i=0;i<(*labels).length;i++){ + new_labels.labels[i]=(*labels).labels[i]; + new_labels.indices[i]=(*labels).indices[i]; + } + new_labels.length=(*labels).length; + + free((*labels).labels); + free((*labels).indices); + + *labels=new_labels; + return(0); +} + +// copy a labels table +int labels_cpy(Labels input, Labels* output){ + init_Labels(output,input.length); + labels_cpy_noinit(input,output); + return(0); +} +int labels_cpy_noinit(Labels input, Labels* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a labels 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.labels[i],(*output).labels+i); + (*output).indices[i]=input.indices[i]; + } + (*output).length=input.length; + + return(0); +} + +// append an element to a labels +int labels_append(Char_Array label, int index, Labels* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_labels(output,2*(*output).memory); + } + + // copy and allocate + char_array_cpy(label,(*output).labels+offset); + (*output).indices[offset]=index; + // increment length + (*output).length++; + return(0); +} +// append an element to a labels without allocating memory +int labels_append_noinit(Char_Array label, int index, Labels* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_labels(output,2*(*output).memory); + } + + // copy without allocating + (*output).labels[offset]=label; + (*output).indices[offset]=index; + // increment length + (*output).length++; + return(0); +} + +// concatenate two labels tables +int labels_concat(Labels input, Labels* output){ + int i; + for(i=0;i<input.length;i++){ + labels_append(input.labels[i],input.indices[i],output); + } + return(0); +} + diff --git a/src/array.h b/src/array.h new file mode 100644 index 0000000..fb74e67 --- /dev/null +++ b/src/array.h @@ -0,0 +1,134 @@ +/* +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. +*/ + +/* Array structures */ + +#ifndef ARRAY_H +#define ARRAY_H + +#include "types.h" + +// init +int init_Int_Array(Int_Array* array, int memory); +int free_Int_Array(Int_Array array); + +// copy +int int_array_cpy(Int_Array input, Int_Array* output); +int int_array_cpy_noinit(Int_Array input, Int_Array* output); + +// resize memory +int int_array_resize(Int_Array* array, int newsize); + +// add a value +int int_array_append(int val, Int_Array* output); +// concatenate +int int_array_concat(Int_Array input, Int_Array* output); + +// find (does not assume the array is sorted) +int int_array_find(int val, Int_Array array); +int int_array_find_err(int val, Int_Array array); + +// sort +int int_array_sort(Int_Array array, int begin, int end); + +// compare Int_Array's +int int_array_cmp(Int_Array array1, Int_Array array2); + +// check whether an array is a sub-array of another +int int_array_is_subarray_ordered(Int_Array input, Int_Array test_array); + +// print array +int int_array_print(Int_Array array); +// read array +int int_array_read(Char_Array str, Int_Array* array); + + +// Char_Array + +// init +int init_Char_Array(Char_Array* array, int memory); +int free_Char_Array(Char_Array array); + +// copy +int char_array_cpy(Char_Array input, Char_Array* output); +int char_array_cpy_noinit(Char_Array input, Char_Array* output); + +// resize memory +int char_array_resize(Char_Array* array, int newsize); + +// add a value +int char_array_append(char val, Char_Array* output); +int char_array_append_str(char* str, Char_Array* output); +// concatenate +int char_array_concat(Char_Array input, Char_Array* output); + +// convert to char* +int char_array_to_str(Char_Array input, char** output); +// noinit (changes the size of input if needed) +char* char_array_to_str_noinit(Char_Array* input); +// convert from char* +int str_to_char_array(char* str, Char_Array* output); + +// format strings +int char_array_snprintf(Char_Array* output, char* fmt, ...); + +// replace '*' with given character +int replace_star(char c, Char_Array str, Char_Array* out); + + +// Str_Array + +// init +int init_Str_Array(Str_Array* array, int memory); +int free_Str_Array(Str_Array array); + +// copy +int str_array_cpy(Str_Array input, Str_Array* output); +int str_array_cpy_noinit(Str_Array input, Str_Array* output); + +// resize memory +int str_array_resize(Str_Array* array, int newsize); + +// add a value +int str_array_append(Char_Array val, Str_Array* output); +int str_array_append_noinit(Char_Array val, Str_Array* output); +// concatenate +int str_array_concat(Str_Array input, Str_Array* output); +int str_array_concat_noinit(Str_Array input, Str_Array* output); + + +// Labels + +// allocate memory +int init_Labels(Labels* labels,int size); +// free memory +int free_Labels(Labels labels); + +// resize the memory allocated to a labels table +int resize_labels(Labels* labels,int new_size); + +// copy a labels table +int labels_cpy(Labels input, Labels* output); +int labels_cpy_noinit(Labels input, Labels* output); + +// append an element to a labels table +int labels_append(Char_Array label, int index, Labels* output); +int labels_append_noinit(Char_Array label, int index, Labels* output); + +// concatenate two labels tables +int labels_concat(Labels input, Labels* output); + +#endif diff --git a/src/cli_parser.c b/src/cli_parser.c new file mode 100644 index 0000000..bdca700 --- /dev/null +++ b/src/cli_parser.c @@ -0,0 +1,123 @@ +/* +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 "cli_parser.h" + +#include <stdio.h> +#include <stdlib.h> +#include "definitions.cpp" +#include "array.h" + +// read a config file and write the output to str_args +int read_config_file(Str_Array* str_args, const char* file, int read_from_stdin){ + FILE* infile; + char c; + Char_Array buffer; + + // allocate memory + init_Str_Array(str_args, ARG_COUNT); + init_Char_Array(&buffer, STR_SIZE); + + // read from file + if(read_from_stdin==0){ + infile=fopen(file,"r"); + if(infile==NULL){ + fprintf(stderr,"error: can't open file %s\n",file); + exit(-1); + } + } + else{ + infile=stdin; + } + + while(1){ + c=fgetc(infile); + // add to str_args + if(c=='&'){ + str_array_append_noinit(buffer,str_args); + init_Char_Array(&buffer, STR_SIZE); + } + else if(c==EOF){ + str_array_append_noinit(buffer,str_args); + break; + } + else{ + char_array_append(c,&buffer); + } + } + fclose(infile); + + return(0); +} + + +// get the title from a string argument +int get_str_arg_title(Char_Array str_arg, Char_Array* out){ + int j,k; + + init_Char_Array(out,STR_SIZE); + + // find "#!" at beginning of line + for(j=0;j<str_arg.length-2;j++){ + if(str_arg.str[j]=='#' && str_arg.str[j+1]=='!' && (j==0 || str_arg.str[j-1]=='\n')){ + break; + } + } + // if no title then error + if(j>=str_arg.length-2){ + fprintf(stderr, "error: an entry in the configuration file does not have a title (which should be preceeded by '#!' at the beginning of a line)\n"); + exit(-1); + } + + // get title until end of line + for(k=j+2;k<str_arg.length && str_arg.str[k]!='\n'; k++){ + char_array_append(str_arg.str[k],out); + } + + return(0); +} + +// find a string argument with the specified title +int find_str_arg(char* title, Str_Array str_args){ + int i,k; + char* ptr; + Char_Array buffer; + + for(i=0;i<str_args.length;i++){ + get_str_arg_title(str_args.strs[i], &buffer); + // match title + for(k=0, ptr=title; k<buffer.length; k++, ptr++){ + if(buffer.str[k]!=*ptr){ + break; + } + } + // if match + if(k==buffer.length){ + free_Char_Array(buffer); + break; + } + + free_Char_Array(buffer); + } + // if found + if(i<str_args.length){ + return(i); + } + else{ + return(-1); + } +} + diff --git a/src/cli_parser.h b/src/cli_parser.h new file mode 100644 index 0000000..b050e37 --- /dev/null +++ b/src/cli_parser.h @@ -0,0 +1,35 @@ +/* +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. +*/ + +/* +Parse command-line arguments +*/ + +#ifndef CLI_PARSER_H +#define CLI_PARSER_H + +#include "types.h" + +// read a config file and write the output to str_args +int read_config_file(Str_Array* str_args, const char* file, int read_from_stdin); + +// get the title from a string argument +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); + + +#endif diff --git a/src/coefficient.c b/src/coefficient.c new file mode 100644 index 0000000..c26b668 --- /dev/null +++ b/src/coefficient.c @@ -0,0 +1,739 @@ +/* +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 "coefficient.h" + +#include <stdio.h> +#include <stdlib.h> +#include "definitions.cpp" +#include "rational.h" +#include "istring.h" +#include "array.h" +#include "number.h" +#include "tools.h" + + +// allocate memory +int init_Coefficient(Coefficient* coef,int size){ + (*coef).factors=calloc(size,sizeof(Int_Array)); + (*coef).nums=calloc(size,sizeof(Number)); + (*coef).denoms=calloc(size,sizeof(coef_denom)); + (*coef).length=0; + (*coef).memory=size; + + return(0); +} + +// free memory +int free_Coefficient(Coefficient coef){ + int i; + for(i=0;i<coef.length;i++){ + free_Int_Array(coef.factors[i]); + free_Number(coef.nums[i]); + } + free(coef.factors); + free(coef.nums); + free(coef.denoms); + + return(0); +} + +// copy a coefficient +int coefficient_cpy(Coefficient input, Coefficient* output){ + init_Coefficient(output,input.length); + coefficient_cpy_noinit(input,output); + return(0); +} +int coefficient_cpy_noinit(Coefficient input, Coefficient* output){ + int i; + + // if output does not have enough memory allocated to it + if(input.length>(*output).memory){ + resize_Coefficient(output,input.length); + } + + for(i=0;i<input.length;i++){ + int_array_cpy(input.factors[i],(*output).factors+i); + number_cpy(input.nums[i],(*output).nums+i); + (*output).denoms[i]=input.denoms[i]; + } + (*output).length=input.length; + return(0); +} + + +// resize the memory allocated to a coefficient +int resize_Coefficient(Coefficient* coefficient,int new_size){ + Coefficient new_coef; + int i; + + init_Coefficient(&new_coef,new_size); + for(i=0;i<(*coefficient).length;i++){ + new_coef.factors[i]=(*coefficient).factors[i]; + new_coef.nums[i]=(*coefficient).nums[i]; + new_coef.denoms[i]=(*coefficient).denoms[i]; + } + new_coef.length=(*coefficient).length; + + free((*coefficient).factors); + free((*coefficient).nums); + free((*coefficient).denoms); + + *coefficient=new_coef; + return(0); +} + + +// append an element to a coefficient +int coefficient_append(Int_Array factor,Number num, coef_denom denom, Coefficient* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_Coefficient(output,2*(*output).memory+1); + } + // copy and allocate + int_array_cpy(factor,(*output).factors+offset); + number_cpy(num,(*output).nums+offset); + (*output).denoms[offset]=denom; + // increment length + (*output).length++; + return(0); +} +// append an element to a coefficient without allocating memory +int coefficient_append_noinit(Int_Array factor, Number num, coef_denom denom, Coefficient* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_Coefficient(output,2*(*output).memory+1); + } + // copy without allocating + (*output).factors[offset]=factor; + (*output).nums[offset]=num; + (*output).denoms[offset]=denom; + // increment length + (*output).length++; + return(0); +} + +// concatenate coefficients and simplify result +int coefficient_concat(Coefficient input, Coefficient* output){ + int i; + for(i=0;i<input.length;i++){ + coefficient_append(input.factors[i],input.nums[i],input.denoms[i],output); + } + + coefficient_simplify(output); + return(0); +} +int coefficient_concat_noinit(Coefficient input, Coefficient* output){ + int i; + for(i=0;i<input.length;i++){ + coefficient_append_noinit(input.factors[i],input.nums[i],input.denoms[i],output); + } + + coefficient_simplify(output); + + // free input arrays + free(input.factors); + free(input.nums); + free(input.denoms); + return(0); +} + + +// simplify a Coefficient +int coefficient_simplify(Coefficient* coefficient){ + int i; + Coefficient output; + init_Coefficient(&output,(*coefficient).length); + // the combination of numerical factors + Number new_num; + init_Number(&new_num,NUMBER_SIZE); + + // sort the factors in the coefficient + for(i=0;i<(*coefficient).length;i++){ + int_array_sort((*coefficient).factors[i],0,(*coefficient).factors[i].length-1); + } + // in order to perform a simplification, the list of terms must be + // sorted (so that terms that are proportional are next to each other) + sort_coefficient(coefficient,0,(*coefficient).length-1); + + for(i=0;i<(*coefficient).length;i++){ + // if the term actually exists + if(number_is_zero((*coefficient).nums[i])!=1){ + // combine numerical factors + number_add_chain((*coefficient).nums[i],&new_num); + } + // if the number is 0, the previous terms that may have the same factors should still be added, hence the 'if' ends here + + // if the factor is different from the next then add term + if(i==(*coefficient).length-1 || (int_array_cmp((*coefficient).factors[i],(*coefficient).factors[i+1])!=0) || coef_denom_cmp((*coefficient).denoms[i],(*coefficient).denoms[i+1])!=0){ + // check that the coefficient is not trivial + if(number_is_zero(new_num)!=1){ + coefficient_append((*coefficient).factors[i],new_num,(*coefficient).denoms[i],&output); + } + + // reset new numerical factor + free_Number(new_num); + init_Number(&new_num,NUMBER_SIZE); + } + } + + free_Number(new_num); + free_Coefficient(*coefficient); + *coefficient=output; + return(0); +} + +// sort the terms in an equation (quicksort algorithm) +int sort_coefficient(Coefficient* coefficient, int begin, int end){ + int i; + int index; + // the pivot: middle of the array + int pivot=(begin+end)/2; + // if the array is non trivial + if(begin<end){ + // send pivot to the end + exchange_coefficient_terms(pivot,end,coefficient); + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + if(coef_denom_cmp((*coefficient).denoms[i],(*coefficient).denoms[end])<0 || ( coef_denom_cmp((*coefficient).denoms[i],(*coefficient).denoms[end])==0 && (int_array_cmp((*coefficient).factors[i],(*coefficient).factors[end])<0)) ){ + // if smaller, exchange with reference index + exchange_coefficient_terms(i,index,coefficient); + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + exchange_coefficient_terms(index,end,coefficient); + // recurse + sort_coefficient(coefficient, begin, index-1); + sort_coefficient(coefficient, index+1, end); + } + return(0); +} + +// exchange two terms (for the sorting algorithm) +int exchange_coefficient_terms(int i, int j, Coefficient* coefficient){ + Int_Array ptmp; + Number tmpq; + coef_denom tmpc; + + ptmp=(*coefficient).factors[j]; + (*coefficient).factors[j]=(*coefficient).factors[i]; + (*coefficient).factors[i]=ptmp; + + tmpq=(*coefficient).nums[j]; + (*coefficient).nums[j]=(*coefficient).nums[i]; + (*coefficient).nums[i]=tmpq; + + tmpc=(*coefficient).denoms[j]; + (*coefficient).denoms[j]=(*coefficient).denoms[i]; + (*coefficient).denoms[i]=tmpc; + return(0); +} + +// derive a coefficient with respect to an index +int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output){ + int i,j; + // temp list of indices + Int_Array factor; + // number of times index was found + int match_count; + // whether the output contains at least one factor + int at_least_one=0; + coef_denom denom; + + // loop over monomials + for(i=0;i<input.length;i++){ + init_Int_Array(&factor,input.factors[i].length); + // init match count + match_count=0; + // loop over indices + for(j=0;j<input.factors[i].length;j++){ + // if found + if(input.factors[i].values[j]==index){ + // if it's the first match, don't add it + if(match_count!=0){ + int_array_append(index,&factor); + } + match_count++; + } + // add the index + else{ + int_array_append(input.factors[i].values[j],&factor); + } + } + + denom=input.denoms[i]; + // if the index is that of 1/C + if(index==input.denoms[i].index){ + // if no C in the numerator (which is normal behavior) + if(match_count==0){ + denom.power++; + } + match_count-=input.denoms[i].power; + } + + + // if the derivative doesn't vanish, add it to the coefficient + if(match_count!=0){ + at_least_one=1; + coefficient_append_noinit(factor,number_Qprod_ret(quot(match_count,1),input.nums[i]), denom, output); + } + else{ + free_Int_Array(factor); + } + } + + if(at_least_one==1){ + coefficient_simplify(output); + } + else{ + // add a trivial element to the coefficient + init_Int_Array(&factor,0); + denom.index=-1; + denom.power=0; + coefficient_append_noinit(factor,number_zero(),denom,output); + } + + return(0); +} + +int coefficient_deriv(Coefficient input, int index, Coefficient* output){ + init_Coefficient(output, COEF_SIZE); + coefficient_deriv_noinit(input, index, output); + return(0); +} + +/* +// derive a coefficient with respect to an index (as a polynomial) (does not derive the 1/(1+C)^p ) +int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output){ + int i; + // temp list of indices + Int_Array factor; + // number of times index was found + int match_count; + // whether the output contains at least one factor + int at_least_one=0; + coef_denom denom; + + // loop over monomials + for(i=0;i<input.length;i++){ + // derivative of monomial + monomial_deriv(input.factors[i], index, &factor, &match_count); + + // if the derivative doesn't vanish, add it to the coefficient + if(match_count>0){ + at_least_one=1; + coefficient_append_noinit(factor,number_Qprod_ret(quot(match_count,1),input.nums[i]), input.denoms[i],output); + } + else{ + free_Int_Array(factor); + } + } + + if(at_least_one>0){ + coefficient_simplify(output); + } + else{ + // add a trivial element to the coefficient + init_Int_Array(&factor,0); + denom.index=-1; + denom.power=0; + coefficient_append_noinit(factor,number_zero(),denom,output); + } + + return(0); +} + +// derive a monomial with respect to an index +int monomial_deriv(Int_Array factor, int index, Int_Array* out_factor, int* match_count){ + int j; + + init_Int_Array(out_factor,factor.length); + // init match count + *match_count=0; + + // loop over indices + for(j=0;j<factor.length;j++){ + // if found + if(factor.values[j]==index){ + // if it's the first match, don't add it + if(*match_count!=0){ + int_array_append(index,out_factor); + } + (*match_count)++; + } + // add the index + else{ + int_array_append(factor.values[j],out_factor); + } + } + + return(0); +} +*/ + + + +// product of two coefficients +int coefficient_prod(Coefficient coef1, Coefficient coef2, Coefficient* output){ + int i,j; + // tmp factor + Int_Array factor; + coef_denom denom; + + // init + init_Coefficient(output,COEF_SIZE); + + // loop over coef1 + for(i=0;i<coef1.length;i++){ + // loop over coef2 + for(j=0;j<coef2.length;j++){ + init_Int_Array(&factor,coef1.factors[i].length+coef2.factors[j].length); + int_array_concat(coef1.factors[i],&factor); + 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; + } + else if(coef1.denoms[i].power==0){ + coef1.denoms[i].index=coef2.denoms[i].index; + } + if(coef1.denoms[i].index!=coef2.denoms[j].index){ + fprintf(stderr,"error: cannot multiply flow equations with different constants\n"); + exit(-1); + } + denom=coef1.denoms[i]; + denom.power+=coef2.denoms[j].power; + coefficient_append_noinit(factor,number_prod_ret(coef1.nums[i],coef2.nums[j]), denom, output); + } + } + + // simplify output + coefficient_simplify(output); + return(0); +} + +// product of coefficients, output replaces the second coefficient +int coefficient_prod_chain(Coefficient in, Coefficient* inout){ + Coefficient tmp_coef; + coefficient_prod(in,*inout,&tmp_coef); + free_Coefficient(*inout); + *inout=tmp_coef; + return(0); +} + + +// print coefficient +// offset specifies the amount of blank space to the left of the terms after the first +// prepend indices by ind_pre +int coefficient_sprint(Coefficient coef, Char_Array* output, int offset, char index_pre){ + Char_Array buffer; + int i,j,k; + int dcount; + + if(coef.length==0){ + char_array_snprintf(output, " (0)\n"); + } + + for(i=0;i<coef.length;i++){ + if(i==0){ + char_array_snprintf(output, " "); + } + else{ + for(j=0;j<=offset;j++){ + char_array_append(' ',output); + } + char_array_append('+',output); + } + + // print numerical coefficient + char_array_append('(',output); + init_Char_Array(&buffer, STR_SIZE); + number_sprint(coef.nums[i], &buffer); + char_array_concat(buffer, output); + free_Char_Array(buffer); + char_array_append(')',output); + + // print factors + for(j=0;j<coef.factors[i].length;j++){ + // constant indices + if(coef.factors[i].values[j]<0){ + // count derivatives + dcount=-coef.factors[i].values[j]/DOFFSET; + char_array_append('[',output); + for(k=0;k<dcount;k++){ + char_array_append('d',output); + } + char_array_snprintf(output,"C%d]",-coef.factors[i].values[j]-dcount*DOFFSET); + } + else{ + // count derivatives + dcount=coef.factors[i].values[j]/DOFFSET; + char_array_append('[',output); + for(k=0;k<dcount;k++){ + char_array_append('d',output); + } + char_array_snprintf(output,"%c%d]",index_pre,coef.factors[i].values[j]-dcount*DOFFSET); + } + } + + // print constant denominators + if(coef.denoms[i].power!=0){ + char_array_snprintf(output,"[/C%d^%d]",-coef.denoms[i].index,coef.denoms[i].power); + } + + char_array_append('\n',output); + } + + return(0); +} + + +// read from a string +#define PP_NULL_MODE 0 +#define PP_BRACKET_MODE 1 +#define PP_INDICES_MODE 2 +#define PP_POWER_MODE 3 +#define PP_COMMENT_MODE 4 +#define PP_NUMBER_MODE 5 +#define PP_CONSTANT_MODE 6 +#define PP_CONSTANT_DENOM_MODE 7 +int char_array_to_Coefficient(Char_Array str_coef, Coefficient* output){ + // buffer + char* buffer=calloc(str_coef.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Int_Array indices; + coef_denom denom; + Number num, tmp1_num; + int mode; + int i,j; + int parenthesis_count=0; + int dcount=0; + + // allocate memory + init_Coefficient(output,COEF_SIZE); + + // init + init_Int_Array(&indices, MONOMIAL_SIZE); + num=number_one(); + denom.index=-1; + denom.power=0; + + *buffer_ptr='\0'; + // loop over the input polynomial + // start in null mode + mode=PP_NULL_MODE; + for(j=0;j<str_coef.length;j++){ + if(mode==PP_COMMENT_MODE){ + if(str_coef.str[j]=='\n'){ + mode=PP_NULL_MODE; + } + } + else{ + switch(str_coef.str[j]){ + // new indices + case '+': + if(mode==PP_NULL_MODE){ + coefficient_append_noinit(indices, num, denom, output); + // reset indices, num + init_Int_Array(&indices, MONOMIAL_SIZE); + num=number_one(); + denom.index=-1; + denom.power=0; + } + break; + + // enter indices or power mode + case '[': + if(mode==PP_NULL_MODE){ + mode=PP_BRACKET_MODE; + // reset derivatives count + dcount=0; + } + break; + // indices mode + case '%': + if(mode==PP_BRACKET_MODE){ + mode=PP_INDICES_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case 'C': + if(mode==PP_BRACKET_MODE){ + mode=PP_CONSTANT_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case '/': + if(mode==PP_BRACKET_MODE){ + mode=PP_CONSTANT_DENOM_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else if(mode!=PP_NULL_MODE){ + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,str_coef.str[j]); + } + break; + // derivatives + case 'd': + if(mode==PP_BRACKET_MODE || mode==PP_INDICES_MODE || mode==PP_CONSTANT_MODE){ + dcount++; + } + break; + // power mode + case '^': + if(mode==PP_CONSTANT_DENOM_MODE){ + sscanf(buffer,"%d",&i); + denom.index=-i; + mode=PP_POWER_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,str_coef.str[j]); + } + break; + // read indices or power + case ']': + sscanf(buffer,"%d",&i); + if(mode==PP_INDICES_MODE){ + int_array_append(i+dcount*DOFFSET,&indices); + } + else if(mode==PP_CONSTANT_MODE){ + int_array_append(-i-dcount*DOFFSET,&indices); + } + else if(mode==PP_POWER_MODE){ + denom.power=i; + } + // switch back to null mode + mode=PP_NULL_MODE; + break; + + // numerical pre-factor + case '(': + if(mode==PP_NULL_MODE){ + mode=PP_NUMBER_MODE; + parenthesis_count=0; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else if(mode==PP_NUMBER_MODE){ + // match parentheses + parenthesis_count++; + buffer_ptr=str_addchar(buffer_ptr,str_coef.str[j]); + } + break; + case ')': + if(mode==PP_NUMBER_MODE){ + if(parenthesis_count==0){ + // write num + str_to_Number(buffer,&tmp1_num); + number_prod_chain(tmp1_num,&num); + free_Number(tmp1_num); + // back to null mode + mode=PP_NULL_MODE; + } + else{ + parenthesis_count--; + buffer_ptr=str_addchar(buffer_ptr,str_coef.str[j]); + } + } + break; + + // characters to ignore + case ' ':break; + case '&':break; + case '\n':break; + + // comments + case '#': + mode=PP_COMMENT_MODE; + break; + + default: + if(mode!=PP_NULL_MODE){ + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,str_coef.str[j]); + } + break; + } + } + } + + // last term + coefficient_append_noinit(indices, num, denom, output); + + free(buffer); + return(0); +} + +int str_to_Coefficient(char* str, Coefficient* output){ + Char_Array array; + array.length=str_len(str); + array.str=str; + char_array_to_Coefficient(array, output); + return(0); +} + +// compare coefficient denominators +int coef_denom_cmp(coef_denom denom1, coef_denom denom2){ + if(denom1.index<denom2.index){ + return(1); + } + else if(denom1.index>denom2.index){ + return(-1); + } + + if(denom1.power<denom2.power){ + return(-1); + } + else if(denom1.power>denom2.power){ + return(1); + } + + return(0); +} + + +// evaluate a coefficient on a vector +int evalcoef(RCC rccs, Coefficient coef, long double* out){ + int i,j; + long double num_factor; + + *out=0; + + // for each monomial + for(i=0;i<coef.length;i++){ + // product of factors + for(j=0, num_factor=1.;j<coef.factors[i].length;j++){ + num_factor*=rccs.values[intlist_find_err(rccs.indices,rccs.length,coef.factors[i].values[j])]; + } + // denominator + if(coef.denoms[i].power>0){ + num_factor/=dpower(rccs.values[intlist_find_err(rccs.indices,rccs.length,coef.denoms[i].index)],coef.denoms[i].power); + } + *out+=num_factor*number_double_val(coef.nums[i]); + } + return(0); +} diff --git a/src/coefficient.h b/src/coefficient.h new file mode 100644 index 0000000..a7a151c --- /dev/null +++ b/src/coefficient.h @@ -0,0 +1,78 @@ +/* +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. +*/ + +/* +Coefficients represent the collection of terms which appear + on the right hand side of a single flow equation. + +They are used as an elementary building block of grouped polynomials. +*/ + +#ifndef COEFFICIENT_H +#define COEFFICIENT_H + +#include "types.h" + +// allocate memory +int init_Coefficient(Coefficient* coef,int size); +// free memory +int free_Coefficient(Coefficient coef); + +// copy a coefficient +int coefficient_cpy(Coefficient input, Coefficient* output); +int coefficient_cpy_noinit(Coefficient input, Coefficient* output); + +// resize the memory allocated to a coefficient +int resize_Coefficient(Coefficient* coefficient,int new_size); + +// append an element to a coefficient +int coefficient_append(Int_Array factor,Number num, coef_denom denom, Coefficient* output); +int coefficient_append_noinit(Int_Array factor, Number num, coef_denom denom, Coefficient* output); + +// concatenate coefficients and simplify result +int coefficient_concat(Coefficient input, Coefficient* output); +int coefficient_concat_noinit(Coefficient input, Coefficient* output); + +// simplify a Coefficient +int coefficient_simplify(Coefficient* coefficient); +// 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 ) +int coefficient_deriv_noinit(Coefficient input, int index, Coefficient* output); +int coefficient_deriv(Coefficient input, int index, Coefficient* output); + +// product of two coefficients +int coefficient_prod(Coefficient coef1, Coefficient coef2, Coefficient* output); +// product of coefficients, output replaces the second coefficient +int coefficient_prod_chain(Coefficient in, Coefficient* inout); + +// print coefficient +int coefficient_sprint(Coefficient coef, Char_Array* output, int offset, char index_pre); + +// read from a string +int char_array_to_Coefficient(Char_Array str_coef, Coefficient* output); +int str_to_Coefficient(char* str, Coefficient* output); + +// compare coefficient denominators +int coef_denom_cmp(coef_denom denom1, coef_denom denom2); + +// evaluate a coefficient on a vector +int evalcoef(RCC rccs, Coefficient coef, long double* out); + +#endif diff --git a/src/definitions.cpp b/src/definitions.cpp new file mode 100644 index 0000000..d32537d --- /dev/null +++ b/src/definitions.cpp @@ -0,0 +1,60 @@ +/* +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. +*/ + +#ifndef DEFINITIONS_GCC +#define DEFINITIONS_GCC + +#define VERSION "1.2" + +// number of entries in a configuration file +#define ARG_COUNT 10 +// size of string representing a monomial +#define MONOMIAL_SIZE 20 +// size of various strings +#define STR_SIZE 100 +// number of terms in coefficients +#define COEF_SIZE 100 +// number of terms in polynomials +#define POLY_SIZE 100 +// number of equations +#define EQUATION_SIZE 20 +// number of fields +#define FIELDS_SIZE 50 +// number of elements in numbers +#define NUMBER_SIZE 5 +// number of elements in a group +#define GROUP_SIZE 5 + + +// display options +#define DISPLAY_EQUATION 1 +#define DISPLAY_NUMERICAL 2 +#define DISPLAY_EXPLOG 3 +#define DISPLAY_FINAL 4 + +// available preprocessors +#define PREPROCESSOR_KONDO 1 + +// offset derivative indices +#define DOFFSET 1000000 + +// types of fields (the order matters) +#define FIELD_PARAMETER 1 +#define FIELD_EXTERNAL 2 +#define FIELD_INTERNAL 3 +#define FIELD_SYMBOL 4 + +#endif diff --git a/src/expansions.c b/src/expansions.c new file mode 100644 index 0000000..c889829 --- /dev/null +++ b/src/expansions.c @@ -0,0 +1,28 @@ +/* +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 new file mode 100644 index 0000000..85d6c2b --- /dev/null +++ b/src/expansions.h @@ -0,0 +1,34 @@ +/* +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 new file mode 100644 index 0000000..1b221f2 --- /dev/null +++ b/src/fields.c @@ -0,0 +1,489 @@ +/* +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 "fields.h" +#include "definitions.cpp" +#include <stdio.h> +#include <stdlib.h> +#include "number.h" +#include "tools.h" +#include "polynomial.h" +#include "array.h" +#include "rational.h" + +// init and free for Fields_Table +int init_Fields_Table(Fields_Table* fields){ + init_Int_Array(&((*fields).parameter),FIELDS_SIZE); + 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_Int_Array(&((*fields).fermions),FIELDS_SIZE); + return(0); +} +int free_Fields_Table(Fields_Table fields){ + free_Int_Array(fields.parameter); + free_Int_Array(fields.external); + free_Int_Array(fields.internal); + free_Identities(fields.ids); + free_Symbols(fields.symbols); + free_Int_Array(fields.fermions); + return(0); +} + +// determine field type +int field_type(int index, Fields_Table fields){ + if(int_array_find(abs(index), fields.parameter)>=0){ + return(FIELD_PARAMETER); + } + else if(int_array_find(abs(index), fields.external)>=0){ + return(FIELD_EXTERNAL); + } + 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); + } + + fprintf(stderr,"error: index %d is neither a parameter nor an external or an internal field, nor a symbol\n",index); + exit(-1); +} + +// check whether a field anticommutes +int is_fermion(int index, Fields_Table fields){ + if(int_array_find(abs(index), fields.fermions)>=0){ + return(1); + } + else{ + return(0); + } +} + + +// ------------------ Identities -------------------- + +// allocate memory +int init_Identities(Identities* identities,int size){ + (*identities).lhs=calloc(size,sizeof(Int_Array)); + (*identities).rhs=calloc(size,sizeof(Polynomial)); + (*identities).length=0; + (*identities).memory=size; + return(0); +} + +// free memory +int free_Identities(Identities identities){ + int i; + for(i=0;i<identities.length;i++){ + free_Int_Array(identities.lhs[i]); + free_Polynomial(identities.rhs[i]); + } + free(identities.lhs); + free(identities.rhs); + return(0); +} + +// resize +int resize_identities(Identities* identities,int new_size){ + Identities new_identities; + int i; + + init_Identities(&new_identities,new_size); + for(i=0;i<(*identities).length;i++){ + new_identities.lhs[i]=(*identities).lhs[i]; + new_identities.rhs[i]=(*identities).rhs[i]; + } + new_identities.length=(*identities).length; + + free((*identities).lhs); + free((*identities).rhs); + + *identities=new_identities; + return(0); +} + +// copy +int identities_cpy(Identities input, Identities* output){ + init_Identities(output,input.length); + identities_cpy_noinit(input,output); + return(0); +} +int identities_cpy_noinit(Identities input, Identities* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy an identities collection of length %d to another with memory %d\n",input.length,(*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + int_array_cpy(input.lhs[i],(*output).lhs+i); + polynomial_cpy(input.rhs[i],(*output).rhs+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a identities +int identities_append(Int_Array lhs, Polynomial rhs, Identities* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_identities(output,2*(*output).memory+1); + } + + // copy and allocate + int_array_cpy(lhs,(*output).lhs+offset); + polynomial_cpy(rhs,(*output).rhs+offset); + // increment length + (*output).length++; + return(0); +} +// append an element to a identities without allocating memory +int identities_append_noinit(Int_Array lhs, Polynomial rhs, Identities* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_identities(output,2*(*output).memory+1); + } + + // copy without allocating + (*output).lhs[offset]=lhs; + (*output).rhs[offset]=rhs; + // increment length + (*output).length++; + return(0); +} + +// concatenate two identitiess +int identities_concat(Identities input, Identities* output){ + int i; + for(i=0;i<input.length;i++){ + identities_append(input.lhs[i],input.rhs[i],output); + } + return(0); +} + + +// resolve the identities +// requires both the monomials in polynomial and the ids in fields to be sorted +int resolve_ids(Polynomial* polynomial, Fields_Table fields){ + int i,j,k,l; + int sign; + int fermion_count; + int at_least_one; + int security; + Int_Array monomial; + Number num; + Number tmp_num; + + // loop over monomials + for(i=0;i<(*polynomial).length;i++){ + at_least_one=1; + security=0; + // repeat the simplification until the monomial is fully simplified + while(at_least_one>0){ + at_least_one=0; + + // prevent infinite loops + security++; + if(security>1000000){ + fprintf(stderr,"error: 1000000 iterations reached when trying to simplify a monomial\n"); + exit(-1); + } + + // loop over ids + for(j=0;j<fields.ids.length;j++){ + // check whether the monomial matches the id + if(int_array_is_subarray_ordered(fields.ids.lhs[j],(*polynomial).monomials[i])==1){ + init_Int_Array(&monomial, (*polynomial).monomials[i].length); + + // remove lhs from monomial + // sign from moving the fields out of the monomial + sign=1; + // number of Fermions to remove from the monomial + fermion_count=0; + for(k=0,l=0;k<(*polynomial).monomials[i].length;k++){ + // check whether the field is identical to the "current" one in the id + // if l is too large, then keep the field + if(l>=fields.ids.lhs[j].length || (*polynomial).monomials[i].values[k]!=fields.ids.lhs[j].values[l]){ + int_array_append((*polynomial).monomials[i].values[k],&monomial); + // sign correction + if(fermion_count % 2 ==1 && is_fermion((*polynomial).monomials[i].values[k], fields)){ + sign*=-1; + } + } + else{ + // increment fermion_count + if(is_fermion(fields.ids.lhs[j].values[l],fields)){ + fermion_count++; + } + // increment "current" field in the id + l++; + } + } + + num=number_Qprod_ret(quot(sign,1),(*polynomial).nums[i]); + // add extra monomials (if there are more than 1) + for(k=1;k<fields.ids.rhs[j].length;k++){ + number_prod(num, fields.ids.rhs[j].nums[k], &tmp_num); + polynomial_append(monomial, (*polynomial).factors[i], tmp_num, polynomial); + free_Number(tmp_num); + int_array_concat(fields.ids.rhs[j].monomials[k],(*polynomial).monomials+(*polynomial).length-1); + // re-sort monomial + sign=1; + monomial_sort((*polynomial).monomials[(*polynomial).length-1],0,(*polynomial).monomials[(*polynomial).length-1].length-1,fields,&sign); + number_Qprod_chain(quot(sign,1),(*polynomial).nums+(*polynomial).length-1); + } + // correct i-th monomial + free_Number((*polynomial).nums[i]); + (*polynomial).nums[i]=number_prod_ret(num,fields.ids.rhs[j].nums[0]); + free_Int_Array((*polynomial).monomials[i]); + (*polynomial).monomials[i]=monomial; + int_array_concat(fields.ids.rhs[j].monomials[0],(*polynomial).monomials+i); + // re-sort monomial + sign=1; + monomial_sort((*polynomial).monomials[i],0,(*polynomial).monomials[i].length-1,fields,&sign); + number_Qprod_chain(quot(sign,1),(*polynomial).nums+i); + + // free num + free_Number(num); + + // repeat the step (in order to perform all of the replacements if several are necessary) + j--; + if(at_least_one==0){ + at_least_one=1; + } + } + } + } + } + + return(0); +} + + +// ------------------ Symbols -------------------- + +// 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; + return(0); +} + +// free memory +int free_Symbols(Symbols symbols){ + int i; + for(i=0;i<symbols.length;i++){ + free_Polynomial(symbols.expr[i]); + } + free(symbols.indices); + free(symbols.expr); + return(0); +} + +// resize +int resize_symbols(Symbols* symbols,int new_size){ + Symbols new_symbols; + 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]; + } + new_symbols.length=(*symbols).length; + + free((*symbols).indices); + free((*symbols).expr); + + *symbols=new_symbols; + return(0); +} + +// copy +int symbols_cpy(Symbols input, Symbols* output){ + init_Symbols(output,input.length); + symbols_cpy_noinit(input,output); + return(0); +} +int symbols_cpy_noinit(Symbols input, Symbols* 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); + exit(-1); + } + for(i=0;i<input.length;i++){ + (*output).indices[i]=input.indices[i]; + polynomial_cpy(input.expr[i],(*output).expr+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a symbols +int symbols_append(int index, Polynomial expr, Symbols* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_symbols(output,2*(*output).memory+1); + } + + // copy and allocate + (*output).indices[offset]=index; + polynomial_cpy(expr,(*output).expr+offset); + // increment length + (*output).length++; + return(0); +} +// append an element to a symbols without allocating memory +int symbols_append_noinit(int index, Polynomial expr, Symbols* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_symbols(output,2*(*output).memory+1); + } + + // copy without allocating + (*output).indices[offset]=index; + (*output).expr[offset]=expr; + // increment length + (*output).length++; + return(0); +} + +// concatenate two symbolss +int symbols_concat(Symbols input, Symbols* output){ + int i; + for(i=0;i<input.length;i++){ + symbols_append(input.indices[i],input.expr[i],output); + } + return(0); +} + + + +// ------------------ Groups -------------------- + +// allocate memory +int init_Groups(Groups* groups,int size){ + (*groups).indices=calloc(size,sizeof(Int_Array)); + (*groups).length=0; + (*groups).memory=size; + return(0); +} + +// free memory +int free_Groups(Groups groups){ + int i; + for(i=0;i<groups.length;i++){ + free_Int_Array(groups.indices[i]); + } + free(groups.indices); + return(0); +} + +// resize +int resize_groups(Groups* groups,int new_size){ + Groups new_groups; + int i; + + init_Groups(&new_groups,new_size); + for(i=0;i<(*groups).length;i++){ + new_groups.indices[i]=(*groups).indices[i]; + } + new_groups.length=(*groups).length; + + free((*groups).indices); + + *groups=new_groups; + return(0); +} + +// copy +int groups_cpy(Groups input, Groups* output){ + init_Groups(output,input.length); + groups_cpy_noinit(input,output); + return(0); +} +int groups_cpy_noinit(Groups input, Groups* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a groups collection of length %d to another with memory %d\n",input.length,(*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + int_array_cpy(input.indices[i],(*output).indices+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a groups +int groups_append(Int_Array indices, Groups* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_groups(output,2*(*output).memory+1); + } + + // copy and allocate + int_array_cpy(indices,(*output).indices+offset); + // increment length + (*output).length++; + return(0); +} +// append an element to a groups without allocating memory +int groups_append_noinit(Int_Array indices, Groups* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_groups(output,2*(*output).memory+1); + } + + // copy without allocating + (*output).indices[offset]=indices; + // increment length + (*output).length++; + return(0); +} + +// concatenate two groupss +int groups_concat(Groups input, Groups* output){ + int i; + for(i=0;i<input.length;i++){ + groups_append(input.indices[i],output); + } + return(0); +} + +// find which group an index belongs to +int find_group(int index, Groups groups){ + int i,j; + for(i=0;i<groups.length;i++){ + for(j=0;j<groups.indices[i].length;j++){ + if(groups.indices[i].values[j]==index){ + return(i); + } + } + } + return(-1); +} diff --git a/src/fields.h b/src/fields.h new file mode 100644 index 0000000..3795d92 --- /dev/null +++ b/src/fields.h @@ -0,0 +1,98 @@ +/* +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. +*/ + +/* declaring fields */ + +#ifndef FIELDS_H +#define FIELDS_H + +#include "types.h" + +// init +int init_Fields_Table(Fields_Table* fields); +int free_Fields_Table(Fields_Table fields); + +// determine field type +int field_type(int index, Fields_Table fields); +// check whether a field anticommutes +int is_fermion(int index, Fields_Table fields); + + +// init +int init_Identities(Identities* identities,int size); +int free_Identities(Identities identities); + +// resize +int resize_identities(Identities* identities,int new_size); + +// copy +int identities_cpy(Identities input, Identities* output); +int identities_cpy_noinit(Identities input, Identities* output); + +// append an element to a identities +int identities_append(Int_Array lhs, Polynomial rhs, Identities* output); +int identities_append_noinit(Int_Array lhs, Polynomial rhs, Identities* output); + +// concatenate two identitiess +int identities_concat(Identities input, Identities* output); + +// resolve the identities +int resolve_ids(Polynomial* polynomial, Fields_Table fields); + + +// init +int init_Symbols(Symbols* symbols,int size); +int free_Symbols(Symbols symbols); + +// resize +int resize_symbols(Symbols* symbols,int new_size); + +// copy +int symbols_cpy(Symbols input, Symbols* output); +int symbols_cpy_noinit(Symbols input, Symbols* 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); + +// concatenate two symbolss +int symbols_concat(Symbols input, Symbols* output); + + +// init +int init_Groups(Groups* groups,int size); +int free_Groups(Groups groups); + +// resize +int resize_groups(Groups* groups,int new_size); + +// copy +int groups_cpy(Groups input, Groups* output); +int groups_cpy_noinit(Groups input, Groups* output); + +// append an element to a groups +int groups_append(Int_Array indices, Groups* output); +int groups_append_noinit(Int_Array indices, Groups* output); + +// concatenate two groupss +int groups_concat(Groups input, Groups* output); + +// find which group an index belongs to +int find_group(int index, Groups groups); + + +#define FIELDS_H_DONE +#endif diff --git a/src/flow.c b/src/flow.c new file mode 100644 index 0000000..d271e44 --- /dev/null +++ b/src/flow.c @@ -0,0 +1,167 @@ +/* +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 "flow.h" + +#include <stdio.h> +#include <stdlib.h> +#include "tools.h" +#include "math.h" +#include "definitions.cpp" +#include "number.h" +#include "array.h" +#include "coefficient.h" + + + +// compute flow numerically, no exponentials +// inputs: flow_equation +// init, niter, tol (the allowed error at each step), ls (whether to display the results in terms of ls), display_mode (what to print) +int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, int niter, long double tol, int display_mode){ + // running coupling contants + RCC rccs=init; + int i,j; + + if(display_mode==DISPLAY_NUMERICAL){ + // print labels + printf("%5s ","n"); + for(j=0;j<rccs.length;j++){ + print_label(rccs.indices[j], labels); + } + printf("\n\n"); + + // print initial values + printf("%5d ",0); + for(j=0;j<rccs.length;j++){ + printf("% 14.7Le ",rccs.values[j]); + } + printf("\n"); + } + + for(i=0;i<niter;i++){ + // compute a single step + step_flow(&rccs, flow_equation, tol); + // convert ls to alphas + 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]); + } + printf("\n"); + } + } + + if(display_mode==DISPLAY_NUMERICAL){ + // print labels + printf("\n"); + printf("%5s ","n"); + for(j=0;j<rccs.length;j++){ + print_label(rccs.indices[j], labels); + } + printf("\n\n"); + } + + if(display_mode==DISPLAY_FINAL){ + RCC_print(rccs); + } + + return(0); +} + +// single step in the flow no exponentials +// inputs: flow_equation, tol +// input/outputs: rccs +int step_flow(RCC* rccs, Grouped_Polynomial flow_equation, long double tol){ + int i; + long double* new_rccs=calloc((*rccs).length,sizeof(long double)); + Int_Array computed; + + init_Int_Array(&computed, (*rccs).length); + + // initialize vectors to 0 + for(i=0;i<(*rccs).length;i++){ + new_rccs[i]=0.; + } + + // compute the constants first + for(i=0;i<flow_equation.length;i++){ + if(flow_equation.indices[i]<0){ + evalcoef(*rccs, flow_equation.coefs[i], new_rccs+i); + // if the new rcc is too small, then ignore it + if(fabs(new_rccs[i])<tol){ + new_rccs[i]=0.; + } + (*rccs).values[i]=new_rccs[i]; + } + } + + // for each equation + for(i=0;i<flow_equation.length;i++){ + if(flow_equation.indices[i]>=0){ + evalcoef(*rccs, flow_equation.coefs[i], new_rccs+i); + // if the new rcc is too small, then ignore it + if(fabs(new_rccs[i])<tol){ + new_rccs[i]=0.; + } + } + } + + // copy results to rccs + for(i=0;i<(*rccs).length;i++){ + (*rccs).values[i]=new_rccs[i]; + } + + // free memory + free_Int_Array(computed); + free(new_rccs); + return(0); +} + + +// print the label of an rcc (takes constants and derivatives into account) +int print_label(int index, Labels labels){ + int i; + int nderivs; + int posin_labels; + Char_Array label; + + // constant term + if(index<0){ + nderivs=-index/DOFFSET; + for (i=0;i<12-nderivs;i++){ + printf(" "); + } + for(i=0;i<nderivs;i++){ + printf("d"); + } + printf("C%d ",-index-nderivs*DOFFSET); + } + else{ + nderivs=index/DOFFSET; + posin_labels=intlist_find_err(labels.indices, labels.length, index-nderivs*DOFFSET); + label=labels.labels[posin_labels]; + for (i=0;i<14-label.length-nderivs;i++){ + printf(" "); + } + for(i=0;i<nderivs;i++){ + printf("d"); + } + printf("%s ",char_array_to_str_noinit(labels.labels+posin_labels)); + } + + return(0); +} diff --git a/src/flow.h b/src/flow.h new file mode 100644 index 0000000..baef992 --- /dev/null +++ b/src/flow.h @@ -0,0 +1,35 @@ +/* +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 flow numerically +*/ + +#ifndef NUMERICAL_FLOW_H +#define NUMERICAL_FLOW_H + + +#include "grouped_polynomial.h" +#include "rcc.h" + +// compute flow +int numerical_flow(Grouped_Polynomial flow_equation, RCC init, Labels labels, int niter, long double tol, int display_mode); +// single step +int step_flow(RCC* rccs, Grouped_Polynomial flow_equation, long double tol); + +// print the label of an rcc (takes constants and derivatives into account) +int print_label(int index, Labels labels); +#endif diff --git a/src/grouped_polynomial.c b/src/grouped_polynomial.c new file mode 100644 index 0000000..b7bea42 --- /dev/null +++ b/src/grouped_polynomial.c @@ -0,0 +1,765 @@ +/* +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 "grouped_polynomial.h" + +#include <stdio.h> +#include <stdlib.h> +#include "definitions.cpp" +#include "rational.h" +#include "istring.h" +#include "coefficient.h" +#include "polynomial.h" +#include "array.h" +#include "number.h" +#include "tools.h" + + +// allocate memory +int init_Grouped_Polynomial(Grouped_Polynomial* gpolynomial, int size){ + (*gpolynomial).coefs=calloc(size,sizeof(Coefficient)); + (*gpolynomial).indices=calloc(size,sizeof(int)); + (*gpolynomial).length=0; + (*gpolynomial).memory=size; + + return(0); +} + +// free memory +int free_Grouped_Polynomial(Grouped_Polynomial gpolynomial){ + int i; + for(i=0;i<gpolynomial.length;i++){ + free_Coefficient(gpolynomial.coefs[i]); + } + free(gpolynomial.coefs); + free(gpolynomial.indices); + + return(0); +} + +// resize the memory allocated to a grouped_polynomial +int resize_grouped_polynomial(Grouped_Polynomial* grouped_polynomial,int new_size){ + Grouped_Polynomial new_poly; + int i; + + init_Grouped_Polynomial(&new_poly,new_size); + for(i=0;i<(*grouped_polynomial).length;i++){ + new_poly.indices[i]=(*grouped_polynomial).indices[i]; + new_poly.coefs[i]=(*grouped_polynomial).coefs[i]; + } + new_poly.length=(*grouped_polynomial).length; + + free((*grouped_polynomial).indices); + free((*grouped_polynomial).coefs); + + *grouped_polynomial=new_poly; + return(0); +} + +// copy a grouped_polynomial +int grouped_polynomial_cpy(Grouped_Polynomial input, Grouped_Polynomial* output){ + init_Grouped_Polynomial(output,input.length); + grouped_polynomial_cpy_noinit(input,output); + return(0); +} +int grouped_polynomial_cpy_noinit(Grouped_Polynomial input, Grouped_Polynomial* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a grouped polynomial of length %d to another with memory %d\n",input.length,(*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + (*output).indices[i]=input.indices[i]; + coefficient_cpy(input.coefs[i], (*output).coefs+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a grouped_polynomial +int grouped_polynomial_append(int index, Coefficient coef, Grouped_Polynomial* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_grouped_polynomial(output,2*(*output).memory+1); + } + + // copy and allocate + (*output).indices[offset]=index; + coefficient_cpy(coef, (*output).coefs+offset); + //increment length + (*output).length++; + + return(0); +} +// append an element to a grouped_polynomial without allocating memory +int grouped_polynomial_append_noinit(int index, Coefficient coef, Grouped_Polynomial* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_grouped_polynomial(output,2*(*output).memory+1); + } + + // copy without allocating + (*output).indices[offset]=index; + (*output).coefs[offset]=coef; + // increment length + (*output).length++; + return(0); +} + +// concatenate two grouped_polynomials +int grouped_polynomial_concat(Grouped_Polynomial input, Grouped_Polynomial* output){ + int i; + for(i=0;i<input.length;i++){ + grouped_polynomial_append(input.indices[i],input.coefs[i],output); + } + return(0); +} +int grouped_polynomial_concat_noinit(Grouped_Polynomial input, Grouped_Polynomial* output){ + int i; + for(i=0;i<input.length;i++){ + grouped_polynomial_append_noinit(input.indices[i],input.coefs[i],output); + } + + // free input arrays + free(input.indices); + free(input.coefs); + return(0); +} + + +// construct a grouped polynomial from a polynomial, grouping together the terms specified in the id table +// robust algorithm: allows for a term in the polynomial to contribute to several id table entries +int group_polynomial(Polynomial polynomial, Grouped_Polynomial* grouped_polynomial, Id_Table idtable, Fields_Table fields){ + int i,j; + // what is left to group + Polynomial remainder; + int index; + Number ratio; + Number num; + Int_Array factor; + int security=0; + int pos; + coef_denom denom; + + // init remainder + polynomial_cpy(polynomial, &remainder); + + // allocate memory + init_Grouped_Polynomial(grouped_polynomial, idtable.length+1); + + // copy indices from idtable and allocate + // the constant term + (*grouped_polynomial).indices[0]=-1; + init_Coefficient((*grouped_polynomial).coefs, COEF_SIZE); + for(i=1;i<=idtable.length;i++){ + (*grouped_polynomial).indices[i]=idtable.indices[i-1]; + init_Coefficient((*grouped_polynomial).coefs+i, COEF_SIZE); + } + (*grouped_polynomial).length=idtable.length+1; + + // keep on going as long as there are terms in the remainder + while(remainder.length>0){ + // stop if the number of iterations exceeds 100 times the length of the polynomial + if(security >= 100*polynomial.length){ + fprintf(stderr,"error: polynomial could not be grouped in less than %d groupings\n", 100*polynomial.length); + exit(-1); + } + security++; + + // index of the last element + i=remainder.length-1; + + // find entry + if(remainder.monomials[i].length==0){ + // constant + index=-1; + } + else{ + // loop over entries + for(j=0,index=-2;j<idtable.length && index==-2;j++){ + // loop over terms in the polynomial + for(pos=0;pos<idtable.polynomials[j].length;pos++){ + if(int_array_cmp(idtable.polynomials[j].monomials[pos],remainder.monomials[i])==0){ + index=j; + break; + } + } + } + } + + 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){ + fprintf(stderr,","); + } + } + fprintf(stderr,") not found in idtable\n"); + exit(-1); + } + + // if not constant + if(index>=0){ + ratio=number_quot_ret(remainder.nums[i],idtable.polynomials[index].nums[pos]); + factor=remainder.factors[i]; + // add to coefficient + denom.index=-1; + denom.power=1; + coefficient_append(factor, ratio, denom, (*grouped_polynomial).coefs+index+1); + + // remove from remainder + free_Int_Array(remainder.monomials[i]); + // do not free factor yet + free_Number(remainder.nums[i]); + remainder.length--; + + // add terms from idtable with minus sign + for(j=0;j<idtable.polynomials[index].length;j++){ + if(j!=pos){ + num=number_prod_ret(ratio, idtable.polynomials[index].nums[j]); + number_Qprod_chain(quot(-1,1),&num); + polynomial_append(idtable.polynomials[index].monomials[j], factor, num, &remainder); + free_Number(num); + } + } + + free_Int_Array(factor); + free_Number(ratio); + + // simplify remainder + polynomial_simplify(&remainder, fields); + } + // constant + else if(index==-1){ + // add to coefficient + denom.index=-1; + denom.power=0; + coefficient_append(remainder.factors[i], remainder.nums[i], denom, (*grouped_polynomial).coefs); + // remove from remainder + free_Int_Array(remainder.monomials[i]); + free_Int_Array(remainder.factors[i]); + free_Number(remainder.nums[i]); + remainder.length--; + } + } + + // simplify the result + simplify_grouped_polynomial(grouped_polynomial); + + free_Polynomial(remainder); + return(0); +} + + +// construct a grouped polynomial from a polynomial, grouping together the terms specified in the id table. +// identifies sub-polynomials in the polynomial corresponding to the entire rhs of an entry in the id table. +// requires the polynomial and the idtable to be sorted +// can only treat cases in which monomials in different polynomials of the idtable are distinct +int group_polynomial_pickandchoose(Polynomial polynomial, Grouped_Polynomial* grouped_polynomial, Id_Table idtable){ + int i,j,k; + // a mask specifying which terms of the polynomial have already been grouped + int* mask=calloc(polynomial.length, sizeof(int)); + int index; + Number ratio, ratio_check; + // whether ratio was ever allocated + int alloc_ratio=0; + // whether the correct index was found + int found_index; + int start_index_search; + Int_Array mask_tmp_flips; + coef_denom denom; + + // allocate memory + init_Grouped_Polynomial(grouped_polynomial, idtable.length+1); + + // copy indices from idtable and allocate + // the constant term + (*grouped_polynomial).indices[0]=-1; + init_Coefficient((*grouped_polynomial).coefs, COEF_SIZE); + for(i=1;i<=idtable.length;i++){ + (*grouped_polynomial).indices[i]=idtable.indices[i-1]; + init_Coefficient((*grouped_polynomial).coefs+i, COEF_SIZE); + } + (*grouped_polynomial).length=idtable.length+1; + + // loop over monomials + for(i=0;i<polynomial.length;i++){ + // check that the term hasn't already been added + if(mask[i]==0){ + // loop until the correct index is found (the polynomial must contain all the terms in the index and the numerical factors must match) + found_index=0; + start_index_search=0; + while(found_index==0){ + found_index=1; + // find entry + index=find_id(polynomial.monomials[i], idtable,start_index_search); + // easier to debug if the error is here instead of inside find_id + if(index==-2){ + fprintf(stderr,"error: monomial not found in idtable\n"); + exit(-1); + } + + // if not constant + if(index>=0){ + // a vector in which to store the indices that were masked + init_Int_Array(&mask_tmp_flips,idtable.polynomials[index].length); + + // loop over all monomials in that entry of the idtable + for(j=0;j<idtable.polynomials[index].length && found_index==1;j++){ + // find the monomial in the polynomial + for(k=i;k<polynomial.length;k++){ + // only check if mask==0 + // only check if the factors are correct + if(mask[k]==0 && int_array_cmp(polynomial.factors[i],polynomial.factors[k])==0 && int_array_cmp(idtable.polynomials[index].monomials[j],polynomial.monomials[k])==0){ + ratio_check=number_quot_ret(polynomial.nums[k],idtable.polynomials[index].nums[j]); + + // if the factors don't factor + if(alloc_ratio!=0 && number_compare(ratio,ratio_check)==0){ + found_index=0; + break; + } + // check that ratio was allocated + if(alloc_ratio!=0){ + free_Number(ratio); + } + ratio=ratio_check; + alloc_ratio=1; + + // added to polynomial + mask[k]=1; + // keep track of the flips so that they can be undone if the index turns out to be incorrect + int_array_append(k,&mask_tmp_flips); + break; + } + } + + // error if the monomial could not be found + if(k==polynomial.length){ + found_index=0; + } + } + + // if the index was incorrect + if(found_index==0){ + // reset mask + for(j=0;j<mask_tmp_flips.length;j++){ + mask[mask_tmp_flips.values[j]]=0; + } + // start index search at next item + start_index_search=index+1; + } + else{ + // add to grouped polynomial + denom.index=-1; + denom.power=1; + coefficient_append(polynomial.factors[i], ratio, denom, (*grouped_polynomial).coefs+index+1); + } + + if(alloc_ratio==1){ + free_Number(ratio); + alloc_ratio=0; + } + free_Int_Array(mask_tmp_flips); + } + // constant + else if(index==-1){ + mask[i]=1; + denom.index=-1; + denom.power=0; + coefficient_append(polynomial.factors[i], polynomial.nums[i], denom, (*grouped_polynomial).coefs); + } + } + } + } + + // check all the terms were grouped + for(i=0;i<polynomial.length;i++){ + if(mask[i]==0){ + fprintf(stderr,"error: this polynomial could not be grouped: no matches were found for some of the terms\n"); + exit(-1); + } + } + + free(mask); + return(0); +} + + +// find the entry in the idtable containing monomial +// start search at the specified index +int find_id(Int_Array monomial, Id_Table idtable, int start){ + int i,j; + + // constant + if(monomial.length==0){ + return(-1); + } + + // loop over entries + for(i=start;i<idtable.length;i++){ + // loop over terms in the polynomial + for(j=0;j<idtable.polynomials[i].length;j++){ + if(int_array_cmp(idtable.polynomials[i].monomials[j],monomial)==0){ + return(i); + } + } + } + + return(-2); +} + + +// simplify grouped polynomial +int simplify_grouped_polynomial(Grouped_Polynomial* polynomial){ + int i; + for(i=0;i<(*polynomial).length;i++){ + coefficient_simplify((*polynomial).coefs+i); + } + return(0); +} + + +// derive 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){ + int i,j,k; + Coefficient tmp_coef; + + // alloc + init_Grouped_Polynomial(dflow, flow_equation.length); + + // for each equation + for(i=0;i<flow_equation.length;i++){ + // copy indices + if(flow_equation.indices[i]>=0){ + (*dflow).indices[i]=flow_equation.indices[i]+DOFFSET; + } + else{ + (*dflow).indices[i]=flow_equation.indices[i]-DOFFSET; + } + + init_Coefficient((*dflow).coefs+i, COEF_SIZE); + // for each index + for(j=0;j<indices.length;j++){ + coefficient_deriv(flow_equation.coefs[i], indices.values[j], &tmp_coef); + // multiply each coefficient by the appropriate dl[j] + for(k=0;k<tmp_coef.length;k++){ + // only in non-trivial cases + if(number_is_zero(tmp_coef.nums[k])==0){ + // non-constants + if(indices.values[j]>=0){ + int_array_append(DOFFSET + indices.values[j], tmp_coef.factors+k); + } + // constants are offset with -doffset (so that the derivatives of constants also have a negative index) + else{ + int_array_append(-DOFFSET + indices.values[j], tmp_coef.factors+k); + } + } + } + + // add to output + coefficient_concat_noinit(tmp_coef, (*dflow).coefs+i); + } + } + + (*dflow).length=flow_equation.length; + + return(0); +} + + +/* +// derive a flow equation with respect to an index +int flow_equation_deriv(Grouped_Polynomial flow_equation, int index, Grouped_Polynomial* output){ + int i,k; + // temp list of indices + Int_Array factor; + // number of times index was found + int match_count; + coef_denom denom; + // store the computation of the derivative of the constant + int previous_constant_index=0; + Coefficient dC; + Coefficient tmp_coef; + + init_Grouped_Polynomial(output, flow_equation.length); + + // loop over equations + for(k=0;k<flow_equation.length;k++){ + init_Coefficient((*output).coefs+k, COEF_SIZE); + + // loop over monomials + for(i=0;i<flow_equation.coefs[k].length;i++){ + + // derivative of the numerator + monomial_deriv(flow_equation.coefs[k].factors[i], index, &factor, &match_count); + + // if the derivative doesn't vanish, add it to the coefficient + if(match_count>0){ + coefficient_append_noinit(factor,number_Qprod_ret(quot(match_count,1),flow_equation.coefs[k].nums[i]), flow_equation.coefs[k].denoms[i], (*output).coefs+k); + } + else{ + free_Int_Array(factor); + } + + // derivative of the denominator + if(flow_equation.coefs[k].denoms[i].power>0){ + // check whether the derivative was already computed + if(flow_equation.coefs[k].denoms[i].index!=previous_constant_index){ + // if not first, then free + if(previous_constant_index!=0){ + free_Coefficient(dC); + previous_constant_index=0; + } + init_Coefficient(&dC,COEF_SIZE); + coefficient_deriv_noinit(flow_equation.coefs[intlist_find_err(flow_equation.indices, flow_equation.length, flow_equation.coefs[k].denoms[i].index)], index, &dC); + previous_constant_index=flow_equation.coefs[k].denoms[i].index; + } + + init_Coefficient(&tmp_coef, dC.length); + coefficient_append(flow_equation.coefs[k].factors[i], number_Qprod_ret(quot(-flow_equation.coefs[k].denoms[i].power,1), flow_equation.coefs[k].nums[i]), flow_equation.coefs[k].denoms[i], &tmp_coef); + (tmp_coef.denoms[0].power)++; + + coefficient_prod_chain(dC, &tmp_coef); + + coefficient_concat_noinit(tmp_coef, (*output).coefs+k); + } + } + + // memory safe + if((*output).coefs[k].length>0){ + coefficient_simplify((*output).coefs+k); + } + else{ + // add a trivial element to the coefficient + init_Int_Array(&factor,0); + denom.index=-1; + denom.power=0; + coefficient_append_noinit(factor,number_zero(),denom,(*output).coefs+k); + } + } + + free_Coefficient(dC); + return(0); +} +*/ + + +// print a grouped polynomial +// prepend the indices on the left side with lhs_pre, and those on the right by rhs_pre +int grouped_polynomial_print(Grouped_Polynomial grouped_polynomial, char lhs_pre, char rhs_pre){ + int i,j; + Char_Array buffer; + int dcount; + + // for each equation + for(i=0;i<grouped_polynomial.length;i++){ + //print lhs + // negative indices are constants + if(grouped_polynomial.indices[i]<0){ + // count derivatives + dcount=-grouped_polynomial.indices[i]/DOFFSET; + for(j=0;j<3-dcount;j++){ + printf(" "); + } + printf("["); + for(j=0;j<dcount;j++){ + printf("d"); + } + printf("C%d] =",-grouped_polynomial.indices[i]-dcount*DOFFSET); + } + else{ + // count derivatives + dcount=grouped_polynomial.indices[i]/DOFFSET; + for(j=0;j<2-dcount;j++){ + printf(" "); + } + printf("["); + for(j=0;j<dcount;j++){ + printf("d"); + } + printf("%c%2d] =",lhs_pre,grouped_polynomial.indices[i]-dcount*DOFFSET); + } + + // rhs + init_Char_Array(&buffer, STR_SIZE); + coefficient_sprint(grouped_polynomial.coefs[i],&buffer,9,rhs_pre); + if(buffer.length>0){ + printf("%s",buffer.str); + } + free_Char_Array(buffer); + + if(i<grouped_polynomial.length-1){ + printf(","); + } + // extra \n + printf("\n"); + } + return(0); +} + +// read from string +#define PP_NULL_MODE 0 +#define PP_COEF_MODE 1 +#define PP_INDEX_MODE 3 +#define PP_COMMENT_MODE 4 +#define PP_BRACKET_MODE 5 +#define PP_CONSTANT_MODE 6 +int char_array_to_Grouped_Polynomial(Char_Array str, Grouped_Polynomial* output){ + // buffer + char* buffer=calloc(str.length+1,sizeof(char)); + char* buffer_ptr=buffer; + int index=-2; + Coefficient coef; + int i,j; + int mode; + int dcount=0; + + init_Grouped_Polynomial(output, EQUATION_SIZE); + + // loop over input + mode=PP_NULL_MODE; + for(j=0;j<str.length;j++){ + if(mode==PP_COMMENT_MODE){ + if(str.str[j]=='\n'){ + mode=PP_NULL_MODE; + } + } + // stay in polynomial mode until ',' + else if(mode==PP_COEF_MODE){ + if(str.str[j]==','){ + // parse polynomial + str_to_Coefficient(buffer, &coef); + // write index and polynomial + grouped_polynomial_append_noinit(index, coef, output); + mode=PP_NULL_MODE; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,str.str[j]); + } + } + else{ + switch(str.str[j]){ + // index + case '[': + if(mode==PP_NULL_MODE){ + mode=PP_BRACKET_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + // reset derivatives count + dcount=0; + } + break; + case '%': + if(mode==PP_BRACKET_MODE){ + mode=PP_INDEX_MODE; + } + break; + // constant term + case 'C': + if(mode==PP_BRACKET_MODE){ + mode=PP_CONSTANT_MODE; + } + break; + // derivatives + case 'd': + if(mode==PP_BRACKET_MODE || mode==PP_INDEX_MODE || mode==PP_CONSTANT_MODE){ + dcount++; + } + break; + // write index + case ']': + sscanf(buffer,"%d",&i); + if(mode==PP_INDEX_MODE){ + index=i+dcount*DOFFSET; + } + else if(mode==PP_CONSTANT_MODE){ + index=-i-dcount*DOFFSET; + } + mode=PP_NULL_MODE; + + break; + + // coef mode + case '=': + if(mode==PP_NULL_MODE){ + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_COEF_MODE; + } + break; + + // comment + case '#': + mode=PP_COMMENT_MODE; + break; + + default: + if(mode!=PP_NULL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str.str[j]); + } + break; + } + } + } + + // last step + if(mode==PP_COEF_MODE){ + str_to_Coefficient(buffer, &coef); + grouped_polynomial_append_noinit(index, coef, output); + } + + free(buffer); + return(0); +} + + +// evaluate an equation on a vector +int evaleq(RCC* rccs, Grouped_Polynomial poly){ + int i; + long double* res=calloc((*rccs).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); + exit(-1); + } + + // initialize vectors to 0 + for(i=0;i<(*rccs).length;i++){ + res[i]=0.; + } + + // for each equation + for(i=0;i<poly.length;i++){ + evalcoef(*rccs, poly.coefs[i], res+i); + } + + // copy res to rccs + for(i=0;i<(*rccs).length;i++){ + (*rccs).values[i]=res[i]; + } + + // free memory + free(res); + return(0); + +} + diff --git a/src/grouped_polynomial.h b/src/grouped_polynomial.h new file mode 100644 index 0000000..3c38f1b --- /dev/null +++ b/src/grouped_polynomial.h @@ -0,0 +1,74 @@ +/* +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. +*/ + +/* +Polynomials can be represented in a grouped way, by putting the terms + proportional to the same monomial together. + +The main part of a grouped polynomial is the list of coefficients, + each of which stands for the set of terms proportional to the + corresponding monomial, specified in indices and labels. + +*/ + +#ifndef GROUPED_POLYNOMIAL_H +#define GROUPED_POLYNOMIAL_H + +#include "types.h" + +// memory +int init_Grouped_Polynomial(Grouped_Polynomial* gpolynomial, int size); +int free_Grouped_Polynomial(Grouped_Polynomial gpolynomial); + +// resize the memory allocated to a grouped polynomial +int resize_grouped_polynomial(Grouped_Polynomial* grouped_polynomial,int new_size); + +// copy a grouped polynomial +int grouped_polynomial_cpy(Grouped_Polynomial input, Grouped_Polynomial* output); +int grouped_polynomial_cpy_noinit(Grouped_Polynomial input, Grouped_Polynomial* output); + +// append an element to a polynomial +int grouped_polynomial_append(int index, Coefficient coef, Grouped_Polynomial* output); +int grouped_polynomial_append_noinit(int index, Coefficient coef, Grouped_Polynomial* output); + +// concatenate two polynomials +int grouped_polynomial_concat(Grouped_Polynomial input, Grouped_Polynomial* output); +int grouped_polynomial_concat_noinit(Grouped_Polynomial input, Grouped_Polynomial* output); + +// construct a grouped polynomial from a polynomial, grouping together the terms specified in the id table. +int group_polynomial(Polynomial polynomial, Grouped_Polynomial* grouped_polynomial, Id_Table idtable, Fields_Table fields); +// more naive and faster version in which the terms in polynomial corresponding to a polynomial in the id table are grouped together (does not allow parts of terms to be grouped together) +int group_polynomial_pickandchoose(Polynomial polynomial, Grouped_Polynomial* grouped_polynomial, Id_Table idtable); + +// find the entry in the idtable containing monomial +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 +int flow_equation_derivx(Grouped_Polynomial flow_equation, Int_Array indices, Grouped_Polynomial* dflow); + +// print a grouped polynomial +int grouped_polynomial_print(Grouped_Polynomial grouped_polynomial, char lhs_pre, char rhs_pre); + +// read from string +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); + +#endif diff --git a/src/idtable.c b/src/idtable.c new file mode 100644 index 0000000..fe409c2 --- /dev/null +++ b/src/idtable.c @@ -0,0 +1,122 @@ +/* +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 "idtable.h" +#include <stdio.h> +#include <stdlib.h> +#include "array.h" +#include "polynomial.h" + +// allocate memory +int init_Id_Table(Id_Table* idtable,int size){ + (*idtable).indices=calloc(size,sizeof(int)); + (*idtable).polynomials=calloc(size,sizeof(Polynomial)); + (*idtable).length=0; + (*idtable).memory=size; + return(0); +} + +// free memory +int free_Id_Table(Id_Table idtable){ + int i; + for(i=0;i<idtable.length;i++){ + free_Polynomial(idtable.polynomials[i]); + } + free(idtable.indices); + free(idtable.polynomials); + + return(0); +} + +// resize the memory allocated to a idtable +int resize_idtable(Id_Table* idtable,int new_size){ + Id_Table new_idtable; + int i; + + init_Id_Table(&new_idtable,new_size); + for(i=0;i<(*idtable).length;i++){ + new_idtable.indices[i]=(*idtable).indices[i]; + new_idtable.polynomials[i]=(*idtable).polynomials[i]; + } + new_idtable.length=(*idtable).length; + + free((*idtable).indices); + free((*idtable).polynomials); + + *idtable=new_idtable; + return(0); +} + +// copy an idtable +int idtable_cpy(Id_Table input, Id_Table* output){ + init_Id_Table(output,input.length); + idtable_cpy_noinit(input,output); + return(0); +} +int idtable_cpy_noinit(Id_Table input, Id_Table* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy an idtable of length %d to another with memory %d\n",input.length,(*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + (*output).indices[i]=input.indices[i]; + polynomial_cpy(input.polynomials[i],(*output).polynomials+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a idtable +int idtable_append(int index, Polynomial polynomial, Id_Table* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_idtable(output,2*(*output).memory); + } + + // copy and allocate + polynomial_cpy(polynomial,(*output).polynomials+offset); + (*output).indices[offset]=index; + // increment length + (*output).length++; + return(0); +} +// append an element to a idtable without allocating memory +int idtable_append_noinit(int index, Polynomial polynomial, Id_Table* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_idtable(output,2*(*output).memory); + } + + // copy without allocating + (*output).indices[offset]=index; + (*output).polynomials[offset]=polynomial; + // increment length + (*output).length++; + return(0); +} + +// concatenate two idtables +int idtable_concat(Id_Table input, Id_Table* output){ + int i; + for(i=0;i<input.length;i++){ + idtable_append(input.indices[i],input.polynomials[i],output); + } + return(0); +} diff --git a/src/idtable.h b/src/idtable.h new file mode 100644 index 0000000..38ab249 --- /dev/null +++ b/src/idtable.h @@ -0,0 +1,44 @@ +/* +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. +*/ + +/* correspondence table to group a polynomial into a flow equation */ + +#ifndef IDTABLE_H +#define IDTABLE_H + +#include "types.h" + +// allocate memory +int init_Id_Table(Id_Table* idtable,int size); +// free memory +int free_Id_Table(Id_Table idtable); + +// resize the memory allocated to a idtable +int resize_idtable(Id_Table* idtable,int new_size); + +// copy an idtable +int idtable_cpy(Id_Table input, Id_Table* output); +int idtable_cpy_noinit(Id_Table input, Id_Table* output); + +// append an element to a idtable +int idtable_append(int index, Polynomial polynomial, Id_Table* output); +int idtable_append_noinit(int index, Polynomial polynomial, Id_Table* output); + +// concatenate two idtables +int idtable_concat(Id_Table input, Id_Table* output); + +#define IDTABLE_H_DONE +#endif diff --git a/src/istring.c b/src/istring.c new file mode 100644 index 0000000..663c06a --- /dev/null +++ b/src/istring.c @@ -0,0 +1,99 @@ +/* +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 <stdlib.h> +#include "istring.h" + +char* str_concat(char* ptr, const char* str){ + char* str_ptr=(char*)str; + + while(*str_ptr!='\0'){ + *ptr=*str_ptr; + ptr++; + str_ptr++; + } + *ptr='\0'; + return(ptr); +} + +int str_concat_memorysafe(char** str_out, int pos, const char* str, int* memory){ + char* out_ptr; + + if(str_len((char*)str)+pos>=*memory){ + *memory=*memory+str_len((char*)str)+pos+1; + resize_str(str_out,*memory); + } + out_ptr=*str_out+pos; + str_concat(out_ptr,str); + return(0); +} + +int resize_str(char** out, int memory){ + char* tmp_str=calloc(memory,sizeof(char)); + char* tmp_ptr=tmp_str; + char* out_ptr=*out; + + for(;*out_ptr!='\0';out_ptr++,tmp_ptr++){ + *tmp_ptr=*out_ptr; + } + *tmp_ptr='\0'; + + free(*out); + *out=tmp_str; + return(0); +} + +char* str_addchar(char* ptr, const char c){ + *ptr=c; + ptr++; + *ptr='\0'; + return(ptr); +} + +int str_len(char* str){ + char* ptr=str; + int ret=0; + while(*ptr!='\0'){ret++;ptr++;} + return(ret); +} + +int str_cmp(char* str1, char* str2){ + char* ptr1=str1; + char* ptr2=str2; + while(*ptr1==*ptr2 && *ptr1!='\0' && *ptr2!='\0'){ + ptr1++; + ptr2++; + } + if(*ptr1=='\0' && *ptr2=='\0'){ + return(1); + } + else{ + return(0); + } +} + + +int str_cpy_noalloc(char* input, char* output){ + char* ptr; + char* out_ptr; + + for(ptr=input,out_ptr=output;*ptr!='\0';ptr++,out_ptr++){ + *out_ptr=*ptr; + } + *out_ptr='\0'; + return(0); +} + diff --git a/src/istring.h b/src/istring.h new file mode 100644 index 0000000..5b47b9b --- /dev/null +++ b/src/istring.h @@ -0,0 +1,40 @@ +/* +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. +*/ + +/* +String manipulation +*/ + +#ifndef ISTRING_H +#define ISTRING_H + +// concatenate str at the position pointed to by ptr, and return a pointer +// to the end of the new string +char* str_concat(char* ptr, const char* str); +// concatenate strings and resize them if necessary +int str_concat_memorysafe(char** str_out, int pos, const char* str, int* memory); +// resize a string +int resize_str(char** out, int memory); +// idem with a single character +char* str_addchar(char* ptr, const char c); +// string length +int str_len(char* str); +// compare strings +int str_cmp(char* str1, char* str2); +// copy a string to another without allocating memory +int str_cpy_noalloc(char* input, char* output); + +#endif diff --git a/src/kondo.c b/src/kondo.c new file mode 100644 index 0000000..c86b4b3 --- /dev/null +++ b/src/kondo.c @@ -0,0 +1,1449 @@ +/* +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 "kondo.h" +#include <stdlib.h> +#include <stdio.h> + +#include "idtable.h" +#include "array.h" +#include "number.h" +#include "istring.h" +#include "cli_parser.h" +#include "fields.h" +#include "parse_file.h" +#include "polynomial.h" +#include "definitions.cpp" +#include "rational.h" + +// dimension of A, B and h (must be <10) +#define KONDO_DIM 3 +// number of spin components +#define KONDO_SPIN 2 + +// offsets for indices of A, B and h +// order matters for symbols table +#define KONDO_A_OFFSET 1 +#define KONDO_B_OFFSET 2 +#define KONDO_H_OFFSET 3 + +// parsing modes (from parse_file.c) +#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 +// indices +#define PP_INDEX_MODE 10 +// factors or monomials +#define PP_BRACKET_MODE 11 +// labels +#define PP_LABEL_MODE 12 +// polynomial +#define PP_POLYNOMIAL_MODE 13 +// field scalar product +#define PP_FIELD_SCALAR_MODE 14 +#define PP_FIELD_VECTOR_PROD_MODE 15 + + + +// generate configuration file +int kondo_generate_conf(Str_Array* str_args, int box_count){ + Str_Array new_args; + Fields_Table fields; + Char_Array tmp_str; + int arg_index; + int i; + Char_Array title; + + init_Str_Array(&new_args,8); + + // fields + 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); + 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); + str_array_append_noinit(tmp_str, &new_args); + + // identities + kondo_identities(&tmp_str); + arg_index=find_str_arg("identities", *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_identities(tmp_str, &fields); + str_array_append_noinit(tmp_str, &new_args); + + // groups + kondo_groups(&tmp_str, box_count); + str_array_append_noinit(tmp_str, &new_args); + + + // propagator + arg_index=find_str_arg("propagator", *str_args); + if(arg_index>=0){ + kondo_propagator((*str_args).strs[arg_index], &tmp_str); + str_array_append_noinit(tmp_str, &new_args); + } + + // input polynomial + arg_index=find_str_arg("input_polynomial", *str_args); + if(arg_index>=0){ + kondo_input_polynomial((*str_args).strs[arg_index], &tmp_str, fields, box_count); + str_array_append_noinit(tmp_str, &new_args); + } + + // id table + arg_index=find_str_arg("id_table", *str_args); + if(arg_index>=0){ + kondo_idtable((*str_args).strs[arg_index], &tmp_str, fields); + str_array_append_noinit(tmp_str, &new_args); + } + + // 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 &&\ + str_cmp(title.str, "identities")==0 &&\ + str_cmp(title.str, "propagator")==0 &&\ + str_cmp(title.str, "input_polynomial")==0 &&\ + str_cmp(title.str, "id_table")==0 ){ + + char_array_cpy((*str_args).strs[i], &tmp_str); + str_array_append_noinit(tmp_str, &new_args); + } + free_Char_Array(title); + } + + free_Fields_Table(fields); + free_Str_Array(*str_args); + *str_args=new_args; + + return(0); +} + + +// generate the Kondo fields table +int kondo_fields_table(int box_count, Char_Array* str_fields, Fields_Table* fields){ + int i,j; + + init_Char_Array(str_fields,STR_SIZE); + char_array_snprintf(str_fields, "#!fields\n"); + + // external fields + char_array_append_str("x:",str_fields); + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_fields, "%d,%d", 10*(i+10*KONDO_A_OFFSET), 10*(i+10*KONDO_B_OFFSET)); + if(i<KONDO_SPIN-1){ + char_array_append(',',str_fields); + } + } + char_array_append('\n',str_fields); + + // internal fields: A + char_array_append_str("i:",str_fields); + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_A_OFFSET)+j); + char_array_append(',',str_fields); + } + } + // B + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=2;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_B_OFFSET)+j); + if(i<KONDO_SPIN-1 || j<2){ + char_array_append(',',str_fields); + } + } + } + char_array_append('\n',str_fields); + + // parameters + char_array_append_str("h:",str_fields); + for(i=0;i<KONDO_DIM;i++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_H_OFFSET)); + if(i<KONDO_DIM-1){ + char_array_append(',',str_fields); + } + } + char_array_append('\n',str_fields); + + // declare Fermions + char_array_append_str("f:",str_fields); + // external fields + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_fields, "%d,%d", 10*(i+10*KONDO_A_OFFSET), 10*(i+10*KONDO_B_OFFSET)); + char_array_append(',',str_fields); + } + // internal fields: A + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_A_OFFSET)+j); + char_array_append(',',str_fields); + } + } + // B + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=2;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_B_OFFSET)+j); + if(i<KONDO_SPIN-1 || j<2){ + char_array_append(',',str_fields); + } + } + } + char_array_append('\n',str_fields); + + // parse fields table + parse_input_fields(*str_fields, fields); + + return(0); +} + + +// generate Kondo symbols +int kondo_symbols(Char_Array* str_symbols, 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"); + + // loop over box index + for(i=1;i<=box_count;i++){ + // loop over letters + for(j=0;j<2;j++){ + // 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); + // 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); + // compute corresponding polynomial + kondo_resolve_ABh(tmp_str.str, &poly, *fields); + free_Char_Array(tmp_str); + // write to output + polynomial_sprint(poly, str_symbols); + free_Polynomial(poly); + // add , + char_array_snprintf(str_symbols,",\n"); + } + } + } + + // scalar products + // loop over box index + for(i=1;i<=box_count;i++){ + // loop over letters + 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); + for(l=0;l<KONDO_DIM;l++){ + char_array_snprintf(str_symbols, "(1)"); + if(j<2){ + char_array_snprintf(str_symbols,"[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)); + } + if(k<2){ + char_array_snprintf(str_symbols,"[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)); + } + + if(l<KONDO_DIM-1){ + char_array_append('+',str_symbols); + } + } + // add , + char_array_snprintf(str_symbols,",\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); + 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)); + if(l<KONDO_DIM-1){ + char_array_append('+',str_symbols); + } + } + + // add , + if(i<box_count){ + char_array_snprintf(str_symbols,",\n"); + } + } + + + return(0); +} + +// 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){ + int i,j,k; + 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"); + + // loop over box index + for(i=1;i<=box_count;i++){ + // loop over letters + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + // write index + char_array_snprintf(str_symbols, "%d=", 100*(10*(KONDO_A_OFFSET+j)+KONDO_A_OFFSET+k)+i); + // write the name of the scalar product + init_Char_Array(&tmp_str, 6); + char_array_snprintf(&tmp_str, "%c%d.%c%d", letters[j], i, letters[k], i); + // compute corresponding polynomial + kondo_resolve_scalar_prod(tmp_str.str, &poly, *fields); + free_Char_Array(tmp_str); + // write to output + polynomial_sprint(poly, str_symbols); + free_Polynomial(poly); + // add , + if(i<box_count || j<2 || k<2){ + char_array_snprintf(str_symbols,",\n"); + } + } + } + } + + parse_input_symbols(*str_symbols, fields); + + return(0); +} + + +// generate Kondo groups (groups of independent variables) +int kondo_groups(Char_Array* str_groups, int box_count){ + int i,j; + + init_Char_Array(str_groups, STR_SIZE); + char_array_snprintf(str_groups, "#!groups\n"); + char_array_append('(',str_groups); + for(i=0;i<KONDO_DIM;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_groups, "%d",100*(10*KONDO_A_OFFSET+i)+j); + if(j<box_count || i<KONDO_DIM-1){ + char_array_append(',',str_groups); + } + } + } + char_array_append(')',str_groups); + char_array_append('\n',str_groups); + + char_array_append('(',str_groups); + for(i=0;i<KONDO_DIM;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_groups, "%d",100*(10*KONDO_B_OFFSET+i)+j); + if(j<box_count || i<KONDO_DIM-1){ + char_array_append(',',str_groups); + } + } + } + char_array_append(')',str_groups); + char_array_append('\n',str_groups); + return(0); +} + + +// generate Kondo identities +// h_3^2=1-h_1^2-h_2^2 +int kondo_identities(Char_Array* str_identities){ + int i; + + init_Char_Array(str_identities,STR_SIZE); + char_array_snprintf(str_identities, "#!identities\n"); + + char_array_snprintf(str_identities, "[f%d][f%d]=(1)",10*(KONDO_DIM-1+10*KONDO_H_OFFSET),10*(KONDO_DIM-1+10*KONDO_H_OFFSET)); + for(i=0;i<KONDO_DIM-1;i++){ + char_array_snprintf(str_identities, "+(-1)[f%d][f%d]",10*(i+10*KONDO_H_OFFSET),10*(i+10*KONDO_H_OFFSET)); + } + + return(0); +} + + +// convert the Kondo propagator +int kondo_propagator(Char_Array str_kondo_propagator, Char_Array* str_propagator){ + int i,j; + // buffer + char* buffer=calloc(str_kondo_propagator.length+1,sizeof(char)); + char* buffer_ptr=buffer; + // offset and index for each element + int offset[2]={-1,-1}; + int index[2]={-1,-1}; + int mode; + int comment=0; + + // allocate memory + init_Char_Array(str_propagator,STR_SIZE); + + // reproduce the loop from parse_input_propagatore but merely copy values, and replace indices + mode=PP_INDEX_MODE; + for(j=0;j<str_kondo_propagator.length;j++){ + if(comment==1){ + // write comments to str + char_array_append(str_kondo_propagator.str[j],str_propagator); + if(str_kondo_propagator.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_kondo_propagator.str[j]){ + // indices + case ';': + if(mode==PP_INDEX_MODE){ + get_offset_index(buffer,offset,index); + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case ':': + if(mode==PP_INDEX_MODE){ + get_offset_index(buffer,offset+1,index+1); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_NUMBER_MODE; + } + break; + + // num + case ',': + if(mode==PP_NUMBER_MODE && offset[0]>=0 && offset[1]>=0 && index[0]>=0 && index[1]>=0){ + // write indices and num + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_propagator,"%d;%d:%s,",10*(i+10*offset[0])+index[0], 10*(i+10*offset[1])+index[1], buffer); + } + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_INDEX_MODE; + } + break; + + // comment + case '#': + comment=1; + char_array_append(str_kondo_propagator.str[j],str_propagator); + break; + + // ignore line breaks + case '\n': break; + + default: + buffer_ptr=str_addchar(buffer_ptr,str_kondo_propagator.str[j]); + break; + } + } + } + + // last step + if(mode==PP_NUMBER_MODE){ + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_propagator,"%d;%d:%s",10*(i+10*offset[0])+index[0], 10*(i+10*offset[1])+index[1], buffer); + if(i<KONDO_SPIN-1){ + char_array_append(',',str_propagator); + } + } + } + + free(buffer); + return(0); + +} + + +// convert Kondo input polynomial +int kondo_input_polynomial(Char_Array str_kondo_polynomial, Char_Array* str_polynomial, Fields_Table fields, int box_count){ + Polynomial tmp_poly; + Polynomial out_poly; + Char_Array tmp_str_kondo_polynomial; + int i; + // whether there is a '%' in the input polynomial + int star=0; + + init_Char_Array(str_polynomial, STR_SIZE); + char_array_snprintf(str_polynomial, "#!input_polynomial\n"); + + // check for a '%' + for(i=0;i<str_kondo_polynomial.length;i++){ + if(str_kondo_polynomial.str[i]=='%'){ + star=1; + break; + } + } + + // if there is a '%', then take a product over boxes + if(star==1){ + // product over i from 1 to box_count + for(i=1;i<=box_count;i++){ + // replace '%' with the appropriate index + replace_star('0'+i,str_kondo_polynomial, &tmp_str_kondo_polynomial); + // read polynomial + parse_kondo_polynomial_factors(tmp_str_kondo_polynomial, &tmp_poly, fields); + + // product + if(i==1){ + polynomial_cpy(tmp_poly,&out_poly); + } + else{ + polynomial_prod_chain(tmp_poly,&out_poly, fields); + } + + free_Polynomial(tmp_poly); + free_Char_Array(tmp_str_kondo_polynomial); + } + } + // if no '%' then read polynomial as is + else{ + parse_kondo_polynomial_factors(str_kondo_polynomial, &out_poly, fields); + } + + // useful simplification + remove_unmatched_plusminus(&out_poly, fields); + polynomial_sprint(out_poly, str_polynomial); + free_Polynomial(out_poly); + return(0); +} + + +// convert the Kondo idtable +int kondo_idtable(Char_Array str_kondo_idtable, Char_Array* str_idtable, Fields_Table fields){ + int j; + // buffer + char* buffer=calloc(str_kondo_idtable.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Polynomial tmp_poly; + int mode; + + // allocate memory + init_Char_Array(str_idtable,STR_SIZE); + + // reproduce the loop from parse_input_id_table but merely copy labels and indices, and replace Kondo polynomials + mode=PP_INDEX_MODE; + for(j=0;j<str_kondo_idtable.length;j++){ + // unless inside a polynomial write to output + if(mode!=PP_POLYNOMIAL_MODE){ + char_array_append(str_kondo_idtable.str[j],str_idtable); + } + + switch(str_kondo_idtable.str[j]){ + // end polynomial mode + case ',': + if(mode==PP_POLYNOMIAL_MODE){ + mode=PP_INDEX_MODE; + // write polynomial + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + polynomial_sprint(tmp_poly, str_idtable); + free_Polynomial(tmp_poly); + char_array_append(',',str_idtable); + } + break; + + case ':': + if(mode==PP_INDEX_MODE){ + mode=PP_POLYNOMIAL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + + default: + if(mode==PP_POLYNOMIAL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str_kondo_idtable.str[j]); + } + break; + } + } + + //last step + if(mode==PP_POLYNOMIAL_MODE){ + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + polynomial_sprint(tmp_poly, str_idtable); + free_Polynomial(tmp_poly); + } + + free(buffer); + return(0); +} + +// read a product of polynomials +int parse_kondo_polynomial_factors(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 '*': + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + 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 + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + if((*output).length==0){ + polynomial_concat(tmp_poly, output); + } + else{ + polynomial_prod_chain(tmp_poly, output, fields); + } + free_Polynomial(tmp_poly); + + free(buffer); + return(0); +} + + +// read a kondo polynomial and convert it to a polynomial expressed in terms of the fields in the fields table +int parse_kondo_polynomial_str(char* str_polynomial, Polynomial* output, Fields_Table fields){ + // input pointer + char* polynomial_ptr; + // buffer + char* buffer=calloc(str_len(str_polynomial),sizeof(char)); + char* buffer_ptr=buffer; + int mode; + int comment=0; + int parenthesis_count=0; + int i; + int offset1, offset2; + int index; + Polynomial tmp_poly; + Number tmp_num, tmp1_num; + Int_Array tmp_factor, tmp_monomial, dummy_factor; + Polynomial scalar_prod_poly; + + // allocate memory + init_Polynomial(output,POLY_SIZE); + + init_Polynomial(&tmp_poly,MONOMIAL_SIZE); + tmp_num=number_one(); + init_Int_Array(&tmp_factor, MONOMIAL_SIZE); + + *buffer_ptr='\0'; + // loop over the input polynomial + // start in null mode + mode=PP_NULL_MODE; + for(polynomial_ptr=str_polynomial;*polynomial_ptr!='\0';polynomial_ptr++){ + if(comment==1){ + if(*polynomial_ptr=='\n'){ + comment=0; + } + } + else{ + switch(*polynomial_ptr){ + // new monomial + case '+': + if(mode==PP_NULL_MODE){ + // if not a constant + if(tmp_poly.length>0){ + // write num + polynomial_multiply_scalar(tmp_poly, tmp_num); + // replace factor + for(i=0;i<tmp_poly.length;i++){ + free_Int_Array(tmp_poly.factors[i]); + int_array_cpy(tmp_factor,tmp_poly.factors+i); + } + } + // if constant + else{ + init_Int_Array(&tmp_monomial,1); + polynomial_append(tmp_monomial,tmp_factor,tmp_num,&tmp_poly); + free_Int_Array(tmp_monomial); + } + free_Int_Array(tmp_factor); + free_Number(tmp_num); + // write polynomial + polynomial_concat_noinit(tmp_poly, output); + // reset tmp_poly + init_Polynomial(&tmp_poly,MONOMIAL_SIZE); + tmp_num=number_one(); + init_Int_Array(&tmp_factor,MONOMIAL_SIZE); + } + break; + + // numerical pre-factor + case '(': + if(mode==PP_NULL_MODE){ + mode=PP_NUMBER_MODE; + parenthesis_count=0; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else if(mode==PP_NUMBER_MODE){ + // match parentheses + parenthesis_count++; + } + break; + case ')': + if(mode==PP_NUMBER_MODE){ + if(parenthesis_count==0){ + // write num + str_to_Number(buffer,&tmp1_num); + number_prod_chain(tmp1_num,&tmp_num); + free_Number(tmp1_num); + // back to null mode + mode=PP_NULL_MODE; + } + else{ + parenthesis_count--; + } + } + break; + + // enter factor mode + case '[': + if(mode==PP_NULL_MODE){ + mode=PP_BRACKET_MODE; + } + break; + // factor mode + case 'l': + if(mode==PP_BRACKET_MODE){ + mode=PP_FACTOR_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // symbol mode + case 'f': + if(mode==PP_BRACKET_MODE){ + mode=PP_FIELD_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // read factor + case ']': + // factor + if(mode==PP_FACTOR_MODE){ + sscanf(buffer,"%d",&i); + int_array_append(i,&tmp_factor); + } + // symbol + else if(mode==PP_FIELD_MODE){ + // 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); + } + } + // 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); + init_Int_Array(&dummy_factor, 1); + polynomial_append_noinit(tmp_monomial, dummy_factor, number_one(), &tmp_poly); + } + } + // scalar product of symbols + else if(mode==PP_FIELD_SCALAR_MODE || mode==PP_FIELD_VECTOR_PROD_MODE){ + get_offsets_index(buffer, &offset1, &offset2, &index); + // if polynomial exists, add to each monomial + if(tmp_poly.length>0){ + for(i=0;i<tmp_poly.length;i++){ + if(mode==PP_FIELD_SCALAR_MODE){ + if(offset1!=KONDO_H_OFFSET || offset2!=KONDO_H_OFFSET){ + int_array_append(1000*(10*offset1+offset2)+index, tmp_poly.monomials+i); + } + } + else{ + int_array_append(100*(100*KONDO_A_OFFSET+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+index, tmp_poly.monomials+i); + } + } + } + // if not, create a new term in the polynomial + else{ + init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); + if(mode==PP_FIELD_SCALAR_MODE){ + if(offset1!=KONDO_H_OFFSET || offset2!=KONDO_H_OFFSET){ + int_array_append(1000*(10*offset1+offset2)+index, &tmp_monomial); + } + } + else{ + int_array_append(100*(100*KONDO_A_OFFSET+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+index, &tmp_monomial); + } + init_Int_Array(&dummy_factor, 1); + polynomial_append_noinit(tmp_monomial, dummy_factor, number_one(), &tmp_poly); + } + /* // older method in which a scalar product was expanded in A, B and h + // resolve scalar product + kondo_resolve_scalar_prod_symbols(buffer, &scalar_prod_poly); + // add to tmp_poly + if(tmp_poly.length==0){ + polynomial_concat(scalar_prod_poly,&tmp_poly); + } + else{ + polynomial_prod_chain(scalar_prod_poly,&tmp_poly,fields); + } + free_Polynomial(scalar_prod_poly); + */ + } + // switch back to null mode + mode=PP_NULL_MODE; + break; + + // symbol scalar product + case '.': + if(mode==PP_FIELD_MODE){ + mode=PP_FIELD_SCALAR_MODE; + } + buffer_ptr=str_addchar(buffer_ptr,*polynomial_ptr); + break; + case 'x': + if(mode==PP_FIELD_MODE){ + mode=PP_FIELD_VECTOR_PROD_MODE; + } + buffer_ptr=str_addchar(buffer_ptr,*polynomial_ptr); + break; + + // scalar product + case '<': + if(mode==PP_NULL_MODE){ + mode=PP_MONOMIAL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case '>': + if(mode==PP_MONOMIAL_MODE){ + // resolve scalar product + kondo_resolve_scalar_prod(buffer, &scalar_prod_poly, fields); + // add to tmp_poly + if(tmp_poly.length==0){ + polynomial_concat(scalar_prod_poly,&tmp_poly); + } + else{ + polynomial_prod_chain(scalar_prod_poly,&tmp_poly,fields); + } + free_Polynomial(scalar_prod_poly); + + mode=PP_NULL_MODE; + } + break; + + // characters to ignore + case ' ':break; + case '&':break; + case '\n':break; + + // comments + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,*polynomial_ptr); + } + break; + } + } + } + + // last term + if(tmp_poly.length>0){ + polynomial_multiply_scalar(tmp_poly,tmp_num); + for(i=0;i<tmp_poly.length;i++){ + free_Int_Array(tmp_poly.factors[i]); + int_array_cpy(tmp_factor,tmp_poly.factors+i); + } + } + else{ + init_Int_Array(&tmp_monomial,1); + polynomial_append(tmp_monomial,tmp_factor,tmp_num,&tmp_poly); + } + free_Int_Array(tmp_factor); + free_Number(tmp_num); + polynomial_concat_noinit(tmp_poly, output); + + // simplify + polynomial_simplify(output, fields); + + free(buffer); + return(0); +} + +// as Char_Array +int parse_kondo_polynomial(Char_Array kondo_polynomial_str, Polynomial* polynomial, Fields_Table fields){ + char* str; + char_array_to_str(kondo_polynomial_str, &str); + parse_kondo_polynomial_str(str, polynomial, fields); + free(str); + return(0); +} + + +// read Aij, Bij, hi where i is a space dimension and j is a box index +int kondo_resolve_ABh(char* str, Polynomial* output, Fields_Table fields){ + char* ptr; + // offset (A,B or H) + int offset=-1; + // dimension + int dim=-1; + // box index + int index=-1; + // polynomial for each term + Polynomial psi[KONDO_SPIN]; + Polynomial poly_conjugate; + Int_Array monomial; + Int_Array factor; + Number_Matrix pauli_mat; + int i,a,b; + + // memory + init_Polynomial(output, MONOMIAL_SIZE); + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset=KONDO_A_OFFSET; + break; + case 'a': + offset=KONDO_A_OFFSET; + break; + case 'B': + offset=KONDO_B_OFFSET; + break; + case 'b': + offset=KONDO_B_OFFSET; + break; + case 'h': + offset=KONDO_H_OFFSET; + break; + default: + // set index if dim was already set + if(dim>=0){ + index=*ptr-'0'; + } + else{ + dim=*ptr-'0'; + } + } + } + + // turn B3 into B2 and B4 into B1 + if(offset==KONDO_B_OFFSET){ + switch(index){ + case 3: + index=2; + break; + case 4: + index=1; + break; + } + } + + // h's + if(offset==KONDO_H_OFFSET){ + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(dim+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), output); + } + // psi's + else{ + // construct spin indices + for(i=0;i<KONDO_SPIN;i++){ + init_Polynomial(psi+i,2); + + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(i+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + + // internal field if applicable + if(index>0){ + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + + int_array_append(10*(i+10*offset)+index, &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + } + } + + // multiply by Pauli matrices + Pauli_matrix(dim+1,&pauli_mat); + for(a=0;a<KONDO_SPIN;a++){ + for(b=0;b<KONDO_SPIN;b++){ + polynomial_cpy(psi[b],&poly_conjugate); + polynomial_conjugate(poly_conjugate); + polynomial_multiply_scalar(poly_conjugate, pauli_mat.matrix[a][b]); + polynomial_prod_chain(psi[a],&poly_conjugate,fields); + // add to poly + polynomial_concat_noinit(poly_conjugate, output); + } + } + + free_Number_Matrix(pauli_mat); + + // free spin indices + for(i=0;i<KONDO_SPIN;i++){ + free_Polynomial(psi[i]); + } + } + + return(0); +} + +#define K_VECT_PROD 1 +#define K_SCALAR_PROD 2 +// read a Kondo scalar product (generalized to vector products as well) +int kondo_resolve_scalar_prod(char* str, Polynomial* output, Fields_Table fields){ + char* ptr; + // offset of each term (A,B or H) + int offset=-1; + // index of each term (0,...,box_count) + int index=0; + int i; + int operation=0; + Polynomial poly_vect1[KONDO_DIM]; + Polynomial poly_vect2[KONDO_DIM]; + + // memory + init_Polynomial(output, MONOMIAL_SIZE); + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset=KONDO_A_OFFSET; + break; + case 'a': + offset=KONDO_A_OFFSET; + break; + case 'B': + offset=KONDO_B_OFFSET; + break; + case 'b': + offset=KONDO_B_OFFSET; + break; + case 'h': + offset=KONDO_H_OFFSET; + break; + + // scalar product + case '.': + // if no previous vector product + if(operation!=K_VECT_PROD){ + kondo_polynomial_vector(offset, index, &poly_vect1, fields); + } + // compute vector product + else{ + kondo_polynomial_vector(offset, index, &poly_vect2, fields); + kondo_polynomial_vector_product(&poly_vect1, poly_vect2, fields); + } + operation=K_SCALAR_PROD; + break; + + // vector product + case 'x': + if(offset>=0){ + kondo_polynomial_vector(offset, index, &poly_vect1, fields); + operation=K_VECT_PROD; + } + break; + + // index + default: + // char to int + index=*ptr-'0'; + } + } + + // final scalar product + if(operation==K_SCALAR_PROD){ + if(offset>=0){ + kondo_polynomial_vector(offset, index, &poly_vect2, fields); + kondo_polynomial_scalar_product(poly_vect1, poly_vect2, output, fields); + } + } + + // free memory + for(i=0;i<KONDO_DIM;i++){ + free_Polynomial(poly_vect1[i]); + free_Polynomial(poly_vect2[i]); + } + + return(0); +} + +// compute a scalar product of polynomial vectors +int kondo_polynomial_scalar_product(Polynomial poly_vect1[3], Polynomial poly_vect2[3], Polynomial* output, Fields_Table fields){ + int i; + Polynomial tmp_poly; + + for(i=0;i<KONDO_DIM;i++){ + polynomial_prod(poly_vect1[i],poly_vect2[i],&tmp_poly,fields); + + // add to output + polynomial_concat_noinit(tmp_poly, output); + } + + polynomial_simplify(output, fields); + + return(0); +} + +// compute a vector product of polynomial vectors +int kondo_polynomial_vector_product(Polynomial (*poly_vect1)[3], Polynomial poly_vect2[3], Fields_Table fields){ + int i; + Polynomial out[3]; + Polynomial tmp_poly; + + for(i=0;i<3;i++){ + init_Polynomial(out+i, POLY_SIZE); + + polynomial_prod((*poly_vect1)[(i+1)%3],poly_vect2[(i+2)%3], &tmp_poly, fields); + polynomial_concat_noinit(tmp_poly, out+i); + + polynomial_prod((*poly_vect1)[(i+2)%3],poly_vect2[(i+1)%3], &tmp_poly, fields); + polynomial_multiply_Qscalar(tmp_poly,quot(-1,1)); + polynomial_concat_noinit(tmp_poly, out+i); + } + + for(i=0;i<3;i++){ + free_Polynomial((*poly_vect1)[i]); + (*poly_vect1)[i]=out[i]; + } + + return(0); +} + +// compute the 3 components of a kondo vector +int kondo_polynomial_vector(int offset, int index, Polynomial (*polys)[3], Fields_Table fields){ + int i,a,b; + // polynomial for each term + Polynomial psi[KONDO_SPIN]; + Polynomial poly_conjugate; + Int_Array monomial; + Int_Array factor; + Number_Matrix pauli_mat; + + for(i=0;i<KONDO_DIM;i++){ + // memory + init_Polynomial((*polys)+i,POLY_SIZE); + } + + // h's + if(offset==KONDO_H_OFFSET){ + // construct every component field + for(i=0;i<KONDO_DIM;i++){ + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(i+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), (*polys)+i); + } + } + // psi's + else{ + // construct spin indices + for(i=0;i<KONDO_SPIN;i++){ + init_Polynomial(psi+i,2); + + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(i+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + + // internal field if applicable + if(index>0){ + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + + int_array_append(10*(i+10*offset)+index, &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + } + } + + // multiply by Pauli matrices + for(i=0;i<KONDO_DIM;i++){ + Pauli_matrix(i+1,&pauli_mat); + for(a=0;a<KONDO_SPIN;a++){ + for(b=0;b<KONDO_SPIN;b++){ + polynomial_cpy(psi[b],&poly_conjugate); + polynomial_conjugate(poly_conjugate); + polynomial_multiply_scalar(poly_conjugate, pauli_mat.matrix[a][b]); + polynomial_prod_chain(psi[a],&poly_conjugate,fields); + // add to polys[j] + polynomial_concat_noinit(poly_conjugate, (*polys)+i); + } + } + + free_Number_Matrix(pauli_mat); + } + + // free spin indices + for(i=0;i<KONDO_SPIN;i++){ + free_Polynomial(psi[i]); + } + } + + return(0); +} + +// read a scalar product of symbols +int kondo_resolve_scalar_prod_symbols(char* str, Polynomial* output){ + char* ptr; + // first or second term + int term=0; + // offset of each term (A,B or H) + int offset[2]; + // index of each term (0,...,box_count) + int index[2]={0,0}; + Int_Array monomial; + Int_Array factor; + int i; + + // memory + init_Polynomial(output, KONDO_DIM); + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset[term]=KONDO_A_OFFSET; + break; + case 'a': + offset[term]=KONDO_A_OFFSET; + break; + case 'B': + offset[term]=KONDO_B_OFFSET; + break; + case 'b': + offset[term]=KONDO_B_OFFSET; + break; + case 'h': + offset[term]=KONDO_H_OFFSET; + break; + // switch term + case '.': + term=1-term; + break; + default: + // char to int + index[term]=*ptr-'0'; + } + } + + // scalar product + for(i=0;i<KONDO_DIM;i++){ + init_Int_Array(&monomial,2); + init_Int_Array(&factor, 1); + + if(offset[0]==KONDO_H_OFFSET){ + int_array_append(10*(10*offset[0]+i)+index[0], &monomial); + } + else{ + int_array_append(100*(10*offset[0]+i)+index[0], &monomial); + } + if(offset[1]==KONDO_H_OFFSET){ + int_array_append(10*(10*offset[1]+i)+index[1], &monomial); + } + else{ + int_array_append(100*(10*offset[1]+i)+index[1], &monomial); + } + + polynomial_append_noinit(monomial, factor, number_one(), output); + } + return(0); +} + +// get the offset and index of a monomial term +// (e.g. A1 yields KONDO_A_OFFSET and 1) +int get_offset_index(char* str, int* offset, int* index){ + char* ptr; + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + *offset=KONDO_A_OFFSET; + break; + case 'a': + *offset=KONDO_A_OFFSET; + break; + case 'B': + *offset=KONDO_B_OFFSET; + break; + case 'b': + *offset=KONDO_B_OFFSET; + break; + case 'h': + *offset=KONDO_H_OFFSET; + break; + default: + // char to int + *index=*ptr-'0'; + } + } + + return(0); +} + +// get the offsets and index of a scalar product +int get_offsets_index(char* str, int* offset1, int* offset2, int* index){ + int offset[2]={-1,-1}; + char* ptr; + int term=0; + + *index=-1; + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset[term]=KONDO_A_OFFSET; + break; + case 'a': + offset[term]=KONDO_A_OFFSET; + break; + case 'B': + offset[term]=KONDO_B_OFFSET; + break; + case 'b': + offset[term]=KONDO_B_OFFSET; + break; + case 'h': + offset[term]=KONDO_H_OFFSET; + break; + // switch term + case '.': + term=1-term; + break; + default: + // char to int + *index=*ptr-'0'; + } + } + + *offset1=offset[0]; + *offset2=offset[1]; + + return(0); +} + +// get the index of the symbol corresponding to a given string +int get_symbol_index(char* str){ + char* ptr; + int offset=-1; + int index=0; + int dim=-1; + + // first check whether the field already is an index + for(ptr=str;*ptr!='\0';ptr++){ + if((*ptr-'0'>=10 || *ptr-'0'<0) && (*ptr!='-')){ + break; + } + } + if(*ptr=='\0'){ + sscanf(str,"%d",&index); + return(index); + } + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset=KONDO_A_OFFSET; + break; + case 'a': + offset=KONDO_A_OFFSET; + break; + case 'B': + offset=KONDO_B_OFFSET; + break; + case 'b': + offset=KONDO_B_OFFSET; + break; + case 'h': + offset=KONDO_H_OFFSET; + break; + default: + // set index if dim was already set + if(dim>=0){ + index=*ptr-'0'; + } + else{ + dim=*ptr-'0'; + } + } + } + + if(offset==-1){ + return(-1); + } + // no symbol for h + if(offset==KONDO_H_OFFSET){ + return(10*(10*offset+dim)); + } + else{ + return(100*(10*offset+dim)+index); + } +} diff --git a/src/kondo.h b/src/kondo.h new file mode 100644 index 0000000..23756ad --- /dev/null +++ b/src/kondo.h @@ -0,0 +1,76 @@ +/* +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. +*/ + +/* Generate configuration files specific to the Kondo model */ + +#ifndef KONDO_H +#define KONDO_H + +#include "types.h" + +// generate configuration file +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 groups (groups of independent variables) +int kondo_groups(Char_Array* str_groups, int box_count); + +// generate Kondo identities +int kondo_identities(Char_Array* str_identities); + +// convert the Kondo propagator +int kondo_propagator(Char_Array str_kondo_propagator, Char_Array* str_propagator); + +// read a product of polynomials +int parse_kondo_polynomial_factors(Char_Array str_polynomial, Polynomial* output, Fields_Table fields); + +// convert Kondo input polynomial +int kondo_input_polynomial(Char_Array str_kondo_polynomial, Char_Array* str_polynomial, Fields_Table fields, int box_count); + +// convert the Kondo idtable +int kondo_idtable(Char_Array str_kondo_idtable, Char_Array* str_idtable, Fields_Table fields); + +// read a kondo polynomial and convert it to a polynomial expressed in terms of the fields in the fields table +int parse_kondo_polynomial_str(char* str_polynomial, Polynomial* output, Fields_Table fields); +int parse_kondo_polynomial(Char_Array kondo_polynomial_str, Polynomial* polynomial, Fields_Table fields); + +// read Aij, Bij, hi where i is a space dimension and j is a box index +int kondo_resolve_ABh(char* str, Polynomial* output, Fields_Table fields); +// read a Kondo scalar product +int kondo_resolve_scalar_prod(char* str, Polynomial* output, Fields_Table fields); +// compute a scalar product of polynomial vectors +int kondo_polynomial_scalar_product(Polynomial poly_vect1[3], Polynomial poly_vect2[3], Polynomial* output, Fields_Table fields); +// compute a vector product of polynomial vectors +int kondo_polynomial_vector_product(Polynomial (*poly_vect1)[3], Polynomial poly_vect2[3], Fields_Table fields); +// compute the 3 components of a kondo vector +int kondo_polynomial_vector(int offset, int index, Polynomial (*polys)[3], Fields_Table fields); +// read a scalar product of symbols +int kondo_resolve_scalar_prod_symbols(char* str, Polynomial* output); + +// get the offset and index of a monomial term +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); +#endif diff --git a/src/kondo_preprocess.c b/src/kondo_preprocess.c new file mode 100644 index 0000000..3371014 --- /dev/null +++ b/src/kondo_preprocess.c @@ -0,0 +1,126 @@ +/* +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. +*/ + +/* +kondo_preprocess + +Generate configuration files for the Kondo problem + +*/ + + +#include <stdio.h> +#include <stdlib.h> + +#include "definitions.cpp" +#include "kondo.h" +#include "cli_parser.h" +#include "array.h" + + +// read cli arguments +int read_args_kondo_pp(int argc,const char* argv[], Str_Array* str_args, Kondopp_Options* opts); +// print usage message +int print_usage_kondo_pp(); + +int main (int argc, const char* argv[]){ + int i; + // string arguments + Str_Array str_args; + // options + Kondopp_Options opts; + + // read command-line arguments + read_args_kondo_pp(argc,argv,&str_args,&opts); + + kondo_generate_conf(&str_args, 2*opts.dimension); + for(i=0;i<str_args.length;i++){ + printf("%s\n",str_args.strs[i].str); + if(i<str_args.length-1){ + printf("&\n"); + } + } + + //free memory + free_Str_Array(str_args); + return(0); +} + + +// read cli arguments +#define CP_FLAG_DIMENSION 1 +int read_args_kondo_pp(int argc,const char* argv[], Str_Array* str_args, Kondopp_Options* opts){ + int i; + // pointers + char* ptr; + // file to read the polynomial from in flow mode + const char* file=""; + // flag that indicates what argument is being read + int flag=0; + // whether a file was specified on the command-line + int exists_file=0; + + + // if there are no arguments + if(argc==1){ + print_usage_kondo_pp(); + exit(-1); + } + + // defaults + // dimensions (including time) + (*opts).dimension=2; + +// loop over arguments +for(i=1;i<argc;i++){ + // flag + if(argv[i][0]=='-'){ + for(ptr=((char*)argv[i])+1;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'd': + flag=CP_FLAG_DIMENSION; + break; + // print version + case 'v': + printf("kondo_preprocess " VERSION "\n"); + exit(1); + break; + } + } + } + // number of dimensions + else if (flag==CP_FLAG_DIMENSION){ + sscanf(argv[i],"%d",&((*opts).dimension)); + 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); +} + +// print usage message +int print_usage_kondo_pp(){ + printf("\nusage:\n kondo_preprocess [-d dimension] <filename>\n\n"); + return(0); +} + diff --git a/src/mean.c b/src/mean.c new file mode 100644 index 0000000..aad7a5a --- /dev/null +++ b/src/mean.c @@ -0,0 +1,793 @@ +/* +Copyright 2015 Ian Jauslin + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* +As of version 1.0, the mean of a monomial is computed directly +*/ + +#include "mean.h" + +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include "definitions.cpp" +#include "tools.h" +#include "polynomial.h" +#include "rational.h" +#include "array.h" +#include "fields.h" +#include "number.h" + +// mean of a monomial +int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Matrix propagator){ + int sign=1; + // +/- internal fields + Int_Array internal_plus; + Int_Array internal_minus; + + // init out + *out=polynomial_one(); + + // sort first + monomial_sort(monomial, 0, monomial.length-1, fields, &sign); + polynomial_multiply_Qscalar(*out, quot(sign,1)); + // get internals + // (*out).monomials is the first element of out but it only has 1 element + // first, free (*out).monomials[0] + free_Int_Array((*out).monomials[0]); + get_internals(monomial, &internal_plus, &internal_minus, (*out).monomials, fields); + + if(internal_plus.length>0 && internal_minus.length>0){ + mean_internal(internal_plus, internal_minus, out, propagator, fields); + } + + free_Int_Array(internal_plus); + free_Int_Array(internal_minus); + return(0); +} + +// compute the mean of a monomial of internal fields (with split + and -) +int mean_internal(Int_Array internal_plus, Int_Array internal_minus, Polynomial* out, Polynomial_Matrix propagator, Fields_Table fields){ + if(internal_plus.length!=internal_minus.length){ + fprintf(stderr,"error: monomial contains unmatched +/- fields\n"); + exit(-1); + } + int n=internal_minus.length; + // pairing as an array of positions + int* pairing=calloc(n,sizeof(int)); + // specifies which indices are available for pairing + int* mask=calloc(n,sizeof(int)); + // signature of the permutation + int pairing_sign; + // sign from mixing - and + together + int mixing_sign; + Polynomial num; + Polynomial num_summed=polynomial_zero(); + // propagator matrix indices + int* indices_minus=calloc(n,sizeof(int)); + int* indices_plus=calloc(n,sizeof(int)); + int i; + // whether the next pairing exists + int exists_next=0; + + // indices + for(i=0;i<n;i++){ + indices_plus[i]=intlist_find_err(propagator.indices, propagator.length, internal_plus.values[i]); + indices_minus[i]=intlist_find_err(propagator.indices, propagator.length, -internal_minus.values[i]); + } + + // init pairing and mask + exists_next=init_pairing(pairing, mask, n, propagator, indices_plus, indices_minus)+1; + + // initial sign + pairing_sign=permutation_signature(pairing,n); + + // mixing sign (from ordering psi+psi-): (-1)^{n(n+1)/2} + if((n*(n+1))/2 %2 ==0){ + mixing_sign=1; + } + else{ + mixing_sign=-1; + } + + // loop over pairings + // loop ends when the first pairing leaves the array + while(exists_next==1){ + num=polynomial_one(); + // propagator product for the current pairing (only simplify after all pairings) + for(i=0;i<n;i++){ + polynomial_prod_chain_nosimplify(propagator.matrix[indices_plus[i]][indices_minus[pairing[i]]],&num, fields); + } + polynomial_multiply_Qscalar(num,quot(mixing_sign*pairing_sign,1)); + polynomial_concat_noinit_inplace(num,&num_summed); + + exists_next=next_pairing(pairing, mask, n, propagator, indices_plus, indices_minus)+1; + pairing_sign=permutation_signature(pairing,n); + } + + // only simplify in mean_symbols + polynomial_prod_chain_nosimplify(num_summed,out,fields); + free_Polynomial(num_summed); + free(pairing); + free(mask); + free(indices_plus); + free(indices_minus); + return(0); +} + +// 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){ + // index we want to increment + int move=0; + int i; + for(i=0;i<n;i++){ + pairing[i]=-1; + mask[i]=0; + } + + // loop until move is out of range + while(move>=0 && move<n){ + // move + pairing[move]=next_wick(move, pairing[move], mask, n, propagator, indices_plus, indices_minus); + // if the next term does not exist, then move previous index + if(pairing[move]==-1){ + move--; + } + // else move next index + else{ + move++; + } + } + + // if move==-1, then there is no first term, return -1 + if(move==-1){ + return(-1); + } + // if the first term exists + return(0); +} + +// next pairing with a non-vanishing propagator +int next_pairing(int* pairing, int* mask, int n, Polynomial_Matrix propagator, int* indices_plus, int* indices_minus){ + // index we want to increment + int move=n-1; + + // last index + mask[pairing[n-1]]=0; + + // loop until move is out of range + while(move>=0 && move<n){ + // move + pairing[move]=next_wick(move, pairing[move], mask, n, propagator, indices_plus, indices_minus); + // if the next term does not exist, then move previous index + if(pairing[move]==-1){ + move--; + } + // else move next index + else{ + move++; + } + } + + // if move==-1, then there is no next term, return -1 + if(move==-1){ + return(-1); + } + // if the next term exists + return(0); +} + +// next term in the Wick expansion +int next_wick(int index, int start, int* mask, int n, Polynomial_Matrix propagator, int* indices_plus, int* indices_minus){ + int i; + // unset mask + if(start>=0 && start<n){ + mask[start]=0; + } + // find next position + for(i=start+1;i<n;i++){ + // if the propagator doesn't vanish + if(mask[i]==0 && polynomial_is_zero(propagator.matrix[indices_plus[index]][indices_minus[i]])==0){ + mask[i]=1; + return(i); + } + } + // no next term + return(-1); +} + + +/* Older function: propagator as number +// compute the mean of a monomial of internal fields (with split + and -) +// compute all contractions +int mean_internal_slow(Int_Array internal_plus, Int_Array internal_minus, Number* outnum, Polynomial_Matrix propagator){ + if(internal_plus.length!=internal_minus.length){ + fprintf(stderr,"error: monomial contains unmatched +/- fields\n"); + exit(-1); + } + int n=internal_minus.length; + // pairing as an array of positions + int* pairing=calloc(n,sizeof(int)); + // specifies which indices are available for pairing + int* mask=calloc(n,sizeof(int)); + // signature of the permutation + int pairing_sign; + // sign from mixing - and + together + int mixing_sign; + Number num; + Number num_summed=number_zero(); + // propagator matrix indices + int index1, index2; + int i,j,k,l; + + // init pairing and mask + for(i=0;i<n-1;i++){ + pairing[i]=i; + mask[i]=1; + } + pairing[n-1]=n-1; + pairing_sign=1; + + // mixing sign: (-1)^{n(n+1)/2} + if((n*(n+1))/2 %2 ==0){ + mixing_sign=1; + } + else{ + mixing_sign=-1; + } + + // loop over pairings + // loop ends when the first pairing leaves the array + while(pairing[0]<n){ + num=number_one(); + // propagator product for the current pairing + for(i=0;i<n;i++){ + // indices within the propagator matrix + index1=intlist_find_err(propagator.indices, propagator.length, internal_plus.values[i]); + index2=intlist_find_err(propagator.indices, propagator.length, -internal_minus.values[pairing[i]]); + + number_prod_chain(propagator.matrix[index1][index2],&num); + } + number_Qprod_chain(quot(mixing_sign*pairing_sign,1),&num); + number_add_chain(num,&num_summed); + free_Number(num); + + // next pairing + // last element of the pairing that we can move + for(i=n-1;i>=0;i--){ + // move i-th + mask[pairing[i]]=0; + // search for next possible position + for(j=pairing[i]+1;j<n;j++){ + if(mask[j]==0){ + break; + } + } + + // if the next position exists + if(j<n){ + // sign correction: change sign by (-1)^{1+(n-i)(n-i-1)/2} + // actually (-1)^{1+(n-1-i)(n-1-i-1)/2 + if(((n-i-1)*(n-i-2))/2 % 2==0){ + pairing_sign*=-1; + } + + pairing[i]=j; + mask[j]=1; + // put the remaining pairings at their left-most possible values + if(i<n-1){ + k=i+1; + for(l=0;l<n;l++){ + if(mask[l]==0){ + mask[l]=1; + pairing[k]=l; + k++; + // if exhausted all indices + if(k>=n){ + break; + } + } + } + } + // if the next position was found, then don't try to move the previous pairings + break; + } + // if no next position is found, store the pairing outside the array (so the algorithm stops when the first pairing is outside the array) + else{ + pairing[i]=n; + } + } + } + + number_prod_chain(num_summed,outnum); + free_Number(num_summed); + free(pairing); + free(mask); + return(0); +} +*/ + + +// get lists of internal fields from a monomial (separate + and -) +// requires the monomial to be sorted (for the sign to be correct) +int get_internals(Int_Array monomial, Int_Array* internal_plus, Int_Array* internal_minus, Int_Array* others, Fields_Table fields){ + int i; + init_Int_Array(internal_plus, monomial.length); + init_Int_Array(internal_minus, monomial.length); + init_Int_Array(others, monomial.length); + for (i=0;i<monomial.length;i++){ + if(int_array_find(abs(monomial.values[i]),fields.internal)>=0){ + // split +/- fields + if(monomial.values[i]>0){ + int_array_append(monomial.values[i],internal_plus); + } + else{ + int_array_append(monomial.values[i],internal_minus); + } + } + else{ + int_array_append(monomial.values[i], others); + } + } + return(0); +} + + +// compute the mean of a monomial containing symbolic expressions +// keep track of which means were already computed +int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed){ + Int_Array symbol_list; + int i; + int power; + int* current_term; + Polynomial mean_num; + Int_Array tmp_monomial; + Number tmp_num; + Int_Array base_monomial; + int sign; + // whether or not the next term exists + int exists_next=0; + // simplify polynomial periodically + int simplify_freq=1; + Polynomial mean_poly; + + init_Polynomial(output, POLY_SIZE); + + // check whether the mean was already computed + for(i=0;i<(*computed).length;i++){ + if(int_array_cmp((*computed).lhs[i], monomial)==0){ + // write polynomial + polynomial_concat((*computed).rhs[i], output); + return(0); + } + } + + init_Int_Array(&symbol_list, monomial.length); + init_Int_Array(&base_monomial, monomial.length); + + // generate symbols list + for(i=0;i<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); + } + else{ + int_array_append(monomial.values[i], &base_monomial); + } + } + power=symbol_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(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; + } + + // loop over terms; the loop stops when all the pointers are at the end of the first symbol + 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); + } + // check whether the monomial vanishes + if(check_monomial_match(tmp_monomial, fields)==1){ + // sort monomial + sign=1; + monomial_sort(tmp_monomial, 0, tmp_monomial.length-1, fields, &sign); + number_Qprod_chain(quot(sign,1), &tmp_num); + + // mean + mean_groups(tmp_monomial, &mean_poly, fields, propagator, groups, computed); + + // write to output + polynomial_multiply_scalar(mean_poly,tmp_num); + polynomial_concat_noinit_inplace(mean_poly, output); + } + + free_Number(tmp_num); + free_Int_Array(tmp_monomial); + + // next term + exists_next=next_prod(current_term, symbol_list, fields, power, base_monomial)+1; + + + // simplfiy every 25 steps (improves both memory usage and performance) + if(simplify_freq %25 ==0){ + polynomial_simplify(output, fields); + simplify_freq=0; + } + simplify_freq++; + } + + // simplify + polynomial_simplify(output, fields); + + // write computed + identities_append(monomial, *output, computed); + + // free memory + free(current_term); + free_Int_Array(symbol_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){ + // index we want to increment + int move=0; + // tmp monomial + Int_Array monomial; + int i; + + init_Int_Array(&monomial, base_monomial.length+5*power); + int_array_cpy_noinit(base_monomial, &monomial); + // init current term + for(i=0;i<power;i++){ + current_term[i]=-1; + } + + // 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); + // if the next term does not exist, then move previous index + if(current_term[move]==-1){ + move--; + } + // else move next index + else{ + move++; + } + } + + free_Int_Array(monomial); + // if move==-1, then there is no first term, return -1 + if(move==-1){ + return(-1); + } + // if the next term exists + return(0); +} + +// 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){ + // index we want to increment + int move=power-1; + // tmp monomial + Int_Array monomial; + int i; + + // init monomial + 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); + } + + // 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); + // if the next term does not exist, then move previous index + if(current_term[move]==-1){ + move--; + } + // else move next index + else{ + move++; + } + } + + free_Int_Array(monomial); + // if move==-1, then there is no next term, return -1 + if(move==-1){ + return(-1); + } + // if the next term exists + return(0); +} + +// 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){ + int i; + // remove last term from monomial + if(start>=0 && start<polynomial.length){ + (*monomial).length-=polynomial.monomials[start].length; + } + // find next position + for(i=start+1;i<polynomial.length;i++){ + // if no repetitions + if(check_monomial_addterm(*monomial,polynomial.monomials[i],fields)==1){ + // append to monomial + int_array_concat(polynomial.monomials[i], monomial); + return(i); + } + } + // no next term + return(-1); +} + + +// signature of a permutation +int permutation_signature(int* permutation, int n){ + int* tmp_array=calloc(n,sizeof(int)); + int i; + int ret=1; + for(i=0;i<n;i++){ + tmp_array[i]=permutation[i]; + } + sort_fermions(tmp_array, 0, n-1, &ret); + free(tmp_array); + return(ret); +} + +// sort a list of anti-commuting variables +int sort_fermions(int* array, int begin, int end, int* sign){ + int i; + int tmp; + int index; + // the pivot: middle of the monomial + int pivot=(begin+end)/2; + + // if the monomial is non trivial + if(begin<end){ + // send pivot to the end + if(pivot!=end){ + tmp=array[end]; + array[end]=array[pivot]; + array[pivot]=tmp; + *sign*=-1; + } + + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + if(array[i]<array[end]){ + // if smaller, exchange with reference index + if(i!=index){ + tmp=array[i]; + array[i]=array[index]; + array[index]=tmp; + *sign*=-1; + } + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + if(end!=index){ + tmp=array[end]; + array[end]=array[index]; + array[index]=tmp; + *sign*=-1; + } + + // recurse + sort_fermions(array, begin, index-1, sign); + sort_fermions(array, index+1, end, sign); + } + return(0); +} + + +// mean while factoring groups out +int mean_groups(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed){ + Polynomial num_mean; + Int_Array tmp_monomial; + int i; + int group=-2; + int next_group=-2; + Polynomial tmp_poly; + int sign; + + init_Polynomial(output, MONOMIAL_SIZE); + + // check whether there are symbols + // requires the symbols to be at the end of the monomial + if(monomial.length==0 || field_type(monomial.values[monomial.length-1], fields)!=FIELD_SYMBOL){ + // mean + mean(monomial, &num_mean, fields, propagator); + // add to output + polynomial_concat_noinit(num_mean,output); + } + else{ + // sort into groups + if(groups.length>0){ + sign=1; + monomial_sort_groups(monomial, 0, monomial.length-1, fields, groups, &sign); + } + // construct groups and take mean + init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); + for(i=0;i<=monomial.length;i++){ + // new group + if(i<monomial.length){ + next_group=find_group(monomial.values[i], groups); + } + // if group changes, take mean + if((i>0 && next_group!=group) || i==monomial.length){ + mean_symbols(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); + // if zero + if(polynomial_is_zero(tmp_poly)==1){ + // set output to 0 + free_Polynomial(*output); + init_Polynomial(output, 1); + free_Polynomial(tmp_poly); + break; + } + // add to output + if(polynomial_is_zero(*output)==1){ + polynomial_concat(tmp_poly, output); + } + else{ + polynomial_prod_chain_nosimplify(tmp_poly, output, fields); + } + free_Polynomial(tmp_poly); + + // reset tmp_monomial + free_Int_Array(tmp_monomial); + init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); + } + + // add to monomial + if(i<monomial.length){ + int_array_append(monomial.values[i], &tmp_monomial); + } + group=next_group; + } + + // sign correction + if(sign==-1){ + polynomial_multiply_Qscalar(*output,quot(sign,1)); + } + + free_Int_Array(tmp_monomial); + + } + + return(0); +} + + + +// mean of a polynomial + +// argument struct for multithreaded mean +struct mean_args{ + Polynomial* polynomial; + Fields_Table fields; + Polynomial_Matrix propagator; + Groups groups; +}; + +// multithreaded +int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads){ + int i; + Polynomial thread_polys[threads]; + pthread_t thread_ids[threads]; + struct mean_args args[threads]; + int len=(*polynomial).length; + + + // alloc + for(i=0;i<threads;i++){ + init_Polynomial(thread_polys+i,(*polynomial).length/threads+1); + // arguments + args[i].fields=fields; + args[i].propagator=propagator; + args[i].groups=groups; + } + + // split polynomial + for(i=0;i<len;i++){ + polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], thread_polys+(i % threads)); + } + + // start threads + for(i=0;i<threads;i++){ + args[i].polynomial=thread_polys+i; + pthread_create(thread_ids+i, NULL, polynomial_mean_thread, (void*)(args+i)); + } + + free_Polynomial(*polynomial); + init_Polynomial(polynomial, len); + + // wait for completion and join + for(i=0;i<threads;i++){ + pthread_join(thread_ids[i], NULL); + polynomial_concat_noinit(thread_polys[i], polynomial); + } + + polynomial_simplify(polynomial, fields); + + return(0); +} + +// 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); + return(NULL); +} + +// single threaded version +int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups){ + int i,j; + Polynomial output; + Polynomial tmp_poly; + // a list of already computed means + Identities computed; + + init_Polynomial(&output, (*polynomial).length); + init_Identities(&computed, EQUATION_SIZE); + + remove_unmatched_plusminus(polynomial, fields); + + // mean of each monomial + for(i=0;i<(*polynomial).length;i++){ + 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 + for(j=0;j<tmp_poly.length;j++){ + int_array_concat((*polynomial).factors[i], tmp_poly.factors+j); + number_prod_chain((*polynomial).nums[i], tmp_poly.nums+j); + } + + // add to output + polynomial_concat_noinit(tmp_poly, &output); + // simplify (simplify here in order to keep memory usage low) + polynomial_simplify(&output, fields); + } + free_Identities(computed); + + free_Polynomial(*polynomial); + *polynomial=output; + + return(0); +} + diff --git a/src/mean.h b/src/mean.h new file mode 100644 index 0000000..34ec1d3 --- /dev/null +++ b/src/mean.h @@ -0,0 +1,70 @@ +/* +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 the mean of a monomial or a polynomial +*/ + +#ifndef MEAN_H +#define MEAN_H + +#include "types.h" + +// mean of a monomial +int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Matrix propagator); + +// 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); +// 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 +int next_pairing(int* pairing, int* mask, int n, Polynomial_Matrix propagator, int* indices_plus, int* indices_minus); +// next term in the Wick expansion +int next_wick(int index, int start, int* mask, int n, Polynomial_Matrix propagator, int* indices_plus, int* indices_minus); + +/* +int mean_internal_slow(Int_Array internal_plus, Int_Array internal_minus, Number* outnum, Polynomial_Matrix propagator); +*/ + +// get lists of internal fields from a monomial (separate + and -) +// requires the monomial to be sorted (for the sign to be correct) +int get_internals(Int_Array monomial, Int_Array* internal_plus, Int_Array* internal_minus, Int_Array* others, Fields_Table fields); + +// 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); +// 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); +// 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); +// 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); + +// signature of a permutation +int permutation_signature(int* permutation, int n); + +// sort a list of anti-commuting variables +int sort_fermions(int* array, int begin, int end, int* sign); + +// mean while factoring groups out +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); +// multithreaded +int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads); +// single thread mean +void* polynomial_mean_thread(void* mean_args); +#endif diff --git a/src/meankondo.c b/src/meankondo.c new file mode 100644 index 0000000..1c976d4 --- /dev/null +++ b/src/meankondo.c @@ -0,0 +1,301 @@ +/* +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. +*/ + +/* +meankondo + +A simple tool to compute the renormalization group flow for Fermionic hierarchical models + +*/ + + +#include <stdio.h> +#include <stdlib.h> + +// pre-compiler definitions +#include "definitions.cpp" + +// various arrays +#include "array.h" + +// list of fields +#include "fields.h" +// numbers +#include "number.h" +// polynomials +#include "polynomial.h" +// list of rccs +#include "idtable.h" +// grouped representation of polynomials +#include "grouped_polynomial.h" +// command line parser +#include "cli_parser.h" +// parse input file +#include "parse_file.h" +// means +#include "mean.h" +// various string operations +#include "istring.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(); +// 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); + + +int main (int argc, const char* argv[]){ + // string arguments + Str_Array str_args; + // options + Meankondo_Options opts; + + // read command-line arguments + read_args_meankondo(argc,argv,&str_args,&opts); + + // warning message if representing rational numbers as floats +#ifdef RATIONAL_AS_FLOAT + fprintf(stderr,"info: representing rational numbers using floats\n"); +#endif + + compute_flow(str_args, opts); + + //free memory + free_Str_Array(str_args); + return(0); +} + + +// parse command-line arguments +#define CP_FLAG_THREADS 1 +int read_args_meankondo(int argc,const char* argv[], Str_Array* str_args, Meankondo_Options* opts){ + int i; + // pointers + char* ptr; + // file to read the polynomial from in flow mode + const char* file=""; + // flag that indicates what argument is being read + int flag=0; + // whether a file was specified on the command-line + int exists_file=0; + + + // defaults + // single thread + (*opts).threads=1; + // do not chain + (*opts).chain=0; + + // loop over arguments + for(i=1;i<argc;i++){ + // flag + if(argv[i][0]=='-'){ + for(ptr=((char*)argv[i])+1;*ptr!='\0';ptr++){ + switch(*ptr){ + // threads + case 't': + flag=CP_FLAG_THREADS; + break; + // chain + case 'C': + (*opts).chain=1; + break; + // print version + case 'v': + printf("meankondo " VERSION "\n"); + exit(1); + break; + default: + print_usage_meankondo(); + exit(-1); + break; + } + } + } + // threads + else if(flag==CP_FLAG_THREADS){ + sscanf(argv[i],"%d",&((*opts).threads)); + 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); +} + +// print usage message +int print_usage_meankondo(){ + printf("\nusage:\n meankondo [-t threads] [-C] <filename>\n\n"); + return(0); +} + + +// compute the renormalization group flow +int compute_flow(Str_Array str_args, Meankondo_Options opts){ + int i; + // index of the entry in the input file + int arg_index; + // header of the entry + Char_Array arg_header; + // list of fields + Fields_Table fields; + // their propagator + Polynomial_Matrix propagator; + // initial polynomial + Polynomial init_poly; + // list of rccs + Id_Table idtable; + // groups of independent fields + Groups groups; + // flow equation + Grouped_Polynomial flow_equation; + + + // 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 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 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); + } + else{ + fprintf(stderr,"error: no input polynomial entry in the configuration file\n"); + exit(-1); + } + + // propagator + arg_index=find_str_arg("propagator", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no propagator entry in the configuration file\n"); + exit(-1); + } + else{ + parse_input_propagator(str_args.strs[arg_index],&propagator, fields); + } + + // 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 groups + arg_index=find_str_arg("groups", str_args); + if(arg_index>=0){ + parse_input_groups(str_args.strs[arg_index],&groups); + } + else{ + init_Groups(&groups, 1); + } + + // flow equation + compute_flow_equation(init_poly, idtable, fields, propagator, groups, opts.threads, &flow_equation); + free_Polynomial(init_poly); + free_Polynomial_Matrix(propagator); + free_Fields_Table(fields); + free_Groups(groups); + + // 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, "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 ){ + printf("%s\n&\n",str_args.strs[i].str); + } + free_Char_Array(arg_header); + } + // print flow equation + printf("#!flow_equation\n"); + } + + // print flow equation + grouped_polynomial_print(flow_equation,'%','%'); + + // free memory + free_Id_Table(idtable); + free_Grouped_Polynomial(flow_equation); + 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); + + // average + if(threads>1){ + polynomial_mean_multithread(&exp_poly, fields, propagator, groups, threads); + } + else{ + polynomial_mean(&exp_poly, fields, propagator, groups); + } + + // 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 new file mode 100644 index 0000000..f45c376 --- /dev/null +++ b/src/meantools.c @@ -0,0 +1,116 @@ +/* +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. +*/ + +/* +meantools + +Utility to perform various operations on flow equations + +*/ + + +#include <stdio.h> +#include <stdlib.h> + +// pre-compiler definitions +#include "definitions.cpp" + +// grouped representation of polynomials +#include "grouped_polynomial.h" +// command line parser +#include "cli_parser.h" +// parse input file +#include "parse_file.h" +// arrays +#include "array.h" +// string functions +#include "istring.h" +// tools +#include "meantools_exp.h" +#include "meantools_deriv.h" +#include "meantools_eval.h" + +#define EXP_COMMAND 1 +#define DERIV_COMMAND 2 +#define EVAL_COMMAND 3 + +// read cli arguments +int read_args_meantools(int argc,const char* argv[], Str_Array* str_args, Meantools_Options* opts); +// print usage message +int print_usage_meantools(); + + +int main (int argc, const char* argv[]){ + // string arguments + Str_Array str_args; + // options + Meantools_Options opts; + + // read command-line arguments + 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; + } + + //free memory + free_Str_Array(str_args); + return(0); +} + + +// parse command-line arguments +int read_args_meantools(int argc,const char* argv[], Str_Array* str_args, Meantools_Options* opts){ + + // if there are no arguments + if(argc==1){ + print_usage_meantools(); + 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){ + (*opts).command=DERIV_COMMAND; + tool_deriv_read_args(argc, argv, str_args, opts); + } + else if(str_cmp((char*)argv[1],"eval")==1){ + (*opts).command=EVAL_COMMAND; + tool_eval_read_args(argc, argv, str_args, opts); + } + else{ + print_usage_meantools(); + exit(-1); + } + + return(0); +} + +// print usage message +int print_usage_meantools(){ + printf("\nusage:\n meantools exp <filename>\n meantools derive [-d derivatives] -V <variables> <filename>\n meantools eval -R <rccs> <filename>\n\n"); + return(0); +} + + + diff --git a/src/meantools_deriv.c b/src/meantools_deriv.c new file mode 100644 index 0000000..28d8641 --- /dev/null +++ b/src/meantools_deriv.c @@ -0,0 +1,195 @@ +/* +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_deriv.h" + +#include <stdio.h> +#include <stdlib.h> +#include "parse_file.h" +#include "cli_parser.h" +#include "istring.h" +#include "definitions.cpp" +#include "array.h" +#include "grouped_polynomial.h" + + +#define CP_FLAG_DERIVS 1 +#define CP_FLAG_VARS 2 +// read command line arguments +int tool_deriv_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; + // buffer in which to read the variables + Char_Array buffer; + int i; + char* ptr; + + // defaults + // derive once + (*opts).deriv_derivs=1; + // derive with respect to all variables + (*opts).deriv_vars.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 'd': + flag=CP_FLAG_DERIVS; + break; + case 'V': + flag=CP_FLAG_VARS; + break; + } + } + } + // number of derivatives + else if(flag==CP_FLAG_DERIVS){ + sscanf(argv[i],"%d",&((*opts).deriv_derivs)); + flag=0; + } + // variables + else if(flag==CP_FLAG_VARS){ + // if the argument is "all" then derive wrt all variables + if(str_cmp((char*)argv[i],"all")){ + (*opts).deriv_vars.length=-2; + } + else{ + str_to_char_array((char*)argv[i], &buffer); + int_array_read(buffer,&((*opts).deriv_vars)); + free_Char_Array(buffer); + } + 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); +} + + +// derive a flow equation +int tool_deriv(Str_Array str_args, Meantools_Options opts){ + // index of the entry in the input file + int arg_index; + // flow equation + Grouped_Polynomial flow_equation; + // flow equation for the derivatives + Grouped_Polynomial flow_equation_deriv; + int i; + + + // parse flow equation + // if there is a unique argument, assume it is the flow equation + if(str_args.length==1){ + char_array_to_Grouped_Polynomial(str_args.strs[0], &flow_equation); + } + else{ + arg_index=find_str_arg("flow_equation", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no flow equation entry in the configuration file\n"); + exit(-1); + } + else{ + char_array_to_Grouped_Polynomial(str_args.strs[arg_index], &flow_equation); + } + + // variables + // check they were not specified on the command line + if(opts.deriv_vars.length==-1){ + arg_index=find_str_arg("variables", str_args); + if(arg_index>=0){ + int_array_read(str_args.strs[arg_index],&(opts.deriv_vars)); + } + } + } + + // if variables length is negative then set the variables to all of the available ones + if(opts.deriv_vars.length<0){ + init_Int_Array(&(opts.deriv_vars), flow_equation.length); + for(i=0;i<flow_equation.length;i++){ + int_array_append(flow_equation.indices[i], &(opts.deriv_vars)); + } + } + + // compute derivatives + flow_equation_derivative(opts.deriv_derivs, opts.deriv_vars, flow_equation, &flow_equation_deriv); + + grouped_polynomial_print(flow_equation_deriv,'%','%'); + + // free memory + free_Grouped_Polynomial(flow_equation); + free_Grouped_Polynomial(flow_equation_deriv); + free_Int_Array(opts.deriv_vars); + return(0); +} + + +// 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){ + Grouped_Polynomial dflow; + Grouped_Polynomial tmpflow; + Int_Array indices; + int i,j; + + int_array_cpy(variables, &indices); + + // output polynomial + grouped_polynomial_cpy(flow_equation, flow_equation_derivs); + + for(j=0,dflow=flow_equation;j<n;j++){ + // tmp flow contains the result of the previous derivative + grouped_polynomial_cpy(dflow, &tmpflow); + // derive + flow_equation_derivx(tmpflow, indices, &dflow); + // free + free_Grouped_Polynomial(tmpflow); + + // add the derived 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); + } + // constants have a negative index + else{ + int_array_append(-(j+1)*DOFFSET+variables.values[i], &indices); + } + } + + // add to flow equation + grouped_polynomial_concat(dflow, flow_equation_derivs); + } + + if(n>0){ + free_Grouped_Polynomial(dflow); + } + free_Int_Array(indices); + return(0); +} diff --git a/src/meantools_deriv.h b/src/meantools_deriv.h new file mode 100644 index 0000000..4ea36a9 --- /dev/null +++ b/src/meantools_deriv.h @@ -0,0 +1,30 @@ +/* +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. +*/ + +#ifndef MEANTOOLS_DERIV_H +#define MEANTOOLS_DERIV_H + +#include "types.h" + +// read arguments +int tool_deriv_read_args(int argc, const char* argv[], Str_Array* str_args, Meantools_Options* opts); +// derive 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); + +#endif + diff --git a/src/meantools_eval.c b/src/meantools_eval.c new file mode 100644 index 0000000..50fff5b --- /dev/null +++ b/src/meantools_eval.c @@ -0,0 +1,129 @@ +/* +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_eval.h" + +#include <stdio.h> +#include <stdlib.h> +#include "parse_file.h" +#include "cli_parser.h" +#include "grouped_polynomial.h" +#include "array.h" +#include "rcc.h" + + +#define CP_FLAG_RCCS 1 +// read command line arguments +int tool_eval_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 + // mark rccstring so that it can be recognized whether it has been set or not + (*opts).eval_rccstring.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){ + // evaluate string + case 'R': + flag=CP_FLAG_RCCS; + break; + } + } + } + // rccs + else if(flag==CP_FLAG_RCCS){ + str_to_char_array((char*)argv[i], &((*opts).eval_rccstring)); + 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); +} + + +// evaluate a flow equation on a vector of rccs +int tool_eval(Str_Array str_args, Meantools_Options opts){ + // index of the entry in the input file + int arg_index; + // rccs + RCC rccs; + // flow equation + Grouped_Polynomial flow_equation; + + + // parse flow equation + // if there is a unique argument, assume it is the flow equation + if(str_args.length==1){ + char_array_to_Grouped_Polynomial(str_args.strs[0], &flow_equation); + } + else{ + arg_index=find_str_arg("flow_equation", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no flow equation entry in the configuration file\n"); + exit(-1); + } + else{ + char_array_to_Grouped_Polynomial(str_args.strs[arg_index], &flow_equation); + } + + // rccs + // check they were not specified on the command line + if(opts.eval_rccstring.length==-1){ + arg_index=find_str_arg("initial_condition", str_args); + if(arg_index>=0){ + char_array_cpy(str_args.strs[arg_index],&(opts.eval_rccstring)); + } + } + } + + // initialize the rccs + prepare_init(flow_equation.indices,flow_equation.length,&rccs); + // read rccs from string + if(opts.eval_rccstring.length!=-1){ + parse_init_cd(opts.eval_rccstring, &rccs); + free_Char_Array(opts.eval_rccstring); + } + + // evaluate + evaleq(&rccs, flow_equation); + + // print + RCC_print(rccs); + + // free memory + free_Grouped_Polynomial(flow_equation); + free_RCC(rccs); + return(0); +} + diff --git a/src/meantools_eval.h b/src/meantools_eval.h new file mode 100644 index 0000000..518049d --- /dev/null +++ b/src/meantools_eval.h @@ -0,0 +1,29 @@ +/* +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. +*/ + +#ifndef MEANTOOLS_EVAL_H +#define MEANTOOLS_EVAL_H + +#include "types.h" + +// read arguments +int tool_eval_read_args(int argc, const char* argv[], Str_Array* str_args, Meantools_Options* opts); +// evaluate a flow equation +int tool_eval(Str_Array str_args, Meantools_Options opts); + +#endif + + diff --git a/src/meantools_exp.c b/src/meantools_exp.c new file mode 100644 index 0000000..1aca928 --- /dev/null +++ b/src/meantools_exp.c @@ -0,0 +1,130 @@ +/* +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_exp.h b/src/meantools_exp.h new file mode 100644 index 0000000..f3f6666 --- /dev/null +++ b/src/meantools_exp.h @@ -0,0 +1,27 @@ +/* +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. +*/ + +#ifndef MEANTOOLS_EXP_H +#define MEANTOOLS_EXP_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); + +#endif diff --git a/src/number.c b/src/number.c new file mode 100644 index 0000000..5d4cd18 --- /dev/null +++ b/src/number.c @@ -0,0 +1,551 @@ +/* +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 "number.h" +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include "istring.h" +#include "definitions.cpp" +#include "tools.h" +#include "rational.h" +#include "array.h" + +// init +int init_Number(Number* number, int memory){ + (*number).scalars=calloc(memory,sizeof(Q)); + (*number).base=calloc(memory,sizeof(int)); + (*number).memory=memory; + (*number).length=0; + return(0); +} +int free_Number(Number number){ + free(number.scalars); + free(number.base); + return(0); +} + +// copy +int number_cpy(Number input, Number* output){ + init_Number(output,input.length); + number_cpy_noinit(input,output); + return(0); +} +int number_cpy_noinit(Number input, Number* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a number of length %d to another with memory %d\n",input.length, (*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + (*output).scalars[i]=input.scalars[i]; + (*output).base[i]=input.base[i]; + } + (*output).length=input.length; + return(0); +} + +// resize memory +int number_resize(Number* number, int newsize){ + Number new_number; + init_Number(&new_number, newsize); + number_cpy_noinit(*number,&new_number); + free_Number(*number); + *number=new_number; + return(0); +} + +// add a value +int number_append(Q scalar, int base, Number* output){ + if((*output).length>=(*output).memory){ + number_resize(output,2*(*output).memory); + } + (*output).scalars[(*output).length]=scalar; + (*output).base[(*output).length]=base; + (*output).length++; + // not optimal + number_sort(*output,0,(*output).length-1); + return(0); +} + +// concatenate +int number_concat(Number input, Number* output){ + int i; + int offset=(*output).length; + if((*output).length+input.length>(*output).memory){ + // make it longer than needed by (*output).length (for speed) + number_resize(output,2*(*output).length+input.length); + } + for(i=0;i<input.length;i++){ + (*output).scalars[offset+i]=input.scalars[i]; + (*output).base[offset+i]=input.base[i]; + } + (*output).length=offset+input.length; + return(0); +} + +// special numbers +Number number_zero(){ + Number ret; + // don't allocate 0 memory since zero's will usually be used to add to + init_Number(&ret,NUMBER_SIZE); + return(ret); +} +Number number_one(){ + Number ret=number_zero(); + number_add_elem(quot(1,1),1,&ret); + return(ret); +} + +// find a base element +int number_find_base(int base, Number number){ + return(intlist_find(number.base, number.length, base)); +} + +// sort +int number_sort(Number number, int begin, int end){ + int i; + int index; + // the pivot: middle of the array + int pivot=(begin+end)/2; + // if the array is non trivial + if(begin<end){ + // send pivot to the end + number_exchange_terms(pivot, end, number); + + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + if(number.base[i]<number.base[end]){ + // if smaller, exchange with reference index + number_exchange_terms(i, index, number); + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + number_exchange_terms(index, end, number); + + // recurse + number_sort(number, begin, index-1); + number_sort(number, index+1, end); + } + return(0); +} + +// exchange terms (for sorting) +int number_exchange_terms(int index1, int index2, Number number){ + Q qtmp; + int tmp; + + qtmp=number.scalars[index1]; + number.scalars[index1]=number.scalars[index2]; + number.scalars[index2]=qtmp; + + tmp=number.base[index1]; + number.base[index1]=number.base[index2]; + number.base[index2]=tmp; + + return(0); +} + +// checks whether two numbers are equal +// requires both numbers to be sorted +int number_compare(Number x1, Number x2){ + int i; + if(x1.length!=x2.length){ + return(0); + } + for(i=0;i<x1.length;i++){ + if(x1.base[i]!=x2.base[i] || Q_cmp(x1.scalars[i],x2.scalars[i])!=0){ + return(0); + } + } + return(1); +} + + +// add (write result to second element) +int number_add_chain(Number input, Number* inout){ + int i; + for(i=0;i<input.length;i++){ + number_add_elem(input.scalars[i], input.base[i], inout); + } + return(0); +} +// add a single element +int number_add_elem(Q scalar, int base, Number* inout){ + int index; + index=number_find_base(base,*inout); + if(index>=0){ + (*inout).scalars[index]=Q_add((*inout).scalars[index], scalar); + } + else{ + number_append(scalar, base, inout); + } + return(0); +} +// create a new number +int number_add(Number x1, Number x2, Number* out){ + number_cpy(x1,out); + number_add_chain(x2,out); + return(0); +} +// return the number +Number number_add_ret(Number x1, Number x2){ + Number out; + number_add(x1,x2,&out); + return(out); +} + +// multiply +int number_prod(Number x1, Number x2, Number* out){ + int i,j; + int div; + Q new_scalar; + int new_base; + init_Number(out, x1.length); + for(i=0;i<x1.length;i++){ + for(j=0;j<x2.length;j++){ + new_scalar=Q_prod(x1.scalars[i], x2.scalars[j]); + // simplify the base + div=gcd(x1.base[i], x2.base[j]); + new_base=(x1.base[i]/div)*(x2.base[j]/div); + new_scalar.numerator*=div; + + number_add_elem(new_scalar, new_base, out); + } + } + return(0); +} +// write to second number +int number_prod_chain(Number input, Number* inout){ + Number tmp; + number_prod(input,*inout,&tmp); + free_Number(*inout); + *inout=tmp; + return(0); +} +// return result +Number number_prod_ret(Number x1, Number x2){ + Number ret; + number_prod(x1,x2,&ret); + return(ret); +} + +// multiply by a rational +int number_Qprod_chain(Q q, Number* inout){ + int i; + for(i=0;i<(*inout).length;i++){ + (*inout).scalars[i]=Q_prod(q,(*inout).scalars[i]); + } + return(0); +} +// write to output +int number_Qprod(Q q, Number x, Number* inout){ + number_cpy(x,inout); + number_Qprod_chain(q,inout); + return(0); +} +// return result +Number number_Qprod_ret(Q q, Number x){ + Number ret; + number_Qprod(q,x,&ret); + 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]; + } + 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; + } + else{ + fprintf(stderr,"error: attempting to invert 0\n"); + exit(-1); + } + } + 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 +int number_quot(Number x1, Number x2, Number* output){ + Number inv; + number_inverse(x2, &inv); + number_prod(x1, inv, output); + free_Number(inv); + return(0); +} +int number_quot_chain(Number x1, Number* inout){ + number_inverse_inplace(inout); + number_prod_chain(x1, inout); + return(0); +} +Number number_quot_ret(Number x1, Number x2){ + Number ret; + number_quot(x1, x2, &ret); + return(ret); +} + + +// remove 0's +int number_simplify(Number in, Number* out){ + int i; + init_Number(out, in.length); + for(i=0;i<in.length;i++){ + if(in.scalars[i].numerator!=0){ + number_append(in.scalars[i],in.base[i], out); + } + } + return(0); +} + + +// check whether a number is 0 +int number_is_zero(Number x){ + int i; + for(i=0;i<x.length;i++){ + if(x.scalars[i].numerator!=0 && x.base[i]!=0){ + return(0); + } + } + return(1); +} + + +// approximate numerical expression +long double number_double_val(Number x){ + int i; + long double ret=0.; + long double b; + for(i=0;i<x.length;i++){ + if(x.scalars[i].numerator!=0){ + b=1.0*x.base[i]; + ret+=Q_double_value(x.scalars[i])*sqrt(b); + } + } + return(ret); +} + + +// print to string +int number_sprint(Number number, Char_Array* out){ + int i; + Number simp; + number_simplify(number, &simp); + for(i=0;i<simp.length;i++){ + if(i>0){ + char_array_snprintf(out," + "); + } + if(simp.length>1 || (simp.length==1 && simp.base[0]!=1)){ + char_array_append('(',out); + } + Q_sprint(simp.scalars[i], out); + if(simp.length>1 || (simp.length==1 && simp.base[0]!=1)){ + char_array_append(')',out); + } + + if(simp.base[i]!=1){ + char_array_snprintf(out,"s{%d}",simp.base[i]); + } + } + + free_Number(simp); + return(0); +} + +// print to stdout +int number_print(Number number){ + Char_Array buffer; + init_Char_Array(&buffer,5*number.length); + number_sprint(number, &buffer); + printf("%s",buffer.str); + return(0); +} + +#define PP_NULL_MODE 0 +#define PP_NUM_MODE 1 +#define PP_SQRT_MODE 2 +// read from a string +int str_to_Number(char* str, Number* number){ + char* ptr; + int mode; + char* buffer=calloc(str_len(str)+1,sizeof(char)); + char* buffer_ptr=buffer; + Q num; + int base; + // whether there are parentheses in the string + int exist_parenthesis=0; + + init_Number(number, NUMBER_SIZE); + + // init num and base + // init to 0 so that if str is empty, then the number is set to 0 + num=quot(0,1); + base=1; + + mode=PP_NULL_MODE; + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + // read number + case '(': + if(mode==PP_NULL_MODE){ + // init base + base=1; + mode=PP_NUM_MODE; + exist_parenthesis=1; + } + break; + case ')': + if(mode==PP_NUM_MODE){ + str_to_Q(buffer,&num); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_NULL_MODE; + } + break; + + // read sqrt + case '{': + // init num + if(num.numerator==0){ + num=quot(1,1); + } + 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; + break; + case '}': + if(mode==PP_SQRT_MODE){ + sscanf(buffer,"%d",&base); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_NULL_MODE; + } + break; + + // write num + case '+': + if(mode==PP_NULL_MODE){ + number_add_elem(num, base, number); + // re-init num and base + num=quot(0,1); + base=1; + } + break; + + default: + if(mode!=PP_NULL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,*ptr); + } + break; + } + } + + // last step + if(mode==PP_NULL_MODE){ + if(exist_parenthesis==0){ + str_to_Q(str, &num); + } + number_add_elem(num, base, number); + } + + free(buffer); + return(0); +} + +// with Char_Array input +int char_array_to_Number(Char_Array cstr_num,Number* output){ + char* buffer; + char_array_to_str(cstr_num,&buffer); + str_to_Number(buffer, output); + free(buffer); + return(0); +} + + +// -------------------- Number_Matrix --------------------- + +// init +int init_Number_Matrix(Number_Matrix* matrix, int length){ + int i,j; + (*matrix).matrix=calloc(length,sizeof(Number*)); + (*matrix).indices=calloc(length,sizeof(int)); + for(i=0;i<length;i++){ + (*matrix).matrix[i]=calloc(length,sizeof(Number)); + for(j=0;j<length;j++){ + (*matrix).matrix[i][j]=number_zero(); + } + } + (*matrix).length=length; + return(0); +} +int free_Number_Matrix(Number_Matrix matrix){ + int i,j; + for(i=0;i<matrix.length;i++){ + for(j=0;j<matrix.length;j++){ + free_Number(matrix.matrix[i][j]); + } + free(matrix.matrix[i]); + } + free(matrix.matrix); + free(matrix.indices); + return(0); +} + +// Pauli matrices +int Pauli_matrix(int i, Number_Matrix* output){ + init_Number_Matrix(output,2); + switch(i){ + case 1: + number_add_elem(quot(1,1),1,(*output).matrix[0]+1); + number_add_elem(quot(1,1),1,(*output).matrix[1]+0); + break; + case 2: + number_add_elem(quot(-1,1),-1,(*output).matrix[0]+1); + number_add_elem(quot(1,1),-1,(*output).matrix[1]+0); + break; + case 3: + number_add_elem(quot(1,1),1,(*output).matrix[0]+0); + number_add_elem(quot(-1,1),1,(*output).matrix[1]+1); + break; + default: + fprintf(stderr,"error: requested %d-th pauli matrix\n",i); + exit(-1); + } + return(0); +} diff --git a/src/number.h b/src/number.h new file mode 100644 index 0000000..4095f9c --- /dev/null +++ b/src/number.h @@ -0,0 +1,120 @@ +/* +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. +*/ + +/* +Numerical constants (rational numbers and their square roots (including \sqrt{-1}=i)) +*/ + +#ifndef NUMBER_H +#define NUMBER_H + +#include "types.h" + +// init +int init_Number(Number* number, int memory); +int free_Number(Number number); + +// copy +int number_cpy(Number input, Number* output); +int number_cpy_noinit(Number input, Number* output); + +// resize memory +int number_resize(Number* number, int newsize); + +// add a value +int number_append(Q scalar, int base, Number* output); + +// concatenate +int number_concat(Number input, Number* output); + +// special numbers +Number number_zero(); +Number number_one(); + +// find a base element +int number_find_base(int base, Number number); + +// sort +int number_sort(Number number, int begin, int end); +// exchange terms (for sorting) +int number_exchange_terms(int index1, int index2, Number number); + +// checks whether two numbers are equal +int number_compare(Number x1, Number x2); + +// add (write result to second element) +int number_add_chain(Number input, Number* inout); +// add a single element +int number_add_elem(Q scalar, int base, Number* inout); +// create a new number +int number_add(Number x1, Number x2, Number* out); +// return the number +Number number_add_ret(Number x1, Number x_2); + +// multiply +int number_prod(Number x1, Number x2, Number* out); +// write to second number +int number_prod_chain(Number input, Number* inout); +// return result +Number number_prod_ret(Number x1, Number x2); + +// multiply by a rational +int number_Qprod_chain(Q q, Number* inout); +// write to output +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 +int number_quot(Number x1, Number x2, Number* output); +int number_quot_chain(Number x1, Number* inout); +Number number_quot_ret(Number x1, Number x2); + +// remove 0's +int number_simplify(Number in, Number* out); + +// check whether a number is 0 +int number_is_zero(Number x); + +// approximate numerical expression +long double number_double_val(Number x); + +// print to string +int number_sprint(Number number, Char_Array* out); +// print to stdout +int number_print(Number number); +// read from a string +int str_to_Number(char* str, Number* number); +// char array input +int char_array_to_Number(Char_Array cstr_num, Number* number); + + +//------------------------ Number_Matrix -------------------------- +// init +int init_Number_Matrix(Number_Matrix* matrix, int length); +int free_Number_Matrix(Number_Matrix matrix); + +// Pauli matrices +int Pauli_matrix(int i, Number_Matrix* output); + +#endif diff --git a/src/numkondo.c b/src/numkondo.c new file mode 100644 index 0000000..dce7de6 --- /dev/null +++ b/src/numkondo.c @@ -0,0 +1,226 @@ +/* +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. +*/ + +/* +numkondo + +Compute the flow of a flow equation numerically + +*/ + + +#include <stdio.h> +#include <stdlib.h> + +// pre-compiler definitions +#include "definitions.cpp" + +// rccs +#include "rcc.h" +// grouped representation of polynomials +#include "grouped_polynomial.h" +// command line parser +#include "cli_parser.h" +// parse input file +#include "parse_file.h" +// numerical flow +#include "flow.h" +// arrays +#include "array.h" + +// read cli arguments +int read_args_numkondo(int argc,const char* argv[], Str_Array* str_args, Numkondo_Options* opts); +// print usage message +int print_usage_numkondo(); +// compute flow +int numflow(Str_Array str_args, Numkondo_Options opts); + + +int main (int argc, const char* argv[]){ + // string arguments + Str_Array str_args; + // options + Numkondo_Options opts; + + // read command-line arguments + read_args_numkondo(argc,argv,&str_args,&opts); + + numflow(str_args, opts); + + //free memory + free_Str_Array(str_args); + return(0); +} + + +// parse command-line arguments +#define CP_FLAG_NITER 1 +#define CP_FLAG_TOL 2 +#define CP_FLAG_RCCS 3 +int read_args_numkondo(int argc,const char* argv[], Str_Array* str_args, Numkondo_Options* opts){ + int i; + // pointers + char* ptr; + // file to read the polynomial from in flow mode + const char* file=""; + // flag that indicates what argument is being read + int flag=0; + // 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; + // default niter + (*opts).niter=100; + // default to 0 tolerance + (*opts).tol=0; + // mark rccstring so that it can be recognized whether it has been set or not + (*opts).eval_rccstring.length=-1; + +// loop over arguments +for(i=1;i<argc;i++){ + // flag + if(argv[i][0]=='-'){ + for(ptr=((char*)argv[i])+1;*ptr!='\0';ptr++){ + switch(*ptr){ + // final step: display the final step of the integration with maximal precision + case 'F': + (*opts).display_mode=DISPLAY_FINAL; + break; + // niter + case 'N': + flag=CP_FLAG_NITER; + break; + // tolerance + case 'D': + flag=CP_FLAG_TOL; + break; + // initial condition + case 'I': + flag=CP_FLAG_RCCS; + break; + // print version + case 'v': + printf("numkondo " VERSION "\n"); + exit(1); + break; + } + } + } + // if the niter flag is up + else if (flag==CP_FLAG_NITER){ + // read niter + sscanf(argv[i],"%d",&((*opts).niter)); + // reset flag + flag=0; + } + // tolerance + else if (flag==CP_FLAG_TOL){ + sscanf(argv[i],"%Lf",&((*opts).tol)); + flag=0; + } + // init condition + else if(flag==CP_FLAG_RCCS){ + str_to_char_array((char*)argv[i], &((*opts).eval_rccstring)); + 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); +} + +// print usage message +int print_usage_numkondo(){ + printf("\nusage:\n numkondo [-F] [-N niter] [-D tolerance] [-I initial_condition] <filename>\n\n"); + return(0); +} + + +// numerical computation of the flow +int numflow(Str_Array str_args, Numkondo_Options opts){ + // index of the entry in the input file + int arg_index; + // list of rccs + Labels labels; + // initial condition + RCC init_cd; + // flow equation + Grouped_Polynomial flow_equation; + + // parse id table + arg_index=find_str_arg("labels", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no labels entry in the configuration file\n"); + exit(-1); + } + else{ + parse_labels(str_args.strs[arg_index], &labels); + } + + // parse flow equation + arg_index=find_str_arg("flow_equation", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no flow equation entry in the configuration file\n"); + exit(-1); + } + else{ + char_array_to_Grouped_Polynomial(str_args.strs[arg_index], &flow_equation); + } + + // initial conditions + // check they were not specified on the command line + if(opts.eval_rccstring.length==-1){ + arg_index=find_str_arg("initial_condition", str_args); + if(arg_index<0){ + fprintf(stderr,"error: no initial condition in the configuration file or on the command line\n"); + exit(-1); + } + else{ + char_array_cpy(str_args.strs[arg_index],&(opts.eval_rccstring)); + } + } + // initialize the rccs + prepare_init(flow_equation.indices,flow_equation.length,&init_cd); + // read rccs from string + if(opts.eval_rccstring.length!=-1){ + parse_init_cd(opts.eval_rccstring, &init_cd); + free_Char_Array(opts.eval_rccstring); + } + + numerical_flow(flow_equation, init_cd, labels, opts.niter, opts.tol, opts.display_mode); + + free_RCC(init_cd); + + // free memory + free_Labels(labels); + free_Grouped_Polynomial(flow_equation); + return(0); +} + diff --git a/src/parse_file.c b/src/parse_file.c new file mode 100644 index 0000000..6054372 --- /dev/null +++ b/src/parse_file.c @@ -0,0 +1,796 @@ +/* +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 "parse_file.h" + +#include <stdio.h> +#include <stdlib.h> +#include "array.h" +#include "fields.h" +#include "rational.h" +#include "number.h" +#include "polynomial.h" +#include "rcc.h" +#include "definitions.cpp" +#include "istring.h" +#include "tools.h" +#include "idtable.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 +// indices +#define PP_INDEX_MODE 11 +// factors or monomials +#define PP_BRACKET_MODE 12 +// labels +#define PP_LABEL_MODE 13 +// polynomial +#define PP_POLYNOMIAL_MODE 14 +// group +#define PP_GROUP_MODE 15 + + +// 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; + + // allocate memory + init_Fields_Table(fields); + + // loop over input + mode=PP_NULL_MODE; + for(j=0;j<str_fields.length;j++){ + if(comment==1){ + if(str_fields.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_fields.str[j]){ + // parameters + case 'h': + if(mode==PP_NULL_MODE){ + mode=PP_PARAMETER_MODE; + } + break; + // external fields + case 'x': + if(mode==PP_NULL_MODE){ + mode=PP_EXTERNAL_MODE; + } + break; + // internal fields + case 'i': + if(mode==PP_NULL_MODE){ + mode=PP_INTERNAL_MODE; + } + break; + case 'f': + if(mode==PP_NULL_MODE){ + mode=PP_FERMIONS_MODE; + } + break; + + // reset buffer + case ':': + buffer_ptr=buffer; + *buffer_ptr='\0'; + break; + + // write to fields + case ',': + 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)); + } + 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)); + } + mode=PP_NULL_MODE; + break; + + // comment + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str_fields.str[j]); + } + break; + } + } + } + free(buffer); + return(0); +} + + +// parse symbols list +// write result to fields +int parse_input_symbols(Char_Array str_symbols, Fields_Table* fields){ + // buffer + char* buffer=calloc(str_symbols.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Polynomial polynomial; + int index; + int i,j; + int mode; + int comment=0; + + // loop over input + mode=PP_INDEX_MODE; + for(j=0;j<str_symbols.length;j++){ + if(comment==1){ + if(str_symbols.str[j]=='\n'){ + comment=0; + } + } + // stay in polynomial mode until ',' + else if(mode==PP_POLYNOMIAL_MODE){ + if(str_symbols.str[j]==','){ + // parse polynomial + str_to_Polynomial(buffer, &polynomial); + // write index and polynomial + symbols_append_noinit(index, polynomial, &((*fields).symbols)); + mode=PP_INDEX_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,str_symbols.str[j]); + } + } + else{ + switch(str_symbols.str[j]){ + // polynomial mode + case '=': + if(mode==PP_INDEX_MODE){ + // read index + sscanf(buffer,"%d",&index); + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_POLYNOMIAL_MODE; + } + break; + + // comment + case '#': + comment=1; + break; + + default: + buffer_ptr=str_addchar(buffer_ptr,str_symbols.str[j]); + break; + } + } + } + + // last step + if(polynomial.length>0){ + str_to_Polynomial(buffer, &polynomial); + symbols_append_noinit(index, polynomial, &((*fields).symbols)); + } + + // simplify + for(i=0;i<(*fields).symbols.length;i++){ + polynomial_simplify((*fields).symbols.expr+i, *fields); + } + + free(buffer); + return(0); +} + +// parse groups of independent fields +int parse_input_groups(Char_Array str_groups, Groups* groups){ + // buffer + char* buffer=calloc(str_groups.length+1,sizeof(char)); + char* buffer_ptr=buffer; + int index; + int j; + Int_Array group; + int mode; + int comment=0; + + // alloc + init_Groups(groups, GROUP_SIZE); + + // loop over input + mode=PP_NULL_MODE; + for(j=0;j<str_groups.length;j++){ + if(comment==1){ + if(str_groups.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_groups.str[j]){ + // group mode + case '(': + if(mode==PP_NULL_MODE){ + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + // init + init_Int_Array(&group, GROUP_SIZE); + mode=PP_GROUP_MODE; + } + break; + case')': + if(mode==PP_GROUP_MODE){ + sscanf(buffer,"%d",&index); + int_array_append(index, &group); + groups_append_noinit(group, groups); + mode=PP_NULL_MODE; + } + break; + + // read index + case',': + if(mode==PP_GROUP_MODE){ + sscanf(buffer,"%d",&index); + int_array_append(index, &group); + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + + // comment + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str_groups.str[j]); + } + break; + } + } + } + + free(buffer); + return(0); +} + + +// parse identities between fields +// write result to fields +int parse_input_identities(Char_Array str_identities, Fields_Table* fields){ + // 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; + + init_Int_Array(&monomial, MONOMIAL_SIZE); + + // loop over input + mode=PP_NULL_MODE; + for(j=0;j<str_identities.length;j++){ + if(comment==1){ + if(str_identities.str[j]=='\n'){ + comment=0; + } + } + // stay in polynomial mode until ',' + else if(mode==PP_POLYNOMIAL_MODE){ + if(str_identities.str[j]==','){ + // parse polynomial + str_to_Polynomial(buffer, &polynomial); + // write monomial and polynomial + identities_append_noinit(monomial, polynomial, &((*fields).ids)); + // realloc + init_Int_Array(&monomial, MONOMIAL_SIZE); + mode=PP_NULL_MODE; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,str_identities.str[j]); + } + } + else{ + switch(str_identities.str[j]){ + // monomial + case '[': + if(mode==PP_NULL_MODE){ + mode=PP_INDEX_MODE; + } + if(mode==PP_INDEX_MODE){ + mode=PP_BRACKET_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // for notational homogeneity + case 'f': + if(mode==PP_BRACKET_MODE){ + mode=PP_FIELD_MODE; + } + break; + // write monomial term + case ']': + if(mode==PP_FIELD_MODE){ + sscanf(buffer,"%d",&i); + int_array_append(i,&monomial); + mode=PP_INDEX_MODE; + } + break; + + // polynomial mode + case '=': + if(mode==PP_INDEX_MODE){ + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_POLYNOMIAL_MODE; + } + break; + + // comment + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str_identities.str[j]); + } + break; + } + } + } + + // last step + if(mode==PP_POLYNOMIAL_MODE){ + str_to_Polynomial(buffer, &polynomial); + identities_append_noinit(monomial, polynomial, &((*fields).ids)); + } + else{ + free_Int_Array(monomial); + } + + // sort + // don't use the identities to simplify + tmp=(*fields).ids.length; + (*fields).ids.length=0; + for(i=0;i<tmp;i++){ + sign=1; + monomial_sort((*fields).ids.lhs[i], 0, (*fields).ids.lhs[i].length-1, *fields, &sign); + polynomial_simplify((*fields).ids.rhs+i, *fields); + polynomial_multiply_Qscalar((*fields).ids.rhs[i],quot(sign,1)); + } + (*fields).ids.length=tmp; + + free(buffer); + return(0); +} + +// parse propagator +int parse_input_propagator(Char_Array str_propagator, Polynomial_Matrix* propagator, Fields_Table fields){ + // buffer + char* buffer=calloc(str_propagator.length+1,sizeof(char)); + char* buffer_ptr=buffer; + int i,j; + int index1=-1; + int index2=-1; + int mode; + int comment=0; + + // allocate memory + init_Polynomial_Matrix(propagator, fields.internal.length); + + // copy indices + for(i=0;i<fields.internal.length;i++){ + (*propagator).indices[i]=fields.internal.values[i]; + } + + // loop over input + mode=PP_INDEX_MODE; + for(j=0;j<str_propagator.length;j++){ + if(comment==1){ + if(str_propagator.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_propagator.str[j]){ + // indices + case ';': + if(mode==PP_INDEX_MODE){ + sscanf(buffer,"%d",&i); + index1=intlist_find_err((*propagator).indices, (*propagator).length, i); + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case ':': + if(mode==PP_INDEX_MODE){ + sscanf(buffer,"%d",&i); + index2=intlist_find_err((*propagator).indices, (*propagator).length, i); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_POLYNOMIAL_MODE; + } + break; + + // num + case ',': + if(mode==PP_POLYNOMIAL_MODE && index1>=0 && index2>=0){ + free_Polynomial((*propagator).matrix[index1][index2]); + str_to_Polynomial(buffer,(*propagator).matrix[index1]+index2); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_INDEX_MODE; + } + 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); + } + + free(buffer); + return(0); +} + + +// 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); + return(0); +} + + + +// parse id table +// fields argument for sorting +int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table fields){ + // 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; + + // allocate memory + init_Id_Table(idtable,EQUATION_SIZE); + + // loop over input + mode=PP_INDEX_MODE; + for(j=0;j<str_idtable.length;j++){ + if(comment==1){ + if(str_idtable.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_idtable.str[j]){ + // end polynomial mode + case ',': + // write polynomial + if(mode==PP_POLYNOMIAL_MODE){ + str_to_Polynomial(buffer,&polynomial); + // add to idtable + idtable_append_noinit(index,polynomial,idtable); + mode=PP_INDEX_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + + case ':': + if(mode==PP_INDEX_MODE){ + sscanf(buffer,"%d",&index); + mode=PP_POLYNOMIAL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + + // comment + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str_idtable.str[j]); + } + break; + } + } + } + + //last step + if(mode==PP_POLYNOMIAL_MODE){ + str_to_Polynomial(buffer,&polynomial); + idtable_append_noinit(index,polynomial,idtable); + } + + // sort + for(j=0;j<(*idtable).length;j++){ + polynomial_simplify((*idtable).polynomials+j, fields); + } + + free(buffer); + return(0); +} + +// parse a list of labels +int parse_labels(Char_Array str_labels, Labels* labels){ + // buffer + char* buffer=calloc(str_labels.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Char_Array label; + int index; + int j; + int mode; + int comment=0; + + // allocate memory + init_Labels(labels,EQUATION_SIZE); + + // loop over input + mode=PP_INDEX_MODE; + for(j=0;j<str_labels.length;j++){ + if(comment==1){ + if(str_labels.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_labels.str[j]){ + case '"': + if(mode==PP_INDEX_MODE){ + mode=PP_LABEL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + // write + else if(mode==PP_LABEL_MODE){ + str_to_char_array(buffer,&label); + labels_append_noinit(label,index,labels); + mode=PP_INDEX_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + + case ':': + // write + if(mode==PP_INDEX_MODE){ + sscanf(buffer,"%d",&index); + } + break; + + // characters to ignore + case ' ':break; + case '&':break; + case '\n':break; + case ',':break; + + // comment + case '#': + comment=1; + break; + + default: + buffer_ptr=str_addchar(buffer_ptr,str_labels.str[j]); + break; + } + } + } + + free(buffer); + return(0); +} + + +// read initial condition for numerical computation +int parse_init_cd(Char_Array init_cd, RCC* init){ + char* buffer=calloc(init_cd.length+1,sizeof(char)); + char* buffer_ptr=buffer; + int index=0; + int i,j; + int comment_mode=0; + int dcount=0; + + *buffer_ptr='\0'; + // loop over the input + for(j=0;j<init_cd.length;j++){ + if(comment_mode==1){ + if(init_cd.str[j]=='\n'){ + comment_mode=0; + } + } + else{ + switch(init_cd.str[j]){ + // new term + case ',': + // write init + sscanf(buffer,"%Lf",(*init).values+intlist_find_err((*init).indices,(*init).length,index)); + // reset buffer + buffer_ptr=buffer; + *buffer_ptr='\0'; + // reset derivatives counter + dcount=0; + break; + // separator + case ':': + // write index + sscanf(buffer,"%d",&i); + if(i<0){ + index=i-dcount*DOFFSET; + } + else{ + index=i+dcount*DOFFSET; + } + buffer_ptr=buffer; + *buffer_ptr='\0'; + break; + // derivatives + case 'd': + dcount++; + break; + + // characters to ignore + case ' ':break; + case '&':break; + case '\n':break; + + // comments + case '#': + comment_mode=1; + break; + + default: + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,init_cd.str[j]); + break; + } + } + } + + // write init + sscanf(buffer,"%Lf",(*init).values+unlist_find((*init).indices,(*init).length,index)); + + free(buffer); + return(0); +} + + +// set indices and length of init +int prepare_init(int* indices, int length, RCC* init){ + int i; + init_RCC(init, length); + for(i=0;i<length;i++){ + (*init).indices[i]=indices[i]; + // set constants to 1 + if(indices[i]<0 && indices[i]>-DOFFSET){ + (*init).values[i]=1.; + } + else{ + (*init).values[i]=0.; + } + + } + return(0); +} diff --git a/src/parse_file.h b/src/parse_file.h new file mode 100644 index 0000000..b51103a --- /dev/null +++ b/src/parse_file.h @@ -0,0 +1,56 @@ +/* +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. +*/ + +/* +Parse the input file +*/ + +#ifndef PARSE_FILE_H +#define PARSE_FILE_H + +#include "types.h" + +// 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 groups of independent fields +int parse_input_groups(Char_Array str_groups, Groups* groups); + +// parse identities between fields +int parse_input_identities(Char_Array str_identities, Fields_Table* fields); + +// 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); + +// parse id table +int parse_input_id_table(Char_Array str_idtable, Id_Table* idtable, Fields_Table fields); + +// parse a list of labels +int parse_labels(Char_Array str_labels, Labels* labels); + +// parse the initial condition +int parse_init_cd(Char_Array init_cd, RCC* init); + +// set indices and length of init +int prepare_init(int* indices, int length, RCC* init); + +#endif diff --git a/src/polynomial.c b/src/polynomial.c new file mode 100644 index 0000000..639728a --- /dev/null +++ b/src/polynomial.c @@ -0,0 +1,1263 @@ +/* +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 "polynomial.h" + +#include <stdio.h> +#include <stdlib.h> +#include "definitions.cpp" +#include "rational.h" +#include "tools.h" +#include "mean.h" +#include "coefficient.h" +#include "istring.h" +#include "array.h" +#include "number.h" +#include "fields.h" + + +// allocate memory +int init_Polynomial(Polynomial* polynomial,int size){ + (*polynomial).monomials=calloc(size,sizeof(Int_Array)); + (*polynomial).factors=calloc(size,sizeof(Int_Array)); + (*polynomial).nums=calloc(size,sizeof(Number)); + (*polynomial).length=0; + (*polynomial).memory=size; + return(0); +} + +// free memory +int free_Polynomial(Polynomial polynomial){ + int i; + for(i=0;i<polynomial.length;i++){ + free_Int_Array(polynomial.monomials[i]); + free_Int_Array(polynomial.factors[i]); + free_Number(polynomial.nums[i]); + } + free(polynomial.monomials); + free(polynomial.factors); + free(polynomial.nums); + + return(0); +} + +// resize the memory allocated to a polynomial +int resize_polynomial(Polynomial* polynomial,int new_size){ + Polynomial new_poly; + int i; + + init_Polynomial(&new_poly,new_size); + for(i=0;i<(*polynomial).length;i++){ + new_poly.monomials[i]=(*polynomial).monomials[i]; + new_poly.factors[i]=(*polynomial).factors[i]; + new_poly.nums[i]=(*polynomial).nums[i]; + } + new_poly.length=(*polynomial).length; + + free((*polynomial).monomials); + free((*polynomial).factors); + free((*polynomial).nums); + + *polynomial=new_poly; + return(0); +} + +// copy a polynomial +int polynomial_cpy(Polynomial input, Polynomial* output){ + init_Polynomial(output,input.length); + polynomial_cpy_noinit(input,output); + return(0); +} +int polynomial_cpy_noinit(Polynomial input, Polynomial* output){ + int i; + if((*output).memory<input.length){ + fprintf(stderr,"error: trying to copy a polynomial of length %d to another with memory %d\n",input.length,(*output).memory); + exit(-1); + } + for(i=0;i<input.length;i++){ + int_array_cpy(input.monomials[i],(*output).monomials+i); + int_array_cpy(input.factors[i],(*output).factors+i); + number_cpy(input.nums[i],(*output).nums+i); + } + (*output).length=input.length; + + return(0); +} + +// append an element to a polynomial +int polynomial_append(Int_Array monomial, Int_Array factor, Number num, Polynomial* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_polynomial(output,2*(*output).memory+1); + } + + // copy and allocate + int_array_cpy(monomial,(*output).monomials+offset); + int_array_cpy(factor,(*output).factors+offset); + number_cpy(num,(*output).nums+offset); + //increment length + (*output).length++; + + return(0); +} +// append an element to a polynomial without allocating memory +int polynomial_append_noinit(Int_Array monomial, Int_Array factor, Number num, Polynomial* output){ + int offset=(*output).length; + + if((*output).length>=(*output).memory){ + resize_polynomial(output,2*(*output).memory+1); + } + + // copy without allocating + (*output).monomials[offset]=monomial; + (*output).factors[offset]=factor; + (*output).nums[offset]=num; + // increment length + (*output).length++; + return(0); +} +// noinit, and if there already exists an element with the same monomial and factor, then just add numbers +int polynomial_append_noinit_inplace(Int_Array monomial, Int_Array factor, Number num, Polynomial* output){ + int i; + int foundit=0; + for(i=0;i<(*output).length;i++){ + if(int_array_cmp(monomial, (*output).monomials[i])==0 && int_array_cmp(factor, (*output).factors[i])==0){ + number_add_chain(num,(*output).nums+i); + foundit=1; + free_Number(num); + free_Int_Array(monomial); + free_Int_Array(factor); + break; + } + } + if(foundit==0){ + polynomial_append_noinit(monomial, factor, num, output); + } + return(0); +} + +// concatenate two polynomials +int polynomial_concat(Polynomial input, Polynomial* output){ + int i; + for(i=0;i<input.length;i++){ + polynomial_append(input.monomials[i],input.factors[i],input.nums[i],output); + } + return(0); +} +// noinit +int polynomial_concat_noinit(Polynomial input, Polynomial* output){ + int i; + for(i=0;i<input.length;i++){ + polynomial_append_noinit(input.monomials[i],input.factors[i],input.nums[i],output); + } + + // free input arrays + free(input.monomials); + free(input.factors); + free(input.nums); + return(0); +} +// noinit, inplace +int polynomial_concat_noinit_inplace(Polynomial input, Polynomial* output){ + int i; + for(i=0;i<input.length;i++){ + polynomial_append_noinit_inplace(input.monomials[i],input.factors[i],input.nums[i],output); + } + + // free input arrays + free(input.monomials); + free(input.factors); + free(input.nums); + return(0); +} + +// add polynomials +int polynomial_add_chain(Polynomial input, Polynomial* inout, Fields_Table fields){ + polynomial_concat(input,inout); + polynomial_simplify(inout, fields); + return(0); +} +// add polynomials (noinit) +int polynomial_add_chain_noinit(Polynomial input, Polynomial* inout, Fields_Table fields){ + polynomial_concat_noinit(input,inout); + polynomial_simplify(inout, fields); + return(0); +} + +// multiply a polynomial by a scalar +int polynomial_multiply_scalar(Polynomial polynomial, Number num){ + int i; + for(i=0;i<polynomial.length;i++){ + number_prod_chain(num,polynomial.nums+i); + } + return(0); +} +// multiply a polynomial by a rational number +int polynomial_multiply_Qscalar(Polynomial polynomial, Q q){ + int i; + for(i=0;i<polynomial.length;i++){ + number_Qprod_chain(q,polynomial.nums+i); + } + return(0); +} + +// change the sign of the monomials in a polynomial +int polynomial_conjugate(Polynomial polynomial){ + int i,j; + for(i=0;i<polynomial.length;i++){ + for(j=0;j<polynomial.monomials[i].length;j++){ + polynomial.monomials[i].values[j]*=-1; + } + } + return(0); +} + + +// returns an initialized polynomial, equal to 1 +Polynomial polynomial_one(){ + Polynomial ret; + Int_Array dummy_monomial; + Int_Array dummy_factor; + + init_Polynomial(&ret,1); + init_Int_Array(&dummy_monomial,1); + init_Int_Array(&dummy_factor,1); + polynomial_append_noinit(dummy_monomial,dummy_factor,number_one(),&ret); + + return(ret); +} + +// returns an initialized polynomial, equal to 0 +Polynomial polynomial_zero(){ + Polynomial ret; + Int_Array dummy_monomial; + Int_Array dummy_factor; + + init_Polynomial(&ret,1); + init_Int_Array(&dummy_monomial,1); + init_Int_Array(&dummy_factor,1); + polynomial_append_noinit(dummy_monomial,dummy_factor,number_zero(),&ret); + + return(ret); +} + +// check whether a polynomial is 0 +int polynomial_is_zero(Polynomial poly){ + int i; + for(i=0;i<poly.length;i++){ + if(number_is_zero(poly.nums[i])==0){ + return(0); + } + } + return(1); +} + +// compute V^p +int polynomial_power(Polynomial input_polynomial, Polynomial* output, int power, Fields_Table fields){ + int i,j; + int* current_term; + // out buffers: since we first check whether the monomial vanishes before adding it to the output, + // it is more efficient to concatenate the monomials in a separate variable, and then add it to the ouput + // instead of incrementally adding terms to the output + Int_Array out_monomial; + int monomial_size; + Int_Array out_factor; + int factor_size; + Number out_num; + + init_Polynomial(output, POLY_SIZE); + + // trivial case + if(power==0){ + init_Int_Array(&out_monomial, 1); + init_Int_Array(&out_factor, 1); + polynomial_append_noinit(out_monomial, out_factor, number_one(), output); + return(0); + } + + // initialize current term + current_term=calloc(power,sizeof(int)); + for(i=0;i<power;i++){ + current_term[i]=0; + } + + // loop over terms; the loop stops when all the pointers in the list + // mentioned above are at the end of the input polynomial + while(current_term[0]<input_polynomial.length){ + // compute the amount of memory to allocate + for(i=0,monomial_size=0,factor_size=0;i<power;i++){ + monomial_size+=input_polynomial.monomials[current_term[i]].length; + factor_size+=input_polynomial.factors[current_term[i]].length; + } + // allocate + init_Int_Array(&out_monomial, monomial_size); + init_Int_Array(&out_factor, factor_size); + out_num=number_one(); + + // concatenate monomial and factor + for(i=0;i<power;i++){ + int_array_concat(input_polynomial.monomials[current_term[i]],&out_monomial); + int_array_concat(input_polynomial.factors[current_term[i]],&out_factor); + number_prod_chain(input_polynomial.nums[current_term[i]], &out_num); + } + + // check whether the monomial vanishes + if(check_monomial(out_monomial, fields)==1){ + // multinomial combinatorial factor n!/(m1!m2!m3!...) + number_Qprod_chain(quot(factorial(power),multinomial(power,current_term)),&out_num); + // write monomials and factors + polynomial_append_noinit(out_monomial, out_factor, out_num, output); + } + else{ + free_Int_Array(out_monomial); + free_Int_Array(out_factor); + free_Number(out_num); + } + + // move to the next term of V^p by advancing the last pointer if possible, + // the next to last if not, and so forth, until all the pointers have + // reached the end of the input polynomial + (current_term[power-1])++; + // loop until the last pointer is in an adequate place or the first + // pointer has reached the end + for(i=power-2;current_term[0]<input_polynomial.length && current_term[power-1]>=input_polynomial.length;i--){ + // try to advance pointer + (current_term[i])++; + // if the step fails, keep on looping, if not, set all the following + // pointers to the latest position + if(current_term[i]<input_polynomial.length){ + for(j=i+1;j<power;j++){ + current_term[j]=current_term[i]; + } + } + } + } + + polynomial_simplify(output, fields); + + // free memory + free(current_term); + return(0); +} + + +// compute V*W +int polynomial_prod(Polynomial input1, Polynomial input2, Polynomial* output, Fields_Table fields){ + polynomial_cpy(input2,output); + polynomial_prod_chain(input1,output, fields); + return(0); +} +// chain +int polynomial_prod_chain_nosimplify(Polynomial input, Polynomial* inout, Fields_Table fields){ + // position in V and W + int pos1, pos2; + Int_Array out_monomial; + Int_Array out_factor; + Number out_num; + // 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; + + // loop over terms + for(pos1=0;pos1<inout_length;pos1++){ + // multiply first term of input to inout[pos1] + // search for the first possible product + firstpos=-1; + for(pos2=0; pos2<input.length; pos2++){ + if(check_monomial_willnot_vanish((*inout).monomials[pos1],input.monomials[pos2],fields)==1){ + firstpos=pos2; + pos2++; + break; + } + } + + // if there was no possible product + if(firstpos==-1){ + number_Qprod_chain(quot(0,1),(*inout).nums+pos1); + } + else{ + // add other terms at the end of inout + for(;pos2<input.length;pos2++){ + // check whether the term will vanish + if(check_monomial_willnot_vanish((*inout).monomials[pos1],input.monomials[pos2],fields)==1){ + // allocate + init_Int_Array(&out_monomial, (*inout).monomials[pos1].length+input.monomials[pos2].length); + init_Int_Array(&out_factor, (*inout).factors[pos1].length+input.factors[pos2].length); + + // concatenate monomial and factor + int_array_concat((*inout).monomials[pos1],&out_monomial); + int_array_concat(input.monomials[pos2],&out_monomial); + int_array_concat((*inout).factors[pos1],&out_factor); + int_array_concat(input.factors[pos2],&out_factor); + number_prod((*inout).nums[pos1],input.nums[pos2],&out_num); + + // write monomials and factors + polynomial_append_noinit(out_monomial, out_factor, out_num, inout); + } + } + // first term + int_array_concat(input.monomials[firstpos],(*inout).monomials+pos1); + int_array_concat(input.factors[firstpos],(*inout).factors+pos1); + number_prod_chain(input.nums[firstpos],(*inout).nums+pos1); + } + } + + return(0); +} +// simplify +int polynomial_prod_chain(Polynomial input, Polynomial* inout, Fields_Table fields){ + polynomial_prod_chain_nosimplify(input, inout, fields); + polynomial_simplify(inout, fields); + return(0); +} + +// exp(V) +int polynomial_exponential(Polynomial input_polynomial, Polynomial* output, Fields_Table fields){ + // a buffer for the result of a given power + Polynomial tmp_poly; + // a buffer for the previous power + Polynomial previous_power; + // power + int power=1; + Int_Array out_monomial; + Int_Array out_factor; + + // allocate memory + init_Polynomial(output,POLY_SIZE); + + // 1 + init_Int_Array(&out_monomial, 1); + init_Int_Array(&out_factor, 1); + polynomial_append_noinit(out_monomial, out_factor, number_one(), output); + + while(1){ + if(power>1){ + if(power>33){ + fprintf(stderr,"error: trying to take a power of a polynomial that is too high (>33)\n"); + exit(-1); + } + // next power + polynomial_prod(input_polynomial,previous_power,&tmp_poly, fields); + + // free + free_Polynomial(previous_power); + } + else{ + polynomial_cpy(input_polynomial,&tmp_poly); + } + + // if the power is high enough that V^p=0, then stop + if(tmp_poly.length==0){ + free_Polynomial(tmp_poly); + break; + } + + // copy for next power + polynomial_cpy(tmp_poly,&previous_power); + + // 1/p! + polynomial_multiply_Qscalar(tmp_poly,quot(1,factorial(power))); + // append tmp to the output + polynomial_concat_noinit(tmp_poly,output); + + // increase power + power++; + } + + return(0); +} + + +// log(1+W) +int polynomial_logarithm(Polynomial input_polynomial,Polynomial* output, Fields_Table fields){ + // a buffer for the result of a given power + Polynomial tmp_poly; + // a buffer for the previous power + Polynomial previous_power; + // power + int power=1; + + // allocate memory + init_Polynomial(output,POLY_SIZE); + + while(1){ + if(power>1){ + // next power + polynomial_prod(input_polynomial,previous_power,&tmp_poly, fields); + + // free + free_Polynomial(previous_power); + } + else{ + polynomial_cpy(input_polynomial,&tmp_poly); + } + + // if the power is high enough that V^p=0, then stop + if(tmp_poly.length==0){ + free_Polynomial(tmp_poly); + break; + } + + // copy for next power + polynomial_cpy(tmp_poly,&previous_power); + + // (-1)^{p-1}/p + polynomial_multiply_Qscalar(tmp_poly,quot(ipower(-1,power-1),power)); + // append tmp to the output + polynomial_concat_noinit(tmp_poly,output); + + // increase power + power++; + } + + return(0); +} + +// check whether a monomial vanishes +int check_monomial(Int_Array monomial, Fields_Table fields){ + int i,j; + for(i=0;i<monomial.length;i++){ + // check for repetitions + if(is_fermion(monomial.values[i], fields)==1){ + for(j=i+1;j<monomial.length;j++){ + if(monomial.values[j]==monomial.values[i]){ + return(0); + } + } + } + } + return(1); +} +// check whether the product of two monomials will vanish +int check_monomial_willnot_vanish(Int_Array monomial1, Int_Array monomial2, Fields_Table fields){ + int i,j; + for(i=0;i<monomial1.length;i++){ + // check for repetitions + if(is_fermion(monomial1.values[i], fields)==1){ + for(j=0;j<monomial2.length;j++){ + if(monomial2.values[j]==monomial1.values[i]){ + return(0); + } + } + } + } + return(1); +} + +// check whether one can add a term to a monomial without creating repetitions +int check_monomial_addterm(Int_Array monomial, Int_Array term, Fields_Table fields){ + int i,j; + for(i=0;i<term.length;i++){ + // check for repetitions + if(is_fermion(term.values[i], fields)==1){ + for(j=0;j<monomial.length;j++){ + if(monomial.values[j]==term.values[i]){ + return(0); + } + } + } + } + return(1); +} + +// check whether a monomial vanishes or has unmatched +/- fields +int check_monomial_match(Int_Array monomial, Fields_Table fields){ + int i,j; + int match=0; + for(i=0;i<monomial.length;i++){ + // count match + if(field_type(monomial.values[i], fields)==FIELD_INTERNAL){ + if(monomial.values[i]>0){ + match++; + } + else if(monomial.values[i]<0){ + match--; + } + } + + // check for repetitions + if(is_fermion(monomial.values[i], fields)==1){ + for(j=i+1;j<monomial.length;j++){ + if(monomial.values[j]==monomial.values[i]){ + return(0); + } + } + } + } + if(match==0){ + return(1); + } + else{ + // different return codes depending on why the monomial was rejected + return(-1); + } +} + +// remove terms with more plus internal fields than minus ones +int remove_unmatched_plusminus(Polynomial* polynomial, Fields_Table fields){ + int i,j; + int match_internals; + int type; + Polynomial output; + + init_Polynomial(&output, (*polynomial).length); + + for(i=0;i<(*polynomial).length;i++){ + match_internals=0; + for(j=0;j<(*polynomial).monomials[i].length;j++){ + // check for unmatched internal fields + type=field_type((*polynomial).monomials[i].values[j],fields); + if(type==FIELD_INTERNAL){ + if((*polynomial).monomials[i].values[j]>0){ + match_internals++; + } + else if((*polynomial).monomials[i].values[j]<0){ + match_internals--; + } + } + // don't remove a term containing symbols + else if(type==FIELD_SYMBOL){ + match_internals=0; + break; + } + } + if(match_internals==0){ + polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], &output); + } + } + + free_Polynomial(*polynomial); + *polynomial=output; + return(0); +} + + +// denominator of a multinomal factor: m1!m2!... +// requires terms to be sorted +int multinomial(int power,int* terms){ + int multiple=1; + int ret=1; + int i; + // the number of numbers to be multiplied in the multinomial is + // equal to power-1 (the first is 1) + for(i=1;i<power;i++){ + // if there is a degeneracy, then increment the multiple by + // which the multinomial is multiplied + if(terms[i-1]==terms[i]){ + multiple++; + } + // if there is no degeneracy, reset it to 1 + else{ + multiple=1; + } + // multiply the result by the multiple + ret*=multiple; + } + return(ret); +} + + +// simplify a Polynomial +// the fields table is there to compute the sign coming from re-arranging monomials +int polynomial_simplify(Polynomial* polynomial, Fields_Table fields){ + int i; + int monomial_cmp; + int factor_cmp; + int sign; + Polynomial output; + init_Polynomial(&output,(*polynomial).length); + // the combination of numerical factors + Number new_num; + init_Number(&new_num,NUMBER_SIZE); + + // sort monomials and factors + for(i=0;i<(*polynomial).length;i++){ + sign=1; + monomial_sort((*polynomial).monomials[i],0,(*polynomial).monomials[i].length-1,fields,&sign); + number_Qprod_chain(quot(sign,1),(*polynomial).nums+i); + int_array_sort((*polynomial).factors[i],0,(*polynomial).factors[i].length-1); + } + + // resolve the identities specified in the fields table + resolve_ids(polynomial, fields); + + // in order to perform a simplification, the list of terms must be + // sorted (so that terms that are proportional are next to each other) + polynomial_sort(polynomial,0,(*polynomial).length-1); + + for(i=0;i<(*polynomial).length;i++){ + // if the term actually exists + if(number_is_zero((*polynomial).nums[i])!=1){ + // combine numerical factors + number_add_chain((*polynomial).nums[i], &new_num); + } + // if the numerator is 0, the previous terms that may have the same factors should still be added, hence the 'if' ends here + + // if either the monomial or the factor is different from the next then add term + if(i<(*polynomial).length-1){ + monomial_cmp=int_array_cmp((*polynomial).monomials[i],(*polynomial).monomials[i+1]); + factor_cmp=int_array_cmp((*polynomial).factors[i],(*polynomial).factors[i+1]); + } + if(i>=(*polynomial).length-1 || monomial_cmp!=0 || factor_cmp!=0 ){ + // check that the polynomial is not trivial + if(number_is_zero(new_num)!=1){ + polynomial_append((*polynomial).monomials[i],(*polynomial).factors[i],new_num,&output); + } + + // reset new numerical factor + free_Number(new_num); + init_Number(&new_num,NUMBER_SIZE); + } + } + + free_Number(new_num); + free_Polynomial(*polynomial); + *polynomial=output; + return(0); +} + +// sort a polynomial +// requires the monomials and factors to be sorted +int polynomial_sort(Polynomial* polynomial, int begin, int end){ + int i; + int index; + int monomial_cmp; + int factor_cmp; + + // the pivot: middle of the array + int pivot=(begin+end)/2; + // if the array is non trivial + if(begin<end){ + // send pivot to the end + exchange_polynomial_terms(pivot,end,polynomial); + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + monomial_cmp=int_array_cmp((*polynomial).monomials[i],(*polynomial).monomials[end]); + factor_cmp=int_array_cmp((*polynomial).factors[i],(*polynomial).factors[end]); + if(monomial_cmp<0 || (monomial_cmp==0 && factor_cmp<0)){ + // if smaller, exchange with reference index + exchange_polynomial_terms(i,index,polynomial); + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + exchange_polynomial_terms(index,end,polynomial); + // recurse + polynomial_sort(polynomial, begin, index-1); + polynomial_sort(polynomial, index+1, end); + } + return(0); +} + +// exchange two terms (for the sorting algorithm) +int exchange_polynomial_terms(int i, int j, Polynomial* polynomial){ + Int_Array ptmp; + Number tmp; + + ptmp=(*polynomial).monomials[j]; + (*polynomial).monomials[j]=(*polynomial).monomials[i]; + (*polynomial).monomials[i]=ptmp; + + ptmp=(*polynomial).factors[j]; + (*polynomial).factors[j]=(*polynomial).factors[i]; + (*polynomial).factors[i]=ptmp; + + tmp=(*polynomial).nums[j]; + (*polynomial).nums[j]=(*polynomial).nums[i]; + (*polynomial).nums[i]=tmp; + + return(0); +} + +// sort a monomial (with sign coming from exchanging two Fermions) +int monomial_sort(Int_Array monomial, int begin, int end, Fields_Table fields, int* sign){ + int i; + int index; + // the pivot: middle of the monomial + int pivot=(begin+end)/2; + + // if the monomial is non trivial + if(begin<end){ + // send pivot to the end + exchange_monomial_terms(monomial, pivot, end, fields, sign); + + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + if(compare_monomial_terms(monomial, i, end, fields)<0){ + // if smaller, exchange with reference index + exchange_monomial_terms(monomial, index, i, fields, sign); + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + exchange_monomial_terms(monomial, index, end, fields, sign); + + // recurse + monomial_sort(monomial, begin, index-1, fields, sign); + monomial_sort(monomial, index+1, end, fields, sign); + } + return(0); +} + +// order fields: parameter, external, internal +int compare_monomial_terms(Int_Array monomial, int pos1, int pos2, Fields_Table fields){ + int type1=field_type(monomial.values[pos1], fields); + int type2=field_type(monomial.values[pos2],fields); + + if(type1 < type2){ + return(-1); + } + else if(type1 > type2){ + return(1); + } + + if(monomial.values[pos1] < monomial.values[pos2]){ + return(-1); + } + else if (monomial.values[pos1] > monomial.values[pos2]){ + return(1); + } + + return(0); +} + +// exchange two fields (with sign) +int exchange_monomial_terms(Int_Array monomial, int pos1, int pos2, Fields_Table fields, int* sign){ + int tmp=monomial.values[pos1]; + int f1,f2; + int i; + + monomial.values[pos1]=monomial.values[pos2]; + monomial.values[pos2]=tmp; + + // sign change + // only if the exchange is not trivial + if(pos1!=pos2){ + f1=is_fermion(monomial.values[pos1],fields); + f2=is_fermion(monomial.values[pos2],fields); + // if both Fermions then sign + if(f1==1 && f2==1){ + *sign*=-1; + } + // if only one of them is a Fermion, then count the number of Fermions between them + else if(f1==1 || f2==1){ + for(i=min(pos1,pos2)+1;i<max(pos1,pos2);i++){ + if(is_fermion(monomial.values[i],fields)==1){ + *sign*=-1; + } + } + } + } + return(0); +} + + +// sort a monomial by putting each group together +int monomial_sort_groups(Int_Array monomial, int begin, int end, Fields_Table fields, Groups groups, int* sign){ + int i; + int index; + // the pivot: middle of the monomial + int pivot=(begin+end)/2; + + // if the monomial is non trivial + if(begin<end){ + // send pivot to the end + exchange_monomial_terms(monomial, pivot, end, fields, sign); + + // loop over the others + for(i=begin, index=begin;i<end;i++){ + // compare with pivot + if(compare_monomial_terms_groups(monomial, i, end, fields, groups)<0){ + // if smaller, exchange with reference index + exchange_monomial_terms(monomial, index, i, fields, sign); + // move reference index + index++; + } + } + // put pivot (which we had sent to the end) in the right place + exchange_monomial_terms(monomial, index, end, fields, sign); + + // recurse + monomial_sort(monomial, begin, index-1, fields, sign); + monomial_sort(monomial, index+1, end, fields, sign); + } + return(0); +} + +// order fields: group, then parameter, external, internal +int compare_monomial_terms_groups(Int_Array monomial, int pos1, int pos2, Fields_Table fields, Groups groups){ + int group1=find_group(monomial.values[pos1], groups); + int group2=find_group(monomial.values[pos2], groups); + + if(group1 < group2){ + return(-1); + } + else if(group1 > group2){ + return(1); + } + + int type1=field_type(monomial.values[pos1], fields); + int type2=field_type(monomial.values[pos2],fields); + + if(type1 < type2){ + return(-1); + } + else if(type1 > type2){ + return(1); + } + + if(monomial.values[pos1] < monomial.values[pos2]){ + return(-1); + } + else if (monomial.values[pos1] > monomial.values[pos2]){ + return(1); + } + + return(0); +} + + +// convert and idtable to a polynomial +int idtable_to_polynomial(Id_Table idtable, Polynomial* polynomial){ + int i,j; + int start=0; + + // allocate memory + init_Polynomial(polynomial,POLY_SIZE); + + for(i=0;i<idtable.length;i++){ + polynomial_concat(idtable.polynomials[i],polynomial); + // set factors + for(j=start;j<(*polynomial).length;j++){ + int_array_append(idtable.indices[i],(*polynomial).factors+j); + } + // shift start point + start+=idtable.polynomials[i].length; + } + + return(0); +} + + +// replace the factors in a polynomial as prescribed by an equation in the form of a Grouped_Polynomial +int replace_factors(Grouped_Polynomial equations, Polynomial* polynomial){ + int i,j; + int index; + Polynomial output; + Coefficient coef; + + init_Polynomial(&output, POLY_SIZE); + + // loop over monomials + for(i=0;i<(*polynomial).length;i++){ + if((*polynomial).factors[i].length>0){ + // initialize coef to store the product of factors + init_Coefficient(&coef, POLY_SIZE); + + // first term + index=intlist_find_err(equations.indices, equations.length, (*polynomial).factors[i].values[0]); + if(index>=0){ + coefficient_cpy_noinit(equations.coefs[index],&coef); + } + + // other terms + for(j=1;j<(*polynomial).factors[i].length;j++){ + index=intlist_find_err(equations.indices, equations.length, (*polynomial).factors[i].values[j]); + if(index>=0){ + coefficient_prod_chain(equations.coefs[index],&coef); + } + } + + // new polynomial terms + for(j=0;j<coef.length;j++){ + // add to output + polynomial_append((*polynomial).monomials[i], coef.factors[j], number_prod_ret((*polynomial).nums[i],coef.nums[j]), &output); + } + + // free memory + free_Coefficient(coef); + } + // if no factors + else{ + polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], &output); + } + } + + // replace output + free_Polynomial(*polynomial); + *polynomial=output; + + return(0); +} + + +// print a polynomial to a string +int polynomial_sprint(Polynomial polynomial, Char_Array* output){ + int i,j; + + // for each monomial + for(i=0;i<polynomial.length;i++){ + if(i==0){ + char_array_snprintf(output, " "); + } + else{ + char_array_snprintf(output, "+ ",i); + } + + // print num + char_array_append('(',output); + number_sprint(polynomial.nums[i],output); + char_array_append(')',output); + + // print factors + for(j=0;j<polynomial.factors[i].length;j++){ + char_array_snprintf(output,"[l%d]",polynomial.factors[i].values[j]); + } + + // print monomials + for(j=0;j<polynomial.monomials[i].length;j++){ + char_array_snprintf(output,"[f%d]",polynomial.monomials[i].values[j]); + } + + char_array_append('\n',output); + } + return(0); +} +// print +int polynomial_print(Polynomial polynomial){ + Char_Array buffer; + init_Char_Array(&buffer, STR_SIZE); + polynomial_sprint(polynomial, &buffer); + printf("%s",buffer.str); + free_Char_Array(buffer); + return(0); +} + +// read a polynomial from a Char_Array +#define PP_NULL_MODE 0 +#define PP_BRACKET_MODE 1 +#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){ + // buffer + char* buffer=calloc(str_polynomial.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Int_Array monomial; + Int_Array factor; + Number num, tmp1_num; + int mode; + int comment=0; + int i,j; + int parenthesis_count=0; + + // allocate memory + init_Polynomial(output,POLY_SIZE); + + // init + init_Int_Array(&monomial, MONOMIAL_SIZE); + init_Int_Array(&factor, MONOMIAL_SIZE); + num=number_one(); + + // if the string contains no '[', then read a number + for(j=0;j<str_polynomial.length;j++){ + // ignore comments + if(comment==1){ + if(str_polynomial.str[j]=='\n'){ + comment=0; + } + } + else{ + if(str_polynomial.str[j]=='['){ + break; + } + if(str_polynomial.str[j]=='#'){ + comment=1; + } + } + } + // no '[': read a number + if(j==str_polynomial.length){ + free_Number(num); + char_array_to_Number(str_polynomial,&num); + polynomial_append_noinit(monomial, factor, num, output); + free(buffer); + return(0); + } + + // reset comment flag + comment=0; + + *buffer_ptr='\0'; + // loop over the input polynomial + // start in null mode + mode=PP_NULL_MODE; + for(j=0;j<str_polynomial.length;j++){ + if(comment==1){ + if(str_polynomial.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_polynomial.str[j]){ + // new monomial + case '+': + if(mode==PP_NULL_MODE){ + polynomial_append_noinit(monomial, factor, num, output); + // reset monomial, factor, num + init_Int_Array(&monomial, MONOMIAL_SIZE); + init_Int_Array(&factor, MONOMIAL_SIZE); + num=number_one(); + } + break; + + // enter monomial or factor mode + case '[': + if(mode==PP_NULL_MODE){ + mode=PP_BRACKET_MODE; + } + break; + // factor mode + case 'l': + if(mode==PP_BRACKET_MODE){ + mode=PP_FACTOR_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // monomial mode + case 'f': + if(mode==PP_BRACKET_MODE){ + mode=PP_MONOMIAL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // read monomial or factor + case ']': + sscanf(buffer,"%d",&i); + if(mode==PP_FACTOR_MODE){ + int_array_append(i,&factor); + } + else if(mode==PP_MONOMIAL_MODE){ + int_array_append(i,&monomial); + } + // switch back to null mode + mode=PP_NULL_MODE; + break; + + // numerical pre-factor + case '(': + if(mode==PP_NULL_MODE){ + mode=PP_NUMBER_MODE; + parenthesis_count=0; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else if(mode==PP_NUMBER_MODE){ + // match parentheses + parenthesis_count++; + buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); + } + break; + case ')': + if(mode==PP_NUMBER_MODE){ + if(parenthesis_count==0){ + // write num + str_to_Number(buffer,&tmp1_num); + number_prod_chain(tmp1_num,&num); + free_Number(tmp1_num); + // back to null mode + mode=PP_NULL_MODE; + } + else{ + parenthesis_count--; + buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); + } + } + break; + + // characters to ignore + case ' ':break; + case '&':break; + case '\n':break; + + // comments + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); + } + break; + } + } + } + + // last term + polynomial_append_noinit(monomial, factor, num, output); + + free(buffer); + return(0); +} + +// with str input +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); + free_Char_Array(buffer); + return(0); +} + + +// -------------------- Polynomial_Matrix --------------------- + +// init +int init_Polynomial_Matrix(Polynomial_Matrix* matrix, int length){ + int i,j; + (*matrix).matrix=calloc(length,sizeof(Polynomial*)); + (*matrix).indices=calloc(length,sizeof(int)); + for(i=0;i<length;i++){ + (*matrix).matrix[i]=calloc(length,sizeof(Polynomial)); + for(j=0;j<length;j++){ + (*matrix).matrix[i][j]=polynomial_zero(); + } + } + (*matrix).length=length; + return(0); +} +int free_Polynomial_Matrix(Polynomial_Matrix matrix){ + int i,j; + for(i=0;i<matrix.length;i++){ + for(j=0;j<matrix.length;j++){ + free_Polynomial(matrix.matrix[i][j]); + } + free(matrix.matrix[i]); + } + free(matrix.matrix); + free(matrix.indices); + return(0); +} diff --git a/src/polynomial.h b/src/polynomial.h new file mode 100644 index 0000000..ec50227 --- /dev/null +++ b/src/polynomial.h @@ -0,0 +1,131 @@ +/* +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. +*/ + +/* +Represent a polynomial as a list of monomials with factors +*/ + +#ifndef POLYNOMIAL_H +#define POLYNOMIAL_H + +#include "types.h" + +// allocate memory +int init_Polynomial(Polynomial* polynomial,int size); +// free memory +int free_Polynomial(Polynomial polynomial); + +// resize the memory allocated to a polynomial +int resize_polynomial(Polynomial* polynomial,int new_size); + +// copy a polynomial +int polynomial_cpy(Polynomial input, Polynomial* output); +int polynomial_cpy_noinit(Polynomial input, Polynomial* output); + +// append an element to a polynomial +int polynomial_append(Int_Array monomial, Int_Array factor, Number num, Polynomial* output); +int polynomial_append_noinit(Int_Array monomial, Int_Array factor, Number num, Polynomial* output); +// noinit, and if there already exists an element with the same monomial and factor, then just add numbers +int polynomial_append_noinit_inplace(Int_Array monomial, Int_Array factor, Number num, Polynomial* output); + +// concatenate two polynomials +int polynomial_concat(Polynomial input, Polynomial* output); +int polynomial_concat_noinit(Polynomial input, Polynomial* output); +int polynomial_concat_noinit_inplace(Polynomial input, Polynomial* output); + +// add polynomials +int polynomial_add_chain(Polynomial input, Polynomial* inout, Fields_Table fields); +// add polynomials (noinit) +int polynomial_add_chain_noinit(Polynomial input, Polynomial* inout, Fields_Table fields); + +// multiply a polynomial by a scalar +int polynomial_multiply_scalar(Polynomial polynomial, Number num); +int polynomial_multiply_Qscalar(Polynomial polynomial, Q q); + +// change the sign of the monomials in a polynomial +int polynomial_conjugate(Polynomial polynomial); + +// returns an initialized polynomial, equal to 1 +Polynomial polynomial_one(); +// returns an initialized polynomial, equal to 0 +Polynomial polynomial_zero(); + +// check whether a polynomial is 0 +int polynomial_is_zero(Polynomial poly); + +// compute V^p +int polynomial_power(Polynomial input_polynomial, Polynomial* output, int power, Fields_Table fields); +// compute V*W +int polynomial_prod(Polynomial input1, Polynomial input2, Polynomial* output, Fields_Table fields); +int polynomial_prod_chain_nosimplify(Polynomial input, Polynomial* inout, Fields_Table fields); +int polynomial_prod_chain(Polynomial input, Polynomial* inout, Fields_Table fields); +// exp(V) +int polynomial_exponential(Polynomial input_polynomial,Polynomial* output, Fields_Table fields); +// log(1+W) +int polynomial_logarithm(Polynomial input_polynomial, Polynomial* output, Fields_Table fields); + +// check whether a monomial vanishes +int check_monomial(Int_Array monomial, Fields_Table fields); +// check whether the product of two monomials will vanish +int check_monomial_willnot_vanish(Int_Array monomial1, Int_Array monomial2, Fields_Table fields); +// check whether one can add a term to a monomial without creating repetitions +int check_monomial_addterm(Int_Array monomial, Int_Array term, Fields_Table fields); +// check whether a monomial vanishes or has unmatched +/- fields +int check_monomial_match(Int_Array monomial, Fields_Table fields); +// remove terms with more plus internal fields than minus ones +int remove_unmatched_plusminus(Polynomial* polynomial, Fields_Table fields); + +// denominator of a multinomal factor: m1!m2!... +int multinomial(int power,int* terms); + +// simplify a Polynomial +int polynomial_simplify(Polynomial* polynomial, Fields_Table fields); +// sort a polynomial +int polynomial_sort(Polynomial* polynomial, int begin, int end); +// exchange two terms (for the sorting algorithm) +int exchange_polynomial_terms(int i, int j, Polynomial* polynomial); + +// sort a monomial (with sign coming from exchanging two Fermions) +int monomial_sort(Int_Array monomial, int begin, int end, Fields_Table fields, int* sign); +// order fields: parameter, external, internal +int compare_monomial_terms(Int_Array monomial, int pos1, int pos2, Fields_Table fields); +// exchange two fields (with sign) +int exchange_monomial_terms(Int_Array monomial, int pos1, int pos2, Fields_Table fields, int* sign); + +// sort a monomial by putting each group together +int monomial_sort_groups(Int_Array monomial, int begin, int end, Fields_Table fields, Groups groups, int* sign); +// order fields: group, then parameter, external, internal +int compare_monomial_terms_groups(Int_Array monomial, int pos1, int pos2, Fields_Table fields, Groups groups); + +// convert and idtable to a polynomial +int idtable_to_polynomial(Id_Table idtable, Polynomial* polynomial); + +// replace the factors in a polynomial as prescribed by an equation in the form of a Grouped_Polynomial +int replace_factors(Grouped_Polynomial equations, Polynomial* polynomial); + +// print a 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); + +//------------------------ Polynomial_Matrix -------------------------- +// init +int init_Polynomial_Matrix(Polynomial_Matrix* matrix, int length); +int free_Polynomial_Matrix(Polynomial_Matrix matrix); + +#endif diff --git a/src/rational.h b/src/rational.h new file mode 100644 index 0000000..5beab8d --- /dev/null +++ b/src/rational.h @@ -0,0 +1,23 @@ +/* +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. +*/ + +/* + represent rational numbers either as a quotient of 64-bit integers, or a quotient of 80-bit floats (with 64-bit precision) +*/ + +// include both, only one is non empty +#include "rational_float.h" +#include "rational_int.h" diff --git a/src/rational_float.c b/src/rational_float.c new file mode 100644 index 0000000..eebc4f4 --- /dev/null +++ b/src/rational_float.c @@ -0,0 +1,196 @@ +/* +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. +*/ + +#ifdef RATIONAL_AS_FLOAT + +#include "rational_float.h" +#include <stdio.h> +#include <stdlib.h> +#include "istring.h" +#include "array.h" +#include "math.h" + +Q quot(long double p, long double q){ + Q ret; + if(q==0){ + fprintf(stderr,"error: %Lf/%Lf is ill defined\n",p,q); + exit(-1); + } + ret.numerator=p; + ret.denominator=q; + return(ret); +} + +// add +Q Q_add(Q x1,Q x2){ + Q ret; + ret.denominator=lcm(x1.denominator,x2.denominator); + ret.numerator=x1.numerator*(ret.denominator/x1.denominator)+x2.numerator*(ret.denominator/x2.denominator); + return(Q_simplify(ret)); +} +//multiply +Q Q_prod(Q x1,Q x2){ + return(Q_simplify(quot(x1.numerator*x2.numerator,x1.denominator*x2.denominator))); +} +// inverse +Q Q_inverse(Q x1){ + if(x1.numerator>0){ + return(quot(x1.denominator,x1.numerator)); + } + else if(x1.numerator<0){ + return(quot(-x1.denominator,-x1.numerator)); + } + else{ + fprintf(stderr,"error: attempting to invert %Lf/%Lf\n",x1.numerator, x1.denominator); + exit(-1); + } + +} +// quotient +Q Q_quot(Q x1, Q x2){ + if(x2.numerator>0){ + return(Q_simplify(quot(x1.numerator*x2.denominator,x1.denominator*x2.numerator))); + } + else if(x2.numerator<0){ + return(Q_simplify(quot(-x1.numerator*x2.denominator,-x1.denominator*x2.numerator))); + } + else{ + fprintf(stderr,"error: attempting to invert %Lf/%Lf\n",x2.numerator, x2.denominator); + exit(-1); + } +} + +// compare +int Q_cmp(Q x1, Q x2){ + Q quo=Q_quot(x1,x2); + if(quo.numerator > quo.denominator){ + return(1); + } + else if(quo.numerator < quo.denominator){ + return(-1); + } + else{ + return(0); + } +} + +// simplify +Q Q_simplify(Q x){ + return(quot(x.numerator/gcd(x.numerator,x.denominator),x.denominator/gcd(x.numerator,x.denominator))); +} +//simplify in place +int Q_simplify_inplace(Q* x){ + Q ret=Q_simplify(*x); + *x=ret; + return(0); +} + +// greatest common divisor +long double gcd(long double x, long double y){ + long double ax=fabsl(x); + long double ay=fabsl(y); + int security=0; + while(ax!=0 && ay!=0){ + if(ax>ay){ax=modld(ax,ay);} + else{ay=modld(ay,ax);} + + security++; + if(security>1000000){ + fprintf(stderr,"error: could not compute gcd( %Lf , %Lf ) after %d tries\n",x,y,security); + exit(-1); + } + } + // if both are negative, gcd should be negative (useful for simplification of fractions and product of square roots) + if(x<0 && y<0){ + ax*=-1; + ay*=-1; + } + if(fabsl(ay)>fabsl(ax)){return(ay);} + else{return(ax);} +} + +long double modld(long double x, long double m){ + long double q=floorl(x/m); + return(x-q*m); +} + +// least common multiple +long double lcm(long double x,long double y){ + if(x!=0 || y!=0){ + return((x*y)/gcd(x,y)); + } + else{ + return(0); + } +} + +// approximate value as double +double Q_double_value(Q q){ + return(1.0*q.numerator/q.denominator); +} + + +// print to string +int Q_sprint(Q num, Char_Array* out){ + if(num.denominator!=1){ + char_array_snprintf(out,"%Lf/%Lf", num.numerator,num.denominator); + } + else{ + char_array_snprintf(out,"%Lf",num.numerator); + } + + return(0); +} + +#define PP_NUMERATOR_MODE 1 +#define PP_DENOMINATOR_MODE 2 +// read from a string +int str_to_Q(char* str, Q* num){ + char* ptr; + int mode; + char* buffer=calloc(str_len(str)+1,sizeof(char)); + char* buffer_ptr=buffer; + + *num=quot(0,1); + + mode=PP_NUMERATOR_MODE; + for(ptr=str;*ptr!='\0';ptr++){ + if(*ptr=='/'){ + sscanf(buffer,"%Lf",&((*num).numerator)); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_DENOMINATOR_MODE; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,*ptr); + } + } + + // last step + if(mode==PP_NUMERATOR_MODE){ + sscanf(buffer,"%Lf",&((*num).numerator)); + } + else if(mode==PP_DENOMINATOR_MODE){ + sscanf(buffer,"%Lf",&((*num).denominator)); + } + + free(buffer); + return(0); +} + +#else +int null_declaration_so_that_the_compiler_does_not_complain; +#endif diff --git a/src/rational_float.h b/src/rational_float.h new file mode 100644 index 0000000..931b5ec --- /dev/null +++ b/src/rational_float.h @@ -0,0 +1,64 @@ +/* +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. +*/ + +/* + Rational numbers + uses long doubles to represent integers (to avoid overflow) +*/ + +#ifdef RATIONAL_AS_FLOAT + +#ifndef RATIONAL_H +#define RATIONAL_H + +#include "types.h" + +// Q from int/int +Q quot(long double p, long double q); + +// add +Q Q_add(Q x1,Q x2); +//multiply +Q Q_prod(Q x1,Q x2); +// inverse +Q Q_inverse(Q x1); +// quotient +Q Q_quot(Q x1, Q x2); + +// compare +int Q_cmp(Q x1, Q x2); + +// simplify +Q Q_simplify(Q x); +//simplify in place +int Q_simplify_inplace(Q* x); + +// greatest common divisor +long double gcd(long double x,long double y); +long double modld(long double x, long double m); +// least common multiple +long double lcm(long double x,long double y); + +// approximate value as double +double Q_double_value(Q q); + +// print to string +int Q_sprint(Q num, Char_Array* out); +// read from a string +int str_to_Q(char* str, Q* num); + +#endif +#endif diff --git a/src/rational_int.c b/src/rational_int.c new file mode 100644 index 0000000..ec601a8 --- /dev/null +++ b/src/rational_int.c @@ -0,0 +1,190 @@ +/* +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. +*/ + +#ifndef RATIONAL_AS_FLOAT + +#include "rational_int.h" +#include <stdio.h> +#include <stdlib.h> +#include "istring.h" +#include "array.h" + +Q quot(long int p, long int q){ + Q ret; + if(q==0){ + fprintf(stderr,"error: %ld/%ld is ill defined\n",p,q); + exit(-1); + } + ret.numerator=p; + ret.denominator=q; + return(ret); +} + +// add +Q Q_add(Q x1,Q x2){ + Q ret; + ret.denominator=lcm(x1.denominator,x2.denominator); + ret.numerator=x1.numerator*(ret.denominator/x1.denominator)+x2.numerator*(ret.denominator/x2.denominator); + return(Q_simplify(ret)); +} +//multiply +Q Q_prod(Q x1,Q x2){ + return(Q_simplify(quot(x1.numerator*x2.numerator,x1.denominator*x2.denominator))); +} +// inverse +Q Q_inverse(Q x1){ + if(x1.numerator>0){ + return(quot(x1.denominator,x1.numerator)); + } + else if(x1.numerator<0){ + return(quot(-x1.denominator,-x1.numerator)); + } + else{ + fprintf(stderr,"error: attempting to invert %ld/%ld\n",x1.numerator, x1.denominator); + exit(-1); + } + +} +// quotient +Q Q_quot(Q x1, Q x2){ + if(x2.numerator>0){ + return(Q_simplify(quot(x1.numerator*x2.denominator,x1.denominator*x2.numerator))); + } + else if(x2.numerator<0){ + return(Q_simplify(quot(-x1.numerator*x2.denominator,-x1.denominator*x2.numerator))); + } + else{ + fprintf(stderr,"error: attempting to invert %ld/%ld\n",x2.numerator, x2.denominator); + exit(-1); + } +} + +// compare +int Q_cmp(Q x1, Q x2){ + Q quo=Q_quot(x1,x2); + if(quo.numerator > quo.denominator){ + return(1); + } + else if(quo.numerator < quo.denominator){ + return(-1); + } + else{ + return(0); + } +} + +// simplify +Q Q_simplify(Q x){ + return(quot(x.numerator/gcd(x.numerator,x.denominator),x.denominator/gcd(x.numerator,x.denominator))); +} +//simplify in place +int Q_simplify_inplace(Q* x){ + Q ret=Q_simplify(*x); + *x=ret; + return(0); +} + +// greatest common divisor +long int gcd(long int x, long int y){ + long int ax=labs(x); + long int ay=labs(y); + int security=0; + while(ax!=0 && ay!=0){ + if(ax>ay){ax=ax%ay;} + else{ay=ay%ax;} + + security++; + if(security>1000000){ + fprintf(stderr,"error: could not compute gcd( %ld , %ld ) after %d tries\n",x,y,security); + exit(-1); + } + } + // if both are negative, gcd should be negative (useful for simplification of fractions and product of square roots) + if(x<0 && y<0){ + ax*=-1; + ay*=-1; + } + if(labs(ay)>labs(ax)){return(ay);} + else{return(ax);} +} + +// least common multiple +long int lcm(long int x,long int y){ + if(x!=0 || y!=0){ + return((x*y)/gcd(x,y)); + } + else{ + return(0); + } +} + +// approximate value as double +double Q_double_value(Q q){ + return(1.0*q.numerator/q.denominator); +} + + +// print to string +int Q_sprint(Q num, Char_Array* out){ + if(num.denominator!=1){ + char_array_snprintf(out,"%ld/%ld", num.numerator,num.denominator); + } + else{ + char_array_snprintf(out,"%ld",num.numerator); + } + + return(0); +} + +#define PP_NUMERATOR_MODE 1 +#define PP_DENOMINATOR_MODE 2 +// read from a string +int str_to_Q(char* str, Q* num){ + char* ptr; + int mode; + char* buffer=calloc(str_len(str)+1,sizeof(char)); + char* buffer_ptr=buffer; + + *num=quot(0,1); + + mode=PP_NUMERATOR_MODE; + for(ptr=str;*ptr!='\0';ptr++){ + if(*ptr=='/'){ + sscanf(buffer,"%ld",&((*num).numerator)); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_DENOMINATOR_MODE; + } + else{ + buffer_ptr=str_addchar(buffer_ptr,*ptr); + } + } + + // last step + if(mode==PP_NUMERATOR_MODE){ + sscanf(buffer,"%ld",&((*num).numerator)); + } + else if(mode==PP_DENOMINATOR_MODE){ + sscanf(buffer,"%ld",&((*num).denominator)); + } + + free(buffer); + return(0); +} + +#else +int null_declaration_so_that_the_compiler_does_not_complain; +#endif diff --git a/src/rational_int.h b/src/rational_int.h new file mode 100644 index 0000000..a9f164d --- /dev/null +++ b/src/rational_int.h @@ -0,0 +1,59 @@ +/* +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. +*/ + +/* Rational numbers */ + +#ifndef RATIONAL_AS_FLOAT +#ifndef RATIONAL_H +#define RATIONAL_H + +#include "types.h" + +// Q from int/int +Q quot(long int p, long int q); + +// add +Q Q_add(Q x1,Q x2); +//multiply +Q Q_prod(Q x1,Q x2); +// inverse +Q Q_inverse(Q x1); +// quotient +Q Q_quot(Q x1, Q x2); + +// compare +int Q_cmp(Q x1, Q x2); + +// simplify +Q Q_simplify(Q x); +//simplify in place +int Q_simplify_inplace(Q* x); + +// greatest common divisor +long int gcd(long int x,long int y); +// least common multiple +long int lcm(long int x,long int y); + +// approximate value as double +double Q_double_value(Q q); + +// print to string +int Q_sprint(Q num, Char_Array* out); +// read from a string +int str_to_Q(char* str, Q* num); + +#endif +#endif diff --git a/src/rcc.c b/src/rcc.c new file mode 100644 index 0000000..484e20a --- /dev/null +++ b/src/rcc.c @@ -0,0 +1,95 @@ +/* +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 "rcc.h" +#include <stdio.h> +#include <stdlib.h> +#include "array.h" + +// init +int init_RCC(RCC* rccs, int size){ + (*rccs).values=calloc(size,sizeof(long double)); + (*rccs).indices=calloc(size,sizeof(int)); + (*rccs).length=size; + return(0); +} + +int free_RCC(RCC rccs){ + free(rccs.values); + free(rccs.indices); + return(0); +} + +// set a given element of an rcc +int RCC_set_elem(long double value, int index, RCC* rcc, int pos){ + (*rcc).values[pos]=value; + (*rcc).indices[pos]=index; + return(0); +} + +int RCC_cpy(RCC input,RCC* output){ + int i; + + init_RCC(output,input.length); + 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){ + int i; + + init_RCC(output,rccs1.length+rccs2.length); + + for(i=0;i<rccs1.length;i++){ + RCC_set_elem(rccs1.values[i], rccs1.indices[i], output, i); + } + + for(i=0;i<rccs2.length;i++){ + RCC_set_elem(rccs2.values[i], rccs2.indices[i], output, i+rccs1.length); + } + + return(0); +} + +// append an rcc at the end of another +int RCC_append(RCC input, RCC* output){ + int i; + for(i=0;i<input.length;i++){ + RCC_set_elem(input.values[i], input.indices[i], output, i+(*output).length); + } + (*output).length+=input.length; + return(0); +} + +// print an rcc vector with maximal precision +int RCC_print(RCC rccs){ + int j; + + for(j=0;j<rccs.length;j++){ + printf("%d:%.19Le",rccs.indices[j],rccs.values[j]); + if(j<rccs.length-1){ + printf(",\n"); + } + else{ + printf("\n"); + } + } + + return(0); +} diff --git a/src/rcc.h b/src/rcc.h new file mode 100644 index 0000000..770309c --- /dev/null +++ b/src/rcc.h @@ -0,0 +1,39 @@ +/* +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. +*/ + +/* RCC struct */ + +#ifndef RCC_H +#define RCC_H + +#include "types.h" + +// init +int init_RCC(RCC* rccs, int size); +int free_RCC(RCC rccs); +// set an element of an rcc +int RCC_set_elem(long double value, int index, RCC* rcc, int pos); +// copy +int RCC_cpy(RCC input,RCC* output); +// concatenate 2 rccs +int RCC_concat(RCC rccs1, RCC rccs2, RCC* output); +// append an rcc to another +int RCC_append(RCC input, RCC* output); + +// print an rcc vector with maximal precision +int RCC_print(RCC rccs); + +#endif diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 0000000..2b7e85d --- /dev/null +++ b/src/tools.c @@ -0,0 +1,142 @@ +/* +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 "tools.h" +#include <stdio.h> +#include <stdlib.h> + +int factorial(int n){ + int i; + int res=1; + for(i=2;i<=n;i++){ + res*=i; + } + return(res); +} + +int ipower(int n, int p){ + int i; + int res=1; + for(i=1;i<=p;i++){ + res*=n; + } + return(res); +} + +// power of a double +long double dpower(long double x, int p){ + int i; + long double res=1.; + if(p>=0){ + for(i=1;i<=p;i++){ + res*=x; + } + } + else{ + for(i=1;i<=-p;i++){ + res/=x; + } + } + + return(res); +} + + +// find an element in a list whose first element is its size +int list_find(int* list, int x){ + int i; + for(i=1;i<=*list;i++){ + if(list[i]==x){return(i);} + } + return(0); +} + +// find an element in a list whose first element is not its number of elements (skips first element) +int unlist_find(int* list, int size, int x){ + int i; + for(i=1;i<size;i++){ + if(list[i]==x){return(i);} + } + fprintf(stderr,"error: element %d not found\n",x); + exit(-1); +} +// find an element in a list whose first element is not its number of elements (skips first element) +// no error reporting +int unlist_find_noerr(int* list, int size, int x){ + int i; + for(i=1;i<size;i++){ + if(list[i]==x){return(i);} + } + return(-1); +} + + +// find an element in a list (checks first element) +int intlist_find(int* list, int size, int x){ + int i; + for(i=0;i<size;i++){ + if(list[i]==x){return(i);} + } + return(-1); +} +// with error +int intlist_find_err(int* list, int size, int x){ + int i; + for(i=0;i<size;i++){ + if(list[i]==x){return(i);} + } + fprintf(stderr,"error: element %d not found\n",x); + exit(-1); +} + + + +// compare two lists +int list_cmp(int* list1, int* list2){ + if(*list1!=*list2){ + return(0); + } + int* ptr1=list1+1; + int* ptr2=list2+1; + int i; + for(i=1;i<=*list1;i++){ + if(*ptr1!=*ptr2){ + return(0); + } + ptr1++; + ptr2++; + } + return(1); +} + + +// max and min +int max(int x1, int x2){ + if(x1>=x2){ + return(x1); + } + else{ + return(x2); + } +} +int min(int x1, int x2){ + if(x1<=x2){ + return(x1); + } + else{ + return(x2); + } +} diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 0000000..e5f319f --- /dev/null +++ b/src/tools.h @@ -0,0 +1,49 @@ +/* +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. +*/ + +/* +Various tools +*/ + +#ifndef TOOLS_H +#define TOOLS_H + +#include "types.h" + +int factorial(int n); +int ipower(int n, int p); +long double dpower(long double x, int p); + +// find an element in a list whose first element is its size +int list_find(int* list, int x); +// compare two lists +int list_cmp(int* list1, int* list2); + +// find an element in a list whose first element is not its number of elements (skips first element) +int unlist_find(int* list, int size, int x); +// no error +int unlist_find_noerr(int* list, int size, int x); + +// find an element in a list (checks first element) +int intlist_find(int* list, int size, int x); +// with error +int intlist_find_err(int* list, int size, int x); + +// max and min +int max(int x1, int x2); +int min(int x1, int x2); + +#endif diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..0452ebc --- /dev/null +++ b/src/types.h @@ -0,0 +1,219 @@ +/* +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. +*/ + +/* + typedefs used by meankondo +*/ + +#ifndef TYPES_H +#define TYPES_H + + +// rational number +typedef struct Q{ +#ifndef RATIONAL_AS_FLOAT + long int numerator; + long int denominator; +#else + long double numerator; + long double denominator; +#endif +} Q; + +// numbers +typedef struct Number{ + Q* scalars; + int* base; + int length; + int memory; +} Number; + +// matrix +typedef struct Number_Matrix{ + Number** matrix; + int* indices; + int length; +} Number_Matrix; + +// list of integers +typedef struct Int_Array{ + int* values; + int length; + int memory; +} Int_Array; + +// string +typedef struct Char_Array{ + char* str; + int length; + int memory; +} Char_Array; + +// string array +typedef struct Str_Array{ + Char_Array* strs; + int length; + int memory; +} Str_Array; + +// polynomial +typedef struct Polynomial{ + Int_Array* monomials; + Int_Array* factors; + Number* nums; + int length; + int memory; +} Polynomial; + +// matrix of polynomial +typedef struct Polynomial_Matrix{ + Polynomial** matrix; + int* indices; + int length; +} Polynomial_Matrix; + +// denominators in coefficients (index of the denominator and the power to which it is raised) +typedef struct coef_denom{ + int index; + int power; +} coef_denom; + +// coefficient +typedef struct Coefficient{ + Int_Array* factors; + Number* nums; + coef_denom* denoms; + int length; + int memory; +} Coefficient; + +// grouped polynomial +typedef struct Grouped_Polynomial{ + Coefficient* coefs; + int* indices; + int length; + int memory; +} Grouped_Polynomial; + +// rcc +typedef struct RCC{ + long double* values; + int* indices; + int length; +} RCC; + +// identities between fields +typedef struct Identities{ + // left hand sides + Int_Array* lhs; + // right hand sides + Polynomial* rhs; + int length; + int memory; +} Identities; + +// symbolic expressions +typedef struct Symbols{ + int* indices; + Polynomial* expr; + int length; + int memory; +} Symbols; + +// groups of independent fields +typedef struct Groups{ + Int_Array* indices; + int length; + int memory; +} Groups; + +// collection of fields +typedef struct Fields_Table{ + // constant parameters + Int_Array parameter; + // anticommuting external fields + Int_Array external; + // anticommuting internal fields + Int_Array internal; + // identities between fields + Identities ids; + // symbolic expressions (commuting) + Symbols symbols; + // list of anti-commuting variables (fields or symbols) + Int_Array fermions; +} Fields_Table; + +// index labels +typedef struct Labels{ + Char_Array* labels; + int* indices; + int length; + int memory; +} Labels; + +// id table +typedef struct Id_Table{ + int* indices; + Polynomial* polynomials; + int length; + int memory; +} Id_Table; + +/* +// polynomial scalar and vectors +typedef struct Polynomial_Scalar{ + Coefficient coef; + int* indices; + int length; +} Polynomial_Scalar; +typedef struct Polynomial_Vector{ + Coefficient* coefv; + int* indices; + int length; +} Polynomial_Vector; +typedef struct Polynomial_Matrix{ + Coefficient** coefm; + int* indices; + int length; +} Polynomial_Matrix; +*/ + + +// command line options +typedef struct Meankondo_Options{ + int threads; + int chain; +} Meankondo_Options; + +typedef struct Numkondo_Options{ + int display_mode; + int niter; + long double tol; + Char_Array eval_rccstring; +} Numkondo_Options; + +typedef struct Meantools_Options{ + int command; + int deriv_derivs; + Int_Array deriv_vars; + Char_Array eval_rccstring; +} Meantools_Options; + +typedef struct Kondopp_Options{ + int dimension; +} Kondopp_Options; + +#endif |