Initial commit

This commit is contained in:
Ian Jauslin 2015-06-14 00:52:45 +00:00
commit aa0f3ae298
61 changed files with 13380 additions and 0 deletions

41
INSTALL Normal file
View File

@ -0,0 +1,41 @@
#######################################################################
## ##
## Compiling and installing meankondo. ##
## ##
#######################################################################
* meankondo should work on any POSIX compliant system, such as GNU/Linux or OSX.
* Compiling:
Run
make
The default paths can be modified by passing the appropriate arguments to
make, as specified in the following table
compiler : CC=/usr/bin/gcc
linker : LD=/usr/bin/gcc
archive : AR=/usr/bin/ar
include : INCLUDE=
lib paths : LIB=
optimize : OPT=-O3
For example,
make CC=/usr/local/bin/gcc INCLUDE=/usr/local/include LIBDIR=-L/usr/local/lib
In addition, libkondo can be linked dynamically or statically, which is
controlled by the STATIC option of the makefile.
If STATIC=0 then link dynamically
If STATIC=2 then link statically
If STATIC=1 (default) then link libkondo statically but other libraries dynamically.
* Installing:
Run
make install
The default install prefix (/usr) can be changed by changing the PREFIX
variable.
For example
make install PREFIX=/usr/local

202
LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

161
Makefile Normal file
View File

@ -0,0 +1,161 @@
## 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.
# whether to link dynamically
# if static=0 then link dynamically
# if static=2 then link statically
# if static=1 then link libkondo statically but other libraries dynamically
STATIC=1
VERSION=1.2
# products of the compilation
PROJECT_BINS= meankondo numkondo meantools kondo_preprocess meantools-convert
PROJECT_SO=libkondo.so.$(VERSION)
PROJECT_LIBS=libkondo.a
PROJECT_MANS=meankondo.1 numkondo.1 meantools.1 meantools-convert.1 kondo_preprocess.1
PROJECT_SCRIPTS=config_functions.sh
PROJECT_DOCS=meankondo-doc.html
# debug and optimization flags
#DB= -ggdb
OPT= -O3
# warning flags
WARNINGS= -Wall -Wextra -Wno-strict-overflow -std=c99 -pedantic
# installation dirs
PREFIX=/usr
BINDIR=$(PREFIX)/bin
LIBDIR=$(PREFIX)/lib
MANDIR=$(PREFIX)/share/man/man1
SCRIPTDIR=$(PREFIX)/share/meankondo/scripts
DOCDIR=$(PREFIX)/share/doc/meankondo-doc
# compiler
CC=/usr/bin/gcc
LD=$(CC)
AR=/usr/bin/ar
# directories
INCLUDE =
LIB =
# flags
override LDFLAGS +=$(LIB)
override CFLAGS +=$(INCLUDE)$(DB) $(OPT) $(WARNINGS)
# build directories
BUILDDIR=./build
SRCDIR=./src
OBJDIR=./objs
# objects
LIBKONDO_OBJS = $(addprefix $(OBJDIR)/,array.o cli_parser.o coefficient.o fields.o grouped_polynomial.o idtable.o istring.o number.o parse_file.o polynomial.o rational_float.o rational_int.o rcc.o tools.o)
MEANKONDO_OBJS = $(addprefix $(OBJDIR)/,meankondo.o mean.o)
NUMKONDO_OBJS = $(addprefix $(OBJDIR)/,numkondo.o flow.o)
MEANTOOLS_OBJS = $(addprefix $(OBJDIR)/,meantools.o meantools_exp.o meantools_deriv.o meantools_eval.o)
KONDO_PP_OBJS = $(addprefix $(OBJDIR)/,kondo_preprocess.o kondo.o)
# flags which depend on whether to link statically or dynamically
# lib flag for libkondo
LIBKONDO_FLAG=-lkondo
# additional library required for static linking
XTRA_LIBS=
ifeq ($(STATIC),1)
# compile libkondo.a
PREREQ=static
# libkondo is linked against libm
XTRA_LIBS=-lm
# link binaries using the static library
LIBKONDO_FLAG=-l:libkondo.a
# install static lib
INSTALLLIB=install-static
else ifeq ($(STATIC),2)
# compile libkondo.a
PREREQ=static
# libkondo is linked against libm
XTRA_LIBS=-lm
# link binaries statically
override LDFLAGS += -static
INSTALLLIB=install-static
else
# compile libkondo.so.$(VERSION)
PREREQ=shared
# required flag for subsequent dynamic linking
override CFLAGS += -fPIC
INSTALLLIB=install-shared
endif
all: init $(PREREQ)
# create dirs
init:
@[ -d $(OBJDIR) ] || /bin/mkdir $(OBJDIR)
@[ -d $(BUILDDIR) ] || /bin/mkdir $(BUILDDIR)
@[ -d $(BUILDDIR)/bin ] || /bin/mkdir $(BUILDDIR)/bin
@[ -d $(BUILDDIR)/lib ] || /bin/mkdir $(BUILDDIR)/lib
# static library
static: $(PROJECT_LIBS) $(PROJECT_BINS)
# shared library
shared: $(PROJECT_SO) $(PROJECT_BINS)
libkondo.a: $(LIBKONDO_OBJS)
$(AR) -rc $(BUILDDIR)/lib/$@ $^
libkondo.so.$(VERSION): $(LIBKONDO_OBJS)
$(LD) -shared -lm $(LDFLAGS) -o $(BUILDDIR)/lib/$@ $^
ln -fs ./libkondo.so.$(VERSION) $(BUILDDIR)/lib/libkondo.so
meankondo: $(MEANKONDO_OBJS)
$(LD) -L$(BUILDDIR)/lib $(LDFLAGS) -o $(BUILDDIR)/bin/$@ $^ $(LIBKONDO_FLAG) -lpthread $(XTRA_LIBS)
numkondo: $(NUMKONDO_OBJS)
$(LD) -L$(BUILDDIR)/lib $(LDFLAGS) -o $(BUILDDIR)/bin/$@ $^ $(LIBKONDO_FLAG) -lm $(XTRA_LIBS)
meantools: $(MEANTOOLS_OBJS)
$(LD) -L$(BUILDDIR)/lib $(LDFLAGS) -o $(BUILDDIR)/bin/$@ $^ $(LIBKONDO_FLAG) $(XTRA_LIBS)
meantools-convert:
cp scripts/meantools-convert $(BUILDDIR)/bin/
kondo_preprocess: $(KONDO_PP_OBJS)
$(LD) -L$(BUILDDIR)/lib $(LDFLAGS) -o $(BUILDDIR)/bin/$@ $^ $(LIBKONDO_FLAG) $(XTRA_LIBS)
%.o : ../$(SRCDIR)/%.c
$(CC) -c $(CFLAGS) $< -o $@
install: $(INSTALLLIB) all
mkdir -p $(BINDIR) $(MANDIR) $(SCRIPTDIR) $(DOCDIR)
install -Dm755 $(addprefix $(BUILDDIR)/bin/,$(PROJECT_BINS)) $(BINDIR)/
install -Dm644 $(addprefix man/,$(PROJECT_MANS)) $(MANDIR)/
gzip $(addprefix $(MANDIR)/,$(PROJECT_MANS))
install -Dm644 $(addprefix scripts/,$(PROJECT_SCRIPTS)) $(SCRIPTDIR)/
install -Dm644 $(addprefix doc/,$(PROJECT_DOCS)) $(DOCDIR)/
install-static: all
mkdir -p $(LIBDIR)
install -Dm755 $(addprefix $(BUILDDIR)/lib/,$(PROJECT_LIBS)) $(LIBDIR)/
install-shared: all
mkdir -p $(LIBDIR)
install -Dm755 $(addprefix $(BUILDDIR)/lib/,$(PROJECT_SO)) $(LIBDIR)/
for lib in $(PROJECT_SO); do ln -fs ./$$lib $(LIBDIR)/$${lib%.so.*}.so; done
clean:
@rm -rf $(OBJDIR)
@rm -rf $(BUILDDIR)

2
NOTICE Normal file
View File

@ -0,0 +1,2 @@
meankondo
Copyright 2015 Ian Jauslin

298
doc/meankondo-doc.html Normal file
View File

@ -0,0 +1,298 @@
<html>
<head>
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script>
<!--<script type="text/javascript" src="/usr/share/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script>-->
<style>
body {
margin-top:40pt;
margin-bottom:40pt;
margin-left:40pt;
margin-right:40pt;
text-align:justify;
}
p {
text-indent:20pt;
}
.codeblock {
display:block;
margin-left:40pt;
margin-top:10pt;
margin-bottom:15pt;
text-indent:0pt;
}
.toc {
font-weight:bold;
}
.toc ul {
list-style-type:none;
}
.toc_sec {
counter-increment: tocsec;
counter-reset: tocsub 0;
}
.toc_sec:before {
content: counter(tocsec) ". ";
}
.toc_sub {
counter-increment: tocsub;
}
.toc_sub:before {
content: counter(tocsec) "." counter(tocsub) ". ";
}
body {
counter-reset: section 0;
}
.section:before {
counter-increment: section;
content: counter(section) ". ";
}
.section {
margin-top:50pt;
counter-reset: subsection 0;
}
.subsection:before {
counter-increment: subsection;
content: counter(section) "." counter(subsection) ". ";
}
.subsection {
margin-top:30pt;
}
</style>
</head>
<body>
<h1 style="margin-bottom:50pt;">meankondo <span style="margin-left:10pt;font-size:18pt">v1.2</span></h1>
<p>
This is the official documentation for <b>meankondo</b>, version 1.2. The aim of this document is not to give a technical description of how to use the various programs bundled with <b>meankondo</b>, nor is it to explain where hierarchical models come from and what their meaning is, but rather a conceptual overview of how <b>meankondo</b> approaches the computation of flow equations, and how its programs can be made to interact with one another to compute various quantities. For a more technical description, see the man pages included with the <b>meankondo</b> source code. For a more theoretical discussion of Fermionic hierarchical models, see [G.Benfatto, G.Gallavotti, I.Jauslin, 2015].
</p>
<h2 style="margin-top:50pt;">Table of contents</h2>
<div class="toc">
<ul>
<li class="toc_sec"><a href="#description">Description</a></li>
<li class="toc_sec"><a href="#quickstart">Quickstart</a></li>
<li class="toc_sec"><a href="#fermionic_hierarchical_models">Fermionic hierarchical models</a></li>
<ul>
<li class="toc_sub"><a href="#fields">Fields</a></li>
<li class="toc_sub"><a href="#propagator">Propagator</a></li>
</ul>
<li class="toc_sec"><a href="#flow_equation">Flow Equation</a></li>
<ul>
<li class="toc_sub"><a href="#flow_equation_definition">Definition</a></li>
<li class="toc_sub"><a href="#flow_equation_computation">Computation</a></li>
</ul>
<li class="toc_sec"><a href="#operations">Operations on flow equations</a></li>
<ul>
<li class="toc_sub"><a href="#numerical_evaluation">Numerical Evaluation</a></li>
<li class="toc_sub"><a href="#exponentiation">Exponentiation</a></li>
<li class="toc_sub"><a href="#derivation">Derivation</a></li>
</ul>
<li class="toc_sec"><a href="#exactness">Comments on the exactness of the computation</a></li>
<li class="toc_sec"><a href="#authors">Authors</a></li>
</ul>
</div>
<h2 class="section" id="description">Description</h2>
<p>
<b>meankondo</b> is a collection of tools to compute and manipulate the renormalization group flow in Fermionic hierarchical models. The programs included in <b>meankondo</b> are the following:
<ul>
<li><b>meankondo</b>: computes the flow equation.</li>
<li><b>numkondo</b>: iterate the flow equation numerically.</li>
<li><b>meantools</b>: tools to exponentiate, derive and evaluate a flow equation.</li>
<li><b>meantools-convert</b>: python script to convert a flow equation to C, javascript or LaTeX code.</li>
</ul>
as well as <i>pre-processors</i>, whose purpose is to help with writing configuration files for specific models:
<ul>
<li><b>kondo_preprocess</b>: hierarchical Kondo model.</li>
</ul>
In addition, <b>meankondo</b> includes a library, <b>libkondo</b>, which can either be compiled as a <i>shared</i> or a <i>static</i> object, and contains the various structures and functions <b>meankondo</b> is built with.
</p>
<p>
<b>Remark</b>: The name "meankondo" comes from the fact that it was originally developed for the hierarchical Kondo model, though the tools in <b>meankondo</b> are quite versatile and can be used for a wide variety of Fermionic hierarchical models.
</p>
<h2 class="section" id="quickstart">Quickstart</h2>
<p>
We first discuss the more elementary commands that can be used to compute and iterate flow equations. The rest of this document is dedicated to what flow equations are and how <b>meankondo</b> represents and manipulates them.
</p>
<p>
Given a configuration file 'config', the flow equation can be computed by
<code class="codeblock">
meankondo config
</code>
and it can be iterated for, say, 100 steps starting from \(\ell_0^{[m]}=-0.01\) using
<code class="codeblock">
meankondo -C config | numkondo -N 100 -I "0:-0.01"
</code>
</p>
<h2 class="section" id="fermionic_hierarchical_models">Fermionic hierarchical models</h2>
<p>
In this section, we discuss how the models that <b>meankondo</b> can process are defined. A model is specified by a collection of <i>fields</i>, and a <i>propagator</i> between pairs of fields.
</p>
<h3 class="subsection" id="fields">Fields</h3>
<p>
Fields are the elementary objects in terms of which a model is defined. Fields can be one of
<ul>
<li><b>internal</b>: which are organized in pairs, and are denoted by \((\psi_i^+,\psi_i^-)\) for \(i\in\{1,\cdots,I\}\).
<li><b>external</b>: which are organized in pairs, and are denoted by \((\Psi_i^+,\Psi_i^-)\) for \(i\in\{1,\cdots,E\}\).
<li><b>super-external</b>: which denoted by \(H_i\) for \(i\in\{1,\cdots,X\}\) (the only difference with external fields is that super-external fields are not in pairs, which is a seemingly innocuous difference; but super-external fields are meant to be used for different purposes as external fields (see <a href="#flow_equation_definition">Definition</a> below)).
</ul>
The fields are used as a basis for a complex algebra, so that we can take products and linear combinations of fields (in other words, the concept of <i>polynomials over the fields</i> is well defined). Some of the fields (<i>Fermions</i>) anti-commute with each other (two fields \(a\) and \(b\) are said to anti-commute if \(ab\equiv-ba\)), and the rest (<i>Bosons</i>) commute. Which fields are Fermions and which are Bosons is specified in the <code>#!fields</code> entry in the configuration file. <b>(Warning: As of version 1.2, all internal fields must be Fermions.)</b>
</p>
<p>
In the configuration file of the <b>meankondo</b> program, the fields are specified in the <code>#!fields</code> entry.
</p>
<h3 class="subsection" id="propagator">Propagator</h3>
<p>
Given a collection of fields, a <i>model</i> is specified as a recipe for computing the <i>average</i> of a polynomial of fields. We will use the following notation: given a polynomial \(F(\psi,\Psi,H)\) in the fields, its average will be denoted by \(\langle F(\psi,\Psi,H)\rangle\). The average is a linear operation, and, as indicated by the name "internal", only acts on internal fields, so that the external and super-external fields are viewed as constants for the averaging operation and can be factored out. It therefore suffices to define the average of a monomial of internal fields.
</p>
<p>
First of all, a monomial of internal fields which does not contain the same number of \(\psi^+_i\) as \(\psi^-_j\) is \(0\). The average of a monomial of the form \(\psi_{i_1}^+\psi_{j_1}^-\cdots\psi_{i_n}^+\psi_{j_n}^-\) in which \(n\in\mathbb N\), \((i_1,\cdots,i_n)\in\{1,\cdots,I\}^n\) and \((j_1,\cdots,j_n)\in\{1,\cdots,I\}^n\), is computed using the <i>Wick rule</i>:
$$
\langle\psi_{i_1}^+\psi_{j_1}^-\cdots\psi_{i_n}^+\psi_{j_n}^-\rangle=
\sum_{\pi\in\mathcal S_n}(-1)^\pi\langle\psi_{i_1}^+\psi_{j_{\pi(1)}}^-\rangle\cdots\langle\psi_{i_n}^+\psi_{j_{\pi(N)}}^-\rangle
$$
in which \(\mathcal S_n\) denotes the set of permutations of \(\{1,\cdots,n\}\) and \((-1)^\pi\) denotes the signature of \(\pi\). Using the Wick rule, we can specify any average by defining the quadratic moments of the model, similarly to the moments of a 0-mean Gaussian measure. The collection of all quadratic moments of the form
$$\langle\psi_i^+\psi_j^-\rangle$$
with \((i,j)\in\{1,\cdots,I\}^2\) is called the <i>propagator</i> of the model.
</p>
<p>
In the configuration file of the <b>meankondo</b> program, the propagator is specified in the <code>#!propagator</code> entry. Note that <b>meankondo</b> recognizes numeric propagators as well as symbolic ones.
</p>
<h2 class="section" id="flow_equation">Flow equation</h2>
<p>
In this section, we discuss what flow equations are, and how <b>meankondo</b> computes them.
</p>
<h3 class="subsection" id="flow_equation_definition">Definition</h3>
<p>
We first discuss how a flow equation is defined from a renormalization group map. The discussion below is not, in any sense, precise, and is meant as a guiding idea to understand why <b>meankondo</b> does what it does in the way it does.
</p>
<p>
Consider a map, which we will call the <i>renormalization group</i> flow, of the form:
$$
V^{[m]}(\Phi^{[m]},H)\longmapsto V^{[m-1]}(\Phi^{[m-1]},H)=\frac1{C^{[m]}}\left(\left\langle\prod_{\nu=1}^k\left(1+V^{[m]}(\Phi_\nu^{[m]},H)\right)\right\rangle-1\right)
$$
where \(V^{[m]}\) anf \(V^{[m-1]}\) are polynomials with no constant term, \(C^{[m]}\in\mathbb R\setminus\{0\}\) is a constant, \(\langle\cdot\rangle\) is the average defined in <a href="#propagator">Propagator</a>, \(H\) is the collection of super-external fields, \(k=I/E\) which we assume to be an integer, \(\{\Phi^{[m]\pm}_{\nu,i}\}_{i\in\{1,\cdots,E\},\ k\in\{1,\cdots,k\}}\) and \(\{\Phi^{[m-1]\pm}_{i}\}_{i\in\{1,\cdots,E\}}\) are collections of combinations of the internal and external fields, of the form
$$
\Phi^{[m]\pm}_{\nu,i}=\alpha_i\Psi_i^\pm+\psi_{j_\nu^{(i)}}^\pm,\quad
\Phi^{[m-1]\pm}_{i}=\Psi_i^\pm
$$
in which \(\alpha_i\in\mathbb R\setminus\{0\}\) is some <i>re-scaling</i> factor, and
$$
\bigcup_{i\in\{1,\cdots,E\}}^\circ\{j_1^{(i)},\cdots,j_k^{(i)}\}=\{1,\cdots,I\}
$$
in which the \(\circ\) over the union means it is disjoint.
</p>
<p>
If \(V^{[m-1]}\) can be written in the same form as \(V^{[m]}\), then the renormalization group map can be written as a finite system of equations: if there exist \(p\in\mathbb N\), \((\ell_1^{[m]},\cdots,\ell_p^{[m]})\in\mathbb C^p\), \((\ell_1^{[m-1]},\cdots,\ell_p^{[m-1]})\in\mathbb C^p\), and polynomials \((O_1(\Phi,H),\cdots,O_l(\Phi,H))\) such that
$$
V^{[m]}(\Phi_\nu^{[m]},H)=\sum_{n=1}^p\ell_n^{[m]}O_n(\Phi_\nu^{[m]},H),\quad
V^{[m-1]}(\Phi^{[m-1]},H)=\sum_{n=1}^p\ell_n^{[m-1]}O_n(\Phi^{[m-1]},H)
$$
then the renormalization group map can be written as a finite system of equations, called the <i>flow equation</i>, which maps
$$
(\ell_1^{[m]},\cdots,\ell_p^{[m]})\longmapsto(C^{[m]},\ell_1^{[m-1]},\cdots,\ell_1^{[m-1]})
$$
(we added the constant \(C^{[m]}\) which plays an important role). The collection \(\underline\ell\) is called the collection of <i>running coupling constants</i>.
</p>
<h3 class="subsection" id="flow_equation_computation">Computation</h3>
<p>
We now discuss how <b>meankondo</b> computes flow equations. The two relevant configuration file entries are <code>#!input_polynomial</code> and <code>#!id_table</code>.
</p>
<p>
The entry <code>#!input_polynomial</code> specifies a polynomial \(F(\underline\ell,\psi,\Psi,H)\) in the fields, as well as in a family of complex symbolic variables \(\underline\ell=(\ell_1,\cdots,\ell_p)\). In the context of the computation in <a href="#flow_equation_definition">Definition</a>, it would be of the form
$$
\prod_{\nu=1}^k\left(1+\sum_{n=1}^p\ell_nO_n(\Phi_{\nu}^{[m]},H)\right).
$$
</p>
<p>
The entry <code>#!id_table</code> specifies a sequence of \(p\) polynomials \((O_1(\Psi,H),\cdots,O_p(\Psi,H))\) in the external fields. In the context of the computation in <a href="#flow_equation_definition">Definition</a> the \(n\)-th polynomial would be
$$
O_n(\Phi_{\nu}^{[m]},H)
$$
which specifies that \(O_n\) corresponds to \(\ell_n\).
</p>
<p>
<b>meankondo</b> first computes the average
$$
F'(\underline\ell,\Psi,H):=\langle F(\underline\ell,\psi,\Psi,H)\rangle
$$
and then <i>groups</i> \(F'\) according to the id table, that is it tries to put it in the form
$$
F'(\underline\ell,\Psi,H)=C(\underline\ell)\left(1+\sum_{n=1}^p\ell'_n(\underline\ell)O_n(\Psi,H)\right)
$$
in which \(C(\underline\ell)\) is a complex constant term and \(\ell'_n(\underline\ell)\) is some complex coefficient, which are both functions of \(\underline\ell\). Note that for Fermionic hierarchical models, \(\ell'_n\) is a rational function of \(\underline\ell\), and \(C\) is a polynomial in \(\underline\ell\). In addition, \(\ell'_n\) can be expressed as a polynomial in \((\underline\ell,C^{-1}(\underline\ell))\). The flow equation is then defined as
$$
\mathcal R:\underline\ell\longmapsto(C(\underline\ell),\ell'_1(\underline\ell),\cdots,\ell'_p(\underline\ell))
$$
If \(F'\) cannot be grouped, then <b>meankondo</b> exits with error code <code>-1</code>.
</p>
<h2 class="section" id="operations">Operations on flow equations</h2>
<p>
In this section we describe the various operations on flow equations that the tools bundled with <b>meankondo</b> support.
</p>
<h3 class="subsection" id="numerical_evaluation">Numerical evaluation</h3>
<p>
Once a flow equation \(\mathcal R\) has been computed, it can be numerically evaluated by passing a vector \(\underline\ell\) of double precision floating point numbers to <b>meantools eval</b> or <b>numkondo</b> which computes \(\mathcal R(\underline\ell)\) in the former case, and \(\mathcal R^m(\underline\ell)\) for any \(m\in\mathbb N\) in the latter.
</p>
<p>
Numerical evaluation is handled in a straightforward manner, but for the following consideration. As was mentioned in <a href="#flow_equation_computation">Computation</a>, \(\mathcal R\) is a polynomial in \((\underline\ell,C^{-1}(\underline\ell))\), and when evaluating \(\mathcal R(\underline\ell)\), <b>meankondo</b> first evaluates \(C\) and the computes \(\ell'_n(\underline\ell)\).
</p>
<h3 class="subsection" id="exponentiation">Exponentiation</h3>
<p>
Oftentimes the renormalization group flow is expressed in terms of an exponential of an effective potential \(\exp(W)\), in which case the exponential must be computed before it can be processed by <b>meankondo</b>:
$$
\exp(W)=1+V.
$$
This is handled by <b>meantools exp</b>, which computes the running coupling constants appearing in \(V\) in terms of those in \(W\).
</p>
<h3 class="subsection" id="derivation">Derivation</h3>
<p>
This feature was introduced to compute the susceptibility in the hierarchical Kondo model. In that case, some of the running coupling constants depend on the field, \(h\), and the susceptibility is expressed as a derivative of \(C(\underline\ell(h))\) with respect to \(h\). To that end, we wrote <b>meantools derive</b> to compute the derivatives of a flow equation with respect to an external variable.
</p>
<p>
The input of <b>meantools derive</b> consists in a flow equation and a collection of variables \(X\subset\{1,\cdots,p\}\). Each running coupling constant \(\ell_i\) for \(i\in X\) is assumed to depend on an external parameter, \(h\). The flow equation is then derived with respect to \(h\): for every \(n\in\{1,\cdots,p\}\), the derivative of \(\ell_n'(\underline\ell)\) with respect to \(h\) in terms of \(\partial_h\ell_i\) for \(i\in X\) is computed. It is then appended to the input flow equation.
</p>
<h2 class="section" id="exactness">Comments on the exactness of the computation</h2>
<p>
The computation of the flow equation, as well as its exponentiation and derivation, are <i>exact</i> in the sense that they only involve operations on integers and are not subject to truncations. The coefficients appearing in the flow equation are therefore <i>exact</i>. This statement has one major caveat: integer operations are only correct as long as the integers involved are not too large. The precise meaning of "not too large" is system dependent. In the source code, integers relating to flow equation coefficients are declared with the <code>long int</code> type, which, at least using the C library <b>meankondo</b> was tested with (that is <code>glibc 2.21</code>), means integers are encoded on 64 bits on 64-bit systems and 32 bits on 32-bit systems. All operations are therefore exact as long as all integers are in \([-2^{31},2^{31}-1]\) on 64-bit systems and \([-2^{15},2^{15}-1]\) on 32-bit systems.
</p>
<!--<p>
Numerical evaluations are not exact. The numbers manipulated <b>meankondo</b> are double precision floating point numbers ("doubles" for short), which are also system-dependent. On systems that follow the IEEE 754 standard, doubles have a precision of 53 bits, which implies they are accurate to 15 decimal places; and the absolute value of doubles is bounded above by \(2^{1024}-2^{1024-53}\) (that is the number whose binary expansion has \(1023\) digits and whose \(53\) left-most digits are \(1\) whereas the others are \(0\)) and below by \(2^{-1022}\).
</p>-->
<p>
Numerical evaluations are not exact. The numbers manipulated <b>meankondo</b> are "long doubles", which, when compiled for x86 processors, have a precision of 64 bits, which implies they are accurate to 19 decimal places; and the absolute value of doubles is bounded above by \(2^{16384}-2^{16384-64}\) (that is the number whose binary expansion has \(16383\) digits and whose \(64\) left-most digits are \(1\) whereas the others are \(0\)) and below by \(2^{-16382}\).
</p>
<h2 class="section" id="authors">Authors</h2>
<p>
<b>meankondo</b> was written by Ian Jauslin, in the context of a project in collaboration with Giuseppe Benfatto and Giovanni Gallavotti.
</p>
</body>
</html>

163
man/kondo_preprocess.1 Normal file
View File

@ -0,0 +1,163 @@
.Dd $Mdocdate: April 14 2015 $
.Dt kondo_preprocess 1.2
.Os
.Sh NAME
.Nm kondo_preprocess
.Nd A pre-processor to generate configuration files for
.Sy meankondo
for the Kondo model
.Sh SYNOPSIS
.Nm
.Op Fl d Ar dimension
.Op Ar config_file
.Pp
.Nm
.Fl v
.Sh DESCRIPTION
.Nm
generates a configuration file to be read by
.Sy meankondo
for the Kondo model. It generates the '#!fields', '#!symbols', '#!identities', '#!groups', '#!propagator', '#!input_polynomial' and '#!id_table' entries from special '#!propagator', '#!input_polynomial' and '#!id_table' entries, which are much more synthetic than those needed for the Kondo model.
.Pp
The quantities in the configuration file are expressed in terms of the observables A and B, which we do not define here, as well as the magnetic field h.
.Pp
.Nm
is part of a set of tools to compute and manipulate Fermionic hierarchical flows:
.Bl -bullet
.It
.Sy meankondo
: computes flow equations for hierarchical Fermionic models
.It
.Sy numkondo
: numerical evaluation of flow equations.
.It
.Sy meantools, meantools-convert
: perform various operations on flow equations (derivation, exponentiation, evaluation and conversion to other formats).
.El
.Pp
as well as the following pre-processors, which generate configuration files for their associated model:
.Bl -bullet
.It
.Sy kondo_proprocess
: Kondo model
.El
.Pp
.Sh COMMAND-LINE ARGUMENTS
.Bl -tag -width Ds
.It Fl d Ar dimension
The dimension of the field theory for the Kondo model (defaults to 2), including imaginary time (2 if the Fermionic chain is not neglected, 1 if it is). This parameter is used to determine how many boxes contribute to each scale in the hierarchical model: id the dimension is 2, then there are 4 boxes, whereas if it is 1, then there are 2.
.It Fl v
Print version information and exit.
.El
.Pp
.Sh CONFIGURATION FILE
.Nm
reads a configuration file, that can either be passed as a command line argument or to stdin, which specifies the model for which to compute the flow equation.
.Pp
A configuration file is a list of entries, separated by a '&' character, each of which has a title (or header), which is preceded by '#!'. Note that '#!' must be at the beginning of a line in order to be read correctly.
.Pp
Whenever the '#' character is encountered, the rest of the line is treated as a comment and ignored (unless it is followed by '!').
.Pp
As a general rule, spaces and line breaks in the entries of the configuration file are ignored, so they may be used at the user's discretion. The few entries that require that no extra line breaks be inserted are explicitly mentioned below.
.Pp
.Nm
recognizes the following entries (unless explicitly mentioned, the entries below are mandatory) (entries may be provided in any order) (any extra entries in the configuration file are ignored):
.Bl -tag -width Ds
.It Sy #!input_polynomial
The polynomial whose mean we wish to compute in order to calculate the flow equation.
.Pp
The format of the polynomial is similar to that in
.Sx meankondo Ns (1) ,
up to the following differences.
.Bl -bullet
.It
The fields can be specified as scalar products of A's and B's. For each n in {1,...,dimension},
.Nm
defines An and Bn, as well as symbols for scalar products of the form
.D1 [f An.An]
.D1 [f Bn.Bn]
.D1 [f An.Bn]
.D1 [f An.h]
.D1 [f Bn.h]
In addition, a vector product symbol is defined for (AnxBn).h :
.D1 [f AnxBn.h]
.Pp
.It
In addition,
.Nm
defines external fields for A and B, denoted by a and b. They can be used as fields in the input polynomial using the syntax
.D1 <a.a>
.D1 <b.b>
.D1 <a.b>
.D1 <a.h>
.D1 <b.h>
.D1 <axb.h>
.Pp
.It
Furthermore, in order to simplify writing products of polynomials over each box index, if the polynomial contains a '%', then
.Nm
multiplies the polynomial by itself as many times as there are boxes (2^dimension times), replacing '%' with the appropriate box index. For example, if dimension=1
.D1 '[fA%.A%]+[fB%.B%]'
is equivalent to
.D1 '[fA1.A1]+[fB1.B1] * [fA2.A2]+[fB2.B2]'.
.El
.Pp
Example:
.D1 (1) + (1/2)[l1][fA1.A1] + (1/2)[l2][fB1.h]
.D1 * (1) + (1/2)[l2][fA2.A2] +(1/2)[l2][fB2.h]
.Pp
.It Sy #!id_table
The idtable used to identify the running coupling constants.
.Pp
The idtable has the same syntax as that in
.Sx meankondo Ns (1) ,
in which the polynomial can use the fields
.D1 <a.a>
.D1 <b.b>
.D1 <a.b>
.D1 <a.h>
.D1 <b.h>
.D1 <axb.h>
defined above.
.Pp
Example:
.D1 1:(1/2)<a.a>, 2:(2)<b.h>
.Pp
.It Sy #!propagator
The propagator of the model.
.Pp
The propagator syntax differs from
.Sx meankondo Ns (1) ,
in that the field indices are specified using An and Bn.
.Pp
Example:
.D1 A1;A2: 1 , A2;A1: -1 , B1;B2: s{-1} , B2;B1: (-1)s{-1}
.Pp
.It Sy extra entries
If there is a '#!symbols' or an '#!identities' entry in the configuration file, then they are appended to the end of those entries in the new configuration file.
.Pp
Any other entry is appended to the new configuration file. This can be useful to pipe the output to tools other than
.Sy meankondo
(e.g.
.Sy meantools ) .
.Pp
.Sh OUTPUT
.Nm
prints the configuration file to stdout.
.Pp
The output of
.Nm
can be piped into
.Sy meankondo
directly.
.Pp
.Sh RETURN CODE
.Nm
returns 0 on success and -1 on error.
.Pp
.Sh SEE ALSO
.Sx meankondo Ns (1) ,
.Sx numkondo Ns (1) ,
.Sx meantools Ns (1) ,
.Sx meantools-convert Ns (1)
.Pp

221
man/meankondo.1 Normal file
View File

@ -0,0 +1,221 @@
.Dd $Mdocdate: April 13 2015 $
.Dt meankondo 1.2
.Os
.Sh NAME
.Nm meankondo
.Nd A tool to compute renormalization group flows for Fermionic hierarchical models
.Sh SYNOPSIS
.Nm
.Op Fl t Ar threads
.Op Fl C
.Op Ar config_file
.Pp
.Nm
.Fl v
.Sh DESCRIPTION
.Nm
computes the renormalization group flow equations for Fermionic hierarchical models, which should be defined in the configuration file provided on the command line, following the syntax detailed below.
.Pp
The flow equation is computed by calculating the mean of a polynomial of fields and running coupling constants using the Wick rule and a propagator provided in the configuration file. The running coupling constants are then identified in the resulting polynomial using an idtable provided in the configuration file.
.Pp
.Nm
is part of a set of tools to compute and manipulate Fermionic hierarchical flows:
.Bl -bullet
.It
.Sy meankondo
: computes flow equations for hierarchical Fermionic models
.It
.Sy numkondo
: numerical evaluation of flow equations.
.It
.Sy meantools, meantools-convert
: perform various operations on flow equations (derivation, exponentiation, evaluation and conversion to other formats).
.El
.Pp
as well as the following pre-processors, which generate configuration files for their associated model:
.Bl -bullet
.It
.Sy kondo_proprocess
: Kondo model
.El
.Pp
.Sh COMMAND-LINE ARGUMENTS
.Bl -tag -width Ds
.It Fl t Ar threads
The number of threads to use for the computation.
.It Fl C
Format the ouptput so it can be piped to
.Sy numkondo ,
that is, instead of printing the flow equation, print a full configuration file containing the flow equation as well as all the other entries of the configuration file that do not pertain to the computation of the flow equation.
.It Fl v
Print version information and exit.
.El
.Pp
.Sh CONFIGURATION FILE
.Nm
reads a configuration file, that can either be passed as a command line argument or to stdin, which specifies the model for which to compute the flow equation.
.Pp
A configuration file is a list of entries, separated by a '&' character, each of which has a title (or header), which is preceded by '#!'. Note that '#!' must be at the beginning of a line in order to be read correctly.
.Pp
Whenever the '#' character is encountered, the rest of the line is treated as a comment and ignored (unless it is followed by '!').
.Pp
As a general rule, spaces and line breaks in the entries of the configuration file are ignored, so they may be used at the user's discretion. The few entries that require that no extra line breaks be inserted are explicitly mentioned below.
.Pp
.Nm
recognizes the following entries (unless explicitly mentioned, the entries below are mandatory) (entries may be provided in any order) (any extra entries in the configuration file are ignored):
.Bl -tag -width Ds
.It Sy #!fields
A list of the fields of the model.
.Pp
The fields entry contains 4 lines which start with 'i:', 'x:', 'h:' and 'f:'. Each of these is followed by a ',' separated list of field indices, which are positive integers.
.Bl -bullet
.It
The indices following 'i' correspond to internal fields, which are integrated out using the Wick rule and the propagator provided in the '#!propagator' entry. Each internal field is associated a conjugate field, whose index is the opposite of the field's index (e.g. 'i:101' defines a field whose index is -101)
.It
The indices following 'x' correspond to external fields that are associated conjugate field (e.g. 'x:100' defines a field whose index is -100). External indices may not appear as internal indices.
.It
The indices following 'h' correspond to external fields that are not associated a conjugate field. External indices may not appear as internal indices.
.It
The 'f' line specifies which of the internal and external indices are Fermions, i.e. which fields anti-commute. The fields appearing in the 'f' line should also either appear in the 'i' or 'x' line. WARNING: for the moment, only cases in which all of the internal fields are Fermions are supported.
.El
.Pp
.Em Line breaks are not ignored in this entry.
.Pp
Example:
.D1 i:101,102,201,202
.D1 x:100,200
.D1 h:301,302,303
.D1 f:100,101,102
.It Sy #!propagator
The propagator of the model.
.Pp
The propagator entry is a ',' separated list whose elements are of the form
.D1 index1;index2: polynomial
where index1 and index2 are internal indices, and polynomial is a polynomial (see the POLYNOMIALS section below for information on how to format polynomials). The polynomial must not depend on the internal fields. Note that a number is a special type of polynomial, so propagators with numerical entries are handled by
.Nm
just as easily as propagators with symbolic entries. Such an entry means that
.D1 <psi_{index1}^-psi_{index2}^+> = polynomial.
.Pp
Example:
.D1 101;102: 1 , 102;101: -1 , 201;202: s{-1} + (-1)[l10] , 202;201: (-1)s{-1} + [l10]
.It Sy #!symbols
Symbolic variables used as shortcuts for more complicated expressions (optional entry).
.Pp
In order to simplify long expressions, symbolic variables can be defined in this entry. Each variable is assigned an index, which is a positive integer that must be different from any of the internel and external indices defined in the '#!fields' entry.
.Pp
The symbols entry is a ',' separated list, whose elements are of the form
.D1 index= polynomial
where index is the index of the variable and polynomial is the expression it stands for (see the POLYNOMIALS section below for information on how to format polynomials). Note that polynomial can contain other symbolic variables. There is no safeguard against self-referencing definitions that may cause infinite loops.
.Pp
Example:
.D1 1001= (-1)[f-100][f100] + (-1)[f-101][f101] , 2001=[f-100][f100] + [f-201][f201]
.Pp
This entry is optional.
.Pp
.It Sy #!identities
Identities satisfied by some of the fields (optional entry).
.Pp
In some cases, some of the quantities involved in a model will satisfy an identity (e.g. a vector may be of unit-norm), which should simplified out from the flow equation.
.Pp
The identities entry is a ',' separated list, whose elements are of the form
.D1 monomial=polynomial
where monomial represents the left side of the identity and is a sequence of field indices of the form '[f index1][f index2]...' and polynomial represents the right side of the identity (see the POLYNOMIALS section below for information on how to format polynomials).
.Pp
Example:
.D1 [f301][f301]=(1)+(-1)[f302][f302]+(-1)[f303][f303]
.Pp
This entry is optional.
.Pp
.It Sy #!input_polynomial
The polynomial whose mean we wish to compute in order to calculate the flow equation.
.Pp
The format of the polynomial is that specified in the POLYNOMIALS section. In addition, the polynomial can be specified as the product of other polynomials:
.D1 polynomial1 * polynomial2 * ...
Note that there are no parentheses, and therefore, products cannot be nested, nor can a product of polynomials be summed with another polynomial.
.Pp
Example:
.D1 (1) + (1/2)[l1][f1001] * (1) + (1/2)[l2][f2001]
.It Sy #!id_table
The idtable used to identify the running coupling constants.
.Pp
Once the mean of the input polynomial has been computed, we are left with a polynomial of the external fields and the running coupling constants that were in the input polynomial. In order to compute a flow equation from this average,
.Nm
uses an idtable to identify which of the monomials of the average contribute to which running coupling constant.
.Pp
The id_table entry is a ',' separated list, whose elements are of the form
.D1 rcc: polynomial
where rcc is the index of the corresponding running coupling constant, which is a non-negative integer, and polynomial is the polynomial to which rcc refers to (which is a polynomial of the external fields).
.Pp
Example:
.D1 1:(-1)[f-100][f100] , 2:[f-200][f200]
.It Sy #!groups
Groups of independent variables (optional entry).
.Pp
In order to speed up the computation of the mean of the input polynomial, groups of independent variables can be specified. When
.Nm
computes the mean of a monomial containing elements of different groups, it factors the monomial into independent factors, computes the mean of each factor, and then takes their product. This way,
.Nm
does not repeatedly try to pair independent fields.
.Pp
The groups entry is a list of collections of fields or symbols of the following form
.D1 (index1,index2,...)
.Pp
Example:
.D1 (1001,1002) (2001,2002)
.Pp
.Em Warning:
.Nm
does not check that the fields in different groups are truly independent, so cases in which fields in different group have a non-vanishing propagator entry may give unexpected results.
.Pp
This entry is optional.
.El
.Pp
.Sh NUMBERS
.Nm
can parse rational numbers and linear combinations of square roots of integers (positive or negative (which is how complex numbers are implemented)) with rational coefficients (i.e. elements of the field extension of Q generated by sqrt(Z)).
.Pp
A number is a '+' separated list whose elements are of the form
.D1 (a/b)s{r}
where a and r are integers and b is a positive integer. s{r} stands for sqrt(r).
.Pp
If a=b, then the number may be written as 's{r}'. If b=1, then it can be '(a)s{r}'. If r=1, then it can be 'a/b'. If b=r=1, then it can be 'a'.
.Pp
Example:
.D1 (1/2)s{2} + (-1)s{-1} + 3/2
.Pp
.Sh POLYNOMIALS
Polynomials are '+' separated lists of monomials. Each monomial is a sequence of numbers, rccs and fields.
.Bl -bullet
.It
Numbers are enclosed between '(' and ')'. If there are several numbers in a monomial, then they are multiplied.
.It
rccs are non-negative indices enclosed between '[l' and ']'.
.It
Fields are non-vanishing indices enclosed between '[f' and ']'. Fields must either appear in the '#!fields' entry or the '#!symbols' entry.
.El
.Pp
If the numerical factor of a monomial is 1, then it can be dropped. However, even if the numerical factor is a single integer, its '(' and ')' delimiters cannot be omitted.
.Pp
Example:
.D1 (1) + ((3/2)s{2} + (-1)s{-1} + 3)[l1][l2][f100][f1001][f101] + [l1][f101] + (3)[l2]
.Pp
.Sh OUTPUT
.Nm
prints the flow equation to stdout.
.Pp
The rccs in the flow equation are of the form '[% index]' and the constant term in the flow equation is denoted by '[C1]'. The factor '[/C1^power]' stands for (1/C1^power).
.Pp
.Sh KNOWN ISSUES
.Nm
only supports models in which all of the internal fields are Fermions.
.Pp
.Sh RETURN CODE
.Nm
returns 0 on success and -1 on error.
.Pp
.Sh SEE ALSO
.Sx numkondo Ns (1) ,
.Sx meantools Ns (1) ,
.Sx meantools-convert Ns (1) ,
.Sx kondo_preprocess Ns (1)
.Pp

137
man/meantools-convert.1 Normal file
View File

@ -0,0 +1,137 @@
.Dd $Mdocdate: June 12 2015 $
.Dt meantools-convert 1.2
.Os
.Sh NAME
.Nm meantools-convert
.Nd Translate flow equations to various formats
.Sh SYNOPSIS
.Nm
.Op Fl i Ar file
.Sy C
.Op Fl l Ar oldl_symbol
.Op Fl L Ar newl_symbol
.Op Fl C Ar constant_symbol
.Op Fl S
.Pp
.Nm
.Op Fl i Ar file
.Sy javascript
.Op Fl l Ar oldl_symbol
.Op Fl L Ar newl_symbol
.Op Fl C Ar constant_symbol
.Pp
.Nm
.Op Fl i Ar file
.Sy LaTeX
.Op Fl l Ar oldl_symbol
.Op Fl L Ar newl_symbol
.Op Fl C Ar constant_symbol
.Op Fl s
.Pp
.Sh DESCRIPTION
.Nm
is a python script to convert flow equations to C, javascript or LaTeX code.
.Pp
.Nm
is part of a set of tools to compute and manipulate Fermionic hierarchical flows:
.Bl -bullet
.It
.Sy meankondo
: computes flow equations for hierarchical Fermionic models
.It
.Sy numkondo
: numerical evaluation of flow equations.
.It
.Sy meantools, meantools-convert
: perform various operations on flow equations (derivation, exponentiation, evaluation and conversion to other formats).
.El
.Pp
as well as the following pre-processors, which generate configuration files for their associated model:
.Bl -bullet
.It
.Sy kondo_proprocess
: Kondo model
.El
.Pp
.Sh COMMAND-LINE ARGUMENTS
.Bl -tag -width Ds
.It Fl i Ar file
File containing the flow equation to convert. If this flag is not specified, then
.Nm
reads the equation from stdin.
.El
.Pp
.Sh C
.Nm
supports the following flags when converting to C code.
.Bl -tag -width Ds
.It Fl l Ar oldl_symbol
The symbol for the running coupling constants appearing on the right hand side (defaults to 'l').
.It Fl L Ar newl_symbol
The symbol for the running coupling constants appearing on the left hand side (defaults to 'newL').
.It Fl C Ar constant_symbol
The symbol for the constant factor (defaults to 'C'). Since there can be multiple constants in a flow equation, the actual symbols will be appended an integer (e.g. C1, C2, etc).
.It Fl S
Write each equation on a single line.
.El
.Pp
.Ar oldl_symbol
and
.Ar newl_symbol
must be arrays of floating point numbers (floats, doubles or long doubles) with enough memory allocated to them to hold all running coupling constants. Similarly,
.Ar constant_symbol Ns n
with n large enough must be allocated as floating point numbers.
.Pp
In addition, if the flow equation contains derivatives (see
.Sx meantools Ns (1) ) ,
then
.Pf d Ar oldl_symbol ,
.Pf d Ar newl_symbol
and
.Pf d Ar constant_symbol Ns n
must be allocated as well. The same holds for higher derivatives, with 'd' replaced by 'dd', 'ddd' and so forth.
.Sh JAVASCRIPT
.Qo
.Nm
.Sy javascript
.Qc
is a shorthand for
.Qo
.Nm
.Sy C
-S
.Qc
.Sh LATEX
.Nm
supports the following flags when converting to LaTeX code.
.Bl -tag -width Ds
.It Fl l Ar oldl_symbol
The symbol for the running coupling constants appearing on the right hand side (defaults to "\\ell").
.It Fl L Ar newl_symbol
The symbol for the running coupling constants appearing on the left hand side (defaults to "\\ell'").
.It Fl C Ar constant_symbol
The symbol for the constant factor (defaults to "C"). Since there can be multiple constants in a flow equation, the actual symbols will be appended an integer subscript (e.g. C_1, C_2, etc).
.It Fl s
Break the line at every '+'.
.El
.Pp
Since the length of the equations can change a lot from one system to another,
.Nm
does not make many formatting decisions (for instance
.Nm
does not insert any alignment characters, and either breaks the line at every '+' sign or at the end of the equation), which are left to the user.
.Pp
.Sh OUTPUT
.Nm
prints the converted flow equation to stdout.
.Pp
.Sh RETURN CODE
.Nm
returns 0 on success and -1 on error.
.Pp
.Sh SEE ALSO
.Sx meankondo Ns (1)
.Sx numkondo Ns (1) ,
.Sx meantools Ns (1) ,
.Sx kondo_preprocess Ns (1)
.Pp

164
man/meantools.1 Normal file
View File

@ -0,0 +1,164 @@
.Dd $Mdocdate: April 14 2015 $
.Dt meantools 1.2
.Os
.Sh NAME
.Nm meantools
.Nd A tool to manipulate flow equations
.Sh SYNOPSIS
.Nm
.Sy exp
.Op Ar config_file
.Pp
.Nm
.Sy derive
.Op Fl d Ar nderivs
.Op Fl V Ar variables
.Op Ar config_file
.Pp
.Nm
.Sy eval
.Op Fl R Ar values
.Op Ar config_file
.Pp
.Sh DESCRIPTION
.Nm
performs various operations on flow equations generated by
.Sy meankondo.
Namely, it can exponentiate, derive and evaluate flow equations.
.Pp
.Nm
is part of a set of tools to compute and manipulate Fermionic hierarchical flows:
.Bl -bullet
.It
.Sy meankondo
: computes flow equations for hierarchical Fermionic models
.It
.Sy numkondo
: numerical evaluation of flow equations.
.It
.Sy meantools, meantools-convert
: perform various operations on flow equations (derivation, exponentiation, evaluation and conversion to other formats).
.El
.Pp
as well as the following pre-processors, which generate configuration files for their associated model:
.Bl -bullet
.It
.Sy kondo_proprocess
: Kondo model
.El
.Pp
.Sh EXP
When run with the 'exp' command,
.Nm
computes the exponential of a flow equation. All the required parameters are set in the configuration file, which it either reads from the file provided on the command line, or from stdin.
.Pp
The syntax for the configuration file is the same as for
.Sx meankondo Ns (1) ,
and will not be belaboured here. The supported entries are
.Bl -tag -width Ds
.It Sy #!input_polynomial
The polynomial whose exponential is to be computed.
.Pp
.It Sy #!fields
The fields appearing in the polynomial
.Pp
.It Sy #!symbols
Symbolic variables (optional entry).
.Pp
.It Sy #!identities
identities between fields (optional entry).
.Pp
.It Sy #!id_table
The idtable used to compute a flow equation from the polynomial.
.El
.Pp
The resulting flow equation is written to stdout.
.Pp
.Sh DERIVE
When run with the 'derive' command,
.Nm
computes derivatives of a flow equation provided in the configuration file, which can either be passed as a command-line argument or through stdin.
.Pp
The derivatives are derivatives with respect to an extra virtual parameter, which all of the rccs are assumed to depend on (to override the default behavior, the '-V' flag can be used to pass a list of rccs that depend on the extra parameter, alternatively such a list can be given in the configuration file). The derivative of the flow equation is a new flow equation for the rccs and their derivatives with respect to the virtual parameter.
.Pp
When multiple derivatives are taken, the flow equation becomes a flow equation for the rccs, their derivatives, second derivatives, and so forth...
.Pp
This operation can be useful, for instance, to compute moments in an interacting system, in which the generating functional can be expressed as an effective potential depending on a parameter with respect to which the result of the integration should be derived. The 'derive' command writes the flow equation for the derived rccs, from which the quantities of interest can be computed.
.Pp
.Sy Command-line arguments:
.Bl -tag -width Ds
.It Fl d Ar nderivs
Number of derivatives (defaults to 1)
.It Fl V Ar variables
The variables that depend on the extra virtual parameter (defaults to all) (WARNING: if one of the variables has a negative index, do not put it first in the list, since
.Nm
would interpret the argument as being a flag, for example, write '-V "0,-1"' instead of '-V "-1,0"').
.Pp
Can either be a ',' separated list if indices or 'all' to derive with respect to all available variables.
.El
.Pp
.Sy Configuration file:
.Pp
The configuration file contains the flow equation to derive, and optionally a list of variables (similar to the '-V' flag). The following entries are supported:
.Bl -tag -width Ds
.It Sy #!flow_equation
The flow equation to derive.
.Pp
The syntax is identical to that in
.Sx numkondo Ns (1) .
.Pp
If this entry is the only one in the configuration file, the '#!flow_equation' header may be omitted.
.Pp
.It Sy #!variables
The variables that depend on the extra virtual parameter (optional entry).
.Pp
The variables entry is a ',' separated list of indices, or 'all' in which case, all of the variables on the right side of the flow equation are assumed to depend on the flow equation.
.Pp
If the '-V' flag is provided on the command-line, this entry is ignored.
.El
.Pp
The resulting flow equation is written to stdout.
.Pp
.Sh EVAL
When run with the 'eval' command,
.Nm
evaluates a flow equation, provided in a configuration file, numerically, using the values provided on the command-line or in the configuration file provided on the command-line or through stdin.
.Pp
.Sy Command-line arguments:
.Bl -tag -width Ds
.It Fl R Ar values
The values of the rccs with which to evaluate the flow equation.
.Ar values
is formatted like an initial_condition (see
.Sx numkondo Ns (1) ) .
.El
.Pp
.Sy Configuration file:
.Pp
The configuration file contains the flow equation to evaluate, and optionally a list of values for the rccs. The following entries are supported:
.Bl -tag -width Ds
.It Sy #!flow_equation
The flow equation to evaluate.
.Pp
The syntax is identical to that in
.Sx numkondo Ns (1) .
.Pp
If this entry is the only one in the configuration file, the '#!flow_equation' header may be omitted.
.Pp
.It Sy #!initial_condition
The value on which to evaluate the flow equation (optional entry).
.Pp
The syntax is identical to that in
.Sx numkondo Ns (1) .
.Pp
If the '-R' flag is provided on the command-line, this entry is ignored.
.El
.Pp
The result of the evaluation is written to stdout, and is formatted is such a way that it can be used as an initial condition for
.Pp
.Sh SEE ALSO
.Sx meankondo Ns (1) ,
.Sx numkondo Ns (1) ,
.Sx meantools-convert Ns (1) ,
.Sx kondo_preprocess Ns (1)
.Pp

157
man/numkondo.1 Normal file
View File

@ -0,0 +1,157 @@
.Dd $Mdocdate: April 14 2015 $
.Dt numkondo 1.2
.Os
.Sh NAME
.Nm numkondo
.Nd A tool to iterate a flow equation numerically.
.Sh SYNOPSIS
.Nm
.Op Fl F
.Op Fl N Ar niter
.Op Fl D Ar tolerance
.Op Fl I Ar initial_condition
.Op Ar config_file
.Pp
.Nm
.Fl v
.Sh DESCRIPTION
.Nm
computes the numerical value of the iterates of a flow equation provided in its configuration file, starting from an initial condition provided in its configuration file.
.Nm
is part of a set of tools to compute and manipulate Fermionic hierarchical flows:
.Bl -bullet
.It
.Sy meankondo
: computes flow equations for hierarchical Fermionic models
.It
.Sy numkondo
: numerical evaluation of flow equations.
.It
.Sy meantools, meantools-convert
: perform various operations on flow equations (derivation, exponentiation, evaluation and conversion to other formats).
.El
.Pp
as well as the following pre-processors, which generate configuration files for their associated model:
.Bl -bullet
.It
.Sy kondo_proprocess
: Kondo model
.El
.Pp
.Sh COMMAND-LINE ARGUMENTS
.Bl -tag -width Ds
.It Fl N Ar niter
Number of iterations
.It Fl F
Only print the last step of the computation, with full precision. The output can be used as an initial condition for further iterations.
.It Fl D Ar tolerance
If this option is provided, any number smaller than
.Ar tolerance
is set to 0.
.It Fl I Ar initial_condition
Set the initial condition from the command-line (overrides the initial condition in the configuration file). The format is the same as the '#!initial_configuration' entry, see below.
.It Fl v
Print version information and exit.
.El
.Pp
.Sh CONFIGURATION FILE
.Nm
reads a configuration file, that can either be passed as a command line argument or to stdin, which specifies the flow equation to iterate, the initial condition, and text labels for each running coupling constant.
.Pp
A configuration file is a list of entries, separated by a '&' character, each of which has a title (or header), which is preceded by '#!'. Note that '#!' must be at the beginning of a line in order to be read correctly.
.Pp
Whenever the '#' character is encountered, the rest of the line is treated as a comment and ignored (unless it is followed by '!').
.Pp
As a general rule, spaces and line breaks in the entries of the configuration file are ignored, so they may be used at the user's discretion. The few entries that require that no extra line breaks be inserted are explicitly mentioned below.
.Pp
.Nm
recognizes the following entries (unless explicitly mentioned, the entries below are mandatory) (entries may be provided in any order) (any extra entries in the configuration file are ignored):
.Bl -tag -width Ds
.It Sy #!flow_equation
The flow equation to be iterated.
.Pp
The flow equation has the same format as the output of
.Sy meankondo.
That is, a flow equation is a ',' separated list whose elements are of the form
.D1 [% index] = equation
where index is a non-negative integer or
.D1 [C index] = equation
where index is is a positive integer; and equation is formatted as explained below. [% index] stands for the running coupling constant corresponding to index, and [C index] is a special type of running coupling constant, which correspond to terms in the effective potential that do not depend on the fields. The difference between [% ...] and [C ...] is that the latter are evaluated first, and may be used in the equation of [% ...].
.Pp
Equations are '+' separated lists whose elements are monomials. Each monomial is a sequence of numbers, rccs and denominators:
.Bl -bullet
.It
Numbers are enclosed between '(' and ')'. If there are several numbers in a monomial, then they are multiplied.
.It
rccs are non-negative indices enclosed between '[%' and ']'.
.It
Denominators are of the form [/C index^power] and correspond to 1/C_index^power. Note that the denominators [C index] are computed before they are divided, and therefore, the equation corresponding to [C index] may not contain any [/C index^power].
.El
.Pp
If the numerical factor of a monomial is 1, then it can be dropped. However, even if the numerical factor is a single integer, its '(' and ')' delimiters cannot be omitted.
.Pp
In addition, in order to deal with derivatives of flow equations, extra running coupling constants can be introduced by adding any number of 'd' before '%' and 'C'. For instance, a flow equation may contain
.D1 [dd% index] = ...
or
.D1 [dC index] = ...
and an equation may contain an rcc of the form
.D1 [d% index]
.Pp
In practice, [C index] is represented as [%-index], and derivatives offset an index by 1000000, so [d% index] is equivalent to [%1000000+index], [dC index] to [%-1000000-index], [dd% index] to [%2000000+index], and so forth... Indices must therefore be smaller than 1000000 if 'd' is used.
.Pp
Example:
.D1 [C1] = [%1] + (1/2)[%1][%2] ,
.D1 [%1] = [%1][/C1^1] + [%1][%1][%2][/C1^2] ,
.D1 [%2] = [%2][/C1^1]
and with a derivative:
.D1 [C1] = [%1] + (1/2)[%1][%2] ,
.D1 [%1] = [%1][/C1^1] + [%1][%1][%2][/C1^2] ,
.D1 [%2] = [%2][/C1^1] ,
.D1 [dC1] = [d%1] + (1/2)[d%1][%2] + (1/2)[%1][d%2],
.D1 [d%1] = [d%1][/C1^1] + (-1)[%1][dC1][/C1^2] + (2)[%1][d%1][%2][/C1^2] + [%1][%1][d%2][/C1^2] + (-2) [%1][%1][%2][dC1][C1^3],
.D1 [d%2] = [d%2][/C1^1] + (-1)[%2][dC1][/C1^2]
.Pp
.It Sy #!initial_condition
The initial condition for the iteration.
.Pp
The initial_condition entry is a ',' separated list whose elements are of the form
.D1 index:value
where index is that of the corresponding rcc and value is a double precision float. The index may contain 'C' and 'd' characters as in the '#!flow_equation' entry.
.Pp
Example:
.D1 1:1.0 , 2:2.3e-6 , d1:2.0
.Pp
Note that if
.Nm
is called with the '-F' flag, the corresponding output is formatted in such a way that it can be used as an initial condition for other iterations.
.Pp
.It Sy #!labels
Labels for the running coupling constants, used as headers to display the flow of the iteration.
.Pp
The labels entry is a ',' separated list whose elements are of the form
.D1 index:"label"
where index is the non-negative index of the corresponding rcc, and label is a string.
.Pp
Example:
.D1 1:"one" , 2:"two"
.El
.Pp
.Sh OUTPUT
Unless the '-F' flag is provided,
.Nm
prints the result of the iteration at each step to stdout.
.Pp
If the '-F' flag is provided,
.Nm
prints the last step of the iteration to stdout in a format that can be re-used as an initial condition for subsequent iterations.
.Pp
.Sh RETURN CODE
.Nm
returns 0 on success and -1 on error.
.Pp
.Sh SEE ALSO
.Sx meankondo Ns (1) ,
.Sx meantools Ns (1) ,
.Sx meantools-convert Ns (1) ,
.Sx kondo_preprocess Ns (1)
.Pp

View File

@ -0,0 +1,91 @@
## 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.
################################################################################################
## ##
## Functions used to manipulate configuration files ##
## ##
################################################################################################
# remove unwanted entries in configuration files (read fromm stdin)
function strip_config {
tostrip="$1"
# whether to skip the entry
skip=0
# whether this is the first entry
first_entry=1
# read file
while read aline; do
# if line is a header
if [[ "$aline" =~ ^#! ]]; then
# check whether to strip
for header in $tostrip; do
if [[ "$aline" = "$header" ]]; then
skip=1
break
fi
done
# add a '&' separator
if [[ "$skip" = 0 && "$first_entry" = 0 ]]; then
echo "&"
fi
[[ "$skip" = 0 ]] && first_entry=0
fi
# change entry
if [[ "$aline" = "&" ]]; then
skip=0
# write out if not instructed to skip
elif [[ $skip = 0 ]]; then
echo "$aline"
fi
done
}
# find a config entry in a file (read from stdin)
function find_config_entry {
header="$1"
# whether the entry was found
foundit=0
# read stdin
while read aline; do
# write out if the header was found
if [[ $foundit = 1 ]]; then
if [[ "$aline" != "&" ]]; then
echo "$aline"
fi
fi
# check the header
if [[ "$aline" = "$header" ]]; then
foundit=1
fi
# new entry
if [[ "$aline" = "&" ]]; then
if [[ "$foundit" = 1 ]]; then
break
fi
fi
done
}

261
scripts/meantools-convert Executable file
View File

@ -0,0 +1,261 @@
#!/usr/bin/env python
## 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.
##########################################################################
## ##
## convert flow equations to various formats ##
## ##
##########################################################################
import sys
import re
def print_usage():
print("\nusage:",file=sys.stderr)
print(" export_flow_equation [-i infile] <format> [options]",file=sys.stderr)
print("\nwhere <format> [options] is one of",file=sys.stderr)
print(" C [-l oldl_symbol] [-L newl_symbol] [-C Constant_symbol] [-S]",file=sys.stderr)
print(" javascript [-l oldl_symbol] [-L newl_symbol] [-C Constant_symbol]",file=sys.stderr)
print(" LaTeX [-l oldl_symbol] [-L newl_symbol] [-C Constant_symbol] [-s]",file=sys.stderr)
print("",file=sys.stderr)
# to C
def C_engine(argv,text):
argc=len(argv)
i=1
# defaults
lsym="l"
Lsym="newL"
Csym="C"
oneline=0
while (i<argc):
# arguments requiring a variable
if (argv[i] in ["-l","-L","-C"]):
if(i>=argc-1):
print("error: '"+argv[i]+"' must be followed by a string",file=sys.stderr)
exit(-1)
# symbol for l
if (argv[i]=="-l"):
lsym=argv[i+1]
i=i+2
# symbol for new l
elif (argv[i]=="-L"):
Lsym=argv[i+1]
i=i+2
# symbol for C
elif (argv[i]=="-C"):
Csym=argv[i+1]
i=i+2
# write each equation on a single line
elif (argv[i]=="-S"):
oneline=1
i=i+1
return(convert_C(text,lsym,Lsym,Csym,oneline))
# to LaTeX
def latex_engine(argv,text):
argc=len(argv)
i=1
# defaults
lsym="\\ell"
Lsym="\\ell'"
Csym="C"
oneline=1
while (i<argc):
# arguments requiring a variable
if (argv[i] in ["-l","-L","-C"]):
if(i>=argc-1):
print("error: '"+argv[i]+"' must be followed by a string",file=sys.stderr)
exit(-1)
# symbol for l
if (argv[i]=="-l"):
lsym=argv[i+1]
i=i+2
# symbol for new l
elif (argv[i]=="-L"):
Lsym=argv[i+1]
i=i+2
# symbol for C
elif (argv[i]=="-C"):
Csym=argv[i+1]
i=i+2
# break lines in equation
elif (argv[i]=="-s"):
oneline=0
i=i+1
return(convert_latex(text,lsym,Lsym,Csym,oneline,columns))
# convert to C format
def convert_C(text, lsym, Lsym, Csym, oneline):
# make sure quotients are floats
text=re.sub(r'([0-9])/',r'\1./',text)
# remove newlines
if (oneline==0):
text=text.replace('\n','\\\n')
# end of lines
text=text.replace(',\\',';')
else:
text=text.replace('\n','')
# end of lines
text=text.replace(',',';\n')
# remove extra space
text=re.sub(r' {2,}',' ',text)
# replace left hand side variables
text=re.sub(r'\[(d*)C *([0-9]*)\] =',r'\1'+Csym+r'\2 =', text)
text=re.sub(r'\[(d*)% *([0-9]*)\] =',r'\1'+Lsym+r'[\2] =', text)
# replace right hand side variables
text=re.sub(r'\[(d*)% *([0-9]*)\]',r'*\1'+lsym+r'[\2]',text)
text=re.sub(r'\[(d*)C *([0-9]*)\]',r'*\1'+Csym+r'[\2]',text)
# replace constants in right hand side (and expand powers as products)
match=re.search(r'\[/C([0-9]*)\^([0-9]*)\]',text)
while(match):
power=int(match.group(2))
# product of constants
prod=''
for i in range(power):
prod=prod+'/'+Csym+match.group(1)
text=text.replace('[/C'+match.group(1)+'^'+match.group(2)+']',prod)
match=re.search(r'\[/C([0-9]*)\^([0-9]*)\]',text)
# replace square roots
text=re.sub(r's\{([0-9]*)\}',r'sqrt(\1)',text)
text=text.replace(')sqrt',')*sqrt')
# re-number variables in a sequential fashion
variables=[]
for match in re.finditer(r'\[([0-9]*)\]',text):
index=int(match.group(1))
if index not in variables:
variables.append(index)
variables.sort()
for index in range(len(variables)):
text=text.replace('['+str(variables[index])+']','[new'+str(index)+']')
text=text.replace('[new','[')
return(text+';')
# convert to LaTeX format
def convert_latex(text, lsym, Lsym, Csym, oneline, columns):
# remove newlines
if (oneline==0):
text=text.replace('\n','\\\\\n')
else:
# end of lines
text=text.replace(',',',\\\\')
# remove extra space
text=re.sub(r' {2,}',' ',text)
# replace left hand side variables
text=re.sub(r'\[(d*)C *([0-9]*)\] =',r'@\1'+Csym+r'_{\2} =', text)
text=re.sub(r'\[(d*)% *([0-9]*)\] =',r'@\1'+Lsym+r'_{\2} =', text)
# replace right hand side variables
text=re.sub(r'\[(d*)% *([0-9]*)\]',r'@\1'+lsym+r'_{\2}',text)
text=re.sub(r'\[(d*)C *([0-9]*)\]',r'@\1'+Csym+r'_{\2}',text)
# rewrite derivatives
# find the highest order of derivatives
i=0
dstr="d"
index=0
while (index>=0):
index=text.find(r'@'+dstr,index)
i=i+1
dstr=dstr+"d"
#replace derivatives
for j in range(i):
# number of derivs
nrd=i-1-j
dstr=""
for k in range(nrd):
dstr=dstr+"d"
if (nrd>1):
text=text.replace(r'@'+dstr,"\\partial^{"+str(nrd)+"}")
elif (nrd==1):
text=text.replace(r'@'+dstr,"\\partial ")
else:
text=text.replace(r'@'+dstr,"")
# replace constants in right hand side
text=re.sub(r'\[/C([0-9]*)\^([0-9]*)\]',r'\\frac1{'+Csym+r'_{\1}^{\2}}',text)
# remove "^{1}"
text=text.replace("^{1}","")
# replace square roots
text=text.replace('s{','\\sqrt{')
# fractions
text=re.sub(r'\((-?)([0-9]*)/([0-9]*)\)',r'\1\\frac{\2}{\3}',text)
# numbers
text=re.sub(r'\(([-0-9]*)\)',r'\1',text)
return(text)
# read arguments
argc=len(sys.argv)
if (argc<=1):
print_usage()
exit(-1)
i=1
infile=""
while i<argc:
if (sys.argv[i]=="-i"):
if(i<argc-1):
infile=sys.argv[i+1]
i=i+2
else:
print("error: '"+sys.argv[i]+"' must be followed by a filename",file=sys.stderr)
exit(-1)
else:
# read input
if (infile==""):
# read input from stdin
text=sys.stdin.read()
else:
f=open(infile,'r')
text=f.read()
f.close()
if (sys.argv[i]=="C"):
print(C_engine(sys.argv[i:],text))
elif (sys.argv[i]=="javascript"):
# reuse C engine but ensure that the single line option is used
print(C_engine(sys.argv[i:]+["-S"],text))
elif (sys.argv[i]=="LaTeX"):
print(latex_engine(sys.argv[i:],text))
else:
print("error: '"+sys.argv[i]+"' is not supported",file=sys.stderr)
exit(-1)
break

628
src/array.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

76
src/kondo.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

131
src/polynomial.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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