Initial commit
This commit is contained in:
628
src/array.c
Normal file
628
src/array.c
Normal file
@ -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);
|
||||
}
|
||||
|
134
src/array.h
Normal file
134
src/array.h
Normal file
@ -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
|
123
src/cli_parser.c
Normal file
123
src/cli_parser.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
|
35
src/cli_parser.h
Normal file
35
src/cli_parser.h
Normal file
@ -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
|
739
src/coefficient.c
Normal file
739
src/coefficient.c
Normal file
@ -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);
|
||||
}
|
78
src/coefficient.h
Normal file
78
src/coefficient.h
Normal file
@ -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
|
60
src/definitions.cpp
Normal file
60
src/definitions.cpp
Normal file
@ -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
|
28
src/expansions.c
Normal file
28
src/expansions.c
Normal file
@ -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"
|
||||
|
||||
|
34
src/expansions.h
Normal file
34
src/expansions.h
Normal file
@ -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
|
489
src/fields.c
Normal file
489
src/fields.c
Normal file
@ -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);
|
||||
}
|
98
src/fields.h
Normal file
98
src/fields.h
Normal file
@ -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
|
167
src/flow.c
Normal file
167
src/flow.c
Normal file
@ -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);
|
||||
}
|
35
src/flow.h
Normal file
35
src/flow.h
Normal file
@ -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
|
765
src/grouped_polynomial.c
Normal file
765
src/grouped_polynomial.c
Normal file
@ -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);
|
||||
|
||||
}
|
||||
|
74
src/grouped_polynomial.h
Normal file
74
src/grouped_polynomial.h
Normal file
@ -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
|
122
src/idtable.c
Normal file
122
src/idtable.c
Normal file
@ -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);
|
||||
}
|
44
src/idtable.h
Normal file
44
src/idtable.h
Normal file
@ -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
|
99
src/istring.c
Normal file
99
src/istring.c
Normal file
@ -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);
|
||||
}
|
||||
|
40
src/istring.h
Normal file
40
src/istring.h
Normal file
@ -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
|
1449
src/kondo.c
Normal file
1449
src/kondo.c
Normal file
File diff suppressed because it is too large
Load Diff
76
src/kondo.h
Normal file
76
src/kondo.h
Normal file
@ -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
|
126
src/kondo_preprocess.c
Normal file
126
src/kondo_preprocess.c
Normal file
@ -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);
|
||||
}
|
||||
|
793
src/mean.c
Normal file
793
src/mean.c
Normal file
@ -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);
|
||||
}
|
||||
|
70
src/mean.h
Normal file
70
src/mean.h
Normal file
@ -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
|
301
src/meankondo.c
Normal file
301
src/meankondo.c
Normal file
@ -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);
|
||||
}
|
116
src/meantools.c
Normal file
116
src/meantools.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
195
src/meantools_deriv.c
Normal file
195
src/meantools_deriv.c
Normal file
@ -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);
|
||||
}
|
30
src/meantools_deriv.h
Normal file
30
src/meantools_deriv.h
Normal file
@ -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
|
||||
|
129
src/meantools_eval.c
Normal file
129
src/meantools_eval.c
Normal file
@ -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);
|
||||
}
|
||||
|
29
src/meantools_eval.h
Normal file
29
src/meantools_eval.h
Normal file
@ -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
|
||||
|
||||
|
130
src/meantools_exp.c
Normal file
130
src/meantools_exp.c
Normal file
@ -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);
|
||||
}
|
27
src/meantools_exp.h
Normal file
27
src/meantools_exp.h
Normal file
@ -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
|
551
src/number.c
Normal file
551
src/number.c
Normal file
@ -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);
|
||||
}
|
120
src/number.h
Normal file
120
src/number.h
Normal file
@ -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
|
226
src/numkondo.c
Normal file
226
src/numkondo.c
Normal file
@ -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);
|
||||
}
|
||||
|
796
src/parse_file.c
Normal file
796
src/parse_file.c
Normal file
@ -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);
|
||||
}
|
56
src/parse_file.h
Normal file
56
src/parse_file.h
Normal file
@ -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
|
1263
src/polynomial.c
Normal file
1263
src/polynomial.c
Normal file
File diff suppressed because it is too large
Load Diff
131
src/polynomial.h
Normal file
131
src/polynomial.h
Normal file
@ -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
|
23
src/rational.h
Normal file
23
src/rational.h
Normal file
@ -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"
|
196
src/rational_float.c
Normal file
196
src/rational_float.c
Normal file
@ -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
|
64
src/rational_float.h
Normal file
64
src/rational_float.h
Normal file
@ -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
|
190
src/rational_int.c
Normal file
190
src/rational_int.c
Normal file
@ -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
|
59
src/rational_int.h
Normal file
59
src/rational_int.h
Normal file
@ -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
|
95
src/rcc.c
Normal file
95
src/rcc.c
Normal file
@ -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);
|
||||
}
|
39
src/rcc.h
Normal file
39
src/rcc.h
Normal file
@ -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
|
142
src/tools.c
Normal file
142
src/tools.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
49
src/tools.h
Normal file
49
src/tools.h
Normal file
@ -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
|
219
src/types.h
Normal file
219
src/types.h
Normal file
@ -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
|
Reference in New Issue
Block a user