ENDIF()
-IF(FEATURE_FUNCTIONPARSER_BUNDLED_CONFIGURED)
- ADD_SUBDIRECTORY(${FUNCTIONPARSER_FOLDER})
-ENDIF()
-
-
IF(FEATURE_THREADS_BUNDLED_CONFIGURED)
INSTALL(DIRECTORY ${TBB_FOLDER}/include/tbb
DESTINATION ${DEAL_II_INCLUDE_RELDIR}/deal.II/bundled
ENDIF()
+IF(FEATURE_MUPARSER_BUNDLED_CONFIGURED)
+ ADD_SUBDIRECTORY(${MUPARSER_FOLDER})
+ENDIF()
+
+
+
MESSAGE(STATUS "Setting up bundled features - Done")
A full version of the library can be downloaded at http://www.boost.org/.
-./functionparser (FunctionParser 4.5)
+./muparser_v2_2_3
==============
-Contains the FunctionParser project which is copyrighted by Juha Nieminen
-and licensed under the GNU Lesser General Public License (LGPL) Version 3.
-See functionparser/README, functionparser/lgpl-3.0.txt or
-http://warp.povusers.org/FunctionParser/
+Contains the MuParser project licensed under the MIT license.
A full version of the FunctionParser project can be downloaded at
-http://warp.povusers.org/FunctionParser/.
-
+http://muparser.beltoforion.de/.
./tbb30_104oss
==============
+++ /dev/null
-This directory contains the functionparser project which is copyrighted
-by Juha Nieminen and licensed under the GNU Lesser General Public License
-(LGPL) Version 3. See ./docs/fparser.html or
-http://warp.povusers.org/FunctionParser/.
-
-A full version of the functionparser project can be downloaded at
-http://warp.povusers.org/FunctionParser/.
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <link href="style.css" rel="stylesheet" type="text/css" title="normal" media=screen>
- <title>Function Parser for C++ v4.5.1 : Documentation</title>
-</head>
-
-<body>
-<h1>Function Parser for C++ v4.5.1 </h1>
-
-<p>Authors: Juha Nieminen
-(<a href="http://iki.fi/warp/">http://iki.fi/warp/</a>),
-Joel Yliluoma
-(<a href="http://iki.fi/bisqwit/">http://iki.fi/bisqwit/</a>).
-
-<p>The usage license of this library is located at the end of this file.
-
-<h2>Table of contents:</h2>
-
-<ul>
- <li><a href="#whatsnew">What's new</a>
- <li><a href="#preface">Preface</a>
- <li><a href="#usage">Usage</a>
- <ul>
- <li><a href="#parsertypes">Parser types</a>
- <li><a href="#configuring">Configuring the compilation</a>
- <li><a href="#copyassignment">Copying and assignment</a>
- <li><a href="#shortdesc">Short descriptions of FunctionParser methods</a>
- <li><a href="#longdesc">Long descriptions of FunctionParser methods</a>
- <ul>
- <li><a href="#longdesc_Parse"><code>Parse()</code></a>
- <li><a href="#longdesc_setDelimiterChar"><code>setDelimiterChar()</code></a>
- <li><a href="#longdesc_ErrorMsg"><code>ErrorMsg()</code></a>
- <li><a href="#longdesc_GetParseErrorType"><code>GetParseErrorType()</code></a>
- <li><a href="#longdesc_Eval"><code>Eval()</code></a>
- <li><a href="#longdesc_EvalError"><code>EvalError()</code></a>
- <li><a href="#longdesc_Optimize"><code>Optimize()</code></a>
- <li><a href="#longdesc_AddConstant"><code>AddConstant()</code></a>
- <li><a href="#longdesc_AddUnit"><code>AddUnit()</code></a>
- <li><a href="#longdesc_AddFunction1"><code>AddFunction()</code></a> (C++ function)
- <li><a href="#longdesc_AddFunction2"><code>AddFunction()</code></a> (FunctionParser)
- <li><a href="#longdesc_AddFunction3"><code>AddFunctionWrapper()</code></a>
- <li><a href="#longdesc_RemoveIdentifier"><code>RemoveIdentifier()</code></a>
- <li><a href="#longdesc_ParseAndDeduceVariables"><code>ParseAndDeduceVariables()</code></a>
- </ul>
- <li><a href="#functionobjects">Specialized function objects</a>
- <li><a href="#base">FunctionParserBase</a>
- </ul>
- <li>Syntax
- <ul>
- <li><a href="#literals">Numeric literals</a>
- <li><a href="#identifiers">Identifier names</a>
- <li><a href="#functionsyntax">The function string syntax</a>
- <li><a href="#inlinevars">Inline variables</a>
- <li><a href="#whitespace">Whitespace</a>
- </ul>
- <li>Miscellaneous
- <ul>
- <li><a href="#fpaccuracy">About floating point accuracy</a>
- <li><a href="#evaluationchecks">About evaluation-time checks</a>
- <li><a href="#threadsafety">About thread safety</a>
- <li><a href="#tipsandtricks">Tips and tricks</a>
- <li><a href="#contact">Contacting the author</a>
- </ul>
-<!-- <li><a href="#algorithm">The algorithm used in the library</a> -->
- <li><a href="#license">Usage license</a>
-</ul>
-
-<a name="whatsnew"></a>
-<h2>What's new</h2>
-
-<p>What's new in v4.5.1
- <ul>
- <li>Reverted the automatic C++11 detection to a precompiler macro setting
- (<code>FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS</code>) because not all
- compilers yet fully support the C++11 math functions.
- <li>Fixed a potential duplicate symbol problem that happens with explicit
- template instantiations.
- </ul>
-
-<p>What's new in v4.5
- <ul>
- <li>Removed support for the <code>"eval()"</code> function from the
- supported syntax. (This function was too dangerous, too difficult to
- maintain internally, not very useful, and more or less a gimmick in
- the first place.)
- <li>Removed several of the conditional compiling macro definitions, namely
- <code>FP_SUPPORT_TR1_MATH</code>, <code>FP_ENABLE_EVAL</code>,
- <code>FP_EVAL_MAX_REC_LEVEL</code>, <code>FP_NO_EVALUATION_CHECKS</code>
- and <code>FP_EPSILON</code>.
- <li>The epsilon value used in comparisons is now set with a member function
- of FunctionParser (which allows setting different values for different
- versions of the parser).
- <li>The math functions previously turned on with
- <code>FP_SUPPORT_TR1_MATH</code> are now automatically used if
- <code>__cplusplus</code> indicates that C++11 is in use.
- <li>Fixed some compilation problems with clang++.
- </ul>
-
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="preface"></a>
-<h2>Preface</h2>
-
-<p>This C++ library offers a class which can be used to parse and evaluate a
-mathematical function from a string (which might be eg. requested from the
-user). The syntax of the function string is similar to mathematical expressions
-written in C/C++ (the exact syntax is specified later in this document).
-The function can then be evaluated with different values of variables.
-
-<p>For example, a function like "<code>sin(sqrt(x*x+y*y))</code>" can be
-parsed from a string (either <code>std::string</code> or a C-style string)
-and then evaluated with different values of <code>x</code> and <code>y</code>.
-This library can be useful for evaluating user-inputted functions, or in
-some cases interpreting mathematical expressions in a scripting language.
-
-<p>This library aims for maximum speed in both parsing and evaluation, while
-keeping maximum portability. The library should compile and work with any
-standard-conforming C++ compiler.
-
-<p>Different numerical types are supported: <code>double</code>,
- <code>float</code>, <code>long double</code>, <code>long int</code>,
- <code>std::complex</code> (of types <code>double</code>,
- <code>float</code> and <code>long double</code>),
- multiple-precision floating point numbers using the MPFR library, and
- arbitrary precision integers using the GMP library. (Note that it's
- not necessary for these two libraries to exist in the system in order
- to use the Function Parser library with the other numerical types. Support
- for these libraries is optionally compiled in using preprocessor settings.)
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="usage"></a>
-<h2>Usage</h2>
-
-<p>To use the <code>FunctionParser</code> class, you have to include
-<code>"fparser.hh"</code> in your source code files which use the
-<code>FunctionParser</code> class.
-
-<p>If you are going to use the MPFR version of the library, you need to
-include <code>"fparser_mpfr.hh"</code>. If you are going to use the GMP
-version of the library, you need to include <code>"fparser_gmpint.hh"</code>.
-(Note that support for these special parser versions needs to be specified
-with preprocessor macros. See the <a href="#parsertypes">documentation
-below</a> for details.)
-
-<p>When compiling, you have to compile <code>fparser.cc</code> and
-<code>fpoptimizer.cc</code> and link them to the main program. In many
-developement environments it's enough to add those two files to your
-current project (usually header files don't have to be added to the
-project for the compilation to work).
-
-<p>If you are going to use the MPFR or the GMP versions of the library,
-you also need to add <code>mpfr/MpfrFloat.cc</code> or
-<code>mpfr/GmpInt.cc</code> files to your project, respectively. Otherwise
-they should not be added to the project.
-
-<p>Note that part of the library source code is inside several
-<code>.inc</code> files inside the <code>extrasrc</code> subdirectory
-(these files contain auto-generated C++ code), provided in the library
-package. These files are used by <code>fparser.cc</code> and don't need
-to be added explicitly to the project in most IDEs (such as Visual Studio).
-Basically, you don't need to do anything with these files, other than keep
-them in the <code>extrasrc</code> subdirectory.
-
-<p>Simple usage example of the library:
-
-<pre>
- FunctionParser fp;
- fp.Parse("sqrt(x*x + y*y)", "x,y");
- double variables[2] = { 1.5, 2.9 };
- double result = fp.Eval(variables);
-</pre>
-
-<!-- -------------------------------------------------------------------- -->
-<a name="parsertypes"></a>
-<h3>Parser types</h3>
-
-<p>Different versions of the function parser class are supported, using
- different floating point or integral types for function evaluation.
-
-<p>All the classes other than the default one, <code>FunctionParser</code>,
- need to be enabled at compile time by defining a preprocessor macro
- (specified below) either in the <code>fpconfig.hh</code> file or your
- compiler settings. (The reason for this is that every parser that is
- included in the compilation process will make the compilation slower
- and increase the size of the executable, so they are compiled only on
- demand. Also, the GMP and MPFR versions of the parser require for those
- libraries to be available, which is often not the case.)
-
-<p>Note that if you try to use the other class types without enabling them
- with the correspondent preprocessor macro, you will get a linker error
- (rather than a compiler error) because those classes will not have been
- instantiated when the library was compiled.
-
-<p>Currently the <code>Optimize()</code> method works only for the
- <code>FunctionParser</code>, <code>FunctionParser_f</code> and
- <code>FunctionParser_ld</code> classes. For the other types it can be
- called but it does nothing.
-
-<p>
-<dl>
- <dt><p><code>FunctionParser</code></dt>
- <dd>
- <p>This is the default class, which uses <code>double</code> as its
- numerical type. This is the only class enabled by default.
- <p>If you use some other type than this one, and you don't want this
- version of the class compiled into the library, you can define the
- preprocessor macro <code>FP_DISABLE_DOUBLE_TYPE</code>.
- </dd>
-
- <dt><p><code>FunctionParser_f</code></dt>
- <dd>
- <p>This parser uses <code>float</code> as its numerical type.
- <p>The <code>FP_SUPPORT_FLOAT_TYPE</code> preprocessor macro needs to be
- defined for this class to be enabled.
- </dd>
-
- <dt><p><code>FunctionParser_ld</code></dt>
- <dd>
- <p>This parser uses <code>long double</code> as its numerical type.
- <p>The <code>FP_SUPPORT_LONG_DOUBLE_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that the <code>FP_USE_STRTOLD</code> preprocessor macro should
- also be defined when using this version of the parser if the compiler
- supports the (C99) function <code>strtold()</code>. (See
- <a href="#configuring">documentation</a> below.)
- </dd>
-
- <dt><p><code>FunctionParser_li</code></dt>
- <dd>
- <p>This parser uses <code>long int</code> as its numerical type.
- <p>The <code>FP_SUPPORT_LONG_INT_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that this version of the class uses a reduced function syntax
- with support only for functions which are feasible to be used with
- integral types (namely <code>abs()</code>, <code>eval()</code>,
- <code>if()</code>, <code>min()</code> and <code>max()</code>, besides
- basic arithmetic operators, except for the power operator).
- </dd>
-
- <dt><p><code>FunctionParser_cd</code>, <code>FunctionParser_cf</code>,
- <code>FunctionParser_cld</code></dt>
- <dd>
- <p>These parsers use <code>std::complex<double></code>,
- <code>std::complex<float></code> and
- <code>std::complex<long double></code> as their numerical type,
- respectively.
- <p>The preprocessor macros to enable them are
- <code>FP_SUPPORT_COMPLEX_DOUBLE_TYPE</code>,
- <code>FP_SUPPORT_COMPLEX_FLOAT_TYPE</code> and
- <code>FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE</code>.
- <p>If <code>FunctionParser_cld</code> is used, the
- <code>FP_USE_STRTOLD</code> macro should also be defined if the compiler
- supports the <code>strtold()</code> function.
- </dd>
-
- <dt><p><code>FunctionParser_mpfr</code></dt>
- <dd>
- <p>This parser uses <code>MpfrFloat</code> as its numerical type.
- <p>The <code>FP_SUPPORT_MPFR_FLOAT_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that to use this version of the parser,
- <code>"fparser_mpfr.hh"</code> needs to be included.
- <p><code>MpfrFloat</code> is an auxiliary class which uses the MPFR
- library for multiple-precision floating point numbers. The class
- behaves largely like a floating point type, and is declared in the
- <code>mpfr/MpfrFloat.hh</code> file (see that file for info about
- the public interface of the class).
- <p>If this class is enabled, <code>mpfr/MpfrFloat.cc</code>
- needs to be compiled into the project, as well as the GMP and MPFR
- libraries. (With the gcc compiler this means using the linker options
- "<code>-lgmp -lmpfr</code>".)
- </dd>
-
- <dt><p><code>FunctionParser_gmpint</code></dt>
- <dd>
- <p>This parser uses <code>GmpInt</code> as its numerical type.
- <p>The <code>FP_SUPPORT_GMP_INT_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that to use this version of the parser,
- <code>"fparser_gmpint.hh"</code> needs to be included.
- <p><code>GmpInt</code> is an auxiliary class which uses the GMP
- library for arbitrary-precision integer numbers. The class
- behaves largely like an integer type, and is declared in the
- <code>mpfr/GmpInt.hh</code> file (see that file for info about
- the public interface of the class).
- <p>If this class is enabled, <code>mpfr/GmpInt.cc</code>
- needs to be compiled into the project, as well as the GMP library.
- <p>This version of the class also uses a reduced version of the syntax,
- like the <code>long int</code> version.
- <p><b>Note:</b> Since there's no upper limit to the size of GMP
- integers, this version of the class should be used with care in
- situations where malicious users might be able to exploit it to
- make the program run out of memory. An example of this would be
- a server-side application usable through the WWW.
- </dd>
-</dl>
-
-<p>Note that these different classes are completely independent and
- instances of different classes cannot be given to each other using the
- <code>AddFunction()</code> method. Only objects of the same type can
- be given to that method.
-
-<p>The rest of the documentation assumes that <code>FunctionParser</code>
- (which uses the <code>double</code> type) is used. The usage of the other
- classes is identical except that <code>double</code> is replaced with the
- correspondent type used by that class. (In other words, whenever the
- rest of this documentation uses the type keyword '<code>double</code>',
- the correspondent type should be used instead, when using another version
- of the class.)
-
-<!-- -------------------------------------------------------------------- -->
-<a name="configuring"></a>
-<h3>Configuring the compilation</h3>
-
-<p>There is a set of precompiler options in the <code>fpconfig.hh</code> file
-which can be used for setting certain features on or off. All of these options
-can also be specified from the outside, using precompiler settings (eg. the
-<code>-D</code> option in gcc), and thus it's not necessary to modify this
-file.
-
-<dl>
- <dt><p><code>FP_USE_STRTOLD</code> : (Default off)</dt>
- <dd><p>If <code>FunctionParser_ld</code> or <code>FunctionParser_cld</code>
- are used, this preprocessor macro should be defined if the compiler
- supports the (C99) function <code>strtold()</code>. If not, then numeric
- literals will be parsed with double precision only, which in most
- systems is less accurate than long double precision, which will cause
- small rounding errors. (This setting has no effect on the other parser
- types.) Note that <code>strtold()</code> will also be automatically used
- if <code>__cplusplus</code> indicates that C++11 is in use.
- </dd>
-
- <dt><p><code>FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS</code> : (Default off)</dt>
- <dd><p>Use C++11 math functions where applicable. (These are ostensibly
- faster than the equivalent formulas using C++98 math functions.) Note
- that not all compilers support these functions (even if they otherwise
- support C++11.)
-
- <dt><p><code>FP_SUPPORT_OPTIMIZER</code> : (Default on)</dt>
- <dd><p>If you are not going to use the <code>Optimize()</code> method, you
- can comment this line out to speed-up the compilation a bit, as
- well as making the binary a bit smaller. (<code>Optimize()</code> can
- still be called, but it will not do anything.)
-
- <p>You can also disable the optimizer by specifying the
- <code>FP_NO_SUPPORT_OPTIMIZER</code> precompiler constant in your
- compiler settings.
- </dd>
-
- <dt><p><code>FP_USE_THREAD_SAFE_EVAL</code> : (Default off)</dt>
- <dd><p>Define this precompiler constant to make <code>Eval()</code>
- thread-safe. Refer to the <a href="#threadsafety">thread safety
- section</a> later in this document for more information.
- Note that defining this may make <code>Eval()</code> slightly slower.
- <p>Also note that the MPFR and GMP versions of the library cannot be
- made thread-safe, and thus this setting has no effect on them.
- </dd>
-
- <dt><p><code>FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA</code> : (Default off)</dt>
- <dd><p>This is like the previous, but makes <code>Eval()</code> use the
- <code>alloca()</code> function (instead of <code>std::vector</code>).
- This will make it faster, but the <code>alloca()</code>
- function is not standard and thus not supported by all compilers.
- </dd>
-</dl>
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="copyassignment"></a>
-<h3>Copying and assignment</h3>
-
-<p>The class implements a safe copy constructor and assignment operator.
-
-<p>It uses the copy-on-write technique for efficiency. This means that
- when copying or assigning a FunctionParser instance, the internal data
- (which in some cases can be quite lengthy) is not immediately copied
- but only when the contents of the copy (or the original) are changed.
-
-<p>This means that copying/assigning is a very fast operation, and if
- the copies are never modified then actual data copying never happens
- either.
-
-<p>The <code>Eval()</code> and <code>EvalError()</code> methods of the
-copy can be called without the internal data being copied.
-
-<p>Calling <code>Parse()</code>, <code>Optimize()</code> or the user-defined
-constant/function adding methods will cause a deep-copy.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="shortdesc"></a>
-<h3>Short descriptions of FunctionParser methods</h3>
-
-<pre>
-int Parse(const std::string& Function, const std::string& Vars,
- bool useDegrees = false);
-
-int Parse(const char* Function, const std::string& Vars,
- bool useDegrees = false);
-</pre>
-
-<p>Parses the given function and compiles it to internal format.
- Return value is -1 if successful, else the index value to the location
- of the error.
-
-<hr>
-<pre>
-void setDelimiterChar(char);
-</pre>
-
-<p>Sets an ending delimiter character for the function string. (See the
- long description for more details.)
-
-<hr>
-<pre>
-static double epsilon();
-static void setEpsilon(double);
-</pre>
-
-<p>Setter and getter for the epsilon value used with comparison operators.
-
-<hr>
-<pre>
-const char* ErrorMsg(void) const;
-</pre>
-
-<p>Returns an error message corresponding to the error in
-<code>Parse()</code>, or an empty string if no such error occurred.
-
-<hr>
-<pre>
-ParseErrorType GetParseErrorType() const;
-</pre>
-
-<p>Returns the type of parsing error which occurred. Possible return types
- are described in the long description.
-
-<hr>
-<pre>
-double Eval(const double* Vars);
-</pre>
-
-<p>Evaluates the function given to <code>Parse()</code>.
-
-<hr>
-<pre>
-int EvalError(void) const;
-</pre>
-
-<p>Returns <code>0</code> if no error happened in the previous call to
-<code>Eval()</code>, else an error code <code>>0</code>.
-
-<hr>
-<pre>
-void Optimize();
-</pre>
-
-<p>Tries to optimize the bytecode for faster evaluation.
-
-<hr>
-<pre>
-bool AddConstant(const std::string& name, double value);
-</pre>
-
-<p>Add a constant to the parser. Returns <code>false</code> if the name of
-the constant is invalid, else <code>true</code>.
-
-<hr>
-<pre>
-bool AddUnit(const std::string& name, double value);
-</pre>
-
-<p>Add a new unit to the parser. Returns <code>false</code> if the name of
-the unit is invalid, else <code>true</code>.
-
-<hr>
-<pre>
-bool AddFunction(const std::string& name,
- double (*functionPtr)(const double*),
- unsigned paramsAmount);
-</pre>
-
-<p>Add a user-defined function to the parser (as a function pointer).
-Returns <code>false</code> if the name of the function is invalid, else
-<code>true</code>.
-
-<hr>
-<pre>
-bool AddFunction(const std::string& name, FunctionParser&);
-</pre>
-
-<p>Add a user-defined function to the parser (as a <code>FunctionParser</code>
-instance). Returns <code>false</code> if the name of the function is invalid,
-else <code>true</code>.
-
-<hr>
-<pre>
-bool RemoveIdentifier(const std::string& name);
-</pre>
-
-<p>Removes the constant, unit or user-defined function with the specified
-name from the parser.
-
-<hr>
-<pre>
-int ParseAndDeduceVariables(const std::string& function,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees = false);
-</pre>
-
-<p>Like <code>Parse()</code>, but the variables in the function are deduced
-automatically. The amount of found variables and the variable names themselves
-are returned by the different versions of the function.
-
-<!-- -------------------------------------------------------------------- -->
-<a name="longdesc"></a>
-<h3>Long descriptions of FunctionParser methods</h3>
-
-<hr>
-<a name="longdesc_Parse"></a>
-<pre>
-int Parse(const std::string& Function, const std::string& Vars,
- bool useDegrees = false);
-
-int Parse(const char* Function, const std::string& Vars,
- bool useDegrees = false);
-</pre>
-
-<p>Parses the given function (and compiles it to internal format).
-Destroys previous function. Following calls to <code>Eval()</code> will evaluate
-the given function.
-
-<p>The strings given as parameters are not needed anymore after parsing.
-
-<p>Parameters:
-
-<table border=2>
- <tr>
- <td><code>Function</code></td>
- <td>String containing the function to parse.</td>
- </tr><tr>
- <td><code>Vars</code></td>
- <td>String containing the variable names, separated by commas.<br>
- Eg. <code>"x,y"</code>, <code>"VarX,VarY,VarZ,n"</code> or
- <code>"x1,x2,x3,x4,__VAR__"</code>.
- </tr><tr>
- <td><code>useDegrees</code></td>
- <td>(Optional.) Whether to use degrees or radians in
- trigonometric functions. (Default: radians)</td>
- </tr>
-</table>
-
-<p>If a <code>char*</code> is given as the <code>Function</code> parameter,
-it must be a null-terminated string.
-
-<p>Variables can have any size and they are case sensitive (ie.
-<code>"var"</code>, <code>"VAR"</code> and <code>"Var"</code> are
-<em>different</em> variable names). Letters, digits, underscores and
-UTF8-encoded characters can be used in variable names, but the name of
-a variable can't begin with a digit. Each variable name can appear only
-once in the '<code>Vars</code>' string. Function names are not legal
-variable names.
-
-<p>Using longer variable names causes no overhead whatsoever to the
-<code>Eval()</code> method, so it's completely safe to use variable names
-of any size.
-
-<p>The third, optional parameter specifies whether angles should be
- interpreted as radians or degrees in trigonometrical functions.
- If not specified, the default value is radians.
-
-<p>Return values:
-
-<ul>
- <li>On success the function returns <code>-1</code>.
- <li>On error the function returns an index to where the error was found
- (<code>0</code> is the first character, <code>1</code> the second, etc).
- If the error was not a parsing error returns an index to the end of the
- string.
-</ul>
-
-<p>Example: <code>parser.Parse("3*x+y", "x,y");</code>
-
-
-<hr>
-<a name="longdesc_setDelimiterChar"></a>
-<pre>
-void setDelimiterChar(char);
-</pre>
-
-<p>By default the parser expects the entire function string to be valid
-(ie. the entire contents of the given <code>std::string</code>, or a C string
-ending in the null character <code>'\0'</code>).
-
-<p>If a delimiter character is specified with this function, then if it's
-encountered at the outermost parsing level by the <code>Parse()</code>
-function, and the input function has been valid so far, <code>Parse()</code>
-will return an index to this character inside the input string, but rather
-than set an error code, <code>FP_NO_ERROR</code> will be set.
-
-<p>The idea is that this can be used to more easily parse functions which
-are embedded inside larger strings, containing surrounding data, without
-having to explicitly extract the function to a separate string.
-
-<p>For example, suppose you are writing an interpreter for a scripting
- language, which can have commands like this:
-
-<p><code>let MyFunction(x,y) = { sin(x*x+y*y) } // A 2-dimensional function</code>
-
-<p>Normally when parsing such a line you would have to extract the part
-inside the curly brackets into a separate string and parse it that way.
-With this feature what you can do instead is to set <code>'}'</code> as
-the delimiter character and then simply give a pointer to the character
-which comes after the <code>'{'</code>. If all goes well, the
-<code>Parse()</code> function will return an index to the <code>'}'</code>
-character (from the given starting point) and <code>GetParseErrorType()</code>
-will return <code>FP_NO_ERROR</code>. You can use the return
-value (if it's not <code>-1</code>) to jump forward in the string to the
-delimiter character.
-
-<p>Note that a null character (<code>'\0'</code>) or the end of the
-<code>std::string</code> (if one was given) will still be a valid end of
-the function string even if a delimiter character was specified. (In this
-case <code>Parse()</code> will return <code>-1</code> if there was no error,
-as usual.)
-
-<p>Also note that the delimiter character cannot be any valid operator
-or alphanumeric (including the underscore) character, nor the other
-characters defined in the function syntax. It must be a character not
-supported by the function parser (such as <code>'}'</code>,
-<code>'"'</code>, <code>']'</code>, etc).
-
-
-<hr>
-<a name="longdesc_Epsilon"></a>
-<pre>
-static double epsilon();
-static void setEpsilon(double);
-</pre>
-
-<p>Comparison operators (for the non-integral versions of the parser) use an
-epsilon value to account for floating point calculation rounding errors.
-This epsilon value can be set and read with these functions. (Note that the
-specified value will be used by all instances of FunctionParser.) If not
-specified, the default values are:
-
-<ul>
- <li>double: 1e-12
- <li>float: 1e-5
- <li>long double: 1e-14
- <li>MpfrFloat: The value of MpfrFloat::someEpsilon()
-</ul>
-
-
-<hr>
-<a name="longdesc_ErrorMsg"></a>
-<pre>
-const char* ErrorMsg(void) const;
-</pre>
-
-<p>Returns a pointer to an error message string corresponding to the error
-caused by <code>Parse()</code> (you can use this to print the proper error
-message to the user). If no such error has occurred, returns an empty string.
-
-
-<hr>
-<a name="longdesc_GetParseErrorType"></a>
-<pre>
-ParseErrorType GetParseErrorType() const;
-</pre>
-
-<p>Returns the type of parse error which occurred.
-
-<p>This method can be used to get the error type if <code>ErrorMsg()</code>
-is not enough for printing the error message. In other words, this can be
-used for printing customized error messages (eg. in another language).
-If the default error messages suffice, then this method doesn't need
-to be called.
-
-<code>FunctionParser::ParseErrorType</code> is an enumerated type inside
-the class (ie. its values are accessed like
-"<code>FunctionParser::SYNTAX_ERROR</code>").
-
-<p>The possible values for FunctionParser::ParseErrorType are listed below,
-along with their equivalent error message returned by the
-<code>ErrorMsg()</code> method:
-
-<p><table border=2>
-<tr>
- <td><code>FP_NO_ERROR</code></td>
- <td>If no error occurred in the previous call to <code>Parse()</code>.</td>
-</tr><tr>
- <td><code>SYNTAX_ERROR</code></td>
- <td>"Syntax error"</td>
-</tr><tr>
- <td><code>MISM_PARENTH</code></td>
- <td>"Mismatched parenthesis"</td>
-</tr><tr>
- <td><code>MISSING_PARENTH</code></td>
- <td>"Missing ')'"</td>
-</tr><tr>
- <td><code>EMPTY_PARENTH</code></td>
- <td>"Empty parentheses"</td>
-</tr><tr>
- <td><code>EXPECT_OPERATOR</code></td>
- <td>"Syntax error: Operator expected"</td>
-</tr><tr>
- <td><code>OUT_OF_MEMORY</code></td>
- <td>"Not enough memory"</td>
-</tr><tr>
- <td><code>UNEXPECTED_ERROR</code></td>
- <td>"An unexpected error occurred. Please make a full bug report to the
- author"</td>
-</tr><tr>
- <td><code>INVALID_VARS</code></td>
- <td>"Syntax error in parameter 'Vars' given to FunctionParser::Parse()"</td>
-</tr><tr>
- <td><code>ILL_PARAMS_AMOUNT</code></td>
- <td>"Illegal number of parameters to function"</td>
-</tr><tr>
- <td><code>PREMATURE_EOS</code></td>
- <td>"Syntax error: Premature end of string"</td>
-</tr><tr>
- <td><code>EXPECT_PARENTH_FUNC</code></td>
- <td>"Syntax error: Expecting ( after function"</td>
-</tr><tr>
- <td><code>UNKNOWN_IDENTIFIER</code></td>
- <td>"Syntax error: Unknown identifier"</td>
-</tr><tr>
- <td><code>NO_FUNCTION_PARSED_YET</code></td>
- <td>"(No function has been parsed yet)"</td>
-</tr>
-</table>
-
-
-<hr>
-<a name="longdesc_Eval"></a>
-<pre>
-double Eval(const double* Vars);
-</pre>
-
-<p>Evaluates the function given to <code>Parse()</code>.
-The array given as parameter must contain the same amount of values as
-the amount of variables given to <code>Parse()</code>. Each value corresponds
-to each variable, in the same order.
-
-<p>Return values:
-<ul>
- <li>On success returns the evaluated value of the function given to
- <code>Parse()</code>.
- <li>On error (such as division by 0) the return value is unspecified,
- probably 0.
-</ul>
-
-<p>Example:
-
-<p><code>double Vars[] = {1, -2.5};</code><br>
-<code>double result = parser.Eval(Vars);</code>
-
-
-<hr>
-<a name="longdesc_EvalError"></a>
-<pre>
-int EvalError(void) const;
-</pre>
-
-<p>Used to test if the call to <code>Eval()</code> succeeded.
-
-<p>Return values:
-
-<p>If there was no error in the previous call to <code>Eval()</code>,
-returns <code>0</code>, else returns a positive value as follows:
-<ul>
- <li>1: division by zero
- <li>2: sqrt error (sqrt of a negative value)
- <li>3: log error (logarithm of a negative value)
- <li>4: trigonometric error (asin or acos of illegal value)
- <li>5: maximum recursion level in <code>eval()</code> reached
-</ul>
-
-
-<hr>
-<a name="longdesc_Optimize"></a>
-<pre>
-void Optimize();
-</pre>
-
-<p>This method can be called after calling the <code>Parse()</code> method.
-It will try to simplify the internal bytecode so that it will evaluate faster
-(it tries to reduce the amount of opcodes in the bytecode).
-
-<p>For example, the bytecode for the function <code>"5+x*y-25*4/8"</code> will
-be reduced to a bytecode equivalent to the function <code>"x*y-7.5"</code> (the
-original 11 opcodes will be reduced to 5). Besides calculating constant
-expressions (like in the example), it also performs other types of
-simplifications with variable and function expressions.
-
-<p>This method is quite slow and the decision of whether to use it or
-not should depend on the type of application. If a function is parsed
-once and evaluated millions of times, then calling <code>Optimize()</code>
-may speed-up noticeably. However, if there are tons of functions to parse
-and each one is evaluated once or just a few times, then calling
-<code>Optimize()</code> will only slow down the program.
-
-<p>Also, if the original function is expected to be optimal, then calling
-<code>Optimize()</code> would be useless.
-
-<p>Note: Currently this method does not make any checks (like
-<code>Eval()</code> does) and thus things like <code>"1/0"</code> will cause
-undefined behaviour. (On the other hand, if such expression is given to the
-parser, <code>Eval()</code> will always give an error code, no matter what
-the parameters.) If caching this type of errors is important, a work-around
-is to call <code>Eval()</code> once before calling <code>Optimize()</code>
-and checking <code>EvalError()</code>.
-
-<p>If the destination application is not going to use this method,
-the compiler constant <code>FP_SUPPORT_OPTIMIZER</code> can be undefined in
-<code>fpconfig.hh</code> to make the library smaller (<code>Optimize()</code>
-can still be called, but it will not do anything).
-
-<p>(If you are interested in seeing how this method optimizes the opcode,
-you can call the <code>PrintByteCode()</code> method before and after the
-call to <code>Optimize()</code> to see the difference.)
-
-
-<hr>
-<a name="longdesc_AddConstant"></a>
-<pre>
-bool AddConstant(const std::string& name, double value);
-</pre>
-
-<p>This method can be used to add constants to the parser. Syntactically
- constants are identical to variables (ie. they follow the same naming
- rules and they can be used in the function string in the same way as
- variables), but internally constants are directly replaced with their
- value at parse time.
-
-<p>Constants used by a function must be added before calling
-<code>Parse()</code> for that function. Constants are preserved between
-<code>Parse()</code> calls in the current FunctionParser instance, so
-they don't need to be added but once. (If you use the same constant in
-several instances of FunctionParser, you will need to add it to all the
-instances separately.)
-
-<p>Constants can be added at any time and the value of old constants can
-be changed, but new additions and changes will only have effect the next
-time <code>Parse()</code> is called. (That is, changing the value of a constant
-after calling <code>Parse()</code> and before calling <code>Eval()</code>
-will have no effect.)
-
-<p>The return value will be <code>false</code> if the '<code>name</code>' of
-the constant was illegal, else <code>true</code>. If the name was illegal,
-the method does nothing.
-
-<p>Example: <code>parser.AddConstant("pi", 3.1415926535897932);</code>
-
-<p>Now for example <code>parser.Parse("x*pi", "x");</code> will be identical
-to the call <code>parser.Parse("x*3.1415926535897932", "x");</code>
-
-
-<hr>
-<a name="longdesc_AddUnit"></a>
-<pre>
-bool AddUnit(const std::string& name, double value);
-</pre>
-
-<p>In some applications it is desirable to have units of measurement.
-A typical example is an application which creates a page layout to be
-printed. When printing, distances are usually measured in points
-(defined by the resolution of the printer). However, it is often more
-useful for the user to be able to specify measurements in other units
-such as centimeters or inches.
-
-<p>A unit is simply a value by which the preceding element is multiplied.
-For example, if the printing has been set up to 300 DPI, one inch is
-then 300 points (dots). Thus saying eg. <code>"5in"</code> is the same as saying
-<code>"5*300"</code> or <code>"1500"</code> (assuming <code>"in"</code> has
-been added as a unit with the value 300).
-
-<p>Note that units are slightly different from a multiplication in
-that they have a higher precedence than any other operator (except
-parentheses). Thus for example <code>"5/2in"</code> is parsed as
-<code>"5/(2*300)"</code>.
-(If 5/2 inches is what one wants, it has to be written <code>"(5/2)in"</code>.)
-
-<p>You can use the <code>AddUnit()</code> method to add a new unit. The
-unit can then be used after any element in the function (and will work as
-a multiplier for that element). An element is a float literal, a constant,
-a variable, a function or any expression in parentheses. When the element
-is not a float literal nor an expression in parentheses, there has to naturally
-be at least one whitespace between the element and the unit (eg.
-<code>"x in"</code>). To change the value of a unit, call
-<code>AddUnit()</code> again with the same unit name and the new value.
-
-<p>Unit names share the same namespace as constants, functions and
- variables, and thus should be distinct from those.
-
-<p>Example: <code>parser.AddUnit("in", 300);</code>
-
-<p>Now for example the function <code>"5in"</code> will be identical to
-<code>"(5*300)"</code>. Other usage examples include <code>"x in"</code>,
-<code>"3in+2"</code>, <code>"pow(x,2)in"</code>, <code>"(x+2)in"</code>.
-
-
-<hr>
-<a name="longdesc_AddFunction1"></a>
-<pre>
-bool AddFunction(const std::string& name,
- double (*functionPtr)(const double*),
- unsigned paramsAmount);
-</pre>
-
-This method can be used to add new functions to the parser. For example,
-if you would like to add a function "<code>sqr(A)</code>" which squares the
-value of <code>A</code>, you can do it with this method (so that you don't
-need to touch the source code of the parser).
-
-<p>The method takes three parameters:
-
-<ul>
- <li>The name of the function. The name follows the same naming conventions
- as variable names.
-
- <li>A C++ function, which will be called when evaluating the function
- string (if the user-given function is called there). The C++ function
- must have the form:
- <p><code>double functionName(const double* params);</code>
-
- <li>The number of parameters the function takes. 0 is a valid value
- in which case the function takes no parameters (such function
- should simply ignore the <code>double*</code> it gets as a parameter).
-</ul>
-
-<p>The return value will be <code>false</code> if the given name was invalid
-(either it did not follow the variable naming conventions, or the name was
-already reserved), else <code>true</code>. If the return value is
-<code>false</code>, nothing is added.
-
-<p>Example: Suppose we have a C++ function like this:
-
-<p><code>double Square(const double* p)</code><br>
-<code>{</code><br>
-<code> return p[0]*p[0];</code><br>
-<code>}</code>
-
-<p>Now we can add this function to the parser like this:
-
-<p><code>parser.AddFunction("sqr", Square, 1);</code><br>
-<code>parser.Parse("2*sqr(x)", "x");</code>
-
-<p>An example of a useful function taking no parameters is a function
- returning a random value. For example:
-
-<p><code>double Rand(const double*)</code><br>
-<code>{</code><br>
-<code> return drand48();</code><br
-<code>}</code>
-
-<p><code>parser.AddFunction("rand", Rand, 0);</code>
-
-<p><em>Important note</em>: If you use the <code>Optimize()</code> method,
-it will assume that the user-given function has no side-effects, that is,
-it always returns the same value for the same parameters. The optimizer will
-optimize the function call away in some cases, making this assumption.
-(The <code>Rand()</code> function given as example above is one such
-problematic case.)
-
-
-<hr>
-<a name="longdesc_AddFunction2"></a>
-<pre>
-bool AddFunction(const std::string& name, FunctionParser&);
-</pre>
-
-<p>This method is almost identical to the previous <code>AddFunction()</code>,
-but instead of taking a C++ function, it takes another FunctionParser
-instance.
-
-<p>There are some important restrictions on making a FunctionParser instance
- call another:
-
-<ul>
- <li>The FunctionParser instance given as parameter must be initialized
- with a <code>Parse()</code> call before giving it as parameter. That
- is, if you want to use the parser <code>A</code> in the parser
- <code>B</code>, you must call <code>A.Parse()</code> before you can
- call <code>B.AddFunction("name", A)</code>.
-
- <li>The amount of variables in the FunctionParser instance given as
- parameter must not change after it has been given to the
- <code>AddFunction()</code>
- of another instance. Changing the number of variables will result in
- malfunction.
-
- <li><code>AddFunction()</code> will fail (ie. return <code>false</code>)
- if a recursive loop is
- formed. The method specifically checks that no such loop is built.
-
- <li>The FunctionParser instance given as parameter will <em>not</em> be
- copied internally, only referenced. Thus the FunctionParser instance
- given as parameter must exist for as long as the other FunctionParser
- instance uses it.
-</ul>
-
-<p>Example:
-
-<p><code>FunctionParser f1, f2;</code><br>
-<p><code>f1.Parse("x*x", "x");</code><br>
-<p><code>f2.AddFunction("sqr", f1);</code>
-
-<p>This version of the <code>AddFunction()</code> method can be useful to
-eg. chain user-given functions. For example, ask the user for a function F1,
- and then ask the user another function F2, but now the user can
- call F1 in this second function if he wants (and so on with a third
- function F3, where he can call F1 and F2, etc).
-
-<hr>
-<a name="longdesc_AddFunction3"></a>
-<pre>
-template<typename DerivedWrapper>
-bool AddFunctionWrapper(const std::string& name, const DerivedWrapper&,
- unsigned paramsAmount);
-</pre>
-
-<p>See section on <a href="#functionobjects">specialized function objects</a>.
-
-<hr>
-<a name="longdesc_RemoveIdentifier"></a>
-<pre>
-bool RemoveIdentifier(const std::string& name);
-</pre>
-
-<p>If a constant, unit or user-defined function with the specified name
-exists in the parser, it will be removed and the return value will be
-<code>true</code>, else nothing will be done and the return value will be
-<code>false</code>.
-
-<p>(Note: If you want to remove <em>everything</em> from an existing
-FunctionParser instance, simply assign a fresh instance to it, ie. like
-"<code>parser = FunctionParser();</code>")
-
-<hr>
-<a name="longdesc_ParseAndDeduceVariables"></a>
-<pre>
-int ParseAndDeduceVariables(const std::string& function,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees = false);
-</pre>
-
-<p>These functions work in the same way as the <code>Parse()</code> function,
-but the variables in the input function string are deduced automatically. The
-parameters are:
-
-<ul>
- <li><code>function</code>: The input function string, as with
- <code>Parse()</code>.
- <li><code>amountOfVariablesFound</code>: If non-null, the amount of found
- variables will be assigned here.
- <li><code>resultVarString</code>: The found variables will be written to
- this string, in the same format as accepted by the <code>Parse()</code>
- function. The variable names will be sorted using the <code><</code>
- operator of <code>std::string</code>.
- <li><code>resultVars</code>: The found variables will be written to this
- vector, each element being one variable name. They will be sorted using
- the <code><</code> operator of <code>std::string</code>. (The amount
- of found variables can be retrieved, rather obviously, with the
- <code>size()</code> method of the vector.)
- <li><code>useDegrees</code>: As with <code>Parse()</code>.
-</ul>
-
-<p>As with <code>Parse()</code>, the return value will be <code>-1</code> if
-the parsing succeeded, else an index to the location of the error. None of
-the specified return values will be modified in case of error.
-
-<!-- -------------------------------------------------------------------- -->
-<a name="functionobjects"></a>
-<h3>Specialized function objects</h3>
-
-<p>The <code>AddFunction()</code> method can be used to add a new user-defined
-function to the parser, its implementation being called through a C++ function
-pointer. Sometimes this might not be enough, though. For example, one might
-want to use <code>boost::function</code> or other similar specialized stateful
-function objects instead of raw function pointers. This library provides a
-mechanism to achieve this.
-
-<h4>Creating and adding a specialized function object</h4>
-
-<p>In order to create a specialized function object, create a class derived
-from the <code>FunctionParser::FunctionWrapper</code> class. This class
-declares a virtual function named <code>callFunction</code> that the derived
-class must implement. For example:
-
-<pre>
-class MyFunctionWrapper:
- public FunctionParser::FunctionWrapper
-{
- public:
- virtual double callFunction(const double* values)
- {
- // Perform the actual function call here, like:
- return someFunctionSomewhere(values);
-
- // In principle the result could also be
- // calculated here, like for example:
- return values[0] * values[0];
- }
-};
-</pre>
-
-<p>You can then add an instance of this class to <code>FunctionParser</code>
-using the <code>AddFunctionWrapper()</code> method, which works like
-<code>AddFunction()</code>, but takes a wrapper object instead of a function
-pointer as parameter. For example:
-
-<pre>
-MyFunctionWrapper wrapper;
-parser.AddFunctionWrapper("funcName", wrapper, 1);
-</pre>
-
-<p>Note that <code>FunctionParser</code> will internally create a copy of
-the wrapper object, managing the lifetime of this copy, and thus the object
-given as parameter does not need to exist for as long as the
-<code>FunctionParser</code> instance. Hence the above could also be written as:
-
-<pre>
-parser.AddFunctionWrapper("funcName", MyFunctionWrapper(), 1);
-</pre>
-
-<p>Note that this also means that the wrapper class must have a working
-copy constructor.
-
-<p>Also note that if the <code>FunctionParser</code> instance is copied, all
-the copies will share the same function wrapper objects given to the original.
-
-<h4>Retrieving specialized function objects</h4>
-
-<p>As noted, the library will internally make a copy of the wrapper object,
-and thus it will be separate from the one which was given as parameter to
-<code>AddFunctionWrapper()</code>. In some cases it may be necessary to
-retrieve this wrapper object (for example to read or change its state).
-This can be done with the <code>GetFunctionWrapper()</code> method, which
-takes the name of the function and returns a pointer to the wrapper object,
-or null if no such object exists with that name.
-
-<p>Note that the returned pointer will be of type
-<code>FunctionParser::FunctionWrapper</code>. In order to get a pointer to
-the actual derived type, the calling code should perform a
-<code>dynamic_cast</code>, for example like this:
-
-<pre>
-MyFunctionWrapper* wrapper =
- dynamic_cast<MyFunctionWrapper*>
- (parser.GetFunctionWrapper("funcName"));
-
-if(!wrapper) { /* oops, the retrieval failed */ }
-else ...
-</pre>
-
-<p>(Using dynamic cast rather than a static cast adds safety because if you
-accidentally try to downcast to the wrong type, the pointer will become null.)
-
-<p>The calling code is free to modify the object in any way it wants, but it
-must not delete it (because <code>FunctionParser</code> itself handles this).
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="base"></a>
-<h3>FunctionParserBase</h3>
-
-<p>All the different parser types are derived from a templated base class
-named <code>FunctionParserBase</code>. In normal use it's not necessary to
-directly refer to this base class in the calling code. However, if the calling
-code also needs to be templated (with respect to the numerical type), then
-using <code>FunctionParserBase</code> directly is the easiest way to achieve
-this.
-
-<p>For example, if you want to make a function that handles more than one
-type of parser, it can be done like this:
-
-<pre>
-template<typename Value_t>
-void someFunction(FunctionParserBase<Value_t>& parser)
-{
- // do something with 'parser' here
-}
-</pre>
-
-<p>Now it's convenient to call that function with more than one type of
-parser, for example:
-
-<pre>
-FunctionParser realParser;
-FunctionParser_cd complexParser;
-
-someFunction(realParser);
-someFunction(complexParser);
-</pre>
-
-<p>Another example is a class that inherits from <code>FunctionParser</code>
-which also wants to support different numerical types. Such class can be
-declared as:
-
-<pre>
-template<typename Value_t>
-class SpecializedParser: public FunctionParserBase<Value_t>
-{
- ...
-};
-</pre>
-
-
-<!-- -------------------------------------------------------------------- -->
-<h2>Syntax</h2>
-
-<a name="literals"></a>
-<h3>Numeric literals</h3>
-
-<p>A numeric literal is a fixed numerical value in the input function string
- (either a floating point value or an integer value, depending on the parser
- type).
-
-<p>An integer literal can consist solely of numerical digits (possibly with
- a preceding unary minus). For example, "<code>12345</code>".
-
-<p>If the literal is preceded by the characters "<code>0x</code>", it
- will be interpreted as a hexadecimal literal, where digits can also include
- the letters from '<code>A</code>' to '<code>F</code>' (in either uppercase
- or lowercase). For example, "<code>0x89ABC</code>" (which corresponds to the
- value 563900).
-
-<p>A floating point literal (only supported by the floating point type parsers)
- may additionally include a decimal point followed by the decimal part of the
- value, such as for example "<code>12.34</code>", optionally followed by a
- decimal exponent.
-
-<p>A decimal exponent consists of an '<code>E</code>' or '<code>e</code>',
- followed by an optional plus or minus sign, followed by decimal digits, and
- indicates multiplication by a power of 10. For example, "<code>1.2e5</code>"
- (which is equivalent to the value 120000).
-
-<p>If a floating point literal is preceded by the characters "<code>0x</code>"
- it will be interpreted in hexadecimal. A hexadecimal floating point
- literal consists of a hexadecimal value, with an optional decimal point,
- followed optionally by a binary exponent in base 10 (in other words, the
- exponent is not in hexadecimal).
-
-<p>A binary exponent has the same format as a decimal exponent, except that
- '<code>P</code>' or '<code>p</code>' is used. A binary exponent indicates
- multiplication by a power of 2. For example, "<code>0xA.Bp10</code>"
- (which is equivalent to the value 10944).
-
-<p>With the complex versions of the library, the imaginary part of a numeric
- literal is written as a regular numeric literal with an '<code>i</code>'
- appended, for example "<code>5i</code>". Note that when also specifying
- the real part of a complex literal, parentheses should be used to avoid
- precedence problems. (For example, "<code>(2+5i) * x</code>"
- is not the same thing as "<code>2+5i * x</code>". The latter
- would be equivalent to "<code>2 + (5i * x)</code>".)
-
-<a name="identifiers"></a>
-<h3>Identifier names</h3>
-
-<p>An identifier is the name of a function (internal or user-defined),
- variable, constant or unit. New identifiers can be specified with the
- functions described in the earlier subsections in this document.
-
-<p>The name of an identifier can use any alphanumeric characters, the
- underscore character and any UTF8-encoded unicode character, excluding
- those denoting whitespace.
- The first character of the name cannot be a numeric digit, though.
-
-<p>All functions, variables, constants and units must use unique names.
- It's not possible to add two different identifiers with the same name.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="functionsyntax"></a>
-<h3>The function string syntax</h3>
-
-<p>The function string understood by the class is very similar (but not
-completely identical in all aspects) to mathematical expressions in the
-C/C++ languages.
-Arithmetic float expressions can be created from float literals, variables
-or functions using the following operators in this order of precedence:
-
-<p><table border=2>
- <tr>
- <td><code>()</code></td>
- <td>expressions in parentheses first</td>
- </tr><tr>
- <td><code>A unit</code></td>
- <td>a unit multiplier (if one has been added)</td>
- </tr><tr>
- <td><code>A^B</code></td>
- <td>exponentiation (A raised to the power B)</td>
- </tr><tr>
- <td><code>-A</code></td>
- <td>unary minus</td>
- </tr><tr>
- <td><code>!A</code></td>
- <td>unary logical not (result is 1 if <code>int(A)</code> is 0, else 0)</td>
- </tr><tr>
- <td><code>A*B A/B A%B</code></td>
- <td>multiplication, division and modulo</td>
- </tr><tr>
- <td><code>A+B A-B</code></td>
- <td>addition and subtraction</td>
- </tr><tr>
- <td><code>A=B A<B A<=B<br>A!=B A>B A>=B</code></td>
- <td>comparison between A and B (result is either 0 or 1)</td>
- </tr><tr>
- <td><code>A&B</code></td>
- <td>result is 1 if <code>int(A)</code> and <code>int(B)</code> differ from
- 0, else 0.<br>
- Note: Regardless of the values, both operands are always
- evaluated. However, if the expression is optimized, it may
- be changed such that only one of the operands is evaluated,
- according to standard shortcut logical operation semantics.</td>
- </tr><tr>
- <td><code>A|B</code></td>
- <td>result is 1 if <code>int(A)</code> or <code>int(B)</code> differ from 0,
- else 0.<br>
- Note: Regardless of the values, both operands are always
- evaluated. However, if the expression is optimized, it may
- be changed such that only one of the operands is evaluated,
- according to standard shortcut logical operation semantics.</td>
- </tr>
-</table>
-
-<p>(Note that currently the exponentiation operator is not supported for
- <code>FunctionParser_li</code> nor <code>FunctionParser_gmpint</code>.
- With the former the result would very easily overflow, making its
- usefulness questionable. With the latter it could be easily abused to
- make the program run out of memory; think of a function like
- "10^10^10^100000".)
-
-<p>Since the unary minus has higher precedence than any other operator, for
- example the following expression is valid: <code>x*-y</code>
-
-<p>The comparison operators use an epsilon value, so expressions which may
-differ in very least-significant digits should work correctly. For example,
-<code>"0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 = 1"</code> should always
-return 1, and the same comparison done with "<code>></code>" or
-"<code><</code>" should always return 0. (The epsilon value can be
-configured in the <code>fpconfig.hh</code> file.)
-Without epsilon this comparison probably returns the wrong value.
-
-<p>The class supports these functions:
-
-<p><table border=2>
-<tr>
- <td><code>abs(A)</code></td>
- <td>Absolute value (magnitude) of A.
- With real numbers, if A is negative, returns -A otherwise returns A.
- With complex numbers, equivalent to <code>hypot(real(x),imag(x))</code>.</td>
-</tr><tr>
- <td><code>acos(A)</code></td>
- <td>Arc-cosine of A. Returns the angle, measured in radians, whose cosine is A.</td>
-</tr><tr>
- <td><code>acosh(A)</code></td>
- <td>Same as acos() but for hyperbolic cosine.</td>
-</tr><tr>
- <td><code>arg(A)</code></td>
- <td>Phase angle of complex number A. Equivalent to <code>atan2(imag(x),real(x))</code>.</td>
-</tr><tr>
- <td><code>asin(A)</code></td>
- <td>Arc-sine of A. Returns the angle, measured in radians, whose sine is A.</td>
-</tr><tr>
- <td><code>asinh(A)</code></td>
- <td>Same as asin() but for hyperbolic sine.</td>
-</tr><tr>
- <td><code>atan(A)</code></td>
- <td>Arc-tangent of (A). Returns the angle, measured in radians,
- whose tangent is A.</td>
-</tr><tr>
- <td><code>atan2(A,B)</code></td>
- <td>Principal arc-tangent of A/B, using the signs of the
- two arguments to determine the quadrant of the result.
- Returns the solution to the two expressions
- hypot(A,B)*sin(x)=A, hypot(A,B)*cos(x)=B.
- The return value is in range -pi to pi, inclusive.</td>
-</tr><tr>
- <td><code>atanh(A)</code></td>
- <td>Same as atan() but for hyperbolic tangent.</td>
-</tr><tr>
- <td><code>cbrt(A)</code></td>
- <td>Cube root of A. Returns a solution to expression pow(x,3)=A.</td>
-</tr><tr>
- <td><code>conj(A)</code></td>
- <td>Complex conjugate of A. Equivalent to <code>real(x) - 1i*imag(x)</code> or <code>polar(abs(x),-arg(x))</code>.</td>
-</tr><tr>
- <td><code>ceil(A)</code></td>
- <td>Ceiling of A. Returns the smallest integer not smaller than A.
- Rounds up to the next higher integer. E.g. -2.9, -2.5 and -2.1 are
- rounded to -2.0, and 2.9, 2.5 and 2.1 are rounded to 3.0.</td>
-</tr><tr>
- <td><code>cos(A)</code></td>
- <td>Cosine of A. Returns the cosine of the angle A, where A is
- measured in radians.</td>
-</tr><tr>
- <td><code>cosh(A)</code></td>
- <td>Same as cos() but for hyperbolic cosine.</td>
-</tr><tr>
- <td><code>cot(A)</code></td>
- <td>Cotangent of A. Equivalent to <code>1/tan(A)</code>.</td>
-</tr><tr>
- <td><code>csc(A)</code></td>
- <td>Cosecant of A. Equivalent to <code>1/sin(A)</code>.</td>
-</tr><tr>
- <td><code>eval(...)</code></td>
- <td>This a recursive call to the function to be evaluated. The
- number of parameters must be the same as the number of parameters
- taken by the function. Must be called inside <code>if()</code> to avoid
- infinite recursion.</td>
-</tr><tr>
- <td><code>exp(A)</code></td>
- <td>Exponential of A. Returns the value of e raised to the power
- A where e is the base of the natural logarithm, i.e. the
- non-repeating value approximately equal to 2.71828182846.</td>
-</tr><tr>
- <td><code>exp2(A)</code></td>
- <td>Base 2 exponential of A. Equivalent to <code>pow(2,A)</code>.</td>
-</tr><tr>
- <td><code>floor(A)</code></td>
- <td>Floor of A. Returns the largest integer not greater than A. Rounds
- down to the next lower integer.
- E.g. -2.9, -2.5 and -2.1 are rounded to -3.0,
- and 2.9, 2.5 and 2.1 are rounded to 2.0.</td>
-</tr><tr>
- <td><code>hypot(A,B)</code></td>
- <td>Euclidean distance function. Equivalent to <code>sqrt(A^2+B^2)</code>.</td>
-</tr><tr>
- <td><code>if(A,B,C)</code></td>
- <td>If int(A) differs from 0, the return value of this function is B,
- else C. Only the parameter which needs to be evaluated is
- evaluated, the other parameter is skipped; this makes it safe to
- use <code>eval()</code> in them.</td>
-</tr><tr>
- <td><code>imag(A)</code></td>
- <td>Return the imaginary part of complex number A. Equivalent to <code>abs(A)*sin(arg(A))</code>.</td>
-</tr><tr>
- <td><code>int(A)</code></td>
- <td>Rounds A to the closest integer. Equidistant values are rounded away from
- zero. E.g. -2.9 and -2.5 are rounded to -3.0; -2.1 is rounded to -2.0,
- and 2.9 and 2.5 are rounded to 3.0; 2.1 is rounded to 2.0.</td>
-</tr><tr>
- <td><code>log(A)</code></td>
- <td>Natural (base e) logarithm of A. Returns the solution to expression exp(x)=A.</td>
-</tr><tr>
- <td><code>log2(A)</code></td>
- <td>Base 2 logarithm of A. Equivalent to <code>log(A)/log(2)</code>.</td>
-</tr><tr>
- <td><code>log10(A)</code></td>
- <td>Base 10 logarithm of A.</td>
-</tr><tr>
- <td><code>max(A,B)</code></td>
- <td>If A>B, the result is A, else B.</td>
-</tr><tr>
- <td><code>min(A,B)</code></td>
- <td>If A<B, the result is A, else B.</td>
-</tr><tr>
- <td><code>polar(A,B)</code></td>
- <td>Returns a complex number from magnitude A, phase angle B (in radians).
- Equivalent to <code>real(A)*(cos(real(B))+1i*sin(real(B)))</code>.</td>
-</tr><tr>
- <td><code>pow(A,B)</code></td>
- <td>Exponentiation (A raised to the power B).</td>
-</tr><tr>
- <td><code>real(A)</code></td>
- <td>Return the real part of complex number A. Equivalent to <code>abs(A)*cos(arg(A))</code>.</td>
-</tr><tr>
- <td><code>sec(A)</code></td>
- <td>Secant of A. Equivalent to <code>1/cos(A)</code>.</td>
-</tr><tr>
- <td><code>sin(A)</code></td>
- <td>Sine of A. Returns the sine of the angle A, where A is
- measured in radians.</td>
-</tr><tr>
- <td><code>sinh(A)</code></td>
- <td>Same as sin() but for hyperbolic sine.</td>
-</tr><tr>
- <td><code>sqrt(A)</code></td>
- <td>Square root of A. Returns a solution to expression pow(x,2)=A.</td>
-</tr><tr>
- <td><code>tan(A)</code></td>
- <td>Tangent of A. Returns the tangent of the angle A, where A
- is measured in radians.</td>
-</tr><tr>
- <td><code>tanh(A)</code></td>
- <td>Same as tan() but for hyperbolic tangent.</td>
-</tr><tr>
- <td><code>trunc(A)</code></td>
- <td>Truncated value of A. Returns an integer corresponding to the value
- of A without its fractional part.
- E.g. -2.9, -2.5 and -2.1 are rounded to -2.0,
- and 2.9, 2.5 and 2.1 are rounded to 2.0.</td>
-</tr>
-</table>
-
-<p>(Note that for <code>FunctionParser_li</code> and
- <code>FunctionParser_gmpint</code> only the functions
- <code>abs()</code>, <code>eval()</code>, <code>if()</code>,
- <code>min()</code> and <code>max()</code> are supported.)
-
-<p>Examples of function string understood by the class:
-
-<p><code>"1+2"</code><br>
-<code>"x-1"</code><br>
-<code>"-sin(sqrt(x^2+y^2))"</code><br>
-<code>"sqrt(XCoord*XCoord + YCoord*YCoord)"</code><br>
-
-<p>An example of a recursive function is the factorial function:
-
-<code>"if(n>1, n*eval(n-1), 1)"</code>
-
-<p>Note that a recursive call has some overhead, which makes it a bit slower
- than any other operation. It may be a good idea to avoid recursive functions
- in very time-critical applications. Recursion also takes some memory, so
- extremely deep recursions should be avoided (eg. millions of nested recursive
- calls).
-
-<p>Also note that even though the maximum recursion level of
-<code>eval()</code> is limited, it is possible to write functions which
-never reach that level but still take enormous amounts of time to evaluate.
-This can sometimes be undesirable because it is prone to exploitation,
-which is why <code>eval()</code> is disabled by default. It can be enabled
-in the <code>fpconfig.hh</code> file.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="inlinevars"></a>
-<h3>Inline variables</h3>
-
-<p>The function syntax supports defining new variables inside the function
-string itself. This can be done with the following syntax:
-
-<p><code>"<variable name> := <expression>; <function>"</code>
-
-<p>For example:
-
-<p><code>"length := sqrt(x*x+y*y); 2*length*sin(length)"</code>
-
-<p>(Spaces around the '<code>:=</code>' operator are optional.)
-
-<p>The obvious benefit of this is that if a long expression needs to be
-used in the function several times, this allows writing it only once and
-using a named variable from that point forward.
-
-<p>The variable name must be an unused identifier (in other words, not an
-existing function, variable or unit name).
-
-<p>The <code><function></code> part can have further inline variable
-definitions, and thus it's possible to have any amount of them, for example:
-
-<p><code>"A := x^2; B := y^2; C := z^2; sqrt(A+B+C)"</code>
-
-<p>The expressions in subsequent inline variable definitions can use any
-of the previous inline variables. It is also possible to redefine an inline
-variable. For example:
-
-<p><code>"A := x^2; A := 2*A; sqrt(A)"</code>
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="whitespace"></a>
-<h3>Whitespace</h3>
-
-<p>Arbitrary amounts of whitespace can optionally be included between
- elements in the function string.
- The following unicode characters are interpreted as whitespace:
-<table>
- <tr>
- <th>Character number</th>
- <th>Character name</th>
- <th>UTF-8 byte sequence</th>
- </tr>
- <tr><td>U+0009</td><td>HORIZONTAL TABULATION </td><td>09</td></tr>
- <tr><td>U+000A</td><td>LINE FEED </td><td>0A</td></tr>
- <tr><td>U+000B</td><td>VERTICAL TABULATION </td><td>0B</td></tr>
- <tr><td>U+000D</td><td>CARRIAGE RETURN </td><td>0D</td></tr>
- <tr><td>U+0020</td><td>SPACE </td><td>20</td></tr>
- <tr><td>U+00A0</td><td>NO-BREAK SPACE </td><td>C2 A0</td></tr>
- <tr><td>U+2000</td><td>EN QUAD </td><td>E2 80 80</td></tr>
- <tr><td>U+2001</td><td>EM QUAD </td><td>E2 80 81</td></tr>
- <tr><td>U+2002</td><td>EN SPACE </td><td>E2 80 82</td></tr>
- <tr><td>U+2003</td><td>EM SPACE </td><td>E2 80 83</td></tr>
- <tr><td>U+2004</td><td>THREE-PER-EM SPACE </td><td>E2 80 84</td></tr>
- <tr><td>U+2005</td><td>FOUR-PER-EM SPACE </td><td>E2 80 85</td></tr>
- <tr><td>U+2006</td><td>SIX-PER-EM SPACE </td><td>E2 80 86</td></tr>
- <tr><td>U+2007</td><td>FIGURE SPACE </td><td>E2 80 87</td></tr>
- <tr><td>U+2008</td><td>PUNCTUATION SPACE </td><td>E2 80 88</td></tr>
- <tr><td>U+2009</td><td>THIN SPACE </td><td>E2 80 89</td></tr>
- <tr><td>U+200A</td><td>HAIR SPACE </td><td>E2 80 8A</td></tr>
- <tr><td>U+200B</td><td>ZERO WIDTH SPACE </td><td>E2 80 8B</td></tr>
- <tr><td>U+202F</td><td>NARROW NO-BREAK SPACE </td><td>E2 80 AF</td></tr>
- <tr><td>U+205F</td><td>MEDIUM MATHEMATICAL SPACE</td><td>E2 81 9F</td></tr>
- <tr><td>U+3000</td><td>IDEOGRAPHIC SPACE </td><td>E3 80 80</td></tr>
-</table>
-
-<!-- -------------------------------------------------------------------- -->
-<h2>Miscellaneous</h2>
-
-<a name="fpaccuracy"></a>
-<h3>About floating point accuracy</h3>
-
-<p>Note that if you are using <code>FunctionParser_ld</code> or
-<code>FunctionParser_cld</code> and you want calculations to be as accurate
-as the <code>long double</code> type allows, you should pay special attention
-to floating point literals in your own code. For example, this is a very
-typical mistake:
-
-<pre>FunctionParser_ld parser;
-parser.AddConstant("pi", 3.14159265358979323846);</pre>
-
-<p>The mistake might not be immediately apparent. The mistake is that a
-literal of type <code>double</code> is passed to the <code>AddConstant()</code>
-function even though it expects a value of type <code>long double</code>.
-In most systems the latter has more bits of precision than the former, which
-means that the value will have its least-significant bits clipped,
-introducing a rounding error. The proper way of making the above calls is:
-
-<pre>FunctionParser_ld parser;
-parser.AddConstant("pi", 3.14159265358979323846L);</pre>
-
-<p>The same principle should be used everywhere in your own code, if you are
-using the <code>long double</code> type.
-
-<p>This is especially important if you are using the <code>MpfrFloat</code>
-type (in which case its string-parsing constructor or its
-<code>ParseValue()</code> or <code>parseString()</code> member functions
-should be used instead of using numerical literals).
-
-<a name="evaluationchecks"></a>
-<h3>About evaluation-time checks</h3>
-
-<p><code>FunctionParser::Eval()</code> will perform certain sanity
-checks before performing certain operations. For example, before calling the
-<code>sqrt</code> function, it will check if the parameter is negative, and
-if so, it will set the proper error code instead of calling the function.
-These checks include:
-
-<ul>
- <li>Division by (the exact value of) zero.
- <li>Square root of a negative value.
- <li>Logarithm of a non-positive value.
- <li>Arcsine or arccosine of a value not in the range [-1, 1]. (This includes
- hyperbolic versions of the functions.)
-</ul>
-
-<p>However, the library <em>can not</em> guarantee that it will catch all
-possible floating point errors before performing them, because this is
-impossible to do with standard C++. For example, dividing a very large
-value by a value which is very close to zero, or calculating the logarithm
-of a very small value may overflow the result, as well as multiplying two
-very large values. Raising a negative number to a non-integral power may
-cause a <em>NaN</em> result, etc.
-
-<p>As a rule of thumb, the library will (by default) detect invalid operations
-if they are invalid for a range of values. For example, square root is undefined
-for all negative values, and arc sine is undefined only values outside the range
-[-1, 1]. In general, operations which are invalid for only one single value
-(rather than a contiguous range of values) will not be detected (division by
-the exact value of zero is an exception to this rule) nor will
-overflow/underflow situations.
-
-<p>The library cannot guarantee that floating point
-errors will never happen during evaluation. This can make the library to
-return the floating point values <em>inf</em> and <em>NaN</em>. Moreover,
-if floating point errors cause an interrupt in the target computer
-architecture and/or when using certain compiler settings, this library
-cannot guarantee that it will never happen.
-
-<p>Note that the optimizer never performs any sanity checks.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="threadsafety"></a>
-<h3>About thread safety</h3>
-
-<p>None of the member functions of the FunctionParser class are thread-safe.
-Most prominently, the <code>Eval()</code> function is not thread-safe.
-(In other words, the <code>Eval()</code> function of a single FunctionParser
-instance cannot be safely called simultaneously by two threads.)
-
-<p>There are ways to use this library in a thread-safe way, though. If each
-thread uses its own FunctionParser instance, no problems will obviously
-happen. Note, however, that if these instances need to be a copy of a given
-FunctionParser instance (eg. one where the user has entered a function),
-a deep copy of this instance has to be performed for each thread. By
-default FunctionParser uses shallow-copying (copy-on-write), which means
-that a simple assignment of copy construction will not copy the data itself.
-To force a deep copy you can all the <code>ForceDeepCopy()</code> function on
-each of the instances of each thread after the assignment or copying has been
-done.
-
-<p>Another possibility is to compile the FunctionParser library so that
-its <code>Eval()</code> function will be thread-safe. (This can be done by
-defining the <code>FP_USE_THREAD_SAFE_EVAL</code> or the
-<code>FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA</code>
-precompiler constant.) As long as only one thread calls the other functions
-of FunctionParser, the other threads can safely call the <code>Eval()</code>
-of this one instance.
-
-<p>Note, however, that compiling the library like this can make
-<code>Eval()</code> slightly slower. (The <code>alloca</code> version, if
-supported by the compiler, will not be as slow.)
-
-<p>Also note that the MPFR and GMP versions of the library cannot be
- made thread-safe, and thus this setting has no effect on them.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="tipsandtricks"></a>
-<h3>Tips and tricks</h3>
-
-<h4>Add constants automatically to all parser objects</h4>
-
-<p>Often the same constants (such as <em>pi</em> and <em>e</em>) and other
-user-defined identifiers (such as units) are always used in all the
-<code>FunctionParser</code> objects throughout the program. It would be
-troublesome to always have to manually add these constants every time a
-new parser object is created.
-
-<p>There is, however, a simple way to always add these user-defined identifiers
-to all instances. Write a class like this:
-
-<pre>
- class ParserWithConsts: public FunctionParser
- {
- public:
- ParserWithConsts()
- {
- AddConstant("pi", 3.14159265358979323846);
- AddConstant("e", 2.71828182845904523536);
- }
- };
-</pre>
-
-<p>Now instead of using <code>FunctionParser</code>, always use
-<code>ParserWithConsts</code>. It will behave identically except that the
-constants (and possibly other user-defined identifiers) will always be
-automatically defined. (Objects of this type even survive
-<a href="http://en.wikipedia.org/wiki/Object_slicing">slicing</a>, so
-they are completely safe to use anywhere.)
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="contact"></a>
-<h3>Contacting the author</h3>
-
-<p>Any comments, bug reports, etc. should be sent to warp@iki.fi
-
-
-<!-- -------------------------------------------------------------------- -->
-<!--
-<a name="algorithm"></a>
-<h2>The algorithm used in the library</h2>
-
-<p>The whole idea behind the algorithm is to convert the regular infix
-format (the regular syntax for mathematical operations in most languages,
-like C and the input of the library) to postfix format. The postfix format
-is also called stack arithmetic since an expression in postfix format
-can be evaluated using a stack and operating with the top of the stack.
-
-<p>For example:
-
-<p><table border=2>
-<tr><th>infix</th> <th>postfix</th></tr>
-<tr><td><code>2+3</code></td><td><code>2 3 +</code></td></tr>
-<tr><td><code>1+2+3</code></td><td><code>1 2 + 3 +</code></td></tr>
-<tr><td><code>5*2+8/2</code></td><td><code>5 2 * 8 2 / +</code></td></tr>
-<tr><td><code>(5+9)*3</code></td><td><code>5 9 + 3 *</code></td></tr>
-</table>
-
-<p>The postfix notation should be read in this way:
-
-<p>Let's take for example the expression: <code>5 2 * 8 2 / +</code>
-<ul>
- <li>Put 5 on the stack
- <li>Put 2 on the stack
- <li>Multiply the two values on the top of the stack and put the result on
- the stack (removing the two old values)
- <li>Put 8 on the stack
- <li>Put 2 on the stack
- <li>Divide the two values on the top of the stack
- <li>Add the two values on the top of the stack (which are in this case
- the result of 5*2 and 8/2, that is, 10 and 4).
-</ul>
-
-<p>At the end there's only one value in the stack, and that value is the
-result of the expression.
-
-<p>Why stack arithmetic?
-
-<p>The last example above can give you a hint.
- In infix format operators have precedence and we have to use parentheses to
-group operations with lower precedence to be calculated before operations
-with higher precedence.
- This causes a problem when evaluating an infix expression, specially
-when converting it to byte code. For example in this kind of expression:
- <code>(x+1)/(y+2)</code>
-we have to calculate first the two additions before we can calculate the
-division. We have to also keep counting parentheses, since there can be
-a countless amount of nested parentheses. This usually means that you
-have to do some type of recursion.
-
-<p>The simplest and mostefficient way of calculating this is to convert it
-to postfix notation.
- The postfix notation has the advantage that you can make all operations
-in a straightforward way. You just evaluate the expression from left to
-right, applying each operation directly and that's it. There are no
-parentheses to worry about. You don't need recursion anywhere.
- You have to keep a stack, of course, but that's extremely easily done.
-Also you just operate with the top of the stack, which makes it very easy.
-You never have to go deeper than 2 items in the stack.
- And even better: Evaluating an expression in postfix format is never
-slower than in infix format. All the contrary, in many cases it's a lot
-faster (eg. because all parentheses are optimized away).
- The above example could be expressed in postfix format:
- <code>x 1 + y 2 + /</code>
-
-<p>The good thing about the postfix notation is also the fact that it can
-be extremely easily expressed in bytecode form.
- You only need a byte value for each operation, for each variable and
-to push a constant to the stack.
- Then you can interpret this bytecode straightforwardly. You just interpret
-it byte by byte, from the beginning to the end. You never have to go back,
-make loops or anything.
-
-<p>This is what makes byte-coded stack arithmetic so fast.
--->
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="license"></a>
-<h2>Usage license</h2>
-
-<p>Copyright © 2003-2011 Juha Nieminen, Joel Yliluoma
-
-<p>This Library is distributed under the
- <a href="http://www.gnu.org/copyleft/lesser.html">Lesser General Public
- License</a> (LGPL) version 3.
-
-</body>
-</html>
+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+++ /dev/null
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
+++ /dev/null
-html
-{
- background-color: #E0E0E0;
-}
-
-body
-{
- background-color: white;
- margin-left: 7%;
- margin-top: 16px;
- margin-right: 7%;
- padding-top: 2em;
- padding-left: 7%;
- padding-right: 7%;
- padding-bottom: 2%;
- border-color: black;
- border: solid;
- border-width: 1px;
-}
-
-h1
-{
- text-align: center;
- background-color: #FFEEBB;
- padding-bottom: 0.2em;
- padding-top: 0.1em;
-}
-
-h2
-{
- background-color: #FFFFCC;
- padding-left: 0.5em;
-}
-
-h3
-{
- background-color: #FFFFEE;
-}
-
-blockquote
-{
- padding-left: 2em;
- padding-right: 2em;
- font-style: italic;
- background-color: #FFFAF0;
-}
-
-li
-{
- padding-top: 0.3em;
-}
-
-pre
-{
- background-color: #E8E8E8;
- padding-left: 1em;
- padding-top: 0.5em;
- padding-bottom: 0.5em;
-}
-
-code
-{
- font-family: monospace;
- color: #900040;
-}
-
-.small
-{
- font-size: 80%;
-}
-
-.codecomment
-{
- color: green;
-}
-
-.highlight
-{
- background: #C0D0FF;
-}
+++ /dev/null
-// Simple example file for the function parser\r
-// ===========================================\r
-\r
-/* When running the program, try for example with these values:\r
-\r
-f(x) = x^2\r
-min x: -5\r
-max x: 5\r
-step: 1\r
-\r
-*/\r
-\r
-#include "../fparser.hh"\r
-\r
-#include <iostream>\r
-#include <string>\r
-\r
-int main()\r
-{\r
- std::string function;\r
- double minx, maxx, step;\r
- FunctionParser fparser;\r
-\r
- fparser.AddConstant("pi", 3.1415926535897932);\r
-\r
- while(true)\r
- {\r
- std::cout << "f(x) = ";\r
- std::getline(std::cin, function);\r
- if(std::cin.fail()) return 0;\r
-\r
- int res = fparser.Parse(function, "x");\r
- if(res < 0) break;\r
-\r
- std::cout << std::string(res+7, ' ') << "^\n"\r
- << fparser.ErrorMsg() << "\n\n";\r
- }\r
-\r
- std::cout << "min x: ";\r
- std::cin >> minx;\r
- std::cout << "max x: ";\r
- std::cin >> maxx;\r
- std::cout << "step: ";\r
- std::cin >> step;\r
- if(std::cin.fail()) return 0;\r
-\r
- double vals[] = { 0 };\r
- for(vals[0] = minx; vals[0] <= maxx; vals[0] += step)\r
- {\r
- std::cout << "f(" << vals[0] << ") = " << fparser.Eval(vals)\r
- << std::endl;\r
- }\r
-\r
- return 0;\r
-}\r
+++ /dev/null
-// Simple example file for the function parser
-// ===========================================
-/* Note that the library has to be compiled with
- FP_SUPPORT_FLOAT_TYPE, FP_SUPPORT_LONG_DOUBLE_TYPE and
- FP_SUPPORT_LONG_INT_TYPE
- preprocessor macros defined for this example to work.
-
- Try with these input values with the different floating point parser
- types to see the difference in accuracy:
-
-f(x) = x + 1.234567890123456789
-min x: 0
-max x: 2
-step: 1
-*/
-
-#include "../fparser.hh"
-
-#include <iostream>
-#include <iomanip>
-#include <string>
-
-template<typename Parser>
-void runExample(const char* valueTypeName)
-{
- typedef typename Parser::value_type Value_t;
-
- std::cout << "Using " << valueTypeName << " parser." << std::endl;
-
- Parser fparser;
- std::string function;
- Value_t minx, maxx, step;
-
- fparser.AddConstant("pi", Value_t(3.1415926535897932));
-
- std::cin.ignore();
- while(true)
- {
- std::cout << "f(x) = ";
- std::getline(std::cin, function);
- if(std::cin.fail()) return;
-
- int res = fparser.Parse(function, "x");
- if(res < 0) break;
-
- std::cout << std::string(res+7, ' ') << "^\n"
- << fparser.ErrorMsg() << "\n\n";
- }
-
- std::cout << "min x: ";
- std::cin >> minx;
- std::cout << "max x: ";
- std::cin >> maxx;
- std::cout << "step: ";
- std::cin >> step;
- if(std::cin.fail()) return;
-
- Value_t vals[] = { 0 };
- for(vals[0] = minx; vals[0] <= maxx; vals[0] += step)
- {
- std::cout << std::setprecision(20);
- std::cout << "f(" << vals[0] << ") = " << fparser.Eval(vals)
- << std::endl;
- }
-}
-
-int main()
-{
- int choice = 0;
- do
- {
- std::cout << "1 = double, 2 = float, 3 = long double, 4 = long int: ";
- std::cin >> choice;
- } while(choice < 1 || choice > 4);
-
- switch(choice)
- {
- case 1: runExample<FunctionParser>("double"); break;
- case 2: runExample<FunctionParser_f>("float"); break;
- case 3: runExample<FunctionParser_ld>("long double"); break;
- case 4: runExample<FunctionParser_li>("long int"); break;
- }
-
- return 0;
-}
+++ /dev/null
-/* NOTE:
- Do not include this file in your project. The fparser.cc file #includes
-this file internally and thus you don't need to do anything (other than keep
-this file in the same directory as fparser.cc).
-
- Part of this file is generated code (by using the make_function_name_parser
-utility, found in the development version of this library). It's not intended
-to be modified by hand.
-*/
-
- unsigned nameLength = 0;
- const unsigned maximumNameLength = 0x80000000U-8;
- /*
- Due to the manner the identifier lengths are returned from
- the readOpcode() function, the maximum supported length for
- identifiers is 0x7FFFFFFF bytes. We minus 8 here to add some
- buffer, because of the multibyteness of UTF-8.
- Function names are limited to 0xFFFF bytes instead, but because
- function names that long just are not defined, the point is moot.
- */
- const unsigned char* const uptr = (const unsigned char*) input;
- typedef signed char schar;
- while(likely(nameLength < maximumNameLength))
- {
- unsigned char byte = uptr[nameLength+0];
- /* Handle the common case of A-Za-z first */
- if(byte >= 0x40)
- {
- if(byte < 0x80) // 0x40..0x7F - most common case
- {
- // Valid characters in 40..7F: A-Za-z_
- // Valid bitmask for 40..5F: 01111111111111111111111111100001
- // Valid bitmask for 60..7F: 01111111111111111111111111100000
- if(sizeof(unsigned long) == 8)
- {
- const unsigned n = sizeof(unsigned long)*8-32;
- // ^ avoids compiler warning when not 64-bit
- unsigned long masklow6bits = 1UL << (byte & 0x3F);
- if(masklow6bits & ~((1UL << 0) | (0x0FUL << (0x1B ))
- | (1UL << n) | (0x1FUL << (0x1B+n))))
- { ++nameLength; continue; }
- }
- else
- {
- unsigned masklow5bits = 1 << (byte & 0x1F);
- if((masklow5bits & ~(1 | (0x1F << 0x1B))) || byte == '_')
- { ++nameLength; continue; }
- }
- break;
- }
- if(byte < 0xF0)
- {
- if(byte < 0xE0)
- {
- if(byte < 0xC2) break; // 0x80..0xC1
- if(byte == 0xC2 && uptr[nameLength+1]==0xA0) break; // skip nbsp
- // C2-DF - next common case when >= 0x40
- // Valid sequence: C2-DF 80-BF
- if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
- nameLength += 2;
- continue;
- }
- if(byte == 0xE0) // E0
- {
- // Valid sequence: E0 A0-BF 80-BF
- if((unsigned char)(uptr[nameLength+1] - 0xA0) > (0xBF-0xA0)) break;
- }
- else
- {
- if(byte == 0xED) break; // ED is invalid
- // Valid sequence: E1-EC 80-BF 80-BF
- // And: EE-EF 80-BF 80-BF
- if(byte == 0xE2)
- {
- // break on various space characters
- if(uptr[nameLength+1] == 0x80
- && (schar(uptr[nameLength+2]) <= schar(0x8B)
- || (uptr[nameLength+2] == 0xAF))) break;
- if(uptr[nameLength+1] == 0x81
- && uptr[nameLength+2] == 0x9F) break;
- } else
- if(byte == 0xE3 && uptr[nameLength+1] == 0x80
- && uptr[nameLength+2] == 0x80) break; // this too
-
- if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
- }
- if(schar(uptr[nameLength+2]) > schar(0xBF)) break;
- nameLength += 3;
- continue;
- }
- if(byte == 0xF0) // F0
- {
- // Valid sequence: F0 90-BF 80-BF 80-BF
- if((unsigned char)(uptr[nameLength+1] - 0x90) > (0xBF-0x90)) break;
- }
- else
- {
- if(byte > 0xF4) break; // F5-FF are invalid
- if(byte == 0xF4) // F4
- {
- // Valid sequence: F4 80-8F
- if(schar(uptr[nameLength+1]) > schar(0x8F)) break;
- }
- else
- {
- // F1-F3
- // Valid sequence: F1-F3 80-BF 80-BF 80-BF
- if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
- }
- }
- if(schar(uptr[nameLength+2]) > schar(0xBF)) break;
- if(schar(uptr[nameLength+3]) > schar(0xBF)) break;
- nameLength += 4;
- continue;
- }
- if(nameLength > 0)
- {
- if(sizeof(unsigned long) == 8)
- {
- // Valid bitmask for 00..1F: 00000000000000000000000000000000
- // Valid bitmask for 20..3F: 00000000000000001111111111000000
- const unsigned n = sizeof(unsigned long)*8-32;
- // ^ avoids compiler warning when not 64-bit
- unsigned long masklow6bits = 1UL << byte;
- if(masklow6bits & (((1UL << 10)-1UL) << (16+n)))
- { ++nameLength; continue; }
- }
- else
- {
- if(byte >= '0' && byte <= '9')
- { ++nameLength; continue; }
- }
- }
- break;
- }
-
- /* This function generated with make_function_name_parser.cc */
-#define lO l3 lH
-#define lN switch(
-#define lM l4 lH
-#define lL if('i' l5
-#define lK 'n' l5
-#define lJ 0x80000003U;
-#define lI l1 3]={
-#define lH case
-#define lG 0x80000005U;
-#define lF )==0)l0(
-#define lE l8 3;}lH
-#define lD std::memcmp(uptr+
-#define lC l2 3 lF
-#define lB lA 1]){lH
-#define lA :lN uptr[
-#define l9 'a' lB
-#define l8 default:l0
-#define l7 lG l0 5;}lH
-#define l6 <<16)|
-#define l5 ==uptr[
-#define l4 lJ l0 3;
-#define l3 0x80000004U;l0 4;
-#define l2 lD 1,tmp,
-#define l1 static const char tmp[
-#define l0 return
-lN
-nameLength){lH
-2:lL
-0]&&'f' l5
-1])l0(cIf
-l6
-0x80000002U;l0
-2;lH
-3
-lA
-0]){lH
-l9'b':if('s' l5
-2])l0(cAbs
-l6
-lM'r':if('g' l5
-2])l0(cArg
-l6
-l4
-lE'c' lB'o' lA
-2]){lH's':l0(cCos
-l6
-lJ
-lH't':l0(cCot
-l6
-lJ
-lE's':if('c' l5
-2])l0(cCsc
-l6
-l4
-lE'e':if('x' l5
-1]&&'p' l5
-2])l0(cExp
-l6
-lM'i':if(lK
-1]&&'t' l5
-2])l0(cInt
-l6
-lM'l':if('o' l5
-1]&&'g' l5
-2])l0(cLog
-l6
-lM'm' lB'a':if('x' l5
-2])l0(cMax
-l6
-lM'i':if(lK
-2])l0(cMin
-l6
-l4
-lE'p':if('o' l5
-1]&&'w' l5
-2])l0(cPow
-l6
-lM's' lB'e':if('c' l5
-2])l0(cSec
-l6
-lM'i':if(lK
-2])l0(cSin
-l6
-l4
-lE't':if('a' l5
-1]&&lK
-2])l0(cTan
-l6
-l4
-lE
-4
-lA
-0]){lH
-l9'c':if('o' l5
-2]&&'s' l5
-3])l0(cAcos
-l6
-lO's':lL
-2]&&lK
-3])l0(cAsin
-l6
-lO't':if('a' l5
-2]&&lK
-3])l0(cAtan
-l6
-l3
-l8
-4;}
-lH'c' lB'b':if('r' l5
-2]&&'t' l5
-3])l0(cCbrt
-l6
-lO'e':lL
-2]&&'l' l5
-3])l0(cCeil
-l6
-lO'o' lA
-2]){lH'n':if('j' l5
-3])l0(cConj
-l6
-lO's':if('h' l5
-3])l0(cCosh
-l6
-l3
-l8
-4;}
-l8
-4;}
-lH'e':{lI'x','p','2'}
-;if(lC
-cExp2
-l6
-l3}
-lH'i':{lI'm','a','g'}
-;if(lC
-cImag
-l6
-l3}
-lH'l':{lI'o','g','2'}
-;if(lC
-cLog2
-l6
-l3}
-lH'r':{lI'e','a','l'}
-;if(lC
-cReal
-l6
-l3}
-lH's' lB'i':if(lK
-2]&&'h' l5
-3])l0(cSinh
-l6
-lO'q':if('r' l5
-2]&&'t' l5
-3])l0(cSqrt
-l6
-l3
-l8
-4;}
-lH't':{lI'a','n','h'}
-;if(lC
-cTanh
-l6
-l3}
-l8
-4;}
-lH
-5
-lA
-0]){lH
-l9'c':{lI'o','s','h'}
-;if(lD
-2,tmp,3
-lF
-cAcosh
-l6
-l7's':{lI'i','n','h'}
-;if(lD
-2,tmp,3
-lF
-cAsinh
-l6
-l7't':if('a' l5
-2]){if(lK
-3]){lN
-uptr[4]){lH'2':l0(cAtan2
-l6
-lG
-lH'h':l0(cAtanh
-l6
-lG
-l8
-5;}
-}
-l0
-5;}
-l0
-5;l8
-5;}
-lH'f':{l1
-4]={'l','o','o','r'}
-;if(l2
-4
-lF
-cFloor
-l6
-l7'h':{l1
-4]={'y','p','o','t'}
-;if(l2
-4
-lF
-cHypot
-l6
-l7'l':{l1
-4]={'o','g','1','0'}
-;if(l2
-4
-lF
-cLog10
-l6
-l7'p':{l1
-4]={'o','l','a','r'}
-;if(l2
-4
-lF
-cPolar
-l6
-l7't':{l1
-4]={'r','u','n','c'}
-;if(l2
-4
-lF
-cTrunc
-l6
-lG
-l0
-5;}
-l8
-5;}
-default:break;}
-l0
-nameLength;
+++ /dev/null
-/* Function Parser for C++ v4.5.1
-
- NOTE:
- Do not include this file in your project. The fparser.cc file #includes
-this file internally and thus you don't need to do anything (other than keep
-this file in the same directory as fparser.cc).
-
- This file contains generated code and is thus not intended to be to
-be modified by hand. It was generated by util/bytecoderules_parser, which
-is available in the development package.
-*/
-#define HasInvalidRangesOpcode HasInvalidRangesOpcode<IsComplexType<Value_t>::result>
-#define FP_TRACE_BYTECODE_OPTIMIZATION(srcline,from,to,with) \
- /*std::cout << "Changing \"" from "\"\t(line " #srcline ")\n" \
- " into \"" to "\"\n" with << std::flush*/
-#define FP_TRACE_OPCODENAME(op) \
- (op < VarBegin \
- ? FP_GetOpcodeName(OPCODE(op)) \
- : findName(mData->mNamePtrs,op,NameData<Value_t>::VARIABLE))
-#define FP_TRACE_BYTECODE_ADD(opcode) \
- /*std::cout << "Adding opcode: " << FP_TRACE_OPCODENAME(opcode) \
- << ", bytecode length " << data->ByteCode.size() \
- << ", pointer is " << (void*)ByteCodePtr \
- << ", code is " << (data->ByteCode.empty() \
- ? (void*)0 \
- : (void*)&data->ByteCode[0]) \
- << std::endl*/
-#define qH1 " B" mF
-#define qG1 gT y*x;
-#define qF1 hV 2;qI
-#define qE1 <<"," aD
-#define qD1 <<"," aB
-#define qC1 "cNeg"
-#define qB1 wA"," aD
-#define qA1 "x[x!=Value_t(0)] "
-#define q91 <<"," a8
-#define q81 wA"," a1
-#define q71 );qW q6
-#define q61 "cPow "
-#define q51 "cSqrt"
-#define q41 "cSqr "
-#define q31 " cExp2"
-#define q21 "cExp "
-#define q11 ){hD wB
-#define q01 "cCeil"
-#define mZ "cImag"
-#define mY "cConj"
-#define mX "cDup "
-#define mW hO wB
-#define mV "cAbs"
-#define mU wQ wH" "
-#define mT qS w2 wB
-#define mS "cFloor"
-#define mR "cTan"
-#define mQ " cDup"
-#define mP "cSin"
-#define mO (y hX;
-#define mN "[ y+x]"
-#define mM hV 2 gC
-#define mL " cExp"
-#define mK "A " wX
-#define mJ "cLess"
-#define mI "[-x]" wH
-#define mH "cDiv" a7
-#define mG "cLog"
-#define mF " cDiv"
-#define mE " " a6
-#define mD " " aF
-#define mC "cMin"
-#define mB "cMax"
-#define mA aY"x "
-#define m9 gN wB
-#define m8 "x cPow"
-#define m7 g1 oG wB
-#define m6 (x);gJ
-#define m5 "B cSqr"
-#define m4 oH dE wB
-#define m3 "[y*x]" wH
-#define m2 "cGreater"
-#define m1 mV" " wL
-#define m0 "cNeg "
-#define aZ " cAdd"
-#define aY "y "
-#define aX "B[IsVarOpcode(B)] "
-#define aW " cSub"
-#define aV gY if(dO wB
-#define aU "cInv"
-#define aT mX aU
-#define aS "cAbsNot"
-#define aR "cLessOrEq"
-#define aQ "cAdd " q51
-#define aP "[y*x] cPow"
-#define aO "cCos"
-#define aN "cLog2"
-#define aM "cCosh"
-#define aL "cLog10"
-#define aK "B[B==A]"
-#define aJ "cNotNot"
-#define aI " " a2
-#define aH "cDup" aZ
-#define aG "cGreaterOrEq"
-#define aF "x" aZ
-#define aE "cEqual"
-#define aD " " aC
-#define aC "A" wY
-#define aB " " wU
-#define aA " cNeg"
-#define a9 " cRDiv"
-#define a8 " B" wY
-#define a7 " x" wH
-#define a6 "cRSub"
-#define a5 "A[IsVarOpcode(A)]"
-#define a4 "x[x!=Value_t()] "
-#define a3 " " a5" "
-#define a2 " with" aD
-#define a1 " " wG
-#define a0 " cNot"
-#define wZ "x[x==Value_t()]" wH
-#define wY " " wC
-#define wX "[x]" wH
-#define wW "cNEqual"
-#define wV a5 mF
-#define wU "x = "<<x
-#define wT "x[isInteger(x)] cPow"
-#define wS a5 wH
-#define wR "x[x!=Value_t(0)]" mF
-#define wQ "x[x>Value_t(0)]"
-#define wP "B[IsNeverNegativeValueOpcode(B)] "
-#define wO "x[x==Value_t(1)] "
-#define wN wA"\n"
-#define wM <<"\n"
-#define wL "x[x==Value_t(0)] "
-#define wK "B[IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] " wD
-#define wJ "A[IsNeverNegativeValueOpcode(A)] "
-#define wI "A[IsVarOpcode(A)&&mData->mByteCode.size()>2] "
-#define wH " cMul"
-#define wG aY"= "<<y wM
-#define wF " x A[IsComparisonOpcode(A)]"
-#define wE FP_TRACE_BYTECODE_ADD
-#define wD "A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] " wZ
-#define wC "= "<<FP_TRACE_OPCODENAME
-#define wB FP_TRACE_BYTECODE_OPTIMIZATION
-#define wA " with" aB<<
-#define w9 qT q6:
-#define w8 cEqual
-#define w7 Lbd gY
-#define w6 Lcb gY
-#define w5 opcode
-#define w4 B==A){
-#define w3 q5 q4
-#define w2 cExp:
-#define w1 qO A qP
-#define w0 qO h2
-#define oZ qF g1
-#define oY if dC
-#define oX fp_pow(
-#define oW fp_log(
-#define oV 3 gC A
-#define oU x==g1 oG
-#define oT gX Lml;
-#define oS q4 Lbo
-#define oR 3 gH
-#define oQ cSinh:
-#define oP g1 0)
-#define oO 0.5)){
-#define oN Ldn;qT
-#define oM ]==h3){
-#define oL qY g8 0
-#define oK .size()
-#define oJ );qE
-#define oI A oJ dU
-#define oH g7 A=
-#define oG 1)){
-#define oF qU hI
-#define oE Lbo oF
-#define oD qT hM hB
-#define oC qL 3]
-#define oB :hC qQ oC
-#define oA cSub oB d3 hJ
-#define o9 q7=-x
-#define o8 gX Loi;
-#define o7 );qF
-#define o6 qE A o7
-#define o5 h3 d4 qL
-#define o4 fp_log2(
-#define o3 ==cSqr){
-#define o2 qT cSqr:
-#define o1 cGreater
-#define o0 Default6
-#define dZ Default5
-#define dY Default2
-#define dX Default1
-#define dW ImmedPtr
-#define dV gA qZ qC
-#define dU h3);
-#define dT gC dU
-#define dS cNotNot
-#define dR fp_log10(
-#define dQ cAbs);
-#define dP fp_abs(x)
-#define dO x>oP){
-#define dN mImmed
-#define dM qE h3 gX
-#define dL qK dJ w3
-#define dK cGreaterOrEq
-#define dJ =q6;
-#define dI qK dJ g6
-#define dH Value_t
-#define dG q8 2 gH q4
-#define dF q0[0]
-#define dE qK qR qX
-#define dD qK qR IsLogicalOpcode(h2
-#define dC (qK==
-#define dB hB oY
-#define dA qY g8 oG
-#define d9 pop_back()
-#define d8 q6;q1 h3 gI
-#define d7 q8 2 gC
-#define d6 hR Lba;
-#define d5 Default4 qU
-#define d4 :if(
-#define d3 qV hS d4 qL
-#define d2 h3 gM if
-#define d1 IsVarOpcode(
-#define d0 mData->
-#define hZ ]qR w4
-#define hY gX Llq
-#define hX ,x gX Lap
-#define hW gT y+x;q8
-#define hV for qA
-#define hU gQ cAbs:
-#define hT unsigned
-#define hS cAdd
-#define hR ,y gX
-#define hQ qL 3 hZ
-#define hP y=q3-1]qR
-#define hO y gO
-#define hN qY if(dP
-#define hM q6:qC
-#define hL :if gF
-#define hK qQ h9 hS hL
-#define hJ 4 qZ mW(292,aY"cAdd B[IsVarOpcode(B)]" aW mD,mN aZ" B" aW,wA"," a8(B)<<"," a1);q4
-#define hI cNeg:
-#define hH :qS cDup:
-#define hG hS hH hK h1 wB(310,aH" " aH,"[Value_t(4)]" wH,);q4
-#define hF (x!=g1
-#define hE qL 2]
-#define hD B g4 w4
-#define hC B=hE qO B)){
-#define hB if hF 0)){
-#define hA gX Lng;
-#define h9 qK qV
-#define h8 }break;
-#define h7 <dH>()){
-#define h6 hR Lap;
-#define h5 isEvenInteger(
-#define h4 DegreesToRadians(x
-#define h3 cMul
-#define h2 A)){
-#define h1 ]==cDup){
-#define h0 hI wB(201,m0 mV,mV,);q4 Lab qU qB
-#define gZ 3 h1 wB(311,aH wH" " aH,"cMul [Value_t(4)]" wH,);q4
-#define gY qU hM
-#define gX );q4
-#define gW y,x gX Lba;
-#define gV IsUnaryOpcode(
-#define gU g6 w5=
-#define gT q3-1]=
-#define gS gR qR IsAlwaysIntegerOpcode(h2
-#define gR ;oH dF
-#define gQ )){qQ h9
-#define gP break gR qO A gQ
-#define gO =q3-1];
-#define gN qJ hO
-#define gM :qJ qC
-#define gL d2(dO
-#define gK ]=q6 q9 2 gH
-#define gJ return;
-#define gI );w5=
-#define gH ;qI q5
-#define gG qL 2 gK q0-=2;
-#define gF (qL 2
-#define gE y;hT B;hT
-#define gD d0 mByteCode
-#define gC ;qI q1
-#define gB q9 2 gC h3 gI
-#define gA ){if gF
-#define g9 oY h3 dV
-#define g8 if(x==g1
-#define g7 default:
-#define g6 q5 q0-=1;
-#define g5 if(!q0){q2
-#define g4 =hE qR
-#define g3 B g4 IsNeverNegativeValueOpcode(B)){
-#define g2 &&!HasInvalidRangesOpcode(
-#define g1 dH(
-#define g0 FP_ReDefinePointers();
-#define qZ ]==q6){
-#define qY if(q0[0 qZ qC
-#define qX IsNeverNegativeValueOpcode(h2
-#define qW gD qD
-#define qV ){case
-#define qU ;case
-#define qT }break qU
-#define qS qQ dF qV
-#define qR ;if(
-#define qQ switch(
-#define qP )&&gD oK>
-#define qO qR d1
-#define qN dF w1 2){
-#define qM d0 dN.d9;
-#define qL q0[-
-#define qK qL 1]
-#define qJ oY q6){
-#define qI tmp-->0;)
-#define qH q4 Default0;
-#define qG }}qH
-#define qF d0 dN qD
-#define qE AddFunctionOpcode(
-#define qD .push_back(
-#define qC x=q7;
-#define qB hM wB(132,"x " mV,"[fp_abs(x)]",wN);q4 Lac;
-#define qA (hT tmp=
-#define q9 ;hV
-#define q8 d0 dN.d9 q9
-#define q7 q3 0]
-#define q6 cImmed
-#define q5 gD.d9;
-#define q4 goto
-#define q3 dW[
-#define q2 q4 Laa;}case
-#define q1 q5 qE
-#define q0 ByteCodePtr
-hT*q0;dH*dW;
-#define FP_ReDefinePointers() q0=!gD.empty()?&gD[0]+gD oK-1:0;dW=!d0 dN.empty()?&d0 dN[0]+d0 dN oK-1:0;
-g0
-wE(opcode);
-#if(!(FP_COMPLEX_VERSION) && !(FP_FLOAT_VERSION))
-dH
-x;hT
-A;dH
-gE
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0
-oH
-dF
-qR
-qX
-wB(393,wJ
-mV,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cAdd:g5
-hG
-Lad;qT
-h3
-hL]==hS){if(qL
-gZ
-Lae;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Laf;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lag
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Lah;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lai;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Laj
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lak;qT
-oA
-Lal;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lam
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lan;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Lao;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lap;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Laq;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lba;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-Lbb
-gY
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbc;h8}
-qH
-TailCall_cDiv:g5
-cDiv
-hH
-wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-w7
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Lbe
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Lbf;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lap;h8}
-qH
-TailCall_cEqual:g5
-w8:dA
-A=dD
-wB(421,"A[IsLogicalOpcode(A)] "
-wO
-aE,"A"
-,qB1(A)wM);q4
-Lap;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Lbg;}
-g8
-0
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Lbh
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Lbh;}
-wB(411,wL
-aE,"cNot"
-,wN);q4
-Lbi;qG
-TailCall_cGreater:g5
-o1:oL
-hU
-wB(413,m1
-m2,aJ,wN);q4
-Lbj;m4(417,wJ
-wL
-m2,"A "
-aJ,qB1(A)wM);q4
-Lbk;}
-}
-}
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Lbl;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-g8
-1
-hU
-wB(414,mV" "
-wO
-aG,aJ,wN);q4
-Lbj;m4(418,wJ
-wO
-aG,"A "
-aJ,qB1(A)wM);q4
-Lbk;}
-}
-}
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Lbm;qG
-TailCall_cInv:g5
-cInv:qY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Lbn;qG
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);oS;}
-}
-g8
-1
-hU
-wB(415,mV" "
-wO
-mJ,"cNot"
-,wN);q4
-Lbp;m4(419,wJ
-wO
-mJ,"A"
-a0,qB1(A)wM);q4
-Lbi;}
-}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lbq;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:oL
-hU
-wB(416,m1
-aR,"cNot"
-,wN);q4
-Lbp;m4(420,wJ
-wL
-aR,"A"
-a0,qB1(A)wM);q4
-Lbi;}
-}
-}
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lca;qG
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);q4
-w6
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lcc;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);q4
-Lcb;qT
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);q4
-Lcb;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);q4
-w6
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lcd;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);q4
-Lcb;qT
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);q4
-Lcb;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lce;}
-qG
-TailCall_cMul:g5
-h3
-hH
-wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lcf
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lcg;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lci;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lcj;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lck;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lcl;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcm;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcn;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lcj;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lco;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lcp;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lcq;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup:wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lda
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldb;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Ldc;qT
-h3:qQ
-hE
-d3
-3
-h1
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Ldd;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lde;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Ldf;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Ldg
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldh;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Ldi;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lap;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Ldj;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Ldk;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-q4
-Default4;g7
-Default4:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Ldl;}
-}
-q4
-dZ
-oF
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lcg;}
-q4
-dZ;g7
-dZ:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lcf;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Ldm;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:dA
-A=dD
-wB(422,"A[IsLogicalOpcode(A)] "
-wO
-wW,"A"
-a0,qB1(A)wM);q4
-Lbi;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Ldn;}
-g8
-0
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Ldo
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Ldo;}
-wB(412,wL
-wW,aJ,wN);q4
-Lbk;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Ldp;qT
-hI
-wB(61,qC1
-aA,,);q4
-w6
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Ldq;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbs:wB(227,mV
-a0,"cNot"
-,);q4
-Lea
-qU
-cAbsNot:A=dD
-wB(389,"A[IsLogicalOpcode(A)] "
-aS
-a0,"A"
-,aI(A)wM);q4
-Lcb;}
-if(A!=q6){wB(390,"A[A!=cImmed] "
-aS
-a0,"A cAbsNotNot"
-,aI(A)wM);q4
-Leb;}
-q4
-o0
-qU
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Lec
-qU
-hS
-gM
-wB(424,aF
-a0,"[-x] "
-aE,wN);q4
-Led;}
-q4
-o0
-qU
-w8:wB(220,aE
-a0,wW,);q4
-Lee
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Lef
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Leg
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Leh
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Lei
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Lej
-oF
-wB(226,qC1
-a0,"cNot"
-,);q4
-Lea
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbb
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Lea
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Lek;g7
-o0:;A=dF
-qR
-qX
-wB(391,wJ"cNot"
-,"A "
-aS,aI(A)wM);q4
-Lel;qG
-TailCall_cNotNot:g5
-dS:qS
-hS
-gM
-wB(423,aF" "
-aJ,"[-x] "
-wW,wN);q4
-Lem;qT
-cNot:wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-Lbb
-gY
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Len;h8}
-qH
-TailCall_cRDiv:g5
-cRDiv:dA
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Leo;qG
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Lep;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Leq
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Leq;}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Lep
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Lfa
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lap;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Lfb;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lfc
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Lfd;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lfe;}
-qG
-g7
-Default0:;A=w5
-qR
-IsComparisonOpcode(h2
-qY
-hK
-qZ
-mW(364,aY"cAdd"
-wF,"[x-y] A"
-,aI(A)qD1<<","
-a1);q4
-Lff;qT
-hI
-wB(365,qC1
-wF,"[-x] {OppositeComparisonOpcode(A)}"
-,aI(A)qD1
-wM);q4
-Lfg;}
-}
-}
-if(d1
-A
-qP
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lfh;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lfi;}
-}
-}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:oZ
-4));gG
-Lfj:w5=h3;Lfk:g0
-Lfl:wE(cMul);q4
-TailCall_cMul;Lae:hV
-4
-dT
-oZ
-4)q71
-gX
-Lfj;Laf:q7=x+g1
-1);gG
-Lbo:w5=h3;q4
-Lfl;Lag:gU
-cSub;Lfm:wE(cSub);q4
-TailCall_cSub;Lah:hW
-2
-gH
-Lfn:g0
-Lfo:wE(cAdd);q4
-TailCall_cAdd;Lai:hW
-oR
-Lfp:qE
-hS);Lfq:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Laj:o9;qL
-2
-gK
-q4
-Lfp;Lak:hW
-2
-gH
-q4
-Lfq;Lal:hW
-4
-gH
-Lga:qE
-hS);Lgb:qE
-B);Lgc:w5=cSub;g0
-q4
-Lfm;Lam:o9;oC=q6
-q9
-oR
-q4
-Lga;Lan:hW
-oR
-q4
-Lgb;Lao:gT
-y+x;Lap:qM
-Lcb:q5
-gJ
-Laq:q8
-oV
-o7
-x
-q71
-gX
-Lfp;Lba:mM
-A
-gX
-Lfp;Lbb:gU
-dS;Lgd:wE(cNotNot);q4
-TailCall_cNotNot;Lbc:gT
-fp_and(x
-h6
-Lbd:oZ));dF
-dJ
-qE
-dU
-oZ
-1));Lge:qW
-q6);Lgf:w5=hS;q4
-Lfn;Lbe:o9;dI
-wE(cDiv);q4
-TailCall_cDiv;Lbf:gT
-y/x;q4
-Lap;Lbg:gT
-fp_equal
-mO
-Lbh:dI
-Lgg:wE(cEqual);q4
-TailCall_cEqual;Lbi:qM
-q5
-Lgh:w5=cNot;g0
-Lgi:wE(cNot);q4
-TailCall_cNot;Lbj:q8
-2
-gH
-Lgj:w5=dS;g0
-q4
-Lgd;Lbk:qM
-w3
-Lgj;Lbl:gT
-fp_less(x
-h6
-Lbm:gT
-fp_lessOrEq(x
-h6
-Lbn:q7=g1
-1)/x;gJ
-Lbp:dG
-Lgh;Lbq:gT
-fp_less
-mO
-Lca:gT
-fp_lessOrEq
-mO
-Lcc:gT
-fp_max(x
-h6
-Lcd:gT
-fp_min(x
-h6
-Lce:gT
-fp_mod
-mO
-Lcf:gU
-cSqr;Lgk:wE(cSqr);q4
-TailCall_cSqr;Lcg:mM
-cSqr);Lgl:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lch:hV
-3
-gC
-cSqr);dM
-Lgl;Lci:q7=x+g1
-1);hE=q6
-q9
-2
-gC
-cPow);gJ
-Lcj:gG
-q4
-Lfl;Lck:gT
-x;Lgm:dG
-Lfk;Lcl:qF1
-qM
-Lgn:hV
-4
-gH
-Lgo:o6
-x);Lgp:qW
-q6
-gX
-Lfk;Lcm:qM
-q4
-Lgn;Lcn:q8
-4
-gC
-B
-gX
-Lgo;Lco:q8
-oR
-q4
-Lgo;Lcp:qK
-dJ
-q4
-Lcb;Lcq:dI
-q4
-Lfl;Lda:q7=x+x;q4
-Lcj;Ldb:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lgf;Ldc:gT
-x;d7
-dU
-qF
-y*x
-gX
-Lge;Ldd:q8
-4
-dT
-qF
-x+x
-gX
-Lgp;Lde:qF1
-q8
-oR
-gJ
-Ldf:qG1
-q4
-Lgm;Ldg:o9;q4
-Lcq;Ldh:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lgc;Ldi:qG1
-q4
-Lap;Ldj:qM
-w3
-Lgl;Ldk:dF=cDup;dW-=1;qM
-Lgq:w5=hS;q4
-Lfo;Ldl:hV
-2
-gH
-Lha:qE
-cSqr
-gX
-Lfk;Ldm:hV
-oR
-q4
-Lha;Ldn:gT
-fp_nequal
-mO
-Ldo:dI
-Lhb:wE(cNEqual);q4
-TailCall_cNEqual;Ldp:o9;g6
-oS;Ldq:o9;gJ
-Lea:g6
-q4
-Lgi;Leb:q1
-cAbsNotNot);gJ
-Lec:q5
-Lel:qE
-cAbsNot);gJ
-Led:o9;Lej:gU
-w8;q4
-Lgg;Lee:gU
-cNEqual;q4
-Lhb;Lef:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Leg:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Leh:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Lei:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Lek:q7=fp_not
-m6
-Lem:o9;q4
-Lee;Len:gT
-fp_or(x
-h6
-Leo:qM
-q5
-w5=cInv;g0
-wE(cInv);q4
-TailCall_cInv;Lep:oZ));dF
-dJ
-q4
-Lfj;Leq:g6
-q4
-Lgk;Lfa:g6
-q4
-Lgq;Lfb:gT
-y-x;q4
-Lap;Lfc:o9;q4
-Lgq;Lfd:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lfq;Lfe:mM
-A
-oJ
-cSub
-gX
-Lfq;Lff:gT
-x-y;d7
-A);gJ
-Lfg:o9;qK
-dJ
-q1
-OppositeComparisonOpcode(A));gJ
-Lfh:qW
-cDup);gJ
-Lfi:dF=cDup;gJ
-gJ
-q4
-TailCall_cAnd;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cNeg;q4
-TailCall_cOr;q4
-TailCall_cRDiv;q4
-TailCall_cSub;
-#endif
-#if((FP_COMPLEX_VERSION) && !(FP_FLOAT_VERSION))
-dH
-x;dH
-gE
-A;hT
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0}
-qH
-TailCall_cAdd:g5
-hG
-Lad;qT
-h3
-hL]==hS){if(qL
-gZ
-Lae;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Laf;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lag
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Lah;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lai;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Laj
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lak;qT
-oA
-Lal;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lam
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lan;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Lao;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lap;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Laq;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lba;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-Lbb
-gY
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbc;h8}
-qH
-TailCall_cConj:g5
-cConj:qS
-cConj:wB(63,mY" "
-mY,,);q4
-w7
-wB(193,"x "
-mY,"[fp_conj(x)]"
-,wN);q4
-Lbe;}
-qH
-TailCall_cDiv:g5
-cDiv
-hH
-wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lbf
-gY
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Lbg
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Lbh;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lap;h8}
-qH
-TailCall_cEqual:g5
-w8:dA
-A=dD
-wB(421,"A[IsLogicalOpcode(A)] "
-wO
-aE,"A"
-,qB1(A)wM);q4
-Lap;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Lbi;}
-g8
-0
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Lbj
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Lbj;}
-wB(411,wL
-aE,"cNot"
-,wN);q4
-Lbk;qG
-TailCall_cGreater:g5
-o1:qY
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Lbl;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Lbm;qG
-TailCall_cImag:g5
-cImag:qS
-cAbs:wB(81,mV" "
-mZ,"[Value_t()]"
-wH,);q4
-Lbn
-qU
-cReal:wB(80,"cReal "
-mZ,"[Value_t()]"
-wH,);q4
-Lbn
-gY
-wB(192,"x "
-mZ,"[fp_imag(x)]"
-,wN);oS;}
-qH
-TailCall_cInv:g5
-cInv:qY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Lbp;qG
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);q4
-Lbq;}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lca;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:qY
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lcb;qG
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);q4
-w7
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lcc;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);q4
-Lbd;qT
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);q4
-Lbd;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);q4
-w7
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lcd;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);q4
-Lbd;qT
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);q4
-Lbd;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lce;}
-qG
-TailCall_cMul:g5
-h3
-hH
-wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lcf
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lcg;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lci;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lcj;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lck;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lcl;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcm;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcn;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lcj;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lco;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lcp;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lcq;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup:wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lda
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldb;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Ldc;qT
-h3:qQ
-hE
-d3
-3
-h1
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Ldd;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lde;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Ldf;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Ldg
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldh;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Ldi;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lap;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Ldj;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Ldk;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-q4
-Default4;g7
-Default4:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Ldl;}
-}
-q4
-dZ
-oF
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lcg;}
-q4
-dZ;g7
-dZ:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lcf;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Ldm;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:dA
-A=dD
-wB(422,"A[IsLogicalOpcode(A)] "
-wO
-wW,"A"
-a0,qB1(A)wM);q4
-Lbk;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Ldn;}
-g8
-0
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Ldo
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Ldo;}
-wB(412,wL
-wW,aJ,wN);q4
-Ldp;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Ldq;qT
-hI
-wB(61,qC1
-aA,,);q4
-w7
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Lea;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Leb
-qU
-hS
-gM
-wB(424,aF
-a0,"[-x] "
-aE,wN);q4
-Lec;qT
-w8:wB(220,aE
-a0,wW,);q4
-Led
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Lee
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Lef
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Leg
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Leh
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Lei
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbb
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Lej
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Lek;}
-qH
-TailCall_cNotNot:g5
-dS:qS
-hS
-gM
-wB(423,aF" "
-aJ,"[-x] "
-wW,wN);q4
-Lel;qT
-cNot:wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-Lbb
-gY
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Lem;h8}
-qH
-TailCall_cRDiv:g5
-cRDiv:dA
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Len;qG
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Lbn;}
-qH
-TailCall_cReal:g5
-cReal:qY
-wB(191,"x cReal"
-,"[fp_real(x)]"
-,wN);q4
-Leo;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Lep
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Lep;}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Lbn
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Leq
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lap;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Lfa;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lfb
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Lfc;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lfd;}
-qG
-g7
-Default0:;A=w5
-w1
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lfe;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lff;}
-}
-}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:oZ
-4));gG
-Lfg:w5=h3;Lfh:g0
-Lfi:wE(cMul);q4
-TailCall_cMul;Lae:hV
-4
-dT
-oZ
-4)q71
-gX
-Lfg;Laf:q7=x+g1
-1);gG
-Lbq:w5=h3;q4
-Lfi;Lag:gU
-cSub;Lfj:wE(cSub);q4
-TailCall_cSub;Lah:hW
-2
-gH
-Lfk:g0
-Lfl:wE(cAdd);q4
-TailCall_cAdd;Lai:hW
-oR
-Lfm:qE
-hS);Lfn:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Laj:o9;qL
-2
-gK
-q4
-Lfm;Lak:hW
-2
-gH
-q4
-Lfn;Lal:hW
-4
-gH
-Lfo:qE
-hS);Lfp:qE
-B);Lfq:w5=cSub;g0
-q4
-Lfj;Lam:o9;oC=q6
-q9
-oR
-q4
-Lfo;Lan:hW
-oR
-q4
-Lfp;Lao:gT
-y+x;Lap:qM
-Lbd:q5
-gJ
-Laq:q8
-oV
-o7
-x
-q71
-gX
-Lfm;Lba:mM
-A
-gX
-Lfm;Lbb:gU
-dS;Lga:wE(cNotNot);q4
-TailCall_cNotNot;Lbc:gT
-fp_and(x
-h6
-Lbe:q7=fp_conj
-m6
-Lbf:oZ));dF
-dJ
-qE
-dU
-oZ
-1));Lgb:qW
-q6);Lgc:w5=hS;q4
-Lfk;Lbg:o9;dI
-wE(cDiv);q4
-TailCall_cDiv;Lbh:gT
-y/x;q4
-Lap;Lbi:gT
-fp_equal
-mO
-Lbj:dI
-Lgd:wE(cEqual);q4
-TailCall_cEqual;Lbk:qM
-q5
-w5=cNot;g0
-Lge:wE(cNot);q4
-TailCall_cNot;Lbl:gT
-fp_less(x
-h6
-Lbm:gT
-fp_lessOrEq(x
-h6
-Lbn:oZ));dF
-dJ
-q4
-Lfg;Lbo:q7=fp_imag
-m6
-Lbp:q7=g1
-1)/x;gJ
-Lca:gT
-fp_less
-mO
-Lcb:gT
-fp_lessOrEq
-mO
-Lcc:gT
-fp_max(x
-h6
-Lcd:gT
-fp_min(x
-h6
-Lce:gT
-fp_mod
-mO
-Lcf:gU
-cSqr;Lgf:wE(cSqr);q4
-TailCall_cSqr;Lcg:mM
-cSqr);Lgg:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lch:hV
-3
-gC
-cSqr);dM
-Lgg;Lci:q7=x+g1
-1);hE=q6
-q9
-2
-gC
-cPow);gJ
-Lcj:gG
-q4
-Lfi;Lck:gT
-x;Lgh:dG
-Lfh;Lcl:qF1
-qM
-Lgi:hV
-4
-gH
-Lgj:o6
-x);Lgk:qW
-q6
-gX
-Lfh;Lcm:qM
-q4
-Lgi;Lcn:q8
-4
-gC
-B
-gX
-Lgj;Lco:q8
-oR
-q4
-Lgj;Lcp:qK
-dJ
-q4
-Lbd;Lcq:dI
-q4
-Lfi;Lda:q7=x+x;q4
-Lcj;Ldb:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lgc;Ldc:gT
-x;d7
-dU
-qF
-y*x
-gX
-Lgb;Ldd:q8
-4
-dT
-qF
-x+x
-gX
-Lgk;Lde:qF1
-q8
-oR
-gJ
-Ldf:qG1
-q4
-Lgh;Ldg:o9;q4
-Lcq;Ldh:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lfq;Ldi:qG1
-q4
-Lap;Ldj:qM
-w3
-Lgg;Ldk:dF=cDup;dW-=1;qM
-Lgl:w5=hS;q4
-Lfl;Ldl:hV
-2
-gH
-Lgm:qE
-cSqr
-gX
-Lfh;Ldm:hV
-oR
-q4
-Lgm;Ldn:gT
-fp_nequal
-mO
-Ldo:dI
-Lgn:wE(cNEqual);q4
-TailCall_cNEqual;Ldp:qM
-q5
-w5=dS;g0
-q4
-Lga;Ldq:o9;g6
-q4
-Lbq;Lea:o9;gJ
-Leb:q1
-cAbsNot);gJ
-Lec:o9;Lei:gU
-w8;q4
-Lgd;Led:gU
-cNEqual;q4
-Lgn;Lee:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Lef:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Leg:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Leh:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Lej:g6
-q4
-Lge;Lek:q7=fp_not
-m6
-Lel:o9;q4
-Led;Lem:gT
-fp_or(x
-h6
-Len:qM
-q5
-w5=cInv;g0
-wE(cInv);q4
-TailCall_cInv;Leo:q7=fp_real
-m6
-Lep:g6
-q4
-Lgf;Leq:g6
-q4
-Lgl;Lfa:gT
-y-x;q4
-Lap;Lfb:o9;q4
-Lgl;Lfc:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lfn;Lfd:mM
-A
-oJ
-cSub
-gX
-Lfn;Lfe:qW
-cDup);gJ
-Lff:dF=cDup;gJ
-gJ
-q4
-TailCall_cAnd;q4
-TailCall_cConj;q4
-TailCall_cImag;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cNeg;q4
-TailCall_cOr;q4
-TailCall_cRDiv;q4
-TailCall_cReal;q4
-TailCall_cSub;
-#endif
-#if((FP_FLOAT_VERSION) && !(FP_COMPLEX_VERSION))
-dH
-x;hT
-A;dH
-gE
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0
-oH
-dF
-qR
-qX
-wB(393,wJ
-mV,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cAcos:g5
-cAcos:hN<=m7(148,"x[fp_abs(x)<=Value_t(1)] cAcos"
-,"[fp_acos(x)]"
-,wN);q4
-Lad;qG
-TailCall_cAcosh:g5
-cAcosh:qY
-if(x>=m7(145,"x[x>=Value_t(1)] cAcosh"
-,"[fp_acosh(x)]"
-,wN);q4
-Lae;qG
-TailCall_cAdd:g5
-hG
-Laf;qT
-h3
-hL]==hS){if(qL
-gZ
-Lag;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Lah;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lai
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Laj;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lak;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Lal
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lam;qT
-oA
-Lan;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lao
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lap;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Laq;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lba;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lbb;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lbc;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-w7
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbe;h8}
-qH
-TailCall_cAsin:g5
-cAsin:hN<=m7(149,"x[fp_abs(x)<=Value_t(1)] cAsin"
-,"[fp_asin(x)]"
-,wN);q4
-Lbf;qG
-TailCall_cAsinh:g5
-cAsinh:qY
-wB(146,"x cAsinh"
-,"[fp_asinh(x)]"
-,wN);q4
-Lbg;}
-qH
-TailCall_cAtan:g5
-cAtan:qY
-wB(150,"x cAtan"
-,"[fp_atan(x)]"
-,wN);q4
-Lbh;}
-qH
-TailCall_cAtan2:g5
-cAtan2:qY
-m9(139,mA"cAtan2"
-,"[fp_atan2(y,x)]"
-,q81);q4
-Lbi;qG
-TailCall_cAtanh:g5
-cAtanh:hN<m7(147,"x[fp_abs(x)<Value_t(1)] cAtanh"
-,"[fp_atanh(x)]"
-,wN);q4
-Lbj;qG
-TailCall_cCbrt:g5
-cCbrt:qY
-wB(151,"x cCbrt"
-,"[fp_cbrt(x)]"
-,wN);q4
-Lbk;}
-qH
-TailCall_cCeil:g5
-cCeil:qS
-hI
-wB(402,m0
-q01,mS
-aA,);q4
-Lbl
-gY
-wB(135,"x "
-q01,"[fp_ceil(x)]"
-,wN);q4
-Lbm
-gS
-wB(396,"A[IsAlwaysIntegerOpcode(A)] "
-q01,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cCos:g5
-cCos:qS
-cAbs:wB(235,mV" "
-aO,aO,);q4
-Lbn
-oF
-wB(238,m0
-aO,aO,);q4
-Lbn
-gY
-wB(152,"x "
-aO,"[fp_cos(x)]"
-,wN);oS;oH
-qN
-qQ
-h9
-cSec:hD
-wB(500,aK" cSec "
-wI
-aO,"B cSec "
-aT,aI(A)q91(B)wM);q4
-Lbp;qT
-cSin:hD
-wB(494,aK" "
-mP" "
-wI
-aO,"B cSinCos"
-,aI(A)q91(B)wM);q4
-Lbq;h8}
-qG
-TailCall_cCosh:g5
-cCosh:qS
-cAbs:wB(236,mV" "
-aM,aM,);q4
-Lca
-qU
-cAsinh:wB(450,"cAsinh "
-aM,"[DO_STACKPLUS1] "
-q41"[Value_t(1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lcb
-oF
-wB(239,m0
-aM,aM,);q4
-Lca
-gY
-wB(153,"x "
-aM,"[fp_cosh(x)]"
-,wN);q4
-Lcc;oH
-qN
-oY
-cSinh
-q11(507,aK" cSinh "
-wI
-aM,"B cSinhCosh"
-,aI(A)q91(B)wM);q4
-Lcd;}
-}
-qG
-TailCall_cCot:g5
-cCot:A=qN
-oY
-cTan
-q11(498,aK" "
-mR" "
-wI"cCot"
-,"B "
-mR" "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-qG
-TailCall_cCsc:g5
-cCsc:A=qN
-oY
-cSin
-q11(496,aK" "
-mP" "
-wI"cCsc"
-,"B "
-mP" "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-qG
-TailCall_cDeg:g5
-cDeg:qY
-wB(133,"x cDeg"
-,"[RadiansToDegrees(x)]"
-,wN);q4
-Lce;}
-qH
-TailCall_cDiv:g5
-cDiv:qS
-cCos:wB(250,aO
-mF,"cSec"
-wH,);q4
-Lcf
-qU
-cCot:wB(254,"cCot"
-mF,mR
-wH,);q4
-Lcg
-qU
-cCsc:wB(252,"cCsc"
-mF,mP
-wH,);q4
-Lch
-qU
-cDup:wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lci
-qU
-w2
-wB(408,"cExp"
-mF,m0"cExp"
-wH,);q4
-Lcj
-qU
-cExp2:wB(409,"cExp2"
-mF,m0"cExp2"
-wH,);q4
-Lck
-qU
-cInv:wB(213,aU
-mF,"cMul"
-,);q4
-Lcl
-qU
-cPow:wB(407,"cPow"
-mF,m0"cPow"
-wH,);q4
-Lcm
-qU
-cSec:wB(253,"cSec"
-mF,aO
-wH,);q4
-Lcn
-qU
-cSin:wB(249,mP
-mF,"cCsc"
-wH,);q4
-Lco
-qU
-cSinCos:wB(502,"cSinCos"
-mF,mR,);q4
-Lcp
-qU
-cSinhCosh:wB(509,"cSinhCosh"
-mF,"cTanh"
-,);q4
-Lcq
-qU
-cTan:wB(251,mR
-mF,"cCot"
-wH,);q4
-Lda
-gY
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Ldb
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Ldc;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lba;}
-dB
-h3
-gA
-qZ
-hP(y/x)==fp_const_rad_to_deg
-h7
-wB(321,"y[(y/x)==fp_const_rad_to_deg<Value_t>()]"
-wH" "
-wR,"cDeg"
-,q81);q4
-Ldd;}
-if((y/x)==fp_const_deg_to_rad
-h7
-wB(322,"y[(y/x)==fp_const_deg_to_rad<Value_t>()]"
-wH" "
-wR,"cRad"
-,q81);q4
-Lde;}
-wB(323,"y"
-wH" "
-wR,"[y/x]"
-wH,q81);q4
-Ldf;}
-}
-wB(325,wR,"[Value_t(1)/x]"
-wH,wN);q4
-Ldg;}
-gP
-cDiv:hC
-wB(271,aX"cDiv "
-wV,"[DO_STACKPLUS1] B A"
-wH
-mF,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Ldh;qT
-cRDiv:qQ
-hE
-qV
-hM
-wB(266,"x"
-a9" "
-wV,"A"
-wH" [x]"
-a9,aI(A)qD1
-wM);q4
-Ldi;g7
-hC
-wB(265,"B[IsVarOpcode(B)]"
-a9" "
-wV,"A"
-wH" B"
-a9,aI(A)q91(B)wM);q4
-Ldj;}
-h8}
-qG
-TailCall_cEqual:g5
-w8:oL
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Ldk
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Ldk;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Ldl;qG
-TailCall_cExp:g5
-w2
-qS
-hS
-gM
-wB(404,aF
-mL,q21"[fp_exp(x)]"
-wH,wN);q4
-Ldm;qT
-cLog:A=dE
-wB(340,wJ
-mG
-mL,"A"
-,aI(A)wM);q4
-oN
-hM
-wB(154,"x"
-mL,"[fp_exp(x)]"
-,wN);q4
-Ldo;}
-qH
-TailCall_cExp2:g5
-cExp2:qS
-hS
-gM
-wB(405,aF
-q31,"cExp2 [fp_exp2(x)]"
-wH,wN);q4
-Ldp;qT
-cLog2:A=dE
-wB(341,wJ
-aN
-q31,"A"
-,aI(A)wM);q4
-oN
-hM
-wB(155,"x"
-q31,"[fp_exp2(x)]"
-,wN);q4
-Ldq;}
-wB(479,"cExp2"
-,"[DO_STACKPLUS1] [fp_log(Value_t(2))]"
-wH
-mL,);incStackPtr();--mStackPtr;q4
-Lea;TailCall_cFloor:g5
-cFloor:qS
-hI
-wB(401,m0
-mS,q01
-aA,);q4
-Leb
-gY
-wB(136,"x "
-mS,"[fp_floor(x)]"
-,wN);q4
-Lec
-gS
-wB(395,"A[IsAlwaysIntegerOpcode(A)] "
-mS,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cGreater:g5
-o1:qY
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Led;}
-g8-oO
-wB(431,"x[x==Value_t(-0.5)] "
-m2,m0
-aS,wN);q4
-Lee;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-dB
-cAbs){wB(427,mV" x[x!=Value_t(0)] "
-aG,"[Value_t(0.5)/x]"
-wH" "
-aJ,wN);q4
-Lef;}
-}
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Leg;}
-g8
-oO
-wB(430,"x[x==Value_t(0.5)] "
-aG,"cAbsNotNot"
-,wN);q4
-Leh;qG
-TailCall_cHypot:g5
-cHypot
-d4
-dF==cSinCos){wB(84,"cSinCos cHypot"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lci;}
-qH
-TailCall_cInt:g5
-cInt:qS
-hM
-wB(137,"x cInt"
-,"[fp_int(x)]"
-,wN);q4
-Lei
-gS
-wB(397,"A[IsAlwaysIntegerOpcode(A)] cInt"
-,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cInv:g5
-cInv:qS
-cCos:wB(256,aO" "
-aU,"cSec"
-,);q4
-Lej
-qU
-cCot:wB(260,"cCot "
-aU,mR,);q4
-Lcp
-qU
-cCsc:wB(258,"cCsc "
-aU,mP,);q4
-Lek
-qU
-cInv:wB(62,aU" "
-aU,,);q4
-Ldn
-qU
-cPow:wB(355,q61
-aU,m0"cPow"
-,);q4
-Lel
-qU
-cSec:wB(259,"cSec "
-aU,aO,);q4
-Lem
-qU
-cSin:wB(255,mP" "
-aU,"cCsc"
-,);q4
-Len
-qU
-cSqrt:wB(206,q51" "
-aU,"cRSqrt"
-,);q4
-Leo
-qU
-cTan:wB(257,mR" "
-aU,"cCot"
-,);q4
-Lep
-gY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Leq;h8}
-qH
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);q4
-Lfa;}
-}
-dB
-cAbs){wB(426,mV" x[x!=Value_t(0)] "
-mJ,"[Value_t(0.5)/x]"
-wH
-a0,wN);q4
-Lfb;}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lfc;}
-g8
-oO
-wB(429,"x[x==Value_t(0.5)] "
-mJ,aS,wN);q4
-Lfd;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:qY
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lfe;}
-g8-oO
-wB(432,"x[x==Value_t(-0.5)] "
-aR,m0"cAbsNotNot"
-,wN);q4
-Lff;qG
-TailCall_cLog:g5
-cLog:mT(343,q21
-mG,,);q4
-Ldn
-qU
-gL
-wB(491,mU
-mG,mG" [fp_log(x)]"
-aZ,wN);q4
-Lfg;}
-o2
-wB(303,q41
-mG,mV" "
-mG" "
-aH,);q4
-Lfh
-aV(156,wQ" "
-mG,"[fp_log(x)]"
-,wN);q4
-Lfi;h8}
-qH
-TailCall_cLog10:g5
-cLog10:mT(481,q21
-aL,"[DO_STACKPLUS1] [fp_log10(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfj
-qU
-gL
-wB(492,mU
-aL,aL" [fp_log10(x)]"
-aZ,wN);q4
-Lfk;}
-o2
-wB(305,q41
-aL,mV" "
-aL" "
-aH,);q4
-Lfl
-aV(157,wQ" "
-aL,"[fp_log10(x)]"
-,wN);q4
-Lfm;h8}
-qH
-TailCall_cLog2:g5
-cLog2:mT(480,q21
-aN,"[DO_STACKPLUS1] [fp_log2(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfn
-qU
-cExp2:wB(344,"cExp2 "
-aN,,);q4
-Ldn
-qU
-gL
-wB(490,mU
-aN,aN" [fp_log2(x)]"
-aZ,wN);q4
-Lfo;}
-o2
-wB(304,q41
-aN,mV" "
-aN" "
-aH,);q4
-Lfp
-aV(158,wQ" "
-aN,"[fp_log2(x)]"
-,wN);q4
-Lfq;h8}
-qH
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);q4
-Ldn
-gY
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lga;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);q4
-oN
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);q4
-Ldn;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);q4
-Ldn
-gY
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lgb;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);q4
-oN
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);q4
-Ldn;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lgc;}
-qG
-TailCall_cMul:g5
-h3:qS
-cCsc:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(508,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cCsc"
-wH,"B cCot"
-,aI(A)q91(B)wM);q4
-Lgd;}
-}
-}
-q4
-dY
-qU
-cDup:wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lge
-qU
-cInv:wB(214,aU
-wH,"cDiv"
-,);q4
-Lgf
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lgg;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgh;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lgi;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lgj;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lgk;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lgl;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgm;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgn;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lgj;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lgo;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lgp;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lgq;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup
-d4
-x+oU
-wB(316,"cDup[x+x==Value_t(1)]"
-aZ
-a7,,wN);q4
-Lha;}
-wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lhb
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lhc;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Lhd;qT
-cDeg:wB(209,"cDeg"
-a7,"[RadiansToDegrees(x)]"
-wH,wN);q4
-Lhe
-qU
-cDiv
-oB
-qV
-o5
-4
-qZ
-mW(278,"y"
-wH" "
-aX
-mH,m3
-qH1,wA","
-a8(B)<<","
-a1);q4
-Lhf;qT
-hI
-wB(279,m0
-aX
-mH,mI
-qH1,wA","
-a8(B)wM);q4
-Lhg
-qU
-q6:mW(277,aY
-aX
-mH,"[y*x] B"
-mF,wA","
-a8(B)<<","
-a1);q4
-Lhh;}
-qT
-h3:qQ
-hE
-d3
-3
-h1
-if(x+oU
-wB(318,"cDup[x+x==Value_t(1)]"
-aZ
-wH
-a7,"cMul"
-,wN);q4
-Lhi;}
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Lhj;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lhk;}
-if((y*x)==fp_const_rad_to_deg
-h7
-wB(307,"y[(y*x)==fp_const_rad_to_deg<Value_t>()]"
-wH
-a7,"cDeg"
-,q81);q4
-Ldd;}
-if((y*x)==fp_const_deg_to_rad
-h7
-wB(308,"y[(y*x)==fp_const_deg_to_rad<Value_t>()]"
-wH
-a7,"cRad"
-,q81);q4
-Lde;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Lhl;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Lhm
-qU
-cRDiv:qQ
-hE
-qV
-o5
-3
-qZ
-mW(285,"y"
-wH
-a9
-a7,m3
-a9,q81);q4
-Lhn;qT
-hI
-wB(286,qC1
-a9
-a7,mI
-a9,wN);q4
-Lho
-qU
-q6:mW(284,"y"
-a9
-a7,"[y*x]"
-a9,q81);q4
-Lhp;qT
-cRad:wB(210,"cRad"
-a7,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lhq
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lia;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Lib;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lba;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Lic;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Lid;}
-if(x==fp_const_rad_to_deg
-h7
-wB(207,"x[x==fp_const_rad_to_deg<Value_t>()]"
-wH,"cDeg"
-,wN);q4
-Lie;}
-if(x==fp_const_deg_to_rad
-h7
-wB(208,"x[x==fp_const_deg_to_rad<Value_t>()]"
-wH,"cRad"
-,wN);q4
-Lif;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-cDiv:hC
-wB(274,aX"cDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-qH1,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Lig;}
-q4
-d5
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgh;}
-q4
-dZ;g7
-dZ:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Lih;}
-}
-q4
-d5
-hI
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lgg;}
-q4
-d5
-cRDiv
-hL
-qZ
-qC
-wB(267,"x"
-a9" "
-wS,"[DO_STACKPLUS1] "
-mK
-a9,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lii;}
-wB(281,"cRDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-a9,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lij;g7
-Default4:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lge;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lik;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:oL
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Lil
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Lil;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Lim;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Lin;qT
-hI
-wB(61,qC1
-aA,,);q4
-Ldn
-qU
-cSin:g9
-wB(244,"x"
-wH" "
-mP
-aA,mI" "
-mP,wN);q4
-Lio;}
-qT
-oQ
-g9
-wB(245,"x"
-wH" cSinh"
-aA,mI" cSinh"
-,wN);q4
-Lip;}
-qT
-cTan:g9
-wB(246,"x"
-wH" "
-mR
-aA,mI" "
-mR,wN);q4
-Liq;}
-qT
-cTanh:g9
-wB(247,"x"
-wH" cTanh"
-aA,mI" cTanh"
-,wN);q4
-Lja;}
-qT
-hM
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Ljb;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbs:wB(227,mV
-a0,"cNot"
-,);q4
-Ljc
-qU
-cAbsNot:A=dD
-wB(389,"A[IsLogicalOpcode(A)] "
-aS
-a0,"A"
-,aI(A)wM);q4
-Ldn;}
-if(A!=q6){wB(390,"A[A!=cImmed] "
-aS
-a0,"A cAbsNotNot"
-,aI(A)wM);q4
-Ljd;}
-q4
-o0
-qU
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Lje
-qU
-w8:wB(220,aE
-a0,wW,);q4
-Ljf
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Ljg
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Ljh
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Lji
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Ljj
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Ljk
-oF
-wB(226,qC1
-a0,"cNot"
-,);q4
-Ljc
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbd
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Ljc
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Ljl;g7
-o0:;A=dF
-qR
-qX
-wB(391,wJ"cNot"
-,"A "
-aS,aI(A)wM);q4
-Ljm;qG
-TailCall_cNotNot:g5
-dS
-d4
-dF==cNot){wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-w7
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Ljn;h8}
-qH
-TailCall_cPow:g5
-cPow:qY
-if(!h5
-x+x)){oY
-cSqr){wB(22,q41"x[!isEvenInteger(x+x)] cPow"
-,mV" [x+x] cPow"
-,wN);q4
-Ljo;}
-}
-if(isInteger(x
-gQ
-w2
-wB(43,q21
-wT,wX
-mL,wN);q4
-Ljp
-qU
-cExp2:wB(44,"cExp2 "
-wT,wX
-q31,wN);q4
-Ljq
-qU
-cPow
-hL
-qZ
-hP!isInteger(y)){wB(42,"y[!isInteger(y)] "
-q61
-wT,aP,q81);q4
-Lka;}
-}
-wB(45,q61
-wT,wX" cPow"
-,wN);q4
-Lkb;}
-}
-if(h5
-x
-hU
-wB(434,mV" x[isEvenInteger(x)] cPow"
-,"[x] cPow"
-,wN);q4
-Lkc
-qU
-h3
-hL]==cAbs){wB(435,mV
-wH" x[isEvenInteger(x)] cPow"
-,"cMul [x] cPow"
-,wN);q4
-Lkd;h8}
-}
-g8)){wB(83,"x[x==Value_t()] cPow"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,wN);q4
-Lke;}
-g8
-oO
-wB(332,"x[x==Value_t(0.5)] cPow"
-,q51,wN);q4
-Lkf;}
-g8
-1)/g1
-3)){wB(333,"x[x==Value_t(1)/Value_t(3)] cPow"
-,"cCbrt"
-,wN);q4
-Lkg;}
-g8
-1)/g1-3)){wB(334,"x[x==Value_t(1)/Value_t(-3)] cPow"
-,"cCbrt "
-aU,wN);q4
-Lkh;}
-g8-oO
-wB(335,"x[x==Value_t(-0.5)] cPow"
-,"cRSqrt"
-,wN);q4
-Lki;}
-g8-oG
-wB(336,"x[x==Value_t(-1)] cPow"
-,aU,wN);q4
-Lkj;}
-qQ
-h9
-cPow
-hL
-qZ
-hP
-h5
-y)&&!h5
-x*y)){wB(21,"y[isEvenInteger(y)&&!isEvenInteger(x*y)] "
-q61
-m8,mV" "
-aP,q81);q4
-Lkk;}
-wB(330,aY
-q61
-m8,aP,q81);q4
-Lka;o2
-wB(46,q41
-m8,"[x+x] cPow"
-,wN);q4
-Lkl
-qU
-q6:hP
-y!=oP||x>=oP){wB(165,"y[y!=Value_t(0)||x>=Value_t(0)] "
-m8,"[fp_pow(y,x)]"
-,q81);q4
-Lkm;h8}
-wB(455,m8,"[DO_POWI]"
-,wN)qR
-TryCompilePowi(x))gJ}
-qH
-TailCall_cRDiv:g5
-cRDiv:qS
-cSinCos:wB(503,"cSinCos"
-a9,"cCot"
-,);q4
-Lep
-qU
-cSinhCosh:wB(510,"cSinhCosh"
-a9,"cTanh "
-aU,);q4
-Lkn
-gY
-g8
-oG
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Lkj;h8}
-qH
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Lko;}
-qH
-TailCall_cRad:g5
-cRad:qS
-h3
-gM
-wB(211,"x"
-wH" cRad"
-,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lkp;qT
-hM
-wB(134,"x cRad"
-,"[DegreesToRadians(x)]"
-,wN);q4
-Lkq;}
-qH
-TailCall_cSec:g5
-cSec:A=qN
-qQ
-h9
-cCos:hD
-wB(497,aK" "
-aO" "
-wI"cSec"
-,"B "
-aO" "
-aT,aI(A)q91(B)wM);q4
-Lbp;qT
-cSin:hD
-wB(495,aK" "
-mP" "
-wI"cSec"
-,"B cSinCos "
-aU,aI(A)q91(B)wM);q4
-Lla;h8
-qG
-TailCall_cSin:g5
-cSin:qS
-hI
-wB(240,m0
-mP,mP
-aA,);q4
-Llb
-gY
-wB(159,"x "
-mP,"[fp_sin(x)]"
-,wN);q4
-Llc;oH
-qN
-oY
-cCsc
-q11(499,aK" cCsc "
-wI
-mP,"B cCsc "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-}
-qG
-TailCall_cSinh:g5
-oQ
-qS
-cAcosh:wB(437,"cAcosh cSinh"
-,"[DO_STACKPLUS1] "
-q41"[Value_t(-1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lld
-qU
-cAsinh:wB(349,"cAsinh cSinh"
-,,);q4
-Ldn
-oF
-wB(241,m0"cSinh"
-,"cSinh"
-aA,);q4
-Lle
-gY
-wB(160,"x cSinh"
-,"[fp_sinh(x)]"
-,wN);q4
-Llf;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Llg
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Llg
-qU
-cSqrt:A=dE
-wB(338,wJ
-q51" cSqr"
-,"A"
-,aI(A)wM);q4
-Ldn;h8}
-qH
-TailCall_cSqrt:g5
-cSqrt:qS
-hS
-d4
-qK
-o3
-A=hE
-w0
-if(oC
-o3
-wB(512,"cSqr"
-a3
-q41
-aQ,"A cHypot"
-,aI(A)wM);q4
-Llh;}
-}
-B
-g4
-gV
-B)){A=oC
-w0
-if(qL
-4]o3
-wB(513,"cSqr"
-a3"B[IsUnaryOpcode(B)] "
-q41
-aQ,"A B cHypot"
-," with"
-a8(B)qE1(A)wM);q4
-Lli;}
-}
-}
-o2
-wB(23,q41
-q51,mV,);q4
-Llj
-gY
-if(x>=oP){wB(161,"x[x>=Value_t(0)] "
-q51,"[fp_sqrt(x)]"
-,wN);q4
-Llk;h8}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Lko
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Lll
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lba;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Llm;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lln
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Llo;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Llp;}
-qG
-TailCall_cTan:g5
-cTan:qS
-cAtan2:wB(354,"cAtan2 "
-mR,"cDiv"
-,);q4
-Lgf
-oF
-wB(242,m0
-mR,mR
-aA,);q4
-Llq
-gY
-wB(163,"x "
-mR,"[fp_tan(x)]"
-,wN);q4
-Lma;oH
-qN
-oY
-cCot
-q11(501,aK" cCot "
-wI
-mR,"B cCot "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-}
-qG
-TailCall_cTanh:g5
-cTanh:qS
-hI
-wB(243,m0"cTanh"
-,"cTanh"
-aA,);q4
-Lmb
-gY
-wB(164,"x cTanh"
-,"[fp_tanh(x)]"
-,wN);q4
-Lmc;}
-qH
-TailCall_cTrunc:g5
-cTrunc:qS
-hM
-wB(138,"x cTrunc"
-,"[fp_trunc(x)]"
-,wN);q4
-Lmd
-gS
-wB(394,"A[IsAlwaysIntegerOpcode(A)] cTrunc"
-,"A"
-,aI(A)wM);gJ
-qG
-g7
-Default0:;A=w5
-qR
-IsComparisonOpcode(h2
-qY
-hK
-qZ
-mW(364,aY"cAdd"
-wF,"[x-y] A"
-,aI(A)qD1<<","
-a1);q4
-Lme;qT
-cAtan
-d4
-dP<fp_const_pi<dH>()*g1
-oO
-wB(380,"cAtan[fp_abs(x)<fp_const_pi<Value_t>()*Value_t(0.5)]"
-wF,"[fp_tan(x)] A"
-,aI(A)qD1
-wM);q4
-Lmf;qT
-cExp
-d4
-dO
-wB(370,"cExp[x>Value_t(0)]"
-wF,"[fp_log(x)] A"
-,aI(A)qD1
-wM);q4
-Lmg;qT
-cExp2
-d4
-dO
-wB(371,"cExp2[x>Value_t(0)]"
-wF,"[fp_log2(x)] A"
-,aI(A)qD1
-wM);q4
-Lmh;qT
-cLog:g3
-wB(373,wP
-mG
-wF,"B [fp_exp(x)] A"
-,aI(A)qD1
-q91(B)wM);q4
-Lmi;qT
-cLog10:g3
-wB(375,wP
-aL
-wF,"B [fp_pow(Value_t(10),x)] A"
-,aI(A)qD1
-q91(B)wM);q4
-Lmj;qT
-cLog2:g3
-wB(374,wP
-aN
-wF,"B [fp_exp2(x)] A"
-,aI(A)qD1
-q91(B)wM);q4
-Lmk;qT
-h3
-hL
-qZ
-hP
-y>oP){wB(366,"y[y>Value_t(0)]"
-wH
-wF,"[x/y] A"
-,aI(A)qD1<<","
-a1);q4
-Lml;}
-if(y<oP){wB(367,"y[y<Value_t(0)]"
-wH
-wF,"[x/y] {OppositeComparisonOpcode(A)}"
-,aI(A)qD1<<","
-a1);q4
-Lmm;}
-qT
-hI
-wB(365,qC1
-wF,"[-x] {OppositeComparisonOpcode(A)}"
-,aI(A)qD1
-wM);q4
-Lmn
-qU
-cPow
-d4
-x>oP
-gA
-qZ
-hP
-y>oP){wB(368,"y[y>Value_t(0)] cPow[x>Value_t(0)]"
-wF,"[fp_pow(x,Value_t(1)/y)] A"
-,aI(A)qD1<<","
-a1);q4
-Lmo;}
-}
-qT
-oQ
-wB(381,"cSinh"
-wF,"[fp_asinh(x)] A"
-,aI(A)qD1
-wM);q4
-Lmp
-qU
-cSqr
-d4
-dO
-wB(369,"cSqr[x>Value_t(0)]"
-wF,mV" [fp_sqrt(x)] A"
-,aI(A)qD1
-wM);q4
-Lmq;qT
-cTanh
-d4
-dP<m7(382,"cTanh[fp_abs(x)<Value_t(1)]"
-wF,"[fp_atanh(x)] A"
-,aI(A)qD1
-wM);q4
-Lna;h8}
-}
-}
-if(d1
-A
-qP
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lnb;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lnc;}
-}
-}
-}
-C=w5
-qR
-IsCommutativeOrParamSwappableBinaryOpcode(C)){qS
-cSin:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(505,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] "
-mP" C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinCos {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Lnd;}
-}
-qT
-oQ
-A=qK
-w1
-3
-gA]==cCosh){B=hQ
-wB(506,aK" "
-aM" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cSinh C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinhCosh {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Lne;}
-}
-h8}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-Lnf:wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:q7=fp_acos
-m6
-Lae:q7=fp_acosh
-m6
-Laf:oZ
-4));gG
-Lng:w5=h3;Lnh:g0
-Lni:wE(cMul);q4
-TailCall_cMul;Lag:hV
-4
-dT
-oZ
-4));Lnj:qW
-q6
-hA
-Lah:q7=x+g1
-1);gG
-Lfa:w5=h3;q4
-Lni;Lai:gU
-cSub;Lnk:wE(cSub);q4
-TailCall_cSub;Laj:hW
-2
-gH
-Lnl:g0
-Lnm:wE(cAdd);q4
-TailCall_cAdd;Lak:hW
-oR
-Lnn:qE
-hS);Lno:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Lal:o9;qL
-2
-gK
-q4
-Lnn;Lam:hW
-2
-gH
-q4
-Lno;Lan:hW
-4
-gH
-Lnp:qE
-hS);Lnq:qE
-B);Loa:w5=cSub;g0
-q4
-Lnk;Lao:o9;oC=q6
-q9
-oR
-q4
-Lnp;Lap:hW
-oR
-q4
-Lnq;Laq:gT
-y+x;Lba:qM
-Ldn:q5
-gJ
-Lbb:q8
-oV
-o7
-x
-q71
-gX
-Lnn;Lbc:mM
-A
-gX
-Lnn;Lbd:gU
-dS;Lob:wE(cNotNot);q4
-TailCall_cNotNot;Lbe:gT
-fp_and(x
-d6
-Lbf:q7=fp_asin
-m6
-Lbg:q7=fp_asinh
-m6
-Lbh:q7=fp_atan
-m6
-Lbi:gT
-fp_atan2(gW
-Lbj:q7=fp_atanh
-m6
-Lbk:q7=fp_cbrt
-m6
-Lbl:q1
-cFloor);Loc:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lbm:q7=fp_ceil
-m6
-Lbn:g6
-Lod:wE(cCos);q4
-TailCall_cCos;Lbo:q7=fp_cos
-m6
-Lbp:dF=cDup;w5=cInv;Loe:wE(cInv);q4
-TailCall_cInv;Lbq:mM
-cSinCos);gJ
-Lca:g6
-wE(cCosh);q4
-TailCall_cCosh;Lcb:q1
-cSqr
-o7
-g1
-1));Lof:qW
-q6
-oJ
-hS);Log:w5=cSqrt;g0
-wE(cSqrt);q4
-TailCall_cSqrt;Lcc:q7=fp_cosh
-m6
-Lcd:mM
-cSinhCosh);gJ
-Lce:q7=RadiansToDegrees
-m6
-Lcf:q1
-cSec
-hA
-Lcg:q1
-cTan
-hA
-Lch:q1
-cSin
-hA
-Lci:oZ));dF
-dJ
-Loh:qE
-dU
-oZ
-1));Loi:qW
-q6);Loj:w5=hS;q4
-Lnl;Lcj:q1
-cNeg
-oJ
-cExp
-hA
-Lck:q1
-cNeg
-oJ
-cExp2
-hA
-Lcl:g6
-q4
-Lfa;Lcm:q1
-cNeg
-oJ
-cPow
-hA
-Lcn:q1
-cCos
-hA
-Lco:q1
-cCsc
-hA
-Lcp:gU
-cTan;Lok:wE(cTan);q4
-TailCall_cTan;Lcq:gU
-cTanh;Lol:wE(cTanh);q4
-TailCall_cTanh;Lda:q1
-cCot
-hA
-Ldb:o9;dI
-Lom:wE(cDiv);q4
-TailCall_cDiv;Ldc:gT
-y/x;q4
-Lba;Ldd:qF1
-q8
-oR
-Lon:w5=cDeg;g0
-wE(cDeg);q4
-TailCall_cDeg;Lde:qF1
-q8
-oR
-Loo:w5=cRad;g0
-wE(cRad);q4
-TailCall_cRad;Ldf:gT
-y/x;dG
-Lng;Ldg:q7=g1
-1)/x;q4
-Lfa;Ldh:mM
-oI
-Lop:g0
-q4
-Lom;Ldi:q8
-3
-gC
-oI
-qF
-x
-q71);Loq:w5=cRDiv;g0
-wE(cRDiv);q4
-TailCall_cRDiv;Ldj:hV
-3
-gC
-oI
-qE
-B
-gX
-Loq;Ldk:dI
-Lpa:wE(cEqual);q4
-TailCall_cEqual;Ldl:gT
-fp_equal(gW
-Ldm:d7
-cExp
-o7
-fp_exp(x)gX
-Lnj;Ldo:q7=fp_exp
-m6
-Ldp:d7
-cExp2
-o7
-fp_exp2(x)gX
-Lnj;Ldq:q7=fp_exp2
-m6
-Lea:qF
-oW
-g1
-2))q71);Lpb:qE
-h3
-gI
-cExp;g0
-wE(cExp);q4
-TailCall_cExp;Leb:q1
-cCeil
-gX
-Loc;Lec:q7=fp_floor
-m6
-Led:gT
-fp_less(x
-d6
-Lee:qM
-q1
-cNeg);Ljm:qE
-cAbsNot);gJ
-Lef:q7=g1
-0.5)/x;qK=d8
-dS;g0
-q4
-Lob;Leg:gT
-fp_lessOrEq(x
-d6
-Leh:qM
-Ljd:q5
-Lpc:qE
-cAbsNotNot);gJ
-Lei:q7=fp_int
-m6
-Lej:gU
-cSec;wE(cSec);q4
-TailCall_cSec;Lek:gU
-cSin;Lpd:wE(cSin);q4
-TailCall_cSin;Lel:q1
-cNeg
-gI
-cPow;Lpe:g0
-Lpf:wE(cPow);q4
-TailCall_cPow;Lem:gU
-cCos;q4
-Lod;Len:gU
-cCsc;wE(cCsc);q4
-TailCall_cCsc;Leo:q1
-cRSqrt);gJ
-Lep:g6
-Lpg:w5=cCot;wE(cCot);q4
-TailCall_cCot;Leq:q7=g1
-1)/x;gJ
-Lfb:q7=g1
-0.5)/x;qK=d8
-cNot;g0
-Lph:wE(cNot);q4
-TailCall_cNot;Lfc:gT
-fp_less(gW
-Lfd:qM
-Lje:w3
-Ljm;Lfe:gT
-fp_lessOrEq(gW
-Lff:qM
-q1
-cNeg
-gX
-Lpc;Lfg:d7
-cLog
-o7
-oW
-x)o8
-Lfh:q1
-dQ
-qE
-cLog);Lpi:qW
-cDup
-gX
-Loj;Lfi:q7=oW
-x);gJ
-Lfj:qF
-dR
-fp_const_e<dH>()));Lpj:dF
-dJ
-q4
-Lng;Lfk:d7
-cLog10
-o7
-dR
-x)o8
-Lfl:q1
-dQ
-qE
-cLog10
-gX
-Lpi;Lfm:q7=dR
-x);gJ
-Lfn:qF
-o4
-fp_const_e<dH>())gX
-Lpj;Lfo:d7
-cLog2
-o7
-o4
-x)o8
-Lfp:q1
-dQ
-qE
-cLog2
-gX
-Lpi;Lfq:q7=o4
-x);gJ
-Lga:gT
-fp_max(x
-d6
-Lgb:gT
-fp_min(x
-d6
-Lgc:gT
-fp_mod(gW
-Lgd:hV
-oR
-q0-=3;q4
-Lpg;Lge:gU
-cSqr;Lpk:wE(cSqr);q4
-TailCall_cSqr;Lgf:gU
-cDiv;q4
-Lom;Lgg:mM
-cSqr
-gX
-Loc;Lgh:hV
-3
-gC
-cSqr);dM
-Loc;Lgi:q7=x+g1
-1);gG
-w5=cPow;q4
-Lpf;Lgj:gG
-q4
-Lni;Lgk:gT
-x;Lpl:dG
-Lnh;Lgl:qF1
-qM
-Lpm:hV
-4
-gH
-Lpn:o6
-x);Lpo:qW
-q6
-gX
-Lnh;Lgm:qM
-q4
-Lpm;Lgn:q8
-4
-gC
-B
-gX
-Lpn;Lgo:q8
-oR
-q4
-Lpn;Lgp:qK
-dJ
-q4
-Ldn;Lgq:dI
-q4
-Lni;Lha:qM
-Lpp:hV
-oR
-gJ
-Lhb:q7=x+x;q4
-Lgj;Lhc:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Loj;Lhd:gT
-x;d7
-dU
-qF
-y*x
-o8
-Lhe:q7=RadiansToDegrees(x
-gX
-Lgq;Lhf:qG1
-q8
-4
-gH
-Lpq:qE
-dU
-Lqa:qE
-B
-gI
-cDiv;q4
-Lop;Lhg:o9;oC=q6
-q9
-oR
-q4
-Lpq;Lhh:qG1
-q8
-oR
-q4
-Lqa;Lhi:q8
-4
-gH
-q4
-Lnh;Lhj:q8
-4
-dT
-qF
-x+x
-gX
-Lpo;Lhk:qF1
-qM
-q4
-Lpp;Lhl:qG1
-q4
-Lpl;Lhm:o9;q4
-Lgq;Lhn:qG1
-q8
-oR
-Lqb:dM
-Loq;Lho:o9;qL
-2
-gK
-q4
-Lqb;Lhp:qG1
-dG
-Loq;Lhq:q7=h4
-gX
-Lgq;Lia:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Loa;Lib:qG1
-q4
-Lba;Lic:qM
-w3
-Loc;Lid:dF=cDup;dW-=1;qM
-Lqc:w5=hS;q4
-Lnm;Lie:qM
-w3
-Lon;Lif:qM
-w3
-Loo;Lig:hV
-oV
-gX
-Lpq;Lih:hV
-2
-gH
-Lqd:qE
-cSqr
-gX
-Lnh;Lii:q8
-oV
-o7
-x
-q71
-gX
-Lqb;Lij:mM
-A
-gX
-Lqb;Lik:hV
-oR
-q4
-Lqd;Lil:dI
-Lqe:wE(cNEqual);q4
-TailCall_cNEqual;Lim:gT
-fp_nequal(gW
-Lin:o9;q4
-Lcl;Lio:o9
-gB
-cSin;g0
-q4
-Lpd;Lip:o9
-gB
-cSinh;g0
-wE(cSinh);q4
-TailCall_cSinh;Liq:o9
-gB
-cTan;g0
-q4
-Lok;Lja:o9
-gB
-cTanh;g0
-q4
-Lol;Ljb:o9;gJ
-Ljc:g6
-q4
-Lph;Ljf:gU
-cNEqual;q4
-Lqe;Ljg:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Ljh:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Lji:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Ljj:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Ljk:gU
-w8;q4
-Lpa;Ljl:q7=fp_not
-m6
-Ljn:gT
-fp_or(x
-d6
-Ljo:d7
-dQ
-qF
-x+x);Lqf:qW
-q6
-gX
-Lpe;Ljp:dL
-Lpb;Ljq:qK=d8
-cExp2;g0
-wE(cExp2);q4
-TailCall_cExp2;Lka:qG1
-dG
-Lpe;Lkb:qK
-dJ
-q1
-h3
-gX
-Lpe;Lkc:dI
-q4
-Lpf;Lkd:q8
-3
-dT
-qF
-x
-gX
-Lqf;Lke:q7=g1
-gX
-Loh;Lkf:qM
-w3
-Log;Lkg:qM
-q5
-w5=cCbrt;g0
-wE(cCbrt);q4
-TailCall_cCbrt;Lkh:qM
-q1
-cCbrt);Lqg:w5=cInv;g0
-q4
-Loe;Lki:qM
-q4
-Leo;Lkj:qM
-w3
-Lqg;Lkk:qF1
-q8
-3
-gC
-dQ
-qF
-y*x
-gX
-Lqf;Lkl:q7=x+x;q4
-Lkc;Lkm:gT
-oX
-gW
-Lkn:q1
-cTanh
-gX
-Lqg;Lko:oZ)gX
-Lpj;Lkp:q7=h4
-gX
-Lcl;Lkq:q7=h4);gJ
-Lla:mM
-cSinCos
-gX
-Lqg;Llb:q1
-cSin
-gX
-Loc;Llc:q7=fp_sin
-m6
-Lld:q1
-cSqr
-o7
-g1-1)gX
-Lof;Lle:q1
-cSinh
-gX
-Loc;Llf:q7=fp_sinh
-m6
-Llg:g6
-q4
-Lpk;Llh:hV
-4
-gC
-A);Lqh:w5=cHypot;g0
-wE(cHypot);q4
-TailCall_cHypot;Lli:hV
-5
-gC
-A
-oJ
-B
-gX
-Lqh;Llj:gU
-cAbs;q4
-Lnf;Llk:q7=fp_sqrt
-m6
-Lll:g6
-q4
-Lqc;Llm:gT
-y-x;q4
-Lba;Lln:o9;q4
-Lqc;Llo:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lno;Llp:mM
-A
-oJ
-cSub
-gX
-Lno;Llq:q1
-cTan
-gX
-Loc;Lma:q7=fp_tan
-m6
-Lmb:q1
-cTanh
-gX
-Loc;Lmc:q7=fp_tanh
-m6
-Lmd:q7=fp_trunc
-m6
-Lme:gT
-x-y;Lqi:q8
-2
-gH
-Lqj:qE
-A);gJ
-Lmf:q7=fp_tan(x);Lqk:dL
-Lqj;Lmg:q7=oW
-x
-gX
-Lqk;Lmh:q7=o4
-x
-gX
-Lqk;Lmi:q7=fp_exp(x
-gX
-Lqk;Lmj:q7=oX
-g1
-10),x
-gX
-Lqk;Lmk:q7=fp_exp2(x
-gX
-Lqk;Lml:gT
-x/y;q4
-Lqi;Lmm:gT
-x/y;q8
-2
-gH
-Lql:qE
-OppositeComparisonOpcode(A));gJ
-Lmn:o9;dL
-Lql;Lmo:gT
-oX
-x,g1
-1)/y
-gX
-Lqi;Lmp:q7=fp_asinh(x
-gX
-Lqk;Lmq:d7
-dQ
-qF
-fp_sqrt(x)q71
-gX
-Lqj;Lna:q7=fp_atanh(x
-gX
-Lqk;Lnb:qW
-cDup);gJ
-Lnc:dF=cDup;gJ
-Lnd:hV
-3
-gC
-cSinCos);Lqm:qE
-GetParamSwappedBinaryOpcode(C));gJ
-Lne:hV
-3
-gC
-cSinhCosh
-gX
-Lqm;gJ
-q4
-TailCall_cAcos;q4
-TailCall_cAcosh;q4
-TailCall_cAnd;q4
-TailCall_cAsin;q4
-TailCall_cAsinh;q4
-TailCall_cAtan;q4
-TailCall_cAtan2;q4
-TailCall_cAtanh;q4
-TailCall_cCeil;q4
-TailCall_cFloor;q4
-TailCall_cInt;q4
-TailCall_cLog;q4
-TailCall_cLog10;q4
-TailCall_cLog2;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cOr;q4
-TailCall_cRDiv;q4
-TailCall_cRad;q4
-TailCall_cSec;q4
-TailCall_cSin;q4
-TailCall_cSinh;q4
-TailCall_cSqrt;q4
-TailCall_cSub;q4
-TailCall_cTan;q4
-TailCall_cTanh;q4
-TailCall_cTrunc;
-#endif
-#if((FP_COMPLEX_VERSION) && (FP_FLOAT_VERSION))
-dH
-x;dH
-gE
-A;hT
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0}
-qH
-TailCall_cAcos:g5
-cAcos:qY
-wB(172,"x cAcos"
-,"[fp_acos(x)]"
-,wN);q4
-Lad;}
-qH
-TailCall_cAcosh:g5
-cAcosh:qY
-wB(169,"x cAcosh"
-,"[fp_acosh(x)]"
-,wN);q4
-Lae;}
-qH
-TailCall_cAdd:g5
-hG
-Laf;qT
-h3
-hL]==hS){if(qL
-gZ
-Lag;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Lah;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lai
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Laj;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lak;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Lal
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lam;qT
-oA
-Lan;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lao
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lap;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Laq;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lba;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lbb;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lbc;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-w7
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbe;h8}
-qH
-TailCall_cArg:g5
-cArg:qY
-wB(190,"x cArg"
-,"[fp_arg(x)]"
-,wN);q4
-Lbf;}
-qH
-TailCall_cAsin:g5
-cAsin:qY
-wB(173,"x cAsin"
-,"[fp_asin(x)]"
-,wN);q4
-Lbg;}
-qH
-TailCall_cAsinh:g5
-cAsinh:qY
-wB(170,"x cAsinh"
-,"[fp_asinh(x)]"
-,wN);q4
-Lbh;}
-qH
-TailCall_cAtan:g5
-cAtan:qY
-if(g1
-x.real(),fp_abs(x.imag()))!=g1
-0,oG
-wB(174,"x[Value_t(x.real(),fp_abs(x.imag()))!=Value_t(0,1)] cAtan"
-,"[fp_atan(x)]"
-,wN);q4
-Lbi;qG
-TailCall_cAtan2:g5
-cAtan2:qY
-m9(139,mA"cAtan2"
-,"[fp_atan2(y,x)]"
-,q81);q4
-Lbj;qG
-TailCall_cAtanh:g5
-cAtanh:qY
-if(g1
-fp_abs(x.real()),x.imag())!=g1
-1,0)){wB(171,"x[Value_t(fp_abs(x.real()),x.imag())!=Value_t(1,0)] cAtanh"
-,"[fp_atanh(x)]"
-,wN);q4
-Lbk;qG
-TailCall_cCbrt:g5
-cCbrt:qY
-wB(175,"x cCbrt"
-,"[fp_cbrt(x)]"
-,wN);q4
-Lbl;}
-qH
-TailCall_cCeil:g5
-cCeil:qS
-hI
-wB(402,m0
-q01,mS
-aA,);q4
-Lbm
-gY
-wB(135,"x "
-q01,"[fp_ceil(x)]"
-,wN);q4
-Lbn
-gS
-wB(396,"A[IsAlwaysIntegerOpcode(A)] "
-q01,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cConj:g5
-cConj:qS
-cConj:wB(63,mY" "
-mY,,);oS
-gY
-wB(193,"x "
-mY,"[fp_conj(x)]"
-,wN);q4
-Lbp;}
-qH
-TailCall_cCos:g5
-cCos:qS
-cAcos:wB(346,"cAcos "
-aO,,);q4
-oE
-wB(238,m0
-aO,aO,);q4
-Lbq
-gY
-wB(176,"x "
-aO,"[fp_cos(x)]"
-,wN);q4
-Lca;oH
-qN
-qQ
-h9
-cSec:hD
-wB(500,aK" cSec "
-wI
-aO,"B cSec "
-aT,aI(A)q91(B)wM);q4
-Lcb;qT
-cSin:hD
-wB(494,aK" "
-mP" "
-wI
-aO,"B cSinCos"
-,aI(A)q91(B)wM);q4
-Lcc;h8}
-qG
-TailCall_cCosh:g5
-cCosh:qS
-cAsinh:wB(450,"cAsinh "
-aM,"[DO_STACKPLUS1] "
-q41"[Value_t(1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lcd
-oF
-wB(239,m0
-aM,aM,);q4
-Lce
-gY
-wB(177,"x "
-aM,"[fp_cosh(x)]"
-,wN);q4
-Lcf;oH
-qN
-oY
-cSinh
-q11(507,aK" cSinh "
-wI
-aM,"B cSinhCosh"
-,aI(A)q91(B)wM);q4
-Lcg;}
-}
-qG
-TailCall_cCot:g5
-cCot:A=qN
-oY
-cTan
-q11(498,aK" "
-mR" "
-wI"cCot"
-,"B "
-mR" "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-qG
-TailCall_cCsc:g5
-cCsc:A=qN
-oY
-cSin
-q11(496,aK" "
-mP" "
-wI"cCsc"
-,"B "
-mP" "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-qG
-TailCall_cDeg:g5
-cDeg:qY
-wB(133,"x cDeg"
-,"[RadiansToDegrees(x)]"
-,wN);q4
-Lch;}
-qH
-TailCall_cDiv:g5
-cDiv:qS
-cCos:wB(250,aO
-mF,"cSec"
-wH,);q4
-Lci
-qU
-cCot:wB(254,"cCot"
-mF,mR
-wH,);q4
-Lcj
-qU
-cCsc:wB(252,"cCsc"
-mF,mP
-wH,);q4
-Lck
-qU
-cDup:wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lcl
-qU
-w2
-wB(408,"cExp"
-mF,m0"cExp"
-wH,);q4
-Lcm
-qU
-cExp2:wB(409,"cExp2"
-mF,m0"cExp2"
-wH,);q4
-Lcn
-qU
-cInv:wB(213,aU
-mF,"cMul"
-,);q4
-Lco
-qU
-cPow:wB(407,"cPow"
-mF,m0"cPow"
-wH,);q4
-Lcp
-qU
-cSec:wB(253,"cSec"
-mF,aO
-wH,);q4
-Lcq
-qU
-cSin:wB(249,mP
-mF,"cCsc"
-wH,);q4
-Lda
-qU
-cSinCos:wB(502,"cSinCos"
-mF,mR,);q4
-Ldb
-qU
-cSinhCosh:wB(509,"cSinhCosh"
-mF,"cTanh"
-,);q4
-Ldc
-qU
-cTan:wB(251,mR
-mF,"cCot"
-wH,);q4
-Ldd
-gY
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Lde
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Ldf;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lba;}
-dB
-h3
-gA
-qZ
-hP(y/x)==fp_const_rad_to_deg
-h7
-wB(321,"y[(y/x)==fp_const_rad_to_deg<Value_t>()]"
-wH" "
-wR,"cDeg"
-,q81);q4
-Ldg;}
-if((y/x)==fp_const_deg_to_rad
-h7
-wB(322,"y[(y/x)==fp_const_deg_to_rad<Value_t>()]"
-wH" "
-wR,"cRad"
-,q81);q4
-Ldh;}
-wB(323,"y"
-wH" "
-wR,"[y/x]"
-wH,q81);q4
-Ldi;}
-}
-wB(325,wR,"[Value_t(1)/x]"
-wH,wN);q4
-Ldj;}
-gP
-cDiv:hC
-wB(271,aX"cDiv "
-wV,"[DO_STACKPLUS1] B A"
-wH
-mF,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Ldk;qT
-cRDiv:qQ
-hE
-qV
-hM
-wB(266,"x"
-a9" "
-wV,"A"
-wH" [x]"
-a9,aI(A)qD1
-wM);q4
-Ldl;g7
-hC
-wB(265,"B[IsVarOpcode(B)]"
-a9" "
-wV,"A"
-wH" B"
-a9,aI(A)q91(B)wM);q4
-Ldm;}
-h8}
-qG
-TailCall_cEqual:g5
-w8:oL
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Ldn
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Ldn;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Ldo;qG
-TailCall_cExp:g5
-w2
-qS
-hS
-gM
-wB(404,aF
-mL,q21"[fp_exp(x)]"
-wH,wN);q4
-Ldp;qT
-cLog:A=dE
-wB(340,wJ
-mG
-mL,"A"
-,aI(A)wM);oS;qT
-hM
-wB(178,"x"
-mL,"[fp_exp(x)]"
-,wN);q4
-Ldq;}
-qH
-TailCall_cExp2:g5
-cExp2:qS
-hS
-gM
-wB(405,aF
-q31,"cExp2 [fp_exp2(x)]"
-wH,wN);q4
-Lea;qT
-cLog2:A=dE
-wB(341,wJ
-aN
-q31,"A"
-,aI(A)wM);oS;qT
-hM
-wB(179,"x"
-q31,"[fp_exp2(x)]"
-,wN);q4
-Leb;}
-wB(479,"cExp2"
-,"[DO_STACKPLUS1] [fp_log(Value_t(2))]"
-wH
-mL,);incStackPtr();--mStackPtr;q4
-Lec;TailCall_cFloor:g5
-cFloor:qS
-hI
-wB(401,m0
-mS,q01
-aA,);q4
-Led
-gY
-wB(136,"x "
-mS,"[fp_floor(x)]"
-,wN);q4
-Lee
-gS
-wB(395,"A[IsAlwaysIntegerOpcode(A)] "
-mS,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cGreater:g5
-o1:qY
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Lef;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Leg;qG
-TailCall_cHypot:g5
-cHypot
-d4
-dF==cSinCos){wB(84,"cSinCos cHypot"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lcl;}
-qH
-TailCall_cImag:g5
-cImag:qS
-cAbs:wB(81,mV" "
-mZ,"[Value_t()]"
-wH,);q4
-Leh
-qU
-cReal:wB(80,"cReal "
-mZ,"[Value_t()]"
-wH,);q4
-Leh
-gY
-wB(192,"x "
-mZ,"[fp_imag(x)]"
-,wN);q4
-Lei;}
-qH
-TailCall_cInt:g5
-cInt:qS
-hM
-wB(137,"x cInt"
-,"[fp_int(x)]"
-,wN);q4
-Lej
-gS
-wB(397,"A[IsAlwaysIntegerOpcode(A)] cInt"
-,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cInv:g5
-cInv:qS
-cCos:wB(256,aO" "
-aU,"cSec"
-,);q4
-Lek
-qU
-cCot:wB(260,"cCot "
-aU,mR,);q4
-Ldb
-qU
-cCsc:wB(258,"cCsc "
-aU,mP,);q4
-Lel
-qU
-cInv:wB(62,aU" "
-aU,,);oS
-qU
-cPow:wB(355,q61
-aU,m0"cPow"
-,);q4
-Lem
-qU
-cSec:wB(259,"cSec "
-aU,aO,);q4
-Len
-qU
-cSin:wB(255,mP" "
-aU,"cCsc"
-,);q4
-Leo
-qU
-cSqrt:wB(206,q51" "
-aU,"cRSqrt"
-,);q4
-Lep
-qU
-cTan:wB(257,mR" "
-aU,"cCot"
-,);q4
-Leq
-gY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Lfa;h8}
-qH
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);q4
-Lfb;}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lfc;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:qY
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lfd;qG
-TailCall_cLog:g5
-cLog:mT(343,q21
-mG,,);oS
-qU
-gL
-wB(491,mU
-mG,mG" [fp_log(x)]"
-aZ,wN);q4
-Lfe;}
-oD
-wB(180,qA1
-mG,"[fp_log(x)]"
-,wN);q4
-Lff;h8}
-qH
-TailCall_cLog10:g5
-cLog10:mT(481,q21
-aL,"[DO_STACKPLUS1] [fp_log10(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfg
-qU
-gL
-wB(492,mU
-aL,aL" [fp_log10(x)]"
-aZ,wN);q4
-Lfh;}
-oD
-wB(181,qA1
-aL,"[fp_log10(x)]"
-,wN);q4
-Lfi;h8}
-qH
-TailCall_cLog2:g5
-cLog2:mT(480,q21
-aN,"[DO_STACKPLUS1] [fp_log2(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfj
-qU
-cExp2:wB(344,"cExp2 "
-aN,,);oS
-qU
-gL
-wB(490,mU
-aN,aN" [fp_log2(x)]"
-aZ,wN);q4
-Lfk;}
-oD
-wB(182,qA1
-aN,"[fp_log2(x)]"
-,wN);q4
-Lfl;h8}
-qH
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);oS
-gY
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lfm;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);oS;qT
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);oS;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);oS
-gY
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lfn;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);oS;qT
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);oS;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lfo;}
-qG
-TailCall_cMul:g5
-h3:qS
-cCsc:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(508,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cCsc"
-wH,"B cCot"
-,aI(A)q91(B)wM);q4
-Lfp;}
-}
-}
-q4
-dY
-qU
-cDup:wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lfq
-qU
-cInv:wB(214,aU
-wH,"cDiv"
-,);q4
-Lga
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lgb;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgc;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lgd;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lge;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lgf;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lgg;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgh;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgi;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lge;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lgj;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lgk;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lgl;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup
-d4
-x+oU
-wB(316,"cDup[x+x==Value_t(1)]"
-aZ
-a7,,wN);q4
-Lgm;}
-wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lgn
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lgo;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Lgp;qT
-cDeg:wB(209,"cDeg"
-a7,"[RadiansToDegrees(x)]"
-wH,wN);q4
-Lgq
-qU
-cDiv
-oB
-qV
-o5
-4
-qZ
-mW(278,"y"
-wH" "
-aX
-mH,m3
-qH1,wA","
-a8(B)<<","
-a1);q4
-Lha;qT
-hI
-wB(279,m0
-aX
-mH,mI
-qH1,wA","
-a8(B)wM);q4
-Lhb
-qU
-q6:mW(277,aY
-aX
-mH,"[y*x] B"
-mF,wA","
-a8(B)<<","
-a1);q4
-Lhc;}
-qT
-h3:qQ
-hE
-d3
-3
-h1
-if(x+oU
-wB(318,"cDup[x+x==Value_t(1)]"
-aZ
-wH
-a7,"cMul"
-,wN);q4
-Lhd;}
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Lhe;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lhf;}
-if((y*x)==fp_const_rad_to_deg
-h7
-wB(307,"y[(y*x)==fp_const_rad_to_deg<Value_t>()]"
-wH
-a7,"cDeg"
-,q81);q4
-Ldg;}
-if((y*x)==fp_const_deg_to_rad
-h7
-wB(308,"y[(y*x)==fp_const_deg_to_rad<Value_t>()]"
-wH
-a7,"cRad"
-,q81);q4
-Ldh;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Lhg;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Lhh
-qU
-cRDiv:qQ
-hE
-qV
-o5
-3
-qZ
-mW(285,"y"
-wH
-a9
-a7,m3
-a9,q81);q4
-Lhi;qT
-hI
-wB(286,qC1
-a9
-a7,mI
-a9,wN);q4
-Lhj
-qU
-q6:mW(284,"y"
-a9
-a7,"[y*x]"
-a9,q81);q4
-Lhk;qT
-cRad:wB(210,"cRad"
-a7,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lhl
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lhm;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Lhn;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lba;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Lho;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Lhp;}
-if(x==fp_const_rad_to_deg
-h7
-wB(207,"x[x==fp_const_rad_to_deg<Value_t>()]"
-wH,"cDeg"
-,wN);q4
-Lhq;}
-if(x==fp_const_deg_to_rad
-h7
-wB(208,"x[x==fp_const_deg_to_rad<Value_t>()]"
-wH,"cRad"
-,wN);q4
-Lia;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-cDiv:hC
-wB(274,aX"cDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-qH1,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Lib;}
-q4
-d5
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgc;}
-q4
-dZ;g7
-dZ:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Lic;}
-}
-q4
-d5
-hI
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lgb;}
-q4
-d5
-cRDiv
-hL
-qZ
-qC
-wB(267,"x"
-a9" "
-wS,"[DO_STACKPLUS1] "
-mK
-a9,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lid;}
-wB(281,"cRDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-a9,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lie;g7
-Default4:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lfq;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lif;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:oL
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Lig
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Lig;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Lih;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Lii;qT
-hI
-wB(61,qC1
-aA,,);oS
-qU
-cSin:g9
-wB(244,"x"
-wH" "
-mP
-aA,mI" "
-mP,wN);q4
-Lij;}
-qT
-oQ
-g9
-wB(245,"x"
-wH" cSinh"
-aA,mI" cSinh"
-,wN);q4
-Lik;}
-qT
-cTan:g9
-wB(246,"x"
-wH" "
-mR
-aA,mI" "
-mR,wN);q4
-Lil;}
-qT
-cTanh:g9
-wB(247,"x"
-wH" cTanh"
-aA,mI" cTanh"
-,wN);q4
-Lim;}
-qT
-hM
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Lin;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Lio
-qU
-w8:wB(220,aE
-a0,wW,);q4
-Lip
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Liq
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Lja
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Ljb
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Ljc
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Ljd
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbd
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Lje
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Ljf;}
-qH
-TailCall_cNotNot:g5
-dS
-d4
-dF==cNot){wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-w7
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Ljg;h8}
-qH
-TailCall_cPolar:g5
-cPolar
-d4
-q0[0
-qZ
-y=q7;qJ
-x
-gO
-wB(194,"x "
-aY"cPolar"
-,"[fp_polar(x,y)]"
-," with "
-aY"= "
-<<y
-qD1
-wM);q4
-Ljh;qG
-TailCall_cPow:g5
-cPow:qY
-if(isInteger(x
-gQ
-w2
-wB(43,q21
-wT,wX
-mL,wN);q4
-Lji
-qU
-cExp2:wB(44,"cExp2 "
-wT,wX
-q31,wN);q4
-Ljj
-qU
-cPow
-hL
-qZ
-hP!isInteger(y)){wB(42,"y[!isInteger(y)] "
-q61
-wT,aP,q81);q4
-Ljk;}
-}
-wB(45,q61
-wT,wX" cPow"
-,wN);q4
-Ljl;}
-}
-g8)){wB(83,"x[x==Value_t()] cPow"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,wN);q4
-Ljm;}
-g8
-oO
-wB(332,"x[x==Value_t(0.5)] cPow"
-,q51,wN);q4
-Ljn;}
-g8
-1)/g1
-3)){wB(333,"x[x==Value_t(1)/Value_t(3)] cPow"
-,"cCbrt"
-,wN);q4
-Ljo;}
-g8
-1)/g1-3)){wB(334,"x[x==Value_t(1)/Value_t(-3)] cPow"
-,"cCbrt "
-aU,wN);q4
-Ljp;}
-g8-oO
-wB(335,"x[x==Value_t(-0.5)] cPow"
-,"cRSqrt"
-,wN);q4
-Ljq;}
-g8-oG
-wB(336,"x[x==Value_t(-1)] cPow"
-,aU,wN);q4
-Lka;}
-qQ
-h9
-cPow
-hL
-qZ
-mW(330,aY
-q61
-m8,aP,q81);q4
-Ljk;o2
-wB(46,q41
-m8,"[x+x] cPow"
-,wN);q4
-Lkb
-qU
-q6:mW(189,aY
-m8,"[fp_pow(y,x)]"
-,q81);q4
-Lkc;}
-wB(455,m8,"[DO_POWI]"
-,wN)qR
-TryCompilePowi(x))gJ}
-qH
-TailCall_cRDiv:g5
-cRDiv:qS
-cSinCos:wB(503,"cSinCos"
-a9,"cCot"
-,);q4
-Leq
-qU
-cSinhCosh:wB(510,"cSinhCosh"
-a9,"cTanh "
-aU,);q4
-Lkd
-gY
-g8
-oG
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Lka;h8}
-qH
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Leh;}
-qH
-TailCall_cRad:g5
-cRad:qS
-h3
-gM
-wB(211,"x"
-wH" cRad"
-,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lke;qT
-hM
-wB(134,"x cRad"
-,"[DegreesToRadians(x)]"
-,wN);q4
-Lkf;}
-qH
-TailCall_cReal:g5
-cReal:qY
-wB(191,"x cReal"
-,"[fp_real(x)]"
-,wN);q4
-Lkg;}
-qH
-TailCall_cSec:g5
-cSec:A=qN
-qQ
-h9
-cCos:hD
-wB(497,aK" "
-aO" "
-wI"cSec"
-,"B "
-aO" "
-aT,aI(A)q91(B)wM);q4
-Lcb;qT
-cSin:hD
-wB(495,aK" "
-mP" "
-wI"cSec"
-,"B cSinCos "
-aU,aI(A)q91(B)wM);q4
-Lkh;h8
-qG
-TailCall_cSin:g5
-cSin:qS
-cAsin:wB(345,"cAsin "
-mP,,);q4
-oE
-wB(240,m0
-mP,mP
-aA,);q4
-Lki
-gY
-wB(183,"x "
-mP,"[fp_sin(x)]"
-,wN);q4
-Lkj;oH
-qN
-oY
-cCsc
-q11(499,aK" cCsc "
-wI
-mP,"B cCsc "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-}
-qG
-TailCall_cSinh:g5
-oQ
-qS
-cAcosh:wB(437,"cAcosh cSinh"
-,"[DO_STACKPLUS1] "
-q41"[Value_t(-1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lkk
-qU
-cAsinh:wB(349,"cAsinh cSinh"
-,,);q4
-oE
-wB(241,m0"cSinh"
-,"cSinh"
-aA,);q4
-Lkl
-gY
-wB(184,"x cSinh"
-,"[fp_sinh(x)]"
-,wN);q4
-Lkm;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Lkn
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Lkn
-qU
-cSqrt:A=dE
-wB(338,wJ
-q51" cSqr"
-,"A"
-,aI(A)wM);oS;h8}
-qH
-TailCall_cSqrt:g5
-cSqrt:qS
-hS
-d4
-qK
-o3
-A=hE
-w0
-if(oC
-o3
-wB(512,"cSqr"
-a3
-q41
-aQ,"A cHypot"
-,aI(A)wM);q4
-Lko;}
-}
-B
-g4
-gV
-B)){A=oC
-w0
-if(qL
-4]o3
-wB(513,"cSqr"
-a3"B[IsUnaryOpcode(B)] "
-q41
-aQ,"A B cHypot"
-," with"
-a8(B)qE1(A)wM);q4
-Lkp;}
-}
-}
-o2
-wB(23,q41
-q51,mV,);q4
-Lkq
-gY
-wB(185,"x "
-q51,"[fp_sqrt(x)]"
-,wN);q4
-Lla;}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Leh
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Llb
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lba;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Llc;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lld
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Lle;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Llf;}
-qG
-TailCall_cTan:g5
-cTan:qS
-cAtan2:wB(354,"cAtan2 "
-mR,"cDiv"
-,);q4
-Lga
-oF
-wB(242,m0
-mR,mR
-aA,);q4
-Llg
-gY
-wB(187,"x "
-mR,"[fp_tan(x)]"
-,wN);q4
-Llh;oH
-qN
-oY
-cCot
-q11(501,aK" cCot "
-wI
-mR,"B cCot "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-}
-qG
-TailCall_cTanh:g5
-cTanh:qS
-cAtanh:wB(352,"cAtanh cTanh"
-,,);q4
-oE
-wB(243,m0"cTanh"
-,"cTanh"
-aA,);q4
-Lli
-gY
-wB(188,"x cTanh"
-,"[fp_tanh(x)]"
-,wN);q4
-Llj;}
-qH
-TailCall_cTrunc:g5
-cTrunc:qS
-hM
-wB(138,"x cTrunc"
-,"[fp_trunc(x)]"
-,wN);q4
-Llk
-gS
-wB(394,"A[IsAlwaysIntegerOpcode(A)] cTrunc"
-,"A"
-,aI(A)wM);gJ
-qG
-g7
-Default0:;A=w5
-w1
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lll;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Llm;}
-}
-}
-}
-C=w5
-qR
-IsCommutativeOrParamSwappableBinaryOpcode(C)){qS
-cSin:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(505,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] "
-mP" C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinCos {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Lln;}
-}
-qT
-oQ
-A=qK
-w1
-3
-gA]==cCosh){B=hQ
-wB(506,aK" "
-aM" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cSinh C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinhCosh {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Llo;}
-}
-h8}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-Llp:wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:q7=fp_acos
-m6
-Lae:q7=fp_acosh
-m6
-Laf:oZ
-4));gG
-Llq:w5=h3;Lma:g0
-Lmb:wE(cMul);q4
-TailCall_cMul;Lag:hV
-4
-dT
-oZ
-4));Lmc:qW
-q6
-hY;Lah:q7=x+g1
-1);gG
-Lfb:w5=h3;q4
-Lmb;Lai:gU
-cSub;Lmd:wE(cSub);q4
-TailCall_cSub;Laj:hW
-2
-gH
-Lme:g0
-Lmf:wE(cAdd);q4
-TailCall_cAdd;Lak:hW
-oR
-Lmg:qE
-hS);Lmh:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Lal:o9;qL
-2
-gK
-q4
-Lmg;Lam:hW
-2
-gH
-q4
-Lmh;Lan:hW
-4
-gH
-Lmi:qE
-hS);Lmj:qE
-B);Lmk:w5=cSub;g0
-q4
-Lmd;Lao:o9;oC=q6
-q9
-oR
-q4
-Lmi;Lap:hW
-oR
-q4
-Lmj;Laq:gT
-y+x;Lba:qM
-Lbo:q5
-gJ
-Lbb:q8
-oV
-o7
-x
-q71
-gX
-Lmg;Lbc:mM
-A
-gX
-Lmg;Lbd:gU
-dS;wE(cNotNot);q4
-TailCall_cNotNot;Lbe:gT
-fp_and(x
-d6
-Lbf:q7=fp_arg
-m6
-Lbg:q7=fp_asin
-m6
-Lbh:q7=fp_asinh
-m6
-Lbi:q7=fp_atan
-m6
-Lbj:gT
-fp_atan2(gW
-Lbk:q7=fp_atanh
-m6
-Lbl:q7=fp_cbrt
-m6
-Lbm:q1
-cFloor);Lml:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lbn:q7=fp_ceil
-m6
-Lbp:q7=fp_conj
-m6
-Lbq:g6
-Lmm:wE(cCos);q4
-TailCall_cCos;Lca:q7=fp_cos
-m6
-Lcb:dF=cDup;w5=cInv;Lmn:wE(cInv);q4
-TailCall_cInv;Lcc:mM
-cSinCos);gJ
-Lcd:q1
-cSqr
-o7
-g1
-1));Lmo:qW
-q6
-oJ
-hS);Lmp:w5=cSqrt;g0
-wE(cSqrt);q4
-TailCall_cSqrt;Lce:g6
-wE(cCosh);q4
-TailCall_cCosh;Lcf:q7=fp_cosh
-m6
-Lcg:mM
-cSinhCosh);gJ
-Lch:q7=RadiansToDegrees
-m6
-Lci:q1
-cSec
-hY;Lcj:q1
-cTan
-hY;Lck:q1
-cSin
-hY;Lcl:oZ));dF
-dJ
-Lmq:qE
-dU
-oZ
-1));Lna:qW
-q6);Lnb:w5=hS;q4
-Lme;Lcm:q1
-cNeg
-oJ
-cExp
-hY;Lcn:q1
-cNeg
-oJ
-cExp2
-hY;Lco:g6
-q4
-Lfb;Lcp:q1
-cNeg
-oJ
-cPow
-hY;Lcq:q1
-cCos
-hY;Lda:q1
-cCsc
-hY;Ldb:gU
-cTan;Lnc:wE(cTan);q4
-TailCall_cTan;Ldc:gU
-cTanh;Lnd:wE(cTanh);q4
-TailCall_cTanh;Ldd:q1
-cCot
-hY;Lde:o9;dI
-Lne:wE(cDiv);q4
-TailCall_cDiv;Ldf:gT
-y/x;q4
-Lba;Ldg:qF1
-q8
-oR
-Lnf:w5=cDeg;g0
-wE(cDeg);q4
-TailCall_cDeg;Ldh:qF1
-q8
-oR
-Lng:w5=cRad;g0
-wE(cRad);q4
-TailCall_cRad;Ldi:gT
-y/x;dG
-Llq;Ldj:q7=g1
-1)/x;q4
-Lfb;Ldk:mM
-oI
-Lnh:g0
-q4
-Lne;Ldl:q8
-3
-gC
-oI
-qF
-x
-q71);Lni:w5=cRDiv;g0
-wE(cRDiv);q4
-TailCall_cRDiv;Ldm:hV
-3
-gC
-oI
-qE
-B
-gX
-Lni;Ldn:dI
-Lnj:wE(cEqual);q4
-TailCall_cEqual;Ldo:gT
-fp_equal(gW
-Ldp:d7
-cExp
-o7
-fp_exp(x)gX
-Lmc;Ldq:q7=fp_exp
-m6
-Lea:d7
-cExp2
-o7
-fp_exp2(x)gX
-Lmc;Leb:q7=fp_exp2
-m6
-Lec:qF
-oW
-g1
-2))q71);Lnk:qE
-h3
-gI
-cExp;g0
-wE(cExp);q4
-TailCall_cExp;Led:q1
-cCeil
-oT
-Lee:q7=fp_floor
-m6
-Lef:gT
-fp_less(x
-d6
-Leg:gT
-fp_lessOrEq(x
-d6
-Leh:oZ));Lnl:dF
-dJ
-q4
-Llq;Lei:q7=fp_imag
-m6
-Lej:q7=fp_int
-m6
-Lek:gU
-cSec;wE(cSec);q4
-TailCall_cSec;Lel:gU
-cSin;Lnm:wE(cSin);q4
-TailCall_cSin;Lem:q1
-cNeg
-gI
-cPow;Lnn:g0
-Lno:wE(cPow);q4
-TailCall_cPow;Len:gU
-cCos;q4
-Lmm;Leo:gU
-cCsc;wE(cCsc);q4
-TailCall_cCsc;Lep:q1
-cRSqrt);gJ
-Leq:g6
-Lnp:w5=cCot;wE(cCot);q4
-TailCall_cCot;Lfa:q7=g1
-1)/x;gJ
-Lfc:gT
-fp_less(gW
-Lfd:gT
-fp_lessOrEq(gW
-Lfe:d7
-cLog
-o7
-oW
-x)gX
-Lna;Lff:q7=oW
-x);gJ
-Lfg:qF
-dR
-fp_const_e<dH>())gX
-Lnl;Lfh:d7
-cLog10
-o7
-dR
-x)gX
-Lna;Lfi:q7=dR
-x);gJ
-Lfj:qF
-o4
-fp_const_e<dH>())gX
-Lnl;Lfk:d7
-cLog2
-o7
-o4
-x)gX
-Lna;Lfl:q7=o4
-x);gJ
-Lfm:gT
-fp_max(x
-d6
-Lfn:gT
-fp_min(x
-d6
-Lfo:gT
-fp_mod(gW
-Lfp:hV
-oR
-q0-=3;q4
-Lnp;Lfq:gU
-cSqr;Lnq:wE(cSqr);q4
-TailCall_cSqr;Lga:gU
-cDiv;q4
-Lne;Lgb:mM
-cSqr
-oT
-Lgc:hV
-3
-gC
-cSqr);dM
-Lml;Lgd:q7=x+g1
-1);gG
-w5=cPow;q4
-Lno;Lge:gG
-q4
-Lmb;Lgf:gT
-x;Loa:dG
-Lma;Lgg:qF1
-qM
-Lob:hV
-4
-gH
-Loc:o6
-x);Lod:qW
-q6
-gX
-Lma;Lgh:qM
-q4
-Lob;Lgi:q8
-4
-gC
-B
-gX
-Loc;Lgj:q8
-oR
-q4
-Loc;Lgk:qK
-dJ
-oS;Lgl:dI
-q4
-Lmb;Lgm:qM
-Loe:hV
-oR
-gJ
-Lgn:q7=x+x;q4
-Lge;Lgo:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lnb;Lgp:gT
-x;d7
-dU
-qF
-y*x
-gX
-Lna;Lgq:q7=RadiansToDegrees(x
-gX
-Lgl;Lha:qG1
-q8
-4
-gH
-Lof:qE
-dU
-Log:qE
-B
-gI
-cDiv;q4
-Lnh;Lhb:o9;oC=q6
-q9
-oR
-q4
-Lof;Lhc:qG1
-q8
-oR
-q4
-Log;Lhd:q8
-4
-gH
-q4
-Lma;Lhe:q8
-4
-dT
-qF
-x+x
-gX
-Lod;Lhf:qF1
-qM
-q4
-Loe;Lhg:qG1
-q4
-Loa;Lhh:o9;q4
-Lgl;Lhi:qG1
-q8
-oR
-Loh:dM
-Lni;Lhj:o9;qL
-2
-gK
-q4
-Loh;Lhk:qG1
-dG
-Lni;Lhl:q7=h4
-gX
-Lgl;Lhm:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lmk;Lhn:qG1
-q4
-Lba;Lho:qM
-w3
-Lml;Lhp:dF=cDup;dW-=1;qM
-Loi:w5=hS;q4
-Lmf;Lhq:qM
-w3
-Lnf;Lia:qM
-w3
-Lng;Lib:hV
-oV
-gX
-Lof;Lic:hV
-2
-gH
-Loj:qE
-cSqr
-gX
-Lma;Lid:q8
-oV
-o7
-x
-q71
-gX
-Loh;Lie:mM
-A
-gX
-Loh;Lif:hV
-oR
-q4
-Loj;Lig:dI
-Lok:wE(cNEqual);q4
-TailCall_cNEqual;Lih:gT
-fp_nequal(gW
-Lii:o9;q4
-Lco;Lij:o9
-gB
-cSin;g0
-q4
-Lnm;Lik:o9
-gB
-cSinh;g0
-wE(cSinh);q4
-TailCall_cSinh;Lil:o9
-gB
-cTan;g0
-q4
-Lnc;Lim:o9
-gB
-cTanh;g0
-q4
-Lnd;Lin:o9;gJ
-Lio:q1
-cAbsNot);gJ
-Lip:gU
-cNEqual;q4
-Lok;Liq:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Lja:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Ljb:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Ljc:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Ljd:gU
-w8;q4
-Lnj;Lje:g6
-wE(cNot);q4
-TailCall_cNot;Ljf:q7=fp_not
-m6
-Ljg:gT
-fp_or(x
-d6
-Ljh:gT
-fp_polar(x
-d6
-Lji:dL
-Lnk;Ljj:qK=d8
-cExp2;g0
-wE(cExp2);q4
-TailCall_cExp2;Ljk:qG1
-dG
-Lnn;Ljl:qK
-dJ
-q1
-h3
-gX
-Lnn;Ljm:q7=g1
-gX
-Lmq;Ljn:qM
-w3
-Lmp;Ljo:qM
-q5
-w5=cCbrt;g0
-wE(cCbrt);q4
-TailCall_cCbrt;Ljp:qM
-q1
-cCbrt);Lol:w5=cInv;g0
-q4
-Lmn;Ljq:qM
-q4
-Lep;Lka:qM
-w3
-Lol;Lkb:q7=x+x;dI
-q4
-Lno;Lkc:gT
-oX
-gW
-Lkd:q1
-cTanh
-gX
-Lol;Lke:q7=h4
-gX
-Lco;Lkf:q7=h4);gJ
-Lkg:q7=fp_real
-m6
-Lkh:mM
-cSinCos
-gX
-Lol;Lki:q1
-cSin
-oT
-Lkj:q7=fp_sin
-m6
-Lkk:q1
-cSqr
-o7
-g1-1)gX
-Lmo;Lkl:q1
-cSinh
-oT
-Lkm:q7=fp_sinh
-m6
-Lkn:g6
-q4
-Lnq;Lko:hV
-4
-gC
-A);Lom:w5=cHypot;g0
-wE(cHypot);q4
-TailCall_cHypot;Lkp:hV
-5
-gC
-A
-oJ
-B
-gX
-Lom;Lkq:gU
-cAbs;q4
-Llp;Lla:q7=fp_sqrt
-m6
-Llb:g6
-q4
-Loi;Llc:gT
-y-x;q4
-Lba;Lld:o9;q4
-Loi;Lle:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lmh;Llf:mM
-A
-oJ
-cSub
-gX
-Lmh;Llg:q1
-cTan
-oT
-Llh:q7=fp_tan
-m6
-Lli:q1
-cTanh
-oT
-Llj:q7=fp_tanh
-m6
-Llk:q7=fp_trunc
-m6
-Lll:qW
-cDup);gJ
-Llm:dF=cDup;gJ
-Lln:hV
-3
-gC
-cSinCos);Lon:qE
-GetParamSwappedBinaryOpcode(C));gJ
-Llo:hV
-3
-gC
-cSinhCosh
-gX
-Lon;gJ
-q4
-TailCall_cAcos;q4
-TailCall_cAcosh;q4
-TailCall_cAnd;q4
-TailCall_cArg;q4
-TailCall_cAsin;q4
-TailCall_cAsinh;q4
-TailCall_cAtan;q4
-TailCall_cAtan2;q4
-TailCall_cAtanh;q4
-TailCall_cCeil;q4
-TailCall_cConj;q4
-TailCall_cFloor;q4
-TailCall_cImag;q4
-TailCall_cInt;q4
-TailCall_cLog;q4
-TailCall_cLog10;q4
-TailCall_cLog2;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cOr;q4
-TailCall_cPolar;q4
-TailCall_cRDiv;q4
-TailCall_cRad;q4
-TailCall_cReal;q4
-TailCall_cSec;q4
-TailCall_cSin;q4
-TailCall_cSinh;q4
-TailCall_cSqrt;q4
-TailCall_cSub;q4
-TailCall_cTan;q4
-TailCall_cTanh;q4
-TailCall_cTrunc;
-#endif
-#undef FP_ReDefinePointers
-#undef FP_TRACE_BYTECODE_OPTIMIZATION
-#undef FP_TRACE_OPCODENAME
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-// NOTE:
-// This file contains only internal types for the function parser library.
-// You don't need to include this file in your code. Include "fparser.hh"
-// only.
-
-#ifndef ONCE_FPARSER_AUX_H_
-#define ONCE_FPARSER_AUX_H_
-
-#include "fptypes.hh"
-
-#include <cmath>
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-#include "mpfr/MpfrFloat.hh"
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-#include "mpfr/GmpInt.hh"
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
-#include <complex>
-#endif
-
-#ifdef ONCE_FPARSER_H_
-namespace FUNCTIONPARSERTYPES
-{
- template<typename>
- struct IsIntType
- {
- enum { result = false };
- };
- template<>
- struct IsIntType<long>
- {
- enum { result = true };
- };
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<>
- struct IsIntType<GmpInt>
- {
- enum { result = true };
- };
-#endif
-
- template<typename>
- struct IsComplexType
- {
- enum { result = false };
- };
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- template<typename T>
- struct IsComplexType<std::complex<T> >
- {
- enum { result = true };
- };
-#endif
-
-
-//==========================================================================
-// Constants
-//==========================================================================
- template<typename Value_t>
- inline Value_t fp_const_pi() // CONSTANT_PI
- {
- return Value_t(3.1415926535897932384626433832795028841971693993751L);
- }
-
- template<typename Value_t>
- inline Value_t fp_const_e() // CONSTANT_E
- {
- return Value_t(2.7182818284590452353602874713526624977572L);
- }
- template<typename Value_t>
- inline Value_t fp_const_einv() // CONSTANT_EI
- {
- return Value_t(0.367879441171442321595523770161460867445811131L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log2() // CONSTANT_L2, CONSTANT_L2EI
- {
- return Value_t(0.69314718055994530941723212145817656807550013436025525412L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log10() // CONSTANT_L10, CONSTANT_L10EI
- {
- return Value_t(2.302585092994045684017991454684364207601101488628772976L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log2inv() // CONSTANT_L2I, CONSTANT_L2E
- {
- return Value_t(1.442695040888963407359924681001892137426645954L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log10inv() // CONSTANT_L10I, CONSTANT_L10E
- {
- return Value_t(0.434294481903251827651128918916605082294397L);
- }
-
- template<typename Value_t>
- inline const Value_t& fp_const_deg_to_rad() // CONSTANT_DR
- {
- static const Value_t factor = fp_const_pi<Value_t>() / Value_t(180); // to rad from deg
- return factor;
- }
-
- template<typename Value_t>
- inline const Value_t& fp_const_rad_to_deg() // CONSTANT_RD
- {
- static const Value_t factor = Value_t(180) / fp_const_pi<Value_t>(); // to deg from rad
- return factor;
- }
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<>
- inline MpfrFloat fp_const_pi<MpfrFloat>() { return MpfrFloat::const_pi(); }
-
- template<>
- inline MpfrFloat fp_const_e<MpfrFloat>() { return MpfrFloat::const_e(); }
-
- template<>
- inline MpfrFloat fp_const_einv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_e(); }
-
- template<>
- inline MpfrFloat fp_const_log2<MpfrFloat>() { return MpfrFloat::const_log2(); }
-
- /*
- template<>
- inline MpfrFloat fp_const_log10<MpfrFloat>() { return fp_log(MpfrFloat(10)); }
-
- template<>
- inline MpfrFloat fp_const_log2inv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_log2(); }
-
- template<>
- inline MpfrFloat fp_const_log10inv<MpfrFloat>() { return fp_log10(MpfrFloat::const_e()); }
- */
-#endif
-
-
-//==========================================================================
-// Generic math functions
-//==========================================================================
- template<typename Value_t>
- inline Value_t fp_abs(const Value_t& x) { return std::fabs(x); }
-
- template<typename Value_t>
- inline Value_t fp_acos(const Value_t& x) { return std::acos(x); }
-
- template<typename Value_t>
- inline Value_t fp_asin(const Value_t& x) { return std::asin(x); }
-
- template<typename Value_t>
- inline Value_t fp_atan(const Value_t& x) { return std::atan(x); }
-
- template<typename Value_t>
- inline Value_t fp_atan2(const Value_t& x, const Value_t& y)
- { return std::atan2(x, y); }
-
- template<typename Value_t>
- inline Value_t fp_ceil(const Value_t& x) { return std::ceil(x); }
-
- template<typename Value_t>
- inline Value_t fp_cos(const Value_t& x) { return std::cos(x); }
-
- template<typename Value_t>
- inline Value_t fp_cosh(const Value_t& x) { return std::cosh(x); }
-
- template<typename Value_t>
- inline Value_t fp_exp(const Value_t& x) { return std::exp(x); }
-
- template<typename Value_t>
- inline Value_t fp_floor(const Value_t& x) { return std::floor(x); }
-
- template<typename Value_t>
- inline Value_t fp_log(const Value_t& x) { return std::log(x); }
-
- template<typename Value_t>
- inline Value_t fp_mod(const Value_t& x, const Value_t& y)
- { return std::fmod(x, y); }
-
- template<typename Value_t>
- inline Value_t fp_sin(const Value_t& x) { return std::sin(x); }
-
- template<typename Value_t>
- inline Value_t fp_sinh(const Value_t& x) { return std::sinh(x); }
-
- template<typename Value_t>
- inline Value_t fp_sqrt(const Value_t& x) { return std::sqrt(x); }
-
- template<typename Value_t>
- inline Value_t fp_tan(const Value_t& x) { return std::tan(x); }
-
- template<typename Value_t>
- inline Value_t fp_tanh(const Value_t& x) { return std::tanh(x); }
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_asinh(const Value_t& x) { return std::asinh(x); }
-
- template<typename Value_t>
- inline Value_t fp_acosh(const Value_t& x) { return std::acosh(x); }
-
- template<typename Value_t>
- inline Value_t fp_atanh(const Value_t& x) { return std::atanh(x); }
-#else
- template<typename Value_t>
- inline Value_t fp_asinh(const Value_t& x)
- { return fp_log(x + fp_sqrt(x*x + Value_t(1))); }
-
- template<typename Value_t>
- inline Value_t fp_acosh(const Value_t& x)
- { return fp_log(x + fp_sqrt(x*x - Value_t(1))); }
-
- template<typename Value_t>
- inline Value_t fp_atanh(const Value_t& x)
- {
- return fp_log( (Value_t(1)+x) / (Value_t(1)-x)) * Value_t(0.5);
- // Note: x = +1 causes division by zero
- // x = -1 causes log(0)
- // Thus, x must not be +-1
- }
-#endif // FP_SUPPORT_ASINH
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_hypot(const Value_t& x, const Value_t& y)
- { return std::hypot(x,y); }
-#else
- template<typename Value_t>
- inline Value_t fp_hypot(const Value_t& x, const Value_t& y)
- { return fp_sqrt(x*x + y*y); }
-#endif
-
- template<typename Value_t>
- inline Value_t fp_pow_base(const Value_t& x, const Value_t& y)
- { return std::pow(x, y); }
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_log2(const Value_t& x) { return std::log2(x); }
-#else
- template<typename Value_t>
- inline Value_t fp_log2(const Value_t& x)
- {
- return fp_log(x) * fp_const_log2inv<Value_t>();
- }
-#endif // FP_SUPPORT_LOG2
-
- template<typename Value_t>
- inline Value_t fp_log10(const Value_t& x)
- {
- return fp_log(x) * fp_const_log10inv<Value_t>();
- }
-
- template<typename Value_t>
- inline Value_t fp_trunc(const Value_t& x)
- {
- return x < Value_t() ? fp_ceil(x) : fp_floor(x);
- }
-
- template<typename Value_t>
- inline Value_t fp_int(const Value_t& x)
- {
- return x < Value_t() ?
- fp_ceil(x - Value_t(0.5)) : fp_floor(x + Value_t(0.5));
- }
-
- template<typename Value_t>
- inline void fp_sinCos(Value_t& sinvalue, Value_t& cosvalue,
- const Value_t& param)
- {
- // Assuming that "cosvalue" and "param" do not
- // overlap, but "sinvalue" and "param" may.
- cosvalue = fp_cos(param);
- sinvalue = fp_sin(param);
- }
-
- template<typename Value_t>
- inline void fp_sinhCosh(Value_t& sinhvalue, Value_t& coshvalue,
- const Value_t& param)
- {
- const Value_t ex(fp_exp(param)), emx(fp_exp(-param));
- sinhvalue = Value_t(0.5)*(ex-emx);
- coshvalue = Value_t(0.5)*(ex+emx);
- }
-
- template<typename Value_t>
- struct Epsilon
- {
- static Value_t value;
- static Value_t defaultValue() { return 0; }
- };
-
- template<> inline double Epsilon<double>::defaultValue() { return 1E-12; }
- template<> inline float Epsilon<float>::defaultValue() { return 1E-5F; }
- template<> inline long double Epsilon<long double>::defaultValue() { return 1E-14L; }
-
- template<> inline std::complex<double>
- Epsilon<std::complex<double> >::defaultValue() { return 1E-12; }
-
- template<> inline std::complex<float>
- Epsilon<std::complex<float> >::defaultValue() { return 1E-5F; }
-
- template<> inline std::complex<long double>
- Epsilon<std::complex<long double> >::defaultValue() { return 1E-14L; }
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<> inline MpfrFloat
- Epsilon<MpfrFloat>::defaultValue() { return MpfrFloat::someEpsilon(); }
-#endif
-
- template<typename Value_t> Value_t Epsilon<Value_t>::value =
- Epsilon<Value_t>::defaultValue();
-
-
-#ifdef _GNU_SOURCE
- inline void fp_sinCos(double& sin, double& cos, const double& a)
- {
- sincos(a, &sin, &cos);
- }
- inline void fp_sinCos(float& sin, float& cos, const float& a)
- {
- sincosf(a, &sin, &cos);
- }
- inline void fp_sinCos(long double& sin, long double& cos,
- const long double& a)
- {
- sincosl(a, &sin, &cos);
- }
-#endif
-
-
-// -------------------------------------------------------------------------
-// Long int
-// -------------------------------------------------------------------------
- inline long fp_abs(const long& x) { return x < 0 ? -x : x; }
- inline long fp_acos(const long&) { return 0; }
- inline long fp_asin(const long&) { return 0; }
- inline long fp_atan(const long&) { return 0; }
- inline long fp_atan2(const long&, const long&) { return 0; }
- inline long fp_cbrt(const long&) { return 0; }
- inline long fp_ceil(const long& x) { return x; }
- inline long fp_cos(const long&) { return 0; }
- inline long fp_cosh(const long&) { return 0; }
- inline long fp_exp(const long&) { return 0; }
- inline long fp_exp2(const long&) { return 0; }
- inline long fp_floor(const long& x) { return x; }
- inline long fp_log(const long&) { return 0; }
- inline long fp_log2(const long&) { return 0; }
- inline long fp_log10(const long&) { return 0; }
- inline long fp_mod(const long& x, const long& y) { return x % y; }
- inline long fp_pow(const long&, const long&) { return 0; }
- inline long fp_sin(const long&) { return 0; }
- inline long fp_sinh(const long&) { return 0; }
- inline long fp_sqrt(const long&) { return 1; }
- inline long fp_tan(const long&) { return 0; }
- inline long fp_tanh(const long&) { return 0; }
- inline long fp_asinh(const long&) { return 0; }
- inline long fp_acosh(const long&) { return 0; }
- inline long fp_atanh(const long&) { return 0; }
- inline long fp_pow_base(const long&, const long&) { return 0; }
- inline void fp_sinCos(long&, long&, const long&) {}
- inline void fp_sinhCosh(long&, long&, const long&) {}
-
- //template<> inline long fp_epsilon<long>() { return 0; }
-
-
-// -------------------------------------------------------------------------
-// MpfrFloat
-// -------------------------------------------------------------------------
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- inline MpfrFloat fp_abs(const MpfrFloat& x) { return MpfrFloat::abs(x); }
- inline MpfrFloat fp_acos(const MpfrFloat& x) { return MpfrFloat::acos(x); }
- inline MpfrFloat fp_acosh(const MpfrFloat& x) { return MpfrFloat::acosh(x); }
- inline MpfrFloat fp_asin(const MpfrFloat& x) { return MpfrFloat::asin(x); }
- inline MpfrFloat fp_asinh(const MpfrFloat& x) { return MpfrFloat::asinh(x); }
- inline MpfrFloat fp_atan(const MpfrFloat& x) { return MpfrFloat::atan(x); }
- inline MpfrFloat fp_atan2(const MpfrFloat& x, const MpfrFloat& y)
- { return MpfrFloat::atan2(x, y); }
- inline MpfrFloat fp_atanh(const MpfrFloat& x) { return MpfrFloat::atanh(x); }
- inline MpfrFloat fp_cbrt(const MpfrFloat& x) { return MpfrFloat::cbrt(x); }
- inline MpfrFloat fp_ceil(const MpfrFloat& x) { return MpfrFloat::ceil(x); }
- inline MpfrFloat fp_cos(const MpfrFloat& x) { return MpfrFloat::cos(x); }
- inline MpfrFloat fp_cosh(const MpfrFloat& x) { return MpfrFloat::cosh(x); }
- inline MpfrFloat fp_exp(const MpfrFloat& x) { return MpfrFloat::exp(x); }
- inline MpfrFloat fp_exp2(const MpfrFloat& x) { return MpfrFloat::exp2(x); }
- inline MpfrFloat fp_floor(const MpfrFloat& x) { return MpfrFloat::floor(x); }
- inline MpfrFloat fp_hypot(const MpfrFloat& x, const MpfrFloat& y)
- { return MpfrFloat::hypot(x, y); }
- inline MpfrFloat fp_int(const MpfrFloat& x) { return MpfrFloat::round(x); }
- inline MpfrFloat fp_log(const MpfrFloat& x) { return MpfrFloat::log(x); }
- inline MpfrFloat fp_log2(const MpfrFloat& x) { return MpfrFloat::log2(x); }
- inline MpfrFloat fp_log10(const MpfrFloat& x) { return MpfrFloat::log10(x); }
- inline MpfrFloat fp_mod(const MpfrFloat& x, const MpfrFloat& y) { return x % y; }
- inline MpfrFloat fp_sin(const MpfrFloat& x) { return MpfrFloat::sin(x); }
- inline MpfrFloat fp_sinh(const MpfrFloat& x) { return MpfrFloat::sinh(x); }
- inline MpfrFloat fp_sqrt(const MpfrFloat& x) { return MpfrFloat::sqrt(x); }
- inline MpfrFloat fp_tan(const MpfrFloat& x) { return MpfrFloat::tan(x); }
- inline MpfrFloat fp_tanh(const MpfrFloat& x) { return MpfrFloat::tanh(x); }
- inline MpfrFloat fp_trunc(const MpfrFloat& x) { return MpfrFloat::trunc(x); }
-
- inline MpfrFloat fp_pow(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
- inline MpfrFloat fp_pow_base(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
-
-
- inline void fp_sinCos(MpfrFloat& sin, MpfrFloat& cos, const MpfrFloat& a)
- {
- MpfrFloat::sincos(a, sin, cos);
- }
-
- inline void fp_sinhCosh(MpfrFloat& sinhvalue, MpfrFloat& coshvalue,
- const MpfrFloat& param)
- {
- const MpfrFloat paramCopy = param;
- sinhvalue = fp_sinh(paramCopy);
- coshvalue = fp_cosh(paramCopy);
- }
-#endif // FP_SUPPORT_MPFR_FLOAT_TYPE
-
-
-// -------------------------------------------------------------------------
-// GMP int
-// -------------------------------------------------------------------------
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- inline GmpInt fp_abs(const GmpInt& x) { return GmpInt::abs(x); }
- inline GmpInt fp_acos(const GmpInt&) { return 0; }
- inline GmpInt fp_acosh(const GmpInt&) { return 0; }
- inline GmpInt fp_asin(const GmpInt&) { return 0; }
- inline GmpInt fp_asinh(const GmpInt&) { return 0; }
- inline GmpInt fp_atan(const GmpInt&) { return 0; }
- inline GmpInt fp_atan2(const GmpInt&, const GmpInt&) { return 0; }
- inline GmpInt fp_atanh(const GmpInt&) { return 0; }
- inline GmpInt fp_cbrt(const GmpInt&) { return 0; }
- inline GmpInt fp_ceil(const GmpInt& x) { return x; }
- inline GmpInt fp_cos(const GmpInt&) { return 0; }
- inline GmpInt fp_cosh(const GmpInt&) { return 0; }
- inline GmpInt fp_exp(const GmpInt&) { return 0; }
- inline GmpInt fp_exp2(const GmpInt&) { return 0; }
- inline GmpInt fp_floor(const GmpInt& x) { return x; }
- inline GmpInt fp_hypot(const GmpInt&, const GmpInt&) { return 0; }
- inline GmpInt fp_int(const GmpInt& x) { return x; }
- inline GmpInt fp_log(const GmpInt&) { return 0; }
- inline GmpInt fp_log2(const GmpInt&) { return 0; }
- inline GmpInt fp_log10(const GmpInt&) { return 0; }
- inline GmpInt fp_mod(const GmpInt& x, const GmpInt& y) { return x % y; }
- inline GmpInt fp_pow(const GmpInt&, const GmpInt&) { return 0; }
- inline GmpInt fp_sin(const GmpInt&) { return 0; }
- inline GmpInt fp_sinh(const GmpInt&) { return 0; }
- inline GmpInt fp_sqrt(const GmpInt&) { return 0; }
- inline GmpInt fp_tan(const GmpInt&) { return 0; }
- inline GmpInt fp_tanh(const GmpInt&) { return 0; }
- inline GmpInt fp_trunc(const GmpInt& x) { return x; }
- inline GmpInt fp_pow_base(const GmpInt&, const GmpInt&) { return 0; }
- inline void fp_sinCos(GmpInt&, GmpInt&, const GmpInt&) {}
- inline void fp_sinhCosh(GmpInt&, GmpInt&, const GmpInt&) {}
-#endif // FP_SUPPORT_GMP_INT_TYPE
-
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_cbrt(const Value_t& x) { return std::cbrt(x); }
-#else
- template<typename Value_t>
- inline Value_t fp_cbrt(const Value_t& x)
- {
- return (x > Value_t() ? fp_exp(fp_log( x) / Value_t(3)) :
- x < Value_t() ? -fp_exp(fp_log(-x) / Value_t(3)) :
- Value_t());
- }
-#endif
-
-// -------------------------------------------------------------------------
-// Synthetic functions and fallbacks for when an optimized
-// implementation or a library function is not available
-// -------------------------------------------------------------------------
- template<typename Value_t> inline Value_t fp_arg(const Value_t& x);
- template<typename Value_t> inline Value_t fp_exp2(const Value_t& x);
- template<typename Value_t> inline Value_t fp_int(const Value_t& x);
- template<typename Value_t> inline Value_t fp_trunc(const Value_t& x);
- template<typename Value_t>
- inline void fp_sinCos(Value_t& , Value_t& , const Value_t& );
- template<typename Value_t>
- inline void fp_sinhCosh(Value_t& , Value_t& , const Value_t& );
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- /* NOTE: Complex multiplication of a and b can be done with:
- tmp = b.real * (a.real + a.imag)
- result.real = tmp - a.imag * (b.real + b.imag)
- result.imag = tmp + a.real * (b.imag - b.real)
- This has fewer multiplications than the standard
- algorithm. Take note, if you support mpfr complex one day.
- */
-
- template<typename T>
- struct FP_ProbablyHasFastLibcComplex
- { enum { result = false }; };
- /* The generic sqrt() etc. implementations in libstdc++
- * are very plain and non-optimized; however, it contains
- * callbacks to libc complex math functions where possible,
- * and I suspect that those may actually be well optimized.
- * So we use std:: functions when we suspect they may be fast,
- * and otherwise we use our own optimized implementations.
- */
-#ifdef __GNUC__
- template<> struct FP_ProbablyHasFastLibcComplex<float>
- { enum { result = true }; };
- template<> struct FP_ProbablyHasFastLibcComplex<double>
- { enum { result = true }; };
- template<> struct FP_ProbablyHasFastLibcComplex<long double>
- { enum { result = true }; };
-#endif
-
- template<typename T>
- inline const std::complex<T> fp_make_imag(const std::complex<T>& v)
- {
- return std::complex<T> ( T(), v.real() );
- }
-
- template<typename T>
- inline std::complex<T> fp_real(const std::complex<T>& x)
- {
- return x.real();
- }
- template<typename T>
- inline std::complex<T> fp_imag(const std::complex<T>& x)
- {
- return x.imag();
- }
- template<typename T>
- inline std::complex<T> fp_arg(const std::complex<T>& x)
- {
- return std::arg(x);
- }
- template<typename T>
- inline std::complex<T> fp_conj(const std::complex<T>& x)
- {
- return std::conj(x);
- }
- template<typename T, bool>
- inline std::complex<T> fp_polar(const T& x, const T& y)
- {
- T si, co; fp_sinCos(si, co, y);
- return std::complex<T> (x*co, x*si);
- }
- template<typename T>
- inline std::complex<T> fp_polar(const std::complex<T>& x, const std::complex<T>& y)
- {
- // x * cos(y) + i * x * sin(y) -- arguments are supposed to be REAL numbers
- return fp_polar<T,true> (x.real(), y.real());
- //return std::polar(x.real(), y.real());
- //return x * (fp_cos(y) + (std::complex<T>(0,1) * fp_sin(y));
- }
-
- // These provide fallbacks in case there's no library function
- template<typename T>
- inline std::complex<T> fp_floor(const std::complex<T>& x)
- {
- return std::complex<T> (fp_floor(x.real()), fp_floor(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_trunc(const std::complex<T>& x)
- {
- return std::complex<T> (fp_trunc(x.real()), fp_trunc(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_int(const std::complex<T>& x)
- {
- return std::complex<T> (fp_int(x.real()), fp_int(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_ceil(const std::complex<T>& x)
- {
- return std::complex<T> (fp_ceil(x.real()), fp_ceil(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_abs(const std::complex<T>& x)
- {
- return std::abs(x);
- //T extent = fp_max(fp_abs(x.real()), fp_abs(x.imag()));
- //if(extent == T()) return x;
- //return extent * fp_hypot(x.real() / extent, x.imag() / extent);
- }
- template<typename T>
- inline std::complex<T> fp_exp(const std::complex<T>& x)
- {
- if(FP_ProbablyHasFastLibcComplex<T>::result)
- return std::exp(x);
- return fp_polar<T,true>(fp_exp(x.real()), x.imag());
- }
- template<typename T>
- inline std::complex<T> fp_log(const std::complex<T>& x)
- {
- if(FP_ProbablyHasFastLibcComplex<T>::result)
- return std::log(x);
- // log(abs(x)) + i*arg(x)
- // log(Xr^2+Xi^2)*0.5 + i*arg(x)
- if(x.imag()==T())
- return std::complex<T>( fp_log(fp_abs(x.real())),
- fp_arg(x.real()) ); // Note: Uses real-value fp_arg() here!
- return std::complex<T>(
- fp_log(std::norm(x)) * T(0.5),
- fp_arg(x).real() );
- }
- template<typename T>
- inline std::complex<T> fp_sqrt(const std::complex<T>& x)
- {
- if(FP_ProbablyHasFastLibcComplex<T>::result)
- return std::sqrt(x);
- return fp_polar<T,true> (fp_sqrt(fp_abs(x).real()),
- T(0.5)*fp_arg(x).real());
- }
- template<typename T>
- inline std::complex<T> fp_acos(const std::complex<T>& x)
- {
- // -i * log(x + i * sqrt(1 - x^2))
- const std::complex<T> i (T(), T(1));
- return -i * fp_log(x + i * fp_sqrt(T(1) - x*x));
- // Note: Real version of acos() cannot handle |x| > 1,
- // because it would cause sqrt(negative value).
- }
- template<typename T>
- inline std::complex<T> fp_asin(const std::complex<T>& x)
- {
- // -i * log(i*x + sqrt(1 - x^2))
- const std::complex<T> i (T(), T(1));
- return -i * fp_log(i*x + fp_sqrt(T(1) - x*x));
- // Note: Real version of asin() cannot handle |x| > 1,
- // because it would cause sqrt(negative value).
- }
- template<typename T>
- inline std::complex<T> fp_atan(const std::complex<T>& x)
- {
- // 0.5i * (log(1-i*x) - log(1+i*x))
- // -0.5i * log( (1+i*x) / (1-i*x) )
- const std::complex<T> i (T(), T(1));
- return (T(-0.5)*i) * fp_log( (T(1)+i*x) / (T(1)-i*x) );
- // Note: x = -1i causes division by zero
- // x = +1i causes log(0)
- // Thus, x must not be +-1i
- }
- template<typename T>
- inline std::complex<T> fp_cos(const std::complex<T>& x)
- {
- return std::cos(x);
- // // (exp(i*x) + exp(-i*x)) / (2)
- // //const std::complex<T> i (T(), T(1));
- // //return (fp_exp(i*x) + fp_exp(-i*x)) * T(0.5);
- // // Also: cos(Xr)*cosh(Xi) - i*sin(Xr)*sinh(Xi)
- // return std::complex<T> (
- // fp_cos(x.real())*fp_cosh(x.imag()),
- // -fp_sin(x.real())*fp_sinh(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_sin(const std::complex<T>& x)
- {
- return std::sin(x);
- // // (exp(i*x) - exp(-i*x)) / (2i)
- // //const std::complex<T> i (T(), T(1));
- // //return (fp_exp(i*x) - fp_exp(-i*x)) * (T(-0.5)*i);
- // // Also: sin(Xr)*cosh(Xi) + cos(Xr)*sinh(Xi)
- // return std::complex<T> (
- // fp_sin(x.real())*fp_cosh(x.imag()),
- // fp_cos(x.real())*fp_sinh(x.imag()));
- }
- template<typename T>
- inline void fp_sinCos(
- std::complex<T>& sinvalue,
- std::complex<T>& cosvalue,
- const std::complex<T>& x)
- {
- //const std::complex<T> i (T(), T(1)), expix(fp_exp(i*x)), expmix(fp_exp((-i)*x));
- //cosvalue = (expix + expmix) * T(0.5);
- //sinvalue = (expix - expmix) * (i*T(-0.5));
- // The above expands to the following:
- T srx, crx; fp_sinCos(srx, crx, x.real());
- T six, cix; fp_sinhCosh(six, cix, x.imag());
- sinvalue = std::complex<T>(srx*cix, crx*six);
- cosvalue = std::complex<T>(crx*cix, -srx*six);
- }
- template<typename T>
- inline void fp_sinhCosh(
- std::complex<T>& sinhvalue,
- std::complex<T>& coshvalue,
- const std::complex<T>& x)
- {
- T srx, crx; fp_sinhCosh(srx, crx, x.real());
- T six, cix; fp_sinCos(six, cix, x.imag());
- sinhvalue = std::complex<T>(srx*cix, crx*six);
- coshvalue = std::complex<T>(crx*cix, srx*six);
- }
- template<typename T>
- inline std::complex<T> fp_tan(const std::complex<T>& x)
- {
- return std::tan(x);
- //std::complex<T> si, co;
- //fp_sinCos(si, co, x);
- //return si/co;
- // // (i-i*exp(2i*x)) / (exp(2i*x)+1)
- // const std::complex<T> i (T(), T(1)), exp2ix=fp_exp((2*i)*x);
- // return (i-i*exp2ix) / (exp2ix+T(1));
- // // Also: sin(x)/cos(y)
- // // return fp_sin(x)/fp_cos(x);
- }
- template<typename T>
- inline std::complex<T> fp_cosh(const std::complex<T>& x)
- {
- return std::cosh(x);
- // // (exp(x) + exp(-x)) * 0.5
- // // Also: cosh(Xr)*cos(Xi) + i*sinh(Xr)*sin(Xi)
- // return std::complex<T> (
- // fp_cosh(x.real())*fp_cos(x.imag()),
- // fp_sinh(x.real())*fp_sin(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_sinh(const std::complex<T>& x)
- {
- return std::sinh(x);
- // // (exp(x) - exp(-x)) * 0.5
- // // Also: sinh(Xr)*cos(Xi) + i*cosh(Xr)*sin(Xi)
- // return std::complex<T> (
- // fp_sinh(x.real())*fp_cos(x.imag()),
- // fp_cosh(x.real())*fp_sin(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_tanh(const std::complex<T>& x)
- {
- return std::tanh(x);
- //std::complex<T> si, co;
- //fp_sinhCosh(si, co, x);
- //return si/co;
- // // (exp(2*x)-1) / (exp(2*x)+1)
- // // Also: sinh(x)/tanh(x)
- // const std::complex<T> exp2x=fp_exp(x+x);
- // return (exp2x-T(1)) / (exp2x+T(1));
- }
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename T>
- inline std::complex<T> fp_acosh(const std::complex<T>& x)
- { return fp_log(x + fp_sqrt(x*x - std::complex<T>(1))); }
- template<typename T>
- inline std::complex<T> fp_asinh(const std::complex<T>& x)
- { return fp_log(x + fp_sqrt(x*x + std::complex<T>(1))); }
- template<typename T>
- inline std::complex<T> fp_atanh(const std::complex<T>& x)
- { return fp_log( (std::complex<T>(1)+x) / (std::complex<T>(1)-x))
- * std::complex<T>(0.5); }
-#endif
- template<typename T>
- inline std::complex<T> fp_pow(const std::complex<T>& x, const std::complex<T>& y)
- {
- // return std::pow(x,y);
-
- // With complex numbers, pow(x,y) can be solved with
- // the general formula: exp(y*log(x)). It handles
- // all special cases gracefully.
- // It expands to the following:
- // A)
- // t1 = log(x)
- // t2 = y * t1
- // res = exp(t2)
- // B)
- // t1.r = log(x.r * x.r + x.i * x.i) * 0.5 \ fp_log()
- // t1.i = atan2(x.i, x.r) /
- // t2.r = y.r*t1.r - y.i*t1.i \ multiplication
- // t2.i = y.r*t1.i + y.i*t1.r /
- // rho = exp(t2.r) \ fp_exp()
- // theta = t2.i /
- // res.r = rho * cos(theta) \ fp_polar(), called from
- // res.i = rho * sin(theta) / fp_exp(). Uses sincos().
- // Aside from the common "norm" calculation in atan2()
- // and in the log parameter, both of which are part of fp_log(),
- // there does not seem to be any incentive to break this
- // function down further; it would not help optimizing it.
- // However, we do handle the following special cases:
- //
- // When x is real (positive or negative):
- // t1.r = log(abs(x.r))
- // t1.i = x.r<0 ? -pi : 0
- // When y is real:
- // t2.r = y.r * t1.r
- // t2.i = y.r * t1.i
- const std::complex<T> t =
- (x.imag() != T())
- ? fp_log(x)
- : std::complex<T> (fp_log(fp_abs(x.real())),
- fp_arg(x.real())); // Note: Uses real-value fp_arg() here!
- return y.imag() != T()
- ? fp_exp(y * t)
- : fp_polar<T,true> (fp_exp(y.real()*t.real()), y.real()*t.imag());
- }
- template<typename T>
- inline std::complex<T> fp_cbrt(const std::complex<T>& x)
- {
- // For real numbers, prefer giving a real solution
- // rather than a complex solution.
- // For example, cbrt(-3) has the following three solutions:
- // A) 0.7211247966535 + 1.2490247864016i
- // B) 0.7211247966535 - 1.2490247864016i
- // C) -1.442249593307
- // exp(log(x)/3) gives A, but we prefer to give C.
- if(x.imag() == T()) return fp_cbrt(x.real());
- const std::complex<T> t(fp_log(x));
- return fp_polar<T,true> (fp_exp(t.real() / T(3)), t.imag() / T(3));
- }
-
- template<typename T>
- inline std::complex<T> fp_exp2(const std::complex<T>& x)
- {
- // pow(2, x)
- // polar(2^Xr, Xi*log(2))
- return fp_polar<T,true> (fp_exp2(x.real()), x.imag()*fp_const_log2<T>());
- }
- template<typename T>
- inline std::complex<T> fp_mod(const std::complex<T>& x, const std::complex<T>& y)
- {
- // Modulo function is probably not defined for complex numbers.
- // But we do our best to calculate it the same way as it is done
- // with real numbers, so that at least it is in some way "consistent".
- if(y.imag() == 0) return fp_mod(x.real(), y.real()); // optimization
- std::complex<T> n = fp_trunc(x / y);
- return x - n * y;
- }
-
- /* libstdc++ already defines a streaming operator for complex values,
- * but we redefine our own that it is compatible with the input
- * accepted by fparser. I.e. instead of (5,3) we now get (5+3i),
- * and instead of (-4,0) we now get -4.
- */
- template<typename T>
- inline std::ostream& operator<<(std::ostream& os, const std::complex<T>& value)
- {
- if(value.imag() == T()) return os << value.real();
- if(value.real() == T()) return os << value.imag() << 'i';
- if(value.imag() < T())
- return os << '(' << value.real() << "-" << -value.imag() << "i)";
- else
- return os << '(' << value.real() << "+" << value.imag() << "i)";
- }
-
- /* Less-than or greater-than operators are not technically defined
- * for Complex types. However, in fparser and its tool set, these
- * operators are widely required to be present.
- * Our implementation here is based on converting the complex number
- * into a scalar and the doing a scalar comparison on the value.
- * The means by which the number is changed into a scalar is based
- * on the following principles:
- * - Does not introduce unjustified amounts of extra inaccuracy
- * - Is transparent to purely real values
- * (this disqualifies something like x.real() + x.imag())
- * - Does not ignore the imaginary value completely
- * (this may be relevant especially in testbed)
- * - Is not so complicated that it would slow down a great deal
- *
- * Basically our formula here is the same as std::abs(),
- * except that it keeps the sign of the original real number,
- * and it does not do a sqrt() calculation that is not really
- * needed because we are only interested in the relative magnitudes.
- *
- * Equality and nonequality operators must not need to be overloaded.
- * They are already implemented in standard, and we must
- * not introduce flawed equality assumptions.
- */
- template<typename T>
- inline T fp_complexScalarize(const std::complex<T>& x)
- {
- T res(std::norm(x));
- if(x.real() < T()) res = -res;
- return res;
- }
- template<typename T>
- inline T fp_realComplexScalarize(const T& x)
- {
- T res(x*x);
- if(x < T()) res = -res;
- return res;
- }
- // { return x.real() * (T(1.0) + fp_abs(x.imag())); }
- #define d(op) \
- template<typename T> \
- inline bool operator op (const std::complex<T>& x, T y) \
- { return fp_complexScalarize(x) op fp_realComplexScalarize(y); } \
- template<typename T> \
- inline bool operator op (const std::complex<T>& x, const std::complex<T>& y) \
- { return fp_complexScalarize(x) op \
- fp_complexScalarize(y); } \
- template<typename T> \
- inline bool operator op (T x, const std::complex<T>& y) \
- { return fp_realComplexScalarize(x) op fp_complexScalarize(y); }
- d( < ) d( <= ) d( > ) d( >= )
- #undef d
-#endif
-
- template<typename Value_t>
- inline Value_t fp_real(const Value_t& x) { return x; }
- template<typename Value_t>
- inline Value_t fp_imag(const Value_t& ) { return Value_t(); }
- template<typename Value_t>
- inline Value_t fp_arg(const Value_t& x)
- { return x < Value_t() ? -fp_const_pi<Value_t>() : Value_t(); }
- template<typename Value_t>
- inline Value_t fp_conj(const Value_t& x) { return x; }
- template<typename Value_t>
- inline Value_t fp_polar(const Value_t& x, const Value_t& y)
- { return x * fp_cos(y); } // This is of course a meaningless function.
-
- template<typename Value_t>
- inline std::complex<Value_t> fp_atan2(const std::complex<Value_t>& y,
- const std::complex<Value_t>& x)
- {
- if(y == Value_t()) return fp_arg(x);
- if(x == Value_t()) return fp_const_pi<Value_t>() * Value_t(-0.5);
- // 2*atan(y / (sqrt(x^2+y^2) + x) )
- // 2*atan( (sqrt(x^2+y^2) - x) / y)
- std::complex<Value_t> res( fp_atan(y / (fp_hypot(x,y) + x)) );
- return res+res;
- }
-
-// -------------------------------------------------------------------------
-// Comparison
-// -------------------------------------------------------------------------
- template<typename Value_t>
- inline bool fp_equal(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x == y)
- : (fp_abs(x - y) <= Epsilon<Value_t>::value); }
-
- template<typename Value_t>
- inline bool fp_nequal(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x != y)
- : (fp_abs(x - y) > Epsilon<Value_t>::value); }
-
- template<typename Value_t>
- inline bool fp_less(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x < y)
- : (x < y - Epsilon<Value_t>::value); }
-
- template<typename Value_t>
- inline bool fp_lessOrEq(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x <= y)
- : (x <= y + Epsilon<Value_t>::value); }
-
-
- template<typename Value_t>
- inline bool fp_greater(const Value_t& x, const Value_t& y)
- { return fp_less(y, x); }
-
- template<typename Value_t>
- inline bool fp_greaterOrEq(const Value_t& x, const Value_t& y)
- { return fp_lessOrEq(y, x); }
-
- template<typename Value_t>
- inline bool fp_truth(const Value_t& d)
- {
- return IsIntType<Value_t>::result
- ? d != Value_t()
- : fp_abs(d) >= Value_t(0.5);
- }
-
- template<typename Value_t>
- inline bool fp_absTruth(const Value_t& abs_d)
- {
- return IsIntType<Value_t>::result
- ? abs_d > Value_t()
- : abs_d >= Value_t(0.5);
- }
-
- template<typename Value_t>
- inline const Value_t& fp_min(const Value_t& d1, const Value_t& d2)
- { return d1<d2 ? d1 : d2; }
-
- template<typename Value_t>
- inline const Value_t& fp_max(const Value_t& d1, const Value_t& d2)
- { return d1>d2 ? d1 : d2; }
-
- template<typename Value_t>
- inline const Value_t fp_not(const Value_t& b)
- { return Value_t(!fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_notNot(const Value_t& b)
- { return Value_t(fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absNot(const Value_t& b)
- { return Value_t(!fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absNotNot(const Value_t& b)
- { return Value_t(fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_and(const Value_t& a, const Value_t& b)
- { return Value_t(fp_truth(a) && fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_or(const Value_t& a, const Value_t& b)
- { return Value_t(fp_truth(a) || fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absAnd(const Value_t& a, const Value_t& b)
- { return Value_t(fp_absTruth(a) && fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absOr(const Value_t& a, const Value_t& b)
- { return Value_t(fp_absTruth(a) || fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_make_imag(const Value_t& ) // Imaginary 1. In real mode, always zero.
- {
- return Value_t();
- }
-
- /////////////
- /* Opcode analysis functions are used by fp_opcode_add.inc */
- /* Moved here from fparser.cc because fp_opcode_add.inc
- * is also now included by fpoptimizer.cc
- */
- bool IsLogicalOpcode(unsigned op);
- bool IsComparisonOpcode(unsigned op);
- unsigned OppositeComparisonOpcode(unsigned op);
- bool IsNeverNegativeValueOpcode(unsigned op);
- bool IsAlwaysIntegerOpcode(unsigned op);
- bool IsUnaryOpcode(unsigned op);
- bool IsBinaryOpcode(unsigned op);
- bool IsVarOpcode(unsigned op);
- bool IsCommutativeOrParamSwappableBinaryOpcode(unsigned op);
- unsigned GetParamSwappedBinaryOpcode(unsigned op);
-
- template<bool ComplexType>
- bool HasInvalidRangesOpcode(unsigned op);
-
- template<typename Value_t>
- inline Value_t DegreesToRadians(const Value_t& degrees)
- {
- return degrees * fp_const_deg_to_rad<Value_t>();
- }
-
- template<typename Value_t>
- inline Value_t RadiansToDegrees(const Value_t& radians)
- {
- return radians * fp_const_rad_to_deg<Value_t>();
- }
-
- template<typename Value_t>
- inline long makeLongInteger(const Value_t& value)
- {
- return (long) fp_int(value);
- }
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- template<typename T>
- inline long makeLongInteger(const std::complex<T>& value)
- {
- return (long) fp_int( std::abs(value) );
- }
-#endif
-
- // Is value an integer that fits in "long" datatype?
- template<typename Value_t>
- inline bool isLongInteger(const Value_t& value)
- {
- return value == Value_t( makeLongInteger(value) );
- }
-
- template<typename Value_t>
- inline bool isOddInteger(const Value_t& value)
- {
- const Value_t halfValue = (value + Value_t(1)) * Value_t(0.5);
- return fp_equal(halfValue, fp_floor(halfValue));
- }
-
- template<typename Value_t>
- inline bool isEvenInteger(const Value_t& value)
- {
- const Value_t halfValue = value * Value_t(0.5);
- return fp_equal(halfValue, fp_floor(halfValue));
- }
-
- template<typename Value_t>
- inline bool isInteger(const Value_t& value)
- {
- return fp_equal(value, fp_floor(value));
- }
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- inline bool isEvenInteger(const long& value)
- {
- return value%2 == 0;
- }
-
- template<>
- inline bool isInteger(const long&) { return true; }
-
- template<>
- inline bool isLongInteger(const long&) { return true; }
-
- template<>
- inline long makeLongInteger(const long& value)
- {
- return value;
- }
-#endif
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<>
- inline bool isInteger(const MpfrFloat& value) { return value.isInteger(); }
-
- template<>
- inline bool isEvenInteger(const MpfrFloat& value)
- {
- return isInteger(value) && value%2 == 0;
- }
-
- template<>
- inline long makeLongInteger(const MpfrFloat& value)
- {
- return (long) value.toInt();
- }
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<>
- inline bool isEvenInteger(const GmpInt& value)
- {
- return value%2 == 0;
- }
-
- template<>
- inline bool isInteger(const GmpInt&) { return true; }
-
- template<>
- inline long makeLongInteger(const GmpInt& value)
- {
- return (long) value.toInt();
- }
-#endif
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- inline bool isOddInteger(const long& value)
- {
- return value%2 != 0;
- }
-#endif
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<>
- inline bool isOddInteger(const MpfrFloat& value)
- {
- return value.isInteger() && value%2 != 0;
- }
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<>
- inline bool isOddInteger(const GmpInt& value)
- {
- return value%2 != 0;
- }
-#endif
-
-
-// -------------------------------------------------------------------------
-// fp_pow
-// -------------------------------------------------------------------------
- // Commented versions in fparser.cc
- template<typename Value_t>
- inline Value_t fp_pow_with_exp_log(const Value_t& x, const Value_t& y)
- {
- return fp_exp(fp_log(x) * y);
- }
-
- template<typename Value_t>
- inline Value_t fp_powi(Value_t x, unsigned long y)
- {
- Value_t result(1);
- while(y != 0)
- {
- if(y & 1) { result *= x; y -= 1; }
- else { x *= x; y /= 2; }
- }
- return result;
- }
-
- template<typename Value_t>
- Value_t fp_pow(const Value_t& x, const Value_t& y)
- {
- if(x == Value_t(1)) return Value_t(1);
- if(isLongInteger(y))
- {
- if(y >= Value_t(0))
- return fp_powi(x, makeLongInteger(y));
- else
- return Value_t(1) / fp_powi(x, -makeLongInteger(y));
- }
- if(y >= Value_t(0))
- {
- if(x > Value_t(0)) return fp_pow_with_exp_log(x, y);
- if(x == Value_t(0)) return Value_t(0);
- if(!isInteger(y*Value_t(16)))
- return -fp_pow_with_exp_log(-x, y);
- }
- else
- {
- if(x > Value_t(0)) return fp_pow_with_exp_log(Value_t(1) / x, -y);
- if(x < Value_t(0))
- {
- if(!isInteger(y*Value_t(-16)))
- return -fp_pow_with_exp_log(Value_t(-1) / x, -y);
- }
- }
- return fp_pow_base(x, y);
- }
-
- template<typename Value_t>
- inline Value_t fp_exp2(const Value_t& x)
- {
- return fp_pow(Value_t(2), x);
- }
-} // namespace FUNCTIONPARSERTYPES
-
-#endif // ONCE_FPARSER_H_
-#endif // ONCE_FPARSER_AUX_H_
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-// NOTE:
-// This file contains only internal types for the function parser library.
-// You don't need to include this file in your code. Include "fparser.hh"
-// only.
-
-#ifndef ONCE_FPARSER_TYPES_H_
-#define ONCE_FPARSER_TYPES_H_
-
-#include "../fpconfig.hh"
-#include <cstring>
-
-#ifdef ONCE_FPARSER_H_
-#include <map>
-#endif
-
-namespace FUNCTIONPARSERTYPES
-{
- enum OPCODE
- {
-// The order of opcodes in the function list must
-// match that which is in the Functions[] array.
- cAbs,
- cAcos, cAcosh,
- cArg, /* get the phase angle of a complex value */
- cAsin, cAsinh,
- cAtan, cAtan2, cAtanh,
- cCbrt, cCeil,
- cConj, /* get the complex conjugate of a complex value */
- cCos, cCosh, cCot, cCsc,
- cExp, cExp2, cFloor, cHypot,
- cIf,
- cImag, /* get imaginary part of a complex value */
- cInt, cLog, cLog10, cLog2, cMax, cMin,
- cPolar, /* create a complex number from polar coordinates */
- cPow,
- cReal, /* get real part of a complex value */
- cSec, cSin, cSinh, cSqrt, cTan, cTanh,
- cTrunc,
-
-// These do not need any ordering:
-// Except that if you change the order of {eq,neq,lt,le,gt,ge}, you
-// must also change the order in ConstantFolding_ComparisonOperations().
- cImmed, cJump,
- cNeg, cAdd, cSub, cMul, cDiv, cMod,
- cEqual, cNEqual, cLess, cLessOrEq, cGreater, cGreaterOrEq,
- cNot, cAnd, cOr,
- cNotNot, /* Protects the double-not sequence from optimizations */
-
- cDeg, cRad, /* Multiplication and division by 180 / pi */
-
- cFCall, cPCall,
-
-#ifdef FP_SUPPORT_OPTIMIZER
- cPopNMov, /* cPopNMov(x,y) moves [y] to [x] and deletes anything
- * above [x]. Used for disposing of temporaries.
- */
- cLog2by, /* log2by(x,y) = log2(x) * y */
- cNop, /* Used by fpoptimizer internally; should not occur in bytecode */
-#endif
- cSinCos, /* sin(x) followed by cos(x) (two values are pushed to stack) */
- cSinhCosh, /* hyperbolic equivalent of sincos */
- cAbsAnd, /* As cAnd, but assume both operands are absolute values */
- cAbsOr, /* As cOr, but assume both operands are absolute values */
- cAbsNot, /* As cAbsNot, but assume the operand is an absolute value */
- cAbsNotNot, /* As cAbsNotNot, but assume the operand is an absolute value */
- cAbsIf, /* As cAbsIf, but assume the 1st operand is an absolute value */
-
- cDup, /* Duplicates the last value in the stack: Push [Stacktop] */
- cFetch, /* Same as Dup, except with absolute index
- * (next value is index) */
- cInv, /* Inverts the last value in the stack (x = 1/x) */
- cSqr, /* squares the last operand in the stack, no push/pop */
- cRDiv, /* reverse division (not x/y, but y/x) */
- cRSub, /* reverse subtraction (not x-y, but y-x) */
- cRSqrt, /* inverse square-root (1/sqrt(x)) */
-
- VarBegin
- };
-
-#ifdef ONCE_FPARSER_H_
- struct FuncDefinition
- {
- enum FunctionFlags
- {
- Enabled = 0x01,
- AngleIn = 0x02,
- AngleOut = 0x04,
- OkForInt = 0x08,
- ComplexOnly = 0x10
- };
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
- const char name[8];
-#else
- struct name { } name;
-#endif
- unsigned params : 8;
- unsigned flags : 8;
-
- inline bool okForInt() const { return (flags & OkForInt) != 0; }
- inline bool complexOnly() const { return (flags & ComplexOnly) != 0; }
- };
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-# define FP_FNAME(n) n
-#else
-# define FP_FNAME(n) {}
-#endif
-// This list must be in the same order as that in OPCODE enum,
-// because the opcode value is used to index this array, and
-// the pointer to array element is used for generating the opcode.
- const FuncDefinition Functions[]=
- {
- /*cAbs */ { FP_FNAME("abs"), 1, FuncDefinition::OkForInt },
- /*cAcos */ { FP_FNAME("acos"), 1, FuncDefinition::AngleOut },
- /*cAcosh*/ { FP_FNAME("acosh"), 1, FuncDefinition::AngleOut },
- /*cArg */ { FP_FNAME("arg"), 1, FuncDefinition::AngleOut | FuncDefinition::ComplexOnly },
- /*cAsin */ { FP_FNAME("asin"), 1, FuncDefinition::AngleOut },
- /*cAsinh*/ { FP_FNAME("asinh"), 1, FuncDefinition::AngleOut },
- /*cAtan */ { FP_FNAME("atan"), 1, FuncDefinition::AngleOut },
- /*cAtan2*/ { FP_FNAME("atan2"), 2, FuncDefinition::AngleOut },
- /*cAtanh*/ { FP_FNAME("atanh"), 1, 0 },
- /*cCbrt */ { FP_FNAME("cbrt"), 1, 0 },
- /*cCeil */ { FP_FNAME("ceil"), 1, 0 },
- /*cConj */ { FP_FNAME("conj"), 1, FuncDefinition::ComplexOnly },
- /*cCos */ { FP_FNAME("cos"), 1, FuncDefinition::AngleIn },
- /*cCosh */ { FP_FNAME("cosh"), 1, FuncDefinition::AngleIn },
- /*cCot */ { FP_FNAME("cot"), 1, FuncDefinition::AngleIn },
- /*cCsc */ { FP_FNAME("csc"), 1, FuncDefinition::AngleIn },
- /*cExp */ { FP_FNAME("exp"), 1, 0 },
- /*cExp2 */ { FP_FNAME("exp2"), 1, 0 },
- /*cFloor*/ { FP_FNAME("floor"), 1, 0 },
- /*cHypot*/ { FP_FNAME("hypot"), 2, 0 },
- /*cIf */ { FP_FNAME("if"), 0, FuncDefinition::OkForInt },
- /*cImag */ { FP_FNAME("imag"), 1, FuncDefinition::ComplexOnly },
- /*cInt */ { FP_FNAME("int"), 1, 0 },
- /*cLog */ { FP_FNAME("log"), 1, 0 },
- /*cLog10*/ { FP_FNAME("log10"), 1, 0 },
- /*cLog2 */ { FP_FNAME("log2"), 1, 0 },
- /*cMax */ { FP_FNAME("max"), 2, FuncDefinition::OkForInt },
- /*cMin */ { FP_FNAME("min"), 2, FuncDefinition::OkForInt },
- /*cPolar */{ FP_FNAME("polar"), 2, FuncDefinition::ComplexOnly | FuncDefinition::AngleIn },
- /*cPow */ { FP_FNAME("pow"), 2, 0 },
- /*cReal */ { FP_FNAME("real"), 1, FuncDefinition::ComplexOnly },
- /*cSec */ { FP_FNAME("sec"), 1, FuncDefinition::AngleIn },
- /*cSin */ { FP_FNAME("sin"), 1, FuncDefinition::AngleIn },
- /*cSinh */ { FP_FNAME("sinh"), 1, FuncDefinition::AngleIn },
- /*cSqrt */ { FP_FNAME("sqrt"), 1, 0 },
- /*cTan */ { FP_FNAME("tan"), 1, FuncDefinition::AngleIn },
- /*cTanh */ { FP_FNAME("tanh"), 1, FuncDefinition::AngleIn },
- /*cTrunc*/ { FP_FNAME("trunc"), 1, 0 }
- };
-#undef FP_FNAME
-
- struct NamePtr
- {
- const char* name;
- unsigned nameLength;
-
- NamePtr(const char* n, unsigned l): name(n), nameLength(l) {}
-
- inline bool operator==(const NamePtr& rhs) const
- {
- return nameLength == rhs.nameLength
- && std::memcmp(name, rhs.name, nameLength) == 0;
- }
- inline bool operator<(const NamePtr& rhs) const
- {
- for(unsigned i = 0; i < nameLength; ++i)
- {
- if(i == rhs.nameLength) return false;
- const char c1 = name[i], c2 = rhs.name[i];
- if(c1 < c2) return true;
- if(c2 < c1) return false;
- }
- return nameLength < rhs.nameLength;
- }
- };
-
- template<typename Value_t>
- struct NameData
- {
- enum DataType { CONSTANT, UNIT, FUNC_PTR, PARSER_PTR, VARIABLE };
- DataType type;
- unsigned index;
- Value_t value;
-
- NameData(DataType t, unsigned v) : type(t), index(v), value() { }
- NameData(DataType t, Value_t v) : type(t), index(), value(v) { }
- NameData() { }
- };
-
- template<typename Value_t>
- class NamePtrsMap: public
- std::map<FUNCTIONPARSERTYPES::NamePtr,
- FUNCTIONPARSERTYPES::NameData<Value_t> >
- {
- };
-
- const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]);
-#endif // ONCE_FPARSER_H_
-}
-
-#ifdef ONCE_FPARSER_H_
-#include <vector>
-
-template<typename Value_t>
-struct FunctionParserBase<Value_t>::Data
-{
- unsigned mReferenceCounter;
-
- char mDelimiterChar;
- ParseErrorType mParseErrorType;
- int mEvalErrorType;
- bool mUseDegreeConversion;
- bool mHasByteCodeFlags;
- const char* mErrorLocation;
-
- unsigned mVariablesAmount;
- std::string mVariablesString;
- FUNCTIONPARSERTYPES::NamePtrsMap<Value_t> mNamePtrs;
-
- struct InlineVariable
- {
- FUNCTIONPARSERTYPES::NamePtr mName;
- unsigned mFetchIndex;
- };
-
- typedef std::vector<InlineVariable> InlineVarNamesContainer;
- InlineVarNamesContainer mInlineVarNames;
-
- struct FuncWrapperPtrData
- {
- /* Only one of the pointers will point to a function, the other
- will be null. (The raw function pointer could be implemented
- as a FunctionWrapper specialization, but it's done like this
- for efficiency.) */
- FunctionPtr mRawFuncPtr;
- FunctionWrapper* mFuncWrapperPtr;
- unsigned mParams;
-
- FuncWrapperPtrData();
- ~FuncWrapperPtrData();
- FuncWrapperPtrData(const FuncWrapperPtrData&);
- FuncWrapperPtrData& operator=(const FuncWrapperPtrData&);
- };
-
- struct FuncParserPtrData
- {
- FunctionParserBase<Value_t>* mParserPtr;
- unsigned mParams;
- };
-
- std::vector<FuncWrapperPtrData> mFuncPtrs;
- std::vector<FuncParserPtrData> mFuncParsers;
-
- std::vector<unsigned> mByteCode;
- std::vector<Value_t> mImmed;
-
-#if !defined(FP_USE_THREAD_SAFE_EVAL) && \
- !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
- std::vector<Value_t> mStack;
- // Note: When mStack exists,
- // mStack.size() and mStackSize are mutually redundant.
-#endif
-
- unsigned mStackSize;
-
- Data();
- Data(const Data&);
- Data& operator=(const Data&); // not implemented on purpose
- ~Data();
-};
-#endif
-
-//#include "fpaux.hh"
-
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-#include "fpconfig.hh"
-#include "fparser.hh"
-
-#include <set>
-#include <cstdlib>
-#include <cstring>
-#include <cctype>
-#include <cmath>
-#include <cassert>
-#include <limits>
-
-#include "extrasrc/fptypes.hh"
-#include "extrasrc/fpaux.hh"
-using namespace FUNCTIONPARSERTYPES;
-
-#ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
-#ifndef FP_USE_THREAD_SAFE_EVAL
-#define FP_USE_THREAD_SAFE_EVAL
-#endif
-#endif
-
-#ifdef __GNUC__
-# define likely(x) __builtin_expect(!!(x), 1)
-# define unlikely(x) __builtin_expect(!!(x), 0)
-#else
-# define likely(x) (x)
-# define unlikely(x) (x)
-#endif
-
-//=========================================================================
-// Opcode analysis functions
-//=========================================================================
-// These functions are used by the Parse() bytecode optimizer (mostly from
-// code in fp_opcode_add.inc).
-
-bool FUNCTIONPARSERTYPES::IsLogicalOpcode(unsigned op)
-{
- switch(op)
- {
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- return true;
- default: break;
- }
- return false;
-}
-
-bool FUNCTIONPARSERTYPES::IsComparisonOpcode(unsigned op)
-{
- switch(op)
- {
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- return true;
- default: break;
- }
- return false;
-}
-
-unsigned FUNCTIONPARSERTYPES::OppositeComparisonOpcode(unsigned op)
-{
- switch(op)
- {
- case cLess: return cGreater;
- case cGreater: return cLess;
- case cLessOrEq: return cGreaterOrEq;
- case cGreaterOrEq: return cLessOrEq;
- }
- return op;
-}
-
-bool FUNCTIONPARSERTYPES::IsNeverNegativeValueOpcode(unsigned op)
-{
- switch(op)
- {
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- case cSqrt: case cRSqrt: case cSqr:
- case cHypot:
- case cAbs:
- case cAcos: case cCosh:
- return true;
- default: break;
- }
- return false;
-}
-
-bool FUNCTIONPARSERTYPES::IsAlwaysIntegerOpcode(unsigned op)
-{
- switch(op)
- {
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- case cInt: case cFloor: case cCeil: case cTrunc:
- return true;
- default: break;
- }
- return false;
-}
-
-bool FUNCTIONPARSERTYPES::IsUnaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cInv: case cNeg:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cSqr: case cRSqrt:
- case cDeg: case cRad:
- return true;
- }
- return (op < FUNC_AMOUNT && Functions[op].params == 1);
-}
-
-bool FUNCTIONPARSERTYPES::IsBinaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cAdd: case cSub: case cRSub:
- case cMul: case cDiv: case cRDiv:
- case cMod:
- case cEqual: case cNEqual: case cLess:
- case cLessOrEq: case cGreater: case cGreaterOrEq:
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- return true;
- }
- return (op < FUNC_AMOUNT && Functions[op].params == 2);
-}
-
-bool FUNCTIONPARSERTYPES::IsVarOpcode(unsigned op)
-{
- // See comment in declaration of FP_ParamGuardMask
- return int(op) >= VarBegin;
-}
-
-bool FUNCTIONPARSERTYPES::IsCommutativeOrParamSwappableBinaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cAdd:
- case cMul:
- case cEqual: case cNEqual:
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cMin: case cMax: case cHypot:
- return true;
- case cDiv: case cSub: case cRDiv: case cRSub:
- return true;
- case cLess: case cGreater:
- case cLessOrEq: case cGreaterOrEq: return true;
- }
- return false;
-}
-
-unsigned FUNCTIONPARSERTYPES::GetParamSwappedBinaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cAdd:
- case cMul:
- case cEqual: case cNEqual:
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cMin: case cMax: case cHypot:
- return op;
- case cDiv: return cRDiv;
- case cSub: return cRSub;
- case cRDiv: return cDiv;
- case cRSub: return cSub;
- case cLess: return cGreater;
- case cGreater: return cLess;
- case cLessOrEq: return cGreaterOrEq;
- case cGreaterOrEq: return cLessOrEq;
- }
- return op; // Error
-}
-
-template<bool ComplexType>
-bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode(unsigned op)
-{
- // Returns true, if the given opcode has a range of
- // input values that gives an error.
- if(ComplexType)
- {
- // COMPLEX:
- switch(op)
- {
- case cAtan: // allowed range: x != +-1i
- case cAtanh: // allowed range: x != +-1
- //case cCot: // allowed range: tan(x) != 0
- //case cCsc: // allowed range: sin(x) != 0
- case cLog: // allowed range: x != 0
- case cLog2: // allowed range: x != 0
- case cLog10: // allowed range: x != 0
- #ifdef FP_SUPPORT_OPTIMIZER
- case cLog2by:// allowed range: x != 0
- #endif
- //case cPow: // allowed when: x != 0 or y != 0
- //case cSec: // allowed range: cos(x) != 0
- //case cTan: // allowed range: cos(x) != 0 --> x != +-(pi/2)
- //case cTanh: // allowed range: log(x) != -1 --> x != +-(pi/2)i
- case cRSqrt: // allowed range: x != 0
- //case cDiv: // allowed range: y != 0
- //case cRDiv: // allowed range: x != 0
- //case cInv: // allowed range: x != 0
- return true;
- }
- }
- else
- {
- // REAL:
- switch(op)
- {
- case cAcos: // allowed range: |x| <= 1
- case cAsin: // allowed range: |x| <= 1
- case cAcosh: // allowed range: x >= 1
- case cAtanh: // allowed range: |x| < 1
- //case cCot: // allowed range: tan(x) != 0
- //case cCsc: // allowed range: sin(x) != 0
- case cLog: // allowed range: x > 0
- case cLog2: // allowed range: x > 0
- case cLog10: // allowed range: x > 0
- #ifdef FP_SUPPORT_OPTIMIZER
- case cLog2by:// allowed range: x > 0
- #endif
- //case cPow: // allowed when: x > 0 or (x = 0 and y != 0) or (x<0)
- // Technically, when (x<0 and y is not integer),
- // it is not allowed, but we allow it anyway
- // in order to make nontrivial roots work.
- //case cSec: // allowed range: cos(x) != 0
- case cSqrt: // allowed range: x >= 0
- case cRSqrt: // allowed range: x > 0
- //case cTan: // allowed range: cos(x) != 0 --> x != +-(pi/2)
- //case cDiv: // allowed range: y != 0
- //case cRDiv: // allowed range: x != 0
- //case cInv: // allowed range: x != 0
- return true;
- }
- }
- return false;
-}
-
-template bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode<false>(unsigned op);
-template bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode<true>(unsigned op);
-
-
-#if(0) // Implementation moved to fpaux.hh due to linker problems
-//=========================================================================
-// Mathematical template functions
-//=========================================================================
-/* fp_pow() is a wrapper for std::pow()
- * that produces an identical value for
- * exp(1) ^ 2.0 (0x4000000000000000)
- * as exp(2.0) (0x4000000000000000)
- * - std::pow() on x86_64
- * produces 2.0 (0x3FFFFFFFFFFFFFFF) instead!
- * See comments below for other special traits.
- */
-namespace
-{
- template<typename ValueT>
- inline ValueT fp_pow_with_exp_log(const ValueT& x, const ValueT& y)
- {
- // Exponentiation using exp(log(x)*y).
- // See http://en.wikipedia.org/wiki/Exponentiation#Real_powers
- // Requirements: x > 0.
- return fp_exp(fp_log(x) * y);
- }
-
- template<typename ValueT>
- inline ValueT fp_powi(ValueT x, unsigned long y)
- {
- // Fast binary exponentiation algorithm
- // See http://en.wikipedia.org/wiki/Exponentiation_by_squaring
- // Requirements: y is non-negative integer.
- ValueT result(1);
- while(y != 0)
- {
- if(y & 1) { result *= x; y -= 1; }
- else { x *= x; y /= 2; }
- }
- return result;
- }
-}
-
-template<typename ValueT>
-ValueT FUNCTIONPARSERTYPES::fp_pow(const ValueT& x, const ValueT& y)
-{
- if(x == ValueT(1)) return ValueT(1);
- // y is now zero or positive
- if(isLongInteger(y))
- {
- // Use fast binary exponentiation algorithm
- if(y >= ValueT(0))
- return fp_powi(x, makeLongInteger(y));
- else
- return ValueT(1) / fp_powi(x, -makeLongInteger(y));
- }
- if(y >= ValueT(0))
- {
- // y is now positive. Calculate using exp(log(x)*y).
- if(x > ValueT(0)) return fp_pow_with_exp_log(x, y);
- if(x == ValueT(0)) return ValueT(0);
- // At this point, y > 0.0 and x is known to be < 0.0,
- // because positive and zero cases are already handled.
- if(!isInteger(y*ValueT(16)))
- return -fp_pow_with_exp_log(-x, y);
- // ^This is not technically correct, but it allows
- // functions such as cbrt(x^5), that is, x^(5/3),
- // to be evaluated when x is negative.
- // It is too complicated (and slow) to test whether y
- // is a formed from a ratio of an integer to an odd integer.
- // (And due to floating point inaccuracy, pointless too.)
- // For example, x^1.30769230769... is
- // actually x^(17/13), i.e. (x^17) ^ (1/13).
- // (-5)^(17/13) gives us now -8.204227562330453.
- // To see whether the result is right, we can test the given
- // root: (-8.204227562330453)^13 gives us the value of (-5)^17,
- // which proves that the expression was correct.
- //
- // The y*16 check prevents e.g. (-4)^(3/2) from being calculated,
- // as it would confuse functioninfo when pow() returns no error
- // but sqrt() does when the formula is converted into sqrt(x)*x.
- //
- // The errors in this approach are:
- // (-2)^sqrt(2) should produce NaN
- // or actually sqrt(2)I + 2^sqrt(2),
- // produces -(2^sqrt(2)) instead.
- // (Impact: Neglible)
- // Thus, at worst, we're changing a NaN (or complex)
- // result into a negative real number result.
- }
- else
- {
- // y is negative. Utilize the x^y = 1/(x^-y) identity.
- if(x > ValueT(0)) return fp_pow_with_exp_log(ValueT(1) / x, -y);
- if(x < ValueT(0))
- {
- if(!isInteger(y*ValueT(-16)))
- return -fp_pow_with_exp_log(ValueT(-1) / x, -y);
- // ^ See comment above.
- }
- // Remaining case: 0.0 ^ negative number
- }
- // This is reached when:
- // x=0, and y<0
- // x<0, and y*16 is either positive or negative integer
- // It is used for producing error values and as a safe fallback.
- return fp_pow_base(x, y);
-}
-#endif
-
-
-//=========================================================================
-// Elementary (atom) parsing functions
-//=========================================================================
-namespace
-{
- const unsigned FP_ParamGuardMask = 1U << (sizeof(unsigned) * 8u - 1u);
- // ^ This mask is used to prevent cFetch/other opcode's parameters
- // from being confused into opcodes or variable indices within the
- // bytecode optimizer. Because the way it is tested in bytecoderules.dat
- // for speed reasons, it must also be the sign-bit of the "int" datatype.
- // Perhaps an "assert(IsVarOpcode(X | FP_ParamGuardMask) == false)"
- // might be justified to put somewhere in the code, just in case?
-
-
- /* Reads an UTF8-encoded sequence which forms a valid identifier name from
- the given input string and returns its length. If bit 31 is set, the
- return value also contains the internal function opcode (defined in
- fptypes.hh) that matches the name.
- */
- unsigned readIdentifierCommon(const char* input)
- {
- /* Assuming unsigned = 32 bits:
- 76543210 76543210 76543210 76543210
- Return value if built-in function:
- 1PPPPPPP PPPPPPPP LLLLLLLL LLLLLLLL
- P = function opcode (15 bits)
- L = function name length (16 bits)
- Return value if not built-in function:
- 0LLLLLLL LLLLLLLL LLLLLLLL LLLLLLLL
- L = identifier length (31 bits)
- If unsigned has more than 32 bits, the other
- higher order bits are to be assumed zero.
- */
-#include "extrasrc/fp_identifier_parser.inc"
- return 0;
- }
-
- template<typename Value_t>
- inline unsigned readIdentifier(const char* input)
- {
- const unsigned value = readIdentifierCommon(input);
- if( (value & 0x80000000U) != 0) // Function?
- {
- // Verify that the function actually exists for this datatype
- if(IsIntType<Value_t>::result
- && !Functions[(value >> 16) & 0x7FFF].okForInt())
- {
- // If it does not exist, return it as an identifier instead
- return value & 0xFFFFu;
- }
- if(!IsComplexType<Value_t>::result
- && Functions[(value >> 16) & 0x7FFF].complexOnly())
- {
- // If it does not exist, return it as an identifier instead
- return value & 0xFFFFu;
- }
- }
- return value;
- }
-
- // Returns true if the entire string is a valid identifier
- template<typename Value_t>
- bool containsOnlyValidIdentifierChars(const std::string& name)
- {
- if(name.empty()) return false;
- return readIdentifier<Value_t>(name.c_str()) == (unsigned) name.size();
- }
-
-
- // -----------------------------------------------------------------------
- // Wrappers for strto... functions
- // -----------------------------------------------------------------------
- template<typename Value_t>
- inline Value_t fp_parseLiteral(const char* str, char** endptr)
- {
- return std::strtod(str, endptr);
- }
-
-#if defined(FP_USE_STRTOLD) || defined(FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS)
- template<>
- inline long double fp_parseLiteral<long double>(const char* str,
- char** endptr)
- {
- using namespace std; // Just in case strtold() is not inside std::
- return strtold(str, endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- inline long fp_parseLiteral<long>(const char* str, char** endptr)
- {
- return std::strtol(str, endptr, 10);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- template<typename T>
- inline std::complex<T> fp_parseComplexLiteral(const char* str,
- char** endptr)
- {
- T result = fp_parseLiteral<T> (str,endptr);
- const char* end = *endptr;
- if( (*end == 'i' || *end == 'I')
- && !std::isalnum(end[1]) )
- {
- ++*endptr;
- return std::complex<T> (T(), result);
- }
- return std::complex<T> (result, T());
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
- template<>
- inline std::complex<double> fp_parseLiteral<std::complex<double> >
- (const char* str, char** endptr)
- {
- return fp_parseComplexLiteral<double> (str,endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
- template<>
- inline std::complex<float> fp_parseLiteral<std::complex<float> >
- (const char* str, char** endptr)
- {
- return fp_parseComplexLiteral<float> (str,endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
- template<>
- inline std::complex<long double> fp_parseLiteral<std::complex<long double> >
- (const char* str, char** endptr)
- {
- return fp_parseComplexLiteral<long double> (str,endptr);
- }
-#endif
-
- // -----------------------------------------------------------------------
- // Hexadecimal floating point literal parsing
- // -----------------------------------------------------------------------
- inline int testXdigit(unsigned c)
- {
- if((c-'0') < 10u) return c&15; // 0..9
- if(((c|0x20)-'a') < 6u) return 9+(c&15); // A..F or a..f
- return -1; // Not a hex digit
- }
-
- template<typename elem_t, unsigned n_limbs, unsigned limb_bits>
- inline void addXdigit(elem_t* buffer, unsigned nibble)
- {
- for(unsigned p=0; p<n_limbs; ++p)
- {
- unsigned carry = unsigned( buffer[p] >> (elem_t)(limb_bits-4) );
- buffer[p] = (buffer[p] << 4) | nibble;
- nibble = carry;
- }
- }
-
- template<typename Value_t>
- Value_t parseHexLiteral(const char* str, char** endptr)
- {
- const unsigned bits_per_char = 8;
-
- const int MantissaBits =
- std::numeric_limits<Value_t>::radix == 2
- ? std::numeric_limits<Value_t>::digits
- : (((sizeof(Value_t) * bits_per_char) &~ 3) - 4);
-
- typedef unsigned long elem_t;
- const int ExtraMantissaBits = 4 + ((MantissaBits+3)&~3); // Store one digit more for correct rounding
- const unsigned limb_bits = sizeof(elem_t) * bits_per_char;
- const unsigned n_limbs = (ExtraMantissaBits + limb_bits-1) / limb_bits;
- elem_t mantissa_buffer[n_limbs] = { 0 };
-
- int n_mantissa_bits = 0; // Track the number of bits
- int exponent = 0; // The exponent that will be used to multiply the mantissa
- // Read integer portion
- while(true)
- {
- int xdigit = testXdigit(*str);
- if(xdigit < 0) break;
- addXdigit<elem_t,n_limbs,limb_bits> (mantissa_buffer, xdigit);
- ++str;
-
- n_mantissa_bits += 4;
- if(n_mantissa_bits >= ExtraMantissaBits)
- {
- // Exhausted the precision. Parse the rest (until exponent)
- // normally but ignore the actual digits.
- for(; testXdigit(*str) >= 0; ++str)
- exponent += 4;
- // Read but ignore decimals
- if(*str == '.')
- for(++str; testXdigit(*str) >= 0; ++str)
- {}
- goto read_exponent;
- }
- }
- // Read decimals
- if(*str == '.')
- for(++str; ; )
- {
- int xdigit = testXdigit(*str);
- if(xdigit < 0) break;
- addXdigit<elem_t,n_limbs,limb_bits> (mantissa_buffer, xdigit);
- ++str;
-
- exponent -= 4;
- n_mantissa_bits += 4;
- if(n_mantissa_bits >= ExtraMantissaBits)
- {
- // Exhausted the precision. Skip the rest
- // of the decimals, until the exponent.
- while(testXdigit(*str) >= 0)
- ++str;
- break;
- }
- }
-
- // Read exponent
- read_exponent:
- if(*str == 'p' || *str == 'P')
- {
- const char* str2 = str+1;
- long p_exponent = strtol(str2, const_cast<char**> (&str2), 10);
- if(str2 != str+1 && p_exponent == (long)(int)p_exponent)
- {
- exponent += (int)p_exponent;
- str = str2;
- }
- }
-
- if(endptr) *endptr = const_cast<char*> (str);
-
- Value_t result = std::ldexp(Value_t(mantissa_buffer[0]), exponent);
- for(unsigned p=1; p<n_limbs; ++p)
- {
- exponent += limb_bits;
- result += ldexp(Value_t(mantissa_buffer[p]), exponent);
- }
- return result;
- }
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- long parseHexLiteral<long>(const char* str, char** endptr)
- {
- return std::strtol(str, endptr, 16);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
- template<>
- std::complex<double>
- parseHexLiteral<std::complex<double> >(const char* str, char** endptr)
- {
- return parseHexLiteral<double> (str, endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
- template<>
- std::complex<float>
- parseHexLiteral<std::complex<float> >(const char* str, char** endptr)
- {
- return parseHexLiteral<float> (str, endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
- template<>
- std::complex<long double>
- parseHexLiteral<std::complex<long double> >(const char* str, char** endptr)
- {
- return parseHexLiteral<long double> (str, endptr);
- }
-#endif
-}
-
-//=========================================================================
-// Utility functions
-//=========================================================================
-namespace
-{
- // -----------------------------------------------------------------------
- // Add a new identifier to the specified identifier map
- // -----------------------------------------------------------------------
- // Return value will be false if the name already existed
- template<typename Value_t>
- bool addNewNameData(NamePtrsMap<Value_t>& namePtrs,
- std::pair<NamePtr, NameData<Value_t> >& newName,
- bool isVar)
- {
- typename NamePtrsMap<Value_t>::iterator nameIter =
- namePtrs.lower_bound(newName.first);
-
- if(nameIter != namePtrs.end() && newName.first == nameIter->first)
- {
- // redefining a var is not allowed.
- if(isVar) return false;
-
- // redefining other tokens is allowed, if the type stays the same.
- if(nameIter->second.type != newName.second.type)
- return false;
-
- // update the data
- nameIter->second = newName.second;
- return true;
- }
-
- if(!isVar)
- {
- // Allocate a copy of the name (pointer stored in the map key)
- // However, for VARIABLEs, the pointer points to VariableString,
- // which is managed separately. Thusly, only done when !IsVar.
- char* namebuf = new char[newName.first.nameLength];
- memcpy(namebuf, newName.first.name, newName.first.nameLength);
- newName.first.name = namebuf;
- }
-
- namePtrs.insert(nameIter, newName);
- return true;
- }
-}
-
-
-//=========================================================================
-// Data struct implementation
-//=========================================================================
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::Data():
- mReferenceCounter(1),
- mDelimiterChar(0),
- mParseErrorType(NO_FUNCTION_PARSED_YET),
- mEvalErrorType(0),
- mUseDegreeConversion(false),
- mErrorLocation(0),
- mVariablesAmount(0),
- mStackSize(0)
-{}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::Data(const Data& rhs):
- mReferenceCounter(0),
- mDelimiterChar(rhs.mDelimiterChar),
- mParseErrorType(rhs.mParseErrorType),
- mEvalErrorType(rhs.mEvalErrorType),
- mUseDegreeConversion(rhs.mUseDegreeConversion),
- mErrorLocation(rhs.mErrorLocation),
- mVariablesAmount(rhs.mVariablesAmount),
- mVariablesString(rhs.mVariablesString),
- mNamePtrs(),
- mFuncPtrs(rhs.mFuncPtrs),
- mFuncParsers(rhs.mFuncParsers),
- mByteCode(rhs.mByteCode),
- mImmed(rhs.mImmed),
-#ifndef FP_USE_THREAD_SAFE_EVAL
- mStack(rhs.mStackSize),
-#endif
- mStackSize(rhs.mStackSize)
-{
- for(typename NamePtrsMap<Value_t>::const_iterator i = rhs.mNamePtrs.begin();
- i != rhs.mNamePtrs.end();
- ++i)
- {
- if(i->second.type == NameData<Value_t>::VARIABLE)
- {
- const std::size_t variableStringOffset =
- i->first.name - rhs.mVariablesString.c_str();
- std::pair<NamePtr, NameData<Value_t> > tmp
- (NamePtr(&mVariablesString[variableStringOffset],
- i->first.nameLength),
- i->second);
- mNamePtrs.insert(mNamePtrs.end(), tmp);
- }
- else
- {
- std::pair<NamePtr, NameData<Value_t> > tmp
- (NamePtr(new char[i->first.nameLength], i->first.nameLength),
- i->second );
- memcpy(const_cast<char*>(tmp.first.name), i->first.name,
- tmp.first.nameLength);
- mNamePtrs.insert(mNamePtrs.end(), tmp);
- }
- }
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::~Data()
-{
- for(typename NamePtrsMap<Value_t>::iterator i = mNamePtrs.begin();
- i != mNamePtrs.end();
- ++i)
- {
- if(i->second.type != NameData<Value_t>::VARIABLE)
- delete[] i->first.name;
- }
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::incFuncWrapperRefCount
-(FunctionWrapper* wrapper)
-{
- ++wrapper->mReferenceCount;
-}
-
-template<typename Value_t>
-unsigned FunctionParserBase<Value_t>::decFuncWrapperRefCount
-(FunctionWrapper* wrapper)
-{
- return --wrapper->mReferenceCount;
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::FuncWrapperPtrData():
- mRawFuncPtr(0), mFuncWrapperPtr(0), mParams(0)
-{}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::~FuncWrapperPtrData()
-{
- if(mFuncWrapperPtr &&
- FunctionParserBase::decFuncWrapperRefCount(mFuncWrapperPtr) == 0)
- delete mFuncWrapperPtr;
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::FuncWrapperPtrData
-(const FuncWrapperPtrData& rhs):
- mRawFuncPtr(rhs.mRawFuncPtr),
- mFuncWrapperPtr(rhs.mFuncWrapperPtr),
- mParams(rhs.mParams)
-{
- if(mFuncWrapperPtr)
- FunctionParserBase::incFuncWrapperRefCount(mFuncWrapperPtr);
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::Data::FuncWrapperPtrData&
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::operator=
-(const FuncWrapperPtrData& rhs)
-{
- if(&rhs != this)
- {
- if(mFuncWrapperPtr &&
- FunctionParserBase::decFuncWrapperRefCount(mFuncWrapperPtr) == 0)
- delete mFuncWrapperPtr;
- mRawFuncPtr = rhs.mRawFuncPtr;
- mFuncWrapperPtr = rhs.mFuncWrapperPtr;
- mParams = rhs.mParams;
- if(mFuncWrapperPtr)
- FunctionParserBase::incFuncWrapperRefCount(mFuncWrapperPtr);
- }
- return *this;
-}
-
-
-//=========================================================================
-// FunctionParser constructors, destructor and assignment
-//=========================================================================
-template<typename Value_t>
-FunctionParserBase<Value_t>::FunctionParserBase():
- mData(new Data),
- mStackPtr(0)
-{
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::~FunctionParserBase()
-{
- if(--(mData->mReferenceCounter) == 0)
- delete mData;
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::FunctionParserBase(const FunctionParserBase& cpy):
- mData(cpy.mData),
- mStackPtr(0)
-{
- ++(mData->mReferenceCounter);
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>&
-FunctionParserBase<Value_t>::operator=(const FunctionParserBase& cpy)
-{
- if(mData != cpy.mData)
- {
- if(--(mData->mReferenceCounter) == 0) delete mData;
-
- mData = cpy.mData;
- ++(mData->mReferenceCounter);
- }
- return *this;
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::Data*
-FunctionParserBase<Value_t>::getParserData()
-{
- return mData;
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::setDelimiterChar(char c)
-{
- mData->mDelimiterChar = c;
-}
-
-
-//---------------------------------------------------------------------------
-// Copy-on-write method
-//---------------------------------------------------------------------------
-template<typename Value_t>
-void FunctionParserBase<Value_t>::CopyOnWrite()
-{
- if(mData->mReferenceCounter > 1)
- {
- Data* oldData = mData;
- mData = new Data(*oldData);
- --(oldData->mReferenceCounter);
- mData->mReferenceCounter = 1;
- }
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::ForceDeepCopy()
-{
- CopyOnWrite();
-}
-
-
-//=========================================================================
-// Epsilon
-//=========================================================================
-template<typename Value_t>
-Value_t FunctionParserBase<Value_t>::epsilon()
-{
- return Epsilon<Value_t>::value;
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::setEpsilon(Value_t value)
-{
- Epsilon<Value_t>::value = value;
-}
-
-
-//=========================================================================
-// User-defined identifier addition functions
-//=========================================================================
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddConstant(const std::string& name,
- Value_t value)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::CONSTANT, value));
-
- return addNewNameData(mData->mNamePtrs, newName, false);
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddUnit(const std::string& name,
- Value_t value)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::UNIT, value));
- return addNewNameData(mData->mNamePtrs, newName, false);
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddFunction
-(const std::string& name, FunctionPtr ptr, unsigned paramsAmount)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::FUNC_PTR,
- unsigned(mData->mFuncPtrs.size())));
-
- const bool success = addNewNameData(mData->mNamePtrs, newName, false);
- if(success)
- {
- mData->mFuncPtrs.push_back(typename Data::FuncWrapperPtrData());
- mData->mFuncPtrs.back().mRawFuncPtr = ptr;
- mData->mFuncPtrs.back().mParams = paramsAmount;
- }
- return success;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::addFunctionWrapperPtr
-(const std::string& name, FunctionWrapper* wrapper, unsigned paramsAmount)
-{
- if(!AddFunction(name, FunctionPtr(0), paramsAmount)) return false;
- mData->mFuncPtrs.back().mFuncWrapperPtr = wrapper;
- return true;
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::FunctionWrapper*
-FunctionParserBase<Value_t>::GetFunctionWrapper(const std::string& name)
-{
- CopyOnWrite();
- NamePtr namePtr(name.data(), unsigned(name.size()));
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(namePtr);
-
- if(nameIter != mData->mNamePtrs.end() &&
- nameIter->second.type == NameData<Value_t>::FUNC_PTR)
- {
- return mData->mFuncPtrs[nameIter->second.index].mFuncWrapperPtr;
- }
- return 0;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::CheckRecursiveLinking
-(const FunctionParserBase* fp) const
-{
- if(fp == this) return true;
- for(unsigned i = 0; i < fp->mData->mFuncParsers.size(); ++i)
- if(CheckRecursiveLinking(fp->mData->mFuncParsers[i].mParserPtr))
- return true;
- return false;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddFunction(const std::string& name,
- FunctionParserBase& fp)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name) ||
- CheckRecursiveLinking(&fp))
- return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::PARSER_PTR,
- unsigned(mData->mFuncParsers.size())));
-
- const bool success = addNewNameData(mData->mNamePtrs, newName, false);
- if(success)
- {
- mData->mFuncParsers.push_back(typename Data::FuncParserPtrData());
- mData->mFuncParsers.back().mParserPtr = &fp;
- mData->mFuncParsers.back().mParams = fp.mData->mVariablesAmount;
- }
- return success;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::RemoveIdentifier(const std::string& name)
-{
- CopyOnWrite();
-
- NamePtr namePtr(name.data(), unsigned(name.size()));
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(namePtr);
-
- if(nameIter != mData->mNamePtrs.end())
- {
- if(nameIter->second.type == NameData<Value_t>::VARIABLE)
- {
- // Illegal attempt to delete variables
- return false;
- }
- delete[] nameIter->first.name;
- mData->mNamePtrs.erase(nameIter);
- return true;
- }
- return false;
-}
-
-
-//=========================================================================
-// Function parsing
-//=========================================================================
-namespace
-{
- // Error messages returned by ErrorMsg():
- const char* const ParseErrorMessage[]=
- {
- "Syntax error", // 0
- "Mismatched parenthesis", // 1
- "Missing ')'", // 2
- "Empty parentheses", // 3
- "Syntax error: Operator expected", // 4
- "Not enough memory", // 5
- "An unexpected error occurred. Please make a full bug report "
- "to the author", // 6
- "Syntax error in parameter 'Vars' given to "
- "FunctionParser::Parse()", // 7
- "Illegal number of parameters to function", // 8
- "Syntax error: Premature end of string", // 9
- "Syntax error: Expecting ( after function", // 10
- "Syntax error: Unknown identifier", // 11
- "(No function has been parsed yet)",
- ""
- };
-
- template<typename Value_t>
- inline typename FunctionParserBase<Value_t>::ParseErrorType
- noCommaError(char c)
- {
- return c == ')' ?
- FunctionParserBase<Value_t>::ILL_PARAMS_AMOUNT :
- FunctionParserBase<Value_t>::SYNTAX_ERROR;
- }
-
- template<typename Value_t>
- inline typename FunctionParserBase<Value_t>::ParseErrorType
- noParenthError(char c)
- {
- return c == ',' ?
- FunctionParserBase<Value_t>::ILL_PARAMS_AMOUNT :
- FunctionParserBase<Value_t>::MISSING_PARENTH;
- }
-
- template<unsigned offset>
- struct IntLiteralMask
- {
- enum { mask =
- // ( 1UL << ('-'-offset)) |
- (0x3FFUL << ('0'-offset)) }; /* 0x3FF = 10 bits worth "1" */
- // Note: If you change fparser to support negative numbers parsing
- // (as opposed to parsing them as cNeg followed by literal),
- // enable the '-' line above, and change the offset value
- // in BeginsLiteral() to '-' instead of '.'.
- };
-
- template<typename Value_t, unsigned offset>
- struct LiteralMask
- {
- enum { mask =
- ( 1UL << ('.'-offset)) |
- IntLiteralMask<offset>::mask };
- };
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<unsigned offset>
- struct LiteralMask<long, offset>: public IntLiteralMask<offset>
- {
- };
-#endif
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<unsigned offset>
- struct LiteralMask<GmpInt, offset>: public IntLiteralMask<offset>
- {
- };
-#endif
-
- template<unsigned offset>
- struct SimpleSpaceMask
- {
- enum { mask =
- (1UL << ('\r'-offset)) |
- (1UL << ('\n'-offset)) |
- (1UL << ('\v'-offset)) |
- (1UL << ('\t'-offset)) |
- (1UL << (' ' -offset)) };
- };
-
- template<typename Value_t>
- inline bool BeginsLiteral(unsigned byte)
- {
- enum { n = sizeof(unsigned long)>=8 ? 0 : '.' };
- byte -= n;
- if(byte > (unsigned char)('9'-n)) return false;
- unsigned long shifted = 1UL << byte;
- const unsigned long mask = LiteralMask<Value_t, n>::mask;
- return (mask & shifted) != 0;
- }
-
- template<typename CharPtr>
- inline void SkipSpace(CharPtr& function)
- {
-/*
- Space characters in unicode:
-U+0020 SPACE Depends on font, often adjusted (see below)
-U+00A0 NO-BREAK SPACE As a space, but often not adjusted
-U+2000 EN QUAD 1 en (= 1/2 em)
-U+2001 EM QUAD 1 em (nominally, the height of the font)
-U+2002 EN SPACE 1 en (= 1/2 em)
-U+2003 EM SPACE 1 em
-U+2004 THREE-PER-EM SPACE 1/3 em
-U+2005 FOUR-PER-EM SPACE 1/4 em
-U+2006 SIX-PER-EM SPACE 1/6 em
-U+2007 FIGURE SPACE Tabular width, the width of digits
-U+2008 PUNCTUATION SPACE The width of a period .
-U+2009 THIN SPACE 1/5 em (or sometimes 1/6 em)
-U+200A HAIR SPACE Narrower than THIN SPACE
-U+200B ZERO WIDTH SPACE Nominally no width, but may expand
-U+202F NARROW NO-BREAK SPACE Narrower than NO-BREAK SPACE (or SPACE)
-U+205F MEDIUM MATHEMATICAL SPACE 4/18 em
-U+3000 IDEOGRAPHIC SPACE The width of ideographic (CJK) characters.
- Also:
-U+000A \n
-U+000D \r
-U+0009 \t
-U+000B \v
- As UTF-8 sequences:
- 09
- 0A
- 0B
- 0D
- 20
- C2 A0
- E2 80 80-8B
- E2 80 AF
- E2 81 9F
- E3 80 80
-*/
- while(true)
- {
- enum { n = sizeof(unsigned long)>=8 ? 0 : '\t' };
- typedef signed char schar;
- unsigned byte = (unsigned char)*function;
- byte -= n;
- // ^Note: values smaller than n intentionally become
- // big values here due to integer wrap. The
- // comparison below thus excludes them, making
- // the effective range 0x09..0x20 (32-bit)
- // or 0x00..0x20 (64-bit) within the if-clause.
- if(byte <= (unsigned char)(' '-n))
- {
- unsigned long shifted = 1UL << byte;
- const unsigned long mask = SimpleSpaceMask<n>::mask;
- if(mask & shifted)
- { ++function; continue; } // \r, \n, \t, \v and space
- break;
- }
- if(likely(byte < 0xC2-n)) break;
-
- if(byte == 0xC2-n && function[1] == char(0xA0))
- { function += 2; continue; } // U+00A0
- if(byte == 0xE3-n &&
- function[1] == char(0x80) && function[2] == char(0x80))
- { function += 3; continue; } // U+3000
- if(byte == 0xE2-n)
- {
- if(function[1] == char(0x81))
- {
- if(function[2] != char(0x9F)) break;
- function += 3; // U+205F
- continue;
- }
- if(function[1] == char(0x80))
- if(function[2] == char(0xAF) || // U+202F
- schar(function[2]) <= schar(0x8B) // U+2000..U+200B
- )
- {
- function += 3;
- continue;
- }
- }
- break;
- } // while(true)
- } // SkipSpace(CharPtr& function)
-}
-
-// ---------------------------------------------------------------------------
-// Return parse error message
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::ErrorMsg() const
-{
- return ParseErrorMessage[mData->mParseErrorType];
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::ParseErrorType
-FunctionParserBase<Value_t>::GetParseErrorType() const
-{
- return mData->mParseErrorType;
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::EvalError() const
-{
- return mData->mEvalErrorType;
-}
-
-
-// ---------------------------------------------------------------------------
-// Parse variables
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::ParseVariables
-(const std::string& inputVarString)
-{
- if(mData->mVariablesString == inputVarString) return true;
-
- /* Delete existing variables from mNamePtrs */
- for(typename NamePtrsMap<Value_t>::iterator i =
- mData->mNamePtrs.begin();
- i != mData->mNamePtrs.end(); )
- {
- if(i->second.type == NameData<Value_t>::VARIABLE)
- {
- typename NamePtrsMap<Value_t>::iterator j (i);
- ++i;
- mData->mNamePtrs.erase(j);
- }
- else ++i;
- }
- mData->mVariablesString = inputVarString;
-
- const std::string& vars = mData->mVariablesString;
- const unsigned len = unsigned(vars.size());
-
- unsigned varNumber = VarBegin;
-
- const char* beginPtr = vars.c_str();
- const char* finalPtr = beginPtr + len;
- while(beginPtr < finalPtr)
- {
- SkipSpace(beginPtr);
- unsigned nameLength = readIdentifier<Value_t>(beginPtr);
- if(nameLength == 0 || (nameLength & 0x80000000U)) return false;
- const char* endPtr = beginPtr + nameLength;
- SkipSpace(endPtr);
- if(endPtr != finalPtr && *endPtr != ',') return false;
-
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(beginPtr, nameLength),
- NameData<Value_t>(NameData<Value_t>::VARIABLE, varNumber++));
-
- if(!addNewNameData(mData->mNamePtrs, newName, true))
- {
- return false;
- }
-
- beginPtr = endPtr + 1;
- }
-
- mData->mVariablesAmount = varNumber - VarBegin;
- return true;
-}
-
-// ---------------------------------------------------------------------------
-// Parse() public interface functions
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-int FunctionParserBase<Value_t>::Parse(const char* Function,
- const std::string& Vars,
- bool useDegrees)
-{
- CopyOnWrite();
-
- if(!ParseVariables(Vars))
- {
- mData->mParseErrorType = INVALID_VARS;
- return int(strlen(Function));
- }
-
- return ParseFunction(Function, useDegrees);
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::Parse(const std::string& Function,
- const std::string& Vars,
- bool useDegrees)
-{
- CopyOnWrite();
-
- if(!ParseVariables(Vars))
- {
- mData->mParseErrorType = INVALID_VARS;
- return int(Function.size());
- }
-
- return ParseFunction(Function.c_str(), useDegrees);
-}
-
-
-// ---------------------------------------------------------------------------
-// Main parsing function
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseFunction(const char* function,
- bool useDegrees)
-{
- mData->mUseDegreeConversion = useDegrees;
- mData->mParseErrorType = FP_NO_ERROR;
-
- mData->mInlineVarNames.clear();
- mData->mByteCode.clear(); mData->mByteCode.reserve(128);
- mData->mImmed.clear(); mData->mImmed.reserve(128);
- mData->mStackSize = mStackPtr = 0;
-
- mData->mHasByteCodeFlags = false;
-
- const char* ptr = Compile(function);
- mData->mInlineVarNames.clear();
-
- if(mData->mHasByteCodeFlags)
- {
- for(unsigned i = unsigned(mData->mByteCode.size()); i-- > 0; )
- mData->mByteCode[i] &= ~FP_ParamGuardMask;
- }
-
- if(mData->mParseErrorType != FP_NO_ERROR)
- return int(mData->mErrorLocation - function);
-
- assert(ptr); // Should never be null at this point. It's a bug otherwise.
- if(*ptr)
- {
- if(mData->mDelimiterChar == 0 || *ptr != mData->mDelimiterChar)
- mData->mParseErrorType = EXPECT_OPERATOR;
- return int(ptr - function);
- }
-
-#ifndef FP_USE_THREAD_SAFE_EVAL
- mData->mStack.resize(mData->mStackSize);
-#endif
-
- return -1;
-}
-
-
-//=========================================================================
-// Parsing and bytecode compiling functions
-//=========================================================================
-template<typename Value_t>
-inline const char* FunctionParserBase<Value_t>::SetErrorType(ParseErrorType t,
- const char* pos)
-{
- mData->mParseErrorType = t;
- mData->mErrorLocation = pos;
- return 0;
-}
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::incStackPtr()
-{
- if(++mStackPtr > mData->mStackSize) ++(mData->mStackSize);
-}
-
-namespace
-{
- const unsigned char powi_factor_table[128] =
- {
- 0,1,0,0,0,0,0,0, 0, 0,0,0,0,0,0,3,/* 0 - 15 */
- 0,0,0,0,0,0,0,0, 0, 5,0,3,0,0,3,0,/* 16 - 31 */
- 0,0,0,0,0,0,0,3, 0, 0,0,0,0,5,0,0,/* 32 - 47 */
- 0,0,5,3,0,0,3,5, 0, 3,0,0,3,0,0,3,/* 48 - 63 */
- 0,0,0,0,0,0,0,0, 0, 0,0,3,0,0,3,0,/* 64 - 79 */
- 0,9,0,0,0,5,0,3, 0, 0,5,7,0,0,0,5,/* 80 - 95 */
- 0,0,0,3,5,0,3,0, 0, 3,0,0,3,0,5,3,/* 96 - 111 */
- 0,0,3,5,0,9,0,7, 3,11,0,3,0,5,3,0,/* 112 - 127 */
- };
-
- inline int get_powi_factor(long abs_int_exponent)
- {
- if(abs_int_exponent >= int(sizeof(powi_factor_table))) return 0;
- return powi_factor_table[abs_int_exponent];
- }
-
-#if 0
- int EstimatePowiComplexity(int abs_int_exponent)
- {
- int cost = 0;
- while(abs_int_exponent > 1)
- {
- int factor = get_powi_factor(abs_int_exponent);
- if(factor)
- {
- cost += EstimatePowiComplexity(factor);
- abs_int_exponent /= factor;
- continue;
- }
- if(!(abs_int_exponent & 1))
- {
- abs_int_exponent /= 2;
- cost += 3; // sqr
- }
- else
- {
- cost += 4; // dup+mul
- abs_int_exponent -= 1;
- }
- }
- return cost;
- }
-#endif
-
- bool IsEligibleIntPowiExponent(long int_exponent)
- {
- if(int_exponent == 0) return false;
- long abs_int_exponent = int_exponent;
- #if 0
- int cost = 0;
-
- if(abs_int_exponent < 0)
- {
- cost += 11;
- abs_int_exponent = -abs_int_exponent;
- }
-
- cost += EstimatePowiComplexity(abs_int_exponent);
-
- return cost < (10*3 + 4*4);
- #else
- if(abs_int_exponent < 0) abs_int_exponent = -abs_int_exponent;
-
- return (abs_int_exponent >= 1)
- && (abs_int_exponent <= 46 ||
- (abs_int_exponent <= 1024 &&
- (abs_int_exponent & (abs_int_exponent - 1)) == 0));
- #endif
- }
-
- /* Needed by fp_opcode_add.inc if tracing is enabled */
- template<typename Value_t>
- std::string findName(const NamePtrsMap<Value_t>& nameMap,
- unsigned index,
- typename NameData<Value_t>::DataType type)
- {
- for(typename NamePtrsMap<Value_t>::const_iterator
- iter = nameMap.begin();
- iter != nameMap.end();
- ++iter)
- {
- if(iter->second.type == type && iter->second.index == index)
- return std::string(iter->first.name,
- iter->first.name + iter->first.nameLength);
- }
- return "?";
- }
-}
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::AddImmedOpcode(Value_t value)
-{
- mData->mImmed.push_back(value);
- mData->mByteCode.push_back(cImmed);
-}
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::CompilePowi(long abs_int_exponent)
-{
- int num_muls=0;
- while(abs_int_exponent > 1)
- {
- long factor = get_powi_factor(abs_int_exponent);
- if(factor)
- {
- CompilePowi(factor);
- abs_int_exponent /= factor;
- continue;
- }
- if(!(abs_int_exponent & 1))
- {
- abs_int_exponent /= 2;
- mData->mByteCode.push_back(cSqr);
- // ^ Don't put AddFunctionOpcode here,
- // it would slow down a great deal.
- }
- else
- {
- mData->mByteCode.push_back(cDup);
- incStackPtr();
- abs_int_exponent -= 1;
- ++num_muls;
- }
- }
- if(num_muls > 0)
- {
- mData->mByteCode.resize(mData->mByteCode.size()+num_muls, cMul);
- mStackPtr -= num_muls;
- }
-}
-
-template<typename Value_t>
-inline bool FunctionParserBase<Value_t>::TryCompilePowi(Value_t original_immed)
-{
- Value_t changed_immed = original_immed;
- for(int sqrt_count=0; /**/; ++sqrt_count)
- {
- long int_exponent = makeLongInteger(changed_immed);
- if(isLongInteger(changed_immed) &&
- IsEligibleIntPowiExponent(int_exponent))
- {
- long abs_int_exponent = int_exponent;
- if(abs_int_exponent < 0)
- abs_int_exponent = -abs_int_exponent;
-
- mData->mImmed.pop_back(); mData->mByteCode.pop_back();
- --mStackPtr;
- // ^Though the above is accounted for by the procedure
- // that generates cPow, we need it for correct cFetch
- // indexes in CompilePowi().
-
- while(sqrt_count > 0)
- {
- int opcode = cSqrt;
- if(sqrt_count == 1 && int_exponent < 0)
- {
- opcode = cRSqrt;
- int_exponent = -int_exponent;
- }
- mData->mByteCode.push_back(opcode);
- --sqrt_count;
- }
- if((abs_int_exponent & 1) == 0)
- {
- // This special rule fixes the optimization
- // shortcoming of (-x)^2 with minimal overhead.
- AddFunctionOpcode(cSqr);
- abs_int_exponent >>= 1;
- }
- CompilePowi(abs_int_exponent);
- if(int_exponent < 0) mData->mByteCode.push_back(cInv);
- ++mStackPtr; // Needed because cPow adding will assume this.
- return true;
- }
- if(sqrt_count >= 4) break;
- changed_immed += changed_immed;
- }
-
- // When we don't know whether x >= 0, we still know that
- // x^y can be safely converted into exp(y * log(x))
- // when y is _not_ integer, because we know that x >= 0.
- // Otherwise either expression will give a NaN.
- if(/*!isInteger(original_immed) ||*/
- IsNeverNegativeValueOpcode(mData->mByteCode[mData->mByteCode.size()-2]))
- {
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- //--mStackPtr; - accounted for by the procedure that generates cPow
- AddFunctionOpcode(cLog);
- AddImmedOpcode(original_immed);
- //incStackPtr(); - this and the next are redundant because...
- AddFunctionOpcode(cMul);
- //--mStackPtr; - ...because the cImmed was popped earlier.
- AddFunctionOpcode(cExp);
- return true;
- }
- return false;
-}
-
-//#include "fpoptimizer/opcodename.hh"
-// ^ needed only if FP_TRACE_BYTECODE_OPTIMIZATION() is used
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::AddFunctionOpcode(unsigned opcode)
-{
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 0
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-template<>
-inline void FunctionParserBase<long>::AddFunctionOpcode(unsigned opcode)
-{
- typedef long Value_t;
-#define FP_FLOAT_VERSION 0
-#define FP_COMPLEX_VERSION 0
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-template<>
-inline void FunctionParserBase<GmpInt>::AddFunctionOpcode(unsigned opcode)
-{
- typedef GmpInt Value_t;
-#define FP_FLOAT_VERSION 0
-#define FP_COMPLEX_VERSION 0
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-template<>
-inline void FunctionParserBase<std::complex<double> >::AddFunctionOpcode(unsigned opcode)
-{
- typedef std::complex<double> Value_t;
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 1
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
-template<>
-inline void FunctionParserBase<std::complex<float> >::AddFunctionOpcode(unsigned opcode)
-{
- typedef std::complex<float> Value_t;
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 1
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-template<>
-inline void FunctionParserBase<std::complex<long double> >::AddFunctionOpcode(unsigned opcode)
-{
- typedef std::complex<long double> Value_t;
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 1
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-template<typename Value_t>
-unsigned
-FunctionParserBase<Value_t>::ParseIdentifier(const char* function)
-{
- return readIdentifier<Value_t>(function);
-}
-
-template<typename Value_t>
-std::pair<const char*, Value_t>
-FunctionParserBase<Value_t>::ParseLiteral(const char* function)
-{
- char* endptr;
-#if 0 /* Profile the hex literal parser */
- if(function[0]=='0' && function[1]=='x')
- {
- // Parse hexadecimal literal if fp_parseLiteral didn't already
- Value_t val = parseHexLiteral<Value_t>(function+2, &endptr);
- if(endptr == function+2)
- return std::pair<const char*,Value_t> (function, Value_t());
- return std::pair<const char*, Value_t> (endptr, val);
- }
-#endif
- Value_t val = fp_parseLiteral<Value_t>(function, &endptr);
-
- if(endptr == function+1 && function[0] == '0' && function[1] == 'x')
- {
- // Parse hexadecimal literal if fp_parseLiteral didn't already
- val = parseHexLiteral<Value_t>(function+2, &endptr);
- if(endptr == function+2)
- return std::pair<const char*,Value_t> (function, Value_t());
- }
- else if(endptr == function)
- return std::pair<const char*,Value_t> (function, Value_t());
-
- return std::pair<const char*,Value_t> (endptr, val);
-}
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-template<>
-std::pair<const char*, MpfrFloat>
-FunctionParserBase<MpfrFloat>::ParseLiteral(const char* function)
-{
- char* endPtr;
- const MpfrFloat val = MpfrFloat::parseString(function, &endPtr);
- if(endPtr == function)
- return std::pair<const char*,MpfrFloat> (function, MpfrFloat());
- return std::pair<const char*,MpfrFloat> (endPtr, val);
-}
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-template<>
-std::pair<const char*, GmpInt>
-FunctionParserBase<GmpInt>::ParseLiteral(const char* function)
-{
- char* endPtr;
- const GmpInt val = GmpInt::parseString(function, &endPtr);
- if(endPtr == function)
- return std::pair<const char*,GmpInt> (function, GmpInt());
- return std::pair<const char*,GmpInt> (endPtr, val);
-}
-#endif
-
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileLiteral(const char* function)
-{
- std::pair<const char*, Value_t> result = ParseLiteral(function);
-
- if(result.first == function)
- return SetErrorType(SYNTAX_ERROR, result.first);
-
- AddImmedOpcode(result.second);
- incStackPtr();
- SkipSpace(result.first);
- return result.first;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileIf(const char* function)
-{
- if(*function != '(') return SetErrorType(EXPECT_PARENTH_FUNC, function);
-
- function = CompileExpression(function+1);
- if(!function) return 0;
- if(*function != ',')
- return SetErrorType(noCommaError<Value_t>(*function), function);
-
- OPCODE opcode = cIf;
- if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
- if(IsNeverNegativeValueOpcode(mData->mByteCode.back()))
- {
- // If we know that the condition to be tested is always
- // a positive value (such as when produced by "x<y"),
- // we can use the faster opcode to evaluate it.
- // cIf tests whether fabs(cond) >= 0.5,
- // cAbsIf simply tests whether cond >= 0.5.
- opcode = cAbsIf;
- }
-
- mData->mByteCode.push_back(opcode);
- const unsigned curByteCodeSize = unsigned(mData->mByteCode.size());
- PushOpcodeParam<false>(0); // Jump index; to be set later
- PushOpcodeParam<true> (0); // Immed jump index; to be set later
-
- --mStackPtr;
-
- function = CompileExpression(function + 1);
- if(!function) return 0;
- if(*function != ',')
- return SetErrorType(noCommaError<Value_t>(*function), function);
-
- mData->mByteCode.push_back(cJump);
- const unsigned curByteCodeSize2 = unsigned(mData->mByteCode.size());
- const unsigned curImmedSize2 = unsigned(mData->mImmed.size());
- PushOpcodeParam<false>(0); // Jump index; to be set later
- PushOpcodeParam<true> (0); // Immed jump index; to be set later
-
- --mStackPtr;
-
- function = CompileExpression(function + 1);
- if(!function) return 0;
- if(*function != ')')
- return SetErrorType(noParenthError<Value_t>(*function), function);
-
- PutOpcodeParamAt<true> ( mData->mByteCode.back(), unsigned(mData->mByteCode.size()-1) );
- // ^Necessary for guarding against if(x,1,2)+1 being changed
- // into if(x,1,3) by fp_opcode_add.inc
-
- // Set jump indices
- PutOpcodeParamAt<false>( curByteCodeSize2+1, curByteCodeSize );
- PutOpcodeParamAt<false>( curImmedSize2, curByteCodeSize+1 );
- PutOpcodeParamAt<false>( unsigned(mData->mByteCode.size())-1, curByteCodeSize2);
- PutOpcodeParamAt<false>( unsigned(mData->mImmed.size()), curByteCodeSize2+1);
-
- ++function;
- SkipSpace(function);
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileFunctionParams
-(const char* function, unsigned requiredParams)
-{
- if(*function != '(') return SetErrorType(EXPECT_PARENTH_FUNC, function);
-
- if(requiredParams > 0)
- {
- const char* function_end = CompileExpression(function+1);
- if(!function_end)
- {
- // If an error occurred, verify whether it was caused by ()
- ++function;
- SkipSpace(function);
- if(*function == ')')
- return SetErrorType(ILL_PARAMS_AMOUNT, function);
- // Not caused by (), use the error message given by CompileExpression()
- return 0;
- }
- function = function_end;
-
- for(unsigned i = 1; i < requiredParams; ++i)
- {
- if(*function != ',')
- return SetErrorType(noCommaError<Value_t>(*function), function);
-
- function = CompileExpression(function+1);
- if(!function) return 0;
- }
- // No need for incStackPtr() because each parse parameter calls it
- mStackPtr -= requiredParams-1;
- }
- else
- {
- incStackPtr(); // return value of function is pushed onto the stack
- ++function;
- SkipSpace(function);
- }
-
- if(*function != ')')
- return SetErrorType(noParenthError<Value_t>(*function), function);
- ++function;
- SkipSpace(function);
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileElement(const char* function)
-{
- if(BeginsLiteral<Value_t>( (unsigned char) *function))
- return CompileLiteral(function);
-
- unsigned nameLength = readIdentifier<Value_t>(function);
- if(nameLength == 0)
- {
- // No identifier found
- if(*function == '(') return CompileParenthesis(function);
- if(*function == ')') return SetErrorType(MISM_PARENTH, function);
- return SetErrorType(SYNTAX_ERROR, function);
- }
-
- // Function, variable or constant
- if(nameLength & 0x80000000U) // Function
- {
- OPCODE func_opcode = OPCODE( (nameLength >> 16) & 0x7FFF );
- return CompileFunction(function + (nameLength & 0xFFFF), func_opcode);
- }
-
- NamePtr name(function, nameLength);
- const char* endPtr = function + nameLength;
- SkipSpace(endPtr);
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(name);
- if(nameIter == mData->mNamePtrs.end())
- {
- // Check if it's an inline variable:
- for(typename Data::InlineVarNamesContainer::reverse_iterator iter =
- mData->mInlineVarNames.rbegin();
- iter != mData->mInlineVarNames.rend();
- ++iter)
- {
- if(name == iter->mName)
- {
- if( iter->mFetchIndex+1 == mStackPtr)
- {
- mData->mByteCode.push_back(cDup);
- }
- else
- {
- mData->mByteCode.push_back(cFetch);
- PushOpcodeParam<true>(iter->mFetchIndex);
- }
- incStackPtr();
- return endPtr;
- }
- }
-
- return SetErrorType(UNKNOWN_IDENTIFIER, function);
- }
-
- const NameData<Value_t>* nameData = &nameIter->second;
- switch(nameData->type)
- {
- case NameData<Value_t>::VARIABLE: // is variable
- if(unlikely(!mData->mByteCode.empty() &&
- mData->mByteCode.back() == nameData->index))
- mData->mByteCode.push_back(cDup);
- else
- mData->mByteCode.push_back(nameData->index);
- incStackPtr();
- return endPtr;
-
- case NameData<Value_t>::CONSTANT: // is constant
- AddImmedOpcode(nameData->value);
- incStackPtr();
- return endPtr;
-
- case NameData<Value_t>::UNIT: // is unit (error if appears here)
- break;
-
- case NameData<Value_t>::FUNC_PTR: // is C++ function
- function = CompileFunctionParams
- (endPtr, mData->mFuncPtrs[nameData->index].mParams);
- //if(!function) return 0;
- mData->mByteCode.push_back(cFCall);
- PushOpcodeParam<true>(nameData->index);
- return function;
-
- case NameData<Value_t>::PARSER_PTR: // is FunctionParser
- function = CompileFunctionParams
- (endPtr, mData->mFuncParsers[nameData->index].mParams);
- //if(!function) return 0;
- mData->mByteCode.push_back(cPCall);
- PushOpcodeParam<true>(nameData->index);
- return function;
- }
-
- // When it's an unit (or unrecognized type):
- return SetErrorType(SYNTAX_ERROR, function);
-}
-
-template<typename Value_t>
-inline const char* FunctionParserBase<Value_t>::CompileFunction
-(const char* function, unsigned func_opcode)
-{
- SkipSpace(function);
- const FuncDefinition& funcDef = Functions[func_opcode];
-
- if(func_opcode == cIf) // "if" is a special case
- return CompileIf(function);
-
- unsigned requiredParams = funcDef.params;
-
- function = CompileFunctionParams(function, requiredParams);
- if(!function) return 0;
-
- if(mData->mUseDegreeConversion)
- {
- if(funcDef.flags & FuncDefinition::AngleIn)
- AddFunctionOpcode(cRad);
-
- AddFunctionOpcode(func_opcode);
-
- if(funcDef.flags & FuncDefinition::AngleOut)
- AddFunctionOpcode(cDeg);
- }
- else
- {
- AddFunctionOpcode(func_opcode);
- }
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileParenthesis(const char* function)
-{
- ++function; // Skip '('
-
- SkipSpace(function);
- if(*function == ')') return SetErrorType(EMPTY_PARENTH, function);
- function = CompileExpression(function);
- if(!function) return 0;
-
- if(*function != ')') return SetErrorType(MISSING_PARENTH, function);
- ++function; // Skip ')'
-
- SkipSpace(function);
- return function;
-}
-
-template<typename Value_t>
-const char*
-FunctionParserBase<Value_t>::CompilePossibleUnit(const char* function)
-{
- unsigned nameLength = readIdentifier<Value_t>(function);
- if(nameLength & 0x80000000U) return function; // built-in function name
- if(nameLength != 0)
- {
- NamePtr name(function, nameLength);
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(name);
- if(nameIter != mData->mNamePtrs.end())
- {
- const NameData<Value_t>* nameData = &nameIter->second;
- if(nameData->type == NameData<Value_t>::UNIT)
- {
- AddImmedOpcode(nameData->value);
- incStackPtr();
- AddFunctionOpcode(cMul);
- --mStackPtr;
-
- const char* endPtr = function + nameLength;
- SkipSpace(endPtr);
- return endPtr;
- }
- }
- }
-
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompilePow(const char* function)
-{
- function = CompileElement(function);
- if(!function) return 0;
- function = CompilePossibleUnit(function);
-
- if(*function == '^')
- {
- ++function;
- SkipSpace(function);
-
- unsigned op = cPow;
- if(mData->mByteCode.back() == cImmed)
- {
- if(mData->mImmed.back() == fp_const_e<Value_t>())
- { op = cExp; mData->mByteCode.pop_back();
- mData->mImmed.pop_back(); --mStackPtr; }
- else if(mData->mImmed.back() == Value_t(2))
- { op = cExp2; mData->mByteCode.pop_back();
- mData->mImmed.pop_back(); --mStackPtr; }
- }
-
- function = CompileUnaryMinus(function);
- if(!function) return 0;
-
- // add opcode
- AddFunctionOpcode(op);
-
- if(op == cPow) --mStackPtr;
- }
- return function;
-}
-
-/* Currently the power operator is skipped for integral types because its
- usefulness with them is questionable, and in the case of GmpInt, for safety
- reasons:
- - With long int almost any power, except for very small ones, would
- overflow the result, so the usefulness of this is rather questionable.
- - With GmpInt the power operator could be easily abused to make the program
- run out of memory (think of a function like "10^10^10^10^1000000").
-*/
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-template<>
-inline const char*
-FunctionParserBase<long>::CompilePow(const char* function)
-{
- function = CompileElement(function);
- if(!function) return 0;
- return CompilePossibleUnit(function);
-}
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-template<>
-inline const char*
-FunctionParserBase<GmpInt>::CompilePow(const char* function)
-{
- function = CompileElement(function);
- if(!function) return 0;
- return CompilePossibleUnit(function);
-}
-#endif
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileUnaryMinus(const char* function)
-{
- char op = *function;
- switch(op)
- {
- case '-':
- case '!':
- ++function;
- SkipSpace(function);
-
- function = CompileUnaryMinus(function);
- if(!function) return 0;
-
- AddFunctionOpcode(op=='-' ? cNeg : cNot);
-
- return function;
- default: break;
- }
- return CompilePow(function);
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileMult(const char* function)
-{
- function = CompileUnaryMinus(function);
- if(!function) return 0;
-
- Value_t pending_immed(1);
- #define FP_FlushImmed(do_reset) \
- if(pending_immed != Value_t(1)) \
- { \
- unsigned op = cMul; \
- if(!IsIntType<Value_t>::result && mData->mByteCode.back() == cInv) \
- { \
- /* (...) cInv 5 cMul -> (...) 5 cRDiv */ \
- /* ^ ^ | */ \
- mData->mByteCode.pop_back(); \
- op = cRDiv; \
- } \
- AddImmedOpcode(pending_immed); \
- incStackPtr(); \
- AddFunctionOpcode(op); \
- --mStackPtr; \
- if(do_reset) pending_immed = Value_t(1); \
- }
- while(true)
- {
- char c = *function;
- if(c == '%')
- {
- FP_FlushImmed(true);
- ++function;
- SkipSpace(function);
- function = CompileUnaryMinus(function);
- if(!function) return 0;
- AddFunctionOpcode(cMod);
- --mStackPtr;
- continue;
- }
- if(c != '*' && c != '/') break;
-
- bool safe_cumulation = (c == '*' || !IsIntType<Value_t>::result);
- if(!safe_cumulation)
- {
- FP_FlushImmed(true);
- }
-
- ++function;
- SkipSpace(function);
- if(mData->mByteCode.back() == cImmed
- && (safe_cumulation
- || mData->mImmed.back() == Value_t(1)))
- {
- // 5 (...) cMul --> (...) ||| 5 cMul
- // 5 (...) cDiv --> (...) cInv ||| 5 cMul
- // ^ | ^
- pending_immed *= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- --mStackPtr;
- function = CompileUnaryMinus(function);
- if(!function) return 0;
- if(c == '/')
- AddFunctionOpcode(cInv);
- continue;
- }
- if(safe_cumulation
- && mData->mByteCode.back() == cMul
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) 5 cMul (...) cMul -> (:::) (...) cMul ||| 5 cMul
- // (:::) 5 cMul (...) cDiv -> (:::) (...) cDiv ||| 5 cMul
- // ^ ^
- pending_immed *= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- // cDiv is not tested here because the bytecode
- // optimizer will convert this kind of cDivs into cMuls.
- bool lhs_inverted = false;
- if(!IsIntType<Value_t>::result && c == '*'
- && mData->mByteCode.back() == cInv)
- {
- // (:::) cInv (...) cMul -> (:::) (...) cRDiv
- // (:::) cInv (...) cDiv -> (:::) (...) cMul cInv
- // ^ ^ |
- mData->mByteCode.pop_back();
- lhs_inverted = true;
- }
- function = CompileUnaryMinus(function);
- if(!function) return 0;
- if(safe_cumulation
- && mData->mByteCode.back() == cMul
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cMul cMul -> (:::) (...) cMul ||| 5 Mul
- // (:::) (...) 5 cMul cDiv -> (:::) (...) cDiv ||| /5 Mul
- // ^ ^
- if(c == '*')
- pending_immed *= mData->mImmed.back();
- else
- pending_immed /= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- else
- if(safe_cumulation
- && mData->mByteCode.back() == cRDiv
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cRDiv cMul -> (:::) (...) cDiv ||| 5 cMul
- // (:::) (...) 5 cRDiv cDiv -> (:::) (...) cMul ||| /5 cMul
- // ^ ^
- if(c == '*')
- { c = '/'; pending_immed *= mData->mImmed.back(); }
- else
- { c = '*'; pending_immed /= mData->mImmed.back(); }
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- if(!lhs_inverted) // if (/x/y) was changed to /(x*y), add missing cInv
- {
- AddFunctionOpcode(c == '*' ? cMul : cDiv);
- --mStackPtr;
- }
- else if(c == '*') // (/x)*y -> rdiv(x,y)
- {
- AddFunctionOpcode(cRDiv);
- --mStackPtr;
- }
- else // (/x)/y -> /(x*y)
- {
- AddFunctionOpcode(cMul);
- --mStackPtr;
- AddFunctionOpcode(cInv);
- }
- }
- FP_FlushImmed(false);
- #undef FP_FlushImmed
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileAddition(const char* function)
-{
- function = CompileMult(function);
- if(!function) return 0;
-
- Value_t pending_immed(0);
- #define FP_FlushImmed(do_reset) \
- if(pending_immed != Value_t(0)) \
- { \
- unsigned op = cAdd; \
- if(mData->mByteCode.back() == cNeg) \
- { \
- /* (...) cNeg 5 cAdd -> (...) 5 cRSub */ \
- /* ^ ^ | */ \
- mData->mByteCode.pop_back(); \
- op = cRSub; \
- } \
- AddImmedOpcode(pending_immed); \
- incStackPtr(); \
- AddFunctionOpcode(op); \
- --mStackPtr; \
- if(do_reset) pending_immed = Value_t(0); \
- }
- while(true)
- {
- char c = *function;
- if(c != '+' && c != '-') break;
- ++function;
- SkipSpace(function);
- if(mData->mByteCode.back() == cImmed)
- {
- // 5 (...) cAdd --> (...) ||| 5 cAdd
- // 5 (...) cSub --> (...) cNeg ||| 5 cAdd
- // ^ | ^
- pending_immed += mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- --mStackPtr;
- function = CompileMult(function);
- if(!function) return 0;
- if(c == '-')
- AddFunctionOpcode(cNeg);
- continue;
- }
- if(mData->mByteCode.back() == cAdd
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) 5 cAdd (...) cAdd -> (:::) (...) cAdd ||| 5 cAdd
- // (:::) 5 cAdd (...) cSub -> (:::) (...) cSub ||| 5 cAdd
- // ^ ^
- pending_immed += mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- // cSub is not tested here because the bytecode
- // optimizer will convert this kind of cSubs into cAdds.
- bool lhs_negated = false;
- if(mData->mByteCode.back() == cNeg)
- {
- // (:::) cNeg (...) cAdd -> (:::) (...) cRSub
- // (:::) cNeg (...) cSub -> (:::) (...) cAdd cNeg
- // ^ ^ |
- mData->mByteCode.pop_back();
- lhs_negated = true;
- }
- function = CompileMult(function);
- if(!function) return 0;
- if(mData->mByteCode.back() == cAdd
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cAdd cAdd -> (:::) (...) cAdd ||| 5 Add
- // (:::) (...) 5 cAdd cSub -> (:::) (...) cSub ||| -5 Add
- // ^ ^
- if(c == '+')
- pending_immed += mData->mImmed.back();
- else
- pending_immed -= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- else
- if(mData->mByteCode.back() == cRSub
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cRSub cAdd -> (:::) (...) cSub ||| 5 cAdd
- // (:::) (...) 5 cRSub cSub -> (:::) (...) cAdd ||| -5 cAdd
- // ^ ^
- if(c == '+')
- { c = '-'; pending_immed += mData->mImmed.back(); }
- else
- { c = '+'; pending_immed -= mData->mImmed.back(); }
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- if(!lhs_negated) // if (-x-y) was changed to -(x+y), add missing cNeg
- {
- AddFunctionOpcode(c == '+' ? cAdd : cSub);
- --mStackPtr;
- }
- else if(c == '+') // (-x)+y -> rsub(x,y)
- {
- AddFunctionOpcode(cRSub);
- --mStackPtr;
- }
- else // (-x)-y -> -(x+y)
- {
- AddFunctionOpcode(cAdd);
- --mStackPtr;
- AddFunctionOpcode(cNeg);
- }
- }
- FP_FlushImmed(false);
- #undef FP_FlushImmed
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileComparison(const char* function)
-{
- unsigned op=0;
- while(true)
- {
- function = CompileAddition(function);
- if(!function) return 0;
-
- if(op)
- {
- AddFunctionOpcode(op);
- --mStackPtr;
- }
- switch(*function)
- {
- case '=':
- ++function; op = cEqual; break;
- case '!':
- if(function[1] == '=')
- { function += 2; op = cNEqual; break; }
- // If '=' does not follow '!', a syntax error will
- // be generated at the outermost parsing level
- return function;
- case '<':
- if(function[1] == '=')
- { function += 2; op = cLessOrEq; break; }
- ++function; op = cLess; break;
- case '>':
- if(function[1] == '=')
- { function += 2; op = cGreaterOrEq; break; }
- ++function; op = cGreater; break;
- default: return function;
- }
- SkipSpace(function);
- }
- return function;
-}
-
-template<typename Value_t>
-inline const char* FunctionParserBase<Value_t>::CompileAnd(const char* function)
-{
- std::size_t param0end=0;
- while(true)
- {
- function = CompileComparison(function);
- if(!function) return 0;
-
- if(param0end)
- {
- if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
-
- AddFunctionOpcode(cAnd);
- --mStackPtr;
- }
- if(*function != '&') break;
- ++function;
- SkipSpace(function);
- param0end = mData->mByteCode.size();
- }
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileExpression(const char* function)
-{
- std::size_t param0end=0;
- while(true)
- {
- SkipSpace(function);
- function = CompileAnd(function);
- if(!function) return 0;
-
- if(param0end)
- {
- if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
-
- AddFunctionOpcode(cOr);
- --mStackPtr;
- }
- if(*function != '|') break;
- ++function;
- param0end = mData->mByteCode.size();
- }
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::Compile(const char* function)
-{
- while(true)
- {
- // Check if an identifier appears as first token:
- SkipSpace(function);
- unsigned nameLength = readIdentifier<Value_t>(function);
- if(nameLength > 0 && !(nameLength & 0x80000000U))
- {
- typename Data::InlineVariable inlineVar =
- { NamePtr(function, nameLength), 0 };
-
- // Check if it's an unknown identifier:
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(inlineVar.mName);
- if(nameIter == mData->mNamePtrs.end())
- {
- const char* function2 = function + nameLength;
- SkipSpace(function2);
-
- // Check if ":=" follows the unknown identifier:
- if(function2[0] == ':' && function2[1] == '=')
- {
- // Parse the expression that follows and create the
- // inline variable:
- function2 = CompileExpression(function2 + 2);
- if(!function2) return 0;
- if(*function2 != ';') return function2;
-
- inlineVar.mFetchIndex = mStackPtr - 1;
- mData->mInlineVarNames.push_back(inlineVar);
-
- // Continue with the expression after the ';':
- function = function2 + 1;
- continue;
- }
- }
- }
- break;
- }
-
- return CompileExpression(function);
-}
-
-template<typename Value_t> template<bool PutFlag>
-inline void FunctionParserBase<Value_t>::PushOpcodeParam
- (unsigned value)
-{
- mData->mByteCode.push_back(value | (PutFlag ? FP_ParamGuardMask : 0u));
- if(PutFlag) mData->mHasByteCodeFlags = true;
-}
-
-template<typename Value_t> template<bool PutFlag>
-inline void FunctionParserBase<Value_t>::PutOpcodeParamAt
- (unsigned value, unsigned offset)
-{
- mData->mByteCode[offset] = value | (PutFlag ? FP_ParamGuardMask : 0u);
- if(PutFlag) mData->mHasByteCodeFlags = true;
-}
-
-//===========================================================================
-// Function evaluation
-//===========================================================================
-template<typename Value_t>
-Value_t FunctionParserBase<Value_t>::Eval(const Value_t* Vars)
-{
- if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0);
-
- const unsigned* const byteCode = &(mData->mByteCode[0]);
- const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]);
- const unsigned byteCodeSize = unsigned(mData->mByteCode.size());
- unsigned IP, DP=0;
- int SP=-1;
-
-#ifdef FP_USE_THREAD_SAFE_EVAL
- /* If Eval() may be called by multiple threads simultaneously,
- * then Eval() must allocate its own stack.
- */
-#ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
- /* alloca() allocates room from the hardware stack.
- * It is automatically freed when the function returns.
- */
- Value_t* const Stack = (Value_t*)alloca(mData->mStackSize*sizeof(Value_t));
-#else
- /* Allocate from the heap. Ensure that it is freed
- * automatically no matter which exit path is taken.
- */
- struct AutoDealloc
- {
- Value_t* ptr;
- ~AutoDealloc() { delete[] ptr; }
- } AutoDeallocStack = { new Value_t[mData->mStackSize] };
- Value_t*& Stack = AutoDeallocStack.ptr;
-#endif
-#else
- /* No thread safety, so use a global stack. */
- std::vector<Value_t>& Stack = mData->mStack;
-#endif
-
- for(IP=0; IP<byteCodeSize; ++IP)
- {
- switch(byteCode[IP])
- {
-// Functions:
- case cAbs: Stack[SP] = fp_abs(Stack[SP]); break;
-
- case cAcos:
- if(IsComplexType<Value_t>::result == false
- && (Stack[SP] < Value_t(-1) || Stack[SP] > Value_t(1)))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_acos(Stack[SP]); break;
-
- case cAcosh:
- if(IsComplexType<Value_t>::result == false
- && Stack[SP] < Value_t(1))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_acosh(Stack[SP]); break;
-
- case cAsin:
- if(IsComplexType<Value_t>::result == false
- && (Stack[SP] < Value_t(-1) || Stack[SP] > Value_t(1)))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_asin(Stack[SP]); break;
-
- case cAsinh: Stack[SP] = fp_asinh(Stack[SP]); break;
-
- case cAtan: Stack[SP] = fp_atan(Stack[SP]); break;
-
- case cAtan2: Stack[SP-1] = fp_atan2(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cAtanh:
- if(IsComplexType<Value_t>::result
- ? (Stack[SP] == Value_t(-1) || Stack[SP] == Value_t(1))
- : (Stack[SP] <= Value_t(-1) || Stack[SP] >= Value_t(1)))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_atanh(Stack[SP]); break;
-
- case cCbrt: Stack[SP] = fp_cbrt(Stack[SP]); break;
-
- case cCeil: Stack[SP] = fp_ceil(Stack[SP]); break;
-
- case cCos: Stack[SP] = fp_cos(Stack[SP]); break;
-
- case cCosh: Stack[SP] = fp_cosh(Stack[SP]); break;
-
- case cCot:
- {
- const Value_t t = fp_tan(Stack[SP]);
- if(t == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/t; break;
- }
-
- case cCsc:
- {
- const Value_t s = fp_sin(Stack[SP]);
- if(s == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/s; break;
- }
-
-
- case cExp: Stack[SP] = fp_exp(Stack[SP]); break;
-
- case cExp2: Stack[SP] = fp_exp2(Stack[SP]); break;
-
- case cFloor: Stack[SP] = fp_floor(Stack[SP]); break;
-
- case cHypot:
- Stack[SP-1] = fp_hypot(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cIf:
- if(fp_truth(Stack[SP--]))
- IP += 2;
- else
- {
- const unsigned* buf = &byteCode[IP+1];
- IP = buf[0];
- DP = buf[1];
- }
- break;
-
- case cInt: Stack[SP] = fp_int(Stack[SP]); break;
-
- case cLog:
- if(IsComplexType<Value_t>::result
- ? Stack[SP] == Value_t(0)
- : !(Stack[SP] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP] = fp_log(Stack[SP]); break;
-
- case cLog10:
- if(IsComplexType<Value_t>::result
- ? Stack[SP] == Value_t(0)
- : !(Stack[SP] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP] = fp_log10(Stack[SP]);
- break;
-
- case cLog2:
- if(IsComplexType<Value_t>::result
- ? Stack[SP] == Value_t(0)
- : !(Stack[SP] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP] = fp_log2(Stack[SP]);
- break;
-
- case cMax: Stack[SP-1] = fp_max(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cMin: Stack[SP-1] = fp_min(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cPow:
- // x:Negative ^ y:NonInteger is failure,
- // except when the reciprocal of y forms an integer
- /*if(IsComplexType<Value_t>::result == false
- && Stack[SP-1] < Value_t(0) &&
- !isInteger(Stack[SP]) &&
- !isInteger(1.0 / Stack[SP]))
- { mEvalErrorType=3; return Value_t(0); }*/
- // x:0 ^ y:negative is failure
- if(Stack[SP-1] == Value_t(0) &&
- Stack[SP] < Value_t(0))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cTrunc: Stack[SP] = fp_trunc(Stack[SP]); break;
-
- case cSec:
- {
- const Value_t c = fp_cos(Stack[SP]);
- if(c == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/c; break;
- }
-
- case cSin: Stack[SP] = fp_sin(Stack[SP]); break;
-
- case cSinh: Stack[SP] = fp_sinh(Stack[SP]); break;
-
- case cSqrt:
- if(IsComplexType<Value_t>::result == false &&
- Stack[SP] < Value_t(0))
- { mData->mEvalErrorType=2; return Value_t(0); }
- Stack[SP] = fp_sqrt(Stack[SP]); break;
-
- case cTan: Stack[SP] = fp_tan(Stack[SP]); break;
-
- case cTanh: Stack[SP] = fp_tanh(Stack[SP]); break;
-
-
-// Misc:
- case cImmed: Stack[++SP] = immed[DP++]; break;
-
- case cJump:
- {
- const unsigned* buf = &byteCode[IP+1];
- IP = buf[0];
- DP = buf[1];
- break;
- }
-
-// Operators:
- case cNeg: Stack[SP] = -Stack[SP]; break;
- case cAdd: Stack[SP-1] += Stack[SP]; --SP; break;
- case cSub: Stack[SP-1] -= Stack[SP]; --SP; break;
- case cMul: Stack[SP-1] *= Stack[SP]; --SP; break;
-
- case cDiv:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP-1] /= Stack[SP]; --SP; break;
-
- case cMod:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP-1] = fp_mod(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cEqual:
- Stack[SP-1] = fp_equal(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cNEqual:
- Stack[SP-1] = fp_nequal(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cLess:
- Stack[SP-1] = fp_less(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cLessOrEq:
- Stack[SP-1] = fp_lessOrEq(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cGreater:
- Stack[SP-1] = fp_less(Stack[SP], Stack[SP-1]);
- --SP; break;
-
- case cGreaterOrEq:
- Stack[SP-1] = fp_lessOrEq(Stack[SP], Stack[SP-1]);
- --SP; break;
-
- case cNot: Stack[SP] = fp_not(Stack[SP]); break;
-
- case cNotNot: Stack[SP] = fp_notNot(Stack[SP]); break;
-
- case cAnd:
- Stack[SP-1] = fp_and(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cOr:
- Stack[SP-1] = fp_or(Stack[SP-1], Stack[SP]);
- --SP; break;
-
-// Degrees-radians conversion:
- case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break;
- case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break;
-
-// User-defined function calls:
- case cFCall:
- {
- const unsigned index = byteCode[++IP];
- const unsigned params = mData->mFuncPtrs[index].mParams;
- const Value_t retVal =
- mData->mFuncPtrs[index].mRawFuncPtr ?
- mData->mFuncPtrs[index].mRawFuncPtr(&Stack[SP-params+1]) :
- mData->mFuncPtrs[index].mFuncWrapperPtr->callFunction
- (&Stack[SP-params+1]);
- SP -= int(params)-1;
- Stack[SP] = retVal;
- break;
- }
-
- case cPCall:
- {
- unsigned index = byteCode[++IP];
- unsigned params = mData->mFuncParsers[index].mParams;
- Value_t retVal =
- mData->mFuncParsers[index].mParserPtr->Eval
- (&Stack[SP-params+1]);
- SP -= int(params)-1;
- Stack[SP] = retVal;
- const int error =
- mData->mFuncParsers[index].mParserPtr->EvalError();
- if(error)
- {
- mData->mEvalErrorType = error;
- return 0;
- }
- break;
- }
-
-
- case cFetch:
- {
- unsigned stackOffs = byteCode[++IP];
- Stack[SP+1] = Stack[stackOffs]; ++SP;
- break;
- }
-
-#ifdef FP_SUPPORT_OPTIMIZER
- case cPopNMov:
- {
- unsigned stackOffs_target = byteCode[++IP];
- unsigned stackOffs_source = byteCode[++IP];
- Stack[stackOffs_target] = Stack[stackOffs_source];
- SP = stackOffs_target;
- break;
- }
-
- case cLog2by:
- if(IsComplexType<Value_t>::result
- ? Stack[SP-1] == Value_t(0)
- : !(Stack[SP-1] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP-1] = fp_log2(Stack[SP-1]) * Stack[SP];
- --SP;
- break;
-
- case cNop: break;
-#endif // FP_SUPPORT_OPTIMIZER
-
- case cSinCos:
- fp_sinCos(Stack[SP], Stack[SP+1], Stack[SP]);
- ++SP;
- break;
- case cSinhCosh:
- fp_sinhCosh(Stack[SP], Stack[SP+1], Stack[SP]);
- ++SP;
- break;
-
- case cAbsNot:
- Stack[SP] = fp_absNot(Stack[SP]); break;
- case cAbsNotNot:
- Stack[SP] = fp_absNotNot(Stack[SP]); break;
- case cAbsAnd:
- Stack[SP-1] = fp_absAnd(Stack[SP-1], Stack[SP]);
- --SP; break;
- case cAbsOr:
- Stack[SP-1] = fp_absOr(Stack[SP-1], Stack[SP]);
- --SP; break;
- case cAbsIf:
- if(fp_absTruth(Stack[SP--]))
- IP += 2;
- else
- {
- const unsigned* buf = &byteCode[IP+1];
- IP = buf[0];
- DP = buf[1];
- }
- break;
-
- case cDup: Stack[SP+1] = Stack[SP]; ++SP; break;
-
- case cInv:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/Stack[SP];
- break;
-
- case cSqr:
- Stack[SP] = Stack[SP]*Stack[SP];
- break;
-
- case cRDiv:
- if(Stack[SP-1] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP-1] = Stack[SP] / Stack[SP-1]; --SP; break;
-
- case cRSub: Stack[SP-1] = Stack[SP] - Stack[SP-1]; --SP; break;
-
- case cRSqrt:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1) / fp_sqrt(Stack[SP]); break;
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- case cReal: Stack[SP] = fp_real(Stack[SP]); break;
- case cImag: Stack[SP] = fp_imag(Stack[SP]); break;
- case cArg: Stack[SP] = fp_arg(Stack[SP]); break;
- case cConj: Stack[SP] = fp_conj(Stack[SP]); break;
- case cPolar:
- Stack[SP-1] = fp_polar(Stack[SP-1], Stack[SP]);
- --SP; break;
-#endif
-
-
-// Variables:
- default:
- Stack[++SP] = Vars[byteCode[IP]-VarBegin];
- }
- }
-
- mData->mEvalErrorType=0;
- return Stack[SP];
-}
-
-
-//===========================================================================
-// Variable deduction
-//===========================================================================
-namespace
-{
- template<typename Value_t>
- int deduceVariables(FunctionParserBase<Value_t>& fParser,
- const char* funcStr,
- std::string& destVarString,
- int* amountOfVariablesFound,
- std::vector<std::string>* destVarNames,
- bool useDegrees)
- {
- typedef std::set<std::string> StrSet;
- StrSet varNames;
-
- int oldIndex = -1;
-
- while(true)
- {
- destVarString.clear();
- for(StrSet::iterator iter = varNames.begin();
- iter != varNames.end();
- ++iter)
- {
- if(iter != varNames.begin()) destVarString += ",";
- destVarString += *iter;
- }
-
- const int index =
- fParser.Parse(funcStr, destVarString, useDegrees);
- if(index < 0) break;
- if(index == oldIndex) return index;
-
- unsigned nameLength = readIdentifier<Value_t>(funcStr + index);
- if(nameLength & 0x80000000U) return index;
- if(nameLength == 0) return index;
-
- varNames.insert(std::string(funcStr + index, nameLength));
- oldIndex = index;
- }
-
- if(amountOfVariablesFound)
- *amountOfVariablesFound = int(varNames.size());
-
- if(destVarNames)
- destVarNames->assign(varNames.begin(), varNames.end());
-
- return -1;
- }
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseAndDeduceVariables
-(const std::string& function,
- int* amountOfVariablesFound,
- bool useDegrees)
-{
- std::string varString;
- return deduceVariables(*this, function.c_str(), varString,
- amountOfVariablesFound, 0, useDegrees);
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseAndDeduceVariables
-(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound,
- bool useDegrees)
-{
- std::string varString;
- const int index =
- deduceVariables(*this, function.c_str(), varString,
- amountOfVariablesFound, 0, useDegrees);
- if(index < 0) resultVarString = varString;
- return index;
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseAndDeduceVariables
-(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees)
-{
- std::string varString;
- std::vector<std::string> vars;
- const int index =
- deduceVariables(*this, function.c_str(), varString,
- 0, &vars, useDegrees);
- if(index < 0) resultVars.swap(vars);
- return index;
-}
-
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-//===========================================================================
-// Bytecode injection
-//===========================================================================
-template<typename Value_t>
-void FunctionParserBase<Value_t>::InjectRawByteCode
-(const unsigned* bytecode, unsigned bytecodeAmount,
- const Value_t* immed, unsigned immedAmount, unsigned stackSize)
-{
- CopyOnWrite();
-
- mData->mByteCode.assign(bytecode, bytecode + bytecodeAmount);
- mData->mImmed.assign(immed, immed + immedAmount);
- mData->mStackSize = stackSize;
-
-#ifndef FP_USE_THREAD_SAFE_EVAL
- mData->mStack.resize(stackSize);
-#endif
-}
-
-//===========================================================================
-// Debug output
-//===========================================================================
-#include <iomanip>
-#include <sstream>
-namespace
-{
- inline void printHex(std::ostream& dest, unsigned n)
- {
- std::ios::fmtflags flags = dest.flags();
- dest.width(4); dest.fill('0'); std::hex(dest); //uppercase(dest);
- dest << n;
- dest.flags(flags);
- }
-
- void padLine(std::ostringstream& dest, unsigned destLength)
- {
- for(std::size_t currentLength = dest.str().length();
- currentLength < destLength;
- ++currentLength)
- {
- dest << ' ';
- }
- }
-
- const struct PowiMuliType
- {
- unsigned opcode_square;
- unsigned opcode_cumulate;
- unsigned opcode_invert;
- unsigned opcode_half;
- unsigned opcode_invhalf;
- } iseq_powi = {cSqr,cMul,cInv,cSqrt,cRSqrt},
- iseq_muli = {~unsigned(0), cAdd,cNeg, ~unsigned(0),~unsigned(0) };
-
- template<typename Value_t>
- Value_t ParsePowiMuli(
- const PowiMuliType& opcodes,
- const std::vector<unsigned>& ByteCode, unsigned& IP,
- unsigned limit,
- std::size_t factor_stack_base,
- std::vector<Value_t>& stack,
- bool IgnoreExcess)
- {
- Value_t result = Value_t(1);
- while(IP < limit)
- {
- if(ByteCode[IP] == opcodes.opcode_square)
- {
- if(!isInteger(result)) break;
- result *= Value_t(2);
- ++IP;
- continue;
- }
- if(ByteCode[IP] == opcodes.opcode_invert)
- {
- if(result < Value_t(0)) break;
- result = -result;
- ++IP;
- continue;
- }
- if(ByteCode[IP] == opcodes.opcode_half)
- {
- if(result > Value_t(0) && isEvenInteger(result))
- break;
- if(isInteger(result * Value_t(0.5))) break;
- result *= Value_t(0.5);
- ++IP;
- continue;
- }
- if(ByteCode[IP] == opcodes.opcode_invhalf)
- {
- if(result > Value_t(0) && isEvenInteger(result))
- break;
- if(isInteger(result * Value_t(-0.5))) break;
- result *= Value_t(-0.5);
- ++IP;
- continue;
- }
-
- unsigned dup_fetch_pos = IP;
- Value_t lhs = Value_t(1);
-
- if(ByteCode[IP] == cFetch)
- {
- unsigned index = ByteCode[++IP];
- if(index < factor_stack_base
- || std::size_t(index-factor_stack_base) >= stack.size())
- {
- // It wasn't a powi-fetch after all
- IP = dup_fetch_pos;
- break;
- }
- lhs = stack[index - factor_stack_base];
- // Note: ^This assumes that cFetch of recentmost
- // is always converted into cDup.
- goto dup_or_fetch;
- }
-
- if(ByteCode[IP] == cDup)
- {
- lhs = result;
- goto dup_or_fetch;
-
- dup_or_fetch:
- stack.push_back(result);
- ++IP;
- Value_t subexponent = ParsePowiMuli
- (opcodes,
- ByteCode, IP, limit,
- factor_stack_base, stack,
- IgnoreExcess);
- if(IP >= limit && IgnoreExcess)
- return lhs*subexponent;
- if(IP >= limit || ByteCode[IP] != opcodes.opcode_cumulate)
- {
- // It wasn't a powi-dup after all
- IP = dup_fetch_pos;
- break;
- }
- ++IP; // skip opcode_cumulate
- stack.pop_back();
- result += lhs*subexponent;
- continue;
- }
- break;
- }
- return result;
- }
-
- template<typename Value_t>
- Value_t ParsePowiSequence(const std::vector<unsigned>& ByteCode,
- unsigned& IP, unsigned limit,
- std::size_t factor_stack_base,
- bool IgnoreExcess = false)
- {
- std::vector<Value_t> stack;
- stack.push_back(Value_t(1));
- return ParsePowiMuli(iseq_powi, ByteCode, IP, limit,
- factor_stack_base, stack,
- IgnoreExcess);
- }
-
- template<typename Value_t>
- Value_t ParseMuliSequence(const std::vector<unsigned>& ByteCode,
- unsigned& IP, unsigned limit,
- std::size_t factor_stack_base,
- bool IgnoreExcess = false)
- {
- std::vector<Value_t> stack;
- stack.push_back(Value_t(1));
- return ParsePowiMuli(iseq_muli, ByteCode, IP, limit,
- factor_stack_base, stack,
- IgnoreExcess);
- }
-
- struct IfInfo
- {
- std::pair<int,std::string> condition;
- std::pair<int,std::string> thenbranch;
- unsigned endif_location;
-
- IfInfo() : condition(), thenbranch(), endif_location() { }
- };
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::PrintByteCode(std::ostream& dest,
- bool showExpression) const
-{
- dest << "Size of stack: " << mData->mStackSize << "\n";
-
- std::ostringstream outputBuffer;
- std::ostream& output = (showExpression ? outputBuffer : dest);
-
- const std::vector<unsigned>& ByteCode = mData->mByteCode;
- const std::vector<Value_t>& Immed = mData->mImmed;
-
- std::vector<std::pair<int,std::string> > stack;
- std::vector<IfInfo> if_stack;
-
- for(unsigned IP = 0, DP = 0; IP <= ByteCode.size(); ++IP)
- {
- after_powi_or_muli:;
- std::string n;
- bool out_params = false;
- unsigned params = 2, produces = 1, opcode = 0;
-
- if(showExpression && !if_stack.empty() &&
- ( // Normal If termination rule:
- if_stack.back().endif_location == IP
- // This rule matches when cJumps are threaded:
- || (IP < ByteCode.size() && ByteCode[IP] == cJump
- && !if_stack.back().thenbranch.second.empty())
- ))
- {
- printHex(output, IP);
- if(if_stack.back().endif_location == IP)
- output << ": ----- (phi)";
- else
- output << ": ----- (phi+)";
-
- stack.resize(stack.size()+2);
- std::swap(stack[stack.size()-3], stack[stack.size()-1]);
- std::swap(if_stack.back().condition, stack[stack.size()-3]);
- std::swap(if_stack.back().thenbranch, stack[stack.size()-2]);
- opcode = cIf;
- params = 3;
- --IP;
- if_stack.pop_back();
- }
- else
- {
- if(IP >= ByteCode.size()) break;
- opcode = ByteCode[IP];
-
- if(showExpression && (
- opcode == cSqr || opcode == cDup
- || opcode == cInv
- || opcode == cSqrt || opcode == cRSqrt
- || opcode == cFetch
- ))
- {
- unsigned changed_ip = IP;
- Value_t exponent =
- ParsePowiSequence<Value_t>
- (ByteCode, changed_ip,
- if_stack.empty()
- ? (unsigned)ByteCode.size()
- : if_stack.back().endif_location,
- stack.size()-1);
- std::string operation_prefix;
- std::ostringstream operation_value;
- int prio = 0;
- if(exponent == Value_t(1.0))
- {
- if(opcode != cDup) goto not_powi_or_muli;
- Value_t factor =
- ParseMuliSequence<Value_t>
- (ByteCode, changed_ip,
- if_stack.empty()
- ? (unsigned)ByteCode.size()
- : if_stack.back().endif_location,
- stack.size()-1);
- if(factor == Value_t(1) || factor == Value_t(-1))
- goto not_powi_or_muli;
- operation_prefix = "*";
- operation_value << factor;
- prio = 3;
- }
- else
- {
- prio = 2;
- operation_prefix = "^";
- operation_value << exponent;
- }
-
- //unsigned explanation_before = changed_ip-2;
- unsigned explanation_before = changed_ip-1;
-
- const char* explanation_prefix = "_";
- for(const unsigned first_ip = IP; IP < changed_ip; ++IP)
- {
- printHex(output, IP);
- output << ": ";
-
- const char* sep = "|";
- if(first_ip+1 == changed_ip)
- { sep = "="; explanation_prefix = " "; }
- else if(IP == first_ip) sep = "\\";
- else if(IP+1 == changed_ip) sep = "/";
- else explanation_prefix = "=";
-
- switch(ByteCode[IP])
- {
- case cInv: output << "inv"; break;
- case cNeg: output << "neg"; break;
- case cDup: output << "dup"; break;
- case cSqr: output << "sqr"; break;
- case cMul: output << "mul"; break;
- case cAdd: output << "add"; break;
- case cCbrt: output << "cbrt"; break;
- case cSqrt: output << "sqrt"; break;
- case cRSqrt: output << "rsqrt"; break;
- case cFetch:
- {
- unsigned index = ByteCode[++IP];
- output << "cFetch(" << index << ")";
- break;
- }
- default: break;
- }
- padLine(outputBuffer, 20);
- output << sep;
- if(IP >= explanation_before)
- {
- explanation_before = (unsigned)ByteCode.size();
- output << explanation_prefix
- << '[' << (stack.size()-1) << ']';
- std::string last = stack.back().second;
- if(stack.back().first >= prio)
- last = "(" + last + ")";
- output << last;
- output << operation_prefix;
- output << operation_value.str();
- }
- else
- {
- unsigned p = first_ip;
- Value_t exp = operation_prefix=="^" ?
- ParsePowiSequence<Value_t>
- (ByteCode, p, IP+1, stack.size()-1, true) :
- ParseMuliSequence<Value_t>
- (ByteCode, p, IP+1, stack.size()-1, true);
- std::string last = stack.back().second;
- if(stack.back().first >= prio)
- last = "(" + last + ")";
- output << " ..." << last;
- output << operation_prefix;
- output << exp;
- }
- dest << outputBuffer.str() << std::endl;
- outputBuffer.str("");
- }
-
- std::string& last = stack.back().second;
- if(stack.back().first >= prio)
- last = "(" + last + ")";
- last += operation_prefix;
- last += operation_value.str();
- stack.back().first = prio;
-
- goto after_powi_or_muli;
- }
- not_powi_or_muli:;
- printHex(output, IP);
- output << ": ";
-
- switch(opcode)
- {
- case cIf:
- {
- unsigned label = ByteCode[IP+1]+1;
- output << "jz ";
- printHex(output, label);
- params = 1;
- produces = 0;
- IP += 2;
-
- if_stack.resize(if_stack.size() + 1);
- std::swap( if_stack.back().condition, stack.back() );
- if_stack.back().endif_location = (unsigned) ByteCode.size();
- stack.pop_back();
- break;
- }
- case cAbsIf:
- {
- unsigned dp = ByteCode[IP+2];
- unsigned label = ByteCode[IP+1]+1;
- output << "jz_abs " << dp << ",";
- printHex(output, label);
- params = 1;
- produces = 0;
- IP += 2;
-
- if_stack.resize(if_stack.size() + 1);
- std::swap( if_stack.back().condition, stack.back() );
- if_stack.back().endif_location = (unsigned) ByteCode.size();
- stack.pop_back();
- break;
- }
-
- case cJump:
- {
- unsigned dp = ByteCode[IP+2];
- unsigned label = ByteCode[IP+1]+1;
-
- if(!if_stack.empty() && !stack.empty())
- {
- std::swap(if_stack.back().thenbranch, stack.back());
- if_stack.back().endif_location = label;
- stack.pop_back();
- }
-
- output << "jump " << dp << ",";
- printHex(output, label);
- params = 0;
- produces = 0;
- IP += 2;
- break;
- }
- case cImmed:
- {
- if(showExpression)
- {
- std::ostringstream buf;
- buf.precision(8);
- buf << Immed[DP];
- stack.push_back( std::make_pair(0, buf.str()) );
- }
- output.precision(8);
- output << "push " << Immed[DP];
- ++DP;
- produces = 0;
- break;
- }
-
- case cFCall:
- {
- const unsigned index = ByteCode[++IP];
- params = mData->mFuncPtrs[index].mParams;
- static std::string name;
- name = "f:" + findName(mData->mNamePtrs, index,
- NameData<Value_t>::FUNC_PTR);
- n = name.c_str();
- out_params = true;
- break;
- }
-
- case cPCall:
- {
- const unsigned index = ByteCode[++IP];
- params = mData->mFuncParsers[index].mParams;
- static std::string name;
- name = "p:" + findName(mData->mNamePtrs, index,
- NameData<Value_t>::PARSER_PTR);
- n = name.c_str();
- out_params = true;
- break;
- }
-
- default:
- if(IsVarOpcode(opcode))
- {
- if(showExpression)
- {
- stack.push_back(std::make_pair(0,
- (findName(mData->mNamePtrs, opcode,
- NameData<Value_t>::VARIABLE))));
- }
- output << "push Var" << opcode-VarBegin;
- produces = 0;
- }
- else
- {
- switch(OPCODE(opcode))
- {
- case cNeg: n = "neg"; params = 1; break;
- case cAdd: n = "add"; break;
- case cSub: n = "sub"; break;
- case cMul: n = "mul"; break;
- case cDiv: n = "div"; break;
- case cMod: n = "mod"; break;
- case cPow: n = "pow"; break;
- case cEqual: n = "eq"; break;
- case cNEqual: n = "neq"; break;
- case cLess: n = "lt"; break;
- case cLessOrEq: n = "le"; break;
- case cGreater: n = "gt"; break;
- case cGreaterOrEq: n = "ge"; break;
- case cAnd: n = "and"; break;
- case cOr: n = "or"; break;
- case cNot: n = "not"; params = 1; break;
- case cNotNot: n = "notnot"; params = 1; break;
- case cDeg: n = "deg"; params = 1; break;
- case cRad: n = "rad"; params = 1; break;
-
- case cFetch:
- {
- unsigned index = ByteCode[++IP];
- if(showExpression && index < stack.size())
- stack.push_back(stack[index]);
- output << "cFetch(" << index << ")";
- produces = 0;
- break;
- }
- #ifdef FP_SUPPORT_OPTIMIZER
- case cLog2by: n = "log2by"; params = 2; out_params = 1; break;
- case cPopNMov:
- {
- std::size_t a = ByteCode[++IP];
- std::size_t b = ByteCode[++IP];
- if(showExpression && b < stack.size())
- {
- std::pair<int, std::string> stacktop(0, "?");
- if(b < stack.size()) stacktop = stack[b];
- stack.resize(a);
- stack.push_back(stacktop);
- }
- output << "cPopNMov(" << a << ", " << b << ")";
- produces = 0;
- break;
- }
- case cNop:
- output << "nop"; params = 0; produces = 0;
- break;
- #endif
- case cSinCos:
- {
- if(showExpression)
- {
- std::pair<int, std::string> sin = stack.back();
- std::pair<int, std::string> cos(
- 0, "cos(" + sin.second + ")");
- sin.first = 0;
- sin.second = "sin(" + sin.second + ")";
- stack.back() = sin;
- stack.push_back(cos);
- }
- output << "sincos";
- produces = 0;
- break;
- }
- case cSinhCosh:
- {
- if(showExpression)
- {
- std::pair<int, std::string> sinh = stack.back();
- std::pair<int, std::string> cosh(
- 0, "cosh(" + sinh.second + ")");
- sinh.first = 0;
- sinh.second = "sinh(" + sinh.second + ")";
- stack.back() = sinh;
- stack.push_back(cosh);
- }
- output << "sinhcosh";
- produces = 0;
- break;
- }
- case cAbsAnd: n = "abs_and"; break;
- case cAbsOr: n = "abs_or"; break;
- case cAbsNot: n = "abs_not"; params = 1; break;
- case cAbsNotNot: n = "abs_notnot"; params = 1; break;
- case cDup:
- {
- if(showExpression)
- stack.push_back(stack.back());
- output << "dup";
- produces = 0;
- break;
- }
- case cInv: n = "inv"; params = 1; break;
- case cSqr: n = "sqr"; params = 1; break;
- case cRDiv: n = "rdiv"; break;
- case cRSub: n = "rsub"; break;
- case cRSqrt: n = "rsqrt"; params = 1; break;
-
- default:
- n = Functions[opcode-cAbs].name;
- params = Functions[opcode-cAbs].params;
- out_params = params != 1;
- }
- }
- }
- }
- if(produces) output << n;
- if(out_params) output << " (" << params << ")";
- if(showExpression)
- {
- padLine(outputBuffer, 20);
-
- if(produces > 0)
- {
- std::ostringstream buf;
- const char *paramsep = ",", *suff = "";
- int prio = 0; bool commutative = false;
- switch(opcode)
- {
- case cIf: buf << "if("; suff = ")";
- break;
- case cAbsIf: buf << "if("; suff = ")";
- break;
- case cOr: prio = 6; paramsep = "|"; commutative = true;
- break;
- case cAnd: prio = 5; paramsep = "&"; commutative = true;
- break;
- case cAdd: prio = 4; paramsep = "+"; commutative = true;
- break;
- case cSub: prio = 4; paramsep = "-";
- break;
- case cMul: prio = 3; paramsep = "*"; commutative = true;
- break;
- case cDiv: prio = 3; paramsep = "/";
- break;
- case cPow: prio = 2; paramsep = "^";
- break;
- case cAbsOr: prio = 6; paramsep = "|"; commutative = true;
- break;
- case cAbsAnd: prio = 5; paramsep = "&"; commutative = true;
- break;
- case cSqr: prio = 2; suff = "^2";
- break;
- case cNeg: buf << "(-("; suff = "))";
- break;
- case cNot: buf << "(!("; suff = "))";
- break;
- default: buf << n << '('; suff = ")";
- }
-
- const char* sep = "";
- for(unsigned a=0; a<params; ++a)
- {
- buf << sep;
- if(stack.size() + a < params)
- buf << "?";
- else
- {
- const std::pair<int,std::string>& prev =
- stack[stack.size() - params + a];
- if(prio > 0 && (prev.first > prio ||
- (prev.first==prio && !commutative)))
- buf << '(' << prev.second << ')';
- else
- buf << prev.second;
- }
- sep = paramsep;
- }
- if(stack.size() >= params)
- stack.resize(stack.size() - params);
- else
- stack.clear();
- buf << suff;
- stack.push_back(std::make_pair(prio, buf.str()));
- //if(n.size() <= 4 && !out_params) padLine(outputBuffer, 20);
- }
- //padLine(outputBuffer, 20);
- output << "= ";
- if(((opcode == cIf || opcode == cAbsIf) && params != 3)
- || opcode == cJump
- #ifdef FP_SUPPORT_OPTIMIZER
- || opcode == cNop
- #endif
- )
- output << "(void)";
- else if(stack.empty())
- output << "[?] ?";
- else
- output << '[' << (stack.size()-1) << ']'
- << stack.back().second;
- }
-
- if(showExpression)
- {
- dest << outputBuffer.str() << std::endl;
- outputBuffer.str("");
- }
- else
- output << std::endl;
- }
- dest << std::flush;
-}
-#endif
-
-
-#ifndef FP_SUPPORT_OPTIMIZER
-template<typename Value_t>
-void FunctionParserBase<Value_t>::Optimize()
-{
- // Do nothing if no optimizations are supported.
-}
-#endif
-
-
-#define FUNCTIONPARSER_INSTANTIATE_CLASS(type) \
- template class FunctionParserBase< type >;
-
-#ifndef FP_DISABLE_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(double)
-#endif
-
-#ifdef FP_SUPPORT_FLOAT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(float)
-#endif
-
-#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(long double)
-#endif
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(long)
-#endif
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(MpfrFloat)
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(GmpInt)
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<double>)
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<float>)
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<long double>)
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-#ifndef ONCE_FPARSER_H_
-#define ONCE_FPARSER_H_
-
-#include <string>
-#include <vector>
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-#include <iostream>
-#endif
-
-#ifdef _MSC_VER
-// Visual Studio's warning about missing definitions for the explicit
-// FunctionParserBase instantiations is irrelevant here.
-#pragma warning(disable : 4661)
-#endif
-
-namespace FPoptimizer_CodeTree { template<typename Value_t> class CodeTree; }
-
-template<typename Value_t>
-class FunctionParserBase
-{
- public:
- enum ParseErrorType
- {
- SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH,
- EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS,
- ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC,
- UNKNOWN_IDENTIFIER,
- NO_FUNCTION_PARSED_YET,
- FP_NO_ERROR
- };
-
- typedef Value_t value_type;
-
-
- int Parse(const char* Function, const std::string& Vars,
- bool useDegrees = false);
- int Parse(const std::string& Function, const std::string& Vars,
- bool useDegrees = false);
-
- void setDelimiterChar(char);
-
- static Value_t epsilon();
- static void setEpsilon(Value_t);
-
- const char* ErrorMsg() const;
- ParseErrorType GetParseErrorType() const;
-
- Value_t Eval(const Value_t* Vars);
- int EvalError() const;
-
- bool AddConstant(const std::string& name, Value_t value);
- bool AddUnit(const std::string& name, Value_t value);
-
- typedef Value_t (*FunctionPtr)(const Value_t*);
-
- bool AddFunction(const std::string& name,
- FunctionPtr, unsigned paramsAmount);
- bool AddFunction(const std::string& name, FunctionParserBase&);
-
- class FunctionWrapper;
-
- template<typename DerivedWrapper>
- bool AddFunctionWrapper(const std::string& name, const DerivedWrapper&,
- unsigned paramsAmount);
-
- FunctionWrapper* GetFunctionWrapper(const std::string& name);
-
- bool RemoveIdentifier(const std::string& name);
-
- void Optimize();
-
-
- int ParseAndDeduceVariables(const std::string& function,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
- int ParseAndDeduceVariables(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
- int ParseAndDeduceVariables(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees = false);
-
-
- FunctionParserBase();
- ~FunctionParserBase();
-
- // Copy constructor and assignment operator (implemented using the
- // copy-on-write technique for efficiency):
- FunctionParserBase(const FunctionParserBase&);
- FunctionParserBase& operator=(const FunctionParserBase&);
-
-
- void ForceDeepCopy();
-
-
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
- // For debugging purposes only.
- // Performs no sanity checks or anything. If the values are wrong, the
- // library will crash. Do not use unless you know what you are doing.
- void InjectRawByteCode(const unsigned* bytecode, unsigned bytecodeAmount,
- const Value_t* immed, unsigned immedAmount,
- unsigned stackSize);
-
- void PrintByteCode(std::ostream& dest, bool showExpression = true) const;
-#endif
-
-
-
-//========================================================================
- protected:
-//========================================================================
- // A derived class can implement its own evaluation logic by using
- // the parser data (found in fptypes.hh).
- struct Data;
- Data* getParserData();
-
-
-//========================================================================
- private:
-//========================================================================
-
- friend class FPoptimizer_CodeTree::CodeTree<Value_t>;
-
-// Private data:
-// ------------
- Data* mData;
- unsigned mStackPtr;
-
-
-// Private methods:
-// ---------------
- void CopyOnWrite();
- bool CheckRecursiveLinking(const FunctionParserBase*) const;
- bool NameExists(const char*, unsigned);
- bool ParseVariables(const std::string&);
- int ParseFunction(const char*, bool);
- const char* SetErrorType(ParseErrorType, const char*);
-
- void AddFunctionOpcode(unsigned);
- void AddImmedOpcode(Value_t v);
- void incStackPtr();
- void CompilePowi(long);
- bool TryCompilePowi(Value_t);
-
- const char* CompileIf(const char*);
- const char* CompileFunctionParams(const char*, unsigned);
- const char* CompileElement(const char*);
- const char* CompilePossibleUnit(const char*);
- const char* CompilePow(const char*);
- const char* CompileUnaryMinus(const char*);
- const char* CompileMult(const char*);
- const char* CompileAddition(const char*);
- const char* CompileComparison(const char*);
- const char* CompileAnd(const char*);
- const char* CompileExpression(const char*);
- inline const char* CompileFunction(const char*, unsigned);
- inline const char* CompileParenthesis(const char*);
- inline const char* CompileLiteral(const char*);
- template<bool SetFlag>
- inline void PushOpcodeParam(unsigned);
- template<bool SetFlag>
- inline void PutOpcodeParamAt(unsigned, unsigned offset);
- const char* Compile(const char*);
-
- bool addFunctionWrapperPtr(const std::string&, FunctionWrapper*, unsigned);
- static void incFuncWrapperRefCount(FunctionWrapper*);
- static unsigned decFuncWrapperRefCount(FunctionWrapper*);
-
-protected:
- // Parsing utility functions
- static std::pair<const char*, Value_t> ParseLiteral(const char*);
- static unsigned ParseIdentifier(const char*);
-};
-
-class FunctionParser: public FunctionParserBase<double> {};
-class FunctionParser_f: public FunctionParserBase<float> {};
-class FunctionParser_ld: public FunctionParserBase<long double> {};
-class FunctionParser_li: public FunctionParserBase<long> {};
-
-#include <complex>
-class FunctionParser_cd: public FunctionParserBase<std::complex<double> > {};
-class FunctionParser_cf: public FunctionParserBase<std::complex<float> > {};
-class FunctionParser_cld: public FunctionParserBase<std::complex<long double> > {};
-
-
-
-template<typename Value_t>
-class FunctionParserBase<Value_t>::FunctionWrapper
-{
- unsigned mReferenceCount;
- friend class FunctionParserBase<Value_t>;
-
- public:
- FunctionWrapper(): mReferenceCount(1) {}
- FunctionWrapper(const FunctionWrapper&): mReferenceCount(1) {}
- virtual ~FunctionWrapper() {}
- FunctionWrapper& operator=(const FunctionWrapper&) { return *this; }
-
- virtual Value_t callFunction(const Value_t*) = 0;
-};
-
-template<typename Value_t>
-template<typename DerivedWrapper>
-bool FunctionParserBase<Value_t>::AddFunctionWrapper
-(const std::string& name, const DerivedWrapper& wrapper, unsigned paramsAmount)
-{
- return addFunctionWrapperPtr
- (name, new DerivedWrapper(wrapper), paramsAmount);
-}
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen *|
-\***************************************************************************/
-
-#ifndef ONCE_FPARSER_GMPINT_H_
-#define ONCE_FPARSER_GMPINT_H_
-
-#include "fparser.hh"
-#include "mpfr/GmpInt.hh"
-
-class FunctionParser_gmpint: public FunctionParserBase<GmpInt> {};
-
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen *|
-\***************************************************************************/
-
-#ifndef ONCE_FPARSER_MPFR_H_
-#define ONCE_FPARSER_MPFR_H_
-
-#include "fparser.hh"
-#include "mpfr/MpfrFloat.hh"
-
-class FunctionParser_mpfr: public FunctionParserBase<MpfrFloat> {};
-
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-// Configuration file
-// ------------------
-
-/* NOTE:
- This file is for the internal use of the function parser only.
- You don't need to include this file in your source files, just
- include "fparser.hh".
-*/
-
-
-/* Uncomment any of these lines or define them in your compiler settings
- to enable the correspondent version of the parser. (These are disabled
- by default because they rely on C99 functions, and non-standard libraries
- in the case pf MPFR and GMP, and they make compiling needlessly slower
- and the resulting binary needlessly larger if they are not used in the
- program.)
-*/
-//#define FP_SUPPORT_FLOAT_TYPE
-//#define FP_SUPPORT_LONG_DOUBLE_TYPE
-//#define FP_SUPPORT_LONG_INT_TYPE
-//#define FP_SUPPORT_MPFR_FLOAT_TYPE
-//#define FP_SUPPORT_GMP_INT_TYPE
-//#define FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-//#define FP_SUPPORT_COMPLEX_FLOAT_TYPE
-//#define FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-
-/* If you are using FunctionParser_ld or FunctionParser_cld and your compiler
- supports the strtold() function, you should uncomment the following line.
- */
-//#define FP_USE_STRTOLD
-
-
-/* Uncomment this line or define it in your compiler settings if you want
- to disable compiling the basic double version of the library, in case
- one of the above types is used but not the double type. (If the double
- type is not used, then disabling it makes compiling faster and the
- resulting binary smaller.)
- */
-//#define FP_DISABLE_DOUBLE_TYPE
-
-/* Uncomment this line or define it in your compiler settings to make the
- parser use C++11 math functions. (Note that these may not be supported
- by all compilers.)
-*/
-//#define FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
-
-/*
- Whether to use shortcut evaluation for the & and | operators:
-*/
-#ifndef FP_DISABLE_SHORTCUT_LOGICAL_EVALUATION
-#define FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
-#endif
-
-/*
- Comment out the following lines out if you are not going to use the
- optimizer and want a slightly smaller library. The Optimize() method
- can still be called, but it will not do anything.
- If you are unsure, just leave it. It won't slow down the other parts of
- the library.
-*/
-#ifndef FP_NO_SUPPORT_OPTIMIZER
-#define FP_SUPPORT_OPTIMIZER
-#endif
-
-#if defined(FP_SUPPORT_COMPLEX_DOUBLE_TYPE) || defined(FP_SUPPORT_COMPLEX_FLOAT_TYPE) || defined(FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE)
-#define FP_SUPPORT_COMPLEX_NUMBERS
-#endif
-
-
-/*
- No member function of FunctionParser is thread-safe. Most prominently,
- Eval() is not thread-safe. By uncommenting one of these lines the Eval()
- function can be made thread-safe at the cost of a possible small overhead.
- The second version requires that the compiler supports the alloca() function,
- which is not standard, but is faster.
- */
-//#define FP_USE_THREAD_SAFE_EVAL
-//#define FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Function optimizer *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-/* NOTE:
- This file contains generated code (from the optimizer sources) and is
- not intended to be modified by hand. If you want to modify the optimizer,
- download the development version of the library.
-*/
-
-#include <algorithm>
-#include <assert.h>
-#include <cctype>
-#include <iostream>
-#include <limits>
-#include <list>
-#include <map>
-#include <set>
-#include <sstream>
-#include <stdint.h>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "fpconfig.hh"
-#ifdef FP_SUPPORT_OPTIMIZER
-#include "fparser.hh"
-#include "extrasrc/fptypes.hh"
-#include "extrasrc/fpaux.hh"
-#define l14 {Value_t
-#define l04 ),info,
-#define iZ3 {data->
-#define iY3 ==cNot||
-#define iX3 "Found "
-#define iW3 info.lQ[b
-#define iV3 ;o<<"\n";
-#define iU3 )yR 2,cPow
-#define iT3 ;}static yU1
-#define iS3 (tree)!=
-#define iR3 ),Value(
-#define iQ3 stackpos
-#define iP3 minValue0
-#define iO3 "dup(%u) "
-#define iN3 =true;iO1
-#define iM3 eR{assert
-#define iL3 "%d, cost "
-#define iK3 "PUSH " iL2
-#define iJ3 "immed "<<
-#define iI3 mFuncParsers
-#define iH3 param.data
-#define iG3 stderr
-#define iF3 sep2=" "
-#define iE3 FPHASH_CONST
-#define iD3 cache_needed[
-#define iC3 fprintf
-#define iB3 "Applying "
-#define iA3 FUNCTIONPARSER_INSTANTIATE_OPTIMIZE
-#define i93 FUNCTIONPARSER_INSTANTIATE_EMPTY_OPTIMIZE
-#define i83 HANDLE_UNARY_CONST_FUNC
-#define i73 {if(n11
-#define i63 second;
-#define i53 within,
-#define i43 AddFrom(
-#define i33 tH3==
-#define i23 c_count
-#define i13 MaxOp
-#define i03 else nM
-#define tZ3 =tZ cL3
-#define tY3 .nJ 0));
-#define tX3 .nJ 1));
-#define tW3 lD m.
-#define tV3 ;a<tree.xB
-#define tU3 iZ);}if
-#define tT3 cS ifp2
-#define tS3 sim.xB1
-#define tR3 );tO tL1
-#define tQ3 ].swap(
-#define tP3 codes[b
-#define tO3 whydump
-#define tN3 for lS1
-#define tM3 for(;a<
-#define tL3 nparams
-#define tK3 281856,
-#define tJ3 cTan i7
-#define tI3 l2 2,2,
-#define tH3 ;if(op
-#define tG3 l4 0,1,
-#define tF3 0x12 nH
-#define tE3 FixIncompleteHashes()
-#define tD3 cSinh,
-#define tC3 ,cTan nS
-#define tB3 ,iX 1,
-#define tA3 nS 0,
-#define t93 cAbs nS
-#define t83 ;case
-#define t73 i1 t83
-#define t63 Params[
-#define t53 Params(
-#define t43 &&p nL3
-#define t33 fp_pow(
-#define t23 false;}
-#define t13 lD1 y4.
-#define t03 cAbsIf)
-#define eZ3 l91++b)
-#define eY3 lX1 nC==
-#define eX3 ;exponent
-#define eW3 =false;
-#define eV3 tN cS1);
-#define eU3 .empty()
-#define eT3 nS3))n92
-#define eS3 (opcode==
-#define eR3 <data eJ3;++
-#define eQ3 l14 nS3(
-#define eP3 ByteCodeSynth xF
-#define eO3 std xM3<
-#define eN3 middle2
-#define eM3 std::string
-#define eL3 SetOpcode(
-#define eK3 ;for iZ1
-#define eJ3 .size()
-#define eI3 ].second
-#define eH3 ].first
-#define eG3 return p
-#define eF3 TreeCountItem
-#define eE3 }return
-#define eD3 Ne_Mask
-#define eC3 Gt_Mask
-#define eB3 Lt_Mask
-#define eA3 const eK
-#define e93 .n7 synth.
-#define e83 range nE3
-#define e73 eK3 a=
-#define e63 ,eQ,c92
-#define e53 eO|lT1)
-#define e43 public:
-#define e33 Rehash(
-#define e23 switch(
-#define e13 pclone
-#define e03 cOr,l6
-#define cZ3 newpow
-#define cY3 change
-#define cX3 (Value_t
-#define cW3 (count
-#define cV3 133,2,
-#define cU3 ,tree
-#define cT3 byteCode
-#define cS3 child)
-#define cR3 (p1 x41)
-#define cQ3 cLog2by
-#define cP3 long iD1
-#define cO3 factor_t
-#define cN3 (p0 yI&&
-#define cM3 value1
-#define cL3 a));if(!
-#define cK3 fp_mod(
-#define cJ3 else{if(
-#define cI3 )min.set(
-#define cH3 xF());nD
-#define cG3 max.known
-#define cF3 known&&
-#define cE3 tX p2;p2
-#define cD3 {tree.x4
-#define cC3 cAbsNot
-#define cB3 ,x53 l8
-#define cA3 e23 lY1
-#define c93 xW 0)nC
-#define c83 IsLogicalValue(xW
-#define c73 }switch
-#define c63 stackptr
-#define c53 cLog);xG
-#define c43 l8 0));
-#define c33 opcodes
-#define c23 did_muli
-#define c13 &Value){
-#define c03 yD const
-#define yZ3 (param.
-#define yY3 ){e23
-#define yX3 :if(&*lE1){
-#define yW3 :{n31 r=
-#define yV3 xY3 e23
-#define yU3 param=*(
-#define yT3 cAbsIf,
-#define yS3 cNotNot,
-#define yR3 l4 16,1,
-#define yQ3 yO3 info
-#define yP3 lE1=r.specs;if(r.found){
-#define yO3 *x8)[a].
-#define yN3 cLess,cH
-#define yM3 default_function_handling
-#define yL3 l4 20,1,
-#define yK3 l4 4,1,
-#define yJ3 450998,
-#define yI3 cExp2 nS
-#define yH3 lJ 2},0,
-#define yG3 )lS 3*3*2*2
-#define yF3 default:
-#define yE3 range<nV
-#define yD3 range xF
-#define yC3 Ge0Lt1
-#define yB3 Gt0Le1
-#define yA3 cAdd lV2
-#define y93 if(op1==
-#define y83 iterator
-#define y73 begin();
-#define y63 TreeSet
-#define y53 parent
-#define y43 insert(i
-#define y33 newrel
-#define y23 y03 xX3 xO2
-#define y13 y03 iF2;if(
-#define y03 ))return
-#define xZ3 ;if(half
-#define xY3 break;}
-#define xX3 IsNever
-#define xW3 e62 eO1
-#define xV3 synth.xH
-#define xU3 b_needed
-#define xT3 cachepos
-#define xS3 ,lE1,info
-#define xR3 half=
-#define xQ3 131,4,1,
-#define xP3 131,8,1,
-#define xO3 ,iM,1,lC1+1);
-#define xN3 4,1,2,1,
-#define xM3 ::vector
-#define xL3 1 y5 n41
-#define xK3 FindPos(
-#define xJ3 src_pos
-#define xI3 xM1 xQ+
-#define xH3 reserve(
-#define xG3 treeptr
-#define xF3 .resize(
-#define xE3 tO1 void
-#define xD3 ImmedTag
-#define xC3 a,const
-#define xB3 RefCount
-#define xA3 Birth();
-#define x93 typename
-#define x83 unsigned
-#define x73 template
-#define x63 7168,
-#define x53 leaf1
-#define x43 cost_t
-#define x33 fpdata
-#define x23 middle
-#define x13 sqrt_cost
-#define x03 const int
-#define nZ3 mul_count
-#define nY3 );nZ l5::
-#define nX3 e62 2)));
-#define nW3 maxValue1
-#define nV3 minValue1
-#define nU3 maxValue0
-#define nT3 ValueType
-#define nS3 result
-#define nR3 nS3;}case
-#define nQ3 nS3.tL
-#define nP3 ::res,b8<
-#define nO3 eG3 yM
-#define nN3 .what nS1
-#define nM3 e62 1),e62 1));
-#define nL3 .max.val
-#define nK3 nS3 yM2
-#define nJ3 nS3 e61
-#define nI3 nS3 yI
-#define nH3 nS3 nL3
-#define nG3 nS3 tG1
-#define nF3 nS3 yM
-#define nE3 xF nS3
-#define nD3 tO n3 0),
-#define nC3 i8);nD lC
-#define nB3 abs_mul
-#define nA3 xM3<x83>&e71
-#define n93 l8 a));
-#define n83 pos_set
-#define n73 goto e1
-#define n63 p1.lT2 p1
-#define n53 [funcno].
-#define n43 eN1[++IP]
-#define n33 sim.x2 1,
-#define n23 {sim.Eat(
-#define n13 eN1[IP]==
-#define n03 subtree
-#define lZ3 invtree
-#define lY3 MakeHash(
-#define lX3 parampair
-#define lW3 rulenumit
-#define lV3 cAnd l3
-#define lU3 ,cMul l3
-#define lT3 cAnd,l6
-#define lS3 x9 lT 2,
-#define lR3 },{{1,
-#define lQ3 cEqual,
-#define lP3 lQ3 lA
-#define lO3 t01},{{3,
-#define lN3 MakeEqual
-#define lM3 nC1,l5::
-#define lL3 nC1,{l5::
-#define lK3 newbase
-#define lJ3 fp_equal(
-#define lI3 branch1op
-#define lH3 branch2op
-#define lG3 if(lJ3
-#define lF3 l8 a)xI
-#define lE3 overlap
-#define lD3 truth_b
-#define lC3 truth_a
-#define lB3 found_dup
-#define lA3 nQ r;r iH
-#define l93 void set(
-#define l83 {tP1 lE
-#define l73 rangeutil
-#define l63 Plan_Has(
-#define l53 StackMax)
-#define l43 i1 true;}
-#define l33 namespace
-#define l23 (cond yX
-#define l13 inverted
-#define l03 xX3:
-#define iZ2 iftree
-#define iY2 depcodes
-#define iX2 explicit
-#define iW2 cCosh nS
-#define iV2 t01 nH
-#define iU2 VarBegin
-#define iT2 t63 a]
-#define iS2 iR2 size()
-#define iR2 Params.
-#define iQ2 ].data);
-#define iP2 i8)));nZ
-#define iO2 yQ1.SubTrees
-#define iN2 yQ1.Others
-#define iM2 );synth
-#define iL2 ;DumpTree(
-#define iK2 ;Value_t
-#define iJ2 begin(),
-#define iI2 cond_add
-#define iH2 cond_mul
-#define iG2 cond_and
-#define iF2 IsAlways
-#define iE2 func lQ1
-#define iD2 bool eM1
-#define iC2 Forget()
-#define iB2 .second);
-#define iA2 Optimize()
-#define i92 costree
-#define i82 sintree
-#define i72 leaf_count
-#define i62 &&cond eD)
-#define i52 .tT1 n]
-#define i42 =GetParam(
-#define i32 sub_params
-#define i22 nC==cLog2&&
-#define i12 nC==cPow&&
-#define i02 printf(
-#define tZ2 cbrt_count
-#define tY2 sqrt_count
-#define tX2 cPow i7
-#define tW2 ,cPow,
-#define tV2 ,cGreater
-#define tU2 exponent);
-#define tT2 Finite
-#define tS2 min.n3 0),
-#define tR2 p1 cS ifp1
-#define tQ2 yR 2,cAdd)
-#define tP2 pcall_tree
-#define tO2 after_powi
-#define tN2 GetHash().
-#define tM2 yP t23
-#define tL2 params)
-#define tK2 grammar
-#define tJ2 cEqual t11
-#define tI2 cLog nS
-#define tH2 cNeg,lT 1,
-#define tG2 ),0},{
-#define tF2 std::move(
-#define tE2 iH cond nC
-#define tD2 tree iH
-#define tC2 ){eL3
-#define tB2 tree))cJ
-#define tA2 );t0=!t0;}
-#define t92 tmp c91 tree
-#define t82 nQ tmp;tmp iH
-#define t72 tree nC
-#define t62 MakeNEqual
-#define t52 )?0:1))l7
-#define t42 isInteger(
-#define t32 Comparison
-#define t22 needs_flip
-#define t12 (half&63)-1;
-#define t02 value]
-#define eZ2 lT1 opcode
-#define eY2 )lS 3*3*3*2
-#define eX2 cS tree);
-#define eW2 mul_item
-#define eV2 innersub
-#define eU2 cbrt_cost
-#define eT2 best_cost
-#define eS2 condition
-#define eR2 nominator
-#define eQ2 per_item
-#define eP2 item_type
-#define eO2 first2
-#define eN2 l4 18,1,
-#define eM2 cIf,iX 3,
-#define eL2 lJ 1},0,
-#define eK2 tJ 1},0,
-#define eJ2 Decision
-#define eI2 not_tree
-#define eH2 (mulgroup
-#define eG2 (lR));nD lC
-#define eF2 Become(xW
-#define eE2 group_by
-#define eD2 exponent=
-#define eC2 ->second
-#define eB2 targetpos
-#define eA2 ParamSpec
-#define e92 rhs.hash2;}
-#define e82 rhs.hash1
-#define e72 struct
-#define e62 Value_t(
-#define e52 .n_int_sqrt
-#define e42 const std::eP
-#define e32 const char*
-#define e22 nT 409641,
-#define e12 ,xF1);lC
-#define e02 );xY3
-#define cZ2 if(t72==
-#define cY2 eO3 bool>
-#define cX2 ,(long double)
-#define cW2 ContainsOtherCandidates
-#define cV2 std::cout
-#define cU2 source_tree
-#define cT2 GetParam eS
-#define cS2 <tP,x43>
-#define cR2 p1_evenness
-#define cQ2 isNegative(
-#define cP2 neg_set
-#define cO2 }else{x8=new
-#define cN2 );}void
-#define cM2 cNop,cNop}}
-#define cL2 cTanh,cNop,
-#define cK2 NewHash
-#define cJ2 >e72 cB<
-#define cI2 matches
-#define cH2 {cV2<<
-#define cG2 iS1 void*)&
-#define cF2 cGreater,cH
-#define cE2 cSin i7
-#define cD2 cCos nS
-#define cC2 ,t21 0x1 nH
-#define cB2 +=1 i1 n91;
-#define cA2 negated
-#define c92 synth);
-#define c82 Specializer
-#define c72 ifdata.ofs
-#define c62 (IfData&ifdata
-#define c52 .push_back(
-#define c42 ;}data;data.
-#define c32 );sim.x2 2,
-#define c22 nP)l14 tmp=
-#define c12 (*x8)[0].info
-#define c02 CodeTree
-#define yZ2 c02 xF
-#define yY2 coshtree
-#define yX2 sinhtree
-#define yW2 best_score
-#define yV2 mulvalue
-#define yU2 pow_item
-#define yT2 subgroup
-#define yS2 PowiResult
-#define yR2 .match_tree
-#define yQ2 )l43
-#define yP2 0));yD3
-#define yO2 maxValue
-#define yN2 minValue
-#define yM2 yI eW3 if(
-#define yL2 fp_min(yL,
-#define yK2 div_tree
-#define yJ2 pow_tree
-#define yI2 preserve
-#define yH2 ,cCos i7
-#define yG2 (rule cU3,info
-#define yF2 e62 0.5)
-#define yE2 PullResult()
-#define yD2 dup_or_fetch
-#define yC2 e33 false
-#define yB2 test_order
-#define yA2 lX3,
-#define y92 .param_count
-#define y82 shift(index)
-#define y72 rulenumber
-#define y62 cTanh nS
-#define y52 cSinh nS
-#define y42 cInv,lT 1,
-#define y32 constraints=
-#define y22 factor_immed
-#define y12 changes
-#define y02 n81 cS y4 l8
-#define xZ2 cS leaf2 l8
-#define xY2 cS x53 l8
-#define xX2 cS cond l8
-#define xW2 exp_diff
-#define xV2 ExponentInfo
-#define xU2 lower_bound(
-#define xT2 factor
-#define xS2 is_logical
-#define xR2 newrel_and
-#define xQ2 tH[c eE
-#define xP2 ;iM.Remember(
-#define xO2 i1 Unknown;}
-#define xN2 res_stackpos
-#define xM2 half_pos
-#define xL2 >>1)):(
-#define xK2 CodeTreeData
-#define xJ2 multiply(
-#define xI2 tO known)
-#define xH2 var_trees
-#define xG2 erase(cs_it);
-#define xF2 parent_opcode
-#define xE2 log2_exponent
-#define xD2 yB swap(tmp);
-#define xC2 Value(Value::
-#define xB2 dup_fetch_pos
-#define xA2 a;if(eK1){x8=
-#define x92 {cZ start_at;
-#define x82 xX3 cQ lC
-#define x72 cSin nS
-#define x62 Value_EvenInt
-#define x52 )){data xC
-#define x42 MakeFalse,{l5
-#define x32 if(list.first
-#define x22 AddCollection
-#define x12 ConditionType
-#define x02 DUP_ONE(apos)
-#define nZ2 SpecialOpcode
-#define nY2 =i eC2.
-#define nX2 IsDefined()
-#define nW2 fp_max(yL);
-#define nV2 (tree,cV2
-#define nU2 e62-1)
-#define nT2 assimilated
-#define nS2 denominator
-#define nR2 fraction
-#define nQ2 l2 18,2,
-#define nP2 .GetDepth()
-#define nO2 iH t72)
-#define nN2 xI leaf2 l8
-#define nM2 DUP_BOTH();
-#define nL2 x73 lL
-#define nK2 -1-offset].
-#define nJ2 tree.GetHash()
-#define nI2 TreeCounts
-#define nH2 ,e62 1))){
-#define nG2 bool t0 eW3
-#define nF2 found_log2
-#define nE2 div_params
-#define nD2 immed_sum
-#define nC2 :sim.Eat(1,
-#define nB2 OPCODE(opcode)
-#define nA2 ;sim.Push(
-#define n92 break;nS3*=
-#define n82 FactorStack xF
-#define n72 iF2 cQ lC
-#define n62 cLessOrEq,
-#define n52 282870 nT
-#define n42 cNotNot nS
-#define n32 cNot nS
-#define n22 replacing_slot
-#define n12 RefParams
-#define n02 if_always[
-#define lZ2 WhatDoWhenCase
-#define lY2 exponent_immed
-#define lX2 new_base_immed
-#define lW2 base_immed
-#define lV2 ||op1==
-#define lU2 remaining
-#define lT2 Rehash t8
-#define lS2 data[a eI3
-#define lR2 lT2 r);}
-#define lQ2 if(newrel_or==
-#define lP2 .UseGetNeeded(
-#define lO2 e7 2,131,
-#define lN2 Immed eJ3);
-#define lM2 OptimizedUsing
-#define lL2 Var_or_Funcno
-#define lK2 lL2;
-#define lJ2 GetParams(
-#define lI2 crc32_t
-#define lH2 signed_chain
-#define lG2 MinusInf
-#define lF2 synth.Find(
-#define lE2 );cV2<<
-#define lD2 return true;
-#define lC2 n_immeds
-#define lB2 stack eJ3
-#define lA2 FindClone(xM
-#define l92 GetOpcode())
-#define l82 needs_rehash
-#define l72 AnyWhere_Rec
-#define l62 minimum_need
-#define l52 ~x83(0)
-#define l42 41,42,43,44,
-#define l32 p1_logical_b
-#define l22 p0_logical_b
-#define l12 p1_logical_a
-#define l02 p0_logical_a
-#define iZ1 (size_t
-#define iY1 )e73
-#define iX1 TopLevel)
-#define iW1 .e33)
-#define iV1 {pow.CopyOnWrite
-#define iU1 nB OPCODE
-#define iT1 const yZ2
-#define iS1 (const
-#define iR1 iS1 yZ2&
-#define iQ1 ,PowiCache&iM,
-#define iP1 else if(
-#define iO1 iP1!nS3
-#define iN1 synth.DoDup(
-#define iM1 cache_needed
-#define iL1 e7 2,1,e7 2,
-#define iK1 [c72+
-#define iJ1 treelist
-#define iI1 IsDescendantOf(
-#define iH1 has_bad_balance
-#define iG1 )tN mulgroup)
-#define iF1 .SetParamsMove(
-#define iE1 cO3 xT2
-#define iD1 double)exponent
-#define iC1 {if(GetOpcode()
-#define iB1 cV2<<std::y11
-#define iA1 cV2<<"POP "
-#define i91 DelParam(
-#define i81 set(fp_ceil);tK
-#define i71 fp_abs(max.val))
-#define i61 fp_abs(min.val)
-#define i51 cNEqual
-#define i41 },0,0x0},{{
-#define i31 tJ 2 i41
-#define i21 Oneness_NotOne|
-#define i11 Value_IsInteger
-#define i01 Constness_Const
-#define tZ1 DumpHashesFrom(
-#define tY1 reltype
-#define tX1 const Value_t&i)
-#define tW1 const c02&
-#define tV1 const Value_t&v
-#define tU1 SequenceOpcodes
-#define tT1 sep_list[
-#define tS1 ;else_tree
-#define tR1 goto fail;}
-#define tQ1 l1 0x4 nH
-#define tP1 x73<
-#define tO1 n12);
-#define tN1 ){case iF2:
-#define tM1 grammar_rules[*r]
-#define tL1 x73 set_if<
-#define tK1 x73 lX
-#define tJ1 TreeCountType xF
-#define tI1 GetParamCount(nX
-#define tH1 >(e62 1),
-#define tG1 nL3)
-#define tF1 )lX3.second
-#define tE1 e62 0.0)){nU
-#define tD1 .IsImmed()
-#define tC1 a)tD1)
-#define tB1 nB2);
-#define tA1 stack[lB2-
-#define t91 stack c52
-#define t81 )eX3 iW1;
-#define t71 synth.PushImmed(
-#define t61 MaxChildDepth
-#define t51 repl_param_list,
-#define t41 const Rule&rule,
-#define t31 std::pair<It,It>
-#define t21 cPow,lA
-#define t11 ,l0 2,
-#define t01 ,l1 0x12
-#define eZ1 Sign_Negative
-#define eY1 Value_Logical
-#define eX1 yZ2&b
-#define eW1 new_factor_immed
-#define eV1 occurance_pos
-#define eU1 exponent_hash
-#define eT1 exponent_list
-#define eS1 CollectionSet xF
-#define eR1 CollectMulGroup(
-#define eQ1 source_set
-#define eP1 exponent,y63
-#define eO1 *const func)(
-#define eN1 ByteCode
-#define eM1 operator
-#define eL1 FindAndDup(tree);
-#define eK1 &*start_at
-#define eJ1 <<nJ2.
-#define eI1 xW 1)tD1&&
-#define eH1 retry_anyparams_3
-#define eG1 retry_anyparams_2
-#define eF1 e6(),eO3
-#define eE1 needlist_cached_t
-#define eD1 yH3 0x4 lR3
-#define eC1 eL2 0x4 lR3
-#define eB1 ),lM2(
-#define eA1 CodeTreeImmed xF(
-#define e91 GetParamCount()==
-#define e81 .back().thenbranch
-#define e71 eN1,size_t&IP,size_t limit,size_t y2
-#define e61 .cG3
-#define e51 (lR,xW i8));nD
-#define e41 ;flipped=!flipped;}
-#define e31 ,l1 0x0},{{3,
-#define e21 }xY3 case
-#define e11 for iZ1 b=0;b<
-#define e01 by_float_exponent
-#define cZ1 lJ3 exponent
-#define cY1 new_exp
-#define cX1 end()&&i->first==
-#define cW1 return BecomeZero;
-#define cV1 =comp.AddItem(atree
-#define cU1 return BecomeOne;
-#define cT1 if(lQ eJ3<=n1)
-#define cS1 addgroup
-#define cR1 found_log2by
-#define cQ1 nC==cC3)
-#define cP1 ParsePowiMuli(
-#define cO1 lL2)
-#define cN1 eL 529654 nT
-#define cM1 branch1_backup
-#define cL1 branch2_backup
-#define cK1 exponent_map
-#define cJ1 plain_set
-#define cI1 rangehalf
-#define cH1 LightWeight(
-#define cG1 xV3 1
-#define cF1 divgroup
-#define cE1 ,iM e63
-#define cD1 if(value
-#define cC1 tK1 c0
-#define cB1 tK1 static
-#define cA1 mulgroup.
-#define c91 .AddParamMove(
-#define c81 yB AddParamMove(
-#define c71 ;n81 cY op1 yB DelParams
-#define c61 should_regenerate=true;
-#define c51 should_regenerate,
-#define c41 Collection
-#define c31 RelationshipResult
-#define c21 Subdivide_Combine(
-#define c11 long value
-#define c01 )const yP
-#define yZ1 rhs c01 hash1
-#define yY1 for iZ1 a xY
-#define yX1 best_sep_factor
-#define yW1 SynthesizeParam
-#define yV1 needlist_cached
-#define yU1 inline x83
-#define yT1 opcode,bool pad
-#define yS1 changed=true;
-#define yR1 );xM iF1
-#define yQ1 NeedList
-#define yP1 tK1 bool
-#define yO1 ;tK1
-#define yN1 i91 a);}
-#define yM1 MakesInteger(
-#define yL1 const Value_t&value
-#define yK1 best_sep_cost
-#define yJ1 MultiplicationRange
-#define yI1 .min.set(fp_floor);
-#define yH1 pihalf_limits
-#define yG1 yR 2,cMul);lC
-#define yF1 n_stacked
-#define yE1 cK2.hash1
-#define yD1 AnyParams_Rec
-#define yC1 ;synth.StackTopIs(
-#define yB1 synth.AddOperation(
-#define yA1 continue;
-#define y91 Become(value l8 0))
-#define y81 }inline
-#define y71 PositionalParams,0}
-#define y61 always_sincostan
-#define y51 Recheck_RefCount_Div
-#define y41 Recheck_RefCount_Mul
-#define y31 MultiplyAndMakeLong(
-#define y21 covers_plus1
-#define y11 endl;DumpHashes(
-#define y01 if(synth.FindAndDup(
-#define xZ1 grammar_func
-#define xY1 tree tD1 cQ
-#define xX1 cOr l3 16,1,
-#define xW1 252421 nT 24830,
-#define xV1 l2 0,2,165888 nT
-#define xU1 Modulo_Radians},
-#define xT1 yB SetParam(
-#define xS1 PositionType
-#define xR1 CollectionResult
-#define xQ1 const_offset
-#define xP1 inline TriTruthValue
-#define xO1 stacktop_desired
-#define xN1 iU3);lC
-#define xM1 SetStackTop(
-#define xL1 tK1 void
-#define xK1 FPoptimizer_ByteCode
-#define xJ1 1)?(poly^(
-#define xI1 eP3&synth)
-#define xH1 e62 0)
-#define xG1 xH1)
-#define xF1 cond_type
-#define xE1 fphash_value_t
-#define xD1 Recheck_RefCount_RDiv
-#define xC1 cMul);tmp tY3 tmp.
-#define xB1 SwapLastTwoInStack();
-#define xA1 SetParams(lJ2)
-#define x91 fPExponentIsTooLarge(
-#define x81 CollectMulGroup_Item(
-#define x71 pair<Value_t,y63>
-#define x61 (x53 l8 1)nN2
-#define x51 for iZ1 a=0;a<yC++a)
-#define x41 .GetImmed()
-#define x31 {int mStackPtr=0;
-#define x21 nL xM1 xQ-1);
-#define x11 covers_full_cycle
-#define x01 AssembleSequence(
-#define nZ1 inverse_nominator
-#define nY1 252180 nT 281854,
-#define nX1 <<std::dec<<")";}
-#define nW1 {DataP slot_holder(y1[
-#define nV1 },{l5::MakeNotP1,l5::
-#define nU1 },{l5::MakeNotP0,l5::
-#define nT1 },{l5::MakeNotNotP1,l5::
-#define nS1 !=xJ)if(TestCase(
-#define nR1 AddFunctionOpcode
-#define nQ1 public e6,public eO3
-#define nP1 yZ2&tree,
-#define nO1 std::pair<T1,T2>&
-#define nN1 tP1 x93
-#define nM1 has_good_balance_found
-#define nL1 n_occurrences
-#define nK1 found_log2_on_exponent
-#define nJ1 covers_minus1
-#define nI1 needs_resynth
-#define nH1 immed_product
-#define nG1 l33 FPoptimizer_Optimize
-#define nF1 (ParamSpec_Extract xF(
-#define nE1 yV3 bitmask&
-#define nD1 Sign_Positive
-#define nC1 ::MakeTrue
-#define nB1 SetParamMove(
-#define nA1 CodeTreeImmed(e62
-#define n91 Suboptimal
-#define n81 changed_if
-#define n71 n_as_tanh_param
-#define n61 opposite=
-#define n51 xE1(
-#define n41 eN1 eJ3
-#define n31 MatchResultType
-#define n21 yP yZ2(
-#define n11 needs_sincos
-#define n01 resulting_exponent
-#define lZ1 Unknown:yF3;}
-#define lY1 GetLogicalValue(xW
-#define lX1 GetParam(a)
-#define lW1 cMul l3 0,1,
-#define lV1 IsImmed())l14
-#define lU1 void FunctionParserBase
-#define lT1 (x83
-#define lS1 lT1 a=0;a<xT;++a)
-#define lR1 o<<"("<<std::hex<<data.
-#define lQ1 (val);else*this=model;}
-#define lP1 IfBalanceGood(
-#define lO1 n_as_tan_param
-#define lN1 changed_exponent
-#define lM1 inverse_denominator
-#define lL1 ;cK2.hash2+=
-#define lK1 retry_positionalparams_2
-#define lJ1 x83 index
-#define lI1 situation_flags&
-#define lH1 518 nT 400412,
-#define lG1 data.subfunc_opcode
-#define lF1 },{l5::MakeNotNotP0,l5::
-#define lE1 (yO3 start_at
-#define lD1 CopyOnWrite();
-#define lC1 recursioncount
-#define lB1 PlanNtimesCache(
-#define lA1 FPoptimizer_Grammar
-#define l91 GetParamCount();
-#define l81 GetPositivityInfo iS3
-#define l71 ParamSpec_SubFunctionData
-#define l61 t43<e62
-#define l51 (tree.GetParamCount()
-#define l41 iZ1 a=yC a-->0;)
-#define l31 PositionalParams_Rec
-#define l21 DumpTreeWithIndent(*this);
-#define l11 e23 type){case cond_or:
-#define l01 tP1 x83 Compare>
-#define iZ tree.i91 a
-#define iY .l91 a-->0;)if(
-#define iX lA 0x4},{{
-#define iW lJ 2 i41 1,
-#define iV edited_powgroup
-#define iU has_unknown_max
-#define iT has_unknown_min
-#define iS static const yD3
-#define iR if(keep_powi
-#define iQ synthed_tree
-#define iP 7168 nT 401798,
-#define iO SelectedParams,0 i41
-#define iN collections
-#define iM cache
-#define iL ,cIf,l0 3,
-#define iK ,eN1,IP,limit,y2,stack);
-#define iJ by_exponent
-#define iI );p2.lT2 p2 yB eL3 iZ2 nC);cJ}
-#define iH .eL3
-#define iG mulgroup;mulgroup iH
-#define iF (p0 e61&&p0 nL3 i2
-#define iE cN3 p0 yM>=e62 0.0))
-#define iD goto ReplaceTreeWithOne t83
-#define iC !=xJ)return n02
-#define iB e01.data
-#define iA iX2 xK2(
-#define i9 needs_sinhcosh
-#define i8 1)x41
-#define i7 ,l4 2,1,
-#define i6 cAdd l3 0,
-#define i5 tG2 e62
-#define i4 tK1 n9
-#define i3 MakeFalse,l5::
-#define i2 <=fp_const_negativezero xF())
-#define i1 ;return
-#define i0 )i1 lH
-#define tZ CalculateResultBoundaries(xW
-#define tY p0=CalculateResultBoundaries(
-#define tX ;yZ2
-#define tW ,2,1 iM2.xR if(found[data.
-#define tV 408964 nT 24963,
-#define tU 528503 nT 24713,
-#define tT matched_params
-#define tS [n1 eH3=true;lQ[n1 eI3
-#define tR lA1::Grammar*
-#define tQ AddOperation(cInv,1,1 iM2.xR}
-#define tP int_exponent_t
-#define tO m.max.
-#define tN ;AddParamMove(
-#define tM nM nU2,e62 1));
-#define tL cG3 eW3
-#define tK return m;}case
-#define tJ x9 AnyParams,
-#define tI powgroup l8
-#define tH relationships
-#define tG ]!=~size_t(0)){synth.yT
-#define tF }},{ProduceNewTree,2,1,
-#define tE nA1(
-#define tD has_mulgroups_remaining
-#define tC MatchInfo xF&
-#define tB e33);i32 c52
-#define tA best_factor
-#define t9 RootPowerTable xF::RootPowers[
-#define t8 (c81
-#define t7 :goto ReplaceTreeWithZero t83
-#define t6 MatchPositionSpec_AnyParams xF
-#define t5 l33 FPoptimizer_CodeTree
-#define t4 n_as_sinh_param
-#define t3 n_as_cosh_param
-#define t2 ();pow iH cLog yB eL3 cMul
-#define t1 0,tU2 i91 1);
-#define t0 is_signed
-#define eZ result_positivity
-#define eY biggest_minimum
-#define eX const l71
-#define eW 122999 nT 139399,
-#define eV 142455 nT 141449,
-#define eU cond_tree
-#define eT then_tree
-#define eS (a);bool needs_cow=GetRefCount()>1;
-#define eR yZ2&tree)
-#define eQ sequencing
-#define eP string FP_GetOpcodeName(
-#define eO );eN1 c52 0x80000000u
-#define eN {if(needs_cow){lD1 goto
-#define eM (lJ2));cA1 e33);
-#define eL ,nQ2
-#define eK eO3 yZ2>
-#define eJ if_stack
-#define eI n_as_sin_param
-#define eH n_as_cos_param
-#define eG PowiResolver::
-#define eF cIf,tG3
-#define eE ].relationship
-#define eD .BalanceGood
-#define eC AddParamMove(yT2
-#define eB valueType
-#define eA back().endif_location
-#define e9 xE1 key
-#define e8 AddParamMove(mul);
-#define e7 130,1,
-#define e6 MatchPositionSpecBase
-#define e5 iX2 c02(
-#define e4 smallest_maximum
-#define e3 ]!=~size_t(0)&&found[data.
-#define e2 }PACKED_GRAMMAR_ATTRIBUTE;
-#define e1 ReplaceTreeWithParam0;
-#define e0 factor_needs_rehashing
-#define cZ MatchPositionSpecBaseP
-#define cY .e33 yB eL3
-#define cX x93 tJ1::y83
-#define cW ParamSpec_Extract xF(nN.param_list,
-#define cV }x32 x41==e62
-#define cU 243,244,245,246,249,250,251,253,255,256,257,258,259}};}
-#define cT ];};extern"C"{
-#define cS .AddParam(
-#define cR iL2 tree lE2"\n";
-#define cQ )return false;
-#define cP 79,122,123,160,161,163,164,165,166,167,168,169,178,179,180,200,204,212,216,224,236,237,239,240,
-#define cO 27,28,29,30,31,32,33,35,36,
-#define cN const ParamSpec_SubFunction
-#define cM const ParamSpec_ParamHolder
-#define cL otherhalf
-#define cK :{AdoptChildrenWithSameOpcode(tree);
-#define cJ goto redo;
-#define cI StackState
-#define cH l2 16,2,
-#define cG const SequenceOpCode xF
-#define cF MatchPositionSpec_PositionalParams xF
-#define cE const nP1 std::ostream&o
-#define cD e62 1.5)*fp_const_pi xF()
-#define cC CalculatePowiFactorCost(
-#define cB ImmedHashGenerator
-#define cA paramholder_matches
-#define c9 ::map<fphash_t,std::set<eM3> >
-#define c8 ComparisonSetBase::
-#define c7 AddParamMove(comp.cJ1[a].value);
-#define c6 T1,x93 T2>inline iD2()(
-#define c5 has_nonlogical_values
-#define c4 from_logical_context)
-#define c3 AnyParams,0}},{ProduceNewTree,
-#define c2 for iZ1 a=xV.l91 a-->0;)
-#define c1 POWI_CACHE_SIZE
-#define c0 static inline yZ2
-#define yZ ++IP;yA1}if(n13 c33.
-#define yY },{l5::xJ,l5::Never},{l5::xJ,l5::Never}}
-#define yX .FoundChild
-#define yW BalanceResultType
-#define yV {yZ2 tmp;tmp iH
-#define yU yB1 GetOpcode(),
-#define yT DoDup(found[data.
-#define yS xB3(0),Opcode(
-#define yR ;sim.Eat(
-#define yQ );void nR1 eZ2,c82<
-#define yP {return
-#define yO const yP data->
-#define yN +=fp_const_twopi xF();
-#define yM .min.val
-#define yL fp_sin(min),fp_sin(max))
-#define yK fp_const_twopi xF());if(
-#define yJ {yZ2 tmp,tmp2;tmp2 iH
-#define yI .min.known
-#define yH for iZ1 a=0;a<l91++a){if(
-#define yG MatchPositionSpec_AnyWhere
-#define yF if yZ3 data.match_type==
-#define yE void OutFloatHex(std::ostream&o,
-#define yD {static void lY3 nB fphash_t&cK2,
-#define yC tree.l91
-#define yB );tree.
-#define yA AddParam(CodeTreeImmed(
-#define y9 cGreaterOrEq,
-#define y8 ,x93 yZ2::
-#define y7 xF model=cI1 xF()){if(known
-#define y6 AssembleSequence_Subdivide(
-#define y5 ]=0x80000000u|x83(
-#define y4 branch2
-#define y3 x83 c;x83 short l[
-#define y2 factor_stack_base
-#define y1 data->Params
-#define y0 (lW3 r=range.first;r!=range.i63++r){
-#define xZ {nI2.erase(i);yA1}
-#define xY =0;a<y53.l91++a)if(
-#define xX ,t21 0x4 nH
-#define xW tree l8
-#define xV branch1
-#define xU ,nU2))eN
-#define xT nN y92
-#define xS =fp_cosh(m yM);tO val=fp_cosh(tO val);
-#define xR StackTopIs(*this)i1;}
-#define xQ StackTop
-#define xP FPOPT_autoptr
-#define xO +=nS3 i1 nS3;}tK1 inline Value_t
-#define xN int_exponent
-#define xM newnode
-#define xL lJ 1 i41
-#define xK has_highlevel_opcodes
-#define xJ Unchanged
-#define xI .IsIdenticalTo(
-#define xH GetStackTop()-
-#define xG sim.AddConst(
-#define xF <Value_t>
-#define xE cE=cV2
-#define xD best_selected_sep
-#define xC ->Recalculate_Hash_NoRecursion();}
-#define xB l91++a)if(ApplyGrammar(tK2,xW a),
-#define xA lU3 2,1,
-#define x9 ,cAdd,
-#define x8 position
-#define x7 x51{yD3
-#define x6 ;tmp2 tY3 tmp iH cInv);tmp c91 tmp2)i1
-#define x5 eO3 c02>
-#define x4 SetParam(0,iZ2 l8 0))tX p1;p1 iH
-#define x3 TestImmedConstraints yZ3 constraints cU3)cQ
-#define x2 SwapLastTwoInStack()yR
-#define x1 n23 1,cInv e02 xG-1 xN1
-#define x0 paramholder_index
-#define nZ lD2 case
-#define nY occurance_counts
-#define nX );a-->0;){iT1&powgroup=lX1;if(powgroup
-#define nW )){tree.tE3;}
-#define nV Value_t>p=tZ a));if(p.
-#define nU tree.ReplaceWithImmed(
-#define nT ,{2,
-#define nS ,l0 1,
-#define nR ,cAdd l3 2,1,
-#define nQ ){yZ2
-#define nP if(xW 0)tD1
-#define nO const FPoptimizer_CodeTree::yZ2&tree
-#define nN model_tree
-#define nM return yD3(
-#define nL ){using l33 FUNCTIONPARSERTYPES;
-#define nK eK&n12
-#define nJ AddParam(xW
-#define nI ConstantFolding_LogicCommon(tree,c8
-#define nH },{{2,
-#define nG nN1 Ref>inline void xP<Ref>::
-#define nF AnyParams,1 i41
-#define nE ):data(new xK2 xF(
-#define nD goto do_return;}
-#define nC .GetOpcode()
-#define nB FUNCTIONPARSERTYPES::
-#define nA b;}};tP1>e72 Comp<nB
-#define n9 xK2 xF::xK2(
-#define n8 lL2(),t53),Hash(),Depth(1 eB1 0){}
-#define n7 SynthesizeByteCode(c92
-#define n6 while(ApplyGrammar(cG2
-#define n5 GetIntegerInfo(xW 0))==iF2)n73
-#define n4 ;tree c91 n81 yQ2
-#define n3 tL1 cGreater>(e62
-#define n2 DumpParams xF yZ3 data.param_list,iH3 y92,o);
-#define n1 restholder_index
-#define n0 yZ2 exponent eX3 iH cMul)eX3 cS
-#define lZ lR);if(fp_nequal(tmp,xG1){nU e62 1)/tmp);nD}lC
-#define lY :if(ParamComparer xF()(t63 1],t63 0])){std::swap(t63 0],t63 1]);Opcode=
-#define lX <x93 Value_t>
-#define lW xF tmp;tmp iH cPow);tmp tY3 tmp.yA e62
-#define lV i01,0x0},
-#define lU AddParamMove(pow l8 1));pow.i91 1);pow.e33 yB nB1 0,pow);goto NowWeAreMulGroup;}
-#define lT GroupFunction,0},lV{{
-#define lS ,e62 1)/e62
-#define lR xW 0)x41
-#define lQ restholder_matches
-#define lP yE1|=key;xE1 crc=(key>>10)|(key<<(64-10))lL1((~n51 crc))*3)^1234567;}};
-#define lO n81;n81 nO2;n81 c91 xW 0));n81 cS xV l8
-#define lN tK1 yZ2::c02(
-#define lM tree.SetParam(0,xW 0)l8 0)xT1 1,CodeTreeImmed(
-#define lL lX void eP3::nR1 eZ2,c82<
-#define lK cMul,lT 2,
-#define lJ cMul,AnyParams,
-#define lI (xW 0)tD1&&xW 1)tD1){nU
-#define lH CalculateResultBoundaries(tmp);}case
-#define lG :cY3=comp.AddRelationship(atree l8 0),atree l8 1),c8
-#define lF cPow,l0 2
-#define lE x93 Value_t>inline iD2()iS1 Value_t&xC3 Value_t&b)yP a
-#define lD {yD3 m=tZ 0));
-#define lC break t83
-#define lB xL1 yZ2::
-#define lA y71,0,
-#define l9 l1 0x0 nH
-#define l8 .GetParam(
-#define l7 tX n81;n81 nO2;n81 iF1 tree.lJ2));n81 cY
-#define l6 SelectedParams,0},0,0x0 nH
-#define l5 RangeComparisonData
-#define l4 y71},{ProduceNewTree,
-#define l3 ,AnyParams,0}},{ReplaceParams,
-#define l2 y71},{ReplaceParams,
-#define l1 cMul,SelectedParams,0},0,
-#define l0 lA 0x0},{{
-#ifdef _MSC_VER
-typedef
-x83
-int
-lI2;
-#else
-typedef
-uint_least32_t
-lI2;
-#endif
-l33
-crc32{enum{startvalue=0xFFFFFFFFUL,poly=0xEDB88320UL}
-;tP1
-lI2
-crc>e72
-b8{enum{b1=(crc&xJ1
-crc
-xL2
-crc>>1),b2=(b1&xJ1
-b1
-xL2
-b1>>1),b3=(b2&xJ1
-b2
-xL2
-b2>>1),b4=(b3&xJ1
-b3
-xL2
-b3>>1),b5=(b4&xJ1
-b4
-xL2
-b4>>1),b6=(b5&xJ1
-b5
-xL2
-b5>>1),b7=(b6&xJ1
-b6
-xL2
-b6>>1),res=(b7&xJ1
-b7
-xL2
-b7>>1)}
-;}
-;inline
-lI2
-update(lI2
-crc,x83
-b){
-#define B4(n) b8<n>nP3 n+1>nP3 n+2>nP3 n+3>::res
-#define R(n) B4(n),B4(n+4),B4(n+8),B4(n+12)
-static
-const
-lI2
-table[256]={R(0x00),R(0x10),R(0x20),R(0x30),R(0x40),R(0x50),R(0x60),R(0x70),R(0x80),R(0x90),R(0xA0),R(0xB0),R(0xC0),R(0xD0),R(0xE0),R(0xF0)}
-;
-#undef R
-#undef B4
-return((crc>>8))^table[(crc^b)&0xFF];y81
-lI2
-calc_upd(lI2
-c,const
-x83
-char*buf,size_t
-size){lI2
-value=c
-eK3
-p=0;p<size;++p)value=update(value,buf[p])i1
-value;y81
-lI2
-calc
-iS1
-x83
-char*buf,size_t
-size)yP
-calc_upd(startvalue,buf,size);}
-}
-#ifndef FPOptimizerAutoPtrHH
-#define FPOptimizerAutoPtrHH
-nN1
-Ref>class
-xP{e43
-xP():p(0){}
-xP(Ref*b):p(b){xA3}
-xP
-iS1
-xP&b):p(b.p){xA3
-y81
-Ref&eM1*(c01*p;y81
-Ref*eM1->(c01
-p;}
-xP&eM1=(Ref*b){Set(b)i1*this;}
-xP&eM1=iS1
-xP&b){Set(b.p)i1*this;}
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-xP(xP&&b):p(b.p){b.p=0;}
-xP&eM1=(xP&&b){if(p!=b.p){iC2;p=b.p;b.p=0;eE3*this;}
-#endif
-~xP(){Forget(cN2
-UnsafeSetP(Ref*newp){p=newp;}
-void
-swap(xP<Ref>&b){Ref*tmp=p;p=b.p;b.p=tmp;}
-private:inline
-static
-void
-Have(Ref*p2);inline
-void
-iC2;inline
-void
-xA3
-inline
-void
-Set(Ref*p2);private:Ref*p;}
-;nG
-iC2{if(!p)return;p->xB3-=1;if(!p->xB3)delete
-p;}
-nG
-Have(Ref*p2){if(p2)++(p2->xB3);}
-nG
-Birth(){Have(p);}
-nG
-Set(Ref*p2){Have(p2);iC2;p=p2;}
-#endif
-e72
-Compare2ndRev{nN1
-T>inline
-iD2()iS1
-T&xC3
-T&b
-c01
-a.second>b.i63}
-}
-;e72
-Compare1st{nN1
-c6
-const
-nO1
-xC3
-nO1
-b
-c01
-a.first<b.first;}
-nN1
-c6
-const
-nO1
-a,T1
-b
-c01
-a.first<b;}
-nN1
-c6
-T1
-xC3
-nO1
-b
-c01
-a<b.first;}
-}
-;
-#ifndef FPoptimizerHashHH
-#define FPoptimizerHashHH
-#ifdef _MSC_VER
-typedef
-x83
-long
-long
-xE1;
-#define FPHASH_CONST(x) x##ULL
-#else
-typedef
-uint_fast64_t
-xE1;
-#define FPHASH_CONST(x) x##ULL
-#endif
-l33
-FUNCTIONPARSERTYPES{e72
-fphash_t{xE1
-hash1,hash2;fphash_t():hash1(0),hash2(0){}
-fphash_t
-iS1
-xE1&xC3
-xE1&b):hash1(a),hash2(b){}
-iD2==iS1
-fphash_t&yZ1==e82&&hash2==e92
-iD2!=iS1
-fphash_t&yZ1!=e82||hash2!=e92
-iD2<iS1
-fphash_t&yZ1!=e82?hash1<e82:hash2<e92}
-;}
-#endif
-#ifndef FPOptimizer_CodeTreeHH
-#define FPOptimizer_CodeTreeHH
-#ifdef FP_SUPPORT_OPTIMIZER
-l33
-lA1{e72
-Grammar;}
-l33
-xK1{tK1
-class
-ByteCodeSynth;}
-t5{tK1
-class
-c02
-yO1
-e72
-xK2
-yO1
-class
-c02{typedef
-xP<xK2
-xF>DataP;DataP
-data;e43
-c02();~c02();e72
-OpcodeTag{}
-;e5
-iU1
-o,OpcodeTag);e72
-FuncOpcodeTag{}
-;e5
-iU1
-o,x83
-f,FuncOpcodeTag);e72
-xD3{}
-;e5
-tV1,xD3);
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-e5
-Value_t&&v,xD3);
-#endif
-e72
-VarTag{}
-;e5
-x83
-varno,VarTag);e72
-CloneTag{}
-;e5
-tW1
-b,CloneTag);void
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&data,bool
-keep_powi=false);void
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&data,const
-x5&xH2,bool
-keep_powi=false);void
-SynthesizeByteCode(eO3
-x83>&cT3,std
-xM3
-xF&immed,size_t&stacktop_max);void
-SynthesizeByteCode(xK1::eP3&synth,bool
-MustPopTemps=true)const;size_t
-SynthCommonSubExpressions(xK1::xI1
-const;void
-SetParams
-iS1
-x5&xE3
-SetParamsMove(x5&tO1
-c02
-GetUniqueRef();
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-void
-SetParams(x5&&tO1
-#endif
-void
-SetParam
-iZ1
-which,tW1
-b);void
-nB1
-size_t
-which,c02&b);void
-AddParam(tW1
-param);void
-AddParamMove(c02¶m);void
-AddParams
-iS1
-x5&xE3
-AddParamsMove(x5&xE3
-AddParamsMove(x5&n12,size_t
-n22);void
-i91
-size_t
-index);void
-DelParams();void
-Become(tW1
-b);inline
-size_t
-GetParamCount(c01
-lJ2)eJ3;y81
-c02&GetParam
-iZ1
-n)yP
-lJ2)[n];y81
-tW1
-GetParam
-iZ1
-n
-c01
-lJ2)[n];y81
-void
-eL3
-iU1
-o)iZ3
-Opcode=o;y81
-iU1
-GetOpcode()yO
-Opcode;y81
-nB
-fphash_t
-GetHash()yO
-Hash;y81
-const
-x5&lJ2
-c01
-y1;y81
-x5&lJ2)yP
-y1;y81
-size_t
-GetDepth()yO
-Depth;y81
-const
-Value_t&GetImmed()yO
-Value;y81
-x83
-GetVar()yO
-lK2
-y81
-x83
-GetFuncNo()yO
-lK2
-y81
-bool
-IsDefined(c01
-GetOpcode()!=nB
-cNop;y81
-bool
-IsImmed(c01
-GetOpcode()==nB
-cImmed;y81
-bool
-IsVar(c01
-GetOpcode()==nB
-iU2;y81
-x83
-GetRefCount()yO
-xB3;}
-void
-ReplaceWithImmed(tX1;void
-e33
-bool
-constantfolding=true);void
-Sort();inline
-void
-Mark_Incompletely_Hashed()iZ3
-Depth=0;y81
-bool
-Is_Incompletely_Hashed()yO
-Depth==0;y81
-const
-tR
-GetOptimizedUsing()yO
-lM2;y81
-void
-SetOptimizedUsing
-iS1
-tR
-g)iZ3
-lM2=g;}
-bool
-RecreateInversionsAndNegations(bool
-prefer_base2=false);void
-tE3;void
-swap(c02&b){data.swap(b.data);}
-bool
-IsIdenticalTo(tW1
-b)const;void
-lD1}
-yO1
-e72
-xK2{int
-xB3;iU1
-Opcode
-iK2
-Value;x83
-lK2
-eK
-Params;nB
-fphash_t
-Hash;size_t
-Depth;const
-tR
-lM2;xK2();xK2
-iS1
-xK2&b);iA
-iU1
-o);iA
-iU1
-o,x83
-f);iA
-tX1;
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-iA
-Value_t&&i);xK2(xK2&&b);
-#endif
-bool
-IsIdenticalTo
-iS1
-xK2&b)const;void
-Sort();void
-Recalculate_Hash_NoRecursion();private:void
-eM1=iS1
-xK2&b);}
-yO1
-c0
-CodeTreeImmed(tX1
-n21
-i
-y8
-xD3());}
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-cC1
-CodeTreeImmed
-cX3&&i)n21
-tF2
-i)y8
-xD3());}
-#endif
-cC1
-CodeTreeOp(iU1
-opcode)n21
-opcode
-y8
-OpcodeTag());}
-cC1
-CodeTreeFuncOp(iU1
-opcode,x83
-f)n21
-opcode,f
-y8
-FuncOpcodeTag());}
-cC1
-CodeTreeVar
-lT1
-varno)n21
-varno
-y8
-VarTag());}
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-xL1
-DumpHashes(xE);xL1
-DumpTree(xE);xL1
-DumpTreeWithIndent(xE,const
-eM3&indent="\\"
-);
-#endif
-}
-#endif
-#endif
-#ifndef FPOptimizer_GrammarHH
-#define FPOptimizer_GrammarHH
-t5{tK1
-class
-c02;}
-l33
-lA1{enum
-ImmedConstraint_Value{ValueMask=0x07,Value_AnyNum=0x0,x62=0x1,Value_OddInt=0x2,i11=0x3,Value_NonInteger=0x4,eY1=0x5}
-;enum
-ImmedConstraint_Sign{SignMask=0x18,Sign_AnySign=0x00,nD1=0x08,eZ1=0x10,Sign_NoIdea=0x18}
-;enum
-ImmedConstraint_Oneness{OnenessMask=0x60,Oneness_Any=0x00,Oneness_One=0x20,Oneness_NotOne=0x40}
-;enum
-ImmedConstraint_Constness{ConstnessMask=0x180,Constness_Any=0x00,i01=0x80,Constness_NotConst=0x100}
-;enum
-Modulo_Mode{Modulo_None=0,Modulo_Radians=1}
-;enum
-Situation_Flags{LogicalContextOnly=0x01,NotForIntegers=0x02,OnlyForIntegers=0x04,OnlyForComplex=0x08,NotForComplex=0x10}
-;enum
-nZ2{NumConstant,ParamHolder,SubFunction}
-;enum
-ParamMatchingType{PositionalParams,SelectedParams,AnyParams,GroupFunction}
-;enum
-RuleType{ProduceNewTree,ReplaceParams}
-;
-#ifdef __GNUC__
-# define PACKED_GRAMMAR_ATTRIBUTE __attribute__((packed))
-#else
-# define PACKED_GRAMMAR_ATTRIBUTE
-#endif
-typedef
-std::pair<nZ2,const
-void*>eA2
-yO1
-eA2
-ParamSpec_Extract
-lT1
-paramlist,lJ1)yO1
-bool
-ParamSpec_Compare
-iS1
-void*xC3
-void*b,nZ2
-type);x83
-ParamSpec_GetDepCode
-iS1
-eA2&b);e72
-ParamSpec_ParamHolder{lJ1:8;x83
-constraints:9;x83
-depcode:15;e2
-tK1
-e72
-ParamSpec_NumConstant
-l14
-constvalue;x83
-modulo;}
-;e72
-l71{x83
-param_count:2;x83
-param_list:30;iU1
-subfunc_opcode:8;ParamMatchingType
-match_type:3;x83
-n1:5;e2
-e72
-ParamSpec_SubFunction{l71
-data;x83
-constraints:9;x83
-depcode:7;e2
-e72
-Rule{RuleType
-ruletype:2;x83
-situation_flags:5;x83
-repl_param_count:2+9;x83
-repl_param_list:30;l71
-match_tree;e2
-e72
-Grammar{x83
-rule_count;x83
-short
-rule_list[999
-cT
-extern
-const
-Rule
-grammar_rules[];}
-xL1
-DumpParam
-iS1
-eA2&p,std::ostream&o=cV2);xL1
-DumpParams
-lT1
-paramlist,x83
-count,std::ostream&o=cV2);}
-#endif
-#ifndef M_PI
-#define M_PI 3.1415926535897932384626433832795
-#endif
-#define CONSTANT_POS_INF HUGE_VAL
-#define CONSTANT_NEG_INF (-HUGE_VAL)
-l33
-FUNCTIONPARSERTYPES{tK1
-inline
-Value_t
-fp_const_pihalf()yP
-fp_const_pi
-xF()*yF2;}
-tK1
-inline
-Value_t
-fp_const_twopi()eQ3
-fp_const_pi
-xF());nS3
-xO
-fp_const_twoe()eQ3
-fp_const_e
-xF());nS3
-xO
-fp_const_twoeinv()eQ3
-fp_const_einv
-xF());nS3
-xO
-fp_const_negativezero()yP-Epsilon
-xF::value;}
-}
-#ifdef FP_SUPPORT_OPTIMIZER
-nG1{using
-l33
-lA1;using
-t5;using
-l33
-FUNCTIONPARSERTYPES
-yO1
-class
-MatchInfo{e43
-eO3
-std::pair<bool,eK> >lQ;eK
-cA;eO3
-x83>tT;e43
-MatchInfo():lQ(),cA(),tT(){}
-e43
-bool
-SaveOrTestRestHolder
-lT1
-n1,eA3&iJ1){cT1{lQ
-xF3
-n1+1);lQ
-tS=iJ1
-l43
-if(lQ[n1
-eH3==false){lQ
-tS=iJ1
-l43
-eA3&found=lQ[n1
-eI3;if(iJ1
-eJ3!=found
-eJ3
-cQ
-for
-iZ1
-a=0;a<iJ1
-eJ3;++a)if(!iJ1[a]xI
-found[a])cQ
-lD2}
-void
-SaveRestHolder
-lT1
-n1,eK&iJ1){cT1
-lQ
-xF3
-n1+1);lQ
-tS.swap(iJ1);}
-bool
-SaveOrTestParamHolder
-lT1
-x0,iT1&xG3){if(cA
-eJ3<=x0){cA.xH3
-x0+1);cA
-xF3
-x0);cA
-c52
-xG3
-yQ2
-if(!cA[x0].nX2){cA[x0]=xG3
-l43
-return
-xG3
-xI
-cA[x0]cN2
-SaveMatchedParamIndex(lJ1){tT
-c52
-index);}
-iT1&GetParamHolderValueIfFound
-lT1
-x0)const{static
-iT1
-dummytree;if(cA
-eJ3<=x0)return
-dummytree
-i1
-cA[x0];}
-iT1&GetParamHolderValue
-lT1
-x0
-c01
-cA[x0];}
-bool
-HasRestHolder
-lT1
-n1
-c01
-lQ
-eJ3>n1&&lQ[n1
-eH3==true;}
-eA3&GetRestHolderValues
-lT1
-n1)const{static
-eA3
-empty_result;cT1
-return
-empty_result
-i1
-lQ[n1
-eI3;}
-const
-eO3
-x83>&GetMatchedParamIndexes(c01
-tT;}
-void
-swap(tC
-b){lQ.swap(b.lQ);cA.swap(b.cA);tT.swap(b.tT);}
-tC
-eM1=iS1
-tC
-b){lQ=b.lQ;cA=b.cA;tT=b.tT
-i1*this;}
-}
-;class
-e6;typedef
-xP<e6>cZ;class
-e6{e43
-int
-xB3;e43
-e6():xB3(0){}
-virtual~e6(){}
-}
-;e72
-n31{bool
-found;cZ
-specs;n31(bool
-f):found(f),specs(){}
-n31(bool
-f,const
-cZ&s):found(f),specs(s){}
-}
-;xL1
-SynthesizeRule(t41
-nP1
-tC
-info)yO1
-n31
-TestParam
-iS1
-eA2&yA2
-const
-nP1
-const
-cZ&start_at,tC
-info)yO1
-n31
-TestParams(eX&nN,const
-nP1
-const
-cZ&start_at,tC
-info,bool
-iX1
-yO1
-bool
-ApplyGrammar
-iS1
-Grammar&tK2,FPoptimizer_CodeTree::nP1
-bool
-from_logical_context=false);xL1
-ApplyGrammars(FPoptimizer_CodeTree::eR
-yO1
-bool
-IsLogisticallyPlausibleParamsMatch(eX¶ms,const
-eR;}
-l33
-lA1{xL1
-DumpMatch(t41
-nO,const
-FPoptimizer_Optimize::tC
-info,bool
-DidMatch,std::ostream&o=cV2);xL1
-DumpMatch(t41
-nO,const
-FPoptimizer_Optimize::tC
-info,e32
-tO3,std::ostream&o=cV2);}
-#endif
-e42
-lA1::nZ2
-yT1=false);e42
-iU1
-yT1=false);
-using
-l33
-lA1;using
-l33
-FUNCTIONPARSERTYPES;e42
-lA1::nZ2
-yT1){
-#if 1
-e32
-p=0;e23
-opcode){case
-NumConstant:p="NumConstant"
-;lC
-ParamHolder:p="ParamHolder"
-;lC
-SubFunction:p="SubFunction"
-;xY3
-std::ostringstream
-tmp;assert(p);tmp<<p;if(pad)while(tmp.str()eJ3<12)tmp<<' '
-i1
-tmp.str();
-#else
-std::ostringstream
-tmp;tmp<<opcode;if(pad)while(tmp.str()eJ3<5)tmp<<' '
-i1
-tmp.str();
-#endif
-}
-e42
-iU1
-yT1){
-#if 1
-e32
-p=0;e23
-opcode){case
-cAbs:p="cAbs"
-;lC
-cAcos:p="cAcos"
-;lC
-cAcosh:p="cAcosh"
-;lC
-cArg:p="cArg"
-;lC
-cAsin:p="cAsin"
-;lC
-cAsinh:p="cAsinh"
-;lC
-cAtan:p="cAtan"
-;lC
-cAtan2:p="cAtan2"
-;lC
-cAtanh:p="cAtanh"
-;lC
-cCbrt:p="cCbrt"
-;lC
-cCeil:p="cCeil"
-;lC
-cConj:p="cConj"
-;lC
-cCos:p="cCos"
-;lC
-cCosh:p="cCosh"
-;lC
-cCot:p="cCot"
-;lC
-cCsc:p="cCsc"
-;lC
-cExp:p="cExp"
-;lC
-cExp2:p="cExp2"
-;lC
-cFloor:p="cFloor"
-;lC
-cHypot:p="cHypot"
-;lC
-cIf:p="cIf"
-;lC
-cImag:p="cImag"
-;lC
-cInt:p="cInt"
-;lC
-cLog:p="cLog"
-;lC
-cLog2:p="cLog2"
-;lC
-cLog10:p="cLog10"
-;lC
-cMax:p="cMax"
-;lC
-cMin:p="cMin"
-;lC
-cPolar:p="cPolar"
-;lC
-cPow:p="cPow"
-;lC
-cReal:p="cReal"
-;lC
-cSec:p="cSec"
-;lC
-cSin:p="cSin"
-;lC
-cSinh:p="cSinh"
-;lC
-cSqrt:p="cSqrt"
-;lC
-cTan:p="cTan"
-;lC
-cTanh:p="cTanh"
-;lC
-cTrunc:p="cTrunc"
-;lC
-cImmed:p="cImmed"
-;lC
-cJump:p="cJump"
-;lC
-cNeg:p="cNeg"
-;lC
-cAdd:p="cAdd"
-;lC
-cSub:p="cSub"
-;lC
-cMul:p="cMul"
-;lC
-cDiv:p="cDiv"
-;lC
-cMod:p="cMod"
-;lC
-cEqual:p="cEqual"
-;lC
-i51:p="cNEqual"
-;lC
-cLess:p="cLess"
-;lC
-cLessOrEq:p="cLessOrEq"
-;lC
-cGreater:p="cGreater"
-;lC
-cGreaterOrEq:p="cGreaterOrEq"
-;lC
-cNot:p="cNot"
-;lC
-cAnd:p="cAnd"
-;lC
-cOr:p="cOr"
-;lC
-cDeg:p="cDeg"
-;lC
-cRad:p="cRad"
-;lC
-cFCall:p="cFCall"
-;lC
-cPCall:p="cPCall"
-;break;
-#ifdef FP_SUPPORT_OPTIMIZER
-case
-cFetch:p="cFetch"
-;lC
-cPopNMov:p="cPopNMov"
-;lC
-cQ3:p="cLog2by"
-;lC
-cNop:p="cNop"
-;break;
-#endif
-case
-cSinCos:p="cSinCos"
-;lC
-cSinhCosh:p="cSinhCosh"
-;lC
-cC3:p="cAbsNot"
-;lC
-cAbsNotNot:p="cAbsNotNot"
-;lC
-cAbsAnd:p="cAbsAnd"
-;lC
-cAbsOr:p="cAbsOr"
-;lC
-cAbsIf:p="cAbsIf"
-;lC
-cDup:p="cDup"
-;lC
-cInv:p="cInv"
-;lC
-cSqr:p="cSqr"
-;lC
-cRDiv:p="cRDiv"
-;lC
-cRSub:p="cRSub"
-;lC
-cNotNot:p="cNotNot"
-;lC
-cRSqrt:p="cRSqrt"
-;lC
-iU2:p="VarBegin"
-;xY3
-std::ostringstream
-tmp;assert(p);tmp<<p;if(pad)while(tmp.str()eJ3<12)tmp<<' '
-i1
-tmp.str();
-#else
-std::ostringstream
-tmp;tmp<<opcode;if(pad)while(tmp.str()eJ3<5)tmp<<' '
-i1
-tmp.str();
-#endif
-}
-#ifdef FP_SUPPORT_OPTIMIZER
-#ifndef FP_GENERATING_POWI_TABLE
-enum{MAX_POWI_BYTECODE_LENGTH=20}
-;
-#else
-enum{MAX_POWI_BYTECODE_LENGTH=999}
-;
-#endif
-enum{MAX_MULI_BYTECODE_LENGTH=3}
-;l33
-xK1{tK1
-class
-ByteCodeSynth{e43
-ByteCodeSynth():eN1(),Immed(),cI(),xQ(0),StackMax(0){eN1.xH3
-64);Immed.xH3
-8);cI.xH3
-16
-cN2
-Pull(eO3
-x83>&bc,std
-xM3
-xF&imm,size_t&StackTop_max){for
-lT1
-a=0;a<n41;++a){eN1[a]&=~0x80000000u;}
-eN1.swap(bc);Immed.swap(imm);StackTop_max=StackMax;}
-size_t
-GetByteCodeSize(c01
-n41;}
-size_t
-GetStackTop(c01
-xQ;}
-void
-PushVar
-lT1
-varno){eN1
-c52
-varno);xI3
-1
-cN2
-PushImmed
-cX3
-immed
-nL
-eN1
-c52
-cImmed);Immed
-c52
-immed);xI3
-1
-cN2
-StackTopIs(nO,int
-offset=0){if((int)xQ>offset){cI[xQ
-nK2
-first=true;cI[xQ
-nK2
-second=tree;}
-}
-bool
-IsStackTop(nO,int
-offset=0
-c01(int)xQ>offset&&cI[xQ
-nK2
-first&&cI[xQ
-nK2
-second
-xI
-tree);y81
-void
-EatNParams
-lT1
-eat_count){xQ-=eat_count;}
-void
-ProducedNParams
-lT1
-produce_count){xI3
-produce_count
-cN2
-DoPopNMov
-iZ1
-eB2,size_t
-srcpos
-nL
-eN1
-c52
-cPopNMov
-e53
-eB2
-e53
-srcpos);xM1
-srcpos+1);cI[eB2]=cI[srcpos];xM1
-eB2+1
-cN2
-DoDup
-iZ1
-xJ3
-nL
-if(xJ3==xQ-1){eN1
-c52
-cDup);}
-else{eN1
-c52
-cFetch
-e53
-xJ3);}
-xI3
-1);cI[xQ-1]=cI[xJ3];}
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-tP1
-int>void
-Dump(){std::ostream&o=cV2;o<<"Stack state now("
-<<xQ<<"):\n"
-e73
-0;a<xQ;++a){o<<a<<": "
-;if(cI[a
-eH3){nO=cI[a
-eI3;o<<'['<<std::hex<<(void*)(&tree.lJ2))<<std::dec<<','<<tree.GetRefCount()<<']'
-iL2
-tree,o);}
-else
-o<<"?"
-iV3}
-o<<std::flush;}
-#endif
-size_t
-xK3
-nO)const{for
-iZ1
-a=xQ;a-->0;)if(cI[a
-eH3&&cI[a
-eI3
-xI
-tree
-y03
-a
-i1~size_t(0);}
-bool
-Find(nO
-c01
-xK3
-tree)!=~size_t(0);}
-bool
-FindAndDup(nO){size_t
-pos=xK3
-tree);if(pos!=~size_t(0)){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iX3"duplicate at ["
-<<pos<<"]: "
-iL2
-tree
-lE2" -- issuing cDup or cFetch\n"
-;
-#endif
-DoDup(pos
-yQ2
-return
-t23
-e72
-IfData{size_t
-ofs;}
-;void
-SynthIfStep1
-c62,iU1
-op
-x21
-c72=n41;eN1
-c52
-op
-eO
-eO
-cN2
-SynthIfStep2
-c62
-x21
-eN1
-iK1
-xL3+2);eN1
-iK1
-2
-y5
-lN2
-c72=n41;eN1
-c52
-cJump
-eO
-eO
-cN2
-SynthIfStep3
-c62
-x21
-eN1.back()|=0x80000000u;eN1
-iK1
-xL3-1);eN1
-iK1
-2
-y5
-lN2
-xI3
-1
-iY1
-0;a<c72;++a){if(eN1[a]==cJump&&eN1[a+1]==(0x80000000u|(c72-1))){eN1[a+xL3-1);eN1[a+2
-y5
-lN2
-c73(eN1[a]){case
-cAbsIf:case
-cIf:case
-cJump:case
-cPopNMov:a+=2;lC
-cFCall:case
-cPCall:case
-cFetch:a+=1;break;yF3
-xY3}
-}
-protected:void
-xM1
-size_t
-value){xQ=value;if(xQ>l53{StackMax=xQ;cI
-xF3
-l53;}
-}
-protected:eO3
-x83>eN1;std
-xM3
-xF
-Immed;eO3
-std::pair<bool,FPoptimizer_CodeTree::yZ2> >cI;size_t
-xQ;size_t
-StackMax;private:void
-incStackPtr(){if(xQ+2>l53
-cI
-xF3
-StackMax=xQ+2);}
-tP1
-bool
-IsIntType,bool
-IsComplexType>e72
-c82{}
-;e43
-void
-AddOperation
-eZ2,x83
-eat_count,x83
-produce_count=1){EatNParams(eat_count);nR1(opcode);ProducedNParams(produce_count
-cN2
-nR1
-eZ2,c82<false,false>yQ
-false,true>yQ
-true,false>yQ
-true,true>);inline
-void
-nR1
-eZ2){nR1(opcode,c82<bool(nB
-IsIntType
-xF::nS3),bool(nB
-IsComplexType
-xF::nS3)>());}
-}
-yO1
-e72
-SequenceOpCode
-yO1
-e72
-tU1{static
-cG
-AddSequence;static
-cG
-MulSequence;}
-;xL1
-x01
-long
-count,cG&eQ,xI1;}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33
-xK1{tK1
-e72
-SequenceOpCode
-l14
-basevalue;x83
-op_flip;x83
-op_normal,op_normal_flip;x83
-op_inverse,op_inverse_flip;}
-yO1
-cG
-tU1
-xF::AddSequence={xH1,cNeg
-x9
-cAdd,cSub,cRSub}
-yO1
-cG
-tU1
-xF::MulSequence={e62
-1),cInv,cMul,cMul,cDiv,cRDiv}
-;
-#define findName(a,b,c) "var"
-#define TryCompilePowi(o) false
-#define mData this
-#define mByteCode eN1
-#define mImmed Immed
-nL2
-false,false>)x31
-# define FP_FLOAT_VERSION 1
-# define FP_COMPLEX_VERSION 0
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-nL2
-true,false>)x31
-# define FP_FLOAT_VERSION 0
-# define FP_COMPLEX_VERSION 0
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
-nL2
-false,true>)x31
-# define FP_FLOAT_VERSION 1
-# define FP_COMPLEX_VERSION 1
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-nL2
-true,true>)x31
-# define FP_FLOAT_VERSION 0
-# define FP_COMPLEX_VERSION 1
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-#endif
-#undef findName
-#undef mImmed
-#undef mByteCode
-#undef mData
-#undef TryCompilePowi
-}
-using
-l33
-xK1;
-#define POWI_TABLE_SIZE 256
-#define POWI_WINDOW_SIZE 3
-l33
-xK1{
-#ifndef FP_GENERATING_POWI_TABLE
-extern
-const
-x83
-char
-powi_table[POWI_TABLE_SIZE];const
-#endif
-x83
-char
-powi_table[POWI_TABLE_SIZE]={0,1,1,1,2,1,2,1,xN3
-4,1,2,xP3
-2,1,xN3
-8,cV3
-xQ3
-15,1,16,1,2,1,4,1,2,xP3
-2,1,4,cV3
-1,16,1,25,xQ3
-27,5,8,3,2,1,30,1,31,3,32,1,2,1,xN3
-8,1,2,xQ3
-39,1,16,137,2,1,4,cV3
-xP3
-45,135,4,31,2,5,32,1,2,131,50,1,51,1,8,3,2,1,54,1,55,3,16,1,57,133,4,137,2,135,60,1,61,3,62,133,63,1,iL1
-131,iL1
-139,lO2
-e7
-30,1,130,137,2,31,lO2
-e7
-e7
-130,cV3
-1,e7
-e7
-2,1,130,133,iL1
-61,130,133,62,139,130,137,e7
-lO2
-e7
-e7
-iL1
-131,e7
-e7
-130,131,2,133,lO2
-130,141,e7
-130,cV3
-1,e7
-5,135,e7
-lO2
-e7
-lO2
-130,133,130,141,130,131,e7
-e7
-2,131}
-;}
-static
-x03
-c1=256;
-#define FPO(x)
-l33{class
-PowiCache{private:int
-iM[c1];int
-iM1[c1];e43
-PowiCache():iM(),iM1(){iM[1]=1;}
-bool
-Plan_Add(c11,int
-count){cD1>=c1
-cQ
-iM1[t02+=count
-i1
-iM[t02!=0;}
-void
-l63
-c11){cD1<c1)iM[t02=1;}
-void
-Start
-iZ1
-value1_pos){for(int
-n=2;n<c1;++n)iM[n]=-1;Remember(1,value1_pos);DumpContents();}
-int
-Find(c11)const{cD1<c1){if(iM[t02>=0){FPO(iC3(iG3,"* I found %ld from cache (%u,%d)\n",value,(unsigned)cache[value],iD3 value]))i1
-iM[t02;}
-eE3-1;}
-void
-Remember(c11,size_t
-iQ3){cD1>=c1)return;FPO(iC3(iG3,"* Remembering that %ld can be found at %u (%d uses remain)\n",value,(unsigned)iQ3,iD3 value]));iM[t02=(int)iQ3;}
-void
-DumpContents()const{FPO(for(int a=1;a<POWI_CACHE_SIZE;++a)if(cache[a]>=0||iD3 a]>0){iC3(iG3,"== cache: sp=%d, val=%d, needs=%d\n",cache[a],a,iD3 a]);})}
-int
-UseGetNeeded(c11){cD1>=0&&value<c1)return--iM1[t02
-i1
-0;}
-}
-yO1
-size_t
-y6
-long
-count
-iQ1
-cG&eQ,xI1;xL1
-c21
-size_t
-apos,long
-aval,size_t
-bpos,long
-bval
-iQ1
-x83
-cumulation_opcode,x83
-cimulation_opcode_flip,xI1;void
-lB1
-c11
-iQ1
-int
-need_count,int
-lC1=0){cD1<1)return;
-#ifdef FP_GENERATING_POWI_TABLE
-if(lC1>32)throw
-false;
-#endif
-if(iM.Plan_Add(value,need_count
-y03;long
-xR3
-1;cD1<POWI_TABLE_SIZE){xR3
-powi_table[t02
-xZ3&128){half&=127
-xZ3&64)xR3-t12
-FPO(iC3(iG3,"value=%ld, half=%ld, otherhalf=%ld\n",value,half,value/half));lB1
-half
-xO3
-iM.l63
-half)i1;}
-iP1
-half&64){xR3-t12}
-}
-else
-cD1&1)xR3
-value&((1<<POWI_WINDOW_SIZE)-1);else
-xR3
-value/2;long
-cL=value-half
-xZ3>cL||half<0)std::swap(half,cL);FPO(iC3(iG3,"value=%ld, half=%ld, otherhalf=%ld\n",value,half,otherhalf))xZ3==cL){lB1
-half,iM,2,lC1+1);}
-else{lB1
-half
-xO3
-lB1
-cL>0?cL:-cL
-xO3}
-iM.l63
-value);}
-tK1
-size_t
-y6
-c11
-iQ1
-cG&eQ,xI1{int
-xT3=iM.Find(value);if(xT3>=0)yP
-xT3;}
-long
-xR3
-1;cD1<POWI_TABLE_SIZE){xR3
-powi_table[t02
-xZ3&128){half&=127
-xZ3&64)xR3-t12
-FPO(iC3(iG3,"* I want %ld, my plan is %ld * %ld\n",value,half,value/half));size_t
-xM2=y6
-half
-cE1
-if(iM
-lP2
-half)>0||xM2!=cG1){iN1
-xM2)xP2
-half,cG1);}
-x01
-value/half
-e63
-size_t
-iQ3=cG1
-xP2
-value,iQ3);iM.DumpContents()i1
-iQ3;}
-iP1
-half&64){xR3-t12}
-}
-else
-cD1&1)xR3
-value&((1<<POWI_WINDOW_SIZE)-1);else
-xR3
-value/2;long
-cL=value-half
-xZ3>cL||half<0)std::swap(half,cL);FPO(iC3(iG3,"* I want %ld, my plan is %ld + %ld\n",value,half,value-half))xZ3==cL){size_t
-xM2=y6
-half
-cE1
-c21
-xM2,half,xM2,half,iM,eQ.op_normal,eQ.op_normal_flip,c92}
-else{long
-part1=half;long
-part2=cL>0?cL:-cL;size_t
-part1_pos=y6
-part1
-cE1
-size_t
-part2_pos=y6
-part2
-cE1
-FPO(iC3(iG3,"Subdivide(%ld: %ld, %ld)\n",value,half,otherhalf));c21
-part1_pos,part1,part2_pos,part2,iM,cL>0?eQ.op_normal:eQ.op_inverse,cL>0?eQ.op_normal_flip:eQ.op_inverse_flip,c92}
-size_t
-iQ3=cG1
-xP2
-value,iQ3);iM.DumpContents()i1
-iQ3;}
-xL1
-c21
-size_t
-apos,long
-aval,size_t
-bpos,long
-bval
-iQ1
-x83
-cumulation_opcode,x83
-cumulation_opcode_flip,xI1{int
-a_needed=iM
-lP2
-aval);int
-xU3=iM
-lP2
-bval);bool
-flipped
-eW3
-#define DUP_BOTH() do{if(apos<bpos){size_t tmp=apos;apos=bpos;bpos=tmp e41 FPO(iC3(iG3,"-> " iO3 iO3"op\n",(unsigned)apos,(unsigned)bpos));iN1 apos);iN1 apos==bpos?cG1:bpos);}while(0)
-#define DUP_ONE(p) do{FPO(iC3(iG3,"-> " iO3"op\n",(unsigned)p));iN1 p);}while(0)
-if(a_needed>0){if(xU3>0){nM2}
-cJ3
-bpos!=cG1)nM2
-else{x02
-e41}
-}
-iP1
-xU3>0){if(apos!=cG1)nM2
-else
-DUP_ONE(bpos);}
-cJ3
-apos==bpos&&apos==cG1)x02;iP1
-apos==cG1&&bpos==xV3
-2){FPO(iC3(iG3,"-> op\n"))e41
-iP1
-apos==xV3
-2&&bpos==cG1)FPO(iC3(iG3,"-> op\n"));iP1
-apos==cG1)DUP_ONE(bpos);iP1
-bpos==cG1){x02
-e41
-else
-nM2}
-yB1
-flipped?cumulation_opcode_flip:cumulation_opcode,2);}
-xL1
-cH1
-long
-count,cG&eQ,xI1{while
-cW3<256){int
-xR3
-xK1::powi_table[count]xZ3&128){half&=127;cH1
-half
-e63
-count/=half;}
-else
-xY3
-if
-cW3==1)return;if(!cW3&1)){yB1
-cSqr,1);cH1
-count/2
-e63}
-else{iN1
-cG1);cH1
-count-1
-e63
-yB1
-cMul,2);}
-}
-}
-l33
-xK1{xL1
-x01
-long
-count,cG&eQ,xI1{if
-cW3==0)t71
-eQ.basevalue);else{bool
-t22
-eW3
-if
-cW3<0){t22=true;count=-count;}
-if(false)cH1
-count
-e63
-iP1
-count>1){PowiCache
-iM;lB1
-count,iM,1);size_t
-xO1=synth.GetStackTop();iM.Start(cG1);FPO(iC3(iG3,"Calculating result for %ld...\n",count));size_t
-xN2=y6
-count
-cE1
-size_t
-n_excess=xV3
-xO1;if(n_excess>0||xN2!=xO1-1){synth.DoPopNMov(xO1-1,xN2);}
-}
-if(t22)yB1
-eQ.op_flip,1);}
-}
-}
-#endif
-#ifndef FPOptimizer_ValueRangeHH
-#define FPOptimizer_ValueRangeHH
-t5{l33
-l73{l01
-e72
-Comp{}
-;tP1>e72
-Comp<nB
-cLess>l83<nA
-cLessOrEq>l83<=nA
-cGreater>l83>nA
-cGreaterOrEq>l83>=nA
-cEqual>l83==nA
-i51>l83!=b;}
-}
-;}
-tK1
-e72
-cI1
-l14
-val;bool
-known;cI1():val(),known(false){}
-cI1(tV1):val(v),known(true){y81
-l93
-tV1){known=true;val=v;}
-l93
-xW3
-Value_t),cI1
-y7)val=iE2
-l93
-xW3
-const
-Value_t&),cI1
-y7)val=iE2
-l01
-void
-set_if
-cX3
-v,xW3
-Value_t),cI1
-y7&&l73::Comp<Compare>()(val,v))val=iE2
-l01
-void
-set_if(tV1,xW3
-const
-Value_t&),cI1
-y7&&l73::Comp<Compare>()(val,v))val=iE2}
-yO1
-e72
-range{cI1
-xF
-min,max;range():min(),max(){}
-range
-cX3
-mi,Value_t
-ma):min(mi),max(ma){}
-range(bool,Value_t
-ma):min(),max(ma){}
-range
-cX3
-mi,bool):min(mi),max(){}
-void
-set_abs();void
-set_neg();}
-yO1
-bool
-IsLogicalTrueValue
-iS1
-yD3&p,bool
-abs)yO1
-bool
-IsLogicalFalseValue
-iS1
-yD3&p,bool
-abs);}
-#endif
-#ifndef FPOptimizer_RangeEstimationHH
-#define FPOptimizer_RangeEstimationHH
-t5{enum
-TriTruthValue{iF2,xX3,Unknown}
-yO1
-yD3
-CalculateResultBoundaries
-iS1
-eR
-yO1
-bool
-IsLogicalValue
-iS1
-eR
-yO1
-TriTruthValue
-GetIntegerInfo
-iS1
-eR
-yO1
-xP1
-GetEvennessInfo
-iS1
-eR{if(!tree
-tD1)return
-Unknown;yL1=tree
-x41;if(nB
-isEvenInteger(value
-y13
-nB
-isOddInteger(value
-y23
-tK1
-xP1
-GetPositivityInfo
-iS1
-eR{yD3
-p=CalculateResultBoundaries(tree);if(p
-yI&&p
-yM>=e62
-y13
-p
-e61
-l61
-y23
-tK1
-xP1
-GetLogicalValue
-iS1
-nP1
-bool
-abs){yD3
-p=CalculateResultBoundaries(tree);if(IsLogicalTrueValue(p,abs
-y13
-IsLogicalFalseValue(p,abs
-y23}
-#endif
-#ifndef FPOptimizer_ConstantFoldingHH
-#define FPOptimizer_ConstantFoldingHH
-t5{xL1
-ConstantFolding(eR;}
-#endif
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5;e72
-ComparisonSetBase{enum{eB3=0x1,Eq_Mask=0x2,Le_Mask=0x3,eC3=0x4,eD3=0x5,Ge_Mask=0x6}
-;static
-int
-Swap_Mask(int
-m)yP(m&Eq_Mask)|((m&eB3)?eC3:0)|((m&eC3)?eB3:0);}
-enum
-c31{Ok,BecomeZero,BecomeOne,n91}
-;enum
-x12{cond_or,iG2,iH2,iI2}
-;}
-yO1
-e72
-ComparisonSet:public
-ComparisonSetBase{e72
-t32{yZ2
-a
-tX
-b;int
-relationship;t32():a(),b(),relationship(){}
-}
-;eO3
-t32>tH;e72
-Item{yZ2
-value;bool
-cA2;Item():value(),cA2(false){}
-}
-;eO3
-Item>cJ1;int
-xQ1;ComparisonSet():tH(),cJ1(),xQ1(0){}
-c31
-AddItem
-iR1
-a,bool
-cA2,x12
-type){for
-iZ1
-c=0;c<cJ1
-eJ3;++c)if(cJ1[c].value
-xI
-a)){if(cA2!=cJ1[c].cA2){l11
-cU1
-case
-iI2:cJ1.erase(cJ1.begin()+c);xQ1
-cB2
-case
-iG2:case
-iH2:cW1}
-eE3
-n91;}
-Item
-pole;pole.value=a;pole.cA2=cA2;cJ1
-c52
-pole)i1
-Ok;}
-c31
-AddRelationship(yZ2
-a,yZ2
-b,int
-tY1,x12
-type){l11
-if(tY1==7)cU1
-lC
-iI2:if(tY1==7){xQ1
-cB2}
-lC
-iG2:case
-iH2:if(tY1==0)cW1
-xY3
-if(!(a.GetHash()<b.GetHash())){a.swap(b);tY1=Swap_Mask(tY1);}
-for
-iZ1
-c=0;c<tH
-eJ3;++c){if(tH[c].a
-xI
-a)&&tH[c].b
-xI
-b)){l11{int
-y33=xQ2|tY1;if(y33==7)cU1
-xQ2=y33;xY3
-case
-iG2:case
-iH2:{int
-y33=xQ2&tY1;if(y33==0)cW1
-xQ2=y33;xY3
-case
-iI2:{int
-newrel_or=xQ2|tY1;int
-xR2=xQ2&tY1;lQ2
-5&&xR2==0){xQ2=eD3
-i1
-n91;}
-lQ2
-7&&xR2==0){xQ1+=1;tH.erase(tH.begin()+c)i1
-n91;}
-lQ2
-7&&xR2==Eq_Mask){xQ2=Eq_Mask;xQ1
-cB2}
-yA1}
-eE3
-n91;}
-}
-t32
-comp;comp.a=a;comp.b=b;comp.relationship=tY1;tH
-c52
-comp)i1
-Ok;}
-}
-;nN1
-Value_t,x93
-CondType>bool
-ConstantFolding_LogicCommon(nP1
-CondType
-xF1,bool
-xS2){bool
-should_regenerate
-eW3
-ComparisonSet
-xF
-comp;x51{x93
-c8
-c31
-cY3=c8
-Ok;iT1&atree=xW
-a);e23
-atree
-nC){case
-cEqual
-lG
-Eq_Mask
-e12
-i51
-lG
-eD3
-e12
-cLess
-lG
-eB3
-e12
-cLessOrEq
-lG
-Le_Mask
-e12
-cGreater
-lG
-eC3
-e12
-cGreaterOrEq
-lG
-Ge_Mask
-e12
-cNot:cY3
-cV1
-l8
-0),true
-e12
-cNotNot:cY3
-cV1
-l8
-0),false,xF1);break;yF3
-if(xS2||IsLogicalValue(atree))cY3
-cV1,false,xF1);c73(cY3){ReplaceTreeWithZero:nU
-0)i1
-true;ReplaceTreeWithOne:nU
-1);nZ
-c8
-Ok:lC
-c8
-BecomeZero
-t7
-c8
-BecomeOne:iD
-c8
-n91:c61
-xY3}
-if(should_regenerate){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantFolding_LogicCommon: "
-cR
-#endif
-if(xS2){tree.DelParams();}
-else{for
-l41{iT1&atree=xW
-a);if(IsLogicalValue(atree))iZ);}
-}
-for
-iZ1
-a=0;a<comp.cJ1
-eJ3;++a){if(comp.cJ1[a].cA2
-lA3
-cNot);r.c7
-r.lR2
-iP1!xS2
-lA3
-cNotNot);r.c7
-r.lR2
-else
-tree.c7}
-for
-iZ1
-a=0;a<comp.tH
-eJ3;++a
-lA3
-cNop);e23
-comp.tH[a
-eE){case
-c8
-eB3:r
-iH
-cLess);lC
-c8
-Eq_Mask:r
-iH
-cEqual);lC
-c8
-eC3:r
-iH
-cGreater);lC
-c8
-Le_Mask:r
-iH
-cLessOrEq);lC
-c8
-eD3:r
-iH
-i51);lC
-c8
-Ge_Mask:r
-iH
-cGreaterOrEq
-e02
-r
-c91
-comp.tH[a].a);r
-c91
-comp.tH[a].b);r.lR2
-if(comp.xQ1!=0)tree.yA
-e62
-comp.xQ1)));
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantFolding_LogicCommon: "
-cR
-#endif
-lD2
-eE3
-t23
-yP1
-ConstantFolding_AndLogic(iM3(tree.GetOpcode()==cAnd||tree.GetOpcode()==cAbsAnd)i1
-nI
-iG2,true);}
-yP1
-ConstantFolding_OrLogic(iM3(tree.GetOpcode()==cOr||tree.GetOpcode()==cAbsOr)i1
-nI
-cond_or,true);}
-yP1
-ConstantFolding_AddLogicItems(iM3(tree.GetOpcode()==cAdd)i1
-nI
-iI2,false);}
-yP1
-ConstantFolding_MulLogicItems(iM3(tree.GetOpcode()==cMul)i1
-nI
-iH2,false);}
-}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5;e72
-CollectionSetBase{enum
-xR1{Ok,n91}
-;}
-yO1
-e72
-CollectionSet:public
-CollectionSetBase{e72
-c41{yZ2
-value
-tX
-xT2;bool
-e0;c41():value(),xT2(),e0(false){}
-c41
-iR1
-v,iT1&f):value(v),xT2(f),e0(false){}
-}
-;std::multimap<fphash_t,c41>iN;typedef
-x93
-std::multimap<fphash_t,c41>::y83
-xS1;CollectionSet():iN(){}
-xS1
-FindIdenticalValueTo
-iR1
-value){fphash_t
-hash=value.GetHash();for(xS1
-i=iN.xU2
-hash);i!=iN.cX1
-hash;++i){cD1
-xI
-i
-eC2.value
-y03
-i;eE3
-iN.end();}
-bool
-Found
-iS1
-xS1&b)yP
-b!=iN.end();}
-xR1
-AddCollectionTo
-iR1
-xT2,const
-xS1&into_which){c41&c=into_which
-eC2;if(c.e0)c.xT2
-cS
-xT2);else{yZ2
-add;add
-iH
-cAdd);add
-c91
-c.xT2);add
-cS
-xT2);c.xT2.swap(add);c.e0=true;eE3
-n91;}
-xR1
-x22
-iR1
-value,iT1&xT2){const
-fphash_t
-hash=value.GetHash();xS1
-i=iN.xU2
-hash);for(;i!=iN.cX1
-hash;++i){if(i
-eC2.value
-xI
-value
-y03
-AddCollectionTo(xT2,i);}
-iN.y43,std::make_pair(hash,c41(value,xT2)))i1
-Ok;}
-xR1
-x22
-iR1
-a)yP
-x22(a,nA1
-1)));}
-}
-yO1
-e72
-ConstantExponentCollection{typedef
-eK
-y63;typedef
-std::x71
-xV2;eO3
-xV2>data;ConstantExponentCollection():data(){}
-void
-MoveToSet_Unique
-iS1
-Value_t&eP1&eQ1){data
-c52
-std::x71(eP1()));data.back().second.swap(eQ1
-cN2
-MoveToSet_NonUnique
-iS1
-Value_t&eP1&eQ1){x93
-eO3
-xV2>::y83
-i=std::xU2
-data.iJ2
-data.end(),exponent,Compare1st());if(i!=data.cX1
-exponent){i
-eC2.y43
-eC2.end(),eQ1.iJ2
-eQ1.end());}
-else{data.y43,std::x71(exponent,eQ1));}
-}
-bool
-iA2{bool
-changed
-eW3
-std::sort(data.iJ2
-data.end(),Compare1st());redo:for
-iZ1
-a=0;a
-eR3
-a)l14
-exp_a=data[a
-eH3;lG3
-exp_a,e62
-1)))yA1
-for
-iZ1
-b=a+1;b
-eR3
-b)l14
-exp_b=data[b
-eH3
-iK2
-xW2=exp_b-exp_a;if(xW2>=fp_abs(exp_a))break
-iK2
-exp_diff_still_probable_integer=xW2*e62
-16);if(t42
-exp_diff_still_probable_integer)&&!(t42
-exp_b)&&!t42
-xW2))){y63&a_set=lS2;y63&b_set=data[b
-eI3;
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantExponentCollection iteration:\n"
-;Dump(cV2);
-#endif
-if(isEvenInteger(exp_b)&&!isEvenInteger(xW2+exp_a)nQ
-tmp2;tmp2
-iH
-cMul);tmp2
-iF1
-b_set);tmp2
-iW1
-tX
-tmp;tmp
-iH
-cAbs);tmp
-c91
-tmp2);tmp
-iW1;b_set
-xF3
-1);b_set[0
-tQ3
-tmp);}
-a_set.insert(a_set.end(),b_set.iJ2
-b_set.end());y63
-b_copy=b_set;data.erase(data.begin()+b);MoveToSet_NonUnique(xW2,b_copy);yS1
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantExponentCollection iteration:\n"
-;Dump(cV2);
-#endif
-cJ}
-}
-eE3
-changed;}
-#ifdef DEBUG_SUBSTITUTIONS
-void
-Dump(std::ostream&out){for
-iZ1
-a=0;a
-eR3
-a){out.precision(12);out<<data[a
-eH3<<": "
-;e11
-lS2
-eJ3;++b){if(b>0)out<<'*'
-iL2
-lS2[b],out);}
-out<<std::endl;}
-}
-#endif
-}
-yO1
-static
-yZ2
-x81
-yZ2&value,bool&xK
-yY3
-value
-nC){case
-cPow:{yZ2
-eD2
-value
-l8
-1);value.y91
-i1
-exponent;}
-case
-cRSqrt:value.y91;xK=true
-i1
-nA1-0.5))t83
-cInv:value.y91;xK=true
-i1
-nA1-1));yF3
-xY3
-return
-nA1
-1));}
-cB1
-void
-eR1
-eS1&mul,const
-nP1
-iT1&xT2,bool&c51
-bool&xK){for
-iZ1
-a=0;a<yC++a
-nQ
-value(xW
-a))tX
-exponent(x81
-value,xK));if(!xT2
-tD1||xT2
-x41!=e62
-1.0)nQ
-cY1;cY1
-iH
-cMul);cY1
-cS
-tU2
-cY1
-cS
-xT2);cY1
-iW1
-eX3.swap(cY1);}
-#if 0 /* FIXME: This does not work */
-cD1
-nC==cMul){if(1){bool
-exponent_is_even=exponent
-tD1&&isEvenInteger(exponent
-x41);e11
-value.eZ3{bool
-tmp=false
-tX
-val(value
-l8
-b))tX
-exp(x81
-val,tmp));if(exponent_is_even||(exp
-tD1&&isEvenInteger(exp
-x41))nQ
-cY1;cY1
-iH
-cMul);cY1
-cS
-tU2
-cY1
-c91
-exp);cY1.ConstantFolding();if(!cY1
-tD1||!isEvenInteger(cY1
-x41)){goto
-cannot_adopt_mul;}
-}
-}
-}
-eR1
-mul,value,exponent,c51
-xK);}
-else
-cannot_adopt_mul:
-#endif
-{if(mul.x22(value,exponent)==CollectionSetBase::n91)c61}
-}
-}
-yP1
-ConstantFolding_MulGrouping(eR{bool
-xK
-eW3
-bool
-should_regenerate
-eW3
-eS1
-mul;eR1
-mul
-cU3,nA1
-1)),c51
-xK);typedef
-std::pair<yZ2,eK>eT1;typedef
-std::multimap<fphash_t,eT1>cK1;cK1
-iJ;for(x93
-eS1::xS1
-j=mul.iN.y73
-j!=mul.iN.end();++j
-nQ&value=j
-eC2.value
-tX&eD2
-j
-eC2.xT2;if(j
-eC2.e0)exponent
-iW1;const
-fphash_t
-eU1=exponent.GetHash();x93
-cK1::y83
-i=iJ.xU2
-eU1);for(;i!=iJ.cX1
-eU1;++i)if(i
-eC2.first
-xI
-exponent)){if(!exponent
-tD1||!cZ1
-x41,e62
-1)))c61
-i
-eC2.second
-c52
-value);goto
-skip_b;}
-iJ.y43,std::make_pair(eU1,std::make_pair(exponent,eK
-iZ1(1),value))));skip_b:;}
-#ifdef FP_MUL_COMBINE_EXPONENTS
-ConstantExponentCollection
-xF
-e01;for(x93
-cK1::y83
-j,i=iJ.y73
-i!=iJ.end();i=j){j=i;++j;eT1&list=i
-eC2;x32.lV1
-eD2
-list.first
-x41;if(!(exponent==xG1)e01.MoveToSet_Unique(exponent,list
-iB2
-iJ.erase(i);}
-}
-if(e01.iA2)c61
-#endif
-if(should_regenerate
-nQ
-before=tree;before.lD1
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantFolding_MulGrouping: "
-iL2
-before
-lE2"\n"
-;
-#endif
-tree.DelParams();for(x93
-cK1::y83
-i=iJ.y73
-i!=iJ.end();++i){eT1&list=i
-eC2;
-#ifndef FP_MUL_COMBINE_EXPONENTS
-x32.lV1
-eD2
-list.first
-x41;if(exponent==xG1
-yA1
-if(cZ1
-nH2
-tree.AddParamsMove(list
-iB2
-yA1}
-}
-#endif
-yZ2
-mul;mul
-iH
-cMul);mul
-iF1
-list
-iB2
-mul
-iW1;if(xK&&list.first
-tD1){x32
-x41==e62
-1)/e62
-3)nQ
-cbrt;cbrt
-iH
-cCbrt);cbrt.e8
-cbrt.lT2
-cbrt);yA1
-cV
-0.5)nQ
-sqrt;sqrt
-iH
-cSqrt);sqrt.e8
-sqrt.lT2
-sqrt);yA1
-cV-0.5)nQ
-rsqrt;rsqrt
-iH
-cRSqrt);rsqrt.e8
-rsqrt.lT2
-rsqrt);yA1
-cV-1)nQ
-inv;inv
-iH
-cInv);inv.e8
-inv.lT2
-inv);yA1}
-}
-yZ2
-pow;pow
-iH
-cPow);pow.e8
-pow
-c91
-list.first);pow.lT2
-pow);}
-#ifdef FP_MUL_COMBINE_EXPONENTS
-iJ.clear(iY1
-0;a<iB
-eJ3;++a)l14
-eD2
-iB[a
-eH3;if(cZ1
-nH2
-tree.AddParamsMove(iB[a]iB2
-yA1}
-yZ2
-mul;mul
-iH
-cMul);mul
-iF1
-iB[a]iB2
-mul
-iW1
-tX
-pow;pow
-iH
-cPow);pow.e8
-pow.yA
-exponent));pow.lT2
-pow);}
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantFolding_MulGrouping: "
-cR
-#endif
-return!tree
-xI
-before);eE3
-t23
-yP1
-ConstantFolding_AddGrouping(eR{bool
-should_regenerate
-eW3
-eS1
-add;x51{if(xW
-a)nC==cMul)yA1
-if(add.x22(xW
-a))==CollectionSetBase::n91)c61}
-cY2
-lU2
-l51);size_t
-tD=0;x51{iT1&mulgroup=xW
-a);if
-eH2
-nC==cMul){e11
-cA1
-eZ3{if
-eH2
-l8
-b)tD1)yA1
-x93
-eS1::xS1
-c=add.FindIdenticalValueTo
-eH2
-l8
-b));if(add.Found(c)nQ
-tmp
-eH2
-y8
-CloneTag());tmp.i91
-b);tmp
-iW1;add.AddCollectionTo(tmp,c);c61
-goto
-done_a;}
-}
-lU2[a]=true;tD+=1;done_a:;}
-}
-if(tD>0){if(tD>1){eO3
-std::pair<yZ2,size_t> >nY;std::multimap<fphash_t,size_t>eV1;bool
-lB3
-eW3
-x51
-if(lU2[a]){e11
-xW
-a).eZ3{iT1&p=xW
-a)l8
-b);const
-fphash_t
-p_hash=p.GetHash();for(std::multimap<fphash_t,size_t>::const_iterator
-i=eV1.xU2
-p_hash);i!=eV1.cX1
-p_hash;++i){if(nY[i
-eC2
-eH3
-xI
-p)){nY[i
-eC2
-eI3+=1;lB3=true;goto
-found_mulgroup_item_dup;}
-}
-nY
-c52
-std::make_pair(p,size_t(1)));eV1.insert(std::make_pair(p_hash,nY
-eJ3-1));found_mulgroup_item_dup:;}
-}
-if(lB3
-nQ
-eE2;{size_t
-max=0
-eK3
-p=0;p<nY
-eJ3;++p)if(nY[p
-eI3<=1)nY[p
-eI3=0;else{nY[p
-eI3*=nY[p
-eH3
-nP2;if(nY[p
-eI3>max){eE2=nY[p
-eH3;max=nY[p
-eI3;}
-}
-}
-yZ2
-group_add;group_add
-iH
-cAdd);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Duplicate across some trees: "
-iL2
-eE2
-lE2" in "
-cR
-#endif
-x51
-if(lU2[a])e11
-xW
-a).eZ3
-if(eE2
-xI
-xW
-a)l8
-b))nQ
-tmp(xW
-a)y8
-CloneTag());tmp.i91
-b);tmp
-iW1;group_add
-c91
-tmp);lU2[a]eW3
-xY3
-group_add
-iW1
-tX
-group;group
-iH
-cMul);group
-c91
-eE2);group
-c91
-group_add);group
-iW1;add.x22(group);c61}
-}
-x51
-if(lU2[a]){if(add.x22(xW
-a))==CollectionSetBase::n91)c61}
-}
-if(should_regenerate){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantFolding_AddGrouping: "
-cR
-#endif
-tree.DelParams();for(x93
-eS1::xS1
-j=add.iN.y73
-j!=add.iN.end();++j
-nQ&value=j
-eC2.value
-tX&coeff=j
-eC2.xT2;if(j
-eC2.e0)coeff
-iW1;if(coeff
-tD1){lG3
-coeff
-x41,xG1)yA1
-lG3
-coeff
-x41
-nH2
-tree
-c91
-value);yA1}
-}
-yZ2
-mul;mul
-iH
-cMul);mul
-c91
-value);mul
-c91
-coeff);mul.e33
-yB
-e8}
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantFolding_AddGrouping: "
-cR
-#endif
-lD2
-eE3
-t23}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5
-yO1
-bool
-ConstantFolding_IfOperations(iM3(tree.GetOpcode()==cIf||tree.GetOpcode()==cAbsIf);for(;;){if(c93==cNot){tD2
-cIf);xW
-0).eF2
-0)c43
-xW
-1).swap(xW
-2));}
-iP1
-xW
-0)cQ1{tD2
-t03;xW
-0).eF2
-0)c43
-xW
-1).swap(xW
-2));}
-else
-yV3
-lY1
-0),t72==t03
-tN1
-tree.eF2
-1));nZ
-l03
-tree.eF2
-2));nZ
-lZ1
-if(c93==cIf||c93==cAbsIf
-nQ
-cond=xW
-0)tX
-lC3;lC3
-tE2==cIf?cNotNot:cAbsNotNot);lC3
-xX2
-1));ConstantFolding(lC3)tX
-lD3;lD3
-tE2==cIf?cNotNot:cAbsNotNot);lD3
-xX2
-2));ConstantFolding(lD3);if(lC3
-tD1||lD3
-tD1
-nQ
-eT;eT
-tE2);eT
-xX2
-1));eT
-tX3
-eT.nJ
-2));eT
-iW1
-tX
-else_tree
-tS1
-tE2)tS1
-xX2
-2))tS1.nJ
-1))tS1.nJ
-2))tS1
-cY
-cond
-nC
-xT1
-0,cond
-l8
-0)yB
-nB1
-1,eT
-yB
-nB1
-2,else_tree
-yQ2}
-if(xW
-1)nC==xW
-2)nC&&(xW
-1)nC==cIf||xW
-1)nC==t03
-nQ&x53=xW
-1)tX&leaf2=xW
-2);if(x53
-l8
-0)nN2
-0))&&x61
-1))||x53
-l8
-2)nN2
-2)))nQ
-eT;eT
-nO2;eT
-tY3
-eT
-xY2
-1));eT
-xZ2
-1));eT
-iW1
-tX
-else_tree
-tS1
-nO2
-tS1.nJ
-0))tS1
-xY2
-2))tS1
-xZ2
-2))tS1
-cY
-x53
-nC
-xT1
-0
-cB3
-0)yB
-nB1
-1,eT
-yB
-nB1
-2,else_tree
-yQ2
-if
-x61
-1))&&x53
-l8
-2)nN2
-2))nQ
-eU;eU
-nO2;eU
-c91
-xW
-0));eU
-xY2
-0));eU
-xZ2
-0));eU
-cY
-x53
-nC
-yB
-nB1
-0,eU
-xT1
-2
-cB3
-2)xT1
-1
-cB3
-1)yQ2
-if
-x61
-2))&&x53
-l8
-2)nN2
-1))nQ
-eI2;eI2
-iH
-leaf2
-nC==cIf?cNot:cC3);eI2
-xZ2
-0));eI2
-iW1
-tX
-eU;eU
-nO2;eU
-c91
-xW
-0));eU
-xY2
-0));eU
-c91
-eI2);eU
-cY
-x53
-nC
-yB
-nB1
-0,eU
-xT1
-2
-cB3
-2)xT1
-1
-cB3
-1)yQ2}
-yZ2&xV=xW
-1)tX&y4=xW
-2);if(xV
-xI
-y4)){tree.eF2
-1)yQ2
-const
-OPCODE
-op1=xV
-nC;const
-OPCODE
-op2=y4
-nC;y93
-op2){if(xV.e91
-1
-nQ
-lO
-0));y02
-0))c71()n4
-if(xV.e91
-2&&y4.e91
-2){if(xV
-l8
-0)xI
-y4
-l8
-0))nQ
-param0=xV
-l8
-0)tX
-lO
-1));y02
-1))c71
-t8
-param0)n4
-if(xV
-l8
-1)xI
-y4
-l8
-1))nQ
-param1=xV
-l8
-1)tX
-lO
-0));y02
-0))c71
-t8
-n81
-c81
-param1
-yQ2}
-y93
-yA3
-cMul
-lV2
-cAnd
-lV2
-cOr
-lV2
-cAbsAnd
-lV2
-cAbsOr
-lV2
-cMin
-lV2
-cMax){eK
-lE3;c2{for
-iZ1
-b=y4.l91
-b-->0;){if(xV
-lF3
-y4
-l8
-b))){if(lE3
-eU3){xV.t13
-lD1}
-lE3
-c52
-xV
-n93
-y4.i91
-b);xV.i91
-a
-e02}
-}
-if(!lE3
-eU3){xV
-iW1;y4
-iW1
-l7
-op1
-yB
-SetParamsMove(lE3)n4}
-}
-y93
-yA3
-cMul||(op1==cAnd&&IsLogicalValue(y4))||(op1==cOr&&IsLogicalValue(y4))){c2
-if(xV
-lF3
-y4)){xV.lD1
-xV.i91
-a);xV
-iW1
-tX
-cL1=y4;y4=tE
-op1==yA3
-cOr
-t52
-op1
-c81
-cL1)n4}
-if((op1==cAnd
-lV2
-cOr)&&op2==cNotNot
-nQ&lH3=y4
-l8
-0);c2
-if(xV
-lF3
-lH3)){xV.lD1
-xV.i91
-a);xV
-iW1
-tX
-cL1=lH3;y4=tE
-op1==cOr
-t52
-op1
-c81
-cL1)n4}
-if(op2==cAdd||op2==cMul||(op2==cAnd&&IsLogicalValue(xV))||(op2==cOr&&IsLogicalValue(xV))){for
-iZ1
-a=y4
-iY
-y4
-lF3
-xV)){y4.t13
-i91
-a);y4
-iW1
-tX
-cM1=xV;xV=tE
-op2==cAdd||op2==cOr
-t52
-op2
-c81
-cM1)n4}
-if((op2==cAnd||op2==cOr)&&op1==cNotNot
-nQ&lI3=xV
-l8
-0
-iY1
-y4
-iY
-y4
-lF3
-lI3)){y4.t13
-i91
-a);y4
-iW1
-tX
-cM1=lI3;xV=tE
-op2==cOr
-t52
-op2
-c81
-cM1)n4
-eE3
-t23}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5
-yO1
-int
-maxFPExponent()yP
-std::numeric_limits
-xF::max_exponent;}
-yP1
-x91
-Value_t
-base,Value_t
-exponent){if(base<xG1
-lD2
-lG3
-base,xG1||lJ3
-base,e62
-1))cQ
-return
-exponent>=e62
-maxFPExponent
-xF())/fp_log2(base);}
-yP1
-ConstantFolding_PowOperations(iM3(tree.GetOpcode()==cPow);nP&&xW
-1).lV1
-const_value=t33
-lR,xW
-i8);nU
-const_value)i1
-t23
-if(eI1
-lJ3
-xW
-i8
-nH2
-tree.eF2
-0)yQ2
-nP&&lJ3
-lR
-nH2
-nU
-1)i1
-t23
-nP&&xW
-1)nC==cMul){bool
-y12=false
-iK2
-lW2=lR
-tX
-mulgroup=xW
-1
-iY1
-mulgroup
-iY
-mulgroup
-l8
-a).lV1
-imm=mulgroup
-l8
-a)x41;{if(x91
-lW2,imm))break
-iK2
-lX2=t33
-lW2,imm);lG3
-lX2,xG1)break;if(!y12){y12=true;cA1
-lD1}
-lW2=lX2;cA1
-i91
-a
-e02}
-if(y12){cA1
-e33);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before pow-mul change: "
-cR
-#endif
-xW
-0).Become(eA1
-lW2));xW
-1).Become
-eH2);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After pow-mul change: "
-cR
-#endif
-}
-}
-if(eI1
-c93==cMul)l14
-lY2=xW
-i8
-iK2
-y22=1.0;bool
-y12=false
-tX&mulgroup=xW
-0
-iY1
-mulgroup
-iY
-mulgroup
-l8
-a).lV1
-imm=mulgroup
-l8
-a)x41;{if(x91
-imm,lY2))break
-iK2
-eW1=t33
-imm,lY2);lG3
-eW1,xG1)break;if(!y12){y12=true;cA1
-lD1}
-y22*=eW1;cA1
-i91
-a
-e02}
-if(y12){cA1
-e33)tX
-cZ3;cZ3
-iH
-cPow);cZ3
-iF1
-tree.lJ2));cZ3.yC2
-yB
-eL3
-cMul
-c81
-cZ3
-yB
-AddParam(eA1
-y22)yQ2}
-if(xW
-0)i12
-eI1
-xW
-0)l8
-1).lV1
-a=xW
-0)l8
-i8
-iK2
-b=xW
-i8
-iK2
-c=a*b;if(isEvenInteger(a)&&!isEvenInteger(c)nQ
-lK3;lK3
-iH
-cAbs);lK3.nJ
-0)c43
-lK3.e33
-yB
-nB1
-0,lK3);}
-else
-tree.SetParam(0,xW
-0)l8
-0)xT1
-1,eA1
-c));eE3
-t23}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5;e72
-l5{enum
-eJ2{MakeFalse=0,MakeTrue=1,t62=2,lN3=3,MakeNotNotP0=4,MakeNotNotP1=5,MakeNotP0=6,MakeNotP1=7,xJ=8}
-;enum
-lZ2{Never=0,Eq0=1,Eq1=2,yB3=3,yC3=4}
-;eJ2
-if_identical;eJ2
-n02
-4];e72{eJ2
-what:4;lZ2
-when:4;}
-l02,l12,l22,l32
-yO1
-eJ2
-Analyze
-iR1
-xC3
-eX1)const{if(a
-xI
-b
-y03
-if_identical;yD3
-tY
-a);yD3
-p1=CalculateResultBoundaries(b);if(p0
-e61&&p1
-yI){if(p0
-nL3<p1
-yM&&n02
-0]iC
-0];if(p0
-nL3<=p1
-yM&&n02
-1]iC
-1];}
-if
-cN3
-p1
-e61){if(p0
-yM>p1
-nL3&&n02
-2]iC
-2];if(p0
-yM>=p1
-nL3&&n02
-3]iC
-3];}
-if(IsLogicalValue(a)){if(l02
-nN3
-l02.when,p1
-y03
-l02.what;if(l22
-nN3
-l22.when,p1
-y03
-l22.what;}
-if(IsLogicalValue(b)){if(l12
-nN3
-l12.when,p0
-y03
-l12.what;if(l32
-nN3
-l32.when,p0
-y03
-l32.what;eE3
-xJ;}
-cB1
-bool
-TestCase(lZ2
-when,const
-yD3&p){if(!p
-yI||!p
-e61
-cQ
-e23
-when){case
-Eq0:nO3==e62
-0.0)t43==p
-yM
-t83
-Eq1:nO3==e62
-1.0)t43==p
-nL3
-t83
-yB3:nO3>xH1
-t43<=e62
-1)t83
-yC3:nO3>=xH1
-l61
-1);yF3;eE3
-t23}
-;l33
-RangeComparisonsData{static
-const
-l5
-Data[6]={{l5
-lL3
-i3
-xJ,l5::i3
-xJ
-lF1
-Eq1
-nT1
-Eq1
-nU1
-Eq0
-nV1
-Eq0}
-}
-,{l5::x42
-lM3
-xJ,l5
-lM3
-xJ
-lF1
-Eq0
-nT1
-Eq0
-nU1
-Eq1
-nV1
-Eq1}
-}
-,{l5::x42
-lM3
-t62,l5::i3
-MakeFalse
-nU1
-yB3
-nT1
-yC3
-yY,{l5
-lL3
-xJ,l5
-lM3
-i3
-lN3
-nU1
-yC3
-nT1
-yB3
-yY,{l5::x42::i3
-i3
-MakeTrue,l5::t62
-lF1
-yC3
-nV1
-yB3
-yY,{l5
-lL3
-i3
-lN3,l5::xJ,l5
-nC1
-lF1
-yB3
-nV1
-yC3
-yY}
-;}
-yP1
-ConstantFolding_Comparison(eR{using
-l33
-RangeComparisonsData;assert(tree.GetOpcode()>=cEqual&&tree.GetOpcode()<=cGreaterOrEq);e23
-Data[t72-cEqual].Analyze(xW
-0),xW
-1))){case
-l5::MakeFalse:nU
-0);nZ
-l5
-nC1:nU
-1
-nY3
-lN3:tD2
-cEqual
-nY3
-t62:tD2
-i51
-nY3
-MakeNotNotP0:tD2
-cNotNot
-yB
-i91
-1
-nY3
-MakeNotNotP1:tD2
-cNotNot
-yB
-i91
-0
-nY3
-MakeNotP0:tD2
-cNot
-yB
-i91
-1
-nY3
-MakeNotP1:tD2
-cNot
-yB
-i91
-0
-nY3
-xJ:;}
-if(xW
-1)tD1)e23
-c93){case
-cAsin:lM
-fp_sin(xW
-iP2
-cAcos:lM
-fp_cos(xW
-i8))yB
-eL3
-t72==cLess?cGreater:t72==cLessOrEq?cGreaterOrEq:t72==cGreater?cLess:t72==cGreaterOrEq?cLessOrEq:t72);nZ
-cAtan:lM
-fp_tan(xW
-iP2
-cLog:lM
-fp_exp(xW
-iP2
-cSinh:lM
-fp_asinh(xW
-iP2
-cTanh:if(fp_less(fp_abs(xW
-i8)nH2
-lM
-fp_atanh(xW
-i8))yQ2
-break;yF3
-xY3
-return
-t23}
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{
-#ifdef DEBUG_SUBSTITUTIONS
-yE
-double
-d){union{double
-d;uint_least64_t
-h
-c42
-d=d;lR1
-h
-nX1
-#ifdef FP_SUPPORT_FLOAT_TYPE
-yE
-float
-f){union{float
-f;uint_least32_t
-h
-c42
-f=f;lR1
-h
-nX1
-#endif
-#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
-yE
-long
-double
-ld){union{long
-double
-ld;e72{uint_least64_t
-a;x83
-short
-b;}
-s
-c42
-ld=ld;lR1
-s.b<<data.s.a
-nX1
-#endif
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-yE
-long
-ld){o<<"("
-<<std::hex<<ld
-nX1
-#endif
-#endif
-}
-t5{lN
-nE)){}
-lN
-const
-Value_t&i
-y8
-xD3
-nE
-i
-x52
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-lN
-Value_t&&i
-y8
-xD3
-nE
-tF2
-i)x52
-#endif
-lN
-x83
-v
-y8
-VarTag
-nE
-iU2,v
-x52
-lN
-iU1
-o
-y8
-OpcodeTag
-nE
-o
-x52
-lN
-iU1
-o,x83
-f
-y8
-FuncOpcodeTag
-nE
-o,f
-x52
-lN
-const
-eX1
-y8
-CloneTag
-nE*b.data)){}
-tK1
-yZ2::~c02(){}
-lB
-ReplaceWithImmed(tX1{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Replacing "
-iL2*this);if(IsImmed())OutFloatHex(cV2,GetImmed()lE2" with const value "
-<<i;OutFloatHex(cV2,i
-lE2"\n"
-;
-#endif
-data=new
-xK2
-xF(i);}
-tK1
-e72
-ParamComparer{iD2()iR1
-xC3
-eX1)const{if(a
-nP2!=b
-nP2)return
-a
-nP2<b
-nP2
-i1
-a.GetHash()<b.GetHash();}
-}
-;xL1
-xK2
-xF::Sort(yY3
-Opcode){case
-cAdd:case
-cMul:case
-cMin:case
-cMax:case
-cAnd:case
-cAbsAnd:case
-cOr:case
-cAbsOr:case
-cHypot:case
-cEqual:case
-i51:std::sort(iR2
-iJ2
-iR2
-end(),ParamComparer
-xF());lC
-cLess
-lY
-cGreater;}
-lC
-cLessOrEq
-lY
-cGreaterOrEq;}
-lC
-cGreater
-lY
-cLess;}
-lC
-cGreaterOrEq
-lY
-cLessOrEq;}
-break;yF3
-xY3}
-lB
-AddParam
-iR1
-param){y1
-c52
-param);}
-lB
-AddParamMove(yZ2¶m){y1
-c52
-yZ2());y1.back().swap(param);}
-lB
-SetParam
-iZ1
-which,const
-eX1)nW1
-which
-iQ2
-y1[which]=b;}
-lB
-nB1
-size_t
-which,eX1)nW1
-which
-iQ2
-y1[which
-tQ3
-b);}
-lB
-AddParams
-iS1
-nK){y1.insert(y1.end(),n12.iJ2
-n12.end());}
-lB
-AddParamsMove(nK){size_t
-endpos=y1
-eJ3,added=n12
-eJ3;y1
-xF3
-endpos+added,yZ2())eK3
-p=0;p<added;++p)y1[endpos+p
-tQ3
-n12[p]);}
-lB
-AddParamsMove(nK,size_t
-n22)nW1
-n22
-iQ2
-i91
-n22);AddParamsMove(tO1}
-lB
-SetParams
-iS1
-nK){eK
-tmp(tO1
-y1.swap(tmp);}
-lB
-SetParamsMove(nK){y1.swap(tO1
-n12.clear();}
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-lB
-SetParams(eK&&n12){SetParamsMove(tO1}
-#endif
-lB
-i91
-size_t
-index){eK&Params=y1;
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-iR2
-erase(iR2
-begin()+index);
-#else
-t63
-index].data=0
-eK3
-p=index;p+1<iS2;++p)t63
-p].data.UnsafeSetP(&*t63
-p+1
-iQ2
-t63
-iS2-1].data.UnsafeSetP(0);iR2
-resize(iS2-1);
-#endif
-}
-lB
-DelParams(){y1.clear();}
-yP1
-yZ2::IsIdenticalTo
-iS1
-eX1)const{if(&*data==&*b.data)return
-true
-i1
-data->IsIdenticalTo(*b.data);}
-yP1
-xK2
-xF::IsIdenticalTo
-iS1
-xK2
-xF&b)const{if(Hash!=b.Hash
-cQ
-if(Opcode!=b.Opcode
-cQ
-e23
-Opcode){case
-cImmed:return
-lJ3
-Value,b.Value)t83
-iU2:return
-lL2==b.lK2
-case
-cFCall:case
-cPCall:if(lL2!=b.lL2
-cQ
-break;yF3
-xY3
-if(iS2!=b.iS2
-cQ
-for
-iZ1
-a=0;a<iS2;++a){if(!iT2
-xI
-b.iT2)cQ}
-lD2}
-lB
-Become
-iS1
-eX1){if(&b!=this&&&*data!=&*b.data){DataP
-tmp=b.data;lD1
-data.swap(tmp);}
-}
-lB
-CopyOnWrite(){if(GetRefCount()>1)data=new
-xK2
-xF(*data);}
-tK1
-yZ2
-yZ2::GetUniqueRef(){if(GetRefCount()>1)return
-yZ2(*this,CloneTag())i1*this;}
-i4):yS
-cNop
-iR3),n8
-i4
-const
-xK2&b):yS
-b.Opcode
-iR3
-b.Value),lL2(b.cO1,t53
-b.Params),Hash(b.Hash),Depth(b.Depth
-eB1
-b.lM2){}
-i4
-tX1:yS
-cImmed
-iR3
-i),n8
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-i4
-xK2
-xF&&b):yS
-b.Opcode
-iR3
-tF2
-b.Value)),lL2(b.cO1,t53
-tF2
-b.Params)),Hash(b.Hash),Depth(b.Depth
-eB1
-b.lM2){}
-i4
-Value_t&&i):yS
-cImmed
-iR3
-tF2
-i)),n8
-#endif
-i4
-iU1
-o):yS
-o
-iR3),n8
-i4
-iU1
-o,x83
-f):yS
-o
-iR3),lL2(f),t53),Hash(),Depth(1
-eB1
-0){}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-l33{xL1
-tZ1
-nO,std
-c9&done,std::ostream&o){x51
-tZ1
-xW
-a),done,o);std::ostringstream
-buf
-iL2
-tree,buf);done[nJ2].insert(buf.str());}
-}
-#endif
-t5{
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-xL1
-DumpHashes(cE){std
-c9
-done;tZ1
-tree,done,o);for(std
-c9::const_iterator
-i=done.y73
-i!=done.end();++i){const
-std::set<eM3>&flist=i
-eC2;if(flist
-eJ3!=1)o<<"ERROR - HASH COLLISION?\n"
-;for(std::set<eM3>::const_iterator
-j=flist.y73
-j!=flist.end();++j){o<<'['<<std::hex<<i->first.hash1<<','<<i->first.hash2<<']'<<std::dec;o<<": "
-<<*j<<"\n"
-;}
-}
-}
-xL1
-DumpTree(cE){e32
-iF3;e23
-t72){case
-cImmed:o<<tree
-x41
-t73
-iU2:o<<"Var"
-<<(tree.GetVar()-iU2)t73
-cAdd:iF3"+"
-;lC
-cMul:iF3"*"
-;lC
-cAnd:iF3"&"
-;lC
-cOr:iF3"|"
-;lC
-cPow:iF3"^"
-;break;yF3
-iF3;o<<FP_GetOpcodeName(t72);cZ2
-cFCall||t72==cPCall)o<<':'<<tree.GetFuncNo();}
-o<<'(';if
-l51<=1&&sep2[1])o<<(sep2+1)<<' ';x51{if(a>0)o<<' '
-iL2
-xW
-a),o);if(a+1<tree.GetParamCount())o<<sep2;}
-o<<')';}
-xL1
-DumpTreeWithIndent(cE,const
-eM3&indent){o<<'['<<std::hex<<(void*)(&tree.lJ2))<<std::dec<<','<<tree.GetRefCount()<<']';o<<indent<<'_';e23
-t72){case
-cImmed:o<<"cImmed "
-<<tree
-x41;o<<'\n'
-t73
-iU2:o<<"VarBegin "
-<<(tree.GetVar()-iU2);o<<'\n'
-i1;yF3
-o<<FP_GetOpcodeName(t72);cZ2
-cFCall||t72==cPCall)o<<':'<<tree.GetFuncNo();o<<'\n';}
-x51{eM3
-ind=indent
-eK3
-p=0;p<ind
-eJ3;p+=2)if(ind[p]=='\\')ind[p]=' ';ind+=(a+1<tree.GetParamCount())?" |"
-:" \\"
-;DumpTreeWithIndent(xW
-a),o,ind);}
-o<<std::flush;}
-#endif
-}
-#endif
-using
-l33
-lA1;using
-l33
-FUNCTIONPARSERTYPES;
-l33
-lA1{x83
-ParamSpec_GetDepCode
-iS1
-eA2&b
-yY3
-b.first){case
-ParamHolder:{cM*s=(cM*)b.second
-i1
-s->depcode;}
-case
-SubFunction:{cN*s=(cN*)b.second
-i1
-s->depcode;}
-yF3
-xY3
-return
-0;}
-xL1
-DumpParam
-iS1
-eA2&yA2
-std::ostream&o){static
-const
-char
-ParamHolderNames[][2]={"%"
-,"&"
-,"x"
-,"y"
-,"z"
-,"a"
-,"b"
-,"c"
-}
-;x83
-y32
-0;e23
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1;using
-l33
-FUNCTIONPARSERTYPES;o.precision(12);o<<param.constvalue;xY3
-case
-ParamHolder:{cM&yU3
-cM*tF1;o<<ParamHolderNames[param.index];y32
-param.constraints;xY3
-case
-SubFunction:{cN&yU3
-cN*tF1;y32
-param.constraints;yF
-GroupFunction){if
-yZ3
-lG1==cNeg){o<<"-"
-;n2}
-iP1
-param.lG1==cInv){o<<"/"
-;n2}
-else{eM3
-opcode=FP_GetOpcodeName((iU1)param.lG1).substr(1
-iY1
-0;a<opcode
-eJ3;++a)opcode[a]=(char)std::toupper(opcode[a]);o<<opcode<<"( "
-;n2
-o<<" )"
-;}
-}
-else{o<<'('<<FP_GetOpcodeName((iU1)param.lG1)<<' ';yF
-PositionalParams)o<<'[';yF
-SelectedParams)o<<'{';n2
-if
-yZ3
-data.n1!=0)o<<" <"
-<<iH3.n1<<'>';yF
-PositionalParams)o<<"]"
-;yF
-SelectedParams)o<<"}"
-;o<<')';}
-xY3
-c73(ImmedConstraint_Value(constraints&ValueMask)){case
-ValueMask:lC
-Value_AnyNum:lC
-x62:o<<"@E"
-;lC
-Value_OddInt:o<<"@O"
-;lC
-i11:o<<"@I"
-;lC
-Value_NonInteger:o<<"@F"
-;lC
-eY1:o<<"@L"
-;yV3
-ImmedConstraint_Sign(constraints&SignMask)){case
-SignMask:lC
-Sign_AnySign:lC
-nD1:o<<"@P"
-;lC
-eZ1:o<<"@N"
-;yV3
-ImmedConstraint_Oneness(constraints&OnenessMask)){case
-OnenessMask:lC
-Oneness_Any:lC
-Oneness_One:o<<"@1"
-;lC
-Oneness_NotOne:o<<"@M"
-;yV3
-ImmedConstraint_Constness(constraints&ConstnessMask)){case
-ConstnessMask:lC
-i01:if(lX3.first==ParamHolder){cM&yU3
-cM*tF1;if
-yZ3
-index<2)xY3
-o<<"@C"
-;lC
-Constness_NotConst:o<<"@V"
-;lC
-Oneness_Any:xY3}
-xL1
-DumpParams
-lT1
-paramlist,x83
-count,std::ostream&o){for
-lT1
-a=0;a<count;++a){if(a>0)o<<' ';const
-eA2¶m=ParamSpec_Extract
-xF(paramlist,a);DumpParam
-xF(param,o);x83
-depcode=ParamSpec_GetDepCode(param);if(depcode!=0)o<<"@D"
-<<depcode;}
-}
-}
-using
-l33
-lA1;using
-l33
-FUNCTIONPARSERTYPES;l33{cM
-plist_p[37]={{2,0,0x0}
-nT
-0,0x4}
-nT
-nD1,0x0}
-nT
-eZ1|Constness_NotConst,0x0}
-nT
-Sign_NoIdea,0x0}
-nT
-eY1,0x0}
-,{3,Sign_NoIdea,0x0}
-,{3,0,0x0}
-,{3,eY1,0x0}
-,{3,0,0x8}
-,{3,Value_OddInt,0x0}
-,{3,Value_NonInteger,0x0}
-,{3,x62,0x0}
-,{3,nD1,0x0}
-,{0,eZ1|lV{0,lV{0,nD1|lV{0,x62|lV{0,i01,0x1}
-,{0,i11|nD1|lV{0,i21
-i01,0x1}
-,{0,i21
-lV{0,Oneness_One|lV{0,eY1|lV{1,lV{1,x62|lV{1,i21
-lV{1,i11|lV{1,nD1|lV{1,eZ1|lV{6,0,0x0}
-,{4,0,0x0}
-,{4,i11,0x0}
-,{4,lV{4,0,0x16}
-,{5,0,0x0}
-,{5,lV}
-yO1
-e72
-plist_n_container{static
-const
-ParamSpec_NumConstant
-xF
-plist_n[20];}
-yO1
-const
-ParamSpec_NumConstant
-xF
-plist_n_container
-xF::plist_n[20]={{e62-2
-i5-1
-i5-0.5
-i5-0.25
-i5
-0
-tG2
-fp_const_deg_to_rad
-xF(tG2
-fp_const_einv
-xF(tG2
-fp_const_log10inv
-xF(i5
-0.5
-tG2
-fp_const_log2
-xF(i5
-1
-tG2
-fp_const_log2inv
-xF(i5
-2
-tG2
-fp_const_log10
-xF(tG2
-fp_const_e
-xF(tG2
-fp_const_rad_to_deg
-xF(tG2-fp_const_pihalf
-xF(),xU1{xH1,xU1{fp_const_pihalf
-xF(),xU1{fp_const_pi
-xF(),xU1}
-;cN
-plist_s[517]={{{1,15,tH2
-398,tH2
-477,tH2
-15,cNeg,GroupFunction,0}
-,i01,0x1
-lR3
-15,y42
-24,y42
-465,y42
-466,y42
-498,cInv,lT
-2,327995
-x9
-l0
-2,48276
-x9
-l6
-260151
-x9
-l6
-470171
-x9
-l6
-169126
-x9
-l6
-48418
-x9
-l6
-1328
-x9
-l6
-283962
-x9
-l6
-169275
-x9
-l6
-39202
-x9
-l6
-283964
-x9
-l6
-283973
-x9
-l6
-476619
-x9
-l6
-296998
-x9
-l6
-47
-x9
-SelectedParams,0}
-,0,0x4
-nH
-161839
-x9
-l6
-25036
-x9
-l6
-35847
-x9
-l6
-60440
-x9
-l6
-30751
-x9
-l6
-270599
-x9
-l6
-60431
-x9
-l6
-259119
-x9
-l6
-183474
-x9
-l6
-332066
-x9
-l6
-7168
-x9
-l6
-197632
-x9
-l6
-291840
-x9
-l6
-283648
-x9
-l6
-238866
-x9
-l6
-239902
-x9
-l6
-31751
-x9
-l6
-244743
-x9
-l6
-384022
-x9
-SelectedParams,0}
-,0,0x4
-nH
-385262
-x9
-l6
-386086
-x9
-l6
-393254
-x9
-SelectedParams,0}
-,0,0x5
-nH
-393254
-x9
-l6
-386095
-x9
-l6
-387312
-x9
-l6
-18662
-x9
-l6
-61670
-x9
-l6
-387397
-x9
-l6
-247855
-x9
-SelectedParams,0}
-,0,0x1
-nH
-342063
-x9
-l6
-297007
-x9
-l6
-15820
-x9
-l6
-393263
-x9
-l6
-393263
-x9
-SelectedParams,0}
-,0,0x5
-nH
-161847
-x9
-l6
-258103
-x9
-l6
-249073
-x9
-l6
-249076
-x9
-iO
-0,0
-x9
-nF
-0,0
-i31
-1,45
-x9
-nF
-1,53
-x9
-nF
-1,54
-x9
-nF
-1,55
-x9
-nF
-1,56
-x9
-nF
-1,26
-x9
-nF
-1,259
-eK2
-0x16
-lR3
-253
-x9
-nF
-1,272
-i31
-1,323
-eK2
-0x16
-lR3
-0
-x9
-nF
-1,21
-x9
-nF
-1,447
-eK2
-0x4
-lR3
-449
-eK2
-0x4
-lR3
-0
-eK2
-0x4
-lR3
-0
-tJ
-2}
-,0,0x4
-lR3
-15
-x9
-nF
-1,24
-tJ
-2}
-,0,0x0
-nH
-58392
-i31
-0,0
-tJ
-1}
-,nD1,0x0
-nH
-24591
-lS3
-33807
-lS3
-48143
-lS3
-285720
-lS3
-290840
-lS3
-305152,l9
-312400,l9
-39202,l9
-121894,l9
-421926,l9
-429094,l9
-443430,l9
-317834,l9
-329098,l9
-7633,l9
-7706,l9
-7730,l9
-38,l9
-50587,l9
-406528,l9
-24583,l9
-31751,l9
-405511,l9
-321551
-iV2
-327713,l9
-322596,l9
-88361,l9
-335174,l9
-327050,l9
-493606,l9
-496678,l9
-503846,l9
-516134,l9
-7217,l9
-333875,l9
-336896,l9
-524326,l9
-509952,l9
-286727,l9
-90127,l9
-131087,l9
-296976,tQ1
-324623,l1
-0x14
-nH
-332815,l1
-0x10}
-,{{3,7340056,tQ1
-289092,l9
-92176
-iV2
-337935
-e31
-7340060
-lO3
-7340176,l9
-338959
-e31
-7340061
-iV2
-7206,l9
-x63
-l9
-357414,l9
-368678,l9
-370745,l1
-0x7}
-,{{3,7340177,l9
-39277,tQ1
-426398
-lO3
-40272286
-iV2
-490910
-lO3
-40336798
-iV2
-50600,l9
-426462
-iV2
-490974
-iV2
-370726,l1
-0x6
-nH
-371750,l1
-0x6
-nH
-428070
-e31
-40336862
-iV2
-38378,l9
-50671
-e31
-47662080,l9
-477184,l9
-568320,l9
-371727,l1
-0x7}
-,{{3,15779306,l9
-370703,l1
-0x7
-nH
-39277,l9
-39279,l1
-0x4}
-,{{3,15779238,l9
-39338,tQ1
-436262,l9
-508966,l9
-39409,tQ1
-296998,tQ1
-35847,l9
-15,tQ1
-377894,l9
-386063,l1
-0x1
-nH
-15,l9
-7192,l9
-122904,l9
-121880,l9
-30751,l9
-57,l9
-7456,l9
-15674
-e31
-67579935,l9
-39237,l9
-58768,l9
-62924,l9
-121856,l9
-15760
-e31
-64009216,l1
-0x0}
-,{{0,0,xL
-0,0,iW
-2,eC1
-2,eD1
-3,eC1
-3,eD1
-38,xL
-1,38,iW
-14,xL
-1,57,xL
-1,16,eL2
-0x0
-nH
-471103,eL2
-0x1
-lR3
-303,xL
-1,323,yH3
-0x0
-nH
-471363,eL2
-0x16
-lR3
-293,eC1
-294,eD1
-295,xL
-1,296,iW
-400,xL
-1,0,xL
-1,460,xL
-1,465,xL
-1,16,eL2
-0x1
-lR3
-57,yH3
-0x1
-lR3
-0,iW
-21,xL
-1,15,eL2
-0x0
-nH
-24591,xL
-1,24,iW
-517,yH3
-0x0
-nH
-46095,lK
-46104,lK
-15397,lK
-287789,lK
-66584,lK
-404763,lK
-62504,lK
-15409,lK
-39951,lK
-24591,lK
-33807,lK
-50200,lK
-62509,lK
-50176,lF,178176,t21
-tF3
-283648,lF,19456,lF,27648,lF,89088,lF,86016,lF,488448,lF,14342,lF,58375,lF,46147
-xX
-46151,lF,284679,lF,7183,lF,46159
-xX
-38993
-xX
-50265,lF,50249,lF,283808,lF,284835,lF,24822,lF,10240,lF,11264,lF,7170,lF,x63
-lF,17408,lF,164864,lF,237568,lF,242688,t21
-0x14
-nH
-476160,lF,25607,lF,121871,lF,50252,lF,39374,lF,50183,lF,7192,lF,121887,lF,252979,lF,46155,lF,38919,lF,50267,lF,50268,lF,50253,lF,46190,lF,50295,lF,7563,t21
-0x10
-nH
-416811,lF,416819,lF,40046,lF,46191
-xX
-415795,lF,40047
-xX
-415787,lF,39015,t21
-0x5
-nH
-39326
-xX
-39326,lF,39332,t21
-0x5
-nH
-39333
-cC2
-50590
-xX
-50590,lF,39338
-xX
-39338,lF,39335,t21
-0x5
-nH
-15786
-xX
-146858,lF,39372,lF,39379,lF,39380,lF,39390
-xX
-50654
-xX
-50654,lF,24,t21
-0x6
-nH
-62,lF,24,lF,62,t21
-0x6
-nH
-43,lF,43
-xX
-51,lF,51
-xX
-50269,lF,50176
-xX
-50270,lF,39159,lF,39183
-xX
-7168
-xX
-31744,lF,99328,lF,31746,lF,100376,lF,39409
-xX
-39411
-xX
-39411,lF,39420,lF,39420
-xX
-15,lF,39025,t21
-0x5
-nH
-39422,lF,16384,lF,62853,lF,15360,lF,15
-cC2
-16,lF,7183
-cC2
-7172
-tW2
-y71,nD1,0x0
-nH
-24591
-tW2
-lT
-2,50200
-tW2
-lT
-2,63521
-tW2
-lT
-2,62500
-tW2
-lT
-2,50453
-tW2
-lT
-2,62488
-tW2
-lT
-1,0,t93
-7,t93
-194,t93
-0,cAcos
-tA3
-cAcosh
-tA3
-cAsin
-tA3
-cAsinh
-nS
-119,cAsinh
-tA3
-cAtan
-t11
-306176,cAtan2
-t11
-x63
-cAtan2
-tA3
-cAtanh
-nS
-246,cCeil
-tA3
-cCeil
-tB3
-0,cD2
-0,cCos
-tB3
-7,cD2
-91,cD2
-92,cD2
-119,cD2
-236,cD2
-255,cD2
-214,iW2
-236,iW2
-464,iW2
-0,cCosh
-tB3
-0,iW2
-0,cExp
-nS
-7,cExp
-nS
-91,cExp
-tA3
-yI3
-7,yI3
-91,yI3
-246,cFloor
-tA3
-cFloor,lA
-0x4
-nH
-309540,cHypot
-t11
-316708,cHypot
-t11
-316724,cHypot,l0
-3,32513024,eM2
-34627584
-iL
-31493120,eM2
-89213952
-iL
-149042176
-iL
-246647808
-iL
-301234176
-iL
-494360576
-iL
-498558976
-iL
-62933520
-iL
-62933520,eM2
-62933526
-iL
-62933526,eM2
-24670208
-iL
-579378176
-iL
-573578240
-iL
-32513024
-iL
-566254592
-iL
-7900160
-iL
-588822528,cIf
-nS
-119,cInt
-nS
-246,tI2
-0,tI2
-7,tI2
-31,tI2
-194,tI2
-363,tI2
-15,cLog,lT
-1,24,cLog,lT
-1,0,cLog10
-tA3
-cLog2
-t11
-x63
-cMax
-t11
-35847,cMax
-t11
-30751,cMax
-tA3
-cMax,AnyParams,1}
-,0,0x4
-nH
-x63
-cMin
-t11
-35847,cMin
-t11
-30751,cMin
-tA3
-cMin,AnyParams,1}
-,0,0x4
-nH
-24591,cMin,lT
-1,0,x72
-7,x72
-91,x72
-92,x72
-119,x72
-149,x72
-231,cSin,lA
-0x5
-lR3
-246,x72
-255,x72
-254,x72
-0,cSin
-tB3
-273,cSin,lA
-0x1
-lR3
-214,y52
-231,tD3
-lA
-0x5
-lR3
-246,y52
-254,y52
-255,y52
-464,y52
-0,cSinh
-tB3
-0,y52
-15,cSqrt,lT
-1,0,cTan
-tA3
-cTan
-tB3
-115,cTan
-tB3
-116
-tC3
-231
-tC3
-246
-tC3
-273
-tC3
-254
-tC3
-255,cTan
-tA3
-y62
-0,cTanh
-tB3
-213,y62
-231,y62
-246,y62
-254,y62
-255,y62
-0,cTrunc
-t11
-15384,cSub,lT
-2,15384,cDiv,lT
-2,476626,cDiv,lT
-2,121913,tJ2
-x63
-lP3
-tF3
-x63
-tJ2
-31744,lP3
-0x20
-nH
-31751,lP3
-0x24
-nH
-31751,tJ2
-121913,i51
-t11
-x63
-cLess,lA
-tF3
-41984,cLess,lA
-0x4
-nH
-41984,cLess
-t11
-7,cLess
-t11
-x63
-cLessOrEq
-t11
-296182,cLessOrEq
-t11
-7168
-tV2,lA
-tF3
-41984
-tV2,lA
-0x4
-nH
-41984
-tV2
-t11
-7
-tV2
-t11
-x63
-y9
-l0
-2,296182,cGreaterOrEq
-tA3
-n32
-245,n32
-7,n32
-550,n32
-553,n32
-554,n32
-556,n32
-31,n32
-559,n32
-15,n32
-560,cNot
-t11
-7706,lT3
-x63
-lT3
-35847,lT3
-30751,lT3
-463903,lT3
-466975,cAnd,iO
-0,0,cAnd,nF
-2,x63
-e03
-7706,e03
-35847,e03
-463903,e03
-466975,e03
-30751,cOr,iO
-1,0,n42
-91,n42
-131,n42
-245,n42
-215,n42
-246,cDeg
-nS
-246,cRad
-t11
-x63
-cAbsAnd,l6
-x63
-cAbsOr,iO
-1,0,cC3
-tA3
-cAbsNotNot,l0
-3,32513024,yT3
-lA
-0x0}
-,}
-;}
-l33
-lA1{const
-Rule
-grammar_rules[262]={{ProduceNewTree,17,1,0,{1,0,cAbs,eN2
-409,{1,146,cAtan,eN2
-403
-nT
-1324,cAtan2,eN2
-405
-nT
-307201,cAtan2
-eL
-253174
-nT
-255224,cAtan2
-eL
-259324
-nT
-257274,cAtan2,eN2
-152,{1,252,cCeil
-i7
-486,{1,68
-yH2
-482,{1,122
-yH2
-483,{1,124
-yH2
-151,{1,125
-yH2
-419,{1,123
-yH2
-0,{1,403,cCos,l2
-2,1,246,{1,252,cCos,l2
-18,1,0,{1,400
-yH2
-301,{1,406,cCosh,l2
-2,1,246,{1,252,cCosh,l2
-18,1,0,{1,400,cCosh
-i7
-458,{1,121,cFloor,eN2
-150,{1,252,cFloor,tG3
-156,{3,7382016,eF
-549,{3,8430592,eF
-556,{3,8436736,eF
-157,{3,42998784,eF
-550,{3,42999808,eF
-562,{3,43039744,eF
-557,{3,49291264,eF
-538,{3,49325056,eF
-469,{3,1058318,eF
-473,{3,1058324,eF
-473,{3,9438734,eF
-469,{3,9438740,cIf,l2
-0,3,32542225,{3,36732434,cIf,l2
-0,3,32542231,{3,36732440,cIf,yR3
-573,{3,32513026,cIf,yR3
-515,{3,455505423,cIf,yR3
-515,{3,433506837,cIf
-i7
-78,{1,256,cLog
-i7
-69,{1,258,cLog
-i7
-404,{1,72,cLog
-i7
-159,{1,147,cLog,l2
-0,1,0
-nT
-487425,cMax
-l3
-16,1,445
-nT
-yJ3
-cMax
-l3
-0,1,0
-nT
-483329,cMin
-l3
-16,1,446
-nT
-yJ3
-cMin,c3
-0,1,153
-nT
-24832
-tW2
-tG3
-153
-nT
-25854
-tW2
-tG3
-154
-nT
-129039
-tW2
-xV1
-32055
-tW2
-xV1
-32056
-tW2
-xV1
-32057
-tW2
-l2
-0,2,166288
-nT
-32137
-tW2
-xV1
-33082
-tW2
-l2
-0,2,7168
-nT
-12688
-tW2
-l2
-0,2,7434
-nT
-12553,tX2
-435
-nT
-46146,tX2
-436
-nT
-46154,tX2
-437
-nT
-46150,tX2
-169
-nT
-83983,tX2
-168
-nT
-130082,tX2
-175
-nT
-133154
-tW2
-tI3
-476160
-nT
-471055
-tW2
-tI3
-274432
-nT
-273423
-tW2
-tI3
-251904
-nT
-266274
-tW2
-tI3
-251904
-nT
-263186,tX2
-171,{1,252,cE2
-421,{1,68,cE2
-151,{1,122,cE2
-419,{1,124,cE2
-170,{1,125,cE2
-482,{1,123,cE2
-0,{1,405,cE2
-172,{1,252,cSinh
-i7
-328,{1,404,cSinh
-i7
-173,{1,252,tJ3
-0,{1,408,tJ3
-176,{1,410,tJ3
-177,{1,252,cTanh,l2
-0,1,442
-nT
-449551,i6
-1,441
-nT
-yJ3
-i6
-1,167
-nT
-268549,i6
-1,181
-nT
-276749,i6
-1,180
-nT
-276500,i6
-2,190770
-nT
-189622,i6
-2,194748
-nT
-193723,i6
-2,202943
-nT
-196795,i6
-2,59699
-nT
-298148,i6
-2,59714
-nT
-325815,i6
-2,59724
-nT
-343224
-x9
-c3
-2,1,337,{1,333
-tJ
-1
-tF
-336,{1,338
-tJ
-1}
-}
-,{ReplaceParams,2,1,340
-nT
-1363
-nR
-342
-nT
-1365
-nR
-463
-nT
-472524
-nR
-47
-nT
-356711
-nR
-349
-nT
-200751
-nR
-360
-nT
-199727
-nR
-480
-nT
-207053
-nR
-481
-nT
-208077
-nR
-417
-nT
-211144
-nR
-209
-nT
-211145
-nR
-418
-nT
-215240
-nR
-212
-nT
-212329
-nR
-204
-nT
-373097
-nR
-211
-nT
-372944
-nR
-217
-nT
-201944
-nR
-221
-nT
-223448
-nR
-367
-nT
-508329
-nR
-219
-nT
-508126
-nR
-224
-nT
-225705
-nR
-223
-nT
-225776
-nR
-365
-nT
-230825
-nR
-426
-nT
-377057
-nR
-497
-nT
-377054
-nR
-497
-nT
-204201
-nR
-426
-nT
-375280
-nR
-224
-nT
-375006,cAdd
-l3
-2,2,407781
-nT
-233698,cAdd
-l3
-2,2,59763
-nT
-233842,i6
-1,372
-nT
-1397,lW1
-95
-nT
-24705,lW1
-96
-nT
-24708,lW1
-444
-nT
-449551,lW1
-443
-nT
-yJ3
-lW1
-100
-nT
-101750,lW1
-108
-nT
-106821,lW1
-105
-nT
-103749
-lU3
-0,2,110607
-nT
-108869
-lU3
-0,2,107535
-nT
-109893,lJ
-0
-tF
-112
-nT
-111634,cMul,SelectedParams,0
-tF
-567,{1,52,lJ
-1
-tF
-568,{1,42,lJ
-1}
-}
-,{ReplaceParams,2,1,467
-nT
-45516
-xA
-356
-nT
-51555
-xA
-468
-nT
-49612
-xA
-357
-nT
-47459
-xA
-429
-nT
-438699
-xA
-432
-nT
-441774
-xA
-486
-nT
-498726
-xA
-494
-nT
-504870
-xA
-382
-nT
-435579
-xA
-497
-nT
-435709
-xA
-426
-nT
-508287
-xA
-414
-nT
-500092
-xA
-499
-nT
-352744
-xA
-345
-nT
-367092
-xA
-381
-nT
-425318
-xA
-478
-nT
-425460
-xA
-47
-nT
-512501
-xA
-505
-nT
-355817
-xA
-47
-nT
-516598
-xA
-507
-nT
-518182
-xA
-508
-nT
-358896
-xA
-351
-nT
-388605
-xA
-511
-nT
-360939
-xA
-503
-nT
-354788
-xA
-514
-nT
-525350
-xA
-510
-nT
-394342
-xA
-386
-nT
-351346
-lU3
-2,2,363004
-nT
-361968
-lU3
-16,1,117
-nT
-1157
-lU3
-16,1,118
-nT
-1158
-lU3
-16,1,402
-nT
-411024
-lU3
-16,2,58768
-nT
-1472
-lU3
-16,2,15760
-nT
-1474
-lU3
-17,1,0,{1,400
-lU3
-17,1,57,{1,14,lJ
-0}
-}
-,{ProduceNewTree,4,1,538
-nT
-41,lQ3
-yK3
-0
-nT
-5167,lQ3
-cH
-41984
-e22
-lQ3
-cH
-tU
-lQ3
-cH
-eV
-lQ3
-cH
-eW
-cEqual
-cN1
-24849,cEqual
-eL
-tV
-cEqual
-eL
-n52
-281873,cEqual
-eL
-iP
-cEqual
-eL
-lH1
-lQ3
-yK3
-562
-nT
-41,i51,yK3
-538
-nT
-5167,i51,cH
-41984
-e22
-i51,cH
-tU
-i51,cH
-eV
-i51,cH
-eW
-i51
-cN1
-24849,i51
-eL
-tV
-i51
-eL
-n52
-281873,i51
-eL
-iP
-i51
-eL
-lH1
-i51,cH
-tU
-yN3
-eV
-yN3
-eW
-cLess,eN2
-571
-nT
-46080,cLess
-cN1
-24832,cLess
-eL
-xW1
-cLess
-eL
-tV
-cLess
-eL
-n52
-tK3
-cLess
-eL
-nY1
-cLess
-eL
-iP
-cLess
-eL
-lH1
-cLess,yL3
-562
-e22
-yN3
-tU
-n62
-cH
-eV
-n62
-cH
-eW
-n62
-eN2
-565
-nT
-409615,cLessOrEq
-cN1
-24832,cLessOrEq
-eL
-xW1
-cLessOrEq
-eL
-tV
-cLessOrEq
-eL
-n52
-tK3
-cLessOrEq
-eL
-nY1
-cLessOrEq
-eL
-iP
-cLessOrEq
-eL
-lH1
-n62
-yL3
-562
-nT
-409647,n62
-cH
-tU
-cF2
-eV
-cF2
-eW
-cGreater,eN2
-539
-nT
-409615
-tV2
-cN1
-24832
-tV2
-eL
-xW1
-cGreater
-eL
-tV
-cGreater
-eL
-n52
-281856
-tV2
-eL
-nY1
-cGreater
-eL
-iP
-cGreater
-eL
-lH1
-cGreater,yL3
-538
-nT
-409647,cF2
-tU
-y9
-cH
-eV
-y9
-cH
-eW
-y9
-eN2
-572
-nT
-46080,y9
-nQ2
-529654
-nT
-24832,y9
-nQ2
-xW1
-y9
-nQ2
-tV
-y9
-nQ2
-n52
-tK3
-y9
-nQ2
-nY1
-y9
-nQ2
-iP
-y9
-nQ2
-lH1
-y9
-yL3
-538
-e22
-y9
-yK3
-519,{1,137,cNot,yR3
-571,{1,2,cNot,l2
-0,1,452
-nT
-yJ3
-lV3
-0,2,537097,{3,547892744,cAnd,c3
-16,1,566,{1,5,cAnd,AnyParams,1}
-}
-,{ReplaceParams,16,1,569
-nT
-13314,lV3
-16,1,544
-nT
-553498,lV3
-16,1,546
-nT
-462369,lV3
-16,1,548
-nT
-466465,lV3
-0,1,457
-nT
-yJ3
-xX1
-570
-nT
-13314,xX1
-563
-nT
-8197,xX1
-541
-nT
-553498,xX1
-542
-nT
-462369,xX1
-543
-nT
-466465,xX1
-564
-nT
-143365,cOr,c3
-4,1,525,{1,137,yS3
-yR3
-572,{1,2,yS3
-l4
-17,1,0,{1,0,yS3
-eN2
-537,{1,256,cAbsNotNot,c3
-18,1,531,{1,254,cAbsNotNot,c3
-0,1,572,{3,43039744,yT3
-tG3
-571,{3,49325056,yT3
-yR3
-454,{3,32513586,yT3
-l2
-16,3,32542225,{3,36732434,yT3
-y71}
-,}
-;e72
-grammar_optimize_abslogical_type{y3
-9
-cT
-grammar_optimize_abslogical_type
-grammar_optimize_abslogical={9,{34,192,228,238,242,247,254,260,261}
-}
-;}
-e72
-grammar_optimize_ignore_if_sideeffects_type{y3
-59
-cT
-grammar_optimize_ignore_if_sideeffects_type
-grammar_optimize_ignore_if_sideeffects={59,{0,20,21,22,23,24,25,26,cO
-l42
-78,cP
-cU
-e72
-grammar_optimize_nonshortcut_logical_evaluation_type{y3
-56
-cT
-grammar_optimize_nonshortcut_logical_evaluation_type
-grammar_optimize_nonshortcut_logical_evaluation={56,{0,25,cO
-l42
-78,cP
-241,243,244,245,246,248,249,250,251,252,253,255,256,257,258,259}
-}
-;}
-e72
-grammar_optimize_recreate_type{y3
-22
-cT
-grammar_optimize_recreate_type
-grammar_optimize_recreate={22,{18,55,56,57,80,81,82,83,84,85,117,118,120,121,130,131,132,133,134,135,136,137}
-}
-;}
-e72
-grammar_optimize_round1_type{y3
-125
-cT
-grammar_optimize_round1_type
-grammar_optimize_round1={125,{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,19,25,cO
-37,38,l42
-45,46,47,48,49,50,51,52,53,54,58,59,60,61,62,63,64,65,66,67,68,69,70,71,78,79,80,81,82,83,84,85,86,87,88,93,94,95,96,97,98,99,100,101,117,118,119,120,121,122,123,124,125,126,127,128,129,138,160,161,162,163,164,165,166,167,168,169,178,179,180,200,204,212,216,224,236,237,239,240,cU
-e72
-grammar_optimize_round2_type{y3
-103
-cT
-grammar_optimize_round2_type
-grammar_optimize_round2={103,{0,15,16,17,25,cO
-39,40,l42
-45,46,47,48,49,50,51,52,53,54,59,60,72,73,78,79,86,87,88,89,90,91,92,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,119,122,123,124,125,126,127,128,139,159,160,161,162,163,164,165,166,167,168,169,178,179,180,200,204,212,216,224,236,237,239,240,cU
-e72
-grammar_optimize_round3_type{y3
-79
-cT
-grammar_optimize_round3_type
-grammar_optimize_round3={79,{74,75,76,77,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,170,171,172,173,174,175,176,177,181,182,183,184,185,186,187,188,189,190,191,193,194,195,196,197,198,199,201,202,203,205,206,207,208,209,210,211,213,214,215,217,218,219,220,221,222,223,225,226,227,229,230,231,232,233,234,235}
-}
-;}
-e72
-grammar_optimize_round4_type{y3
-12
-cT
-grammar_optimize_round4_type
-grammar_optimize_round4={12,{18,55,56,57,130,131,132,133,134,135,136,137}
-}
-;}
-e72
-grammar_optimize_shortcut_logical_evaluation_type{y3
-53
-cT
-grammar_optimize_shortcut_logical_evaluation_type
-grammar_optimize_shortcut_logical_evaluation={53,{0,25,cO
-l42
-78,cP
-cU}
-l33
-lA1{tK1
-eA2
-ParamSpec_Extract
-lT1
-paramlist,lJ1){index=(paramlist>>(index*10))&1023;if(index>=57)return
-eA2(SubFunction,cG2
-plist_s[index-57]);if(index>=37)return
-eA2(NumConstant,cG2
-plist_n_container
-xF::plist_n[index-37])i1
-eA2(ParamHolder,cG2
-plist_p[index]);}
-}
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <stdio.h>
-#include <algorithm>
-#include <map>
-#include <sstream>
-using
-l33
-FUNCTIONPARSERTYPES;using
-l33
-lA1;using
-t5;using
-nG1;l33{nN1
-It,x93
-T,x93
-Comp>t31
-MyEqualRange(It
-first,It
-last,const
-T&val,Comp
-comp){size_t
-len=last-first;while(len>0){size_t
-xR3
-len/2;It
-x23(first);x23+=half;if(comp(*x23,val)){first=x23;++first;len=len-half-1;}
-iP1
-comp(val,*x23)){len=half;}
-else{It
-left(first);{It&eO2=left;It
-last2(x23);size_t
-len2=last2-eO2;while(len2>0){size_t
-half2=len2/2;It
-eN3(eO2);eN3+=half2;if(comp(*eN3,val)){eO2=eN3;++eO2;len2=len2-half2-1;}
-else
-len2=half2;}
-}
-first+=len;It
-right(++x23);{It&eO2=right;It&last2=first;size_t
-len2=last2-eO2;while(len2>0){size_t
-half2=len2/2;It
-eN3(eO2);eN3+=half2;if(comp(val,*eN3))len2=half2;else{eO2=eN3;++eO2;len2=len2-half2-1;}
-}
-eE3
-t31(left,right);}
-eE3
-t31(first,first);}
-tK1
-e72
-OpcodeRuleCompare{iD2()iS1
-nP1
-x83
-y72)const{const
-Rule&rule=grammar_rules[y72]i1
-t72<rule
-yR2.subfunc_opcode;}
-iD2()lT1
-y72,const
-eR
-const{const
-Rule&rule=grammar_rules[y72]i1
-rule
-yR2.subfunc_opcode<t72;}
-}
-yO1
-bool
-TestRuleAndApplyIfMatch(t41
-nP1
-bool
-c4{MatchInfo
-xF
-info;n31
-found(false,cZ());if((rule.lI1
-LogicalContextOnly)&&!c4{tR1
-if(nB
-IsIntType
-xF::nS3){if(rule.lI1
-NotForIntegers)tR1
-cJ3
-rule.lI1
-OnlyForIntegers)tR1
-if(nB
-IsComplexType
-xF::nS3){if(rule.lI1
-NotForComplex)tR1
-cJ3
-rule.lI1
-OnlyForComplex)tR1
-for(;;){
-#ifdef DEBUG_SUBSTITUTIONS
-#endif
-found=TestParams(rule
-yR2
-cU3,found.specs,info,true);if(found.found)break;if(!&*found.specs){fail:;
-#ifdef DEBUG_SUBSTITUTIONS
-DumpMatch
-yG2,false);
-#endif
-return
-t23}
-#ifdef DEBUG_SUBSTITUTIONS
-DumpMatch
-yG2,true);
-#endif
-SynthesizeRule
-yG2
-yQ2}
-nG1{yP1
-ApplyGrammar
-iS1
-Grammar&tK2,nP1
-bool
-c4{if(tree.GetOptimizedUsing()==&tK2){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Already optimized: "
-iL2
-tree
-lE2"\n"
-<<std::flush;
-#endif
-return
-t23
-if(true){bool
-changed
-eW3
-e23
-t72){case
-cNot:case
-cNotNot:case
-cAnd:case
-cOr:for
-iZ1
-a=0
-tV3
-true))yS1
-lC
-cIf:case
-cAbsIf:if(ApplyGrammar(tK2,xW
-0),t72==cIf))yS1
-for
-iZ1
-a=1
-tV3
-c4)yS1
-break;yF3
-for
-iZ1
-a=0
-tV3
-false))yS1}
-if(changed){tree.Mark_Incompletely_Hashed(yQ2}
-typedef
-const
-x83
-short*lW3;std::pair<lW3,lW3>range=MyEqualRange(tK2.rule_list,tK2.rule_list+tK2.rule_count
-cU3,OpcodeRuleCompare
-xF());eO3
-x83
-short>rules;rules.xH3
-range.second-range.first);for
-y0
-if(IsLogisticallyPlausibleParamsMatch(tM1
-yR2
-cU3))rules
-c52*r);}
-range.first=!rules
-eU3?&rules[0]:0;range.second=!rules
-eU3?&rules[rules
-eJ3-1]+1:0;if(range.first!=range.second){
-#ifdef DEBUG_SUBSTITUTIONS
-if(range.first!=range.second)cH2"Input ("
-<<FP_GetOpcodeName(t72)<<")["
-<<tree.GetParamCount()<<"]"
-;if(c4
-cV2<<"(Logical)"
-;x83
-first=l52,prev=l52;e32
-sep=", rules "
-;for
-y0
-if(first==l52)first=prev=*r;iP1*r==prev+1)prev=*r;else
-cH2
-sep<<first;sep=","
-;if(prev!=first)cV2<<'-'<<prev;first=prev=*r;}
-}
-if(first!=l52)cH2
-sep<<first;if(prev!=first)cV2<<'-'<<prev;}
-cV2<<": "
-iL2
-tree
-lE2"\n"
-<<std::flush;}
-#endif
-bool
-changed
-eW3
-for
-y0
-#ifndef DEBUG_SUBSTITUTIONS
-if(!IsLogisticallyPlausibleParamsMatch(tM1
-yR2
-cU3))yA1
-#endif
-if(TestRuleAndApplyIfMatch(tM1
-cU3,c4){yS1
-xY3}
-if(changed){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Changed."
-<<std::endl;cV2<<"Output: "
-iL2
-tree
-lE2"\n"
-<<std::flush;
-#endif
-tree.Mark_Incompletely_Hashed(yQ2}
-tree.SetOptimizedUsing(&tK2)i1
-t23
-yP1
-ApplyGrammar
-iS1
-void*p,FPoptimizer_CodeTree::eR
-yP
-ApplyGrammar(*iS1
-Grammar*)p
-cU3);}
-xL1
-ApplyGrammars(FPoptimizer_CodeTree::eR{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round1\n"
-;
-#endif
-n6
-grammar_optimize_round1
-cU3
-nW
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round2\n"
-;
-#endif
-n6
-grammar_optimize_round2
-cU3
-nW
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round3\n"
-;
-#endif
-n6
-grammar_optimize_round3
-cU3
-nW
-#ifndef FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_nonshortcut_logical_evaluation\n"
-;
-#endif
-n6
-grammar_optimize_nonshortcut_logical_evaluation
-cU3
-nW
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round4\n"
-;
-#endif
-n6
-grammar_optimize_round4
-cU3
-nW
-#ifdef FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_shortcut_logical_evaluation\n"
-;
-#endif
-n6
-grammar_optimize_shortcut_logical_evaluation
-cU3
-nW
-#endif
-#ifdef FP_ENABLE_IGNORE_IF_SIDEEFFECTS
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_ignore_if_sideeffects\n"
-;
-#endif
-n6
-grammar_optimize_ignore_if_sideeffects
-cU3
-nW
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_abslogical\n"
-;
-#endif
-n6
-grammar_optimize_abslogical
-cU3
-nW
-#undef C
-}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <algorithm>
-#include <assert.h>
-#include <cstring>
-#include <cmath>
-#include <memory> /* for auto_ptr */
-using
-l33
-FUNCTIONPARSERTYPES;using
-l33
-lA1;using
-t5;using
-nG1;l33{yP1
-TestImmedConstraints
-lT1
-bitmask,const
-eR{e23
-bitmask&ValueMask){case
-Value_AnyNum:case
-ValueMask:lC
-x62:if(GetEvennessInfo
-iS3
-n72
-Value_OddInt:if(GetEvennessInfo
-iS3
-x82
-i11:if(GetIntegerInfo
-iS3
-n72
-Value_NonInteger:if(GetIntegerInfo
-iS3
-x82
-eY1:if(!IsLogicalValue(tree)cQ
-nE1
-SignMask){case
-Sign_AnySign:lC
-nD1:if(l81
-n72
-eZ1:if(l81
-x82
-Sign_NoIdea:if(l81
-Unknown
-cQ
-nE1
-OnenessMask){case
-Oneness_Any:case
-OnenessMask:lC
-Oneness_One:if(!xY1
-if(!lJ3
-fp_abs(tree
-x41),e62
-1))cQ
-lC
-Oneness_NotOne:if(!xY1
-lG3
-fp_abs(tree
-x41),e62
-1))cQ
-nE1
-ConstnessMask){case
-Constness_Any:lC
-i01:if(!xY1
-lC
-Constness_NotConst:if(xY1
-xY3
-lD2}
-tP1
-x83
-extent,x83
-nbits,x93
-eP2=x83
-int>e72
-nbitmap{private:static
-const
-x83
-bits_in_char=8;static
-const
-x83
-eQ2=(sizeof(eP2)*bits_in_char)/nbits;eP2
-data[(extent+eQ2-1)/eQ2];e43
-void
-inc(lJ1,int
-by=1){data[pos(index)]+=by*eP2(1<<y82);y81
-void
-dec(lJ1){inc(index,-1);}
-int
-get(lJ1
-c01(data[pos(index)]>>y82)&mask()iT3
-pos(lJ1)yP
-index/eQ2
-iT3
-shift(lJ1)yP
-nbits*(index%eQ2)iT3
-mask()yP(1<<nbits)-1
-iT3
-mask(lJ1)yP
-mask()<<y82;}
-}
-;e72
-Needs{int
-SubTrees:8;int
-Others:8;int
-l62:8;int
-Immeds:8;nbitmap<iU2,2>SubTreesDetail;Needs(){std::memset(this,0,sizeof(*this));}
-Needs
-iS1
-Needs&b){std::memcpy(this,&b,sizeof(b));}
-Needs&eM1=iS1
-Needs&b){std::memcpy(this,&b,sizeof(b))i1*this;}
-}
-yO1
-Needs
-CreateNeedList_uncached(eX&tL2{Needs
-yQ1;for
-lT1
-a=0;a<params
-y92;++a){const
-eA2&lX3=ParamSpec_Extract
-xF(params.param_list,a);e23
-lX3.first){case
-SubFunction:{cN&yU3
-cN*tF1;yF
-GroupFunction)++yQ1.Immeds;else{++iO2;assert(iH3.subfunc_opcode<VarBegin);yQ1.SubTreesDetail.inc
-yZ3
-lG1);}
-++yQ1.l62;xY3
-case
-NumConstant:case
-ParamHolder:++iN2;++yQ1.l62;xY3
-eE3
-yQ1;}
-tK1
-Needs&CreateNeedList(eX&tL2{typedef
-std::map<eX*,Needs>eE1;static
-eE1
-yV1;eE1::y83
-i=yV1.xU2&tL2;if(i!=yV1.cX1&tL2
-return
-i
-eC2
-i1
-yV1.y43,std::make_pair(¶ms,CreateNeedList_uncached
-xF(tL2))eC2;}
-tK1
-yZ2
-CalculateGroupFunction
-iS1
-eA2&yA2
-const
-tC
-info
-yY3
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1
-i1
-CodeTreeImmed
-yZ3
-constvalue);}
-case
-ParamHolder:{cM&yU3
-cM*tF1
-i1
-info.GetParamHolderValueIfFound
-yZ3
-index);}
-case
-SubFunction:{cN&yU3
-cN*tF1
-tX
-nS3;nS3
-iH
-param.lG1);nS3.lJ2).xH3
-iH3
-y92);for
-lT1
-a=0;a<iH3
-y92;++a
-nQ
-tmp(CalculateGroupFunction
-nF1
-iH3.param_list,a),info));nS3
-c91
-tmp);}
-nS3
-iW1
-i1
-nS3;}
-eE3
-yZ2();}
-}
-nG1{yP1
-IsLogisticallyPlausibleParamsMatch(eX¶ms,const
-eR{Needs
-yQ1(CreateNeedList
-xF(tL2);size_t
-tL3=yC
-if(tL3<size_t(yQ1.l62))tM2
-for
-iZ1
-a=0;a<tL3;++a){x83
-opcode=xW
-a)nC;e23
-opcode){case
-cImmed:if(yQ1.Immeds>0)--yQ1.Immeds;else--iN2;lC
-iU2:case
-cFCall:case
-cPCall:--iN2;break;yF3
-assert(opcode<VarBegin);if(iO2>0&&yQ1.SubTreesDetail.get(opcode)>0){--iO2;yQ1.SubTreesDetail.dec(opcode);}
-else--iN2;}
-}
-if(yQ1.Immeds>0||iO2>0||iN2>0)tM2
-if(params.match_type!=AnyParams){if(0||iO2<0||iN2<0)tM2}
-lD2}
-tK1
-n31
-TestParam
-iS1
-eA2&yA2
-const
-nP1
-const
-cZ&start_at,tC
-info
-yY3
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1;if(!xY1
-Value_t
-imm=tree
-x41;switch
-yZ3
-modulo){case
-Modulo_None:lC
-Modulo_Radians:imm=cK3
-imm,yK
-imm<xG1
-imm
-yN
-if(imm>fp_const_pi
-xF())imm-=fp_const_twopi
-xF(e02
-return
-lJ3
-imm,param.constvalue);}
-case
-ParamHolder:{cM&yU3
-cM*tF1;if(!x3
-return
-info.SaveOrTestParamHolder
-yZ3
-index
-cU3);}
-case
-SubFunction:{cN&yU3
-cN*tF1;yF
-GroupFunction){if(!x3
-yZ2
-xZ1=CalculateGroupFunction(yA2
-info);
-#ifdef DEBUG_SUBSTITUTIONS
-DumpHashes(xZ1
-lE2*iS1
-void**)&xZ1
-x41;cV2<<"\n"
-;cV2<<*iS1
-void**)&tree
-x41;cV2<<"\n"
-;DumpHashes(tree
-lE2"Comparing "
-iL2
-xZ1
-lE2" and "
-iL2
-tree
-lE2": "
-;cV2<<(xZ1
-xI
-tree)?"true"
-:"false"
-lE2"\n"
-;
-#endif
-return
-xZ1
-xI
-tree);}
-cJ3!eK1){if(!x3
-if(t72!=param.lG1
-cQ
-eE3
-TestParams
-yZ3
-data
-cU3,start_at,info,false);}
-}
-eE3
-t23
-tK1
-e72
-l31
-x92
-MatchInfo
-xF
-info;l31():start_at(),info(){}
-}
-yO1
-class
-MatchPositionSpec_PositionalParams:nQ1
-l31
-xF>{e43
-iX2
-MatchPositionSpec_PositionalParams
-iZ1
-n):eF1
-l31
-xF>(n){}
-}
-;e72
-l72
-x92
-l72():start_at(){}
-}
-;class
-yG:nQ1
-l72>{e43
-x83
-trypos;iX2
-yG
-iZ1
-n):eF1
-l72>(n),trypos(0){}
-}
-yO1
-n31
-TestParam_AnyWhere
-iS1
-eA2&yA2
-const
-nP1
-const
-cZ&start_at,tC
-info,cY2&used,bool
-iX1{xP<yG>x8;x83
-xA2(yG*)eK1;a=x8->trypos;goto
-retry_anywhere_2;cO2
-yG
-l51);a=0;}
-tM3
-yC++a){if(used[a])yA1
-retry_anywhere
-yW3
-TestParam(yA2
-xW
-a)xS3);yP3
-used[a]=true;if(iX1
-info.SaveMatchedParamIndex(a);x8->trypos=a
-i1
-n31(true,&*x8);}
-}
-retry_anywhere_2
-yX3
-goto
-retry_anywhere;}
-eE3
-t23
-tK1
-e72
-yD1
-x92
-MatchInfo
-xF
-info;cY2
-used;iX2
-yD1
-iZ1
-tL3):start_at(),info(),used(tL3){}
-}
-yO1
-class
-MatchPositionSpec_AnyParams:nQ1
-yD1
-xF>{e43
-iX2
-MatchPositionSpec_AnyParams
-iZ1
-n,size_t
-m):eF1
-yD1
-xF>(n,yD1
-xF(m)){}
-}
-yO1
-n31
-TestParams(eX&nN,const
-nP1
-const
-cZ&start_at,tC
-info,bool
-iX1{if(nN.match_type!=AnyParams){if(xT!=tree.GetParamCount()cQ}
-if(!IsLogisticallyPlausibleParamsMatch(nN
-cU3))tM2
-e23
-nN.match_type){case
-PositionalParams:{xP<cF>x8;x83
-xA2(cF*)eK1;a=xT-1;goto
-lK1;cO2
-cF(xT);a=0;}
-tM3
-xT;++a){(yQ3=info;retry_positionalparams
-yW3
-TestParam(cW
-a),xW
-a)xS3);yP3
-yA1}
-}
-lK1
-yX3
-info=(yQ3;goto
-retry_positionalparams;}
-if(a>0){--a;goto
-lK1;}
-info=c12
-i1
-t23
-if(iX1
-tN3
-info.SaveMatchedParamIndex(a)i1
-n31(true,&*x8);}
-case
-SelectedParams:case
-AnyParams:{xP<t6>x8;cY2
-used
-l51);eO3
-x83>iY2(xT);eO3
-x83>yB2(xT);tN3{const
-eA2
-lX3=cW
-a);iY2[a]=ParamSpec_GetDepCode(lX3);}
-{x83
-b=0;tN3
-if(iY2[a]!=0)yB2[b++]=a;tN3
-if(iY2[a]==0)yB2[b++]=a;}
-x83
-xA2(t6*)eK1;if(xT==0){a=0;goto
-retry_anyparams_4;}
-a=xT-1;goto
-eG1;cO2
-t6(xT
-cU3.GetParamCount());a=0;if(xT!=0){c12=info;(*x8)[0].used=used;}
-}
-tM3
-xT;++a){if(a>0){(yQ3=info;(yO3
-used=used;}
-retry_anyparams
-yW3
-TestParam_AnyWhere
-xF(cW
-yB2[a])cU3
-xS3,used,iX1;yP3
-yA1}
-}
-eG1
-yX3
-info=(yQ3;used=(yO3
-used;goto
-retry_anyparams;}
-eH1:if(a>0){--a;goto
-eG1;}
-info=c12
-i1
-t23
-retry_anyparams_4:if(nN.n1!=0){if(!TopLevel||!info.HasRestHolder(nN.n1)){eK
-cI2;cI2.reserve
-l51);for
-lT1
-b=0;b<yC++b){if(used[b])yA1
-cI2
-c52
-xW
-b));used[b]=true;if(iX1
-info.SaveMatchedParamIndex(b);}
-if(!info.SaveOrTestRestHolder(nN.n1,cI2)){goto
-eH1;}
-}
-else{eA3&cI2=info.GetRestHolderValues(nN.n1
-iY1
-0;a<cI2
-eJ3;++a){bool
-found
-eW3
-for
-lT1
-b=0;b<yC++b){if(used[b])yA1
-if(cI2[a]xI
-xW
-b))){used[b]=true;if(iX1
-info.SaveMatchedParamIndex(b);found=true;xY3}
-if(!found){goto
-eH1;}
-}
-}
-eE3
-n31(true,xT?&*x8:0);}
-case
-GroupFunction:xY3
-return
-t23}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <algorithm>
-#include <assert.h>
-using
-t5;using
-nG1;l33{tK1
-yZ2
-yW1
-iS1
-eA2&yA2
-tC
-info,bool
-inner=true
-yY3
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1
-i1
-CodeTreeImmed
-yZ3
-constvalue);}
-case
-ParamHolder:{cM&yU3
-cM*tF1
-i1
-info.GetParamHolderValue
-yZ3
-index);}
-case
-SubFunction:{cN&yU3
-cN*tF1
-tX
-tree;tD2
-param.lG1);for
-lT1
-a=0;a<iH3
-y92;++a
-nQ
-nparam=yW1
-nF1
-iH3.param_list,a
-l04
-true
-c81
-nparam);}
-if
-yZ3
-data.n1!=0){eK
-trees(info.GetRestHolderValues
-yZ3
-data.n1)yB
-AddParamsMove(trees);if
-l51==1){assert(tree.GetOpcode()==cAdd||tree.GetOpcode()==cMul||tree.GetOpcode()==cMin||tree.GetOpcode()==cMax||tree.GetOpcode()==cAnd||tree.GetOpcode()==cOr||tree.GetOpcode()==cAbsAnd||tree.GetOpcode()==cAbsOr);tree.eF2
-0));}
-else
-if
-l51==0
-yY3
-t72){case
-cAdd:case
-cOr:tree=nA1
-0));lC
-cMul:case
-cAnd:tree=nA1
-1));yF3
-xY3}
-}
-if(inner)tree
-iW1
-i1
-tree;}
-eE3
-yZ2();}
-}
-nG1{xL1
-SynthesizeRule(t41
-nP1
-tC
-info
-yY3
-rule.ruletype){case
-ProduceNewTree:{tree.Become(yW1
-nF1
-rule.t51
-0
-l04
-false)e02
-case
-ReplaceParams:yF3{eO3
-x83>list=info.GetMatchedParamIndexes();std::sort(list.iJ2
-list.end()iY1
-list
-eJ3;a-->0;)tree.i91
-list[a]);for
-lT1
-a=0;a<rule.repl_param_count;++a
-nQ
-nparam=yW1
-nF1
-rule.t51
-a
-l04
-true
-c81
-nparam);}
-xY3}
-}
-}
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-#include <sstream>
-#include <cstring>
-using
-l33
-FUNCTIONPARSERTYPES;using
-l33
-lA1;using
-t5;using
-nG1;l33
-lA1{xL1
-DumpMatch(t41
-const
-nP1
-const
-tC
-info,bool
-DidMatch,std::ostream&o){DumpMatch
-yG2,DidMatch?iX3"match"
-:iX3"mismatch"
-,o);}
-xL1
-DumpMatch(t41
-const
-nP1
-const
-tC
-info,e32
-tO3,std::ostream&o){static
-const
-char
-ParamHolderNames[][2]={"%"
-,"&"
-,"x"
-,"y"
-,"z"
-,"a"
-,"b"
-,"c"
-}
-;o<<tO3<<" (rule "
-<<(&rule-grammar_rules)<<")"
-<<":\n Pattern : "
-;{eA2
-tmp;tmp.first=SubFunction;ParamSpec_SubFunction
-tmp2;tmp2.data=rule
-yR2;tmp.second=cG2
-tmp2;DumpParam
-xF(tmp,o);}
-o<<"\n Replacement: "
-;DumpParams
-xF(rule.t51
-rule.repl_param_count,o)iV3
-o<<" Tree : "
-iL2
-tree,o)iV3
-if(!std::strcmp(tO3,iX3"match"
-))DumpHashes(tree,o
-iY1
-0;a<info.cA
-eJ3;++a){if(!info.cA[a].nX2)yA1
-o<<" "
-<<ParamHolderNames[a]<<" = "
-iL2
-info.cA[a],o)iV3}
-e11
-info.lQ
-eJ3;++b){if(!iW3
-eH3)yA1
-for
-iZ1
-a=0;a<iW3
-eI3
-eJ3;++a){o<<" <"
-<<b<<"> = "
-iL2
-iW3
-eI3[a],o);o<<std::endl;}
-}
-o<<std::flush;}
-}
-#endif
-#include <list>
-#include <algorithm>
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{yP1
-MarkIncompletes(FPoptimizer_CodeTree::eR{if(tree.Is_Incompletely_Hashed())lD2
-bool
-l82
-eW3
-x51
-l82|=MarkIncompletes(xW
-a));if(l82)tree.Mark_Incompletely_Hashed()i1
-l82;}
-xL1
-FixIncompletes(FPoptimizer_CodeTree::eR{if(tree.Is_Incompletely_Hashed()){x51
-FixIncompletes(xW
-a)yB
-e33);}
-}
-}
-t5{lB
-Sort()iZ3
-Sort();}
-lB
-e33
-bool
-constantfolding){if(constantfolding)ConstantFolding(*this);else
-Sort();data
-xC
-tK1
-e72
-cB
-c03
-Value_t
-c13
-yE1=0;
-#if 0
-long
-double
-value=Value;e9=crc32::calc(iS1
-x83
-char*)&value,sizeof(value));key^=(key<<24);
-#elif 0
-union{e72{x83
-char
-filler1[16]iK2
-v;x83
-char
-filler2[16];}
-buf2;e72{x83
-char
-filler3[sizeof
-cX3)+16-sizeof(xE1)];e9;}
-buf1;}
-data;memset(&data,0,sizeof(data));data.buf2.v=Value;e9=data.buf1.key;
-#else
-int
-exponent
-iK2
-nR2=std::frexp(Value,&tU2
-e9=lT1(exponent+0x8000)&0xFFFF);if(nR2<0){nR2=-nR2;key=key^0xFFFF;}
-else
-key+=0x10000;nR2-=yF2;key<<=39;key|=n51(nR2+nR2)*e62
-1u<<31))<<8;
-#endif
-lP
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
-nN1
-T
-cJ2
-std::complex<T> >c03
-std::complex<T>c13
-cB<T>::lY3
-cK2,Value.real());nB
-fphash_t
-temp;cB<T>::lY3
-temp,Value.imag());yE1^=temp.hash2;cK2.hash2^=temp.hash1;}
-}
-;
-#endif
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-tP1
-cJ2
-long>yD
-long
-Value){e9=Value;lP
-#endif
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-tP1
-cJ2
-GmpInt>c03
-GmpInt
-c13
-e9=Value.toInt();lP
-#endif
-xL1
-xK2
-xF::Recalculate_Hash_NoRecursion(){fphash_t
-cK2(n51
-Opcode)<<56,Opcode*iE3(0x1131462E270012B));Depth=1;e23
-Opcode){case
-cImmed:{cB
-xF::lY3
-cK2,Value
-e02
-case
-iU2:{yE1|=n51
-cO1<<48
-lL1((n51
-cO1)*11)^iE3(0x3A83A83A83A83A0);xY3
-case
-cFCall:case
-cPCall:{yE1|=n51
-cO1<<48
-lL1((~n51
-cO1)*7)^3456789;}
-yF3{size_t
-t61=0
-e73
-0;a<iS2;++a){if(iT2
-nP2>t61)t61=iT2
-nP2;yE1+=((iT2.tN2
-hash1*(a+1))>>12)lL1
-iT2.tN2
-hash1
-lL1(3)*iE3(0x9ABCD801357);cK2.hash2*=iE3(0xECADB912345)lL1(~iT2.tN2
-hash2)^4567890;}
-Depth+=t61;}
-}
-if(Hash!=cK2){Hash=cK2;lM2=0;}
-}
-lB
-tE3{MarkIncompletes(*this);FixIncompletes(*this);}
-}
-#endif
-#include <cmath>
-#include <list>
-#include <cassert>
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{using
-t5
-yO1
-bool
-x01
-const
-nP1
-long
-count,const
-xK1::SequenceOpCode
-xF&eQ,xK1::eP3&synth,size_t
-max_bytecode_grow_length);static
-const
-e72
-SinCosTanDataType{OPCODE
-whichopcode;OPCODE
-inverse_opcode;enum{eR2,nS2,nZ1,lM1}
-;OPCODE
-codes[4];}
-SinCosTanData[12]={{cTan,cCot,{cSin,cCos,cCsc,cSec}
-}
-,{cCot,cCot,{cCos,cSin,cSec,cCsc}
-}
-,{cCos,cSec,{cSin,cTan,cCsc,cCot}
-}
-,{cSec,cCos,{cTan,cSin,cCot,cCsc}
-}
-,{cSin,cCsc,{cCos,cCot,cSec,cTan}
-}
-,{cCsc,cSin,{cCot,cCos,cTan,cSec}
-}
-,{cL2{tD3
-cCosh,cM2,{tD3
-cNop,{cL2
-cNop,cCosh}
-}
-,{cCosh,cNop,{tD3
-cL2
-cNop}
-}
-,{cNop,cTanh,{cCosh,tD3
-cM2,{cNop,tD3{cNop,cTanh,cCosh,cNop}
-}
-,{cNop,cCosh,{cTanh,tD3
-cM2}
-;}
-t5{lB
-SynthesizeByteCode(eO3
-x83>&eN1,std
-xM3
-xF&Immed,size_t&stacktop_max){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Making bytecode for:\n"
-;l21
-#endif
-while(RecreateInversionsAndNegations()){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"One change issued, produced:\n"
-;l21
-#endif
-tE3;using
-nG1;using
-l33
-lA1;const
-void*g=cG2
-grammar_optimize_recreate;while(ApplyGrammar(*iS1
-Grammar*)g,*this)){tE3;}
-}
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Actually synthesizing, after recreating inv/neg:\n"
-;l21
-#endif
-xK1::eP3
-synth;SynthesizeByteCode(synth,false
-iM2.Pull(eN1,Immed,stacktop_max);}
-lB
-SynthesizeByteCode(xK1::eP3&synth,bool
-MustPopTemps)const{y01*this))yP;}
-for
-iZ1
-a=0;a<12;++a){const
-SinCosTanDataType&data=SinCosTanData[a];if(data.whichopcode!=cNop)iC1!=data.whichopcode)yA1
-c02
-lZ3;lZ3.xA1);lZ3
-iH
-data.inverse_opcode);lZ3.yC2);y01
-lZ3)){synth.tQ
-else
-iC1!=cInv)yA1
-if(GetParam(0)nC!=data.inverse_opcode)yA1
-y01
-GetParam(0))){synth.tQ
-size_t
-found[4];e11
-4;++b){c02
-tree;if(data.tP3]==cNop){tD2
-cInv);c02
-n03;n03.xA1);n03
-iH
-data.tP3^2]);n03.yC2
-c81
-n03);}
-else{tree.xA1
-yB
-eL3
-data.tP3]);}
-tree.yC2);found[b]=synth.xK3
-tree);}
-if(found[data.eR2
-e3
-nS2
-tG
-eR2]iM2.yT
-nS2]);yB1
-cDiv
-tW
-eR2
-e3
-lM1
-tG
-eR2]iM2.yT
-lM1]);yB1
-cMul
-tW
-nZ1
-e3
-lM1
-tG
-nZ1]iM2.yT
-lM1]);yB1
-cRDiv
-tW
-nZ1
-e3
-nS2
-tG
-nZ1]iM2.yT
-nS2]);yB1
-cMul,2,1
-iM2.tQ
-size_t
-n_subexpressions_synthesized=SynthCommonSubExpressions(c92
-e23
-l92{case
-iU2:synth.PushVar(GetVar());lC
-cImmed:t71
-GetImmed());lC
-cAdd:case
-cMul:case
-cMin:case
-cMax:case
-cAnd:case
-cOr:case
-cAbsAnd:case
-cAbsOr:iC1==cMul){bool
-c23
-eW3
-yH
-lX1
-tD1&&isLongInteger(lX1
-x41)){c11=makeLongInteger(lX1
-x41);c02
-tmp(*this,x93
-c02::CloneTag());tmp.i91
-a);tmp
-iW1;if(x01
-tmp,value,xK1::tU1
-xF::AddSequence,synth,MAX_MULI_BYTECODE_LENGTH)){c23=true;xY3}
-}
-if(c23)xY3
-int
-yF1=0;cY2
-done(GetParamCount(),false);c02
-iQ;iQ
-iH
-l92;for(;;){bool
-found
-eW3
-yH
-done[a])yA1
-if(synth.IsStackTop(lX1)){found=true;done[a]=true;lX1.n7
-iQ
-cS
-lX1);if(++yF1>1){yU
-2);iQ.yC2)yC1
-iQ);yF1=yF1-2+1;}
-}
-}
-if(!found)xY3
-yH
-done[a])yA1
-lX1.n7
-iQ
-cS
-lX1);if(++yF1>1){yU
-2);iQ.yC2)yC1
-iQ);yF1=yF1-2+1;}
-}
-if(yF1==0
-yY3
-l92{case
-cAdd:case
-cOr:case
-cAbsOr:t71
-0);lC
-cMul:case
-cAnd:case
-cAbsAnd:t71
-1);lC
-cMin:case
-cMax:t71
-0);break;yF3
-xY3++yF1;}
-assert(n_stacked==1);xY3
-case
-cPow:{tW1
-p0
-i42
-0);tW1
-p1
-i42
-1);if(!p1
-tD1||!isLongInteger
-cR3||!x01
-p0,makeLongInteger
-cR3,xK1::tU1
-xF::MulSequence,synth,MAX_POWI_BYTECODE_LENGTH)){p0.n7
-p1.n7
-yU
-2);e21
-cIf:case
-cAbsIf:{x93
-xK1::eP3::IfData
-ifdata;GetParam(0)e93
-SynthIfStep1(ifdata,l92;GetParam(1)e93
-SynthIfStep2(ifdata);GetParam(2)e93
-SynthIfStep3(ifdata
-e02
-case
-cFCall:case
-cPCall:{for
-iZ1
-a=0;a<l91++a)lX1.n7
-yU
-lT1)GetParamCount());yB1
-0x80000000u|GetFuncNo(),0,0
-e02
-yF3{for
-iZ1
-a=0;a<l91++a)lX1.n7
-yU
-lT1)GetParamCount()e02}
-synth.StackTopIs(*this);if(MustPopTemps&&n_subexpressions_synthesized>0){size_t
-top=synth.GetStackTop(iM2.DoPopNMov(top-1-n_subexpressions_synthesized,top-1);}
-}
-}
-l33{yP1
-x01
-const
-nP1
-long
-count,const
-xK1::SequenceOpCode
-xF&eQ,xK1::eP3&synth,size_t
-max_bytecode_grow_length){if
-cW3!=0){xK1::eP3
-backup=synth;tree.n7
-size_t
-bytecodesize_backup=synth.GetByteCodeSize();xK1::x01
-count
-e63
-size_t
-bytecode_grow_amount=synth.GetByteCodeSize()-bytecodesize_backup;if(bytecode_grow_amount>max_bytecode_grow_length){synth=backup
-i1
-t23
-lD2}
-else{xK1::x01
-count,eQ,synth
-yQ2}
-}
-#endif
-#include <cmath>
-#include <cassert>
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{using
-t5;
-#define FactorStack std xM3
-const
-e72
-PowiMuliType{x83
-opcode_square;x83
-opcode_cumulate;x83
-opcode_invert;x83
-opcode_half;x83
-opcode_invhalf;}
-iseq_powi={cSqr,cMul,cInv,cSqrt,cRSqrt}
-,iseq_muli={l52
-x9
-cNeg,l52,l52}
-yO1
-Value_t
-cP1
-const
-PowiMuliType&c33,const
-std
-nA3,n82&stack)eQ3
-1);while(IP<limit){if(n13
-c33.opcode_square){if(!t42
-eT3
-2;yZ
-opcode_invert){nS3=-nS3;yZ
-opcode_half){if(nS3>xH1&&isEvenInteger(eT3
-yF2;yZ
-opcode_invhalf){if(nS3>xH1&&isEvenInteger(eT3
-e62-0.5);++IP;yA1}
-size_t
-xB2=IP
-iK2
-lhs(1);if(n13
-cFetch){lJ1=n43;if(index<y2||size_t(index-y2)>=lB2){IP=xB2;xY3
-lhs=stack[index-y2];goto
-yD2;}
-if(n13
-cDup){lhs=nS3;goto
-yD2;yD2:t91
-nS3);++IP
-iK2
-subexponent=cP1
-c33
-iK
-if(IP>=limit||eN1[IP]!=c33.opcode_cumulate){IP=xB2;xY3++IP;stack.pop_back();nS3+=lhs*subexponent;yA1}
-xY3
-return
-nS3;}
-tK1
-Value_t
-ParsePowiSequence
-iS1
-std
-nA3){n82
-stack;t91
-e62
-1))i1
-cP1
-iseq_powi
-iK}
-tK1
-Value_t
-ParseMuliSequence
-iS1
-std
-nA3){n82
-stack;t91
-e62
-1))i1
-cP1
-iseq_muli
-iK}
-tK1
-class
-CodeTreeParserData{e43
-iX2
-CodeTreeParserData(bool
-k_powi):stack(),clones(),keep_powi(k_powi){}
-void
-Eat
-iZ1
-tL3,OPCODE
-opcode
-nQ
-xM;xM
-iH
-opcode);eK
-params=Pop(tL3
-yR1
-tL2;if(!keep_powi)e23
-opcode){case
-cTanh:{yZ2
-sinh,cosh;sinh
-iH
-cSinh);sinh
-cS
-xM
-c43
-sinh
-iW1;cosh
-iH
-cCosh);cosh
-c91
-xM
-c43
-cosh
-iW1
-tX
-pow;pow
-iH
-cPow);pow
-c91
-cosh);pow.yA
-nU2));pow
-iW1;xM
-iH
-cMul);xM.nB1
-0,sinh);xM
-c91
-pow
-e02
-case
-cTan:{yZ2
-sin,cos;sin
-iH
-cSin);sin
-cS
-xM
-c43
-sin
-iW1;cos
-iH
-cCos);cos
-c91
-xM
-c43
-cos
-iW1
-tX
-pow;pow
-iH
-cPow);pow
-c91
-cos);pow.yA
-nU2));pow
-iW1;xM
-iH
-cMul);xM.nB1
-0,sin);xM
-c91
-pow
-e02
-case
-cPow:{iT1&p0=xM
-l8
-0);iT1&p1=xM
-l8
-1);if(p1
-nC==cAdd){eK
-mulgroup(p1.GetParamCount()iY1
-0;a<p1.l91++a
-nQ
-pow;pow
-iH
-cPow);pow
-cS
-p0);pow
-cS
-p1
-n93
-pow
-iW1;mulgroup[a
-tQ3
-pow);}
-xM
-iH
-cMul
-yR1
-mulgroup);}
-xY3
-yF3
-xY3
-xM.e33!keep_powi);lA2,false);
-#ifdef DEBUG_SUBSTITUTIONS
-iA1<<tL3<<", "
-<<FP_GetOpcodeName(opcode)<<"->"
-<<FP_GetOpcodeName(xM
-nC)<<": "
-iK3
-xM);iB1
-xM);
-#endif
-t91
-xM
-cN2
-EatFunc
-iZ1
-tL3,OPCODE
-opcode,x83
-funcno
-nQ
-xM=CodeTreeFuncOp
-xF(opcode,funcno);eK
-params=Pop(tL3
-yR1
-tL2;xM.yC2);
-#ifdef DEBUG_SUBSTITUTIONS
-iA1<<tL3<<", "
-iK3
-xM);iB1
-xM);
-#endif
-lA2);t91
-xM
-cN2
-AddConst(yL1
-nQ
-xM=CodeTreeImmed(value);lA2);Push(xM
-cN2
-AddVar
-lT1
-varno
-nQ
-xM=CodeTreeVar
-xF(varno);lA2);Push(xM
-cN2
-SwapLastTwoInStack(){tA1
-1
-tQ3
-tA1
-2]cN2
-Dup(){Fetch(lB2-1
-cN2
-Fetch
-iZ1
-which){Push(stack[which]);}
-nN1
-T>void
-Push(T
-tree){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iK3
-tree);iB1
-tree);
-#endif
-t91
-tree
-cN2
-PopNMov
-iZ1
-target,size_t
-source){stack[target]=stack[source];stack
-xF3
-target+1);}
-yZ2
-yE2{clones.clear()tX
-nS3(stack.back());stack
-xF3
-lB2-1)i1
-nS3;}
-eK
-Pop
-iZ1
-n_pop){eK
-nS3(n_pop);for
-lT1
-n=0;n<n_pop;++n)nS3[n
-tQ3
-tA1
-n_pop+n]);
-#ifdef DEBUG_SUBSTITUTIONS
-for
-iZ1
-n=n_pop;n-->0;){iA1
-iL2
-nS3[n]);iB1
-nS3[n]);}
-#endif
-stack
-xF3
-lB2-n_pop)i1
-nS3;}
-size_t
-GetStackTop(c01
-lB2;}
-private:void
-FindClone(yZ2&,bool=true)yP;}
-private:eK
-stack;std::multimap<fphash_t,yZ2>clones;bool
-keep_powi;private:CodeTreeParserData
-iS1
-CodeTreeParserData&);CodeTreeParserData&eM1=iS1
-CodeTreeParserData&);}
-yO1
-e72
-IfInfo{yZ2
-eS2
-tX
-thenbranch;size_t
-endif_location;IfInfo():eS2(),thenbranch(),endif_location(){}
-}
-;}
-t5{lB
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&x33,bool
-keep_powi){eK
-xH2;xH2.xH3
-x33.mVariablesAmount);for
-lT1
-n=0;n<x33.mVariablesAmount;++n){xH2
-c52
-CodeTreeVar
-xF(n+iU2));}
-GenerateFrom(x33,xH2,keep_powi);}
-lB
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&x33,const
-x5&xH2,bool
-keep_powi){const
-eO3
-x83>&eN1=x33.mByteCode;const
-std
-xM3
-xF&Immed=x33.mImmed;
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"ENTERS GenerateFrom()\n"
-;
-#endif
-CodeTreeParserData
-xF
-sim(keep_powi);eO3
-IfInfo
-xF>eJ
-eK3
-IP=0,DP=0;;++IP){tO2:while(!eJ
-eU3&&(eJ.eA==IP||(IP<n41&&n13
-cJump&&eJ
-e81.nX2))){c02
-elsebranch=sim.yE2
-nA2
-eJ.back().eS2)nA2
-eJ
-e81)nA2
-elsebranch)yR
-3,cIf);eJ.pop_back();}
-if(IP>=n41)break;x83
-opcode=eN1[IP];if(eS3
-cSqr||opcode==cDup||eS3
-cInv&&!IsIntType
-xF::nS3)||opcode==cNeg||opcode==cSqrt||opcode==cRSqrt||opcode==cFetch)){size_t
-was_ip=IP
-iK2
-eD2
-ParsePowiSequence
-xF(eN1,IP,eJ
-eU3?n41:eJ.eA,sim.xH
-1);if(exponent!=e62
-1.0)){xG
-exponent
-iU3);goto
-tO2;}
-if
-eS3
-cDup||opcode==cFetch||opcode==cNeg)l14
-xT2=ParseMuliSequence
-xF(eN1,IP,eJ
-eU3?n41:eJ.eA,sim.xH
-1);if(xT2!=e62
-1.0)){xG
-xT2)yR
-2,cMul);goto
-tO2;}
-}
-IP=was_ip;}
-if(nB2>=iU2){lJ1=opcode-iU2
-nA2
-xH2[index]);}
-else{e23
-nB2){case
-cIf:case
-cAbsIf:{eJ
-xF3
-eJ
-eJ3+1);c02
-res(sim.yE2);eJ.back().eS2.swap(res);eJ.eA=n41;IP+=2;yA1}
-case
-cJump:{c02
-res(sim.yE2);eJ
-e81.swap(res);eJ.eA=eN1[IP+1]+1;IP+=2;yA1}
-case
-cImmed:xG
-Immed[DP++]);lC
-cDup:sim.Dup();lC
-cNop:lC
-cFCall:{x83
-funcno=n43;assert(funcno<fpdata.mFuncPtrs.size());x83
-params=x33.mFuncPtrs
-n53
-mParams;sim.EatFunc(params,nB2,funcno
-e02
-case
-cPCall:{x83
-funcno=n43;assert(funcno<fpdata.iI3.size());const
-FunctionParserBase
-xF&p=*x33.iI3
-n53
-mParserPtr;x83
-params=x33.iI3
-n53
-mParams;x5
-paramlist=sim.Pop(tL2;c02
-tP2;tP2.GenerateFrom(*p.mData,paramlist)nA2
-tP2
-e02
-case
-cInv:xG
-1
-c32
-cDiv);lC
-cNeg
-nC2
-cNeg);break;xG
-0
-c32
-cSub);lC
-cSqr:xG
-2
-xN1
-cSqrt:xG
-yF2
-xN1
-cRSqrt:xG
-e62-0.5)xN1
-cCbrt:xG
-e62
-1)/e62
-3)xN1
-cDeg:xG
-fp_const_rad_to_deg
-xF())yG1
-cRad:xG
-fp_const_deg_to_rad
-xF())yG1
-cExp:iR)goto
-yM3;xG
-fp_const_e
-xF()c32
-cPow);lC
-cExp2:iR)goto
-yM3;xG
-2.0
-c32
-cPow);lC
-cCot
-nC2
-cTan);iR)x1
-cCsc
-nC2
-cSin);iR)x1
-cSec
-nC2
-cCos);iR)x1
-cInt:
-#ifndef __x86_64
-iR)n23
-1,cInt
-e02
-#endif
-xG
-yF2)tQ2
-yR
-1,cFloor);lC
-cLog10
-nC2
-c53
-fp_const_log10inv
-xF())yG1
-cLog2
-nC2
-c53
-fp_const_log2inv
-xF())yG1
-cQ3:n33
-c53
-fp_const_log2inv
-xF())yR
-3,cMul);lC
-cHypot:xG
-2
-iU3);tS3
-xG
-2
-iU3)tQ2;xG
-yF2
-xN1
-cSinCos:sim.Dup()yR
-1,cSin);n33
-cCos);lC
-cSinhCosh:sim.Dup()yR
-1,cSinh);n33
-cCosh);lC
-cRSub:tS3
-case
-cSub:iR)n23
-2,cSub
-e02
-xG-1)yR
-2,cMul)tQ2;lC
-cRDiv:tS3
-case
-cDiv:iR||IsIntType
-xF::nS3)n23
-2,cDiv
-e02
-xG-1
-iU3)yG1
-cAdd:case
-cMul:case
-cMod:case
-cPow:case
-cEqual:case
-cLess:case
-cGreater:case
-i51:case
-cLessOrEq:case
-cGreaterOrEq:case
-cAnd:case
-cOr:case
-cAbsAnd:case
-cAbsOr:sim.Eat(2,tB1
-lC
-cNot:case
-cNotNot:case
-cC3:case
-cAbsNotNot
-nC2
-tB1
-lC
-cFetch:sim.Fetch(n43);lC
-cPopNMov:{x83
-stackOffs_target=n43;x83
-stackOffs_source=n43;sim.PopNMov(stackOffs_target,stackOffs_source
-e02
-yF3
-yM3:;x83
-funcno=opcode-cAbs;assert(funcno<FUNC_AMOUNT);const
-FuncDefinition&func=Functions[funcno]yR
-func.params,tB1
-xY3}
-}
-Become(sim.yE2);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Produced tree:\n"
-;l21
-#endif
-}
-}
-#endif
-#include <algorithm>
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <assert.h>
-#define FP_MUL_COMBINE_EXPONENTS
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5
-yO1
-static
-void
-AdoptChildrenWithSameOpcode(eR{
-#ifdef DEBUG_SUBSTITUTIONS
-bool
-nT2
-eW3
-#endif
-for
-l41
-if(xW
-a)nC==t72){
-#ifdef DEBUG_SUBSTITUTIONS
-if(!nT2)cH2"Before assimilation: "
-cR
-nT2=true;}
-#endif
-tree.AddParamsMove(xW
-a).GetUniqueRef().lJ2),a);}
-#ifdef DEBUG_SUBSTITUTIONS
-if(nT2)cH2"After assimilation: "
-cR}
-#endif
-}
-}
-t5{xL1
-ConstantFolding(eR{tree.Sort();
-#ifdef DEBUG_SUBSTITUTIONS
-void*c63=0;cV2<<"["
-<<(&c63)<<"]Runs ConstantFolding for: "
-cR
-DumpHashes(tree
-lE2
-std::flush;
-#endif
-if(false){redo:;tree.Sort();
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"["
-<<(&c63)<<"]Re-runs ConstantFolding: "
-cR
-DumpHashes(tree);
-#endif
-}
-if(t72!=cImmed){yD3
-p=CalculateResultBoundaries(tree);if(p
-yI&&p
-e61&&p
-yM==p
-tG1{nU
-p
-yM);nD}
-if(false){ReplaceTreeWithOne:nU
-e62
-1));goto
-do_return;ReplaceTreeWithZero:nU
-xG1;goto
-do_return;ReplaceTreeWithParam0:
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before replace: "
-;cV2<<std::hex<<'['
-eJ1
-hash1<<','
-eJ1
-hash2<<']'<<std::dec
-cR
-#endif
-tree.eF2
-0));
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After replace: "
-;cV2<<std::hex<<'['
-eJ1
-hash1<<','
-eJ1
-hash2<<']'<<std::dec
-cR
-#endif
-cJ
-c73(t72){case
-cImmed:lC
-iU2:lC
-cAnd:case
-cAbsAnd
-cK
-bool
-c5
-eW3
-for
-l41{if(!c83
-a)))c5=true;cA3
-a),t72==cAbsAnd)){case
-xX3
-t7
-iF2:iZ);lC
-lZ1
-c73
-l51){case
-0:iD
-1:tD2
-t72==cAnd?cNotNot:cAbsNotNot);cJ
-yF3
-cZ2
-cAnd||!c5)if(ConstantFolding_AndLogic(tB2
-e21
-cOr:case
-cAbsOr
-cK
-bool
-c5
-eW3
-for
-l41{if(!c83
-a)))c5=true;cA3
-a),t72==cAbsOr)tN1
-iD
-l03
-iZ);lC
-lZ1
-c73
-l51){case
-0
-t7
-1:tD2
-t72==cOr?cNotNot:cAbsNotNot);cJ
-yF3
-cZ2
-cOr||!c5)if(ConstantFolding_OrLogic(tB2
-e21
-cNot:case
-cC3:{x83
-n61
-0;e23
-c93){case
-cEqual:n61
-i51;lC
-i51:n61
-cEqual;lC
-cLess:n61
-cGreaterOrEq;lC
-cGreater:n61
-cLessOrEq;lC
-cLessOrEq:n61
-cGreater;lC
-cGreaterOrEq:n61
-cLess;lC
-cNotNot:n61
-cNot;lC
-cNot:n61
-cNotNot;lC
-cC3:n61
-cAbsNotNot;lC
-cAbsNotNot:n61
-cC3;break;yF3
-xY3
-if(opposite){tD2
-OPCODE(opposite)yB
-SetParamsMove(xW
-0).GetUniqueRef().lJ2));cJ
-c73(lY1
-0)cU3
-cQ1){case
-iF2
-t7
-l03
-iD
-lZ1
-cZ2
-cNot&&GetPositivityInfo(xW
-0))==iF2)tD2
-cC3);if(c93==cIf||c93==cAbsIf
-nQ
-iZ2=xW
-0);iT1&ifp1=iZ2
-l8
-1);iT1&ifp2=iZ2
-l8
-2);if(ifp1
-nC
-iY3
-ifp1
-cQ1
-cD3
-ifp1
-nC==cNot?cNotNot:cAbsNotNot);tR2
-c43
-n63)cE3
-nO2;p2
-tT3
-iI
-if(ifp2
-nC
-iY3
-ifp2
-cQ1
-cD3
-t72);tR2);n63)cE3
-iH
-ifp2
-nC==cNot?cNotNot:cAbsNotNot);p2
-tT3
-l8
-0)iI
-e21
-cNotNot:case
-cAbsNotNot:{if(c83
-0)))n73
-cA3
-0),t72==cAbsNotNot)){case
-xX3
-t7
-iF2:iD
-lZ1
-cZ2
-cNotNot&&GetPositivityInfo(xW
-0))==iF2)tD2
-cAbsNotNot);if(c93==cIf||c93==cAbsIf
-nQ
-iZ2=xW
-0);iT1&ifp1=iZ2
-l8
-1);iT1&ifp2=iZ2
-l8
-2);if(ifp1
-nC
-iY3
-ifp1
-cQ1{tree.SetParam(0,iZ2
-l8
-0)yB
-AddParam(ifp1)cE3
-nO2;p2
-tT3
-iI
-if(ifp2
-nC
-iY3
-ifp2
-cQ1
-cD3
-t72);tR2);n63
-yB
-AddParam(ifp2
-yB
-eL3
-iZ2
-nC);cJ}
-e21
-cIf:case
-cAbsIf:{if(ConstantFolding_IfOperations(tB2
-xY3
-case
-cMul:{NowWeAreMulGroup:;AdoptChildrenWithSameOpcode(tree)iK2
-nH1=e62
-1);size_t
-lC2=0;bool
-nI1
-eW3
-x51{if(!xW
-tC1
-yA1
-Value_t
-immed=xW
-a)x41;if(immed==xG1
-goto
-ReplaceTreeWithZero;nH1*=immed;++lC2;}
-if(lC2>1||(lC2==1&&lJ3
-nH1,e62
-1))))nI1=true;if(nI1){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"cMul: Will add new "
-iJ3
-nH1<<"\n"
-;
-#endif
-for
-l41
-if(xW
-tC1{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<" - For that, deleting "
-iJ3
-xW
-a)x41;cV2<<"\n"
-;
-#endif
-tU3(!lJ3
-nH1,e62
-1)))tree
-cS
-eA1
-nH1));c73
-l51){case
-0:iD
-1:n73
-yF3
-if(ConstantFolding_MulGrouping(tB2
-if(ConstantFolding_MulLogicItems(tB2
-e21
-cAdd
-cK
-Value_t
-nD2=0.0;size_t
-lC2=0;bool
-nI1
-eW3
-x51{if(!xW
-tC1
-yA1
-Value_t
-immed=xW
-a)x41;nD2+=immed;++lC2;}
-if(lC2>1||(lC2==1&&nD2==xG1)nI1=true;if(nI1){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"cAdd: Will add new "
-iJ3
-nD2<<"\n"
-;cV2<<"In: "
-cR
-#endif
-for
-l41
-if(xW
-tC1{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<" - For that, deleting "
-iJ3
-xW
-a)x41;cV2<<"\n"
-;
-#endif
-tU3(!(nD2==e62
-0.0)))tree
-cS
-eA1
-nD2));c73
-l51){case
-0
-t7
-1:n73
-yF3
-if(ConstantFolding_AddGrouping(tB2
-if(ConstantFolding_AddLogicItems(tB2
-e21
-cMin
-cK
-size_t
-yI2=0;yD3
-e4;x51{while(a+1<tree.GetParamCount()&&xW
-a)xI
-xW
-a+1)))iZ+1);yE3
-max.cF3(!e4
-e61||(p
-tG1<e4
-tG1){e4
-nL3=p
-nL3;e4
-e61=true;yI2=a;}
-}
-if(e4
-e61)for
-l41{yE3
-min.cF3
-a!=yI2&&p
-yM>=e4
-tG1
-tU3
-l51==1){n73
-e21
-cMax
-cK
-size_t
-yI2=0;yD3
-eY;x51{while(a+1<tree.GetParamCount()&&xW
-a)xI
-xW
-a+1)))iZ+1);yE3
-min.cF3(!eY
-yI||p
-yM>eY
-yM)){eY
-yM=p
-yM;eY
-yI=true;yI2=a;}
-}
-if(eY
-yI){for
-l41{yE3
-max.cF3
-a!=yI2&&(p
-tG1<eY
-yM){iZ);}
-}
-}
-if
-l51==1){n73
-e21
-cEqual:case
-i51:case
-cLess:case
-cGreater:case
-cLessOrEq:case
-cGreaterOrEq:if(ConstantFolding_Comparison(tB2
-lC
-cAbs:{yD3
-tY
-xW
-0));if
-iE
-n73
-if
-iF{tD2
-cMul
-yB
-yA
-e62
-1)));goto
-NowWeAreMulGroup;}
-if(c93==cMul){iT1&p=xW
-0);eK
-n83;eK
-cP2
-e73
-0;a<p.l91++a){tY
-p
-n93
-if
-iE{n83
-c52
-p
-n93}
-if
-iF{cP2
-c52
-p
-n93}
-}
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Abs: mul group has "
-<<n83
-eJ3<<" pos, "
-<<cP2
-eJ3<<"neg\n"
-;
-#endif
-if(!n83
-eU3||!cP2
-eU3){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"AbsReplace-Before: "
-iL2
-tree
-lE2"\n"
-<<std::flush;DumpHashes
-nV2);
-#endif
-yZ2
-e13;e13
-iH
-cMul
-iY1
-0;a<p.l91++a){tY
-p
-n93
-if(iE||iF){}
-else
-e13
-cS
-p
-n93}
-e13
-iW1
-tX
-nB3;nB3
-iH
-cAbs);nB3
-c91
-e13);nB3
-iW1
-tX
-iG
-cMul);mulgroup
-c91
-nB3);cA1
-AddParamsMove(n83);if(!cP2
-eU3){if(cP2
-eJ3%2)cA1
-yA
-nU2));cA1
-AddParamsMove(cP2);}
-tree.Become
-eH2);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"AbsReplace-After: "
-;DumpTree
-nV2
-lE2"\n"
-<<std::flush;DumpHashes
-nV2);
-#endif
-goto
-NowWeAreMulGroup;}
-}
-xY3
-#define HANDLE_UNARY_CONST_FUNC(funcname) nP){nU funcname(lR));nD
-case
-cLog:i83(fp_log);if(c93==cPow
-nQ
-pow=xW
-0);if(GetPositivityInfo(pow
-l8
-0))==iF2)iV1
-t2
-yB
-lU
-if(GetEvennessInfo(pow
-l8
-1))==iF2)iV1()tX
-abs;abs
-iH
-cAbs);abs
-c91
-pow
-c43
-abs.Rehash
-t2);pow.nB1
-0,abs
-yB
-lU}
-iP1
-c93==cAbs
-nQ
-pow=xW
-0)l8
-0);if(pow
-nC==cPow)iV1()tX
-abs;abs
-iH
-cAbs);abs
-c91
-pow
-c43
-abs.Rehash
-t2);pow.nB1
-0,abs
-yB
-lU}
-lC
-cAcosh:i83(fp_acosh);lC
-cAsinh:i83(fp_asinh);lC
-cAtanh:i83(fp_atanh);lC
-cAcos:i83(fp_acos);lC
-cAsin:i83(fp_asin);lC
-cAtan:i83(fp_atan);lC
-cCosh:i83(fp_cosh);lC
-cSinh:i83(fp_sinh);lC
-cTanh:i83(fp_tanh);lC
-cSin:i83(fp_sin);lC
-cCos:i83(fp_cos);lC
-cTan:i83(fp_tan);lC
-cCeil:if(n5
-i83(fp_ceil);lC
-cTrunc:if(n5
-i83(fp_trunc);lC
-cFloor:if(n5
-i83(fp_floor);lC
-cInt:if(n5
-i83(fp_int);lC
-cCbrt:i83(fp_cbrt);lC
-cSqrt:i83(fp_sqrt);lC
-cExp:i83(fp_exp);lC
-cLog2:i83(fp_log2);lC
-cLog10:i83(fp_log10);lC
-cQ3:if
-lI
-fp_log2(lR)*xW
-nC3
-cArg:i83(fp_arg);lC
-cConj:i83(fp_conj);lC
-cImag:i83(fp_imag);lC
-cReal:i83(fp_real);lC
-cPolar:if
-lI
-fp_polar
-e51
-lC
-cMod:if
-lI
-fp_mod
-e51
-lC
-cAtan2:{yD3
-tY
-xW
-yP2
-p1=tZ
-1));nP&&lJ3
-lR,xG1){if(p1
-e61&&(p1
-tG1<xG1{nU
-fp_const_pi
-cH3
-if(p1
-yI&&p1
-yM>=tE1
-xG1;nD}
-if(eI1
-lJ3
-xW
-i8,xG1){if(p0
-e61&&(p0
-tG1<xG1{nU-fp_const_pihalf
-cH3
-if
-cN3
-p0
-yM>xG1{nU
-fp_const_pihalf
-cH3}
-if
-lI
-fp_atan2
-e51
-if((p1
-yI&&p1
-yM>xG1||(p1
-e61&&(p1
-tG1<fp_const_negativezero
-xF())nQ
-yJ2;yJ2
-iH
-cPow);yJ2
-c91
-xW
-1));yJ2.yA
-nU2));yJ2
-iW1
-tX
-yK2;yK2
-iH
-cMul);yK2
-c91
-xW
-0));yK2
-c91
-yJ2);yK2
-cY
-cAtan
-yB
-nB1
-0,yK2
-yB
-i91
-1);e21
-cPow:{if(ConstantFolding_PowOperations(tB2
-xY3
-case
-cDiv:nP&&eI1
-xW
-i8!=tE1
-lR/xW
-nC3
-cInv:nP&&lR!=tE1
-e62
-1)/lR);nD
-lC
-cSub:if
-lI
-lR-xW
-nC3
-cNeg:nP){nU-lR);nD
-lC
-cRad:nP){nU
-RadiansToDegrees
-eG2
-cDeg:nP){nU
-DegreesToRadians
-eG2
-cSqr:nP){nU
-lR*lR);nD
-lC
-cExp2:i83(fp_exp2);lC
-cRSqrt:nP){nU
-e62
-1)/fp_sqrt
-eG2
-cCot:c22
-fp_tan(lZ
-cSec:c22
-fp_cos(lZ
-cCsc:c22
-fp_sin(lZ
-cHypot:if
-lI
-fp_hypot
-e51
-lC
-cRDiv:case
-cRSub:case
-cDup:case
-cFetch:case
-cPopNMov:case
-cSinCos:case
-cSinhCosh:case
-cNop:case
-cJump:lC
-cPCall:case
-cFCall:xY3
-do_return:;
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"["
-<<(&c63)<<"]Done ConstantFolding, result: "
-cR
-DumpHashes(tree);
-#endif
-}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-t5{xL1
-yD3::set_abs(nL
-bool
-has_negative=!min.known||min.val<e62);bool
-has_positive=!cG3||max.val>e62);bool
-crosses_axis=has_negative&&has_positive;cI1
-xF
-newmax;if(min.cF3
-cG3)newmax.set(fp_max(i61,i71);if(crosses_axis
-cI3
-e62));cJ3
-min.cF3
-cG3
-cI3
-fp_min(i61,i71);iP1
-min.known
-cI3
-i61);else
-min.set(i71;}
-max=newmax;}
-xL1
-yD3::set_neg(){std::swap(min,max);min.val=-min.val;max.val=-max.val;}
-yP1
-IsLogicalTrueValue
-iS1
-yD3&p,bool
-abs){if(nB
-IsIntType
-xF::nS3){if(p
-yI&&p
-yM>=e62
-1))lD2
-if(!abs&&p
-e61
-t43<=nU2)lD2}
-cJ3
-p
-yI&&p
-yM>=yF2)lD2
-if(!abs&&p
-e61
-t43<=e62-0.5))lD2
-eE3
-t23
-yP1
-IsLogicalFalseValue
-iS1
-yD3&p,bool
-abs){if(nB
-IsIntType
-xF::nS3){if(abs)eG3
-e61
-l61
-1);else
-eG3
-yI&&p
-e61&&p
-yM>nU2
-l61
-1);}
-cJ3
-abs)eG3
-e61
-l61
-0.5);else
-eG3
-yI&&p
-e61&&p
-yM>e62-0.5)l61
-0.5);}
-}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;using
-t5;t5{tK1
-yD3
-CalculateResultBoundaries
-iS1
-eR
-#ifdef DEBUG_SUBSTITUTIONS_extra_verbose
-{using
-l33
-FUNCTIONPARSERTYPES;yD3
-tmp=CalculateResultBoundaries_do(tree
-lE2"Estimated boundaries: "
-;if(tmp
-yI)cV2<<tmp
-yM;else
-cV2<<"-inf"
-;cV2<<" .. "
-;if(tmp
-e61)cV2<<tmp
-nL3;else
-cV2<<"+inf"
-;cV2<<": "
-iL2
-tree
-lE2
-std::endl
-i1
-tmp;}
-tK1
-yD3
-yZ2::CalculateResultBoundaries_do
-iS1
-eR
-#endif
-{iS
-yH1(-fp_const_pihalf
-xF(),fp_const_pihalf
-xF());iS
-pi_limits(-fp_const_pi
-xF(),fp_const_pi
-xF());iS
-abs_pi_limits(xH1,fp_const_pi
-xF());iS
-plusminus1_limits(nU2,e62
-1));using
-l33
-std;e23
-t72){case
-cImmed:nM
-tree
-x41
-cU3
-x41)t83
-cAnd:case
-cAbsAnd:case
-cOr:case
-cAbsOr:case
-cNot:case
-cC3:case
-cNotNot:case
-cAbsNotNot:case
-cEqual:case
-i51:case
-cLess:case
-cLessOrEq:case
-cGreater:case
-cGreaterOrEq:{nM
-xH1,e62
-1));}
-case
-cAbs:tW3
-set_abs();tK
-cLog:tW3
-tS2
-fp_log);nD3
-fp_log);tK
-cLog2:tW3
-tS2
-fp_log2);nD3
-fp_log2);tK
-cLog10:tW3
-tS2
-fp_log10);nD3
-fp_log10);tK
-cAcosh:tW3
-min.tL1
-cGreaterOrEq
-tH1
-fp_acosh
-tR3
-cGreaterOrEq
-tH1
-fp_acosh);tK
-cAsinh:tW3
-min.set(fp_asinh);tO
-set(fp_asinh);tK
-cAtanh:tW3
-min.n3-1),fp_atanh
-tR3
-cLess
-tH1
-fp_atanh);tK
-cAcos:lD
-nM(tO
-cF3(tO
-val)<e62
-1))?fp_acos(tO
-val):xH1,(m
-yI&&(m
-yM)>=nU2)?fp_acos(m
-yM):fp_const_pi
-xF());}
-case
-cAsin:tW3
-min.n3-1),fp_asin,yH1
-yM
-tR3
-cLess
-tH1
-fp_asin,yH1
-tG1;tK
-cAtan:tW3
-min.set(fp_atan,yH1
-yM);tO
-set(fp_atan,yH1
-tG1;tK
-cAtan2:{nP&&lJ3
-lR,xG1)yP
-abs_pi_limits;}
-if(eI1
-lJ3
-xW
-i8,xG1)yP
-yH1;eE3
-pi_limits;}
-case
-cSin:lD
-bool
-x11=!m
-yI||!tO
-known||(tO
-val-m
-yM)>=(yK
-x11)tM
-Value_t
-min=cK3
-m
-yM,yK
-min<xG1
-min
-yN
-Value_t
-max=cK3
-tO
-val,yK
-max<xG1
-max
-yN
-if(max<min)max
-yN
-bool
-y21=(min<=fp_const_pihalf
-xF()&&max>=fp_const_pihalf
-xF());bool
-nJ1=(min<=cD&&max>=cD);if(y21&&nJ1)tM
-if(nJ1)nM
-nU2,nW2
-if(y21)nM
-yL2
-e62
-1));nM
-yL2
-nW2}
-case
-cCos:lD
-if(m
-yI)m
-yM+=fp_const_pihalf
-xF();if(xI2
-tO
-val+=fp_const_pihalf
-xF();bool
-x11=!m
-yI||!tO
-known||(tO
-val-m
-yM)>=(yK
-x11)tM
-Value_t
-min=cK3
-m
-yM,yK
-min<xG1
-min
-yN
-Value_t
-max=cK3
-tO
-val,yK
-max<xG1
-max
-yN
-if(max<min)max
-yN
-bool
-y21=(min<=fp_const_pihalf
-xF()&&max>=fp_const_pihalf
-xF());bool
-nJ1=(min<=cD&&max>=cD);if(y21&&nJ1)tM
-if(nJ1)nM
-nU2,nW2
-if(y21)nM
-yL2
-e62
-1));nM
-yL2
-nW2}
-case
-cTan:{nM);}
-case
-cCeil:lD
-tO
-i81
-cFloor:lD
-m
-yI1
-tK
-cTrunc:lD
-m
-yI1
-tO
-i81
-cInt:lD
-m
-yI1
-tO
-i81
-cSinh:tW3
-min.set(fp_sinh);tO
-set(fp_sinh);tK
-cTanh:tW3
-min.set(fp_tanh,plusminus1_limits.min);tO
-set(fp_tanh,plusminus1_limits.max);tK
-cCosh:lD
-if(m
-yI){if(xI2{if(m
-yM>=xH1&&tO
-val>=xG1{m
-yM
-xS}
-iP1(m
-yM)<xH1&&tO
-val>=xG1
-l14
-tmp
-xS
-if(tmp>tO
-val)tO
-val=tmp;m
-yM=e62
-1);}
-else{m
-yM
-xS
-std::swap(m
-yM,tO
-val);}
-}
-cJ3
-m
-yM>=xG1{m.tL
-m
-yM=fp_cosh(m
-yM);}
-else{m.tL
-m
-yM=e62
-1);}
-}
-}
-else{m
-yI=true;m
-yM=e62
-1);if(xI2{m
-yM=fp_cosh(tO
-val);m.tL}
-else
-m.tL}
-tK
-cIf:case
-cAbsIf:{yD3
-res1=tZ
-1));yD3
-res2=tZ
-2));if(!res2
-yI)res1
-yI
-eW3
-iP1
-res1
-yI&&(res2
-yM)<res1
-yM)res1
-yM=res2
-yM;if(!res2
-e61)res1.tL
-iP1
-res1
-e61&&(res2
-tG1>res1
-tG1
-res1
-nL3=res2
-nL3
-i1
-res1;}
-case
-cMin:{bool
-iT
-eW3
-bool
-iU
-eW3
-e83;x7
-m
-tZ3
-m
-yI)iT
-iN3
-yI||(m
-yM)<nF3)nF3=m
-yM;if(!xI2
-iU
-iN3
-e61||(tO
-val)<nG3
-nH3=tO
-val;}
-if(iT)nK3
-iU)nQ3
-return
-nR3
-cMax:{bool
-iT
-eW3
-bool
-iU
-eW3
-e83;x7
-m
-tZ3
-m
-yI)iT
-iN3
-yI||m
-yM>nF3)nF3=m
-yM;if(!xI2
-iU
-iN3
-e61||tO
-val>nG3
-nH3=tO
-val;}
-if(iT)nK3
-iU)nQ3
-return
-nR3
-cAdd:{e83(xH1,xG1;x7
-item=tZ
-a));if(item
-yI)nF3+=item
-yM;else
-nK3
-item
-e61)nH3+=item
-nL3;else
-nQ3
-if(!nI3&&!nJ3)xY3
-if(nI3&&nJ3&&nF3>nG3
-std::swap(nF3,nG3
-i1
-nR3
-cMul:{e72
-Value{enum
-nT3{tT2,lG2,PlusInf}
-;nT3
-eB
-iK2
-value;Value(nT3
-t):eB(t),value(0){}
-Value
-cX3
-v):eB(tT2),value(v){}
-bool
-cQ2
-c01
-eB==lG2||(eB==tT2&&value<xG1;}
-void
-eM1*=iS1
-Value&rhs){if(eB==tT2&&rhs.eB==tT2)value*=rhs.value;else
-eB=(cQ2)!=rhs.cQ2)?lG2:PlusInf);}
-iD2<iS1
-Value&rhs
-c01(eB==lG2&&rhs.eB!=lG2)||(eB==tT2&&(rhs.eB==PlusInf||(rhs.eB==tT2&&value<rhs.value)));}
-}
-;e72
-yJ1{Value
-yN2,yO2;yJ1():yN2(Value::PlusInf),yO2(Value::lG2){}
-void
-xJ2
-Value
-cM3,const
-Value&value2){cM3*=value2;if(cM3<yN2)yN2=cM3;if(yO2<cM3)yO2=cM3;}
-}
-;e83(nM3
-x7
-item
-tZ3
-item
-yI&&!item
-e61)nM);Value
-iP3=nI3?Value(nF3):xC2
-lG2);Value
-nU3=nJ3?Value(nG3:xC2
-PlusInf);Value
-nV3=item
-yI?Value(item
-yM):xC2
-lG2);Value
-nW3=item
-e61?Value(item
-tG1:xC2
-PlusInf);yJ1
-range;range.xJ2
-iP3,nV3);range.xJ2
-iP3,nW3);range.xJ2
-nU3,nV3);range.xJ2
-nU3,nW3);if(range.yN2.eB==Value::tT2)nF3=range.yN2.value;else
-nK3
-range.yO2.eB==Value::tT2)nH3=range.yO2.value;else
-nQ3
-if(!nI3&&!nJ3)xY3
-if(nI3&&nJ3&&nF3>nG3
-std::swap(nF3,nG3
-i1
-nR3
-cMod:{yD3
-x=tZ
-yP2
-y=tZ
-1));if(y
-e61){if(y
-nL3>=xG1{if(!x
-yI||(x
-yM)<xG1
-nM-y
-nL3,y
-tG1;i03
-xH1,y
-tG1;}
-cJ3!x
-e61||(x
-tG1>=xG1
-nM
-y
-nL3,-y
-tG1;i03
-y
-nL3,fp_const_negativezero
-xF());}
-}
-i03);}
-case
-cPow:{if(eI1
-xW
-i8==xG1{nM
-nM3}
-nP&&lR==xG1{nM
-xH1,xG1;}
-nP&&lJ3
-lR
-nH2
-nM
-nM3}
-if(eI1
-xW
-i8>xH1&&GetEvennessInfo(xW
-1))==iF2)l14
-eD2
-xW
-i8;yD3
-tmp=tZ
-yP2
-nS3;nI3=true;nF3=0;if(tmp
-yI&&tmp
-yM>=xG1
-nF3=t33
-tmp
-yM,tU2
-iP1
-tmp
-e61&&tmp
-nL3<=xG1
-nF3=t33
-tmp
-nL3,tU2
-nQ3
-if(tmp
-yI&&tmp
-e61){nJ3=true;nH3=fp_max(fp_abs(tmp
-yM),fp_abs(tmp
-tG1);nH3=t33
-nH3,tU2
-eE3
-nS3;}
-yD3
-tY
-xW
-yP2
-p1=tZ
-1));TriTruthValue
-p0_positivity=cN3(p0
-yM)>=xG1?iF2:(p0
-e61&&(p0
-tG1<xH1?l03
-Unknown);TriTruthValue
-cR2=GetEvennessInfo(xW
-1));TriTruthValue
-eZ=Unknown;e23
-p0_positivity
-tN1
-eZ=iF2;lC
-l03{eZ=cR2;xY3
-yF3
-e23
-cR2
-tN1
-eZ=iF2;lC
-l03
-lC
-Unknown:{if(eI1!t42
-xW
-i8)&&xW
-i8>=xG1{eZ=iF2;}
-xY3}
-c73(eZ
-tN1
-l14
-min=xH1;if
-cN3
-p1
-yI){min=t33
-p0
-yM,p1
-yM);if(p0
-yM<xH1&&(!p1
-e61||p1
-nL3>=xG1&&min>=xG1
-min=xH1;}
-if
-cN3
-p0
-yM>=xH1&&p0
-e61&&p1
-e61)l14
-max=t33
-p0
-nL3,p1
-tG1;if(min>max)std::swap(min,max);nM
-min,max);}
-nM
-min,false);}
-case
-l03{nM
-false,fp_const_negativezero
-xF());}
-yF3{xY3
-e21
-cNeg:tW3
-set_neg();tK
-cSub:yJ
-cNeg);tmp2
-tX3
-tmp
-iH
-cAdd);tmp
-tY3
-tmp
-c91
-tmp2
-i0
-cInv:{c02
-lW-1))i0
-cDiv:yJ
-cInv);tmp2
-tX3
-tmp
-iH
-xC1
-AddParamMove(tmp2
-i0
-cRad:yV
-xC1
-yA
-fp_const_rad_to_deg
-xF())i0
-cDeg:yV
-xC1
-yA
-fp_const_deg_to_rad
-xF())i0
-cSqr:{c02
-lW
-2))i0
-cExp:yV
-cPow);tmp.yA
-fp_const_e
-xF()));tmp.nJ
-0)i0
-cExp2:yV
-cPow);tmp.yA
-nX3
-tmp.nJ
-0)i0
-cCbrt:tW3
-min.set(fp_cbrt);tO
-set(fp_cbrt);tK
-cSqrt:lD
-if(m
-yI)m
-yM=(m
-yM)<xH1?0:fp_sqrt(m
-yM);if(xI2
-tO
-val=(tO
-val)<xH1?0:fp_sqrt(tO
-val);tK
-cRSqrt:{c02
-lW-0.5))i0
-cHypot:{yZ2
-xsqr,ysqr,add,sqrt;xsqr
-tY3
-xsqr.yA
-nX3
-ysqr
-tX3
-ysqr.yA
-nX3
-xsqr
-iH
-cPow);ysqr
-iH
-cPow);add
-c91
-xsqr);add
-c91
-ysqr);add
-iH
-cAdd);sqrt
-c91
-add);sqrt
-iH
-cSqrt)i1
-CalculateResultBoundaries(sqrt);}
-case
-cQ3:yJ
-cLog2);tmp2
-tY3
-tmp
-iH
-cMul);tmp
-c91
-tmp2);tmp.nJ
-1)i0
-cCot:yJ
-cTan)x6
-lH
-cSec:yJ
-cCos)x6
-lH
-cCsc:yJ
-cSin)x6
-CalculateResultBoundaries(tmp);}
-lC
-cRDiv:case
-cRSub:case
-cDup:case
-cFetch:case
-cPopNMov:case
-cSinCos:case
-cSinhCosh:case
-cNop:case
-cJump:case
-iU2:lC
-cArg:case
-cConj:case
-cImag:case
-cReal:case
-cPolar:lC
-cPCall:lC
-cFCall:xY3
-nM);}
-tK1
-TriTruthValue
-GetIntegerInfo
-iS1
-eR{e23
-t72){case
-cImmed:return
-t42
-tree
-x41)?iF2:xX3
-t83
-cFloor:case
-cCeil:case
-cTrunc:case
-cInt:return
-iF2
-t83
-cAnd:case
-cOr:case
-cNot:case
-cNotNot:case
-cEqual:case
-i51:case
-cLess:case
-cLessOrEq:case
-cGreater:case
-cGreaterOrEq:return
-iF2
-t83
-cIf:{TriTruthValue
-a=GetIntegerInfo(xW
-1));TriTruthValue
-b=GetIntegerInfo(xW
-2));if(a==b)return
-a
-xO2
-case
-cAdd:case
-cMul:{for
-l41
-if(GetIntegerInfo(xW
-a))!=iF2)return
-Unknown
-i1
-iF2;}
-yF3
-xY3
-return
-Unknown;}
-yP1
-IsLogicalValue
-iS1
-eR{e23
-t72){case
-cImmed:return
-lJ3
-tree
-x41,xG1||lJ3
-tree
-x41,e62
-1))t83
-cAnd:case
-cOr:case
-cNot:case
-cNotNot:case
-cAbsAnd:case
-cAbsOr:case
-cC3:case
-cAbsNotNot:case
-cEqual:case
-i51:case
-cLess:case
-cLessOrEq:case
-cGreater:case
-cGreaterOrEq:nZ
-cMul:{for
-l41
-if(!c83
-a))cQ
-lD2}
-case
-cIf:case
-cAbsIf:yP
-c83
-1))&&c83
-2));}
-yF3
-xY3
-return
-t23}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;
-#if defined(__x86_64) || !defined(FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS)
-# define CBRT_IS_SLOW
-#endif
-#if defined(DEBUG_POWI) || defined(DEBUG_SUBSTITUTIONS)
-#include <cstdio>
-#endif
-l33
-xK1{extern
-const
-x83
-char
-powi_table[256];}
-l33{using
-t5
-yO1
-bool
-IsOptimizableUsingPowi(long
-immed,long
-penalty=0){xK1::eP3
-synth;synth.PushVar(iU2);size_t
-bytecodesize_backup=synth.GetByteCodeSize();xK1::x01
-immed,xK1::tU1
-xF::MulSequence,c92
-size_t
-bytecode_grow_amount=synth.GetByteCodeSize()-bytecodesize_backup
-i1
-bytecode_grow_amount<size_t(MAX_POWI_BYTECODE_LENGTH-penalty);}
-xL1
-ChangeIntoRootChain(nP1
-bool
-l13,long
-tY2,long
-tZ2){while(tZ2>0
-t82
-cCbrt);t92);tmp.e33
-xD2--tZ2;}
-while(tY2>0
-t82
-cSqrt);if(l13){tmp
-iH
-cRSqrt);l13
-eW3}
-t92);tmp.e33
-xD2--tY2;}
-if(l13
-t82
-cInv);t92
-xD2}
-}
-tK1
-e72
-RootPowerTable{static
-const
-Value_t
-RootPowers[(1+4)*(1+3)];}
-yO1
-const
-Value_t
-t9(1+4)*(1+3)]={e62
-1)lS
-2)lS
-2*2)lS
-2*2*2)lS
-2*2*2*2)lS
-3)lS
-3*2)lS
-3*2*2)lS
-3*2*2*2)lS
-3*2*2*2*2)lS
-3*3)lS
-3*3*2
-yG3
-yG3*2
-yG3*2*2)lS
-3*3*3
-eY2
-eY2*2
-eY2*2*2
-eY2*2*2*2)}
-;e72
-PowiResolver{static
-const
-x83
-MaxSep=4;static
-x03
-i13=5;typedef
-int
-cO3;typedef
-long
-x43;typedef
-long
-tP;e72
-yS2{yS2():n_int_sqrt(0),n_int_cbrt(0),sep_list(),n01(0){}
-int
-n_int_sqrt;int
-n_int_cbrt;int
-tT1
-MaxSep];tP
-n01;}
-yO1
-static
-yS2
-CreatePowiResult
-cX3
-exponent){yS2
-nS3;cO3
-tA=FindIntegerFactor(tU2
-if(tA==0){
-#ifdef DEBUG_POWI
-i02"no factor found for %Lg\n"
-,(cP3);
-#endif
-return
-nS3;}
-nS3.n01=y31
-exponent,tA);x43
-eT2=EvaluateFactorCost(tA,0,0,0)+cC
-nS3.n01);int
-s_count=0;int
-i23=0;int
-nZ3=0;
-#ifdef DEBUG_POWI
-i02"orig = %Lg\n"
-,(cP3);i02"plain factor = "
-iL3"%ld\n"
-,(int)tA,(long)eT2);
-#endif
-for
-lT1
-n_s=0;n_s<MaxSep;++n_s){int
-xD=0;x43
-yK1=eT2;cO3
-yX1=tA;for(int
-s=1;s<i13*4;++s){
-#ifdef CBRT_IS_SLOW
-if(s>=i13)break;
-#endif
-int
-n_sqrt=s%i13;int
-n_cbrt=s/i13;if(n_sqrt+n_cbrt>4)yA1
-Value_t
-lN1=exponent;lN1-=t9
-s];iE1=FindIntegerFactor(lN1);if(xT2!=0){tP
-xN=y31
-lN1,xT2);x43
-cost=EvaluateFactorCost(xT2,s_count+n_sqrt,i23+n_cbrt,nZ3+1)+cC
-xN);
-#ifdef DEBUG_POWI
-i02"Candidate sep %u (%d*sqrt %d*cbrt)factor = "
-iL3"%ld (for %Lg to %ld)\n"
-,s,n_sqrt,n_cbrt,xT2,(long)cost
-cX2
-lN1,(long)xN);
-#endif
-if(cost<yK1){xD=s;yX1=xT2;yK1=cost;}
-}
-}
-if(!xD)break;
-#ifdef DEBUG_POWI
-i02"CHOSEN sep %u (%d*sqrt %d*cbrt)factor = "
-iL3"%ld, exponent %Lg->%Lg\n"
-,xD,xD%i13,xD/i13,yX1,yK1
-cX2(exponent)cX2(exponent-t9
-xD]));
-#endif
-nS3.tT1
-n_s]=xD
-eX3-=t9
-xD];s_count+=xD%i13;i23+=xD/i13;eT2=yK1;tA=yX1;nZ3+=1;}
-nS3.n01=y31
-exponent,tA);
-#ifdef DEBUG_POWI
-i02"resulting exponent is %ld (from exponent=%Lg, best_factor=%Lg)\n"
-,nS3.n01,(cP3
-cX2
-tA);
-#endif
-while(tA%2==0){++nS3
-e52;tA/=2;}
-while(tA%3==0){++nS3.n_int_cbrt;tA/=3;eE3
-nS3;}
-private:static
-x43
-cC
-tP
-xN){static
-std::map
-cS2
-iM;if(xN<0){x43
-cost=22
-i1
-cost+cC-xN);}
-std::map
-cS2::y83
-i=iM.xU2
-xN);if(i!=iM.cX1
-xN)return
-i
-eC2;std::pair
-cS2
-nS3(xN,0.0);x43&cost=nS3.i63
-while(xN>1){int
-xT2=0;if(xN<256){xT2=xK1::powi_table[xN];if(xT2&128)xT2&=127;else
-xT2=0;if(xT2&64)xT2=-(xT2&63)-1;}
-if(xT2){cost+=cC
-xT2);xN/=xT2;yA1}
-if(!(xN&1)){xN/=2;cost+=6;}
-else{cost+=7;xN-=1;}
-}
-iM.y43,nS3)i1
-cost;}
-cB1
-tP
-y31
-yL1,iE1)yP
-makeLongInteger(value*e62
-xT2));}
-cB1
-bool
-yM1
-yL1,iE1)l14
-v=value*e62
-xT2)i1
-isLongInteger(v);}
-cB1
-cO3
-FindIntegerFactor(yL1){iE1=(2*2*2*2);
-#ifdef CBRT_IS_SLOW
-#else
-xT2*=(3*3*3);
-#endif
-cO3
-nS3=0;if(yM1
-value,xT2)){nS3=xT2;while((xT2%2)==0&&yM1
-value,xT2/2))nS3=xT2/=2;while((xT2%3)==0&&yM1
-value,xT2/3))nS3=xT2/=3;}
-#ifdef CBRT_IS_SLOW
-if(nS3==0){if(yM1
-value,3
-y03
-3;}
-#endif
-return
-nS3;}
-static
-int
-EvaluateFactorCost(int
-xT2,int
-s,int
-c,int
-nmuls){x03
-x13=6;
-#ifdef CBRT_IS_SLOW
-x03
-eU2=25;
-#else
-x03
-eU2=8;
-#endif
-int
-nS3=s*x13+c*eU2;while(xT2%2==0){xT2/=2;nS3+=x13;}
-while(xT2%3==0){xT2/=3;nS3+=eU2;}
-nS3+=nmuls
-i1
-nS3;}
-}
-;}
-t5{yP1
-yZ2::RecreateInversionsAndNegations(bool
-prefer_base2){bool
-changed=false
-e73
-0;a<l91++a)if(lX1.RecreateInversionsAndNegations(prefer_base2))yS1
-if(changed){exit_changed:Mark_Incompletely_Hashed(yQ2
-e23
-l92{case
-cMul:{eK
-nE2
-tX
-nF2,cR1;if(true){bool
-nK1=false
-iK2
-xE2=0
-e73
-tI1
-i12
-tI
-0)i22
-tI
-1)tD1){nK1=true;xE2=tI
-i8;xY3}
-if(nK1)l14
-immeds=1.0
-e73
-tI1
-tD1){immeds*=powgroup
-x41;yN1}
-for
-iZ1
-a=l91
-a-->0;nQ&powgroup=lX1;if(powgroup
-i12
-tI
-0)i22
-tI
-1)tD1
-nQ&log2=tI
-0);log2.lD1
-log2
-iH
-cQ3);log2.yA
-t33
-immeds,e62
-1)/xE2)));log2
-iW1;xY3}
-}
-}
-for
-iZ1
-a=tI1
-i12
-tI
-1)tD1){iT1&exp_param=tI
-1)iK2
-eD2
-exp_param
-x41;if(cZ1,nU2)){lD1
-nE2
-c52
-lX1
-c43
-yN1
-iP1
-exponent<xH1&&t42
-exponent)nQ
-iV;iV
-iH
-cPow);iV
-cS
-tI
-0));iV.yA-exponent));iV
-iW1;nE2
-c52
-iV);lD1
-yN1}
-iP1
-powgroup
-i22!nF2.nX2){nF2=tI
-0);lD1
-yN1
-iP1
-powgroup
-nC==cQ3&&!cR1.nX2){cR1=powgroup;lD1
-yN1}
-if(!nE2
-eU3){changed=true
-tX
-cF1;cF1
-iH
-cMul);cF1
-iF1
-nE2);cF1
-iW1
-tX
-iG
-cMul);cA1
-SetParamsMove
-eM
-if(cA1
-IsImmed()&&fp_equal
-eH2
-x41
-nH2
-eL3
-cInv)tN
-cF1);}
-cJ3
-cA1
-GetDepth()>=cF1
-nP2
-tC2
-cDiv
-iG1
-tN
-cF1);}
-else{eL3
-cRDiv)tN
-cF1
-iG1;}
-}
-}
-if(nF2.nX2
-nQ
-iG
-l92;cA1
-SetParamsMove
-eM
-while(cA1
-RecreateInversionsAndNegations(prefer_base2))cA1
-tE3;eL3
-cQ3)tN
-nF2
-iG1;yS1}
-if(cR1.nX2
-nQ
-iG
-cMul);mulgroup
-c91
-cR1
-l8
-1));cA1
-AddParamsMove
-eM
-while(cA1
-RecreateInversionsAndNegations(prefer_base2))cA1
-tE3;DelParams();eL3
-cQ3)tN
-cR1
-l8
-0)iG1;yS1
-e21
-cAdd:{eK
-i32
-e73
-l91
-a-->0;)if(eY3
-cMul){nG2
-y41:tX&mulgroup=cT2
-for
-iZ1
-b=cA1
-l91
-b-->0;){if
-eH2
-l8
-b).lV1
-xT2=mulgroup
-l8
-b)x41;lG3
-xT2
-xU
-y41;}
-cA1
-lD1
-cA1
-i91
-b
-tA2
-iP1
-lJ3
-xT2,e62-2)))eN
-y41;}
-cA1
-lD1
-cA1
-i91
-b);cA1
-yA
-e62
-2))tA2}
-}
-if(t0){cA1
-tB
-mulgroup);yN1}
-iP1
-eY3
-cDiv&&!IsIntType
-xF::nS3){nG2
-y51:tX&cF1=cT2
-if(cF1
-l8
-0)tD1){lG3
-cF1
-l8
-0)x41
-xU
-y51;}
-cF1.lD1
-cF1.i91
-0);cF1
-iH
-cInv
-tA2}
-if(t0)eN
-y51;}
-cF1.tB
-cF1);yN1}
-iP1
-eY3
-cRDiv&&!IsIntType
-xF::nS3){nG2
-xD1:tX&cF1=cT2
-if(cF1
-l8
-1)tD1){lG3
-cF1
-l8
-i8
-xU
-xD1;}
-cF1.lD1
-cF1.i91
-1);cF1
-iH
-cInv
-tA2}
-if(t0)eN
-xD1;}
-cF1.tB
-cF1);yN1}
-if(!i32
-eU3){
-#ifdef DEBUG_SUBSTITUTIONS
-i02"Will make a Sub conversion in:\n"
-);fflush(stdout);l21
-#endif
-yZ2
-yT2;yT2
-iH
-cAdd);yT2
-iF1
-i32);yT2
-iW1
-tX
-cS1;cS1
-iH
-cAdd);cS1
-iF1
-lJ2));cS1
-iW1;if(cS1
-tD1&&lJ3
-cS1
-x41,xG1
-tC2
-cNeg);eC);}
-cJ3
-cS1
-nP2==1
-tC2
-cRSub);eC)eV3}
-iP1
-yT2
-nC==cAdd
-tC2
-cSub)eV3
-eC
-l8
-0)iY1
-1;a<yT2.l91++a
-nQ
-eV2;eV2
-iH
-cSub);eV2
-iF1
-lJ2));eV2.yC2)tN
-eV2);eC
-n93}
-}
-else{eL3
-cSub)eV3
-eC);}
-}
-#ifdef DEBUG_SUBSTITUTIONS
-i02"After Sub conversion:\n"
-);fflush(stdout);l21
-#endif
-e21
-cPow:{iT1&p0
-i42
-0);iT1&p1
-i42
-1);if(p1
-tD1){if(p1
-x41!=xH1&&!t42
-p1
-x41)){eG
-yS2
-r=eG
-CreatePowiResult(fp_abs
-cR3);if(r.n01!=0){bool
-lH2
-eW3
-if(p1
-x41<xH1&&r.tT1
-0]==0&&r
-e52>0){lH2=true;}
-#ifdef DEBUG_POWI
-i02"Will resolve powi %Lg as powi(chain(%d,%d),%ld)"
-cX2
-fp_abs
-cR3,r
-e52,r.n_int_cbrt,r.n01);for
-lT1
-n=0;n<eG
-MaxSep;++n){if(r
-i52==0)break;int
-n_sqrt=r
-i52%eG
-i13;int
-n_cbrt=r
-i52/eG
-i13;i02"*chain(%d,%d)"
-,n_sqrt,n_cbrt);}
-i02"\n"
-);
-#endif
-yZ2
-cU2
-i42
-0)tX
-yU2=cU2;yU2.lD1
-ChangeIntoRootChain(yU2,lH2,r
-e52,r.n_int_cbrt);yU2
-iW1
-tX
-pow;if(r.n01!=1){pow
-iH
-cPow);pow
-c91
-yU2);pow.yA
-e62
-r.n01)));}
-else
-pow.swap(yU2)tX
-mul;mul
-iH
-cMul);mul
-c91
-pow);for
-lT1
-n=0;n<eG
-MaxSep;++n){if(r
-i52==0)break;int
-n_sqrt=r
-i52%eG
-i13;int
-n_cbrt=r
-i52/eG
-i13
-tX
-eW2=cU2;eW2.lD1
-ChangeIntoRootChain(eW2,false,n_sqrt,n_cbrt);eW2
-iW1;mul
-c91
-eW2);}
-if(p1
-x41<xH1&&!lH2){mul
-iW1;eL3
-cInv);nB1
-0,mul);i91
-1);}
-else{eL3
-cMul);SetParamsMove(mul.lJ2));}
-#ifdef DEBUG_POWI
-l21
-#endif
-yS1
-xY3}
-}
-if(GetOpcode()==cPow&&(!p1
-tD1||!isLongInteger
-cR3||!IsOptimizableUsingPowi
-xF(makeLongInteger
-cR3))){if(p0
-tD1&&p0
-x41>e62
-0.0)){if(prefer_base2)l14
-yV2=fp_log2(p0
-x41);lG3
-yV2
-nH2
-i91
-0);}
-else{n0
-eA1
-yV2))eX3
-cS
-p1
-t81
-nB1
-t1}
-eL3
-cExp2);yS1}
-else
-l14
-yV2=fp_log(p0
-x41);lG3
-yV2
-nH2
-i91
-0);}
-else{n0
-eA1
-yV2))eX3
-cS
-p1
-t81
-nB1
-t1}
-eL3
-cExp);yS1}
-}
-iP1
-GetPositivityInfo(p0)==iF2){if(prefer_base2
-nQ
-log;log
-iH
-cLog2);log
-cS
-p0);log
-iW1;n0
-p1)eX3
-c91
-log
-t81
-eL3
-cExp2);nB1
-t1
-yS1}
-else{yZ2
-log;log
-iH
-cLog);log
-cS
-p0);log
-iW1;n0
-p1)eX3
-c91
-log
-t81
-eL3
-cExp);nB1
-t1
-yS1}
-}
-e21
-cDiv:{if(GetParam(0)tD1&&lJ3
-GetParam(0)x41
-nH2
-eL3
-cInv);i91
-0);}
-xY3
-yF3
-xY3
-if(changed)goto
-exit_changed
-i1
-changed;}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{using
-t5;class
-eF3{size_t
-nL1;size_t
-eH;size_t
-eI;size_t
-lO1;size_t
-t3;size_t
-t4;size_t
-n71;e43
-eF3():nL1(0),eH(0),eI(0),lO1(0),t3(0),t4(0),n71(0){}
-void
-i43
-OPCODE
-op){nL1+=1
-i33
-cCos)++eH
-i33
-cSin)++eI
-i33
-cSec)++eH
-i33
-cCsc)++eI
-i33
-cTan)++lO1
-i33
-cCot)++lO1
-i33
-cSinh)++t4
-i33
-cCosh)++t3
-i33
-cTanh)++n71;}
-size_t
-GetCSEscore()const{size_t
-nS3=nL1
-i1
-nS3;}
-int
-NeedsSinCos()const{bool
-y61=(nL1==(eH+eI+lO1));if((lO1&&(eI||eH))||(eI&&eH)){if(y61)return
-1
-i1
-2;eE3
-0;}
-int
-NeedsSinhCosh()const{bool
-y61=(nL1==(t3+t4+n71));if((n71&&(t4||t3))||(t4&&t3)){if(y61)return
-1
-i1
-2;eE3
-0;}
-size_t
-MinimumDepth()const{size_t
-n_sincos=std::min(eH,eI);size_t
-n_sinhcosh=std::min(t3,t4);if(n_sincos==0&&n_sinhcosh==0)return
-2
-i1
-1;}
-}
-yO1
-class
-TreeCountType:public
-std::multimap<fphash_t,std::pair<eF3,yZ2> >{}
-;xL1
-FindTreeCounts(tJ1&nI2,const
-nP1
-OPCODE
-xF2,bool
-skip_root=false){cX
-i=nI2.xU2
-nJ2);if(!skip_root){bool
-found
-eW3
-for(;i!=nI2.cX1
-nJ2;++i){if(tree
-xI
-i
-eC2.second)){i
-eC2.first.i43
-xF2);found=true;xY3}
-if(!found){eF3
-count;count.i43
-xF2);nI2.y43,std::make_pair(nJ2,std::make_pair
-cW3
-cU3)));}
-}
-x51
-FindTreeCounts(nI2,xW
-a),t72);}
-e72
-yW{bool
-BalanceGood;bool
-FoundChild;}
-yO1
-yW
-lP1
-iT1&root,iT1&cS3{if(root
-xI
-cS3){yW
-nS3={true,true}
-i1
-nS3;}
-yW
-nS3={true,false}
-;if(root
-nC==cIf||root
-nC==t03{yW
-cond=lP1
-root
-l8
-0),cS3;yW
-xV=lP1
-root
-l8
-1),cS3;yW
-y4=lP1
-root
-l8
-2),cS3;if
-l23||xV
-yX||y4
-yX){nS3
-yX=true;}
-nS3
-eD=((xV
-yX==y4
-yX)||l23
-i62)&&(cond
-eD||(xV
-yX&&y4
-yX))&&(xV
-eD||l23
-i62)&&(y4
-eD||l23
-i62);}
-else{bool
-iH1
-eW3
-bool
-nM1=false
-eK3
-b=root.GetParamCount(),a=0;a<b;++a){yW
-tmp=lP1
-root
-l8
-a),cS3;if(tmp
-yX)nS3
-yX=true;if(tmp
-eD==false)iH1=true;iP1
-tmp
-yX)nM1=true;}
-if(iH1&&!nM1)nS3
-eD
-eW3
-eE3
-nS3;}
-yP1
-cW2
-iR1
-i53
-const
-nP1
-const
-xK1::eP3&synth,const
-tJ1&nI2){for
-iZ1
-b=tree.GetParamCount(),a=0;a<b;++a){iT1&leaf=xW
-a);cX
-synth_it;for(x93
-tJ1::const_iterator
-i=nI2.y73
-i!=nI2.end();++i){if(i->first!=leaf.GetHash())yA1
-const
-eF3&occ
-nY2
-first;size_t
-score=occ.GetCSEscore();iT1&candidate
-nY2
-i63
-if(lF2
-candidate))yA1
-if(leaf
-nP2<occ.MinimumDepth())yA1
-if(score<2)yA1
-if(lP1
-i53
-leaf)eD==false)continue
-l43
-if(cW2(i53
-leaf,synth,nI2))lD2
-eE3
-t23
-yP1
-iI1
-iT1&y53,iT1&expr){yY1
-y53
-lF3
-expr))lD2
-yY1
-iI1
-y53
-l8
-a),expr
-y03
-true
-i1
-t23
-yP1
-GoodMomentForCSE
-iR1
-y53,iT1&expr){if(y53
-nC==cIf)lD2
-yY1
-y53
-lF3
-expr))lD2
-size_t
-i72=0;yY1
-iI1
-y53
-l8
-a),expr))++i72
-i1
-i72!=1;}
-}
-t5{tK1
-size_t
-yZ2::SynthCommonSubExpressions(xK1::xI1
-const{if(e91
-0)return
-0;size_t
-stacktop_before=synth.GetStackTop();tJ1
-nI2;FindTreeCounts(nI2,*this,GetOpcode(),true);for(;;){size_t
-yW2=0;
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<"Finding a CSE candidate, root is:"
-<<std::y11*this);
-#endif
-cX
-cs_it(nI2.end());for(cX
-j=nI2.y73
-j!=nI2.end();){cX
-i(j++);const
-eF3&occ
-nY2
-first;size_t
-score=occ.GetCSEscore();iT1&tree
-nY2
-i63
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<"Score "
-<<score<<":\n"
-<<std::flush;DumpTreeWithIndent(tree);
-#endif
-if(lF2
-tree))xZ
-if(tree
-nP2<occ.MinimumDepth())xZ
-if(score<2)xZ
-if(lP1*this
-cU3)eD==false)xZ
-if(cW2(*this
-cU3,synth,nI2)){yA1}
-if(!GoodMomentForCSE(*this
-cU3))xZ
-score*=tree
-nP2;if(score>yW2){yW2=score;cs_it=i;}
-}
-if(yW2<=0){
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<"No more CSE candidates.\n"
-<<std::flush;
-#endif
-xY3
-iT1&tree=cs_it
-eC2.i63
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<iX3"Common Subexpression:"
-;DumpTree
-xF(tree
-lE2
-std::endl;
-#endif
-#if 0
-int
-n11=occ.NeedsSinCos();int
-i9=occ.NeedsSinhCosh()tX
-i82,i92,yX2,yY2;if(n11){i82
-eX2
-i82
-iH
-cSin);i82
-iW1;i92
-eX2
-i92
-iH
-cCos);i92
-iW1;if(lF2
-i82)||lF2
-i92))i73==2){nI2.xG2
-yA1}
-n11=0;}
-}
-if(i9){yX2
-eX2
-yX2
-iH
-cSinh);yX2
-iW1;yY2
-eX2
-yY2
-iH
-cCosh);yY2
-iW1;if(lF2
-yX2)||lF2
-yY2)){if(i9==2){nI2.xG2
-yA1}
-i9=0;}
-}
-#endif
-tree.SynthesizeByteCode(synth,false);nI2.xG2
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-synth.x73
-Dump<0>(lE2"Done with Common Subexpression:"
-;DumpTree
-xF(tree
-lE2
-std::endl;
-#endif
-#if 0
-if(n11)i73==2||i9){synth.eL1}
-yB1
-cSinCos,1,2)yC1
-i82,1)yC1
-i92,0);}
-if(i9)i73)synth.eL1
-if(i9==2){synth.eL1}
-yB1
-cSinhCosh,1,2)yC1
-yX2,1)yC1
-yY2,0);}
-#endif
-eE3
-xV3
-stacktop_before;}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-tK1
-lU1
-xF::iA2{using
-t5;CopyOnWrite()tX
-tree;tree.GenerateFrom(*mData);FPoptimizer_Optimize::ApplyGrammars(tree);eO3
-x83>cT3;std
-xM3
-xF
-immed;size_t
-stacktop_max=0;tree.SynthesizeByteCode(cT3,immed,stacktop_max);if(mData->mStackSize!=stacktop_max){mData->mStackSize=x83(stacktop_max);
-#if !defined(FP_USE_THREAD_SAFE_EVAL) && \
- !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
-mData->mStack
-xF3
-stacktop_max);
-#endif
-}
-mData->mByteCode.swap(cT3);mData->mImmed.swap(immed);}
-#define FUNCTIONPARSER_INSTANTIATE_EMPTY_OPTIMIZE(type) tP1>lU1<type>::iA2{}
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-i93(MpfrFloat)
-#endif
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-i93(GmpInt)
-#endif
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-i93(std::complex<double>)
-#endif
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
-i93(std::complex<float>)
-#endif
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-i93(std::complex<long
-double>)
-#endif
-#define FUNCTIONPARSER_INSTANTIATE_OPTIMIZE(type) x73 lU1<type>::iA2;
-#ifndef FP_DISABLE_DOUBLE_TYPE
-iA3(double)
-#endif
-#ifdef FP_SUPPORT_FLOAT_TYPE
-iA3(float)
-#endif
-#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
-iA3(long
-double)
-#endif
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-iA3(long)
-#endif
-#endif // FP_SUPPORT_OPTIMIZER
-
-#endif
+++ /dev/null
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
+++ /dev/null
-#include "GmpInt.hh"
-#include <gmp.h>
-#include <deque>
-#include <vector>
-#include <cstring>
-#include <cctype>
-
-//===========================================================================
-// Shared data
-//===========================================================================
-namespace
-{
- unsigned long gIntDefaultNumberOfBits = 256;
-
- std::vector<char>& intString()
- {
- static std::vector<char> str;
- return str;
- }
-}
-
-//===========================================================================
-// Auxiliary structs
-//===========================================================================
-struct GmpInt::GmpIntData
-{
- unsigned mRefCount;
- GmpIntData* nextFreeNode;
- mpz_t mInteger;
-
- GmpIntData(): mRefCount(1), nextFreeNode(0) {}
-};
-
-class GmpInt::GmpIntDataContainer
-{
- std::deque<GmpInt::GmpIntData> mData;
- GmpInt::GmpIntData* mFirstFreeNode;
- GmpInt::GmpIntData* mConst_0;
-
- public:
- GmpIntDataContainer(): mFirstFreeNode(0), mConst_0(0) {}
-
- ~GmpIntDataContainer()
- {
- for(size_t i = 0; i < mData.size(); ++i)
- mpz_clear(mData[i].mInteger);
- }
-
- GmpInt::GmpIntData* allocateGmpIntData(unsigned long numberOfBits,
- bool initToZero)
- {
- if(mFirstFreeNode)
- {
- GmpInt::GmpIntData* node = mFirstFreeNode;
- mFirstFreeNode = node->nextFreeNode;
- if(initToZero) mpz_set_si(node->mInteger, 0);
- ++(node->mRefCount);
- return node;
- }
-
- mData.push_back(GmpInt::GmpIntData());
- if(numberOfBits > 0)
- mpz_init2(mData.back().mInteger, numberOfBits);
- else
- mpz_init(mData.back().mInteger);
- return &mData.back();
- }
-
- void releaseGmpIntData(GmpIntData* data)
- {
- if(--(data->mRefCount) == 0)
- {
- data->nextFreeNode = mFirstFreeNode;
- mFirstFreeNode = data;
- }
- }
-
- GmpInt::GmpIntData* const_0()
- {
- if(!mConst_0)
- mConst_0 = allocateGmpIntData(gIntDefaultNumberOfBits, true);
- return mConst_0;
- }
-};
-
-
-GmpInt::GmpIntDataContainer& GmpInt::gmpIntDataContainer()
-{
- static GmpIntDataContainer container;
- return container;
-}
-
-//===========================================================================
-// Auxiliary functions
-//===========================================================================
-void GmpInt::setDefaultNumberOfBits(unsigned long value)
-{
- gIntDefaultNumberOfBits = value;
-}
-
-unsigned long GmpInt::getDefaultNumberOfBits()
-{
- return gIntDefaultNumberOfBits;
-}
-
-inline void GmpInt::copyIfShared()
-{
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- GmpIntData* oldData = mData;
- mData = gmpIntDataContainer().allocateGmpIntData(0, false);
- mpz_set(mData->mInteger, oldData->mInteger);
- }
-}
-
-
-//===========================================================================
-// Constructors, destructor, assignment
-//===========================================================================
-GmpInt::GmpInt(DummyType):
- mData(gmpIntDataContainer().allocateGmpIntData(0, false))
-{}
-
-GmpInt::GmpInt()
-{
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
-}
-
-GmpInt::GmpInt(long value)
-{
- if(value == 0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_si(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(unsigned long value)
-{
- if(value == 0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_ui(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(int value)
-{
- if(value == 0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_si(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(double value)
-{
- const double absValue = value >= 0.0 ? value : -value;
- if(absValue < 1.0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_d(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(long double value)
-{
- const long double absValue = value >= 0.0L ? value : -value;
- if(absValue < 1.0L)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_d(mData->mInteger, double(value));
- }
-}
-
-GmpInt::GmpInt(const GmpInt& rhs):
- mData(rhs.mData)
-{
- ++(mData->mRefCount);
-}
-
-GmpInt& GmpInt::operator=(const GmpInt& rhs)
-{
- if(mData != rhs.mData)
- {
- gmpIntDataContainer().releaseGmpIntData(mData);
- mData = rhs.mData;
- ++(mData->mRefCount);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator=(signed long value)
-{
- if(value == 0)
- {
- gmpIntDataContainer().releaseGmpIntData(mData);
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- }
- mpz_set_si(mData->mInteger, value);
- }
- return *this;
-}
-
-GmpInt::~GmpInt()
-{
- gmpIntDataContainer().releaseGmpIntData(mData);
-}
-
-
-//===========================================================================
-// Data getters
-//===========================================================================
-template<>
-void GmpInt::get_raw_mpfr_data<mpz_t>(mpz_t& dest_mpz_t)
-{
- std::memcpy(&dest_mpz_t, mData->mInteger, sizeof(mpz_t));
-}
-
-const char* GmpInt::getAsString(int base) const
-{
- intString().resize(mpz_sizeinbase(mData->mInteger, base) + 2);
- return mpz_get_str(&intString()[0], base, mData->mInteger);
-}
-
-long GmpInt::toInt() const
-{
- return mpz_get_si(mData->mInteger);
-}
-
-
-//===========================================================================
-// Modifying operators
-//===========================================================================
-GmpInt& GmpInt::operator+=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_add(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator+=(long value)
-{
- copyIfShared();
- if(value >= 0)
- mpz_add_ui(mData->mInteger, mData->mInteger, value);
- else
- mpz_sub_ui(mData->mInteger, mData->mInteger, -value);
- return *this;
-}
-
-GmpInt& GmpInt::operator-=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_sub(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator-=(long value)
-{
- copyIfShared();
- if(value >= 0)
- mpz_sub_ui(mData->mInteger, mData->mInteger, value);
- else
- mpz_add_ui(mData->mInteger, mData->mInteger, -value);
- return *this;
-}
-
-GmpInt& GmpInt::operator*=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_mul(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator*=(long value)
-{
- copyIfShared();
- mpz_mul_si(mData->mInteger, mData->mInteger, value);
- return *this;
-}
-
-GmpInt& GmpInt::operator/=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_tdiv_q(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator/=(long value)
-{
- copyIfShared();
- if(value >= 0)
- mpz_tdiv_q_ui(mData->mInteger, mData->mInteger, value);
- else
- {
- mpz_neg(mData->mInteger, mData->mInteger);
- mpz_tdiv_q_ui(mData->mInteger, mData->mInteger, -value);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator%=(const GmpInt& rhs)
-{
- copyIfShared();
- if(operator<(0))
- {
- negate();
- mpz_mod(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- negate();
- }
- else
- {
- mpz_mod(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator%=(long value)
-{
- copyIfShared();
- if(value < 0) value = -value;
- if(operator<(0))
- {
- negate();
- mpz_mod_ui(mData->mInteger, mData->mInteger, value);
- negate();
- }
- else
- {
- mpz_mod_ui(mData->mInteger, mData->mInteger, value);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator<<=(unsigned long bits)
-{
- copyIfShared();
- mpz_mul_2exp(mData->mInteger, mData->mInteger, bits);
- return *this;
-}
-
-GmpInt& GmpInt::operator>>=(unsigned long bits)
-{
- copyIfShared();
- mpz_tdiv_q_2exp(mData->mInteger, mData->mInteger, bits);
- return *this;
-}
-
-
-//===========================================================================
-// Modifying functions
-//===========================================================================
-void GmpInt::addProduct(const GmpInt& value1, const GmpInt& value2)
-{
- copyIfShared();
- mpz_addmul(mData->mInteger, value1.mData->mInteger, value2.mData->mInteger);
-}
-
-void GmpInt::addProduct(const GmpInt& value1, unsigned long value2)
-{
- copyIfShared();
- mpz_addmul_ui(mData->mInteger, value1.mData->mInteger, value2);
-}
-
-void GmpInt::subProduct(const GmpInt& value1, const GmpInt& value2)
-{
- copyIfShared();
- mpz_submul(mData->mInteger, value1.mData->mInteger, value2.mData->mInteger);
-}
-
-void GmpInt::subProduct(const GmpInt& value1, unsigned long value2)
-{
- copyIfShared();
- mpz_submul_ui(mData->mInteger, value1.mData->mInteger, value2);
-}
-
-void GmpInt::negate()
-{
- copyIfShared();
- mpz_neg(mData->mInteger, mData->mInteger);
-}
-
-void GmpInt::abs()
-{
- copyIfShared();
- mpz_abs(mData->mInteger, mData->mInteger);
-}
-
-GmpInt GmpInt::abs(const GmpInt& value)
-{
- GmpInt retval(kNoInitialization);
- mpz_abs(retval.mData->mInteger, value.mData->mInteger);
- return retval;
-}
-
-
-//===========================================================================
-// Non-modifying operators
-//===========================================================================
-GmpInt GmpInt::operator+(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_add(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator+(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value >= 0)
- mpz_add_ui(retval.mData->mInteger, mData->mInteger, value);
- else
- mpz_sub_ui(retval.mData->mInteger, mData->mInteger, -value);
- return retval;
-}
-
-GmpInt GmpInt::operator-(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_sub(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator-(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value >= 0)
- mpz_sub_ui(retval.mData->mInteger, mData->mInteger, value);
- else
- mpz_add_ui(retval.mData->mInteger, mData->mInteger, -value);
- return retval;
-}
-
-GmpInt GmpInt::operator*(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_mul(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator*(long value) const
-{
- GmpInt retval(kNoInitialization);
- mpz_mul_si(retval.mData->mInteger, mData->mInteger, value);
- return retval;
-}
-
-GmpInt GmpInt::operator/(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_tdiv_q(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator/(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value >= 0)
- mpz_tdiv_q_ui(retval.mData->mInteger, mData->mInteger, value);
- else
- {
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- mpz_tdiv_q_ui(retval.mData->mInteger, retval.mData->mInteger, -value);
- }
- return retval;
-}
-
-GmpInt GmpInt::operator%(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- if(operator<(0))
- {
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- mpz_mod(retval.mData->mInteger,
- retval.mData->mInteger, rhs.mData->mInteger);
- retval.negate();
- }
- else
- {
- mpz_mod(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- }
- return retval;
-}
-
-GmpInt GmpInt::operator%(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value < 0) value = -value;
- if(operator<(0))
- {
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- mpz_mod_ui(retval.mData->mInteger, retval.mData->mInteger, value);
- retval.negate();
- }
- else
- {
- mpz_mod_ui(retval.mData->mInteger, mData->mInteger, value);
- }
- return retval;
-}
-
-GmpInt GmpInt::operator-() const
-{
- GmpInt retval(kNoInitialization);
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator<<(unsigned long bits) const
-{
- GmpInt retval(kNoInitialization);
- mpz_mul_2exp(retval.mData->mInteger, mData->mInteger, bits);
- return retval;
-}
-
-GmpInt GmpInt::operator>>(unsigned long bits) const
-{
- GmpInt retval(kNoInitialization);
- mpz_tdiv_q_2exp(retval.mData->mInteger, mData->mInteger, bits);
- return retval;
-}
-
-
-//===========================================================================
-// Comparison operators
-//===========================================================================
-bool GmpInt::operator<(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) < 0;
-}
-
-bool GmpInt::operator<(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) < 0;
-}
-
-bool GmpInt::operator<=(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) <= 0;
-}
-
-bool GmpInt::operator<=(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) <= 0;
-}
-
-bool GmpInt::operator>(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) > 0;
-}
-
-bool GmpInt::operator>(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) > 0;
-}
-
-bool GmpInt::operator>=(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) >= 0;
-}
-
-bool GmpInt::operator>=(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) >= 0;
-}
-
-bool GmpInt::operator==(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) == 0;
-}
-
-bool GmpInt::operator==(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) == 0;
-}
-
-bool GmpInt::operator!=(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) != 0;
-}
-
-bool GmpInt::operator!=(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) != 0;
-}
-
-void GmpInt::parseValue(const char* value)
-{
- mpz_set_str(mData->mInteger, value, 10);
-}
-
-void GmpInt::parseValue(const char* value, char** endptr)
-{
- static std::vector<char> str;
-
- unsigned startIndex = 0;
- while(value[startIndex] && std::isspace(value[startIndex])) ++startIndex;
- if(!value[startIndex]) { *endptr = const_cast<char*>(value); return; }
-
- unsigned endIndex = startIndex;
- if(value[endIndex] == '-') ++endIndex;
- if(!std::isdigit(value[endIndex]))
- { *endptr = const_cast<char*>(value); return; }
- if(value[endIndex] == '0' && value[endIndex+1] == 'x')
- {
- endIndex += 1;
- while(std::isxdigit(value[++endIndex])) {}
- }
- else
- {
- while(std::isdigit(value[++endIndex])) {}
- }
-
- str.reserve(endIndex - startIndex + 1);
- str.assign(value + startIndex, value + endIndex);
- str.push_back(0);
-
- mpz_set_str(mData->mInteger, &str[0], 0);
- *endptr = const_cast<char*>(value + endIndex);
-}
-
-GmpInt GmpInt::parseString(const char* str, char** endptr)
-{
- GmpInt retval(kNoInitialization);
- retval.parseValue(str, endptr);
- return retval;
-}
-
-//===========================================================================
-// Operator functions
-//===========================================================================
-GmpInt operator+(long lhs, const GmpInt& rhs)
-{
- GmpInt retval(GmpInt::kNoInitialization);
- if(lhs >= 0)
- mpz_add_ui(retval.mData->mInteger, rhs.mData->mInteger, lhs);
- else
- mpz_sub_ui(retval.mData->mInteger, rhs.mData->mInteger, -lhs);
- return retval;
-}
-
-GmpInt operator-(long lhs, const GmpInt& rhs)
-{
- GmpInt retval(GmpInt::kNoInitialization);
- if(lhs >= 0)
- mpz_ui_sub(retval.mData->mInteger, lhs, rhs.mData->mInteger);
- else
- {
- mpz_add_ui(retval.mData->mInteger, rhs.mData->mInteger, -lhs);
- mpz_neg(retval.mData->mInteger, retval.mData->mInteger);
- }
- return retval;
-}
-
-GmpInt operator*(long lhs, const GmpInt& rhs)
-{
- return rhs * lhs;
-}
-
-GmpInt operator/(long lhs, const GmpInt& rhs)
-{
- return GmpInt(lhs) / rhs;
-}
-
-GmpInt operator%(long lhs, const GmpInt& rhs)
-{
- return GmpInt(lhs) % rhs;
-}
+++ /dev/null
-#ifndef ONCE_FP_GMP_INT_HH_
-#define ONCE_FP_GMP_INT_HH_
-
-#include <iostream>
-
-class GmpInt
-{
- public:
- /* A default of 256 bits will be used for all newly-instantiated GmpInt
- objects. This default can be changed with the function below.
- */
- static void setDefaultNumberOfBits(unsigned long);
- static unsigned long getDefaultNumberOfBits();
-
- GmpInt();
- GmpInt(long value);
- GmpInt(unsigned long value);
- GmpInt(int value);
- GmpInt(double value);
- GmpInt(long double value);
-
- GmpInt(const GmpInt&);
- GmpInt& operator=(const GmpInt&);
- GmpInt& operator=(signed long value);
-
- ~GmpInt();
-
-
- /* This function can be used to retrieve the raw mpz_t data structure
- used by this object. (The template trick is used to avoid a dependency
- of this header file with <gmp.h>.)
- In other words, it can be called like:
-
- mpz_t raw_mpz_data;
- intValue.get_raw_mpz_data(raw_mpz_data);
-
- Note that the returned mpz_t should be considered as read-only and
- not be modified from the outside because it may be shared among
- several objects. If the calling code needs to modify the data, it
- should copy it for itself first with the appropriate GMP library
- functions.
- */
- template<typename Mpz_t>
- void get_raw_mpfr_data(Mpz_t& dest_mpz_t);
-
-
- // Note that the returned char* points to an internal (shared) buffer
- // which will be valid until the next time this function is called
- // (by any object).
- const char* getAsString(int base = 10) const;
- long toInt() const;
-
- GmpInt& operator+=(const GmpInt&);
- GmpInt& operator+=(long);
- GmpInt& operator-=(const GmpInt&);
- GmpInt& operator-=(long);
- GmpInt& operator*=(const GmpInt&);
- GmpInt& operator*=(long);
- GmpInt& operator/=(const GmpInt&);
- GmpInt& operator/=(long);
- GmpInt& operator%=(const GmpInt&);
- GmpInt& operator%=(long);
-
- GmpInt& operator<<=(unsigned long);
- GmpInt& operator>>=(unsigned long);
-
- // Equivalent to "+= value1 * value2;"
- void addProduct(const GmpInt& value1, const GmpInt& value2);
- void addProduct(const GmpInt& value1, unsigned long value2);
-
- // Equivalent to "-= value1 * value2;"
- void subProduct(const GmpInt& value1, const GmpInt& value2);
- void subProduct(const GmpInt& value1, unsigned long value2);
-
- void negate();
- void abs();
- static GmpInt abs(const GmpInt&);
-
- GmpInt operator+(const GmpInt&) const;
- GmpInt operator+(long) const;
- GmpInt operator-(const GmpInt&) const;
- GmpInt operator-(long) const;
- GmpInt operator*(const GmpInt&) const;
- GmpInt operator*(long) const;
- GmpInt operator/(const GmpInt&) const;
- GmpInt operator/(long) const;
- GmpInt operator%(const GmpInt&) const;
- GmpInt operator%(long) const;
-
- GmpInt operator-() const;
-
- GmpInt operator<<(unsigned long) const;
- GmpInt operator>>(unsigned long) const;
-
- bool operator<(const GmpInt&) const;
- bool operator<(long) const;
- bool operator<=(const GmpInt&) const;
- bool operator<=(long) const;
- bool operator>(const GmpInt&) const;
- bool operator>(long) const;
- bool operator>=(const GmpInt&) const;
- bool operator>=(long) const;
- bool operator==(const GmpInt&) const;
- bool operator==(long) const;
- bool operator!=(const GmpInt&) const;
- bool operator!=(long) const;
-
- void parseValue(const char* value);
- void parseValue(const char* value, char** endptr);
- static GmpInt parseString(const char* str, char** endptr);
-
-
- private:
- struct GmpIntData;
- class GmpIntDataContainer;
-
- GmpIntData* mData;
-
- enum DummyType { kNoInitialization };
- GmpInt(DummyType);
-
- void copyIfShared();
- static GmpIntDataContainer& gmpIntDataContainer();
-
- friend GmpInt operator+(long lhs, const GmpInt& rhs);
- friend GmpInt operator-(long lhs, const GmpInt& rhs);
-};
-
-GmpInt operator+(long lhs, const GmpInt& rhs);
-GmpInt operator-(long lhs, const GmpInt& rhs);
-GmpInt operator*(long lhs, const GmpInt& rhs);
-GmpInt operator/(long lhs, const GmpInt& rhs);
-GmpInt operator%(long lhs, const GmpInt& rhs);
-
-inline bool operator<(long lhs, const GmpInt& rhs) { return rhs > lhs; }
-inline bool operator<=(long lhs, const GmpInt& rhs) { return rhs >= lhs; }
-inline bool operator>(long lhs, const GmpInt& rhs) { return rhs < lhs; }
-inline bool operator>=(long lhs, const GmpInt& rhs) { return rhs <= lhs; }
-inline bool operator==(long lhs, const GmpInt& rhs) { return rhs == lhs; }
-inline bool operator!=(long lhs, const GmpInt& rhs) { return rhs != lhs; }
-
-inline std::ostream& operator<<(std::ostream& os, const GmpInt& value)
-{
- os << value.getAsString();
- return os;
-}
-
-#endif
+++ /dev/null
-#include "MpfrFloat.hh"
-#include <stdio.h>
-#include <mpfr.h>
-#include <deque>
-#include <vector>
-#include <cstring>
-#include <cassert>
-
-//===========================================================================
-// Auxiliary structs
-//===========================================================================
-struct MpfrFloat::MpfrFloatData
-{
- unsigned mRefCount;
- MpfrFloatData* nextFreeNode;
- mpfr_t mFloat;
-
- MpfrFloatData(): mRefCount(1), nextFreeNode(0) {}
-};
-
-class MpfrFloat::MpfrFloatDataContainer
-{
- unsigned long mDefaultPrecision;
- std::deque<MpfrFloatData> mData;
- MpfrFloatData* mFirstFreeNode;
-
- MpfrFloatData
- *mConst_0, *mConst_pi, *mConst_e, *mConst_log2, *mConst_epsilon;
-
- void recalculateEpsilon()
- {
- mpfr_set_si(mConst_epsilon->mFloat, 1, GMP_RNDN);
- mpfr_div_2ui(mConst_epsilon->mFloat, mConst_epsilon->mFloat,
- mDefaultPrecision*7/8 - 1, GMP_RNDN);
- }
-
- public:
- MpfrFloatDataContainer():
- mDefaultPrecision(256), mFirstFreeNode(0), mConst_0(0),
- mConst_pi(0), mConst_e(0), mConst_log2(0), mConst_epsilon(0)
- {}
-
- ~MpfrFloatDataContainer()
- {
- for(size_t i = 0; i < mData.size(); ++i)
- mpfr_clear(mData[i].mFloat);
- }
-
- MpfrFloatData* allocateMpfrFloatData(bool initToZero)
- {
- if(mFirstFreeNode)
- {
- MpfrFloatData* node = mFirstFreeNode;
- mFirstFreeNode = node->nextFreeNode;
- if(initToZero) mpfr_set_si(node->mFloat, 0, GMP_RNDN);
- ++(node->mRefCount);
- return node;
- }
-
- mData.push_back(MpfrFloatData());
- mpfr_init2(mData.back().mFloat, mDefaultPrecision);
- if(initToZero) mpfr_set_si(mData.back().mFloat, 0, GMP_RNDN);
- return &mData.back();
- }
-
- void releaseMpfrFloatData(MpfrFloatData* data)
- {
- if(--(data->mRefCount) == 0)
- {
- data->nextFreeNode = mFirstFreeNode;
- mFirstFreeNode = data;
- }
- }
-
- void setDefaultPrecision(unsigned long bits)
- {
- if(bits != mDefaultPrecision)
- {
- mDefaultPrecision = bits;
- for(size_t i = 0; i < mData.size(); ++i)
- mpfr_prec_round(mData[i].mFloat, bits, GMP_RNDN);
-
- if(mConst_pi) mpfr_const_pi(mConst_pi->mFloat, GMP_RNDN);
- if(mConst_e)
- {
- mpfr_set_si(mConst_e->mFloat, 1, GMP_RNDN);
- mpfr_exp(mConst_e->mFloat, mConst_e->mFloat, GMP_RNDN);
- }
- if(mConst_log2) mpfr_const_log2(mConst_log2->mFloat, GMP_RNDN);
- if(mConst_epsilon) recalculateEpsilon();
- }
- }
-
- unsigned long getDefaultPrecision() const
- {
- return mDefaultPrecision;
- }
-
- MpfrFloatData* const_0()
- {
- if(!mConst_0) mConst_0 = allocateMpfrFloatData(true);
- return mConst_0;
- }
-
- MpfrFloat const_pi()
- {
- if(!mConst_pi)
- {
- mConst_pi = allocateMpfrFloatData(false);
- mpfr_const_pi(mConst_pi->mFloat, GMP_RNDN);
- }
- return MpfrFloat(mConst_pi);
- }
-
- MpfrFloat const_e()
- {
- if(!mConst_e)
- {
- mConst_e = allocateMpfrFloatData(false);
- mpfr_set_si(mConst_e->mFloat, 1, GMP_RNDN);
- mpfr_exp(mConst_e->mFloat, mConst_e->mFloat, GMP_RNDN);
- }
- return MpfrFloat(mConst_e);
- }
-
- MpfrFloat const_log2()
- {
- if(!mConst_log2)
- {
- mConst_log2 = allocateMpfrFloatData(false);
- mpfr_const_log2(mConst_log2->mFloat, GMP_RNDN);
- }
- return MpfrFloat(mConst_log2);
- }
-
- MpfrFloat const_epsilon()
- {
- if(!mConst_epsilon)
- {
- mConst_epsilon = allocateMpfrFloatData(false);
- recalculateEpsilon();
- }
- return MpfrFloat(mConst_epsilon);
- }
-};
-
-
-//===========================================================================
-// Shared data
-//===========================================================================
-// This should ensure that the container is not accessed by any MpfrFloat
-// instance before it has been constructed or after it has been destroyed
-// (which might otherwise happen if MpfrFloat is instantiated globally.)
-MpfrFloat::MpfrFloatDataContainer& MpfrFloat::mpfrFloatDataContainer()
-{
- static MpfrFloat::MpfrFloatDataContainer container;
- return container;
-}
-
-
-//===========================================================================
-// Auxiliary functions
-//===========================================================================
-void MpfrFloat::setDefaultMantissaBits(unsigned long bits)
-{
- mpfrFloatDataContainer().setDefaultPrecision(bits);
-}
-
-unsigned long MpfrFloat::getCurrentDefaultMantissaBits()
-{
- return mpfrFloatDataContainer().getDefaultPrecision();
-}
-
-inline void MpfrFloat::copyIfShared()
-{
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- MpfrFloatData* oldData = mData;
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set(mData->mFloat, oldData->mFloat, GMP_RNDN);
- }
-}
-
-
-//===========================================================================
-// Constructors, destructor, assignment
-//===========================================================================
-MpfrFloat::MpfrFloat(DummyType):
- mData(mpfrFloatDataContainer().allocateMpfrFloatData(false))
-{}
-
-MpfrFloat::MpfrFloat(MpfrFloatData* data):
- mData(data)
-{
- assert(data != 0);
- ++(mData->mRefCount);
-}
-
-MpfrFloat::MpfrFloat():
- mData(mpfrFloatDataContainer().const_0())
-{
- ++(mData->mRefCount);
-}
-
-MpfrFloat::MpfrFloat(double value)
-{
- if(value == 0.0)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_d(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(long double value)
-{
- if(value == 0.0L)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_ld(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(long value)
-{
- if(value == 0)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(int value)
-{
- if(value == 0)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(const char* value, char** endptr):
- mData(mpfrFloatDataContainer().allocateMpfrFloatData(false))
-{
- mpfr_strtofr(mData->mFloat, value, endptr, 0, GMP_RNDN);
-}
-
-MpfrFloat::~MpfrFloat()
-{
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
-}
-
-MpfrFloat::MpfrFloat(const MpfrFloat& rhs):
- mData(rhs.mData)
-{
- ++(mData->mRefCount);
-}
-
-MpfrFloat& MpfrFloat::operator=(const MpfrFloat& rhs)
-{
- if(mData != rhs.mData)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = rhs.mData;
- ++(mData->mRefCount);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(double value)
-{
- if(value == 0.0)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_d(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(long double value)
-{
- if(value == 0.0L)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_ld(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(long value)
-{
- if(value == 0)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(int value)
-{
- if(value == 0)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-/*
-MpfrFloat& MpfrFloat::operator=(const char* value)
-{
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
-
- mpfr_set_str(mData->mFloat, value, 10, GMP_RNDN);
- return *this;
-}
-*/
-
-void MpfrFloat::parseValue(const char* value)
-{
- copyIfShared();
- mpfr_set_str(mData->mFloat, value, 10, GMP_RNDN);
-}
-
-void MpfrFloat::parseValue(const char* value, char** endptr)
-{
- copyIfShared();
- mpfr_strtofr(mData->mFloat, value, endptr, 0, GMP_RNDN);
-}
-
-
-//===========================================================================
-// Data getters
-//===========================================================================
-template<>
-void MpfrFloat::get_raw_mpfr_data<mpfr_t>(mpfr_t& dest_mpfr_t)
-{
- std::memcpy(&dest_mpfr_t, mData->mFloat, sizeof(mpfr_t));
-}
-
-const char* MpfrFloat::getAsString(unsigned precision) const
-{
-#if(MPFR_VERSION_MAJOR < 2 || (MPFR_VERSION_MAJOR == 2 && MPFR_VERSION_MINOR < 4))
- static const char* retval =
- "[mpfr_snprintf() is not supported in mpfr versions prior to 2.4]";
- return retval;
-#else
- static std::vector<char> str;
- str.resize(precision+30);
- mpfr_snprintf(&(str[0]), precision+30, "%.*RNg", precision, mData->mFloat);
- return &(str[0]);
-#endif
-}
-
-bool MpfrFloat::isInteger() const
-{
- return mpfr_integer_p(mData->mFloat) != 0;
-}
-
-long MpfrFloat::toInt() const
-{
- return mpfr_get_si(mData->mFloat, GMP_RNDN);
-}
-
-double MpfrFloat::toDouble() const
-{
- return mpfr_get_d(mData->mFloat, GMP_RNDN);
-}
-
-
-//===========================================================================
-// Modifying operators
-//===========================================================================
-MpfrFloat& MpfrFloat::operator+=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_add(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator+=(double value)
-{
- copyIfShared();
- mpfr_add_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator-=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_sub(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator-=(double value)
-{
- copyIfShared();
- mpfr_sub_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator*=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_mul(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator*=(double value)
-{
- copyIfShared();
- mpfr_mul_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator/=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_div(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator/=(double value)
-{
- copyIfShared();
- mpfr_div_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator%=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_fmod(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-
-//===========================================================================
-// Modifying functions
-//===========================================================================
-void MpfrFloat::negate()
-{
- copyIfShared();
- mpfr_neg(mData->mFloat, mData->mFloat, GMP_RNDN);
-}
-
-void MpfrFloat::abs()
-{
- copyIfShared();
- mpfr_abs(mData->mFloat, mData->mFloat, GMP_RNDN);
-}
-
-
-//===========================================================================
-// Non-modifying operators
-//===========================================================================
-MpfrFloat MpfrFloat::operator+(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_add(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator+(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_add_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator-(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_sub(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator-(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_sub_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator*(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_mul(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator*(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_mul_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator/(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_div(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator/(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_div_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator%(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_fmod(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator-() const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_neg(retval.mData->mFloat, mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-
-
-//===========================================================================
-// Comparison operators
-//===========================================================================
-bool MpfrFloat::operator<(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) < 0;
-}
-
-bool MpfrFloat::operator<(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) < 0;
-}
-
-bool MpfrFloat::operator<=(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) <= 0;
-}
-
-bool MpfrFloat::operator<=(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) <= 0;
-}
-
-bool MpfrFloat::operator>(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) > 0;
-}
-
-bool MpfrFloat::operator>(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) > 0;
-}
-
-bool MpfrFloat::operator>=(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) >= 0;
-}
-
-bool MpfrFloat::operator>=(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) >= 0;
-}
-
-bool MpfrFloat::operator==(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) == 0;
-}
-
-bool MpfrFloat::operator==(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) == 0;
-}
-
-bool MpfrFloat::operator!=(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) != 0;
-}
-
-bool MpfrFloat::operator!=(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) != 0;
-}
-
-
-//===========================================================================
-// Operator functions
-//===========================================================================
-MpfrFloat operator+(double lhs, const MpfrFloat& rhs)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_add_d(retval.mData->mFloat, rhs.mData->mFloat, lhs, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat operator-(double lhs, const MpfrFloat& rhs)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_d_sub(retval.mData->mFloat, lhs, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat operator*(double lhs, const MpfrFloat& rhs)
-{
- return rhs * lhs;
-}
-
-MpfrFloat operator/(double lhs, const MpfrFloat& rhs)
-{
- return MpfrFloat(lhs) / rhs;
-}
-
-MpfrFloat operator%(double lhs, const MpfrFloat& rhs)
-{
- return MpfrFloat(lhs) % rhs;
-}
-
-std::ostream& operator<<(std::ostream& os, const MpfrFloat& value)
-{
- os << value.getAsString(unsigned(os.precision()));
- return os;
-}
-
-//===========================================================================
-// Static functions
-//===========================================================================
-MpfrFloat MpfrFloat::log(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_log(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::log2(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_log2(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::log10(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_log10(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::exp(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_exp(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::exp2(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_exp2(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::exp10(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_exp10(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cos(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cos(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sin(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sin(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::tan(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_tan(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sec(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sec(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::csc(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_csc(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cot(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cot(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-void MpfrFloat::sincos(const MpfrFloat& value,
- MpfrFloat& sin,
- MpfrFloat& cos)
-{
- sin.copyIfShared();
- cos.copyIfShared();
- mpfr_sin_cos
- (sin.mData->mFloat, cos.mData->mFloat, value.mData->mFloat, GMP_RNDN);
-}
-
-MpfrFloat MpfrFloat::acos(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_acos(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::asin(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_asin(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::atan(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_atan(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::atan2(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_atan2(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::hypot(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_hypot(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cosh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cosh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sinh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sinh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::tanh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_tanh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::acosh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_acosh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::asinh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_asinh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::atanh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_atanh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sqrt(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sqrt(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cbrt(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cbrt(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::root(const MpfrFloat& value, unsigned long root)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_root(retval.mData->mFloat, value.mData->mFloat, root, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::pow(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_pow(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::pow(const MpfrFloat& value, long exponent)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_pow_si(retval.mData->mFloat, value.mData->mFloat, exponent, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::abs(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_abs(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::dim(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_dim(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::round(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_round(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::ceil(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_ceil(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::floor(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_floor(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::trunc(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_trunc(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::parseString(const char* str, char** endptr)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_strtofr(retval.mData->mFloat, str, endptr, 0, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::const_pi()
-{
- return mpfrFloatDataContainer().const_pi();
-}
-
-MpfrFloat MpfrFloat::const_e()
-{
- return mpfrFloatDataContainer().const_e();
-}
-
-MpfrFloat MpfrFloat::const_log2()
-{
- return mpfrFloatDataContainer().const_log2();
-}
-
-MpfrFloat MpfrFloat::someEpsilon()
-{
- return mpfrFloatDataContainer().const_epsilon();
-}
+++ /dev/null
-#ifndef ONCE_FP_MPFR_FLOAT_
-#define ONCE_FP_MPFR_FLOAT_
-
-#include <iostream>
-
-class MpfrFloat
-{
- public:
- /* A default of 256 bits will be used unless changed with this function.
- Note that all existing and cached GMP objects will be resized to the
- specified precision (which can be a somewhat heavy operation).
- */
- static void setDefaultMantissaBits(unsigned long bits);
-
- static unsigned long getCurrentDefaultMantissaBits();
-
- /* The default constructor initializes the object to the value 0.
- It's efficient to instantiate such zero-initialized objects because
- all of them will share the same mpfr data. (Also any object initialized
- with or assigned the explicit value of zero will also share that one
- mpfr data.) Thus multiple zero-initialized MpfrFloat instances won't
- consume significant amounts of memory (until they are modified to
- contain some other value, of course).
-
- Important caveat:
- ----------------
- Note that initializing an MpfrFloat object with, for example, 0.1 will
- suffer from accuracy problems (at least if the MpfrFloat object has
- more mantissa bits than a double). The C++ double value 0.1 has only
- 53 mantissa bits, while the MpfrFloat object usually has more. If the
- MpfrFloat object is initialized with a double, only that many bits of
- accuracy will end up in the value of the MpfrFloat object. This can
- create significant rounding/accuracy problems in some cases.
- If you need to initialize the MpfrObject with some value (which cannot
- be represented accurately by base-2 floating point numbers, eg. 0.1)
- at full mantissa precision, you have to use parseValue("0.1") instead,
- rather than relying on the constructor taking a double type value.
- */
- MpfrFloat();
- MpfrFloat(double value);
- MpfrFloat(long double value);
- MpfrFloat(long value);
- MpfrFloat(int value);
- MpfrFloat(const char* value, char** endptr);
-
- ~MpfrFloat();
-
- MpfrFloat(const MpfrFloat&);
-
- MpfrFloat& operator=(const MpfrFloat&);
- MpfrFloat& operator=(double value);
- MpfrFloat& operator=(long double value);
- MpfrFloat& operator=(long value);
- MpfrFloat& operator=(int value);
- //MpfrFloat& operator=(const char* value);
-
- void parseValue(const char* value);
- void parseValue(const char* value, char** endptr);
-
-
- /* This function can be used to retrieve the raw mpfr_t data structure
- used by this object. (The template trick is used to avoid a dependency
- of this header file with <mpfr.h>.)
- In other words, it can be called like:
-
- mpfr_t raw_mpfr_data;
- floatValue.get_raw_mpfr_data(raw_mpfr_data);
-
- Note that the returned mpfr_t should be considered as read-only and
- not be modified from the outside because it may be shared among
- several objects. If the calling code needs to modify the data, it
- should copy it for itself first with the appropriate MPFR library
- functions.
- */
- template<typename Mpfr_t>
- void get_raw_mpfr_data(Mpfr_t& dest_mpfr_t);
-
-
- /* Note that the returned char* points to an internal (shared) buffer
- which will be valid until the next time this function is called
- (by any object).
- */
- const char* getAsString(unsigned precision) const;
-
- bool isInteger() const;
- long toInt() const;
- double toDouble() const;
-
- MpfrFloat& operator+=(const MpfrFloat&);
- MpfrFloat& operator+=(double);
- MpfrFloat& operator-=(const MpfrFloat&);
- MpfrFloat& operator-=(double);
- MpfrFloat& operator*=(const MpfrFloat&);
- MpfrFloat& operator*=(double);
- MpfrFloat& operator/=(const MpfrFloat&);
- MpfrFloat& operator/=(double);
- MpfrFloat& operator%=(const MpfrFloat&);
-
- void negate();
- void abs();
-
- MpfrFloat operator+(const MpfrFloat&) const;
- MpfrFloat operator+(double) const;
- MpfrFloat operator-(const MpfrFloat&) const;
- MpfrFloat operator-(double) const;
- MpfrFloat operator*(const MpfrFloat&) const;
- MpfrFloat operator*(double) const;
- MpfrFloat operator/(const MpfrFloat&) const;
- MpfrFloat operator/(double) const;
- MpfrFloat operator%(const MpfrFloat&) const;
-
- MpfrFloat operator-() const;
-
- bool operator<(const MpfrFloat&) const;
- bool operator<(double) const;
- bool operator<=(const MpfrFloat&) const;
- bool operator<=(double) const;
- bool operator>(const MpfrFloat&) const;
- bool operator>(double) const;
- bool operator>=(const MpfrFloat&) const;
- bool operator>=(double) const;
- bool operator==(const MpfrFloat&) const;
- bool operator==(double) const;
- bool operator!=(const MpfrFloat&) const;
- bool operator!=(double) const;
-
- static MpfrFloat log(const MpfrFloat&);
- static MpfrFloat log2(const MpfrFloat&);
- static MpfrFloat log10(const MpfrFloat&);
- static MpfrFloat exp(const MpfrFloat&);
- static MpfrFloat exp2(const MpfrFloat&);
- static MpfrFloat exp10(const MpfrFloat&);
- static MpfrFloat cos(const MpfrFloat&);
- static MpfrFloat sin(const MpfrFloat&);
- static MpfrFloat tan(const MpfrFloat&);
- static MpfrFloat sec(const MpfrFloat&);
- static MpfrFloat csc(const MpfrFloat&);
- static MpfrFloat cot(const MpfrFloat&);
- static void sincos(const MpfrFloat&, MpfrFloat& sin, MpfrFloat& cos);
- static MpfrFloat acos(const MpfrFloat&);
- static MpfrFloat asin(const MpfrFloat&);
- static MpfrFloat atan(const MpfrFloat&);
- static MpfrFloat atan2(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat hypot(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat cosh(const MpfrFloat&);
- static MpfrFloat sinh(const MpfrFloat&);
- static MpfrFloat tanh(const MpfrFloat&);
- static MpfrFloat acosh(const MpfrFloat&);
- static MpfrFloat asinh(const MpfrFloat&);
- static MpfrFloat atanh(const MpfrFloat&);
- static MpfrFloat sqrt(const MpfrFloat&);
- static MpfrFloat cbrt(const MpfrFloat&);
- static MpfrFloat root(const MpfrFloat&, unsigned long root);
- static MpfrFloat pow(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat pow(const MpfrFloat&, long exponent);
- static MpfrFloat abs(const MpfrFloat&);
- static MpfrFloat dim(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat round(const MpfrFloat&);
- static MpfrFloat ceil(const MpfrFloat&);
- static MpfrFloat floor(const MpfrFloat&);
- static MpfrFloat trunc(const MpfrFloat&);
-
- static MpfrFloat parseString(const char* str, char** endptr);
-
- // These values are cached (and recalculated every time the mantissa bits
- // change), so it's efficient to call these repeatedly:
- static MpfrFloat const_pi();
- static MpfrFloat const_e();
- static MpfrFloat const_log2();
- static MpfrFloat someEpsilon();
-
-
- private:
- struct MpfrFloatData;
- class MpfrFloatDataContainer;
-
- MpfrFloatData* mData;
-
- enum DummyType { kNoInitialization };
- MpfrFloat(DummyType);
- MpfrFloat(MpfrFloatData*);
-
- void copyIfShared();
- static MpfrFloatDataContainer& mpfrFloatDataContainer();
-
- friend MpfrFloat operator+(double lhs, const MpfrFloat& rhs);
- friend MpfrFloat operator-(double lhs, const MpfrFloat& rhs);
-};
-
-MpfrFloat operator+(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator-(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator*(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator/(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator%(double lhs, const MpfrFloat& rhs);
-
-inline bool operator<(double lhs, const MpfrFloat& rhs) { return rhs > lhs; }
-inline bool operator<=(double lhs, const MpfrFloat& rhs) { return rhs >= lhs; }
-inline bool operator>(double lhs, const MpfrFloat& rhs) { return rhs < lhs; }
-inline bool operator>=(double lhs, const MpfrFloat& rhs) { return rhs <= lhs; }
-inline bool operator==(double lhs, const MpfrFloat& rhs) { return rhs == lhs; }
-inline bool operator!=(double lhs, const MpfrFloat& rhs) { return rhs != lhs; }
-
-// This function takes into account the value of os.precision()
-std::ostream& operator<<(std::ostream& os, const MpfrFloat& value);
-
-#endif
## ---------------------------------------------------------------------
-## $Id$
+## $Id: CMakeLists.txt 32392 2014-02-03 16:24:36Z heister $
##
## Copyright (C) 2012 - 2013 by the deal.II authors
##
## ---------------------------------------------------------------------
#
-# Remove -Wall and -pedantic from DEAL_II_CXX_FLAGS (in directory scope) to
# avoid some annoying warnings...
#
STRIP_FLAG(DEAL_II_CXX_FLAGS "-Wall")
STRIP_FLAG(DEAL_II_CXX_FLAGS "-pedantic")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-switch)
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-nested-anon-types)
-DEAL_II_ADD_LIBRARY(obj_functionparser OBJECT
- fparser.cc
- fpoptimizer.cc
+INCLUDE_DIRECTORIES(
+ include/
+)
+
+DEAL_II_ADD_LIBRARY(obj_muparser OBJECT
+src/muParserBase.cpp
+src/muParserBytecode.cpp
+src/muParserCallback.cpp
+src/muParser.cpp
+src/muParserError.cpp
+src/muParserInt.cpp
+src/muParserTest.cpp
+src/muParserTokenReader.cpp
)
-IF(DEAL_II_WITH_THREADS)
- DEAL_II_ADD_DEFINITIONS(obj_functionparser "FP_USE_THREAD_SAFE_EVAL")
-ENDIF()
+#IF(DEAL_II_WITH_THREADS)
+# DEAL_II_ADD_DEFINITIONS(obj_muparser "FP_USE_THREAD_SAFE_EVAL")
+#ENDIF()
--- /dev/null
+#######################################################################\r
+# #\r
+# #\r
+# __________ #\r
+# _____ __ __\______ \_____ _______ ______ ____ _______ #\r
+# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #\r
+# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #\r
+# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #\r
+# \/ \/ \/ \/ #\r
+# Fast math parser Library #\r
+# #\r
+# Copyright (C) 2013 Ingo Berg #\r
+# #\r
+# Web: muparser.beltoforion.de #\r
+# e-mail: muparser@beltoforion.de #\r
+# #\r
+# #\r
+#######################################################################\r
+\r
+\r
+History:\r
+--------\r
+\r
+Rev 2.2.3: 22.12.2012\r
+---------------------\r
+\r
+ Removed features:\r
+ * build files for msvc2005, borland and watcom compiler were removed\r
+\r
+ Bugfixes:\r
+ * Bugfix for Intel Compilers added: The power operator did not work properly \r
+ with Intel C++ composer XE 2011.\r
+ (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1)\r
+ * Issue 3509860: Callbacks of functions with string parameters called twice\r
+ (see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979)\r
+ * Issue 3570423: example1 shows slot number in hexadecimal\r
+ (see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979)\r
+ * Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition:\r
+ - division by zero in constant expressions was reported with the code "ec_GENERIC" \r
+ instead of "ecDIV_BY_ZERO"\r
+ - added throwing of "ecDOMAIN_ERROR" to sqrt and log functions\r
+\r
+\r
+Rev 2.2.2: 18.02.2012\r
+---------------------\r
+ Bugfixes:\r
+ * Optimizer did'nt work properly for division:\r
+ (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825)\r
+\r
+Rev 2.2.1: 22.01.2012\r
+---------------------\r
+ Bugfixes:\r
+ * Optimizer bug in 64 bit systems fixed\r
+ (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1)\r
+ \r
+Rev 2.2.0: 22.01.2012\r
+---------------------\r
+ Improvements:\r
+ * Optimizer rewritten and improved. In general: more optimizations are \r
+ now applied to the bytecode. The downside is that callback Functions \r
+ can no longer be flagged as non-optimizable. (The flag is still present \r
+ but ignored) This is necessary since the optimizer had to call the \r
+ functions in order to precalculate the result (see Bugfixes). These calls \r
+ posed a problems for callback functions with side effects and if-then-else \r
+ clauses in general since they undermined the shortcut evaluation prinziple.\r
+\r
+ Bugfixes:\r
+ * Infix operators where not properly detected in the presence of a constant \r
+ name starting with an underscore which is a valid character for infix \r
+ operators too (i.e. "-_pi").\r
+ * Issue 3463353: Callback functions are called twice during the first call to eval.\r
+ * Issue 3447007: GetUsedVar unnecessaryly executes callback functions.\r
+\r
+\r
+Rev 2.1.0: 19.11.2011\r
+---------------------\r
+ New feature:\r
+ * Function atan2 added\r
+\r
+ Bugfixes:\r
+ * Issue 3438380: Changed behaviour of tellg with GCC >4.6 led to failures \r
+ in value detection callbacks.\r
+ * Issue 3438715: only "double" is a valid MUP_BASETYPE \r
+ MUP_BASETYPE can now be any of:\r
+ float, \r
+ double, \r
+ long double, \r
+ short, \r
+ unsigned short, \r
+ unsigned int, \r
+ long,\r
+ unsigned long. \r
+ Previousely only floating point types were allowed. \r
+ Using "int" is still not allowed!\r
+ * Compiler issues with GCC 4.6 fixed\r
+ * Custom value recognition callbacks added with AddValIdent had lower\r
+ priority than built in functions. This was causing problems with \r
+ hex value recognition since detection of non hex values had priority\r
+ over the detection of hex values. The "0" in the hex prefix "0x" would \r
+ be read as a separate non-hex number leaving the rest of the expression\r
+ unparseable.\r
+\r
+Rev 2.0.0: 04.09.2011\r
+---------------------\r
+This release introduces a new version numbering scheme in order to make\r
+future changes in the ABI apparent to users of the library. The number is\r
+now based on the SONAME property as used by GNU/Linux. \r
+\r
+ Changes:\r
+ * Beginning with this version all version numbers will be SONAME compliant\r
+ * Project files for MSVC2010 added\r
+ * Project files for MSVC2003 removed\r
+ * Bytecode parsing engine cleaned up and rewritten\r
+ * Retrieving all results of expressions made up of comma separate \r
+ subexpressions is now possible with a new Eval overload.\r
+ * Callback functions with fixed number of arguments can now have up to 10 \r
+ Parameters (previous limit was 5)\r
+\r
+ New features:\r
+ * ternary if-then-else operator added (C++ like; "(...) ? ... : ..." )\r
+ * new intrinsic binary operators: "&&", "||" (logical and, or)\r
+ * A new bulkmode allows submitting large arrays as variables to compute large \r
+ numbers of expressions with a single call. This can drastically improve \r
+ parsing performance when interfacing the library from managed languages like \r
+ C#. (It doesn't bring any performance benefit for C++ users though...)\r
+\r
+ Removed features:\r
+ * intrinsic "and", "or" and "xor" operators have been removed. I'd like to let \r
+ users the freedom of defining them on their own versions (either as logical or bitwise \r
+ operators).\r
+ * Implementation for complex numbers removed. This was merely a hack. If you \r
+ need complex numbers try muParserX which provides native support for them.\r
+ (see: http://beltoforion.de/muparserx/math_expression_parser_en.html)\r
+\r
+ Bugfixes:\r
+ * User defined operators could collide with built in operators that entirely \r
+ contained their identifier. i.e. user defined "&" would not work with the built \r
+ in "&&" operator since the user defined operator was detected with a higher \r
+ priority resulting in a syntax error.\r
+ * Detection of unknown variables did not work properly in case a postfix operator\r
+ was defined which was part of the undefined variable.\r
+ i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did\r
+ not detect "multi" as an undefined variable.\r
+ (Reference: http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979)\r
+ * Postfix operators sharing the first few characters were causing bogus parsing exception.\r
+ (Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979)\r
+\r
+Rev 1.34: 04.09.2010\r
+--------------------\r
+ Changes:\r
+ * The prefix needed for parsing hex values is now "0x" and no longer "$". \r
+ * AddValIdent reintroduced into the DLL interface\r
+\r
+ New features:\r
+ * The associativity of binary operators can now be changed. The pow operator \r
+ is now right associative. (This is what Mathematica is using) \r
+ * Seperator can now be used outside of functions. This allows compound \r
+ expressions like:\r
+ "a=10,b=20,c=a*b" The last "argument" will be taken as the return value\r
+\r
+ Bugfixes: \r
+ * The copy constructor did not copy binary operator definitions. Those were lost\r
+ in the copied parser instance.\r
+ * Mixing special characters and alphabetic characters in binary operator names \r
+ led to inconsistent parsing behaviour when parsing expressions like "a ++ b" \r
+ and "a++b" when "++" is defined as a binary operator. Binary operators must \r
+ now consist entirely of special characters or of alphabetic ones.\r
+ (original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1)\r
+ * User defined operators were not exactly handled like built in operators. This \r
+ led to inconsistencies in expression evaluation when using them. The results \r
+ differed due to slightly different precedence rules.\r
+ * Using empty string arguments ("") would cause a crash of muParser\r
+\r
+\r
+Rev 1.32: 29.01.2010 \r
+--------------------\r
+\r
+ Changes:\r
+ * "example3" renamed to "example2"\r
+ * Project/Makefiles files are now provided for:\r
+ - msvc2003 \r
+ - msvc2005 \r
+ - msvc2008\r
+ - watcom (makefile)\r
+ - mingw (makefile)\r
+ - bcc (makefile)\r
+ * Project files for borland cpp builder were removed\r
+\r
+\r
+ New features:\r
+ * Added function returning muparsers version number\r
+ * Added function for resetting the locale\r
+\r
+\r
+ Bugfixes: \r
+ * Changes example1 in order to fix issues with irritating memory leak reports. \r
+ Added conditional code for memory leak detection with MSVC in example1.\r
+ (see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx)\r
+ * Fixed some warnings for gcc\r
+\r
+\r
+\r
+Rev 1.31cp: 15.01.2010 (Maintainance release for CodeProject)\r
+----------------------\r
+\r
+ Changes:\r
+ * Archive structure changed\r
+ * C# wrapper added\r
+ * Fixed issued that prevented compiling with VS2010 Beta2\r
+ \r
+\r
+Rev 1.30: 09.06.2008\r
+--------------------\r
+\r
+ Changes:\r
+ * Epsilon of the numerical differentiation algorithm changed to allow greater accuracy.\r
+\r
+ New features:\r
+ * Setting thousands separator and decimal separator is now possible\r
+\r
+ Bugfixes:\r
+ * The dll interface did not provide a callback for functions without any arguments. \r
+ \r
+\r
+Rev 1.29: Januar 2008\r
+---------------------\r
+\r
+ Unrelease Version available only via SVN.\r
+\r
+\r
+Rev 1.28: 02. July, 2007\r
+---------------------------\r
+ \r
+ Library changes:\r
+ * Interface for the dynamic library changed and extended to create an interface \r
+ using pure C functions only. \r
+ * mupInit() removed\r
+\r
+ Build system:\r
+ * MSVC7 Project files removed in favor of MSVC8\r
+\r
+ Bugfixes:\r
+ * The dynamic library did not build on other systems than linux due to a misplaced \r
+ preprocessor definition. This is fixed now.\r
+\r
+\r
+Rev 1.27:\r
+---------------------------\r
+\r
+ Build system:\r
+ * Modified build\ directory layout introducing some subfolders \r
+ for the various IDE supported\r
+ * Project files for BCB and MSVC7 added\r
+ * Switched to use bakefile 0.2.1 which now correctly creates the \r
+ "make uninstall" target for autoconf's Makefile.in\r
+ * Now the library debug builds are named "muparserd" instead of "muparser"\r
+ to allow multiple mixed release/debug builds to coexist; so e.g. on Windows\r
+ when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib"\r
+\r
+ New Features:\r
+ * Factory functions can now take a user defined pointer\r
+ * String functions can now be used with up to two additional \r
+ double parameters\r
+ * Support for UNICODE character types added\r
+ * Infix operator priority can now be changed by the user\r
+\r
+ Bugfixes:\r
+ * An internal error was raised when evaluating an empty \r
+ expressions\r
+ * The error message raised in case of name collisions between \r
+ implicitely defined variables and postfix operators did contain\r
+ misleading data.\r
+\r
+\r
+Rev 1.26: (unofficial release)\r
+------------------------------\r
+\r
+ New Features:\r
+ * Unary operator precedence can now be changed by the user.\r
+\r
+\r
+Rev 1.25: 5. February, 2006\r
+---------------------------\r
+\r
+ Build system: (special thanks to Francesco Montorsi for implementing it!)\r
+ * created a bakefile-based build system which adds support for the following win32 compilers:\r
+ -> MS visual C++ (6 and .NET)\r
+ -> BorlandC++ (5 or greater)\r
+ -> Mingw32 (tested with gcc 3.2)\r
+ -> Watcom (not tested)\r
+ and for GCC on Unix (using a standard autoconf's configure script).\r
+\r
+ Compatibility improvements:\r
+ * fixed some small warnings when using -Wall with GCC on Unix\r
+ * added inclusion guards for win32-specific portions of code\r
+ * added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler.\r
+\r
+\r
+Rev 1.24: 29. October, 2005\r
+---------------------------\r
+\r
+Changes:\r
+\r
+ Compatibility improvements:\r
+ * parser now works on 64 bit compilers\r
+ * (bytecode base datatype can now be changed freely)\r
+\r
+\r
+Rev 1.23: 19. October, 2005\r
+---------------------------\r
+\r
+Changes:\r
+\r
+ Bugfixes:\r
+ * Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug.\r
+\r
+ New features:\r
+ * Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6\r
+\r
+\r
+Rev 1.22: October, 2005\r
+-----------------------\r
+\r
+Release notes:\r
+\r
+All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with\r
+gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates. \r
+This should make the code cleaner. The Borland Project files were removed. If you want to use it \r
+with Borland either use the dll version or create your own project files. I can't support it since I don't \r
+have this compiler at hand.\r
+\r
+Changes:\r
+\r
+ Project Changes:\r
+ * Borland project files removed\r
+ (The code should still compile with BCB but I cant provide you with project files)\r
+\r
+ Internal Changes:\r
+ * unnecessary template files have been removed:\r
+ - new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp\r
+ - removed Files: muIParserTypes.h\r
+\r
+\r
+Rev 1.2 / 1.21: April, 2005\r
+---------------------------\r
+\r
+Release Notes:\r
+First of all the interface has changed so this version is not backwards compatible.\r
+After receiving a couple of questions about it, this version features support for\r
+user defined binary operators. Consequently the built in operators can now be \r
+turned off, thus you can deactivate them and write complete customized parser\r
+subclasses that only contain the functionality you want. Another new feature is \r
+the introduction of callback functions taking string arguments, implicit \r
+generation of variables and the Assignement operator.\r
+\r
+ Functionality\r
+ * New built in operator: xor; Logical xor.\r
+ * New built in operator: Assignement operator; Defining variables in terms of \r
+ other variables/constants\r
+ * New feature: Strings as arguments for callback functions\r
+ * New feature: User defined binary operators\r
+ * New feature: ParserInt a class with a sample implementation for\r
+ integer numbers.\r
+ * New feature: Callbacks to value regognition functions.\r
+\r
+ * Removed: all predefined postfix operators have been removed.\r
+ * New project file: Now comes with a ready to use windows DLL.\r
+ * New project file: Makefile for cygwin now included.\r
+ * New example: Example3 shows usage of the DLL.\r
+\r
+ Interface changes\r
+ * New member function: DefineOprt For adding user defined binary operators.\r
+ * New member function: EnableBuiltInOprt(bool) Enables/Disables built in \r
+ binary operators.\r
+ * New member function: AddValIdent(...) to add callbacks for custom value \r
+ recognition functions.\r
+ * Removed: SetVar(), SetConst().\r
+ * Renamed: Most interface functions have been renamed\r
+ * Changed: The type for multiargument callbacks multfun_type has changed. \r
+ It no longer takes a std::vector as input.\r
+\r
+ Internal changes\r
+ * new class muParserTokenReader.h encapsulates the token identification \r
+ and token assignement.\r
+ * Internal handling of function callbacks unified as a result the performance \r
+ of the bytecode evaluation increased.\r
+\r
+\r
+Rev 1.10 : December 30, 2004\r
+----------------------------\r
+\r
+Release Notes:\r
+This version does not contain major new feature compared to V1.07 but its internal structure has\r
+changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode\r
+parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you\r
+can change its value datatype. It should work on 64-bit systems. For this reason I supply both\r
+versions for download. If you use V1.07 and are happy with it there is no need for updating\r
+your version.\r
+\r
+ * New example program: Archive now contains two demo programs: One for standard C++ and one for\r
+ managed C++.\r
+ * New member function: RemoveVar(...) can be used for removing a single variable from the internal \r
+ storage.\r
+ * New member function: GetVar() can be used for querying the variable names and pointers of all\r
+ variables defined in the parser.\r
+ * New member function: GetConst() can be used for querying all defined constants and their values.\r
+ * New member function: GetFunDef() can be used for querying all defined functions and the number of\r
+ arguments they expect.\r
+ * Internal structure changed; hanging base datatype at compile time is now possible.\r
+ * Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now.\r
+ * Bugfix: Variable names must will now be tested if they conflict with constant or function names.\r
+ * Internal change: Removed most dependencies from the C-string libraries.\r
+ * Internal change: Bytecode is now stored in a separate class: ParserByteCode.h\r
+ * Internal change: GetUsedVar() does no longer require that variables are defined at time of call.\r
+ * Internal change: Error treatment changed. ParserException is no longer derived from\r
+ std::runtime_error; Internal treatment of Error messages changed.\r
+ * New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()\r
+ they are used for defining the charset allowed for variable-, operator- and\r
+ function names.\r
+\r
+\r
+Rev 1.09 : November 20, 2004\r
+----------------------------\r
+\r
+ * New member function: RemoveVar(...) can be used for removing a single variable from the internal \r
+ storage.\r
+ * Internal structure changed; changing base datatype at compile time is now possible.\r
+ * Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now.\r
+ * Internal change: Removed most dependencies from the C-string libraries.\r
+ * Internal change: Bytecode is now stored in a seperate class: ParserByteCode.h.\r
+ * Internal change: GetUsedVar() does no longer require that variables are defined at time of call.\r
+ * Internal change: Error treatment changed. ParserException is no longer derived from \r
+ std::runtime_error; Internal treatment of Error messages changed.\r
+ * New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()\r
+ they are used for defining the charset allowed for variable-, operator- and function names.\r
+\r
+\r
+Rev 1.08 : November, 2004 \r
+-------------------------\r
+\r
+ * unpublished; experimental template version with respect to data type and underlying string\r
+ type (string <-> widestring). The idea was dropped...\r
+\r
+\r
+Rev 1.07 : September 4 2004\r
+---------------------------\r
+\r
+ * Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some\r
+ issues left.\r
+ * Improved portability; Changes in order to allow compiling on BCB.\r
+ * New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with\r
+ respect to a certain variable; added in muParser.h.\r
+\r
+\r
+Rev 1.06 : August 20 2004\r
+-------------------------\r
+\r
+ * Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter\r
+ indicating that the function can not be optimized.\r
+ * Internal changes: muParserStack.h simplified; refactorings\r
+ * Parser is now distributed under the MIT License; all comments changed accordingly.\r
+\r
+\r
+Rev 1.05 : August 20 2004\r
+-------------------------\r
+\r
+ * Variable/constant names will now be checked for invalid characters.\r
+ * Querying the names of all variables used in an expression is now possible; new function: GetUsedVar().\r
+ * Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat).\r
+ * Predefined functions with variable number of arguments added: sum, avg, min, max.\r
+ * Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp().\r
+ * Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp().\r
+ * Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly.\r
+ * Internal changes: static array removed in Command code calculation routine; misc. changes.\r
+\r
+\r
+Rev 1.04 : August 16 2004\r
+-------------------------\r
+\r
+ * Support for functions with variable number of arguments added.\r
+ * Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h;\r
+ changed: Parser.h, Parser.cpp.\r
+ * Bug in the bytecode calculation function fixed (affected the unary minus operator).\r
+ * Optimizer can be deactivated; new function: EnableOptimizer(bool bStat).\r
+\r
+\r
+Rev 1.03 : August 10 2004\r
+-------------------------\r
+\r
+ * Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(),\r
+ ClearPostOp().\r
+ * Minor changes to the bytecode parsing routine.\r
+ * User defined functions can now have up to four parameters.\r
+ * Performance optimized: simple formula optimization added; (precalculation of constant parts of the\r
+ expression).\r
+ * Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly.\r
+\r
+\r
+Rev 1.02 : July 30 2004\r
+-----------------------\r
+\r
+ * Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(),\r
+ ClearConst().\r
+ * Single variables can now be added using AddVar(); you have now the choice of adding them either\r
+ one by one or all at the same time using SetVar(const varmap_type &a_vVar).\r
+ * Internal handling of variables changed, is now similar to function handling.\r
+ * Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to\r
+ derive new parsers with a modified set of default functions and constants.\r
+ * Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold\r
+ function parameter count.\r
+\r
+\r
+Rev 1.01 : July 23 2004\r
+-----------------------\r
+\r
+ * Support for user defined functions has been added; new functions: AddFun(), ClearFun(),\r
+ InitFunctions().\r
+ * Built in constants have been removed; the parser contained undocumented built in\r
+ constants pi, e.\r
+ There was the possibility of name conflicts with user defined variables.\r
+ * Setting multiple variables with SetVar can now be done with a map of names and pointers as the only\r
+ argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3\r
+ arguments (array of names, array of pointers, and array length) is now marked as deprecated.\r
+ * The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for\r
+ base 10, and ln for base e.\r
+\r
+\r
+Rev 1.00 : July 21 2004\r
+-----------------------\r
+\r
+ * Initial release\r
--- /dev/null
+#######################################################################\r
+# #\r
+# #\r
+# __________ #\r
+# _____ __ __\______ \_____ _______ ______ ____ _______ #\r
+# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #\r
+# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #\r
+# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #\r
+# \/ \/ \/ \/ #\r
+# Fast math parser Library #\r
+# #\r
+# Copyright (C) 2011 Ingo Berg #\r
+# #\r
+# Web: muparser.beltoforion.de #\r
+# e-mail: muparser@beltoforion.de #\r
+# #\r
+# #\r
+#######################################################################\r
+\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+ OR OTHER DEALINGS IN THE SOFTWARE.\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_H\r
+#define MU_PARSER_H\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <vector>\r
+\r
+//--- Parser includes --------------------------------------------------------------------------\r
+#include "muParserBase.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+/** \file\r
+ \brief Definition of the standard floating point parser.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ /** \brief Mathematical expressions parser.\r
+ \r
+ Standard implementation of the mathematical expressions parser. \r
+ Can be used as a reference implementation for subclassing the parser.\r
+\r
+ <small>\r
+ (C) 2011 Ingo Berg<br>\r
+ muparser(at)gmx.de\r
+ </small>\r
+ */\r
+ /* final */ class Parser : public ParserBase\r
+ {\r
+ public:\r
+\r
+ Parser();\r
+\r
+ virtual void InitCharSets();\r
+ virtual void InitFun();\r
+ virtual void InitConst();\r
+ virtual void InitOprt();\r
+ virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);\r
+\r
+ value_type Diff(value_type *a_Var, \r
+ value_type a_fPos, \r
+ value_type a_fEpsilon = 0) const;\r
+\r
+ protected:\r
+\r
+ // Trigonometric functions\r
+ static value_type Sin(value_type);\r
+ static value_type Cos(value_type);\r
+ static value_type Tan(value_type);\r
+ static value_type Tan2(value_type, value_type);\r
+ // arcus functions\r
+ static value_type ASin(value_type);\r
+ static value_type ACos(value_type);\r
+ static value_type ATan(value_type);\r
+ static value_type ATan2(value_type, value_type);\r
+\r
+ // hyperbolic functions\r
+ static value_type Sinh(value_type);\r
+ static value_type Cosh(value_type);\r
+ static value_type Tanh(value_type);\r
+ // arcus hyperbolic functions\r
+ static value_type ASinh(value_type);\r
+ static value_type ACosh(value_type);\r
+ static value_type ATanh(value_type);\r
+ // Logarithm functions\r
+ static value_type Log2(value_type); // Logarithm Base 2\r
+ static value_type Log10(value_type); // Logarithm Base 10\r
+ static value_type Ln(value_type); // Logarithm Base e (natural logarithm)\r
+ // misc\r
+ static value_type Exp(value_type);\r
+ static value_type Abs(value_type);\r
+ static value_type Sqrt(value_type);\r
+ static value_type Rint(value_type);\r
+ static value_type Sign(value_type);\r
+\r
+ // Prefix operators\r
+ // !!! Unary Minus is a MUST if you want to use negative signs !!!\r
+ static value_type UnaryMinus(value_type);\r
+\r
+ // Functions with variable number of arguments\r
+ static value_type Sum(const value_type*, int); // sum\r
+ static value_type Avg(const value_type*, int); // mean value\r
+ static value_type Min(const value_type*, int); // minimum\r
+ static value_type Max(const value_type*, int); // maximum\r
+\r
+ static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal);\r
+ };\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_BASE_H\r
+#define MU_PARSER_BASE_H\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <cmath>\r
+#include <string>\r
+#include <iostream>\r
+#include <map>\r
+#include <memory>\r
+#include <locale>\r
+\r
+//--- Parser includes --------------------------------------------------------------------------\r
+#include "muParserDef.h"\r
+#include "muParserStack.h"\r
+#include "muParserTokenReader.h"\r
+#include "muParserBytecode.h"\r
+#include "muParserError.h"\r
+\r
+\r
+namespace mu\r
+{\r
+/** \file\r
+ \brief This file contains the class definition of the muparser engine.\r
+*/\r
+\r
+//--------------------------------------------------------------------------------------------------\r
+/** \brief Mathematical expressions parser (base parser engine).\r
+ \author (C) 2013 Ingo Berg\r
+\r
+ This is the implementation of a bytecode based mathematical expressions parser. \r
+ The formula will be parsed from string and converted into a bytecode. \r
+ Future calculations will be done with the bytecode instead the formula string\r
+ resulting in a significant performance increase. \r
+ Complementary to a set of internally implemented functions the parser is able to handle \r
+ user defined functions and variables. \r
+*/\r
+class ParserBase \r
+{\r
+friend class ParserTokenReader;\r
+\r
+private:\r
+\r
+ /** \brief Typedef for the parse functions. \r
+ \r
+ The parse function do the actual work. The parser exchanges\r
+ the function pointer to the parser function depending on \r
+ which state it is in. (i.e. bytecode parser vs. string parser)\r
+ */\r
+ typedef value_type (ParserBase::*ParseFunction)() const; \r
+\r
+ /** \brief Type used for storing an array of values. */\r
+ typedef std::vector<value_type> valbuf_type;\r
+\r
+ /** \brief Type for a vector of strings. */\r
+ typedef std::vector<string_type> stringbuf_type;\r
+\r
+ /** \brief Typedef for the token reader. */\r
+ typedef ParserTokenReader token_reader_type;\r
+ \r
+ /** \brief Type used for parser tokens. */\r
+ typedef ParserToken<value_type, string_type> token_type;\r
+\r
+ /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */\r
+ static const int s_MaxNumOpenMPThreads = 4;\r
+\r
+ public:\r
+\r
+ /** \brief Type of the error class. \r
+ \r
+ Included for backwards compatibility.\r
+ */\r
+ typedef ParserError exception_type;\r
+\r
+ static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);\r
+\r
+ ParserBase(); \r
+ ParserBase(const ParserBase &a_Parser);\r
+ ParserBase& operator=(const ParserBase &a_Parser);\r
+\r
+ virtual ~ParserBase();\r
+ \r
+ value_type Eval() const;\r
+ value_type* Eval(int &nStackSize) const;\r
+ void Eval(value_type *results, int nBulkSize);\r
+\r
+ int GetNumResults() const;\r
+\r
+ void SetExpr(const string_type &a_sExpr);\r
+ void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);\r
+\r
+ void SetDecSep(char_type cDecSep);\r
+ void SetThousandsSep(char_type cThousandsSep = 0);\r
+ void ResetLocale();\r
+\r
+ void EnableOptimizer(bool a_bIsOn=true);\r
+ void EnableBuiltInOprt(bool a_bIsOn=true);\r
+\r
+ bool HasBuiltInOprt() const;\r
+ void AddValIdent(identfun_type a_pCallback);\r
+\r
+ /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) \r
+ \brief Define a parser function without arguments.\r
+ \param a_strName Name of the function\r
+ \param a_pFun Pointer to the callback function\r
+ \param a_bAllowOpt A flag indicating this function may be optimized\r
+ */\r
+ template<typename T>\r
+ void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true)\r
+ {\r
+ AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );\r
+ }\r
+\r
+ void DefineOprt(const string_type &a_strName, \r
+ fun_type2 a_pFun, \r
+ unsigned a_iPri=0, \r
+ EOprtAssociativity a_eAssociativity = oaLEFT,\r
+ bool a_bAllowOpt = false);\r
+ void DefineConst(const string_type &a_sName, value_type a_fVal);\r
+ void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);\r
+ void DefineVar(const string_type &a_sName, value_type *a_fVar);\r
+ void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);\r
+ void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);\r
+\r
+ // Clear user defined variables, constants or functions\r
+ void ClearVar();\r
+ void ClearFun();\r
+ void ClearConst();\r
+ void ClearInfixOprt();\r
+ void ClearPostfixOprt();\r
+ void ClearOprt();\r
+ \r
+ void RemoveVar(const string_type &a_strVarName);\r
+ const varmap_type& GetUsedVar() const;\r
+ const varmap_type& GetVar() const;\r
+ const valmap_type& GetConst() const;\r
+ const string_type& GetExpr() const;\r
+ const funmap_type& GetFunDef() const;\r
+ string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;\r
+\r
+ const char_type ** GetOprtDef() const;\r
+ void DefineNameChars(const char_type *a_szCharset);\r
+ void DefineOprtChars(const char_type *a_szCharset);\r
+ void DefineInfixOprtChars(const char_type *a_szCharset);\r
+\r
+ const char_type* ValidNameChars() const;\r
+ const char_type* ValidOprtChars() const;\r
+ const char_type* ValidInfixOprtChars() const;\r
+\r
+ void SetArgSep(char_type cArgSep);\r
+ char_type GetArgSep() const;\r
+ \r
+ void Error(EErrorCodes a_iErrc, \r
+ int a_iPos = (int)mu::string_type::npos, \r
+ const string_type &a_strTok = string_type() ) const;\r
+\r
+ protected:\r
+ \r
+ void Init();\r
+\r
+ virtual void InitCharSets() = 0;\r
+ virtual void InitFun() = 0;\r
+ virtual void InitConst() = 0;\r
+ virtual void InitOprt() = 0; \r
+\r
+ virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);\r
+\r
+ static const char_type *c_DefaultOprt[]; \r
+ static std::locale s_locale; ///< The locale used by the parser\r
+ static bool g_DbgDumpCmdCode;\r
+ static bool g_DbgDumpStack;\r
+\r
+ /** \brief A facet class used to change decimal and thousands separator. */\r
+ template<class TChar>\r
+ class change_dec_sep : public std::numpunct<TChar>\r
+ {\r
+ public:\r
+ \r
+ explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)\r
+ :std::numpunct<TChar>()\r
+ ,m_nGroup(nGroup)\r
+ ,m_cDecPoint(cDecSep)\r
+ ,m_cThousandsSep(cThousandsSep)\r
+ {}\r
+ \r
+ protected:\r
+ \r
+ virtual char_type do_decimal_point() const\r
+ {\r
+ return m_cDecPoint;\r
+ }\r
+\r
+ virtual char_type do_thousands_sep() const\r
+ {\r
+ return m_cThousandsSep;\r
+ }\r
+\r
+ virtual std::string do_grouping() const \r
+ { \r
+ return std::string(1, m_nGroup); \r
+ }\r
+\r
+ private:\r
+\r
+ int m_nGroup;\r
+ char_type m_cDecPoint; \r
+ char_type m_cThousandsSep;\r
+ };\r
+\r
+ private:\r
+\r
+ void Assign(const ParserBase &a_Parser);\r
+ void InitTokenReader();\r
+ void ReInit() const;\r
+\r
+ void AddCallback( const string_type &a_strName, \r
+ const ParserCallback &a_Callback, \r
+ funmap_type &a_Storage,\r
+ const char_type *a_szCharSet );\r
+\r
+ void ApplyRemainingOprt(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const;\r
+ void ApplyBinOprt(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const;\r
+\r
+ void ApplyIfElse(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const;\r
+\r
+ void ApplyFunc(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal, \r
+ int iArgCount) const; \r
+\r
+ token_type ApplyStrFunc(const token_type &a_FunTok,\r
+ const std::vector<token_type> &a_vArg) const;\r
+\r
+ int GetOprtPrecedence(const token_type &a_Tok) const;\r
+ EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;\r
+\r
+ void CreateRPN() const;\r
+\r
+ value_type ParseString() const; \r
+ value_type ParseCmdCode() const;\r
+ value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;\r
+\r
+ void CheckName(const string_type &a_strName, const string_type &a_CharSet) const;\r
+ void CheckOprt(const string_type &a_sName,\r
+ const ParserCallback &a_Callback,\r
+ const string_type &a_szCharSet) const;\r
+\r
+ void StackDump(const ParserStack<token_type > &a_stVal, \r
+ const ParserStack<token_type > &a_stOprt) const;\r
+\r
+ /** \brief Pointer to the parser function. \r
+ \r
+ Eval() calls the function whose address is stored there.\r
+ */\r
+ mutable ParseFunction m_pParseFormula;\r
+ mutable ParserByteCode m_vRPN; ///< The Bytecode class.\r
+ mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments\r
+ stringbuf_type m_vStringVarBuf;\r
+\r
+ std::auto_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.\r
+\r
+ funmap_type m_FunDef; ///< Map of function names and pointers.\r
+ funmap_type m_PostOprtDef; ///< Postfix operator callbacks\r
+ funmap_type m_InfixOprtDef; ///< unary infix operator.\r
+ funmap_type m_OprtDef; ///< Binary operator callbacks\r
+ valmap_type m_ConstDef; ///< user constants.\r
+ strmap_type m_StrVarDef; ///< user defined string constants\r
+ varmap_type m_VarDef; ///< user defind variables.\r
+\r
+ bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off\r
+\r
+ string_type m_sNameChars; ///< Charset for names\r
+ string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens\r
+ string_type m_sInfixOprtChars; ///< Charset for infix operator tokens\r
+ \r
+ mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses\r
+\r
+ // items merely used for caching state information\r
+ mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine\r
+ mutable int m_nFinalResultIdx;\r
+};\r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_BYTECODE_H\r
+#define MU_PARSER_BYTECODE_H\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+\r
+#include "muParserDef.h"\r
+#include "muParserError.h"\r
+#include "muParserToken.h"\r
+\r
+/** \file\r
+ \brief Definition of the parser bytecode class.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+ struct SToken\r
+ {\r
+ ECmdCode Cmd;\r
+ int StackPos;\r
+\r
+ union u\r
+ {\r
+ struct sVal\r
+ {\r
+ value_type *ptr;\r
+ value_type data;\r
+ value_type data2;\r
+ } Val;\r
+\r
+ struct sFun\r
+ {\r
+ // Note: generic_fun_type is merely a placeholder. The real type could be \r
+ // anything between gun_type1 and fun_type9. I can't use a void\r
+ // pointer due to constraints in the ANSI standard which allows\r
+ // data pointers and function pointers to differ in size.\r
+ generic_fun_type ptr;\r
+ int argc;\r
+ int idx;\r
+ } Fun;\r
+\r
+ struct sOprt\r
+ {\r
+ value_type *ptr;\r
+ int offset;\r
+ } Oprt;\r
+ } u;\r
+ };\r
+ \r
+ \r
+ /** \brief Bytecode implementation of the Math Parser.\r
+\r
+ The bytecode contains the formula converted to revers polish notation stored in a continious\r
+ memory area. Associated with this data are operator codes, variable pointers, constant \r
+ values and function pointers. Those are necessary in order to calculate the result.\r
+ All those data items will be casted to the underlying datatype of the bytecode.\r
+\r
+ \author (C) 2004-2013 Ingo Berg \r
+*/\r
+class ParserByteCode\r
+{\r
+private:\r
+\r
+ /** \brief Token type for internal use only. */\r
+ typedef ParserToken<value_type, string_type> token_type;\r
+\r
+ /** \brief Token vector for storing the RPN. */\r
+ typedef std::vector<SToken> rpn_type;\r
+\r
+ /** \brief Position in the Calculation array. */\r
+ unsigned m_iStackPos;\r
+\r
+ /** \brief Maximum size needed for the stack. */\r
+ std::size_t m_iMaxStackSize;\r
+ \r
+ /** \brief The actual rpn storage. */\r
+ rpn_type m_vRPN;\r
+\r
+ bool m_bEnableOptimizer;\r
+\r
+ void ConstantFolding(ECmdCode a_Oprt);\r
+\r
+public:\r
+\r
+ ParserByteCode();\r
+ ParserByteCode(const ParserByteCode &a_ByteCode);\r
+ ParserByteCode& operator=(const ParserByteCode &a_ByteCode);\r
+ void Assign(const ParserByteCode &a_ByteCode);\r
+\r
+ void AddVar(value_type *a_pVar);\r
+ void AddVal(value_type a_fVal);\r
+ void AddOp(ECmdCode a_Oprt);\r
+ void AddIfElse(ECmdCode a_Oprt);\r
+ void AddAssignOp(value_type *a_pVar);\r
+ void AddFun(generic_fun_type a_pFun, int a_iArgc);\r
+ void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);\r
+ void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);\r
+\r
+ void EnableOptimizer(bool bStat);\r
+\r
+ void Finalize();\r
+ void clear();\r
+ std::size_t GetMaxStackSize() const;\r
+ std::size_t GetSize() const;\r
+\r
+ const SToken* GetBase() const;\r
+ void AsciiDump();\r
+};\r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_CALLBACK_H\r
+#define MU_PARSER_CALLBACK_H\r
+\r
+#include "muParserDef.h"\r
+\r
+/** \file\r
+ \brief Definition of the parser callback class.\r
+*/\r
+\r
+namespace mu\r
+{\r
+\r
+/** \brief Encapsulation of prototypes for a numerical parser function.\r
+\r
+ Encapsulates the prototyp for numerical parser functions. The class\r
+ stores the number of arguments for parser functions as well\r
+ as additional flags indication the function is non optimizeable.\r
+ The pointer to the callback function pointer is stored as void* \r
+ and needs to be casted according to the argument count.\r
+ Negative argument counts indicate a parser function with a variable number\r
+ of arguments. \r
+\r
+ \author (C) 2004-2011 Ingo Berg\r
+*/\r
+class ParserCallback\r
+{\r
+public:\r
+ ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);\r
+ ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity);\r
+ ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);\r
+\r
+ ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);\r
+\r
+ ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback();\r
+ ParserCallback(const ParserCallback &a_Fun);\r
+ \r
+ ParserCallback* Clone() const;\r
+\r
+ bool IsOptimizable() const;\r
+ void* GetAddr() const;\r
+ ECmdCode GetCode() const;\r
+ ETypeCode GetType() const;\r
+ int GetPri() const;\r
+ EOprtAssociativity GetAssociativity() const;\r
+ int GetArgc() const;\r
+\r
+private:\r
+ void *m_pFun; ///< Pointer to the callback function, casted to void\r
+ \r
+ /** \brief Number of numeric function arguments\r
+ \r
+ This number is negative for functions with variable number of arguments. in this cases\r
+ they represent the actual number of arguments found.\r
+ */\r
+ int m_iArgc; \r
+ int m_iPri; ///< Valid only for binary and infix operators; Operator precedence.\r
+ EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators \r
+ ECmdCode m_iCode;\r
+ ETypeCode m_iType;\r
+ bool m_bAllowOpti; ///< Flag indication optimizeability \r
+};\r
+\r
+//------------------------------------------------------------------------------\r
+/** \brief Container for Callback objects. */\r
+typedef std::map<string_type, ParserCallback> funmap_type; \r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_DLL_H\r
+#define MU_PARSER_DLL_H\r
+\r
+#if defined(WIN32) || defined(_WIN32)\r
+ #ifdef MUPARSERLIB_EXPORTS\r
+ #define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl\r
+ #else\r
+ #define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl\r
+ #endif\r
+#else\r
+ #define API_EXPORT(TYPE) TYPE\r
+#endif\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+/** \file \r
+ \brief This file contains the DLL interface of muparser.\r
+*/\r
+\r
+// Basic types\r
+typedef void* muParserHandle_t; // parser handle\r
+typedef char muChar_t; // character type\r
+typedef int muBool_t; // boolean type\r
+typedef int muInt_t; // integer type \r
+typedef double muFloat_t; // floating point type\r
+\r
+// function types for calculation\r
+typedef muFloat_t (*muFun0_t )(); \r
+typedef muFloat_t (*muFun1_t )(muFloat_t); \r
+typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+\r
+// Function prototypes for bulkmode functions\r
+typedef muFloat_t (*muBulkFun0_t )(int, int); \r
+typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t); \r
+typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+\r
+typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t);\r
+typedef muFloat_t (*muStrFun1_t)(const muChar_t*);\r
+typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t);\r
+typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t);\r
+\r
+// Functions for parser management\r
+typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler\r
+typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables\r
+typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+// Constants\r
+static const int muOPRT_ASCT_LEFT = 0;\r
+static const int muOPRT_ASCT_RIGHT = 1;\r
+\r
+static const int muBASETYPE_FLOAT = 0;\r
+static const int muBASETYPE_INT = 1;\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+//\r
+//\r
+// muParser C compatible bindings\r
+//\r
+//\r
+//-----------------------------------------------------------------------------------------------------\r
+\r
+\r
+// Basic operations / initialization \r
+API_EXPORT(muParserHandle_t) mupCreate(int nBaseType);\r
+API_EXPORT(void) mupRelease(muParserHandle_t a_hParser);\r
+API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr);\r
+API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData);\r
+API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser);\r
+API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser);\r
+API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum);\r
+API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize);\r
+\r
+// Defining callbacks / variables / constants\r
+API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize);\r
+\r
+// Defining bulkmode functions\r
+API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun);\r
+\r
+// string functions\r
+API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun);\r
+API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun);\r
+API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun);\r
+\r
+API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muMultFun_t a_pFun, \r
+ muBool_t a_bOptimize);\r
+\r
+API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun2_t a_pFun, \r
+ muInt_t a_nPrec, \r
+ muInt_t a_nOprtAsct,\r
+ muBool_t a_bOptimize);\r
+\r
+API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFloat_t a_fVal );\r
+\r
+API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ const muChar_t *a_sVal );\r
+\r
+API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFloat_t *a_fVar);\r
+\r
+API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFloat_t *a_fVar);\r
+\r
+API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun1_t a_pOprt, \r
+ muBool_t a_bOptimize);\r
+\r
+\r
+API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun1_t a_pOprt, \r
+ muBool_t a_bOptimize);\r
+\r
+// Define character sets for identifiers\r
+API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);\r
+API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);\r
+API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);\r
+\r
+// Remove all / single variables\r
+API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName);\r
+API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser);\r
+\r
+// Querying variables / expression variables / constants\r
+API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser);\r
+API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser);\r
+API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);\r
+API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);\r
+API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar);\r
+API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep);\r
+API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep);\r
+API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep);\r
+API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser);\r
+\r
+// Add value recognition callbacks\r
+API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t);\r
+\r
+// Error handling\r
+API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler);\r
+API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser);\r
+API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser);\r
+API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser);\r
+API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser);\r
+//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser);\r
+\r
+// This is used for .NET only. It creates a new variable allowing the dll to\r
+// manage the variable rather than the .NET garbage collector.\r
+API_EXPORT(muFloat_t*) mupCreateVar();\r
+API_EXPORT(void) mupReleaseVar(muFloat_t*);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // include guard\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MUP_DEF_H\r
+#define MUP_DEF_H\r
+\r
+#include <iostream>\r
+#include <string>\r
+#include <sstream>\r
+#include <map>\r
+\r
+#include "muParserFixes.h"\r
+\r
+/** \file\r
+ \brief This file contains standard definitions used by the parser.\r
+*/\r
+\r
+#define MUP_VERSION _T("2.2.3")\r
+#define MUP_VERSION_DATE _T("20121222; SF")\r
+\r
+#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")\r
+\r
+/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */\r
+//#define MUP_MATH_EXCEPTIONS\r
+\r
+/** \brief Define the base datatype for values.\r
+\r
+ This datatype must be a built in value type. You can not use custom classes.\r
+ It should be working with all types except "int"!\r
+*/\r
+#define MUP_BASETYPE double\r
+\r
+/** \brief Activate this option in order to compile with OpenMP support. \r
+\r
+ OpenMP is used only in the bulk mode it may increase the performance a bit. \r
+*/\r
+//#define MUP_USE_OPENMP\r
+\r
+#if defined(_UNICODE)\r
+ /** \brief Definition of the basic parser string type. */\r
+ #define MUP_STRING_TYPE std::wstring\r
+\r
+ #if !defined(_T)\r
+ #define _T(x) L##x\r
+ #endif // not defined _T\r
+#else\r
+ #ifndef _T\r
+ #define _T(x) x\r
+ #endif\r
+ \r
+ /** \brief Definition of the basic parser string type. */\r
+ #define MUP_STRING_TYPE std::string\r
+#endif\r
+\r
+#if defined(_DEBUG)\r
+ /** \brief Debug macro to force an abortion of the programm with a certain message.\r
+ */\r
+ #define MUP_FAIL(MSG) \\r
+ { \\r
+ bool MSG=false; \\r
+ assert(MSG); \\r
+ }\r
+\r
+ /** \brief An assertion that does not kill the program.\r
+\r
+ This macro is neutralised in UNICODE builds. It's\r
+ too difficult to translate.\r
+ */\r
+ #define MUP_ASSERT(COND) \\r
+ if (!(COND)) \\r
+ { \\r
+ stringstream_type ss; \\r
+ ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \\r
+ << __FILE__ << _T(" line ") \\r
+ << __LINE__ << _T("."); \\r
+ throw ParserError( ss.str() ); \\r
+ }\r
+#else\r
+ #define MUP_FAIL(MSG)\r
+ #define MUP_ASSERT(COND)\r
+#endif\r
+\r
+\r
+namespace mu\r
+{\r
+#if defined(_UNICODE)\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Encapsulate wcout. */\r
+ inline std::wostream& console()\r
+ {\r
+ return std::wcout;\r
+ }\r
+\r
+ /** \brief Encapsulate cin. */\r
+ inline std::wistream& console_in()\r
+ {\r
+ return std::wcin;\r
+ }\r
+\r
+#else\r
+\r
+ /** \brief Encapsulate cout. \r
+ \r
+ Used for supporting UNICODE more easily.\r
+ */\r
+ inline std::ostream& console()\r
+ {\r
+ return std::cout;\r
+ }\r
+\r
+ /** \brief Encapsulate cin. \r
+\r
+ Used for supporting UNICODE more easily.\r
+ */\r
+ inline std::istream& console_in()\r
+ {\r
+ return std::cin;\r
+ }\r
+\r
+#endif\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Bytecode values.\r
+\r
+ \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!\r
+ */\r
+ enum ECmdCode\r
+ {\r
+ // The following are codes for built in binary operators\r
+ // apart from built in operators the user has the opportunity to\r
+ // add user defined operators.\r
+ cmLE = 0, ///< Operator item: less or equal\r
+ cmGE = 1, ///< Operator item: greater or equal\r
+ cmNEQ = 2, ///< Operator item: not equal\r
+ cmEQ = 3, ///< Operator item: equals\r
+ cmLT = 4, ///< Operator item: less than\r
+ cmGT = 5, ///< Operator item: greater than\r
+ cmADD = 6, ///< Operator item: add\r
+ cmSUB = 7, ///< Operator item: subtract\r
+ cmMUL = 8, ///< Operator item: multiply\r
+ cmDIV = 9, ///< Operator item: division\r
+ cmPOW = 10, ///< Operator item: y to the power of ...\r
+ cmLAND = 11,\r
+ cmLOR = 12,\r
+ cmASSIGN = 13, ///< Operator item: Assignment operator\r
+ cmBO = 14, ///< Operator item: opening bracket\r
+ cmBC = 15, ///< Operator item: closing bracket\r
+ cmIF = 16, ///< For use in the ternary if-then-else operator\r
+ cmELSE = 17, ///< For use in the ternary if-then-else operator\r
+ cmENDIF = 18, ///< For use in the ternary if-then-else operator\r
+ cmARG_SEP = 19, ///< function argument separator\r
+ cmVAR = 20, ///< variable item\r
+ cmVAL = 21, ///< value item\r
+\r
+ // For optimization purposes\r
+ cmVARPOW2,\r
+ cmVARPOW3,\r
+ cmVARPOW4,\r
+ cmVARMUL,\r
+ cmPOW2,\r
+\r
+ // operators and functions\r
+ cmFUNC, ///< Code for a generic function item\r
+ cmFUNC_STR, ///< Code for a function with a string parameter\r
+ cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index \r
+ cmSTRING, ///< Code for a string token\r
+ cmOPRT_BIN, ///< user defined binary operator\r
+ cmOPRT_POSTFIX, ///< code for postfix operators\r
+ cmOPRT_INFIX, ///< code for infix operators\r
+ cmEND, ///< end of formula\r
+ cmUNKNOWN ///< uninitialized item\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Types internally used by the parser.\r
+ */\r
+ enum ETypeCode\r
+ {\r
+ tpSTR = 0, ///< String type (Function arguments and constants only, no string variables)\r
+ tpDBL = 1, ///< Floating point variables\r
+ tpVOID = 2 ///< Undefined type.\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ enum EParserVersionInfo\r
+ {\r
+ pviBRIEF,\r
+ pviFULL\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Parser operator precedence values. */\r
+ enum EOprtAssociativity\r
+ {\r
+ oaLEFT = 0,\r
+ oaRIGHT = 1,\r
+ oaNONE = 2\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Parser operator precedence values. */\r
+ enum EOprtPrecedence\r
+ {\r
+ // binary operators\r
+ prLOR = 1,\r
+ prLAND = 2,\r
+ prLOGIC = 3, ///< logic operators\r
+ prCMP = 4, ///< comparsion operators\r
+ prADD_SUB = 5, ///< addition\r
+ prMUL_DIV = 6, ///< multiplication/division\r
+ prPOW = 7, ///< power operator priority (highest)\r
+\r
+ // infix operators\r
+ prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator\r
+ prPOSTFIX = 6 ///< Postfix operator priority (currently unused)\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ // basic types\r
+\r
+ /** \brief The numeric datatype used by the parser. \r
+ \r
+ Normally this is a floating point type either single or double precision.\r
+ */\r
+ typedef MUP_BASETYPE value_type;\r
+\r
+ /** \brief The stringtype used by the parser. \r
+\r
+ Depends on wether UNICODE is used or not.\r
+ */\r
+ typedef MUP_STRING_TYPE string_type;\r
+\r
+ /** \brief The character type used by the parser. \r
+ \r
+ Depends on wether UNICODE is used or not.\r
+ */\r
+ typedef string_type::value_type char_type;\r
+\r
+ /** \brief Typedef for easily using stringstream that respect the parser stringtype. */\r
+ typedef std::basic_stringstream<char_type,\r
+ std::char_traits<char_type>,\r
+ std::allocator<char_type> > stringstream_type;\r
+\r
+ // Data container types\r
+\r
+ /** \brief Type used for storing variables. */\r
+ typedef std::map<string_type, value_type*> varmap_type;\r
+ \r
+ /** \brief Type used for storing constants. */\r
+ typedef std::map<string_type, value_type> valmap_type;\r
+ \r
+ /** \brief Type for assigning a string name to an index in the internal string table. */\r
+ typedef std::map<string_type, std::size_t> strmap_type;\r
+\r
+ // Parser callbacks\r
+ \r
+ /** \brief Callback type used for functions without arguments. */\r
+ typedef value_type (*generic_fun_type)();\r
+\r
+ /** \brief Callback type used for functions without arguments. */\r
+ typedef value_type (*fun_type0)();\r
+\r
+ /** \brief Callback type used for functions with a single arguments. */\r
+ typedef value_type (*fun_type1)(value_type);\r
+\r
+ /** \brief Callback type used for functions with two arguments. */\r
+ typedef value_type (*fun_type2)(value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with three arguments. */\r
+ typedef value_type (*fun_type3)(value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with four arguments. */\r
+ typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions without arguments. */\r
+ typedef value_type (*bulkfun_type0)(int, int);\r
+\r
+ /** \brief Callback type used for functions with a single arguments. */\r
+ typedef value_type (*bulkfun_type1)(int, int, value_type);\r
+\r
+ /** \brief Callback type used for functions with two arguments. */\r
+ typedef value_type (*bulkfun_type2)(int, int, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with three arguments. */\r
+ typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with four arguments. */\r
+ typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with a variable argument list. */\r
+ typedef value_type (*multfun_type)(const value_type*, int);\r
+\r
+ /** \brief Callback type used for functions taking a string as an argument. */\r
+ typedef value_type (*strfun_type1)(const char_type*);\r
+\r
+ /** \brief Callback type used for functions taking a string and a value as arguments. */\r
+ typedef value_type (*strfun_type2)(const char_type*, value_type);\r
+\r
+ /** \brief Callback type used for functions taking a string and two values as arguments. */\r
+ typedef value_type (*strfun_type3)(const char_type*, value_type, value_type);\r
+\r
+ /** \brief Callback used for functions that identify values in a string. */\r
+ typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal);\r
+\r
+ /** \brief Callback used for variable creation factory functions. */\r
+ typedef value_type* (*facfun_type)(const char_type*, void*);\r
+} // end of namespace\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_ERROR_H\r
+#define MU_PARSER_ERROR_H\r
+\r
+#include <cassert>\r
+#include <stdexcept>\r
+#include <string>\r
+#include <sstream>\r
+#include <vector>\r
+#include <memory>\r
+\r
+#include "muParserDef.h"\r
+\r
+/** \file \r
+ \brief This file defines the error class used by the parser.\r
+*/\r
+\r
+namespace mu\r
+{\r
+\r
+/** \brief Error codes. */\r
+enum EErrorCodes\r
+{\r
+ // Formula syntax errors\r
+ ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found\r
+ ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.\r
+ ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(")\r
+ ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23")\r
+ ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found\r
+ ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found\r
+ ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found\r
+ ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing\r
+ ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position\r
+ ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument\r
+ ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument\r
+ ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3")\r
+ ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)")\r
+ ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)")\r
+ ecTOO_MANY_PARAMS = 14, ///< Too many function parameters\r
+ ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)")\r
+ ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type\r
+ ecSTR_RESULT = 17, ///< result is a string\r
+\r
+ // Invalid Parser input Parameters\r
+ ecINVALID_NAME = 18, ///< Invalid function, variable or constant name.\r
+ ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier\r
+ ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name.\r
+ ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name.\r
+\r
+ ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator\r
+ ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer \r
+ ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer \r
+ ecEMPTY_EXPRESSION = 25, ///< The Expression is empty\r
+ ecNAME_CONFLICT = 26, ///< Name conflict\r
+ ecOPT_PRI = 27, ///< Invalid operator priority\r
+ // \r
+ ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused)\r
+ ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused)\r
+ ecGENERIC = 30, ///< Generic error\r
+ ecLOCALE = 31, ///< Conflict with current locale\r
+\r
+ ecUNEXPECTED_CONDITIONAL = 32,\r
+ ecMISSING_ELSE_CLAUSE = 33, \r
+ ecMISPLACED_COLON = 34,\r
+\r
+ // internal errors\r
+ ecINTERNAL_ERROR = 35, ///< Internal error of any kind.\r
+ \r
+ // The last two are special entries \r
+ ecCOUNT, ///< This is no error code, It just stores just the total number of error codes\r
+ ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages\r
+};\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief A class that handles the error messages.\r
+*/\r
+class ParserErrorMsg\r
+{\r
+public:\r
+ typedef ParserErrorMsg self_type;\r
+\r
+ ParserErrorMsg& operator=(const ParserErrorMsg &);\r
+ ParserErrorMsg(const ParserErrorMsg&);\r
+ ParserErrorMsg();\r
+\r
+ ~ParserErrorMsg();\r
+\r
+ static const ParserErrorMsg& Instance();\r
+ string_type operator[](unsigned a_iIdx) const;\r
+\r
+private:\r
+ std::vector<string_type> m_vErrMsg; ///< A vector with the predefined error messages\r
+ static const self_type m_Instance; ///< The instance pointer\r
+};\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Error class of the parser. \r
+ \author Ingo Berg\r
+\r
+ Part of the math parser package.\r
+*/\r
+class ParserError\r
+{\r
+private:\r
+\r
+ /** \brief Replace all ocuurences of a substring with another string. */\r
+ void ReplaceSubString( string_type &strSource, \r
+ const string_type &strFind,\r
+ const string_type &strReplaceWith);\r
+ void Reset();\r
+\r
+public:\r
+\r
+ ParserError();\r
+ explicit ParserError(EErrorCodes a_iErrc);\r
+ explicit ParserError(const string_type &sMsg);\r
+ ParserError( EErrorCodes a_iErrc,\r
+ const string_type &sTok,\r
+ const string_type &sFormula = string_type(),\r
+ int a_iPos = -1);\r
+ ParserError( EErrorCodes a_iErrc, \r
+ int a_iPos, \r
+ const string_type &sTok);\r
+ ParserError( const char_type *a_szMsg, \r
+ int a_iPos = -1, \r
+ const string_type &sTok = string_type());\r
+ ParserError(const ParserError &a_Obj);\r
+ ParserError& operator=(const ParserError &a_Obj);\r
+ ~ParserError();\r
+\r
+ void SetFormula(const string_type &a_strFormula);\r
+ const string_type& GetExpr() const;\r
+ const string_type& GetMsg() const;\r
+ std::size_t GetPos() const;\r
+ const string_type& GetToken() const;\r
+ EErrorCodes GetCode() const;\r
+\r
+private:\r
+ string_type m_strMsg; ///< The message string\r
+ string_type m_strFormula; ///< Formula string\r
+ string_type m_strTok; ///< Token related with the error\r
+ int m_iPos; ///< Formula position related to the error \r
+ EErrorCodes m_iErrc; ///< Error code\r
+ const ParserErrorMsg &m_ErrMsg;\r
+}; \r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_FIXES_H\r
+#define MU_PARSER_FIXES_H\r
+\r
+/** \file\r
+ \brief This file contains compatibility fixes for some platforms.\r
+*/\r
+\r
+//\r
+// Compatibility fixes\r
+//\r
+\r
+//---------------------------------------------------------------------------\r
+//\r
+// Intel Compiler\r
+//\r
+//---------------------------------------------------------------------------\r
+\r
+#ifdef __INTEL_COMPILER\r
+\r
+// remark #981: operands are evaluated in unspecified order\r
+// disabled -> completely pointless if the functions do not have side effects\r
+//\r
+#pragma warning(disable:981)\r
+\r
+// remark #383: value copied to temporary, reference to temporary used\r
+#pragma warning(disable:383)\r
+\r
+// remark #1572: floating-point equality and inequality comparisons are unreliable\r
+// disabled -> everyone knows it, the parser passes this problem\r
+// deliberately to the user\r
+#pragma warning(disable:1572)\r
+\r
+#endif\r
+\r
+#endif // include guard\r
+\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_INT_H\r
+#define MU_PARSER_INT_H\r
+\r
+#include "muParserBase.h"\r
+#include <vector>\r
+\r
+\r
+/** \file\r
+ \brief Definition of a parser using integer value.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+\r
+/** \brief Mathematical expressions parser.\r
+ \r
+ This version of the parser handles only integer numbers. It disables the built in operators thus it is \r
+ slower than muParser. Integer values are stored in the double value_type and converted if needed.\r
+*/\r
+class ParserInt : public ParserBase\r
+{\r
+private:\r
+ static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };\r
+ \r
+ static value_type Abs(value_type);\r
+ static value_type Sign(value_type);\r
+ static value_type Ite(value_type, value_type, value_type);\r
+ // !! The unary Minus is a MUST, otherwise you cant use negative signs !!\r
+ static value_type UnaryMinus(value_type);\r
+ // Functions with variable number of arguments\r
+ static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum\r
+ static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum\r
+ static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum\r
+ // binary operator callbacks\r
+ static value_type Add(value_type v1, value_type v2);\r
+ static value_type Sub(value_type v1, value_type v2);\r
+ static value_type Mul(value_type v1, value_type v2);\r
+ static value_type Div(value_type v1, value_type v2);\r
+ static value_type Mod(value_type v1, value_type v2);\r
+ static value_type Pow(value_type v1, value_type v2);\r
+ static value_type Shr(value_type v1, value_type v2);\r
+ static value_type Shl(value_type v1, value_type v2);\r
+ static value_type LogAnd(value_type v1, value_type v2);\r
+ static value_type LogOr(value_type v1, value_type v2);\r
+ static value_type And(value_type v1, value_type v2);\r
+ static value_type Or(value_type v1, value_type v2);\r
+ static value_type Xor(value_type v1, value_type v2);\r
+ static value_type Less(value_type v1, value_type v2);\r
+ static value_type Greater(value_type v1, value_type v2);\r
+ static value_type LessEq(value_type v1, value_type v2);\r
+ static value_type GreaterEq(value_type v1, value_type v2);\r
+ static value_type Equal(value_type v1, value_type v2);\r
+ static value_type NotEqual(value_type v1, value_type v2);\r
+ static value_type Not(value_type v1);\r
+\r
+ static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
+ static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
+ static int IsVal (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
+\r
+ /** \brief A facet class used to change decimal and thousands separator. */\r
+ template<class TChar>\r
+ class change_dec_sep : public std::numpunct<TChar>\r
+ {\r
+ public:\r
+ \r
+ explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)\r
+ :std::numpunct<TChar>()\r
+ ,m_cDecPoint(cDecSep)\r
+ ,m_cThousandsSep(cThousandsSep)\r
+ ,m_nGroup(nGroup)\r
+ {}\r
+ \r
+ protected:\r
+ \r
+ virtual char_type do_decimal_point() const\r
+ {\r
+ return m_cDecPoint;\r
+ }\r
+\r
+ virtual char_type do_thousands_sep() const\r
+ {\r
+ return m_cThousandsSep;\r
+ }\r
+\r
+ virtual std::string do_grouping() const \r
+ { \r
+ return std::string(1, m_nGroup); \r
+ }\r
+\r
+ private:\r
+\r
+ int m_nGroup;\r
+ char_type m_cDecPoint; \r
+ char_type m_cThousandsSep;\r
+ };\r
+\r
+public:\r
+ ParserInt();\r
+\r
+ virtual void InitFun();\r
+ virtual void InitOprt();\r
+ virtual void InitConst();\r
+ virtual void InitCharSets();\r
+};\r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_STACK_H\r
+#define MU_PARSER_STACK_H\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+\r
+#include "muParserError.h"\r
+#include "muParserToken.h"\r
+\r
+/** \file \r
+ \brief This file defines the stack used by muparser.\r
+*/\r
+\r
+namespace mu\r
+{\r
+\r
+ /** \brief Parser stack implementation. \r
+\r
+ Stack implementation based on a std::stack. The behaviour of pop() had been\r
+ slightly changed in order to get an error code if the stack is empty.\r
+ The stack is used within the Parser both as a value stack and as an operator stack.\r
+\r
+ \author (C) 2004-2011 Ingo Berg \r
+ */\r
+ template <typename TValueType>\r
+ class ParserStack \r
+ {\r
+ private:\r
+\r
+ /** \brief Type of the underlying stack implementation. */\r
+ typedef std::stack<TValueType, std::vector<TValueType> > impl_type;\r
+ \r
+ impl_type m_Stack; ///< This is the actual stack.\r
+\r
+ public: \r
+ \r
+ //---------------------------------------------------------------------------\r
+ ParserStack()\r
+ :m_Stack()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ virtual ~ParserStack()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Pop a value from the stack.\r
+ \r
+ Unlike the standard implementation this function will return the value that\r
+ is going to be taken from the stack.\r
+\r
+ \throw ParserException in case the stack is empty.\r
+ \sa pop(int &a_iErrc)\r
+ */\r
+ TValueType pop()\r
+ {\r
+ if (empty())\r
+ throw ParserError( _T("stack is empty.") );\r
+\r
+ TValueType el = top();\r
+ m_Stack.pop();\r
+ return el;\r
+ }\r
+\r
+ /** \brief Push an object into the stack. \r
+\r
+ \param a_Val object to push into the stack.\r
+ \throw nothrow\r
+ */\r
+ void push(const TValueType& a_Val) \r
+ { \r
+ m_Stack.push(a_Val); \r
+ }\r
+\r
+ /** \brief Return the number of stored elements. */\r
+ unsigned size() const\r
+ { \r
+ return (unsigned)m_Stack.size(); \r
+ }\r
+\r
+ /** \brief Returns true if stack is empty false otherwise. */\r
+ bool empty() const\r
+ {\r
+ return m_Stack.size()==0; \r
+ }\r
+ \r
+ /** \brief Return reference to the top object in the stack. \r
+ \r
+ The top object is the one pushed most recently.\r
+ */\r
+ TValueType& top() \r
+ { \r
+ return m_Stack.top(); \r
+ }\r
+ };\r
+} // namespace MathUtils\r
+\r
+#endif\r
--- /dev/null
+#ifndef MU_PARSER_TEMPLATE_MAGIC_H\r
+#define MU_PARSER_TEMPLATE_MAGIC_H\r
+\r
+#include <cmath>\r
+#include "muParserError.h"\r
+\r
+\r
+namespace mu\r
+{\r
+ //-----------------------------------------------------------------------------------------------\r
+ //\r
+ // Compile time type detection\r
+ //\r
+ //-----------------------------------------------------------------------------------------------\r
+\r
+ /** \brief A class singling out integer types at compile time using \r
+ template meta programming.\r
+ */\r
+ template<typename T>\r
+ struct TypeInfo\r
+ {\r
+ static bool IsInteger() { return false; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<char>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<short>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<int>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<long>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned char>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned short>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned int>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned long>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+\r
+ //-----------------------------------------------------------------------------------------------\r
+ //\r
+ // Standard math functions with dummy overload for integer types\r
+ //\r
+ //-----------------------------------------------------------------------------------------------\r
+\r
+ /** \brief A template class for providing wrappers for essential math functions.\r
+\r
+ This template is spezialized for several types in order to provide a unified interface\r
+ for parser internal math function calls regardless of the data type.\r
+ */\r
+ template<typename T>\r
+ struct MathImpl\r
+ {\r
+ static T Sin(T v) { return sin(v); }\r
+ static T Cos(T v) { return cos(v); }\r
+ static T Tan(T v) { return tan(v); }\r
+ static T ASin(T v) { return asin(v); }\r
+ static T ACos(T v) { return acos(v); }\r
+ static T ATan(T v) { return atan(v); }\r
+ static T ATan2(T v1, T v2) { return atan2(v1, v2); }\r
+ static T Sinh(T v) { return sinh(v); }\r
+ static T Cosh(T v) { return cosh(v); }\r
+ static T Tanh(T v) { return tanh(v); }\r
+ static T ASinh(T v) { return log(v + sqrt(v * v + 1)); }\r
+ static T ACosh(T v) { return log(v + sqrt(v * v - 1)); }\r
+ static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); }\r
+ static T Log(T v) { return log(v); } \r
+ static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2\r
+ static T Log10(T v) { return log10(v); } // Logarithm base 10\r
+ static T Exp(T v) { return exp(v); }\r
+ static T Abs(T v) { return (v>=0) ? v : -v; }\r
+ static T Sqrt(T v) { return sqrt(v); }\r
+ static T Rint(T v) { return floor(v + (T)0.5); }\r
+ static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); }\r
+ static T Pow(T v1, T v2) { return std::pow(v1, v2); }\r
+ };\r
+\r
+ // Create (mostly) dummy math function definitions for integer types. They are mostly\r
+ // empty since they are not applicable for integer values.\r
+#define MAKE_MATH_DUMMY(TYPE) \\r
+ template<> \\r
+ struct MathImpl<TYPE> \\r
+ { \\r
+ static TYPE Sin(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Cos(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Tan(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ASin(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ACos(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ATan(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ATan2(TYPE, TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Sinh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Cosh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Tanh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ASinh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ACosh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ATanh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Log(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Log2(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Log10(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Exp(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Abs(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Sqrt(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Rint(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Sign(TYPE v) { return (TYPE)((v<0) ? -1 : (v>0) ? 1 : 0); } \\r
+ static TYPE Pow(TYPE v1, TYPE v2) { return (TYPE)std::pow((double)v1, (double)v2); } \\r
+ };\r
+\r
+ MAKE_MATH_DUMMY(char)\r
+ MAKE_MATH_DUMMY(short)\r
+ MAKE_MATH_DUMMY(int)\r
+ MAKE_MATH_DUMMY(long)\r
+\r
+#undef MAKE_MATH_DUMMY\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_TEST_H\r
+#define MU_PARSER_TEST_H\r
+\r
+#include <string>\r
+#include <cstdlib>\r
+#include <numeric> // for accumulate\r
+#include "muParser.h"\r
+#include "muParserInt.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser test class.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ /** \brief Namespace for test cases. */\r
+ namespace Test\r
+ {\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Test cases for unit testing.\r
+\r
+ (C) 2004-2011 Ingo Berg\r
+ */\r
+ class ParserTester // final\r
+ {\r
+ private:\r
+ static int c_iCount;\r
+\r
+ // Multiarg callbacks\r
+ static value_type f1of1(value_type v) { return v;};\r
+ \r
+ static value_type f1of2(value_type v, value_type ) {return v;};\r
+ static value_type f2of2(value_type , value_type v) {return v;};\r
+\r
+ static value_type f1of3(value_type v, value_type , value_type ) {return v;};\r
+ static value_type f2of3(value_type , value_type v, value_type ) {return v;};\r
+ static value_type f3of3(value_type , value_type , value_type v) {return v;};\r
+ \r
+ static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;}\r
+ static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;}\r
+ static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;}\r
+ static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;}\r
+\r
+ static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; }\r
+ static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; }\r
+ static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; }\r
+ static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; }\r
+ static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; }\r
+\r
+ static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; }\r
+ static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; }\r
+\r
+ static value_type plus2(value_type v1) { return v1+2; }\r
+ static value_type times3(value_type v1) { return v1*3; }\r
+ static value_type sqr(value_type v1) { return v1*v1; }\r
+ static value_type sign(value_type v) { return -v; }\r
+ static value_type add(value_type v1, value_type v2) { return v1+v2; }\r
+ static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; }\r
+ \r
+\r
+ static value_type FirstArg(const value_type* a_afArg, int a_iArgc)\r
+ {\r
+ if (!a_iArgc) \r
+ throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") );\r
+\r
+ return a_afArg[0];\r
+ }\r
+\r
+ static value_type LastArg(const value_type* a_afArg, int a_iArgc)\r
+ {\r
+ if (!a_iArgc) \r
+ throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") );\r
+\r
+ return a_afArg[a_iArgc-1];\r
+ }\r
+\r
+ static value_type Sum(const value_type* a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw mu::Parser::exception_type( _T("too few arguments for function sum.") );\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
+ return fRes;\r
+ }\r
+\r
+ static value_type Rnd(value_type v)\r
+ {\r
+ return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0)));\r
+ }\r
+\r
+ static value_type RndWithString(const char_type*)\r
+ {\r
+ return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );\r
+ }\r
+\r
+ static value_type Ping()\r
+ { \r
+ return 10; \r
+ }\r
+\r
+ static value_type ValueOf(const char_type*) \r
+ { \r
+ return 123; \r
+ }\r
+\r
+ static value_type StrFun1(const char_type* v1) \r
+ { \r
+ int val(0);\r
+ stringstream_type(v1) >> val;\r
+ return (value_type)val;\r
+ }\r
+\r
+ static value_type StrFun2(const char_type* v1, value_type v2) \r
+ { \r
+ int val(0);\r
+ stringstream_type(v1) >> val;\r
+ return (value_type)(val + v2);\r
+ }\r
+ \r
+ static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) \r
+ { \r
+ int val(0);\r
+ stringstream_type(v1) >> val;\r
+ return val + v2 + v3;\r
+ }\r
+\r
+ static value_type StrToFloat(const char_type* a_szMsg)\r
+ {\r
+ value_type val(0);\r
+ stringstream_type(a_szMsg) >> val;\r
+ return val;\r
+ }\r
+\r
+ // postfix operator callback\r
+ static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; }\r
+ static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; }\r
+ static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }\r
+\r
+ // Custom value recognition\r
+ static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal);\r
+\r
+ int TestNames();\r
+ int TestSyntax();\r
+ int TestMultiArg();\r
+ int TestPostFix();\r
+ int TestExpression();\r
+ int TestInfixOprt();\r
+ int TestBinOprt();\r
+ int TestVarConst();\r
+ int TestInterface();\r
+ int TestException();\r
+ int TestStrArg();\r
+ int TestIfThenElse();\r
+\r
+ void Abort() const;\r
+\r
+ public:\r
+ typedef int (ParserTester::*testfun_type)();\r
+\r
+ ParserTester();\r
+ void Run();\r
+\r
+ private:\r
+ std::vector<testfun_type> m_vTestFun;\r
+ void AddTest(testfun_type a_pFun);\r
+\r
+ // Test Double Parser\r
+ int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);\r
+ int EqnTestWithVarChange(const string_type& a_str, \r
+ double a_fRes1, \r
+ double a_fVar1, \r
+ double a_fRes2, \r
+ double a_fVar2);\r
+ int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);\r
+\r
+ // Test Int Parser\r
+ int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);\r
+ };\r
+ } // namespace Test\r
+} // namespace mu\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_TOKEN_H\r
+#define MU_PARSER_TOKEN_H\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+#include <memory>\r
+\r
+#include "muParserError.h"\r
+#include "muParserCallback.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser token definition.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ /** \brief Encapsulation of the data for a single formula token. \r
+\r
+ Formula token implementation. Part of the Math Parser Package.\r
+ Formula tokens can be either one of the following:\r
+ <ul>\r
+ <li>value</li>\r
+ <li>variable</li>\r
+ <li>function with numerical arguments</li>\r
+ <li>functions with a string as argument</li>\r
+ <li>prefix operators</li>\r
+ <li>infix operators</li>\r
+ <li>binary operator</li>\r
+ </ul>\r
+\r
+ \author (C) 2004-2013 Ingo Berg \r
+ */\r
+ template<typename TBase, typename TString>\r
+ class ParserToken\r
+ {\r
+ private:\r
+\r
+ ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode.\r
+ ETypeCode m_iType;\r
+ void *m_pTok; ///< Stores Token pointer; not applicable for all tokens\r
+ int m_iIdx; ///< An otional index to an external buffer storing the token data\r
+ TString m_strTok; ///< Token string\r
+ TString m_strVal; ///< Value for string variables\r
+ value_type m_fVal; ///< the value \r
+ std::auto_ptr<ParserCallback> m_pCallback;\r
+\r
+ public:\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor (default).\r
+ \r
+ Sets token to an neutral state of type cmUNKNOWN.\r
+ \throw nothrow\r
+ \sa ECmdCode\r
+ */\r
+ ParserToken()\r
+ :m_iCode(cmUNKNOWN)\r
+ ,m_iType(tpVOID)\r
+ ,m_pTok(0)\r
+ ,m_iIdx(-1)\r
+ ,m_strTok()\r
+ ,m_pCallback()\r
+ {}\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Create token from another one.\r
+ \r
+ Implemented by calling Assign(...)\r
+ \throw nothrow\r
+ \post m_iType==cmUNKNOWN\r
+ \sa #Assign\r
+ */\r
+ ParserToken(const ParserToken &a_Tok)\r
+ {\r
+ Assign(a_Tok);\r
+ }\r
+ \r
+ //------------------------------------------------------------------------------\r
+ /** \brief Assignement operator. \r
+ \r
+ Copy token state from another token and return this.\r
+ Implemented by calling Assign(...).\r
+ \throw nothrow\r
+ */\r
+ ParserToken& operator=(const ParserToken &a_Tok)\r
+ {\r
+ Assign(a_Tok);\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Copy token information from argument.\r
+ \r
+ \throw nothrow\r
+ */\r
+ void Assign(const ParserToken &a_Tok)\r
+ {\r
+ m_iCode = a_Tok.m_iCode;\r
+ m_pTok = a_Tok.m_pTok;\r
+ m_strTok = a_Tok.m_strTok;\r
+ m_iIdx = a_Tok.m_iIdx;\r
+ m_strVal = a_Tok.m_strVal;\r
+ m_iType = a_Tok.m_iType;\r
+ m_fVal = a_Tok.m_fVal;\r
+ // create new callback object if a_Tok has one \r
+ m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Assign a token type. \r
+\r
+ Token may not be of type value, variable or function. Those have seperate set functions. \r
+\r
+ \pre [assert] a_iType!=cmVAR\r
+ \pre [assert] a_iType!=cmVAL\r
+ \pre [assert] a_iType!=cmFUNC\r
+ \post m_fVal = 0\r
+ \post m_pTok = 0\r
+ */\r
+ ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())\r
+ {\r
+ // The following types cant be set this way, they have special Set functions\r
+ assert(a_iType!=cmVAR);\r
+ assert(a_iType!=cmVAL);\r
+ assert(a_iType!=cmFUNC);\r
+\r
+ m_iCode = a_iType;\r
+ m_iType = tpVOID;\r
+ m_pTok = 0;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = -1;\r
+\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set Callback type. */\r
+ ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)\r
+ {\r
+ assert(a_pCallback.GetAddr());\r
+\r
+ m_iCode = a_pCallback.GetCode();\r
+ m_iType = tpVOID;\r
+ m_strTok = a_sTok;\r
+ m_pCallback.reset(new ParserCallback(a_pCallback));\r
+\r
+ m_pTok = 0;\r
+ m_iIdx = -1;\r
+ \r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Make this token a value token. \r
+ \r
+ Member variables not necessary for value tokens will be invalidated.\r
+ \throw nothrow\r
+ */\r
+ ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())\r
+ {\r
+ m_iCode = cmVAL;\r
+ m_iType = tpDBL;\r
+ m_fVal = a_fVal;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = -1;\r
+ \r
+ m_pTok = 0;\r
+ m_pCallback.reset(0);\r
+\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief make this token a variable token. \r
+ \r
+ Member variables not necessary for variable tokens will be invalidated.\r
+ \throw nothrow\r
+ */\r
+ ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)\r
+ {\r
+ m_iCode = cmVAR;\r
+ m_iType = tpDBL;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = -1;\r
+ m_pTok = (void*)a_pVar;\r
+ m_pCallback.reset(0);\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Make this token a variable token. \r
+ \r
+ Member variables not necessary for variable tokens will be invalidated.\r
+ \throw nothrow\r
+ */\r
+ ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)\r
+ {\r
+ m_iCode = cmSTRING;\r
+ m_iType = tpSTR;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = static_cast<int>(a_iSize);\r
+\r
+ m_pTok = 0;\r
+ m_pCallback.reset(0);\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set an index associated with the token related data. \r
+ \r
+ In cmSTRFUNC - This is the index to a string table in the main parser.\r
+ \param a_iIdx The index the string function result will take in the bytecode parser.\r
+ \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING\r
+ */\r
+ void SetIdx(int a_iIdx)\r
+ {\r
+ if (m_iCode!=cmSTRING || a_iIdx<0)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+ \r
+ m_iIdx = a_iIdx;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return Index associated with the token related data. \r
+ \r
+ In cmSTRFUNC - This is the index to a string table in the main parser.\r
+\r
+ \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING\r
+ \return The index the result will take in the Bytecode calculatin array (#m_iIdx).\r
+ */\r
+ int GetIdx() const\r
+ {\r
+ if (m_iIdx<0 || m_iCode!=cmSTRING )\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_iIdx;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the token type.\r
+ \r
+ \return #m_iType\r
+ \throw nothrow\r
+ */\r
+ ECmdCode GetCode() const\r
+ {\r
+ if (m_pCallback.get())\r
+ {\r
+ return m_pCallback->GetCode();\r
+ }\r
+ else\r
+ {\r
+ return m_iCode;\r
+ }\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ ETypeCode GetType() const\r
+ {\r
+ if (m_pCallback.get())\r
+ {\r
+ return m_pCallback->GetType();\r
+ }\r
+ else\r
+ {\r
+ return m_iType;\r
+ }\r
+ }\r
+ \r
+ //------------------------------------------------------------------------------\r
+ int GetPri() const\r
+ {\r
+ if ( !m_pCallback.get())\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+ \r
+ if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_pCallback->GetPri();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ EOprtAssociativity GetAssociativity() const\r
+ {\r
+ if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_pCallback->GetAssociativity();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the address of the callback function assoziated with\r
+ function and operator tokens.\r
+\r
+ \return The pointer stored in #m_pTok.\r
+ \throw exception_type if token type is non of:\r
+ <ul>\r
+ <li>cmFUNC</li>\r
+ <li>cmSTRFUNC</li>\r
+ <li>cmPOSTOP</li>\r
+ <li>cmINFIXOP</li>\r
+ <li>cmOPRT_BIN</li>\r
+ </ul>\r
+ \sa ECmdCode\r
+ */\r
+ generic_fun_type GetFuncAddr() const\r
+ {\r
+ return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \biref Get value of the token.\r
+ \r
+ Only applicable to variable and value tokens.\r
+ \throw exception_type if token is no value/variable token.\r
+ */\r
+ TBase GetVal() const\r
+ {\r
+ switch (m_iCode)\r
+ {\r
+ case cmVAL: return m_fVal;\r
+ case cmVAR: return *((TBase*)m_pTok);\r
+ default: throw ParserError(ecVAL_EXPECTED);\r
+ }\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Get address of a variable token.\r
+\r
+ Valid only if m_iType==CmdVar.\r
+ \throw exception_type if token is no variable token.\r
+ */\r
+ TBase* GetVar() const\r
+ {\r
+ if (m_iCode!=cmVAR)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return (TBase*)m_pTok;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the number of function arguments. \r
+\r
+ Valid only if m_iType==CmdFUNC.\r
+ */\r
+ int GetArgCount() const\r
+ {\r
+ assert(m_pCallback.get());\r
+\r
+ if (!m_pCallback->GetAddr())\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_pCallback->GetArgc();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the token identifier. \r
+ \r
+ If #m_iType is cmSTRING the token identifier is the value of the string argument\r
+ for a string function.\r
+ \return #m_strTok\r
+ \throw nothrow\r
+ \sa m_strTok\r
+ */\r
+ const TString& GetAsString() const\r
+ {\r
+ return m_strTok;\r
+ }\r
+ };\r
+} // namespace mu\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_TOKEN_READER_H\r
+#define MU_PARSER_TOKEN_READER_H\r
+\r
+#include <cassert>\r
+#include <cstdio>\r
+#include <cstring>\r
+#include <list>\r
+#include <map>\r
+#include <memory>\r
+#include <stack>\r
+#include <string>\r
+\r
+#include "muParserDef.h"\r
+#include "muParserToken.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser token reader definition.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+ // Forward declaration\r
+ class ParserBase;\r
+\r
+ /** \brief Token reader for the ParserBase class.\r
+\r
+ */\r
+ class ParserTokenReader \r
+ {\r
+ private:\r
+\r
+ typedef ParserToken<value_type, string_type> token_type;\r
+\r
+ public:\r
+\r
+ ParserTokenReader(ParserBase *a_pParent);\r
+ ParserTokenReader* Clone(ParserBase *a_pParent) const;\r
+\r
+ void AddValIdent(identfun_type a_pCallback);\r
+ void SetVarCreator(facfun_type a_pFactory, void *pUserData);\r
+ void SetFormula(const string_type &a_strFormula);\r
+ void SetArgSep(char_type cArgSep);\r
+\r
+ int GetPos() const;\r
+ const string_type& GetExpr() const;\r
+ varmap_type& GetUsedVar();\r
+ char_type GetArgSep() const;\r
+\r
+ void IgnoreUndefVar(bool bIgnore);\r
+ void ReInit();\r
+ token_type ReadNextToken();\r
+\r
+ private:\r
+\r
+ /** \brief Syntax codes. \r
+ \r
+ The syntax codes control the syntax check done during the first time parsing of \r
+ the expression string. They are flags that indicate which tokens are allowed next\r
+ if certain tokens are identified.\r
+ */\r
+ enum ESynCodes\r
+ {\r
+ noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" \r
+ noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"\r
+ noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14"\r
+ noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a"\r
+ noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ...\r
+ noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" \r
+ noOPT = 1 << 6, ///< to avoid i.e. "(+)"\r
+ noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!"\r
+ noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4"\r
+ noEND = 1 << 9, ///< to avoid unexpected end of formula\r
+ noSTR = 1 << 10, ///< to block numeric arguments on string functions\r
+ noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7"\r
+ noIF = 1 << 12,\r
+ noELSE = 1 << 13,\r
+ sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,\r
+ noANY = ~0 ///< All of he above flags set\r
+ }; \r
+\r
+ ParserTokenReader(const ParserTokenReader &a_Reader);\r
+ ParserTokenReader& operator=(const ParserTokenReader &a_Reader);\r
+ void Assign(const ParserTokenReader &a_Reader);\r
+\r
+ void SetParent(ParserBase *a_pParent);\r
+ int ExtractToken(const char_type *a_szCharSet, \r
+ string_type &a_strTok, \r
+ int a_iPos) const;\r
+ int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const;\r
+\r
+ bool IsBuiltIn(token_type &a_Tok);\r
+ bool IsArgSep(token_type &a_Tok);\r
+ bool IsEOF(token_type &a_Tok);\r
+ bool IsInfixOpTok(token_type &a_Tok);\r
+ bool IsFunTok(token_type &a_Tok);\r
+ bool IsPostOpTok(token_type &a_Tok);\r
+ bool IsOprt(token_type &a_Tok);\r
+ bool IsValTok(token_type &a_Tok);\r
+ bool IsVarTok(token_type &a_Tok);\r
+ bool IsStrVarTok(token_type &a_Tok);\r
+ bool IsUndefVarTok(token_type &a_Tok);\r
+ bool IsString(token_type &a_Tok);\r
+ void Error(EErrorCodes a_iErrc, \r
+ int a_iPos = -1, \r
+ const string_type &a_sTok = string_type() ) const;\r
+\r
+ token_type& SaveBeforeReturn(const token_type &tok);\r
+\r
+ ParserBase *m_pParser;\r
+ string_type m_strFormula;\r
+ int m_iPos;\r
+ int m_iSynFlags;\r
+ bool m_bIgnoreUndefVar;\r
+\r
+ const funmap_type *m_pFunDef;\r
+ const funmap_type *m_pPostOprtDef;\r
+ const funmap_type *m_pInfixOprtDef;\r
+ const funmap_type *m_pOprtDef;\r
+ const valmap_type *m_pConstDef;\r
+ const strmap_type *m_pStrVarDef;\r
+ varmap_type *m_pVarDef; ///< The only non const pointer to parser internals\r
+ facfun_type m_pFactory;\r
+ void *m_pFactoryData;\r
+ std::list<identfun_type> m_vIdentFun; ///< Value token identification function\r
+ varmap_type m_UsedVar;\r
+ value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables\r
+ int m_iBrackets;\r
+ token_type m_lastTok;\r
+ char_type m_cArgSep; ///< The character used for separating function arguments\r
+ };\r
+} // namespace mu\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/* \r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+\r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#include "muParser.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <cmath>\r
+#include <algorithm>\r
+#include <numeric>\r
+\r
+/** \brief Pi (what else?). */\r
+#define PARSER_CONST_PI 3.141592653589793238462643\r
+\r
+/** \brief The eulerian number. */\r
+#define PARSER_CONST_E 2.718281828459045235360287\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief Implementation of the standard floating point parser.\r
+*/\r
+\r
+\r
+\r
+/** \brief Namespace for mathematical applications. */\r
+namespace mu\r
+{\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ // Trigonometric function\r
+ value_type Parser::Sin(value_type v) { return MathImpl<value_type>::Sin(v); }\r
+ value_type Parser::Cos(value_type v) { return MathImpl<value_type>::Cos(v); }\r
+ value_type Parser::Tan(value_type v) { return MathImpl<value_type>::Tan(v); }\r
+ value_type Parser::ASin(value_type v) { return MathImpl<value_type>::ASin(v); }\r
+ value_type Parser::ACos(value_type v) { return MathImpl<value_type>::ACos(v); }\r
+ value_type Parser::ATan(value_type v) { return MathImpl<value_type>::ATan(v); }\r
+ value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); }\r
+ value_type Parser::Sinh(value_type v) { return MathImpl<value_type>::Sinh(v); }\r
+ value_type Parser::Cosh(value_type v) { return MathImpl<value_type>::Cosh(v); }\r
+ value_type Parser::Tanh(value_type v) { return MathImpl<value_type>::Tanh(v); }\r
+ value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); }\r
+ value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); }\r
+ value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); }\r
+\r
+ //---------------------------------------------------------------------------\r
+ // Logarithm functions\r
+\r
+ // Logarithm base 2\r
+ value_type Parser::Log2(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<=0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("Log2"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Log2(v); \r
+ } \r
+\r
+ // Logarithm base 10\r
+ value_type Parser::Log10(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<=0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("Log10"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Log10(v); \r
+ } \r
+\r
+// Logarithm base e (natural logarithm)\r
+ value_type Parser::Ln(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<=0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("Ln"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Log(v); \r
+ } \r
+\r
+ //---------------------------------------------------------------------------\r
+ // misc\r
+ value_type Parser::Exp(value_type v) { return MathImpl<value_type>::Exp(v); }\r
+ value_type Parser::Abs(value_type v) { return MathImpl<value_type>::Abs(v); }\r
+ value_type Parser::Sqrt(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("sqrt"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Sqrt(v); \r
+ }\r
+ value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); }\r
+ value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for the unary minus operator.\r
+ \param v The value to negate\r
+ \return -v\r
+ */\r
+ value_type Parser::UnaryMinus(value_type v) \r
+ { \r
+ return -v; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for adding multiple values. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function sum."));\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
+ return fRes;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for averaging multiple values. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function sum."));\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
+ return fRes/(value_type)a_iArgc;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for determining the minimum value out of a vector. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Min(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function min."));\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes = std::min(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for determining the maximum value out of a vector. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Max(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function min."));\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Default value recognition callback. \r
+ \param [in] a_szExpr Pointer to the expression\r
+ \param [in, out] a_iPos Pointer to an index storing the current position within the expression\r
+ \param [out] a_fVal Pointer where the value should be stored in case one is found.\r
+ \return 1 if a value was found 0 otherwise.\r
+ */\r
+ int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal)\r
+ {\r
+ value_type fVal(0);\r
+\r
+ stringstream_type stream(a_szExpr);\r
+ stream.seekg(0); // todo: check if this really is necessary\r
+ stream.imbue(Parser::s_locale);\r
+ stream >> fVal;\r
+ stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading\r
+\r
+ if (iEnd==(stringstream_type::pos_type)-1)\r
+ return 0;\r
+\r
+ *a_iPos += (int)iEnd;\r
+ *a_fVal = fVal;\r
+ return 1;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor. \r
+\r
+ Call ParserBase class constructor and trigger Function, Operator and Constant initialization.\r
+ */\r
+ Parser::Parser()\r
+ :ParserBase()\r
+ {\r
+ AddValIdent(IsVal);\r
+\r
+ InitCharSets();\r
+ InitFun();\r
+ InitConst();\r
+ InitOprt();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the character sets. \r
+ \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars\r
+ \r
+ This function is used for initializing the default character sets that define\r
+ the characters to be useable in function and variable names and operators.\r
+ */\r
+ void Parser::InitCharSets()\r
+ {\r
+ DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );\r
+ DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") );\r
+ DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize the default functions. */\r
+ void Parser::InitFun()\r
+ {\r
+ if (mu::TypeInfo<mu::value_type>::IsInteger())\r
+ {\r
+ // When setting MUP_BASETYPE to an integer type\r
+ // Place functions for dealing with integer values here\r
+ // ...\r
+ // ...\r
+ // ...\r
+ }\r
+ else\r
+ {\r
+ // trigonometric functions\r
+ DefineFun(_T("sin"), Sin);\r
+ DefineFun(_T("cos"), Cos);\r
+ DefineFun(_T("tan"), Tan);\r
+ // arcus functions\r
+ DefineFun(_T("asin"), ASin);\r
+ DefineFun(_T("acos"), ACos);\r
+ DefineFun(_T("atan"), ATan);\r
+ DefineFun(_T("atan2"), ATan2);\r
+ // hyperbolic functions\r
+ DefineFun(_T("sinh"), Sinh);\r
+ DefineFun(_T("cosh"), Cosh);\r
+ DefineFun(_T("tanh"), Tanh);\r
+ // arcus hyperbolic functions\r
+ DefineFun(_T("asinh"), ASinh);\r
+ DefineFun(_T("acosh"), ACosh);\r
+ DefineFun(_T("atanh"), ATanh);\r
+ // Logarithm functions\r
+ DefineFun(_T("log2"), Log2);\r
+ DefineFun(_T("log10"), Log10);\r
+ DefineFun(_T("log"), Log10);\r
+ DefineFun(_T("ln"), Ln);\r
+ // misc\r
+ DefineFun(_T("exp"), Exp);\r
+ DefineFun(_T("sqrt"), Sqrt);\r
+ DefineFun(_T("sign"), Sign);\r
+ DefineFun(_T("rint"), Rint);\r
+ DefineFun(_T("abs"), Abs);\r
+ // Functions with variable number of arguments\r
+ DefineFun(_T("sum"), Sum);\r
+ DefineFun(_T("avg"), Avg);\r
+ DefineFun(_T("min"), Min);\r
+ DefineFun(_T("max"), Max);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize constants.\r
+ \r
+ By default the parser recognizes two constants. Pi ("pi") and the eulerian\r
+ number ("_e").\r
+ */\r
+ void Parser::InitConst()\r
+ {\r
+ DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);\r
+ DefineConst(_T("_e"), (value_type)PARSER_CONST_E);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize operators. \r
+ \r
+ By default only the unary minus operator is added.\r
+ */\r
+ void Parser::InitOprt()\r
+ {\r
+ DefineInfixOprt(_T("-"), UnaryMinus);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)\r
+ {\r
+ // this is just sample code to illustrate modifying variable names on the fly.\r
+ // I'm not sure anyone really needs such a feature...\r
+ /*\r
+\r
+\r
+ string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);\r
+ string sRepl = std::string("_") + sVar + "_";\r
+ \r
+ int nOrigVarEnd = nEnd;\r
+ cout << "variable detected!\n";\r
+ cout << " Expr: " << *pExpr << "\n";\r
+ cout << " Start: " << nStart << "\n";\r
+ cout << " End: " << nEnd << "\n";\r
+ cout << " Var: \"" << sVar << "\"\n";\r
+ cout << " Repl: \"" << sRepl << "\"\n";\r
+ nEnd = nStart + sRepl.length();\r
+ cout << " End: " << nEnd << "\n";\r
+ pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);\r
+ cout << " New expr: " << *pExpr << "\n";\r
+ */\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Numerically differentiate with regard to a variable. \r
+ \param [in] a_Var Pointer to the differentiation variable.\r
+ \param [in] a_fPos Position at which the differentiation should take place.\r
+ \param [in] a_fEpsilon Epsilon used for the numerical differentiation.\r
+\r
+ Numerical differentiation uses a 5 point operator yielding a 4th order \r
+ formula. The default value for epsilon is 0.00074 which is\r
+ numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muparser\r
+ forum:\r
+\r
+ http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843\r
+ */\r
+ value_type Parser::Diff(value_type *a_Var, \r
+ value_type a_fPos, \r
+ value_type a_fEpsilon) const\r
+ {\r
+ value_type fRes(0), \r
+ fBuf(*a_Var),\r
+ f[4] = {0,0,0,0},\r
+ fEpsilon(a_fEpsilon);\r
+\r
+ // Backwards compatible calculation of epsilon inc case the user doesnt provide\r
+ // his own epsilon\r
+ if (fEpsilon==0)\r
+ fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;\r
+\r
+ *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval();\r
+ *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval();\r
+ *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval();\r
+ *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval();\r
+ *a_Var = fBuf; // restore variable\r
+\r
+ fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);\r
+ return fRes;\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserBase.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <cassert>\r
+#include <cmath>\r
+#include <memory>\r
+#include <vector>\r
+#include <deque>\r
+#include <sstream>\r
+#include <locale>\r
+\r
+#ifdef MUP_USE_OPENMP\r
+ #include <omp.h>\r
+#endif\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief This file contains the basic implementation of the muparser engine.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));\r
+\r
+ bool ParserBase::g_DbgDumpCmdCode = false;\r
+ bool ParserBase::g_DbgDumpStack = false;\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Identifiers for built in binary operators. \r
+\r
+ When defining custom binary operators with #AddOprt(...) make sure not to choose \r
+ names conflicting with these definitions. \r
+ */\r
+ const char_type* ParserBase::c_DefaultOprt[] = \r
+ { \r
+ _T("<="), _T(">="), _T("!="), \r
+ _T("=="), _T("<"), _T(">"), \r
+ _T("+"), _T("-"), _T("*"), \r
+ _T("/"), _T("^"), _T("&&"), \r
+ _T("||"), _T("="), _T("("), \r
+ _T(")"), _T("?"), _T(":"), 0 \r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Constructor.\r
+ \param a_szFormula the formula to interpret.\r
+ \throw ParserException if a_szFormula is null.\r
+ */\r
+ ParserBase::ParserBase()\r
+ :m_pParseFormula(&ParserBase::ParseString)\r
+ ,m_vRPN()\r
+ ,m_vStringBuf()\r
+ ,m_pTokenReader()\r
+ ,m_FunDef()\r
+ ,m_PostOprtDef()\r
+ ,m_InfixOprtDef()\r
+ ,m_OprtDef()\r
+ ,m_ConstDef()\r
+ ,m_StrVarDef()\r
+ ,m_VarDef()\r
+ ,m_bBuiltInOp(true)\r
+ ,m_sNameChars()\r
+ ,m_sOprtChars()\r
+ ,m_sInfixOprtChars()\r
+ ,m_nIfElseCounter(0)\r
+ ,m_vStackBuffer()\r
+ ,m_nFinalResultIdx(0)\r
+ {\r
+ InitTokenReader();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor. \r
+\r
+ Tha parser can be safely copy constructed but the bytecode is reset during\r
+ copy construction.\r
+ */\r
+ ParserBase::ParserBase(const ParserBase &a_Parser)\r
+ :m_pParseFormula(&ParserBase::ParseString)\r
+ ,m_vRPN()\r
+ ,m_vStringBuf()\r
+ ,m_pTokenReader()\r
+ ,m_FunDef()\r
+ ,m_PostOprtDef()\r
+ ,m_InfixOprtDef()\r
+ ,m_OprtDef()\r
+ ,m_ConstDef()\r
+ ,m_StrVarDef()\r
+ ,m_VarDef()\r
+ ,m_bBuiltInOp(true)\r
+ ,m_sNameChars()\r
+ ,m_sOprtChars()\r
+ ,m_sInfixOprtChars()\r
+ ,m_nIfElseCounter(0)\r
+ {\r
+ m_pTokenReader.reset(new token_reader_type(this));\r
+ Assign(a_Parser);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserBase::~ParserBase()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignement operator. \r
+\r
+ Implemented by calling Assign(a_Parser). Self assignement is suppressed.\r
+ \param a_Parser Object to copy to this.\r
+ \return *this\r
+ \throw nothrow\r
+ */\r
+ ParserBase& ParserBase::operator=(const ParserBase &a_Parser)\r
+ {\r
+ Assign(a_Parser);\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy state of a parser object to this. \r
+\r
+ Clears Variables and Functions of this parser.\r
+ Copies the states of all internal variables.\r
+ Resets parse function to string parse mode.\r
+\r
+ \param a_Parser the source object.\r
+ */\r
+ void ParserBase::Assign(const ParserBase &a_Parser)\r
+ {\r
+ if (&a_Parser==this)\r
+ return;\r
+\r
+ // Don't copy bytecode instead cause the parser to create new bytecode\r
+ // by resetting the parse function.\r
+ ReInit();\r
+\r
+ m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants\r
+ m_VarDef = a_Parser.m_VarDef; // Copy user defined variables\r
+ m_bBuiltInOp = a_Parser.m_bBuiltInOp;\r
+ m_vStringBuf = a_Parser.m_vStringBuf;\r
+ m_vStackBuffer = a_Parser.m_vStackBuffer;\r
+ m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;\r
+ m_StrVarDef = a_Parser.m_StrVarDef;\r
+ m_vStringVarBuf = a_Parser.m_vStringVarBuf;\r
+ m_nIfElseCounter = a_Parser.m_nIfElseCounter;\r
+ m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));\r
+\r
+ // Copy function and operator callbacks\r
+ m_FunDef = a_Parser.m_FunDef; // Copy function definitions\r
+ m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators\r
+ m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation\r
+ m_OprtDef = a_Parser.m_OprtDef; // binary operators\r
+\r
+ m_sNameChars = a_Parser.m_sNameChars;\r
+ m_sOprtChars = a_Parser.m_sOprtChars;\r
+ m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set the decimal separator.\r
+ \param cDecSep Decimal separator as a character value.\r
+ \sa SetThousandsSep\r
+\r
+ By default muparser uses the "C" locale. The decimal separator of this\r
+ locale is overwritten by the one provided here.\r
+ */\r
+ void ParserBase::SetDecSep(char_type cDecSep)\r
+ {\r
+ char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();\r
+ s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));\r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ /** \brief Sets the thousands operator. \r
+ \param cThousandsSep The thousands separator as a character\r
+ \sa SetDecSep\r
+\r
+ By default muparser uses the "C" locale. The thousands separator of this\r
+ locale is overwritten by the one provided here.\r
+ */\r
+ void ParserBase::SetThousandsSep(char_type cThousandsSep)\r
+ {\r
+ char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();\r
+ s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Resets the locale. \r
+\r
+ The default locale used "." as decimal separator, no thousands separator and\r
+ "," as function argument separator.\r
+ */\r
+ void ParserBase::ResetLocale()\r
+ {\r
+ s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));\r
+ SetArgSep(',');\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize the token reader. \r
+\r
+ Create new token reader object and submit pointers to function, operator,\r
+ constant and variable definitions.\r
+\r
+ \post m_pTokenReader.get()!=0\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::InitTokenReader()\r
+ {\r
+ m_pTokenReader.reset(new token_reader_type(this));\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Reset parser to string parsing mode and clear internal buffers.\r
+\r
+ Clear bytecode, reset the token reader.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ReInit() const\r
+ {\r
+ m_pParseFormula = &ParserBase::ParseString;\r
+ m_vStringBuf.clear();\r
+ m_vRPN.clear();\r
+ m_pTokenReader->ReInit();\r
+ m_nIfElseCounter = 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Returns the version of muparser. \r
+ \param eInfo A flag indicating whether the full version info should be \r
+ returned or not.\r
+\r
+ Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS\r
+ are returned only if eInfo==pviFULL.\r
+ */\r
+ string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const\r
+ {\r
+ string_type sCompileTimeSettings;\r
+ \r
+ stringstream_type ss;\r
+\r
+ ss << MUP_VERSION;\r
+\r
+ if (eInfo==pviFULL)\r
+ {\r
+ ss << _T(" (") << MUP_VERSION_DATE;\r
+ ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT");\r
+\r
+#ifdef _DEBUG\r
+ ss << _T("; DEBUG");\r
+#else \r
+ ss << _T("; RELEASE");\r
+#endif\r
+\r
+#ifdef _UNICODE\r
+ ss << _T("; UNICODE");\r
+#else\r
+ #ifdef _MBCS\r
+ ss << _T("; MBCS");\r
+ #else\r
+ ss << _T("; ASCII");\r
+ #endif\r
+#endif\r
+\r
+#ifdef MUP_USE_OPENMP\r
+ ss << _T("; OPENMP");\r
+//#else\r
+// ss << _T("; NO_OPENMP");\r
+#endif\r
+\r
+#if defined(MUP_MATH_EXCEPTIONS)\r
+ ss << _T("; MATHEXC");\r
+//#else\r
+// ss << _T("; NO_MATHEXC");\r
+#endif\r
+\r
+ ss << _T(")");\r
+ }\r
+\r
+ return ss.str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a value parsing function. \r
+ \r
+ When parsing an expression muParser tries to detect values in the expression\r
+ string using different valident callbacks. Thuis it's possible to parse\r
+ for hex values, binary values and floating point values. \r
+ */\r
+ void ParserBase::AddValIdent(identfun_type a_pCallback)\r
+ {\r
+ m_pTokenReader->AddValIdent(a_pCallback);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set a function that can create variable pointer for unknown expression variables. \r
+ \param a_pFactory A pointer to the variable factory.\r
+ \param pUserData A user defined context pointer.\r
+ */\r
+ void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData)\r
+ {\r
+ m_pTokenReader->SetVarCreator(a_pFactory, pUserData); \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a function or operator callback to the parser. */\r
+ void ParserBase::AddCallback( const string_type &a_strName,\r
+ const ParserCallback &a_Callback, \r
+ funmap_type &a_Storage,\r
+ const char_type *a_szCharSet )\r
+ {\r
+ if (a_Callback.GetAddr()==0)\r
+ Error(ecINVALID_FUN_PTR);\r
+\r
+ const funmap_type *pFunMap = &a_Storage;\r
+\r
+ // Check for conflicting operator or function names\r
+ if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ CheckOprt(a_strName, a_Callback, a_szCharSet);\r
+ a_Storage[a_strName] = a_Callback;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a name contains invalid characters. \r
+\r
+ \throw ParserException if the name contains invalid charakters.\r
+ */\r
+ void ParserBase::CheckOprt(const string_type &a_sName,\r
+ const ParserCallback &a_Callback,\r
+ const string_type &a_szCharSet) const\r
+ {\r
+ if ( !a_sName.length() ||\r
+ (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||\r
+ (a_sName[0]>='0' && a_sName[0]<='9'))\r
+ {\r
+ switch(a_Callback.GetCode())\r
+ {\r
+ case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName);\r
+ case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName);\r
+ default: Error(ecINVALID_NAME, -1, a_sName);\r
+ }\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a name contains invalid characters. \r
+\r
+ \throw ParserException if the name contains invalid charakters.\r
+ */\r
+ void ParserBase::CheckName(const string_type &a_sName,\r
+ const string_type &a_szCharSet) const\r
+ {\r
+ if ( !a_sName.length() ||\r
+ (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||\r
+ (a_sName[0]>='0' && a_sName[0]<='9'))\r
+ {\r
+ Error(ecINVALID_NAME);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set the formula. \r
+ \param a_strFormula Formula as string_type\r
+ \throw ParserException in case of syntax errors.\r
+\r
+ Triggers first time calculation thus the creation of the bytecode and\r
+ scanning of used variables.\r
+ */\r
+ void ParserBase::SetExpr(const string_type &a_sExpr)\r
+ {\r
+ // Check locale compatibility\r
+ std::locale loc;\r
+ if (m_pTokenReader->GetArgSep()==std::use_facet<numpunct<char_type> >(loc).decimal_point())\r
+ Error(ecLOCALE);\r
+\r
+ // <ibg> 20060222: Bugfix for Borland-Kylix:\r
+ // adding a space to the expression will keep Borlands KYLIX from going wild\r
+ // when calling tellg on a stringstream created from the expression after \r
+ // reading a value at the end of an expression. (mu::Parser::IsVal function)\r
+ // (tellg returns -1 otherwise causing the parser to ignore the value)\r
+ string_type sBuf(a_sExpr + _T(" ") );\r
+ m_pTokenReader->SetFormula(sBuf);\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get the default symbols used for the built in operators. \r
+ \sa c_DefaultOprt\r
+ */\r
+ const char_type** ParserBase::GetOprtDef() const\r
+ {\r
+ return (const char_type **)(&c_DefaultOprt[0]);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the set of valid characters to be used in names of\r
+ functions, variables, constants.\r
+ */\r
+ void ParserBase::DefineNameChars(const char_type *a_szCharset)\r
+ {\r
+ m_sNameChars = a_szCharset;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the set of valid characters to be used in names of\r
+ binary operators and postfix operators.\r
+ */\r
+ void ParserBase::DefineOprtChars(const char_type *a_szCharset)\r
+ {\r
+ m_sOprtChars = a_szCharset;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the set of valid characters to be used in names of\r
+ infix operators.\r
+ */\r
+ void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset)\r
+ {\r
+ m_sInfixOprtChars = a_szCharset;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Virtual function that defines the characters allowed in name identifiers. \r
+ \sa #ValidOprtChars, #ValidPrefixOprtChars\r
+ */ \r
+ const char_type* ParserBase::ValidNameChars() const\r
+ {\r
+ assert(m_sNameChars.size());\r
+ return m_sNameChars.c_str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Virtual function that defines the characters allowed in operator definitions. \r
+ \sa #ValidNameChars, #ValidPrefixOprtChars\r
+ */\r
+ const char_type* ParserBase::ValidOprtChars() const\r
+ {\r
+ assert(m_sOprtChars.size());\r
+ return m_sOprtChars.c_str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Virtual function that defines the characters allowed in infix operator definitions.\r
+ \sa #ValidNameChars, #ValidOprtChars\r
+ */\r
+ const char_type* ParserBase::ValidInfixOprtChars() const\r
+ {\r
+ assert(m_sInfixOprtChars.size());\r
+ return m_sInfixOprtChars.c_str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined operator. \r
+ \post Will reset the Parser to string parsing mode.\r
+ */\r
+ void ParserBase::DefinePostfixOprt(const string_type &a_sName, \r
+ fun_type1 a_pFun,\r
+ bool a_bAllowOpt)\r
+ {\r
+ AddCallback(a_sName, \r
+ ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX),\r
+ m_PostOprtDef, \r
+ ValidOprtChars() );\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize user defined functions. \r
+ \r
+ Calls the virtual functions InitFun(), InitConst() and InitOprt().\r
+ */\r
+ void ParserBase::Init()\r
+ {\r
+ InitCharSets();\r
+ InitFun();\r
+ InitConst();\r
+ InitOprt();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined operator. \r
+ \post Will reset the Parser to string parsing mode.\r
+ \param [in] a_sName operator Identifier \r
+ \param [in] a_pFun Operator callback function\r
+ \param [in] a_iPrec Operator Precedence (default=prSIGN)\r
+ \param [in] a_bAllowOpt True if operator is volatile (default=false)\r
+ \sa EPrec\r
+ */\r
+ void ParserBase::DefineInfixOprt(const string_type &a_sName, \r
+ fun_type1 a_pFun, \r
+ int a_iPrec, \r
+ bool a_bAllowOpt)\r
+ {\r
+ AddCallback(a_sName, \r
+ ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), \r
+ m_InfixOprtDef, \r
+ ValidInfixOprtChars() );\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define a binary operator. \r
+ \param [in] a_sName The identifier of the operator.\r
+ \param [in] a_pFun Pointer to the callback function.\r
+ \param [in] a_iPrec Precedence of the operator.\r
+ \param [in] a_eAssociativity The associativity of the operator.\r
+ \param [in] a_bAllowOpt If this is true the operator may be optimized away.\r
+ \r
+ Adds a new Binary operator the the parser instance. \r
+ */\r
+ void ParserBase::DefineOprt( const string_type &a_sName, \r
+ fun_type2 a_pFun, \r
+ unsigned a_iPrec, \r
+ EOprtAssociativity a_eAssociativity,\r
+ bool a_bAllowOpt )\r
+ {\r
+ // Check for conflicts with built in operator names\r
+ for (int i=0; m_bBuiltInOp && i<cmENDIF; ++i)\r
+ if (a_sName == string_type(c_DefaultOprt[i]))\r
+ Error(ecBUILTIN_OVERLOAD, -1, a_sName);\r
+\r
+ AddCallback(a_sName, \r
+ ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), \r
+ m_OprtDef, \r
+ ValidOprtChars() );\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define a new string constant.\r
+ \param [in] a_strName The name of the constant.\r
+ \param [in] a_strVal the value of the constant. \r
+ */\r
+ void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal)\r
+ {\r
+ // Test if a constant with that names already exists\r
+ if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())\r
+ Error(ecNAME_CONFLICT);\r
+\r
+ CheckName(a_strName, ValidNameChars());\r
+ \r
+ m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer\r
+ m_StrVarDef[a_strName] = m_vStringBuf.size(); // bind buffer index to variable name\r
+\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined variable. \r
+ \param [in] a_sName the variable name\r
+ \param [in] a_pVar A pointer to the variable vaule.\r
+ \post Will reset the Parser to string parsing mode.\r
+ \throw ParserException in case the name contains invalid signs or a_pVar is NULL.\r
+ */\r
+ void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar)\r
+ {\r
+ if (a_pVar==0)\r
+ Error(ecINVALID_VAR_PTR);\r
+\r
+ // Test if a constant with that names already exists\r
+ if (m_ConstDef.find(a_sName)!=m_ConstDef.end())\r
+ Error(ecNAME_CONFLICT);\r
+\r
+ CheckName(a_sName, ValidNameChars());\r
+ m_VarDef[a_sName] = a_pVar;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined constant. \r
+ \param [in] a_sName The name of the constant.\r
+ \param [in] a_fVal the value of the constant.\r
+ \post Will reset the Parser to string parsing mode.\r
+ \throw ParserException in case the name contains invalid signs.\r
+ */\r
+ void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal)\r
+ {\r
+ CheckName(a_sName, ValidNameChars());\r
+ m_ConstDef[a_sName] = a_fVal;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get operator priority.\r
+ \throw ParserException if a_Oprt is no operator code\r
+ */\r
+ int ParserBase::GetOprtPrecedence(const token_type &a_Tok) const\r
+ {\r
+ switch (a_Tok.GetCode())\r
+ {\r
+ // built in operators\r
+ case cmEND: return -5;\r
+ case cmARG_SEP: return -4;\r
+ case cmASSIGN: return -1; \r
+ case cmELSE:\r
+ case cmIF: return 0;\r
+ case cmLAND: return prLAND;\r
+ case cmLOR: return prLOR;\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ: return prCMP; \r
+ case cmADD:\r
+ case cmSUB: return prADD_SUB;\r
+ case cmMUL:\r
+ case cmDIV: return prMUL_DIV;\r
+ case cmPOW: return prPOW;\r
+\r
+ // user defined binary operators\r
+ case cmOPRT_INFIX: \r
+ case cmOPRT_BIN: return a_Tok.GetPri();\r
+ default: Error(ecINTERNAL_ERROR, 5);\r
+ return 999;\r
+ } \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get operator priority.\r
+ \throw ParserException if a_Oprt is no operator code\r
+ */\r
+ EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) const\r
+ {\r
+ switch (a_Tok.GetCode())\r
+ {\r
+ case cmASSIGN:\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ: \r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV: return oaLEFT;\r
+ case cmPOW: return oaRIGHT;\r
+ case cmOPRT_BIN: return a_Tok.GetAssociativity();\r
+ default: return oaNONE;\r
+ } \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing the used variables only. */\r
+ const varmap_type& ParserBase::GetUsedVar() const\r
+ {\r
+ try\r
+ {\r
+ m_pTokenReader->IgnoreUndefVar(true);\r
+ CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it\r
+ // may contain references to nonexisting variables.\r
+ m_pParseFormula = &ParserBase::ParseString;\r
+ m_pTokenReader->IgnoreUndefVar(false);\r
+ }\r
+ catch(exception_type &e)\r
+ {\r
+ // Make sure to stay in string parse mode, dont call ReInit()\r
+ // because it deletes the array with the used variables\r
+ m_pParseFormula = &ParserBase::ParseString;\r
+ m_pTokenReader->IgnoreUndefVar(false);\r
+ throw e;\r
+ }\r
+ \r
+ return m_pTokenReader->GetUsedVar();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing the used variables only. */\r
+ const varmap_type& ParserBase::GetVar() const\r
+ {\r
+ return m_VarDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing all parser constants. */\r
+ const valmap_type& ParserBase::GetConst() const\r
+ {\r
+ return m_ConstDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return prototypes of all parser functions.\r
+ \return #m_FunDef\r
+ \sa FunProt\r
+ \throw nothrow\r
+ \r
+ The return type is a map of the public type #funmap_type containing the prototype\r
+ definitions for all numerical parser functions. String functions are not part of \r
+ this map. The Prototype definition is encapsulated in objects of the class FunProt\r
+ one per parser function each associated with function names via a map construct.\r
+ */\r
+ const funmap_type& ParserBase::GetFunDef() const\r
+ {\r
+ return m_FunDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Retrieve the formula. */\r
+ const string_type& ParserBase::GetExpr() const\r
+ {\r
+ return m_pTokenReader->GetExpr();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Execute a function that takes a single string argument.\r
+ \param a_FunTok Function token.\r
+ \throw exception_type If the function token is not a string function\r
+ */\r
+ ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok,\r
+ const std::vector<token_type> &a_vArg) const\r
+ {\r
+ if (a_vArg.back().GetCode()!=cmSTRING)\r
+ Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());\r
+\r
+ token_type valTok;\r
+ generic_fun_type pFunc = a_FunTok.GetFuncAddr();\r
+ assert(pFunc);\r
+\r
+ try\r
+ {\r
+ // Check function arguments; write dummy value into valtok to represent the result\r
+ switch(a_FunTok.GetArgCount())\r
+ {\r
+ case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break;\r
+ case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break;\r
+ case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break;\r
+ default: Error(ecINTERNAL_ERROR);\r
+ }\r
+ }\r
+ catch(ParserError& )\r
+ {\r
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());\r
+ }\r
+\r
+ // string functions won't be optimized\r
+ m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());\r
+ \r
+ // Push dummy value representing the function result to the stack\r
+ return valTok;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Apply a function token. \r
+ \param iArgCount Number of Arguments actually gathered used only for multiarg functions.\r
+ \post The result is pushed to the value stack\r
+ \post The function token is removed from the stack\r
+ \throw exception_type if Argument count does not mach function requirements.\r
+ */\r
+ void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal, \r
+ int a_iArgCount) const\r
+ { \r
+ assert(m_pTokenReader.get());\r
+\r
+ // Operator stack empty or does not contain tokens with callback functions\r
+ if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 )\r
+ return;\r
+\r
+ token_type funTok = a_stOpt.pop();\r
+ assert(funTok.GetFuncAddr());\r
+\r
+ // Binary operators must rely on their internal operator number\r
+ // since counting of operators relies on commas for function arguments\r
+ // binary operators do not have commas in their expression\r
+ int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;\r
+\r
+ // determine how many parameters the function needs. To remember iArgCount includes the \r
+ // string parameter whilst GetArgCount() counts only numeric parameters.\r
+ int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0);\r
+\r
+ // Thats the number of numerical parameters\r
+ int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0);\r
+\r
+ if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1)\r
+ Error(ecINTERNAL_ERROR);\r
+\r
+ if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) \r
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
+\r
+ if (funTok.GetCode()!=cmOPRT_BIN && iArgCount<iArgRequired )\r
+ Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
+\r
+ if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired )\r
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
+\r
+ // Collect the numeric function arguments from the value stack and store them\r
+ // in a vector\r
+ std::vector<token_type> stArg; \r
+ for (int i=0; i<iArgNumerical; ++i)\r
+ {\r
+ stArg.push_back( a_stVal.pop() );\r
+ if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )\r
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());\r
+ }\r
+\r
+ switch(funTok.GetCode())\r
+ {\r
+ case cmFUNC_STR: \r
+ stArg.push_back(a_stVal.pop());\r
+ \r
+ if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )\r
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());\r
+\r
+ ApplyStrFunc(funTok, stArg); \r
+ break;\r
+\r
+ case cmFUNC_BULK: \r
+ m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); \r
+ break;\r
+\r
+ case cmOPRT_BIN:\r
+ case cmOPRT_POSTFIX:\r
+ case cmOPRT_INFIX:\r
+ case cmFUNC:\r
+ if (funTok.GetArgCount()==-1 && iArgCount==0)\r
+ Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());\r
+\r
+ m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical);\r
+ break;\r
+ }\r
+\r
+ // Push dummy value representing the function result to the stack\r
+ token_type token;\r
+ token.SetVal(1); \r
+ a_stVal.push(token);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::ApplyIfElse(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const\r
+ {\r
+ // Check if there is an if Else clause to be calculated\r
+ while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE)\r
+ {\r
+ token_type opElse = a_stOpt.pop();\r
+ MUP_ASSERT(a_stOpt.size()>0);\r
+\r
+ // Take the value associated with the else branch from the value stack\r
+ token_type vVal2 = a_stVal.pop();\r
+\r
+ MUP_ASSERT(a_stOpt.size()>0);\r
+ MUP_ASSERT(a_stVal.size()>=2);\r
+\r
+ // it then else is a ternary operator Pop all three values from the value s\r
+ // tack and just return the right value\r
+ token_type vVal1 = a_stVal.pop();\r
+ token_type vExpr = a_stVal.pop();\r
+\r
+ a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2);\r
+\r
+ token_type opIf = a_stOpt.pop();\r
+ MUP_ASSERT(opElse.GetCode()==cmELSE);\r
+ MUP_ASSERT(opIf.GetCode()==cmIF);\r
+\r
+ m_vRPN.AddIfElse(cmENDIF);\r
+ } // while pending if-else-clause found\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Performs the necessary steps to write code for\r
+ the execution of binary operators into the bytecode. \r
+ */\r
+ void ParserBase::ApplyBinOprt(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const\r
+ {\r
+ // is it a user defined binary operator?\r
+ if (a_stOpt.top().GetCode()==cmOPRT_BIN)\r
+ {\r
+ ApplyFunc(a_stOpt, a_stVal, 2);\r
+ }\r
+ else\r
+ {\r
+ MUP_ASSERT(a_stVal.size()>=2);\r
+ token_type valTok1 = a_stVal.pop(),\r
+ valTok2 = a_stVal.pop(),\r
+ optTok = a_stOpt.pop(),\r
+ resTok; \r
+\r
+ if ( valTok1.GetType()!=valTok2.GetType() || \r
+ (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) )\r
+ Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());\r
+\r
+ if (optTok.GetCode()==cmASSIGN)\r
+ {\r
+ if (valTok2.GetCode()!=cmVAR)\r
+ Error(ecUNEXPECTED_OPERATOR, -1, _T("="));\r
+ \r
+ m_vRPN.AddAssignOp(valTok2.GetVar());\r
+ }\r
+ else\r
+ m_vRPN.AddOp(optTok.GetCode());\r
+\r
+ resTok.SetVal(1);\r
+ a_stVal.push(resTok);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Apply a binary operator. \r
+ \param a_stOpt The operator stack\r
+ \param a_stVal The value stack\r
+ */\r
+ void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt,\r
+ ParserStack<token_type> &stVal) const\r
+ {\r
+ while (stOpt.size() && \r
+ stOpt.top().GetCode() != cmBO &&\r
+ stOpt.top().GetCode() != cmIF)\r
+ {\r
+ token_type tok = stOpt.top();\r
+ switch (tok.GetCode())\r
+ {\r
+ case cmOPRT_INFIX:\r
+ case cmOPRT_BIN:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV:\r
+ case cmPOW:\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmASSIGN:\r
+ if (stOpt.top().GetCode()==cmOPRT_INFIX)\r
+ ApplyFunc(stOpt, stVal, 1);\r
+ else\r
+ ApplyBinOprt(stOpt, stVal);\r
+ break;\r
+\r
+ case cmELSE:\r
+ ApplyIfElse(stOpt, stVal);\r
+ break;\r
+\r
+ default:\r
+ Error(ecINTERNAL_ERROR);\r
+ }\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Parse the command code.\r
+ \sa ParseString(...)\r
+\r
+ Command code contains precalculated stack positions of the values and the\r
+ associated operators. The Stack is filled beginning from index one the \r
+ value at index zero is not used at all.\r
+ */\r
+ value_type ParserBase::ParseCmdCode() const\r
+ {\r
+ return ParseCmdCodeBulk(0, 0);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Evaluate the RPN. \r
+ \param nOffset The offset added to variable addresses (for bulk mode)\r
+ \param nThreadID OpenMP Thread id of the calling thread\r
+ */\r
+ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const\r
+ {\r
+ assert(nThreadID<=s_MaxNumOpenMPThreads);\r
+\r
+ // Note: The check for nOffset==0 and nThreadID here is not necessary but \r
+ // brings a minor performance gain when not in bulk mode.\r
+ value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];\r
+ value_type buf;\r
+ int sidx(0);\r
+ for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok)\r
+ {\r
+ switch (pTok->Cmd)\r
+ {\r
+ // built in binary operators\r
+ case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1]; continue;\r
+ case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1]; continue;\r
+ case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1]; continue;\r
+ case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1]; continue;\r
+ case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1]; continue;\r
+ case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1]; continue;\r
+ case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue;\r
+ case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue;\r
+ case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue;\r
+ case cmDIV: --sidx;\r
+\r
+ #if defined(MUP_MATH_EXCEPTIONS)\r
+ if (Stack[1+sidx]==0)\r
+ Error(ecDIV_BY_ZERO);\r
+ #endif\r
+ Stack[sidx] /= Stack[1+sidx]; \r
+ continue;\r
+\r
+ case cmPOW: \r
+ --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1+sidx]);\r
+ continue;\r
+\r
+ case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue;\r
+ case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1]; continue;\r
+\r
+ case cmASSIGN: \r
+ --sidx; Stack[sidx] = *pTok->u.Oprt.ptr = Stack[sidx+1]; continue;\r
+\r
+ //case cmBO: // unused, listed for compiler optimization purposes\r
+ //case cmBC:\r
+ // MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
+ // continue;\r
+\r
+ case cmIF:\r
+ if (Stack[sidx--]==0)\r
+ pTok += pTok->u.Oprt.offset;\r
+ continue;\r
+\r
+ case cmELSE:\r
+ pTok += pTok->u.Oprt.offset;\r
+ continue;\r
+\r
+ case cmENDIF:\r
+ continue;\r
+\r
+ //case cmARG_SEP:\r
+ // MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
+ // continue;\r
+\r
+ // value and variable tokens\r
+ case cmVAR: Stack[++sidx] = *(pTok->u.Val.ptr + nOffset); continue;\r
+ case cmVAL: Stack[++sidx] = pTok->u.Val.data2; continue;\r
+ \r
+ case cmVARPOW2: buf = *(pTok->u.Val.ptr + nOffset);\r
+ Stack[++sidx] = buf*buf;\r
+ continue;\r
+\r
+ case cmVARPOW3: buf = *(pTok->u.Val.ptr + nOffset);\r
+ Stack[++sidx] = buf*buf*buf;\r
+ continue;\r
+\r
+ case cmVARPOW4: buf = *(pTok->u.Val.ptr + nOffset);\r
+ Stack[++sidx] = buf*buf*buf*buf;\r
+ continue;\r
+ \r
+ case cmVARMUL: Stack[++sidx] = *(pTok->u.Val.ptr + nOffset) * pTok->u.Val.data + pTok->u.Val.data2;\r
+ continue;\r
+\r
+ // Next is treatment of numeric functions\r
+ case cmFUNC:\r
+ {\r
+ int iArgCount = pTok->u.Fun.argc;\r
+\r
+ // switch according to argument count\r
+ switch(iArgCount) \r
+ {\r
+ case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->u.Fun.ptr)(); continue;\r
+ case 1: Stack[sidx] = (*(fun_type1)pTok->u.Fun.ptr)(Stack[sidx]); continue;\r
+ case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue;\r
+ case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;\r
+ case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;\r
+ case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;\r
+ case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;\r
+ case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;\r
+ case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;\r
+ case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;\r
+ case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;\r
+ default:\r
+ if (iArgCount>0) // function with variable arguments store the number as a negative value\r
+ Error(ecINTERNAL_ERROR, 1);\r
+\r
+ sidx -= -iArgCount - 1;\r
+ Stack[sidx] =(*(multfun_type)pTok->u.Fun.ptr)(&Stack[sidx], -iArgCount);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ // Next is treatment of string functions\r
+ case cmFUNC_STR:\r
+ {\r
+ sidx -= pTok->u.Fun.argc -1;\r
+\r
+ // The index of the string argument in the string table\r
+ int iIdxStack = pTok->u.Fun.idx; \r
+ MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() );\r
+\r
+ switch(pTok->u.Fun.argc) // switch according to argument count\r
+ {\r
+ case 0: Stack[sidx] = (*(strfun_type1)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue;\r
+ case 1: Stack[sidx] = (*(strfun_type2)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue;\r
+ case 2: Stack[sidx] = (*(strfun_type3)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue;\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ case cmFUNC_BULK:\r
+ {\r
+ int iArgCount = pTok->u.Fun.argc;\r
+\r
+ // switch according to argument count\r
+ switch(iArgCount) \r
+ {\r
+ case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->u.Fun.ptr)(nOffset, nThreadID); continue;\r
+ case 1: Stack[sidx] = (*(bulkfun_type1 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue;\r
+ case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue;\r
+ case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;\r
+ case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;\r
+ case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;\r
+ case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;\r
+ case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;\r
+ case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;\r
+ case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;\r
+ case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;\r
+ default:\r
+ Error(ecINTERNAL_ERROR, 2);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //case cmSTRING:\r
+ //case cmOPRT_BIN:\r
+ //case cmOPRT_POSTFIX:\r
+ //case cmOPRT_INFIX:\r
+ // MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
+ // continue;\r
+\r
+ //case cmEND:\r
+ // return Stack[m_nFinalResultIdx]; \r
+\r
+ default:\r
+ Error(ecINTERNAL_ERROR, 3);\r
+ return 0;\r
+ } // switch CmdCode\r
+ } // for all bytecode tokens\r
+\r
+ return Stack[m_nFinalResultIdx]; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::CreateRPN() const\r
+ {\r
+ if (!m_pTokenReader->GetExpr().length())\r
+ Error(ecUNEXPECTED_EOF, 0);\r
+\r
+ ParserStack<token_type> stOpt, stVal;\r
+ ParserStack<int> stArgCount;\r
+ token_type opta, opt; // for storing operators\r
+ token_type val, tval; // for storing value\r
+ string_type strBuf; // buffer for string function arguments\r
+\r
+ ReInit();\r
+ \r
+ // The outermost counter counts the number of seperated items\r
+ // such as in "a=10,b=20,c=c+a"\r
+ stArgCount.push(1);\r
+ \r
+ for(;;)\r
+ {\r
+ opt = m_pTokenReader->ReadNextToken();\r
+\r
+ switch (opt.GetCode())\r
+ {\r
+ //\r
+ // Next three are different kind of value entries\r
+ //\r
+ case cmSTRING:\r
+ opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token \r
+ stVal.push(opt);\r
+ m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer\r
+ break;\r
+ \r
+ case cmVAR:\r
+ stVal.push(opt);\r
+ m_vRPN.AddVar( static_cast<value_type*>(opt.GetVar()) );\r
+ break;\r
+\r
+ case cmVAL:\r
+ stVal.push(opt);\r
+ m_vRPN.AddVal( opt.GetVal() );\r
+ break;\r
+\r
+ case cmELSE:\r
+ m_nIfElseCounter--;\r
+ if (m_nIfElseCounter<0)\r
+ Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());\r
+\r
+ ApplyRemainingOprt(stOpt, stVal);\r
+ m_vRPN.AddIfElse(cmELSE);\r
+ stOpt.push(opt);\r
+ break;\r
+\r
+\r
+ case cmARG_SEP:\r
+ if (stArgCount.empty())\r
+ Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());\r
+\r
+ ++stArgCount.top();\r
+ // fallthrough intentional (no break!)\r
+\r
+ case cmEND:\r
+ ApplyRemainingOprt(stOpt, stVal);\r
+ break;\r
+\r
+ case cmBC:\r
+ {\r
+ // The argument count for parameterless functions is zero\r
+ // by default an opening bracket sets parameter count to 1\r
+ // in preparation of arguments to come. If the last token\r
+ // was an opening bracket we know better...\r
+ if (opta.GetCode()==cmBO)\r
+ --stArgCount.top();\r
+ \r
+ ApplyRemainingOprt(stOpt, stVal);\r
+\r
+ // Check if the bracket content has been evaluated completely\r
+ if (stOpt.size() && stOpt.top().GetCode()==cmBO)\r
+ {\r
+ // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check\r
+ // if there is either a function or a sign pending\r
+ // neither the opening nor the closing bracket will be pushed back to\r
+ // the operator stack\r
+ // Check if a function is standing in front of the opening bracket, \r
+ // if yes evaluate it afterwards check for infix operators\r
+ assert(stArgCount.size());\r
+ int iArgCount = stArgCount.pop();\r
+ \r
+ stOpt.pop(); // Take opening bracket from stack\r
+\r
+ if (iArgCount>1 && ( stOpt.size()==0 || \r
+ (stOpt.top().GetCode()!=cmFUNC && \r
+ stOpt.top().GetCode()!=cmFUNC_BULK && \r
+ stOpt.top().GetCode()!=cmFUNC_STR) ) )\r
+ Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());\r
+ \r
+ // The opening bracket was popped from the stack now check if there\r
+ // was a function before this bracket\r
+ if (stOpt.size() && \r
+ stOpt.top().GetCode()!=cmOPRT_INFIX && \r
+ stOpt.top().GetCode()!=cmOPRT_BIN && \r
+ stOpt.top().GetFuncAddr()!=0)\r
+ {\r
+ ApplyFunc(stOpt, stVal, iArgCount);\r
+ }\r
+ }\r
+ } // if bracket content is evaluated\r
+ break;\r
+\r
+ //\r
+ // Next are the binary operator entries\r
+ //\r
+ //case cmAND: // built in binary operators\r
+ //case cmOR:\r
+ //case cmXOR:\r
+ case cmIF:\r
+ m_nIfElseCounter++;\r
+ // fallthrough intentional (no break!)\r
+\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ:\r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV:\r
+ case cmPOW:\r
+ case cmASSIGN:\r
+ case cmOPRT_BIN:\r
+\r
+ // A binary operator (user defined or built in) has been found. \r
+ while ( stOpt.size() && \r
+ stOpt.top().GetCode() != cmBO &&\r
+ stOpt.top().GetCode() != cmELSE &&\r
+ stOpt.top().GetCode() != cmIF)\r
+ {\r
+ int nPrec1 = GetOprtPrecedence(stOpt.top()),\r
+ nPrec2 = GetOprtPrecedence(opt);\r
+\r
+ if (stOpt.top().GetCode()==opt.GetCode())\r
+ {\r
+\r
+ // Deal with operator associativity\r
+ EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);\r
+ if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || \r
+ (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ else if (nPrec1 < nPrec2)\r
+ {\r
+ // In case the operators are not equal the precedence decides alone...\r
+ break;\r
+ }\r
+ \r
+ if (stOpt.top().GetCode()==cmOPRT_INFIX)\r
+ ApplyFunc(stOpt, stVal, 1);\r
+ else\r
+ ApplyBinOprt(stOpt, stVal);\r
+ } // while ( ... )\r
+\r
+ if (opt.GetCode()==cmIF)\r
+ m_vRPN.AddIfElse(opt.GetCode());\r
+\r
+ // The operator can't be evaluated right now, push back to the operator stack\r
+ stOpt.push(opt);\r
+ break;\r
+\r
+ //\r
+ // Last section contains functions and operators implicitely mapped to functions\r
+ //\r
+ case cmBO:\r
+ stArgCount.push(1);\r
+ stOpt.push(opt);\r
+ break;\r
+\r
+ case cmOPRT_INFIX:\r
+ case cmFUNC:\r
+ case cmFUNC_BULK:\r
+ case cmFUNC_STR: \r
+ stOpt.push(opt);\r
+ break;\r
+\r
+ case cmOPRT_POSTFIX:\r
+ stOpt.push(opt);\r
+ ApplyFunc(stOpt, stVal, 1); // this is the postfix operator\r
+ break;\r
+\r
+ default: Error(ecINTERNAL_ERROR, 3);\r
+ } // end of switch operator-token\r
+\r
+ opta = opt;\r
+\r
+ if ( opt.GetCode() == cmEND )\r
+ {\r
+ m_vRPN.Finalize();\r
+ break;\r
+ }\r
+\r
+ if (ParserBase::g_DbgDumpStack)\r
+ {\r
+ StackDump(stVal, stOpt);\r
+ m_vRPN.AsciiDump();\r
+ }\r
+ } // while (true)\r
+\r
+ if (ParserBase::g_DbgDumpCmdCode)\r
+ m_vRPN.AsciiDump();\r
+\r
+ if (m_nIfElseCounter>0)\r
+ Error(ecMISSING_ELSE_CLAUSE);\r
+\r
+ // get the last value (= final result) from the stack\r
+ MUP_ASSERT(stArgCount.size()==1);\r
+ m_nFinalResultIdx = stArgCount.top();\r
+ if (m_nFinalResultIdx==0)\r
+ Error(ecINTERNAL_ERROR, 9);\r
+\r
+ if (stVal.size()==0)\r
+ Error(ecEMPTY_EXPRESSION);\r
+\r
+ if (stVal.top().GetType()!=tpDBL)\r
+ Error(ecSTR_RESULT);\r
+\r
+ m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief One of the two main parse functions.\r
+ \sa ParseCmdCode(...)\r
+\r
+ Parse expression from input string. Perform syntax checking and create \r
+ bytecode. After parsing the string and creating the bytecode the function \r
+ pointer #m_pParseFormula will be changed to the second parse routine the \r
+ uses bytecode instead of string parsing.\r
+ */\r
+ value_type ParserBase::ParseString() const\r
+ {\r
+ try\r
+ {\r
+ CreateRPN();\r
+ m_pParseFormula = &ParserBase::ParseCmdCode;\r
+ return (this->*m_pParseFormula)(); \r
+ }\r
+ catch(ParserError &exc)\r
+ {\r
+ exc.SetFormula(m_pTokenReader->GetExpr());\r
+ throw;\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Create an error containing the parse error position.\r
+\r
+ This function will create an Parser Exception object containing the error text and\r
+ its position.\r
+\r
+ \param a_iErrc [in] The error code of type #EErrorCodes.\r
+ \param a_iPos [in] The position where the error was detected.\r
+ \param a_strTok [in] The token string representation associated with the error.\r
+ \throw ParserException always throws thats the only purpose of this function.\r
+ */\r
+ void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const\r
+ {\r
+ throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined variables.\r
+ \throw nothrow\r
+\r
+ Resets the parser to string parsing mode by calling #ReInit.\r
+ */\r
+ void ParserBase::ClearVar()\r
+ {\r
+ m_VarDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Remove a variable from internal storage.\r
+ \throw nothrow\r
+\r
+ Removes a variable if it exists. If the Variable does not exist nothing will be done.\r
+ */\r
+ void ParserBase::RemoveVar(const string_type &a_strVarName)\r
+ {\r
+ varmap_type::iterator item = m_VarDef.find(a_strVarName);\r
+ if (item!=m_VarDef.end())\r
+ {\r
+ m_VarDef.erase(item);\r
+ ReInit();\r
+ }\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all functions.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearFun()\r
+ {\r
+ m_FunDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined constants.\r
+\r
+ Both numeric and string constants will be removed from the internal storage.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearConst()\r
+ {\r
+ m_ConstDef.clear();\r
+ m_StrVarDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined postfix operators.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearPostfixOprt()\r
+ {\r
+ m_PostOprtDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined binary operators.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearOprt()\r
+ {\r
+ m_OprtDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear the user defined Prefix operators. \r
+ \post Resets the parser to string parser mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearInfixOprt()\r
+ {\r
+ m_InfixOprtDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Enable or disable the formula optimization feature. \r
+ \post Resets the parser to string parser mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::EnableOptimizer(bool a_bIsOn)\r
+ {\r
+ m_vRPN.EnableOptimizer(a_bIsOn);\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Enable the dumping of bytecode amd stack content on the console. \r
+ \param bDumpCmd Flag to enable dumping of the current bytecode to the console.\r
+ \param bDumpStack Flag to enable dumping of the stack content is written to the console.\r
+\r
+ This function is for debug purposes only!\r
+ */\r
+ void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)\r
+ {\r
+ ParserBase::g_DbgDumpCmdCode = bDumpCmd;\r
+ ParserBase::g_DbgDumpStack = bDumpStack;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Enable or disable the built in binary operators.\r
+ \throw nothrow\r
+ \sa m_bBuiltInOp, ReInit()\r
+\r
+ If you disable the built in binary operators there will be no binary operators\r
+ defined. Thus you must add them manually one by one. It is not possible to\r
+ disable built in operators selectively. This function will Reinitialize the\r
+ parser by calling ReInit().\r
+ */\r
+ void ParserBase::EnableBuiltInOprt(bool a_bIsOn)\r
+ {\r
+ m_bBuiltInOp = a_bIsOn;\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Query status of built in variables.\r
+ \return #m_bBuiltInOp; true if built in operators are enabled.\r
+ \throw nothrow\r
+ */\r
+ bool ParserBase::HasBuiltInOprt() const\r
+ {\r
+ return m_bBuiltInOp;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Get the argument separator character. \r
+ */\r
+ char_type ParserBase::GetArgSep() const\r
+ {\r
+ return m_pTokenReader->GetArgSep();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set argument separator. \r
+ \param cArgSep the argument separator character.\r
+ */\r
+ void ParserBase::SetArgSep(char_type cArgSep)\r
+ {\r
+ m_pTokenReader->SetArgSep(cArgSep);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Dump stack content. \r
+\r
+ This function is used for debugging only.\r
+ */\r
+ void ParserBase::StackDump(const ParserStack<token_type> &a_stVal, \r
+ const ParserStack<token_type> &a_stOprt) const\r
+ {\r
+ ParserStack<token_type> stOprt(a_stOprt), \r
+ stVal(a_stVal);\r
+\r
+ mu::console() << _T("\nValue stack:\n");\r
+ while ( !stVal.empty() ) \r
+ {\r
+ token_type val = stVal.pop();\r
+ if (val.GetType()==tpSTR)\r
+ mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");\r
+ else\r
+ mu::console() << _T(" ") << val.GetVal() << _T(" ");\r
+ }\r
+ mu::console() << "\nOperator stack:\n";\r
+\r
+ while ( !stOprt.empty() )\r
+ {\r
+ if (stOprt.top().GetCode()<=cmASSIGN) \r
+ {\r
+ mu::console() << _T("OPRT_INTRNL \"")\r
+ << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] \r
+ << _T("\" \n");\r
+ }\r
+ else\r
+ {\r
+ switch(stOprt.top().GetCode())\r
+ {\r
+ case cmVAR: mu::console() << _T("VAR\n"); break;\r
+ case cmVAL: mu::console() << _T("VAL\n"); break;\r
+ case cmFUNC: mu::console() << _T("FUNC \"") \r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmFUNC_BULK: mu::console() << _T("FUNC_BULK \"") \r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"")\r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"") \r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break;\r
+ case cmEND: mu::console() << _T("END\n"); break;\r
+ case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break;\r
+ case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break;\r
+ case cmBC: mu::console() << _T("BRACKET \")\"\n"); break;\r
+ case cmIF: mu::console() << _T("IF\n"); break;\r
+ case cmELSE: mu::console() << _T("ELSE\n"); break;\r
+ case cmENDIF: mu::console() << _T("ENDIF\n"); break;\r
+ default: mu::console() << stOprt.top().GetCode() << _T(" "); break;\r
+ }\r
+ } \r
+ stOprt.pop();\r
+ }\r
+\r
+ mu::console() << dec << endl;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Evaluate an expression containing comma seperated subexpressions \r
+ \param [out] nStackSize The total number of results available\r
+ \return Pointer to the array containing all expression results\r
+\r
+ This member function can be used to retriev all results of an expression\r
+ made up of multiple comma seperated subexpressions (i.e. "x+y,sin(x),cos(y)")\r
+ */\r
+ value_type* ParserBase::Eval(int &nStackSize) const\r
+ {\r
+ (this->*m_pParseFormula)(); \r
+ nStackSize = m_nFinalResultIdx;\r
+\r
+ // (for historic reasons the stack starts at position 1)\r
+ return &m_vStackBuffer[1];\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the number of results on the calculation stack. \r
+ \r
+ If the expression contains comma seperated subexpressions (i.e. "sin(y), x+y"). \r
+ There mey be more than one return value. This function returns the number of \r
+ available results.\r
+ */\r
+ int ParserBase::GetNumResults() const\r
+ {\r
+ return m_nFinalResultIdx;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Calculate the result.\r
+\r
+ A note on const correctness: \r
+ I consider it important that Calc is a const function.\r
+ Due to caching operations Calc changes only the state of internal variables with one exception\r
+ m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making\r
+ Calc non const GetUsedVar is non const because it explicitely calls Eval() forcing this update. \r
+\r
+ \pre A formula must be set.\r
+ \pre Variables must have been set (if needed)\r
+\r
+ \sa #m_pParseFormula\r
+ \return The evaluation result\r
+ \throw ParseException if no Formula is set or in case of any other error related to the formula.\r
+ */\r
+ value_type ParserBase::Eval() const\r
+ {\r
+ return (this->*m_pParseFormula)(); \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::Eval(value_type *results, int nBulkSize)\r
+ {\r
+ CreateRPN();\r
+\r
+ int i = 0;\r
+\r
+#ifdef MUP_USE_OPENMP\r
+//#define DEBUG_OMP_STUFF\r
+ #ifdef DEBUG_OMP_STUFF\r
+ int *pThread = new int[nBulkSize];\r
+ int *pIdx = new int[nBulkSize];\r
+ #endif\r
+\r
+ int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);\r
+ int nThreadID, ct=0;\r
+ omp_set_num_threads(nMaxThreads);\r
+\r
+ #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID)\r
+ for (i=0; i<nBulkSize; ++i)\r
+ {\r
+ nThreadID = omp_get_thread_num();\r
+ results[i] = ParseCmdCodeBulk(i, nThreadID);\r
+\r
+ #ifdef DEBUG_OMP_STUFF\r
+ #pragma omp critical\r
+ {\r
+ pThread[ct] = nThreadID; \r
+ pIdx[ct] = i; \r
+ ct++;\r
+ }\r
+ #endif\r
+ }\r
+\r
+#ifdef DEBUG_OMP_STUFF\r
+ FILE *pFile = fopen("bulk_dbg.txt", "w");\r
+ for (i=0; i<nBulkSize; ++i)\r
+ {\r
+ fprintf(pFile, "idx: %d thread: %d \n", pIdx[i], pThread[i]);\r
+ }\r
+ \r
+ delete [] pIdx;\r
+ delete [] pThread;\r
+\r
+ fclose(pFile);\r
+#endif\r
+\r
+#else\r
+ for (i=0; i<nBulkSize; ++i)\r
+ {\r
+ results[i] = ParseCmdCodeBulk(i, 0);\r
+ }\r
+#endif\r
+\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserBytecode.h"\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+#include <iostream>\r
+\r
+#include "muParserDef.h"\r
+#include "muParserError.h"\r
+#include "muParserToken.h"\r
+#include "muParserStack.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+\r
+namespace mu\r
+{\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Bytecode default constructor. */\r
+ ParserByteCode::ParserByteCode()\r
+ :m_iStackPos(0)\r
+ ,m_iMaxStackSize(0)\r
+ ,m_vRPN()\r
+ ,m_bEnableOptimizer(true)\r
+ {\r
+ m_vRPN.reserve(50);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor. \r
+ \r
+ Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)\r
+ */\r
+ ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)\r
+ {\r
+ Assign(a_ByteCode);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignment operator.\r
+ \r
+ Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)\r
+ */\r
+ ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode)\r
+ {\r
+ Assign(a_ByteCode);\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserByteCode::EnableOptimizer(bool bStat)\r
+ {\r
+ m_bEnableOptimizer = bStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy state of another object to this. \r
+ \r
+ \throw nowthrow\r
+ */\r
+ void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)\r
+ {\r
+ if (this==&a_ByteCode) \r
+ return;\r
+\r
+ m_iStackPos = a_ByteCode.m_iStackPos;\r
+ m_vRPN = a_ByteCode.m_vRPN;\r
+ m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a Variable pointer to bytecode. \r
+ \param a_pVar Pointer to be added.\r
+ \throw nothrow\r
+ */\r
+ void ParserByteCode::AddVar(value_type *a_pVar)\r
+ {\r
+ ++m_iStackPos;\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ // optimization does not apply\r
+ SToken tok;\r
+ tok.Cmd = cmVAR;\r
+ tok.u.Val.ptr = a_pVar;\r
+ tok.u.Val.data = 1;\r
+ tok.u.Val.data2 = 0;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a Variable pointer to bytecode. \r
+\r
+ Value entries in byte code consist of:\r
+ <ul>\r
+ <li>value array position of the value</li>\r
+ <li>the operator code according to ParserToken::cmVAL</li>\r
+ <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>\r
+ </ul>\r
+\r
+ \param a_pVal Value to be added.\r
+ \throw nothrow\r
+ */\r
+ void ParserByteCode::AddVal(value_type a_fVal)\r
+ {\r
+ ++m_iStackPos;\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ // If optimization does not apply\r
+ SToken tok;\r
+ tok.Cmd = cmVAL;\r
+ tok.u.Val.ptr = NULL;\r
+ tok.u.Val.data = 0;\r
+ tok.u.Val.data2 = a_fVal;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)\r
+ {\r
+ std::size_t sz = m_vRPN.size();\r
+ value_type &x = m_vRPN[sz-2].u.Val.data2,\r
+ &y = m_vRPN[sz-1].u.Val.data2;\r
+ switch (a_Oprt)\r
+ {\r
+ case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;\r
+ case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break;\r
+ case cmLT: x = x < y; m_vRPN.pop_back(); break;\r
+ case cmGT: x = x > y; m_vRPN.pop_back(); break;\r
+ case cmLE: x = x <= y; m_vRPN.pop_back(); break;\r
+ case cmGE: x = x >= y; m_vRPN.pop_back(); break;\r
+ case cmNEQ: x = x != y; m_vRPN.pop_back(); break;\r
+ case cmEQ: x = x == y; m_vRPN.pop_back(); break;\r
+ case cmADD: x = x + y; m_vRPN.pop_back(); break;\r
+ case cmSUB: x = x - y; m_vRPN.pop_back(); break;\r
+ case cmMUL: x = x * y; m_vRPN.pop_back(); break;\r
+ case cmDIV: \r
+\r
+#if defined(MUP_MATH_EXCEPTIONS)\r
+ if (y==0)\r
+ throw ParserError(ecDIV_BY_ZERO, _T("0"));\r
+#endif\r
+\r
+ x = x / y; \r
+ m_vRPN.pop_back();\r
+ break;\r
+\r
+ case cmPOW: x = MathImpl<value_type>::Pow(x, y); \r
+ m_vRPN.pop_back();\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ } // switch opcode\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add an operator identifier to bytecode. \r
+ \r
+ Operator entries in byte code consist of:\r
+ <ul>\r
+ <li>value array position of the result</li>\r
+ <li>the operator code according to ParserToken::ECmdCode</li>\r
+ </ul>\r
+\r
+ \sa ParserToken::ECmdCode\r
+ */\r
+ void ParserByteCode::AddOp(ECmdCode a_Oprt)\r
+ {\r
+ bool bOptimized = false;\r
+\r
+ if (m_bEnableOptimizer)\r
+ {\r
+ std::size_t sz = m_vRPN.size();\r
+\r
+ // Check for foldable constants like:\r
+ // cmVAL cmVAL cmADD \r
+ // where cmADD can stand fopr any binary operator applied to\r
+ // two constant values.\r
+ if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)\r
+ {\r
+ ConstantFolding(a_Oprt);\r
+ bOptimized = true;\r
+ }\r
+ else\r
+ {\r
+ switch(a_Oprt)\r
+ {\r
+ case cmPOW:\r
+ // Optimization for ploynomials of low order\r
+ if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)\r
+ {\r
+ if (m_vRPN[sz-1].u.Val.data2==2)\r
+ m_vRPN[sz-2].Cmd = cmVARPOW2;\r
+ else if (m_vRPN[sz-1].u.Val.data2==3)\r
+ m_vRPN[sz-2].Cmd = cmVARPOW3;\r
+ else if (m_vRPN[sz-1].u.Val.data2==4)\r
+ m_vRPN[sz-2].Cmd = cmVARPOW4;\r
+ else\r
+ break;\r
+\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ break;\r
+\r
+ case cmSUB:\r
+ case cmADD:\r
+ // Simple optimization based on pattern recognition for a shitload of different\r
+ // bytecode combinations of addition/subtraction\r
+ if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || \r
+ (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) )\r
+ {\r
+ assert( (m_vRPN[sz-2].u.Val.ptr==NULL && m_vRPN[sz-1].u.Val.ptr!=NULL) ||\r
+ (m_vRPN[sz-2].u.Val.ptr!=NULL && m_vRPN[sz-1].u.Val.ptr==NULL) || \r
+ (m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) );\r
+\r
+ m_vRPN[sz-2].Cmd = cmVARMUL;\r
+ m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr)); // variable\r
+ m_vRPN[sz-2].u.Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].u.Val.data2; // offset\r
+ m_vRPN[sz-2].u.Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].u.Val.data; // multiplikatior\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ } \r
+ break;\r
+\r
+ case cmMUL:\r
+ if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) \r
+ {\r
+ m_vRPN[sz-2].Cmd = cmVARMUL;\r
+ m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));\r
+ m_vRPN[sz-2].u.Val.data = m_vRPN[sz-2].u.Val.data2 + m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 = 0;\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ } \r
+ else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )\r
+ {\r
+ // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2\r
+ m_vRPN[sz-2].Cmd = cmVARMUL;\r
+ m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));\r
+ if (m_vRPN[sz-1].Cmd == cmVAL)\r
+ {\r
+ m_vRPN[sz-2].u.Val.data *= m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 *= m_vRPN[sz-1].u.Val.data2;\r
+ }\r
+ else\r
+ {\r
+ m_vRPN[sz-2].u.Val.data = m_vRPN[sz-1].u.Val.data * m_vRPN[sz-2].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 = m_vRPN[sz-1].u.Val.data2 * m_vRPN[sz-2].u.Val.data2;\r
+ }\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&\r
+ m_vRPN[sz-1].u.Val.ptr == m_vRPN[sz-2].u.Val.ptr)\r
+ {\r
+ // Optimization: a*a -> a^2\r
+ m_vRPN[sz-2].Cmd = cmVARPOW2;\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ break;\r
+\r
+ case cmDIV:\r
+ if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].u.Val.data2!=0)\r
+ {\r
+ // Optimization: 4*a/2 -> 2*a\r
+ m_vRPN[sz-2].u.Val.data /= m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 /= m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ break;\r
+ \r
+ } // switch a_Oprt\r
+ }\r
+ }\r
+\r
+ // If optimization can't be applied just write the value\r
+ if (!bOptimized)\r
+ {\r
+ --m_iStackPos;\r
+ SToken tok;\r
+ tok.Cmd = a_Oprt;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserByteCode::AddIfElse(ECmdCode a_Oprt)\r
+ {\r
+ SToken tok;\r
+ tok.Cmd = a_Oprt;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add an assignement operator\r
+ \r
+ Operator entries in byte code consist of:\r
+ <ul>\r
+ <li>cmASSIGN code</li>\r
+ <li>the pointer of the destination variable</li>\r
+ </ul>\r
+\r
+ \sa ParserToken::ECmdCode\r
+ */\r
+ void ParserByteCode::AddAssignOp(value_type *a_pVar)\r
+ {\r
+ --m_iStackPos;\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmASSIGN;\r
+ tok.u.Val.ptr = a_pVar;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add function to bytecode. \r
+\r
+ \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.\r
+ \param a_pFun Pointer to function callback.\r
+ */\r
+ void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)\r
+ {\r
+ if (a_iArgc>=0)\r
+ {\r
+ m_iStackPos = m_iStackPos - a_iArgc + 1; \r
+ }\r
+ else\r
+ {\r
+ // function with unlimited number of arguments\r
+ m_iStackPos = m_iStackPos + a_iArgc + 1; \r
+ }\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmFUNC;\r
+ tok.u.Fun.argc = a_iArgc;\r
+ tok.u.Fun.ptr = a_pFun;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a bulk function to bytecode. \r
+\r
+ \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.\r
+ \param a_pFun Pointer to function callback.\r
+ */\r
+ void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)\r
+ {\r
+ m_iStackPos = m_iStackPos - a_iArgc + 1; \r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmFUNC_BULK;\r
+ tok.u.Fun.argc = a_iArgc;\r
+ tok.u.Fun.ptr = a_pFun;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add Strung function entry to the parser bytecode. \r
+ \throw nothrow\r
+\r
+ A string function entry consists of the stack position of the return value,\r
+ followed by a cmSTRFUNC code, the function pointer and an index into the \r
+ string buffer maintained by the parser.\r
+ */\r
+ void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)\r
+ {\r
+ m_iStackPos = m_iStackPos - a_iArgc + 1;\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmFUNC_STR;\r
+ tok.u.Fun.argc = a_iArgc;\r
+ tok.u.Fun.idx = a_iIdx;\r
+ tok.u.Fun.ptr = a_pFun;\r
+ m_vRPN.push_back(tok);\r
+\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add end marker to bytecode.\r
+ \r
+ \throw nothrow \r
+ */\r
+ void ParserByteCode::Finalize()\r
+ {\r
+ SToken tok;\r
+ tok.Cmd = cmEND;\r
+ m_vRPN.push_back(tok);\r
+ rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit\r
+\r
+ // Determine the if-then-else jump offsets\r
+ ParserStack<int> stIf, stElse;\r
+ int idx;\r
+ for (int i=0; i<(int)m_vRPN.size(); ++i)\r
+ {\r
+ switch(m_vRPN[i].Cmd)\r
+ {\r
+ case cmIF:\r
+ stIf.push(i);\r
+ break;\r
+\r
+ case cmELSE:\r
+ stElse.push(i);\r
+ idx = stIf.pop();\r
+ m_vRPN[idx].u.Oprt.offset = i - idx;\r
+ break;\r
+ \r
+ case cmENDIF:\r
+ idx = stElse.pop();\r
+ m_vRPN[idx].u.Oprt.offset = i - idx;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ const SToken* ParserByteCode::GetBase() const\r
+ {\r
+ if (m_vRPN.size()==0)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+ else\r
+ return &m_vRPN[0];\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ std::size_t ParserByteCode::GetMaxStackSize() const\r
+ {\r
+ return m_iMaxStackSize+1;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Returns the number of entries in the bytecode. */\r
+ std::size_t ParserByteCode::GetSize() const\r
+ {\r
+ return m_vRPN.size();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Delete the bytecode. \r
+ \r
+ \throw nothrow\r
+\r
+ The name of this function is a violation of my own coding guidelines\r
+ but this way it's more in line with the STL functions thus more \r
+ intuitive.\r
+ */\r
+ void ParserByteCode::clear()\r
+ {\r
+ m_vRPN.clear();\r
+ m_iStackPos = 0;\r
+ m_iMaxStackSize = 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Dump bytecode (for debugging only!). */\r
+ void ParserByteCode::AsciiDump()\r
+ {\r
+ if (!m_vRPN.size()) \r
+ {\r
+ mu::console() << _T("No bytecode available\n");\r
+ return;\r
+ }\r
+\r
+ mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");\r
+ for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)\r
+ {\r
+ mu::console() << std::dec << i << _T(" : \t");\r
+ switch (m_vRPN[i].Cmd)\r
+ {\r
+ case cmVAL: mu::console() << _T("VAL \t");\r
+ mu::console() << _T("[") << m_vRPN[i].u.Val.data2 << _T("]\n");\r
+ break;\r
+\r
+ case cmVAR: mu::console() << _T("VAR \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARPOW2: mu::console() << _T("VARPOW2 \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARPOW3: mu::console() << _T("VARPOW3 \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARPOW4: mu::console() << _T("VARPOW4 \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARMUL: mu::console() << _T("VARMUL \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]"); \r
+ mu::console() << _T(" * [") << m_vRPN[i].u.Val.data << _T("]");\r
+ mu::console() << _T(" + [") << m_vRPN[i].u.Val.data2 << _T("]\n");\r
+ break;\r
+\r
+ case cmFUNC: mu::console() << _T("CALL\t");\r
+ mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].u.Fun.argc << _T("]"); \r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Fun.ptr << _T("]"); \r
+ mu::console() << _T("\n");\r
+ break;\r
+\r
+ case cmFUNC_STR:\r
+ mu::console() << _T("CALL STRFUNC\t");\r
+ mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].u.Fun.argc << _T("]");\r
+ mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].u.Fun.idx << _T("]");\r
+ mu::console() << _T("[ADDR: 0x") << m_vRPN[i].u.Fun.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmLT: mu::console() << _T("LT\n"); break;\r
+ case cmGT: mu::console() << _T("GT\n"); break;\r
+ case cmLE: mu::console() << _T("LE\n"); break;\r
+ case cmGE: mu::console() << _T("GE\n"); break;\r
+ case cmEQ: mu::console() << _T("EQ\n"); break;\r
+ case cmNEQ: mu::console() << _T("NEQ\n"); break;\r
+ case cmADD: mu::console() << _T("ADD\n"); break;\r
+ case cmLAND: mu::console() << _T("&&\n"); break;\r
+ case cmLOR: mu::console() << _T("||\n"); break;\r
+ case cmSUB: mu::console() << _T("SUB\n"); break;\r
+ case cmMUL: mu::console() << _T("MUL\n"); break;\r
+ case cmDIV: mu::console() << _T("DIV\n"); break;\r
+ case cmPOW: mu::console() << _T("POW\n"); break;\r
+\r
+ case cmIF: mu::console() << _T("IF\t");\r
+ mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].u.Oprt.offset << _T("]\n");\r
+ break;\r
+\r
+ case cmELSE: mu::console() << _T("ELSE\t");\r
+ mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].u.Oprt.offset << _T("]\n");\r
+ break;\r
+\r
+ case cmENDIF: mu::console() << _T("ENDIF\n"); break;\r
+\r
+ case cmASSIGN: \r
+ mu::console() << _T("ASSIGN\t");\r
+ mu::console() << _T("[ADDR: 0x") << m_vRPN[i].u.Oprt.ptr << _T("]\n"); \r
+ break; \r
+\r
+ default: mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n"); \r
+ break;\r
+ } // switch cmdCode\r
+ } // while bytecode\r
+\r
+ mu::console() << _T("END") << std::endl;\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserCallback.h"\r
+\r
+/** \file\r
+ \brief Implementation of the parser callback class.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(1)\r
+ ,m_iPri(a_iPrec)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(a_iCode)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor for constructing funcstion callbacks taking two arguments. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor for constructing binary operator callbacks. \r
+ \param a_pFun Pointer to a static function taking two arguments\r
+ \param a_bAllowOpti A flag indicating this funcation can be optimized\r
+ \param a_iPrec The operator precedence\r
+ \param a_eOprtAsct The operators associativity\r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(fun_type2 a_pFun, \r
+ bool a_bAllowOpti, \r
+ int a_iPrec, \r
+ EOprtAssociativity a_eOprtAsct)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(a_iPrec)\r
+ ,m_eOprtAsct(a_eOprtAsct)\r
+ ,m_iCode(cmOPRT_BIN)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(3)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(4)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(5)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(6)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(7)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(8)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(9)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(10)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(1)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor for constructing funcstion callbacks taking two arguments. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(3)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(4)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(5)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(6)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(7)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(8)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(9)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(10)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(-1)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_STR)\r
+ ,m_iType(tpSTR)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(1)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_STR)\r
+ ,m_iType(tpSTR)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_STR)\r
+ ,m_iType(tpSTR)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Default constructor. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback()\r
+ :m_pFun(0)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmUNKNOWN)\r
+ ,m_iType(tpVOID)\r
+ ,m_bAllowOpti(0)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(const ParserCallback &ref)\r
+ {\r
+ m_pFun = ref.m_pFun;\r
+ m_iArgc = ref.m_iArgc;\r
+ m_bAllowOpti = ref.m_bAllowOpti;\r
+ m_iCode = ref.m_iCode;\r
+ m_iType = ref.m_iType;\r
+ m_iPri = ref.m_iPri;\r
+ m_eOprtAsct = ref.m_eOprtAsct;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Clone this instance and return a pointer to the new instance. */\r
+ ParserCallback* ParserCallback::Clone() const\r
+ {\r
+ return new ParserCallback(*this);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return tru if the function is conservative.\r
+\r
+ Conservative functions return always the same result for the same argument.\r
+ \throw nothrow\r
+ */\r
+ bool ParserCallback::IsOptimizable() const \r
+ { \r
+ return m_bAllowOpti; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get the callback address for the parser function. \r
+ \r
+ The type of the address is void. It needs to be recasted according to the\r
+ argument number to the right type.\r
+\r
+ \throw nothrow\r
+ \return #pFun\r
+ */\r
+ void* ParserCallback::GetAddr() const \r
+ { \r
+ return m_pFun; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the callback code. */\r
+ ECmdCode ParserCallback::GetCode() const \r
+ { \r
+ return m_iCode; \r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ ETypeCode ParserCallback::GetType() const \r
+ { \r
+ return m_iType; \r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the operator precedence. \r
+ \throw nothrown\r
+\r
+ Only valid if the callback token is an operator token (binary or infix).\r
+ */\r
+ int ParserCallback::GetPri() const \r
+ { \r
+ return m_iPri; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the operators associativity. \r
+ \throw nothrown\r
+\r
+ Only valid if the callback token is a binary operator token.\r
+ */\r
+ EOprtAssociativity ParserCallback::GetAssociativity() const\r
+ {\r
+ return m_eOprtAsct;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Returns the number of function Arguments. */\r
+ int ParserCallback::GetArgc() const \r
+ { \r
+ return m_iArgc; \r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#if defined(MUPARSER_DLL) \r
+\r
+#if defined(_WIN32)\r
+ #define WIN32_LEAN_AND_MEAN\r
+ #include <windows.h>\r
+#endif\r
+\r
+#include "muParserDLL.h"\r
+#include "muParser.h"\r
+#include "muParserInt.h"\r
+#include "muParserError.h"\r
+\r
+\r
+#define MU_TRY \\r
+ try \\r
+ {\r
+\r
+#define MU_CATCH \\r
+ } \\r
+ catch(muError_t &e) \\r
+ { \\r
+ ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \\r
+ pTag->exc = e; \\r
+ pTag->bError = true; \\r
+ if (pTag->errHandler) \\r
+ (pTag->errHandler)(a_hParser); \\r
+ } \\r
+ catch(...) \\r
+ { \\r
+ ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \\r
+ pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \\r
+ pTag->bError = true; \\r
+ if (pTag->errHandler) \\r
+ (pTag->errHandler)(a_hParser); \\r
+ }\r
+\r
+/** \file \r
+ \brief This file contains the implementation of the DLL interface of muparser.\r
+*/\r
+\r
+//---------------------------------------------------------------------------\r
+// private types\r
+typedef mu::ParserBase::exception_type muError_t;\r
+typedef mu::ParserBase muParser_t;\r
+\r
+int g_nBulkSize;\r
+\r
+//---------------------------------------------------------------------------\r
+class ParserTag\r
+{\r
+public:\r
+ ParserTag(int nType)\r
+ :pParser( (nType==muBASETYPE_FLOAT) ? (mu::ParserBase*)new mu::Parser() : \r
+ (nType==muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL)\r
+ ,exc()\r
+ ,errHandler(NULL)\r
+ ,bError(false)\r
+ ,m_nParserType(nType)\r
+ {}\r
+ \r
+ ~ParserTag()\r
+ {\r
+ delete pParser;\r
+ }\r
+\r
+ mu::ParserBase *pParser;\r
+ mu::ParserBase::exception_type exc;\r
+ muErrorHandler_t errHandler;\r
+ bool bError;\r
+\r
+private:\r
+ ParserTag(const ParserTag &ref);\r
+ ParserTag& operator=(const ParserTag &ref);\r
+\r
+ int m_nParserType;\r
+};\r
+\r
+static muChar_t s_tmpOutBuf[2048];\r
+\r
+//---------------------------------------------------------------------------\r
+//\r
+//\r
+// unexported functions\r
+//\r
+//\r
+//---------------------------------------------------------------------------\r
+\r
+//---------------------------------------------------------------------------\r
+muParser_t* AsParser(muParserHandle_t a_hParser)\r
+{\r
+ return static_cast<ParserTag*>(a_hParser)->pParser;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+ParserTag* AsParserTag(muParserHandle_t a_hParser)\r
+{\r
+ return static_cast<ParserTag*>(a_hParser);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+#if defined(_WIN32)\r
+ #define _CRT_SECURE_NO_DEPRECATE\r
+\r
+ BOOL APIENTRY DllMain( HANDLE /*hModule*/, \r
+ DWORD ul_reason_for_call, \r
+ LPVOID /*lpReserved*/ )\r
+ {\r
+ switch (ul_reason_for_call)\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+ break;\r
+\r
+ case DLL_THREAD_ATTACH:\r
+ case DLL_THREAD_DETACH:\r
+ case DLL_PROCESS_DETACH:\r
+ break;\r
+ }\r
+\r
+ return TRUE;\r
+ }\r
+\r
+#endif\r
+\r
+//---------------------------------------------------------------------------\r
+//\r
+//\r
+// exported functions\r
+//\r
+//\r
+//---------------------------------------------------------------------------\r
+\r
+API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData)\r
+{\r
+ MU_TRY\r
+ muParser_t* p(AsParser(a_hParser));\r
+ p->SetVarFactory(a_pFactory, pUserData);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Create a new Parser instance and return its handle.\r
+*/\r
+API_EXPORT(muParserHandle_t) mupCreate(int nBaseType)\r
+{\r
+ switch(nBaseType)\r
+ {\r
+ case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT));\r
+ case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT));\r
+ default: return NULL;\r
+ }\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Release the parser instance related with a parser handle.\r
+*/\r
+API_EXPORT(void) mupRelease(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ ParserTag* p = static_cast<ParserTag*>(a_hParser);\r
+ delete p;\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str());\r
+ return s_tmpOutBuf;\r
+ MU_CATCH\r
+\r
+ return "";\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Evaluate the expression.\r
+*/\r
+API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ return p->Eval();\r
+ MU_CATCH\r
+\r
+ return 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum)\r
+{\r
+ MU_TRY\r
+ assert(nNum!=NULL);\r
+\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ return p->Eval(*nNum);\r
+ MU_CATCH\r
+\r
+ return 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_res, int nSize)\r
+{\r
+ MU_TRY\r
+ muParser_t* p(AsParser(a_hParser));\r
+ p->Eval(a_res, nSize);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetExpr(a_szExpr);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->RemoveVar( a_szName );\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Release all parser variables.\r
+ \param a_hParser Handle to the parser instance.\r
+*/\r
+API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearVar();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Release all parser variables.\r
+ \param a_hParser Handle to the parser instance.\r
+*/\r
+API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearConst();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Clear all user defined operators.\r
+ \param a_hParser Handle to the parser instance.\r
+*/\r
+API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearOprt();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearFun();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun0( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun0_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun1( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun1_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun2( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun2_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun3( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun3_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun4( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun4_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun5( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun5_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun6( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun6_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun7( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun7_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun8( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun8_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun9( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun9_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun10( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun10_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muBulkFun0_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muBulkFun1_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muBulkFun2_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun3_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun4_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun5_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun6_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun7_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun8_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun9_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun10( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun10_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrFun1( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muStrFun1_t a_pFun )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrFun2( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muStrFun2_t a_pFun )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrFun3( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muStrFun3_t a_pFun )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muMultFun_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun2_t a_pFun, \r
+ muInt_t a_nPrec, \r
+ muInt_t a_nOprtAsct,\r
+ muBool_t a_bAllowOpt)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineOprt(a_szName, \r
+ a_pFun, \r
+ a_nPrec, \r
+ (mu::EOprtAssociativity)a_nOprtAsct, \r
+ a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFloat_t *a_pVar)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineVar(a_szName, a_pVar);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFloat_t *a_pVar)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineVar(a_szName, a_pVar);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFloat_t a_fVal)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineConst(a_szName, a_fVal);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ const muChar_t *a_szVal)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineStrConst(a_szName, a_szVal);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+\r
+ // C# explodes when pMsg is returned directly. For some reason it can't access\r
+ // the memory where the message lies directly.\r
+ sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str());\r
+ return s_tmpOutBuf;\r
+ \r
+ MU_CATCH\r
+\r
+ return "";\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser,\r
+ const muChar_t* a_szName,\r
+ muFun1_t a_pOprt,\r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser,\r
+ const muChar_t* a_szName,\r
+ muFun1_t a_pOprt,\r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+// Define character sets for identifiers\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineNameChars( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szCharset )\r
+{\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineNameChars(a_szCharset);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineOprtChars( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szCharset )\r
+{\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineOprtChars(a_szCharset);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szCharset)\r
+{\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineInfixOprtChars(a_szCharset);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Get the number of variables defined in the parser.\r
+ \param a_hParser [in] Must be a valid parser handle.\r
+ \return The number of used variables.\r
+ \sa mupGetExprVar\r
+*/\r
+API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetVar();\r
+ return (int)VarMap.size();\r
+ MU_CATCH\r
+\r
+ return 0; // never reached\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return a variable that is used in an expression.\r
+ \param a_hParser [in] A valid parser handle.\r
+ \param a_iVar [in] The index of the variable to return.\r
+ \param a_szName [out] Pointer to the variable name.\r
+ \param a_pVar [out] Pointer to the variable.\r
+ \throw nothrow\r
+\r
+ Prior to calling this function call mupGetExprVarNum in order to get the\r
+ number of variables in the expression. If the parameter a_iVar is greater\r
+ than the number of variables both a_szName and a_pVar will be set to zero.\r
+ As a side effect this function will trigger an internal calculation of the\r
+ expression undefined variables will be set to zero during this calculation.\r
+ During the calculation user defined callback functions present in the expression\r
+ will be called, this is unavoidable.\r
+*/\r
+API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, \r
+ unsigned a_iVar, \r
+ const muChar_t **a_szName, \r
+ muFloat_t **a_pVar)\r
+{\r
+ // A static buffer is needed for the name since i cant return the\r
+ // pointer from the map.\r
+ static muChar_t szName[1024];\r
+\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetVar();\r
+\r
+ if (a_iVar>=VarMap.size())\r
+ {\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+ return;\r
+ }\r
+ mu::varmap_type::const_iterator item;\r
+\r
+ item = VarMap.begin();\r
+ for (unsigned i=0; i<a_iVar; ++i)\r
+ item++;\r
+\r
+ strncpy(szName, item->first.c_str(), sizeof(szName));\r
+ szName[sizeof(szName)-1] = 0;\r
+\r
+ *a_szName = &szName[0];\r
+ *a_pVar = item->second;\r
+ return;\r
+\r
+ MU_CATCH\r
+\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Get the number of variables used in the expression currently set in the parser.\r
+ \param a_hParser [in] Must be a valid parser handle.\r
+ \return The number of used variables.\r
+ \sa mupGetExprVar\r
+*/\r
+API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetUsedVar();\r
+ return (int)VarMap.size();\r
+ MU_CATCH\r
+\r
+ return 0; // never reached\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return a variable that is used in an expression.\r
+\r
+ Prior to calling this function call mupGetExprVarNum in order to get the\r
+ number of variables in the expression. If the parameter a_iVar is greater\r
+ than the number of variables both a_szName and a_pVar will be set to zero.\r
+ As a side effect this function will trigger an internal calculation of the\r
+ expression undefined variables will be set to zero during this calculation.\r
+ During the calculation user defined callback functions present in the expression\r
+ will be called, this is unavoidable.\r
+\r
+ \param a_hParser [in] A valid parser handle.\r
+ \param a_iVar [in] The index of the variable to return.\r
+ \param a_szName [out] Pointer to the variable name.\r
+ \param a_pVar [out] Pointer to the variable.\r
+ \throw nothrow\r
+*/\r
+API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, \r
+ unsigned a_iVar, \r
+ const muChar_t **a_szName, \r
+ muFloat_t **a_pVar)\r
+{\r
+ // A static buffer is needed for the name since i cant return the\r
+ // pointer from the map.\r
+ static muChar_t szName[1024];\r
+\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetUsedVar();\r
+\r
+ if (a_iVar>=VarMap.size())\r
+ {\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+ return;\r
+ }\r
+ mu::varmap_type::const_iterator item;\r
+\r
+ item = VarMap.begin();\r
+ for (unsigned i=0; i<a_iVar; ++i)\r
+ item++;\r
+\r
+ strncpy(szName, item->first.c_str(), sizeof(szName));\r
+ szName[sizeof(szName)-1] = 0;\r
+\r
+ *a_szName = &szName[0];\r
+ *a_pVar = item->second;\r
+ return;\r
+\r
+ MU_CATCH\r
+\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the number of constants defined in a parser. */\r
+API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::valmap_type ValMap = p->GetConst();\r
+ return (int)ValMap.size();\r
+ MU_CATCH\r
+\r
+ return 0; // never reached\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetArgSep(cArgSep);\r
+ MU_CATCH\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ResetLocale();\r
+ MU_CATCH\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetDecSep(cDecSep);\r
+ MU_CATCH\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetThousandsSep(cThousandsSep);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Retrieve name and value of a single parser constant.\r
+ \param a_hParser [in] a valid parser handle\r
+ \param a_iVar [in] Index of the constant to query\r
+ \param a_pszName [out] pointer to a null terminated string with the constant name\r
+ \param [out] The constant value\r
+*/\r
+API_EXPORT(void) mupGetConst( muParserHandle_t a_hParser, \r
+ unsigned a_iVar,\r
+ const muChar_t **a_pszName, \r
+ muFloat_t *a_fVal)\r
+{\r
+ // A static buffer is needed for the name since i cant return the\r
+ // pointer from the map.\r
+ static muChar_t szName[1024];\r
+\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::valmap_type ValMap = p->GetConst();\r
+\r
+ if (a_iVar>=ValMap.size())\r
+ {\r
+ *a_pszName = 0;\r
+ *a_fVal = 0;\r
+ return;\r
+ }\r
+\r
+ mu::valmap_type::const_iterator item;\r
+ item = ValMap.begin();\r
+ for (unsigned i=0; i<a_iVar; ++i)\r
+ item++;\r
+\r
+ strncpy(szName, item->first.c_str(), sizeof(szName));\r
+ szName[sizeof(szName)-1] = 0;\r
+\r
+ *a_pszName = &szName[0];\r
+ *a_fVal = item->second;\r
+ return;\r
+\r
+ MU_CATCH\r
+\r
+ *a_pszName = 0;\r
+ *a_fVal = 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Add a custom value regognition function.\r
+*/\r
+API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, \r
+ muIdentFun_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* p(AsParser(a_hParser));\r
+ p->AddValIdent(a_pFun);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Query if an error occured.\r
+\r
+ After querying the internal error bit will be reset. So a consecutive call\r
+ will return false.\r
+*/\r
+API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser)\r
+{\r
+ bool bError( AsParserTag(a_hParser)->bError );\r
+ AsParserTag(a_hParser)->bError = false;\r
+ return bError;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Reset the internal error flag.\r
+*/\r
+API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser)\r
+{\r
+ AsParserTag(a_hParser)->bError = false;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler)\r
+{\r
+ AsParserTag(a_hParser)->errHandler = a_pHandler;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the message associated with the last error.\r
+*/\r
+API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser)\r
+{\r
+ ParserTag* const p(AsParserTag(a_hParser));\r
+ const muChar_t *pMsg = p->exc.GetMsg().c_str();\r
+\r
+ // C# explodes when pMsg is returned directly. For some reason it can't access\r
+ // the memory where the message lies directly.\r
+ sprintf(s_tmpOutBuf, "%s", pMsg);\r
+ return s_tmpOutBuf;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the message associated with the last error.\r
+*/\r
+API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser)\r
+{\r
+ ParserTag* const p(AsParserTag(a_hParser));\r
+ const muChar_t *pToken = p->exc.GetToken().c_str();\r
+\r
+ // C# explodes when pMsg is returned directly. For some reason it can't access\r
+ // the memory where the message lies directly.\r
+ sprintf(s_tmpOutBuf, "%s", pToken);\r
+ return s_tmpOutBuf;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the code associated with the last error.\r
+*/\r
+API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser)\r
+{\r
+ return AsParserTag(a_hParser)->exc.GetCode();\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the postion associated with the last error. */\r
+API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser)\r
+{\r
+ return (int)AsParserTag(a_hParser)->exc.GetPos();\r
+}\r
+\r
+////-----------------------------------------------------------------------------------------------------\r
+//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser)\r
+//{\r
+// return AsParserTag(a_hParser)->exc.GetExpr().c_str();\r
+//}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(muFloat_t*) mupCreateVar()\r
+{\r
+ return new muFloat_t(0);\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupReleaseVar(muFloat_t *ptr)\r
+{\r
+ delete ptr;\r
+}\r
+\r
+#endif // MUPARSER_DLL\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#include "muParserError.h"\r
+\r
+\r
+namespace mu\r
+{\r
+ const ParserErrorMsg ParserErrorMsg::m_Instance;\r
+\r
+ //------------------------------------------------------------------------------\r
+ const ParserErrorMsg& ParserErrorMsg::Instance()\r
+ {\r
+ return m_Instance;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ string_type ParserErrorMsg::operator[](unsigned a_iIdx) const\r
+ {\r
+ return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserErrorMsg::~ParserErrorMsg()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignement operator is deactivated.\r
+ */\r
+ ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& )\r
+ {\r
+ assert(false);\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserErrorMsg::ParserErrorMsg()\r
+ :m_vErrMsg(0)\r
+ {\r
+ m_vErrMsg.resize(ecCOUNT);\r
+\r
+ m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$.");\r
+ m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");\r
+ m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");\r
+ m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty.");\r
+ m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");\r
+ m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)");\r
+ m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");\r
+ m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");\r
+ m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");\r
+ m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero");\r
+ m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error");\r
+ m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict");\r
+ m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");\r
+ m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");\r
+ m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");\r
+ m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");\r
+ m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");\r
+ m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected.");\r
+ m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");\r
+ m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string.");\r
+ m_vErrMsg[ecGENERIC] = _T("Parser error.");\r
+ m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator.");\r
+ m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceeded by a closing bracket.");\r
+ m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");\r
+ m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");\r
+\r
+ #if defined(_DEBUG)\r
+ for (int i=0; i<ecCOUNT; ++i)\r
+ if (!m_vErrMsg[i].length())\r
+ assert(false);\r
+ #endif\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ //\r
+ // ParserError class\r
+ //\r
+ //---------------------------------------------------------------------------\r
+\r
+ /** \brief Default constructor. */\r
+ ParserError::ParserError()\r
+ :m_strMsg()\r
+ ,m_strFormula()\r
+ ,m_strTok()\r
+ ,m_iPos(-1)\r
+ ,m_iErrc(ecUNDEFINED)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief This Constructor is used for internal exceptions only. \r
+ \r
+ It does not contain any information but the error code.\r
+ */\r
+ ParserError::ParserError(EErrorCodes a_iErrc) \r
+ :m_strMsg()\r
+ ,m_strFormula()\r
+ ,m_strTok()\r
+ ,m_iPos(-1)\r
+ ,m_iErrc(a_iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ m_strMsg = m_ErrMsg[m_iErrc];\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error from a message text. */\r
+ ParserError::ParserError(const string_type &sMsg) \r
+ :m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ Reset();\r
+ m_strMsg = sMsg;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error object. \r
+ \param [in] a_iErrc the error code.\r
+ \param [in] sTok The token string related to this error.\r
+ \param [in] sExpr The expression related to the error.\r
+ \param [in] a_iPos the position in the expression where the error occured. \r
+ */\r
+ ParserError::ParserError( EErrorCodes iErrc,\r
+ const string_type &sTok,\r
+ const string_type &sExpr,\r
+ int iPos )\r
+ :m_strMsg()\r
+ ,m_strFormula(sExpr)\r
+ ,m_strTok(sTok)\r
+ ,m_iPos(iPos)\r
+ ,m_iErrc(iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ m_strMsg = m_ErrMsg[m_iErrc];\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error object. \r
+ \param [in] iErrc the error code.\r
+ \param [in] iPos the position in the expression where the error occured. \r
+ \param [in] sTok The token string related to this error.\r
+ */\r
+ ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) \r
+ :m_strMsg()\r
+ ,m_strFormula()\r
+ ,m_strTok(sTok)\r
+ ,m_iPos(iPos)\r
+ ,m_iErrc(iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ m_strMsg = m_ErrMsg[m_iErrc];\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error object. \r
+ \param [in] szMsg The error message text.\r
+ \param [in] iPos the position related to the error.\r
+ \param [in] sTok The token string related to this error.\r
+ */\r
+ ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) \r
+ :m_strMsg(szMsg)\r
+ ,m_strFormula()\r
+ ,m_strTok(sTok)\r
+ ,m_iPos(iPos)\r
+ ,m_iErrc(ecGENERIC)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Copy constructor. */\r
+ ParserError::ParserError(const ParserError &a_Obj)\r
+ :m_strMsg(a_Obj.m_strMsg)\r
+ ,m_strFormula(a_Obj.m_strFormula)\r
+ ,m_strTok(a_Obj.m_strTok)\r
+ ,m_iPos(a_Obj.m_iPos)\r
+ ,m_iErrc(a_Obj.m_iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Assignment operator. */\r
+ ParserError& ParserError::operator=(const ParserError &a_Obj)\r
+ {\r
+ if (this==&a_Obj)\r
+ return *this;\r
+\r
+ m_strMsg = a_Obj.m_strMsg;\r
+ m_strFormula = a_Obj.m_strFormula;\r
+ m_strTok = a_Obj.m_strTok;\r
+ m_iPos = a_Obj.m_iPos;\r
+ m_iErrc = a_Obj.m_iErrc;\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ ParserError::~ParserError()\r
+ {}\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Replace all ocuurences of a substring with another string. \r
+ \param strFind The string that shall be replaced.\r
+ \param strReplaceWith The string that should be inserted instead of strFind\r
+ */\r
+ void ParserError::ReplaceSubString( string_type &strSource,\r
+ const string_type &strFind,\r
+ const string_type &strReplaceWith)\r
+ {\r
+ string_type strResult;\r
+ string_type::size_type iPos(0), iNext(0);\r
+\r
+ for(;;)\r
+ {\r
+ iNext = strSource.find(strFind, iPos);\r
+ strResult.append(strSource, iPos, iNext-iPos);\r
+\r
+ if( iNext==string_type::npos )\r
+ break;\r
+\r
+ strResult.append(strReplaceWith);\r
+ iPos = iNext + strFind.length();\r
+ } \r
+\r
+ strSource.swap(strResult);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Reset the erro object. */\r
+ void ParserError::Reset()\r
+ {\r
+ m_strMsg = _T("");\r
+ m_strFormula = _T("");\r
+ m_strTok = _T("");\r
+ m_iPos = -1;\r
+ m_iErrc = ecUNDEFINED;\r
+ }\r
+ \r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set the expression related to this error. */\r
+ void ParserError::SetFormula(const string_type &a_strFormula)\r
+ {\r
+ m_strFormula = a_strFormula;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief gets the expression related tp this error.*/\r
+ const string_type& ParserError::GetExpr() const \r
+ {\r
+ return m_strFormula;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Returns the message string for this error. */\r
+ const string_type& ParserError::GetMsg() const\r
+ {\r
+ return m_strMsg;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the formula position related to the error. \r
+\r
+ If the error is not related to a distinct position this will return -1\r
+ */\r
+ std::size_t ParserError::GetPos() const\r
+ {\r
+ return m_iPos;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return string related with this token (if available). */\r
+ const string_type& ParserError::GetToken() const\r
+ {\r
+ return m_strTok;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the error code. */\r
+ EErrorCodes ParserError::GetCode() const\r
+ {\r
+ return m_iErrc;\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserInt.h"\r
+\r
+#include <cmath>\r
+#include <algorithm>\r
+#include <numeric>\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief Implementation of a parser using integer value.\r
+*/\r
+\r
+/** \brief Namespace for mathematical applications. */\r
+namespace mu\r
+{\r
+value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }\r
+value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }\r
+value_type ParserInt::Ite(value_type v1, \r
+ value_type v2, \r
+ value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }\r
+value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }\r
+value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }\r
+value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }\r
+value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }\r
+value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }\r
+value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }\r
+value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }\r
+value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }\r
+value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }\r
+value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }\r
+value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }\r
+value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }\r
+value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }\r
+value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }\r
+value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }\r
+value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }\r
+value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }\r
+value_type ParserInt::Not(value_type v) { return !Round(v); }\r
+\r
+value_type ParserInt::Pow(value_type v1, value_type v2) \r
+{ \r
+ return std::pow((double)Round(v1), (double)Round(v2)); \r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+// Unary operator Callbacks: Infix operators\r
+value_type ParserInt::UnaryMinus(value_type v) \r
+{ \r
+ return -Round(v); \r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)\r
+{ \r
+ if (!a_iArgc) \r
+ throw ParserError(_T("too few arguments for function sum."));\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes += a_afArg[i];\r
+\r
+ return fRes;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)\r
+{ \r
+ if (!a_iArgc) \r
+ throw ParserError( _T("too few arguments for function min.") );\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes = std::min(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)\r
+{ \r
+ if (!a_iArgc) \r
+ throw ParserError(_T("too few arguments for function min."));\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes = std::max(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+// Default value recognition callback\r
+int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+{\r
+ string_type buf(a_szExpr);\r
+ std::size_t pos = buf.find_first_not_of(_T("0123456789"));\r
+\r
+ if (pos==std::string::npos)\r
+ return 0;\r
+\r
+ stringstream_type stream( buf.substr(0, pos ) );\r
+ int iVal(0);\r
+\r
+ stream >> iVal;\r
+ if (stream.fail())\r
+ return 0;\r
+ \r
+ stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading\r
+ if (stream.fail())\r
+ iEnd = stream.str().length(); \r
+\r
+ if (iEnd==(stringstream_type::pos_type)-1)\r
+ return 0;\r
+\r
+ *a_iPos += (int)iEnd;\r
+ *a_fVal = (value_type)iVal;\r
+ return 1;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Check a given position in the expression for the presence of \r
+ a hex value. \r
+ \param a_szExpr Pointer to the expression string\r
+ \param [in/out] a_iPos Pointer to an interger value holding the current parsing \r
+ position in the expression.\r
+ \param [out] a_fVal Pointer to the position where the detected value shall be stored.\r
+\r
+ Hey values must be prefixed with "0x" in order to be detected properly.\r
+*/\r
+int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+{\r
+ if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) \r
+ return 0;\r
+\r
+ unsigned iVal(0);\r
+\r
+ // New code based on streams for UNICODE compliance:\r
+ stringstream_type::pos_type nPos(0);\r
+ stringstream_type ss(a_szExpr + 2);\r
+ ss >> std::hex >> iVal;\r
+ nPos = ss.tellg();\r
+\r
+ if (nPos==(stringstream_type::pos_type)0)\r
+ return 1;\r
+\r
+ *a_iPos += (int)(2 + nPos);\r
+ *a_fVal = (value_type)iVal;\r
+ return 1;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+{\r
+ if (a_szExpr[0]!='#') \r
+ return 0;\r
+\r
+ unsigned iVal(0), \r
+ iBits(sizeof(iVal)*8),\r
+ i(0);\r
+\r
+ for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)\r
+ iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);\r
+\r
+ if (i==0) \r
+ return 0;\r
+\r
+ if (i==iBits)\r
+ throw exception_type(_T("Binary to integer conversion error (overflow)."));\r
+\r
+ *a_fVal = (unsigned)(iVal >> (iBits-i) );\r
+ *a_iPos += i+1;\r
+\r
+ return 1;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Constructor. \r
+\r
+ Call ParserBase class constructor and trigger Function, Operator and Constant initialization.\r
+*/\r
+ParserInt::ParserInt()\r
+ :ParserBase()\r
+{\r
+ AddValIdent(IsVal); // lowest priority\r
+ AddValIdent(IsBinVal);\r
+ AddValIdent(IsHexVal); // highest priority\r
+\r
+ InitCharSets();\r
+ InitFun();\r
+ InitOprt();\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+void ParserInt::InitConst()\r
+{\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+void ParserInt::InitCharSets()\r
+{\r
+ DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );\r
+ DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );\r
+ DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Initialize the default functions. */\r
+void ParserInt::InitFun()\r
+{\r
+ DefineFun( _T("sign"), Sign);\r
+ DefineFun( _T("abs"), Abs);\r
+ DefineFun( _T("if"), Ite);\r
+ DefineFun( _T("sum"), Sum);\r
+ DefineFun( _T("min"), Min);\r
+ DefineFun( _T("max"), Max);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Initialize operators. */\r
+void ParserInt::InitOprt()\r
+{\r
+ // disable all built in operators, not all of them usefull for integer numbers\r
+ // (they don't do rounding of values)\r
+ EnableBuiltInOprt(false);\r
+\r
+ // Disable all built in operators, they wont work with integer numbers\r
+ // since they are designed for floating point numbers\r
+ DefineInfixOprt( _T("-"), UnaryMinus);\r
+ DefineInfixOprt( _T("!"), Not);\r
+\r
+ DefineOprt( _T("&"), LogAnd, prLOGIC);\r
+ DefineOprt( _T("|"), LogOr, prLOGIC);\r
+ DefineOprt( _T("&&"), And, prLOGIC);\r
+ DefineOprt( _T("||"), Or, prLOGIC);\r
+\r
+ DefineOprt( _T("<"), Less, prCMP);\r
+ DefineOprt( _T(">"), Greater, prCMP);\r
+ DefineOprt( _T("<="), LessEq, prCMP);\r
+ DefineOprt( _T(">="), GreaterEq, prCMP);\r
+ DefineOprt( _T("=="), Equal, prCMP);\r
+ DefineOprt( _T("!="), NotEqual, prCMP);\r
+\r
+ DefineOprt( _T("+"), Add, prADD_SUB);\r
+ DefineOprt( _T("-"), Sub, prADD_SUB);\r
+\r
+ DefineOprt( _T("*"), Mul, prMUL_DIV);\r
+ DefineOprt( _T("/"), Div, prMUL_DIV);\r
+ DefineOprt( _T("%"), Mod, prMUL_DIV);\r
+\r
+ DefineOprt( _T("^"), Pow, prPOW, oaRIGHT);\r
+ DefineOprt( _T(">>"), Shr, prMUL_DIV+1);\r
+ DefineOprt( _T("<<"), Shl, prMUL_DIV+1);\r
+}\r
+\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserTest.h"\r
+\r
+#include <cstdio>\r
+#include <cmath>\r
+#include <iostream>\r
+#include <limits>\r
+\r
+#define PARSER_CONST_PI 3.141592653589793238462643\r
+#define PARSER_CONST_E 2.718281828459045235360287\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief This file contains the implementation of parser test cases.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ namespace Test\r
+ {\r
+ int ParserTester::c_iCount = 0;\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ ParserTester::ParserTester()\r
+ :m_vTestFun()\r
+ {\r
+ AddTest(&ParserTester::TestNames);\r
+ AddTest(&ParserTester::TestSyntax);\r
+ AddTest(&ParserTester::TestPostFix);\r
+ AddTest(&ParserTester::TestInfixOprt);\r
+ AddTest(&ParserTester::TestVarConst);\r
+ AddTest(&ParserTester::TestMultiArg);\r
+ AddTest(&ParserTester::TestExpression);\r
+ AddTest(&ParserTester::TestIfThenElse);\r
+ AddTest(&ParserTester::TestInterface);\r
+ AddTest(&ParserTester::TestBinOprt);\r
+ AddTest(&ParserTester::TestException);\r
+ AddTest(&ParserTester::TestStrArg);\r
+\r
+ ParserTester::c_iCount = 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+ {\r
+ if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) \r
+ return 0;\r
+\r
+ unsigned iVal(0);\r
+\r
+ // New code based on streams for UNICODE compliance:\r
+ stringstream_type::pos_type nPos(0);\r
+ stringstream_type ss(a_szExpr + 2);\r
+ ss >> std::hex >> iVal;\r
+ nPos = ss.tellg();\r
+\r
+ if (nPos==(stringstream_type::pos_type)0)\r
+ return 1;\r
+\r
+ *a_iPos += (int)(2 + nPos);\r
+ *a_fVal = (value_type)iVal;\r
+ return 1;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::TestInterface()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing member functions...");\r
+ \r
+ // Test RemoveVar\r
+ value_type afVal[3] = {1,2,3};\r
+ Parser p;\r
+ \r
+ try\r
+ {\r
+ p.DefineVar( _T("a"), &afVal[0]);\r
+ p.DefineVar( _T("b"), &afVal[1]);\r
+ p.DefineVar( _T("c"), &afVal[2]);\r
+ p.SetExpr( _T("a+b+c") );\r
+ p.Eval();\r
+ }\r
+ catch(...)\r
+ {\r
+ iStat += 1; // this is not supposed to happen \r
+ }\r
+\r
+ try\r
+ {\r
+ p.RemoveVar( _T("c") );\r
+ p.Eval();\r
+ iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted...\r
+ }\r
+ catch(...)\r
+ {\r
+ // failure is expected...\r
+ }\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::TestStrArg()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing string arguments...");\r
+ \r
+ iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash\r
+ iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true);\r
+ iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true);\r
+ // use in expressions with variables\r
+ iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true);\r
+ iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true);\r
+ // string + numeric arguments\r
+ iStat += EqnTest(_T("strfun1(\"100\")"), 100, true);\r
+ iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true);\r
+ iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true);\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::TestBinOprt()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing binary operators...");\r
+ \r
+ // built in operators\r
+ // xor operator\r
+ //iStat += EqnTest(_T("1 xor 2"), 3, true); \r
+ //iStat += EqnTest(_T("a xor b"), 3, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("1 xor 2 xor 3"), 0, true); \r
+ //iStat += EqnTest(_T("a xor b xor 3"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("a xor b xor c"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("(1 xor 2) xor 3"), 0, true); \r
+ //iStat += EqnTest(_T("(a xor b) xor c"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("(a) xor (b) xor c"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("1 or 2"), 3, true); \r
+ //iStat += EqnTest(_T("a or b"), 3, true); // with a=1 and b=2\r
+ iStat += EqnTest(_T("a++b"), 3, true);\r
+ iStat += EqnTest(_T("a ++ b"), 3, true);\r
+ iStat += EqnTest(_T("1++2"), 3, true);\r
+ iStat += EqnTest(_T("1 ++ 2"), 3, true);\r
+ iStat += EqnTest(_T("a add b"), 3, true);\r
+ iStat += EqnTest(_T("1 add 2"), 3, true);\r
+ iStat += EqnTest(_T("a<b"), 1, true);\r
+ iStat += EqnTest(_T("b>a"), 1, true);\r
+ iStat += EqnTest(_T("a>a"), 0, true);\r
+ iStat += EqnTest(_T("a<a"), 0, true);\r
+ iStat += EqnTest(_T("a>a"), 0, true);\r
+ iStat += EqnTest(_T("a<=a"), 1, true);\r
+ iStat += EqnTest(_T("a<=b"), 1, true);\r
+ iStat += EqnTest(_T("b<=a"), 0, true);\r
+ iStat += EqnTest(_T("a>=a"), 1, true);\r
+ iStat += EqnTest(_T("b>=a"), 1, true);\r
+ iStat += EqnTest(_T("a>=b"), 0, true);\r
+\r
+ // Test logical operators, expecially if user defined "&" and the internal "&&" collide\r
+ iStat += EqnTest(_T("1 && 1"), 1, true); \r
+ iStat += EqnTest(_T("1 && 0"), 0, true); \r
+ iStat += EqnTest(_T("(a<b) && (b>a)"), 1, true); \r
+ iStat += EqnTest(_T("(a<b) && (a>b)"), 0, true); \r
+ //iStat += EqnTest(_T("12 and 255"), 12, true); \r
+ //iStat += EqnTest(_T("12 and 0"), 0, true); \r
+ iStat += EqnTest(_T("12 & 255"), 12, true); \r
+ iStat += EqnTest(_T("12 & 0"), 0, true); \r
+ iStat += EqnTest(_T("12&255"), 12, true); \r
+ iStat += EqnTest(_T("12&0"), 0, true); \r
+\r
+ // Assignement operator\r
+ iStat += EqnTest(_T("a = b"), 2, true); \r
+ iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); \r
+ iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true);\r
+ iStat += EqnTest(_T("(a=b)*2"), 4, true);\r
+ iStat += EqnTest(_T("2*(a=b)"), 4, true);\r
+ iStat += EqnTest(_T("2*(a=b+1)"), 6, true);\r
+ iStat += EqnTest(_T("(a=b+1)*2"), 6, true);\r
+\r
+ iStat += EqnTest(_T("2^2^3"), 256, true); \r
+ iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); \r
+\r
+ // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3\r
+ iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); \r
+\r
+ // Test user defined binary operators\r
+ iStat += EqnTestInt(_T("1 | 2"), 3, true); \r
+ iStat += EqnTestInt(_T("1 || 2"), 1, true); \r
+ iStat += EqnTestInt(_T("123 & 456"), 72, true); \r
+ iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true);\r
+ iStat += EqnTestInt(_T("1 && 0"), 0, true); \r
+ iStat += EqnTestInt(_T("123 && 456"), 1, true); \r
+ iStat += EqnTestInt(_T("1 << 3"), 8, true); \r
+ iStat += EqnTestInt(_T("8 >> 3"), 1, true); \r
+ iStat += EqnTestInt(_T("9 / 4"), 2, true); \r
+ iStat += EqnTestInt(_T("9 % 4"), 1, true); \r
+ iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true);\r
+ iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true);\r
+ iStat += EqnTestInt(_T("-10+1"), -9, true);\r
+ iStat += EqnTestInt(_T("1+2*3"), 7, true);\r
+ iStat += EqnTestInt(_T("const1 != const2"), 1, true);\r
+ iStat += EqnTestInt(_T("const1 != const2"), 0, false);\r
+ iStat += EqnTestInt(_T("const1 == const2"), 0, true);\r
+ iStat += EqnTestInt(_T("const1 == 1"), 1, true);\r
+ iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true);\r
+ iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false);\r
+ iStat += EqnTestInt(_T("const1 < const2"), 1, true);\r
+ iStat += EqnTestInt(_T("const2 > const1"), 1, true);\r
+ iStat += EqnTestInt(_T("const1 <= 1"), 1, true);\r
+ iStat += EqnTestInt(_T("const2 >= 2"), 1, true);\r
+ iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true);\r
+ iStat += EqnTestInt(_T("a != b"), 1, true);\r
+ iStat += EqnTestInt(_T("a != b"), 0, false);\r
+ iStat += EqnTestInt(_T("a == b"), 0, true);\r
+ iStat += EqnTestInt(_T("a == 1"), 1, true);\r
+ iStat += EqnTestInt(_T("10*(a == 1)"), 10, true);\r
+ iStat += EqnTestInt(_T("2*(a | b)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(a | b)"), 7, false);\r
+ iStat += EqnTestInt(_T("a < b"), 1, true);\r
+ iStat += EqnTestInt(_T("b > a"), 1, true);\r
+ iStat += EqnTestInt(_T("a <= 1"), 1, true);\r
+ iStat += EqnTestInt(_T("b >= 2"), 1, true);\r
+ iStat += EqnTestInt(_T("2*(a + b)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(a - b)"), -2, true);\r
+ iStat += EqnTestInt(_T("a + (a << b)"), 5, true);\r
+ iStat += EqnTestInt(_T("-2^2"), -4, true);\r
+ iStat += EqnTestInt(_T("3--a"), 4, true);\r
+ iStat += EqnTestInt(_T("3+-3^2"), -6, true);\r
+\r
+ // Test reading of hex values:\r
+ iStat += EqnTestInt(_T("0xff"), 255, true);\r
+ iStat += EqnTestInt(_T("10+0xff"), 265, true);\r
+ iStat += EqnTestInt(_T("0xff+10"), 265, true);\r
+ iStat += EqnTestInt(_T("10*0xff"), 2550, true);\r
+ iStat += EqnTestInt(_T("0xff*10"), 2550, true);\r
+ iStat += EqnTestInt(_T("10+0xff+1"), 266, true);\r
+ iStat += EqnTestInt(_T("1+0xff+10"), 266, true);\r
+\r
+// incorrect: '^' is yor here, not power\r
+// iStat += EqnTestInt("-(1+2)^2", -9, true);\r
+// iStat += EqnTestInt("-1^3", -1, true); \r
+\r
+ // Test precedence\r
+ // a=1, b=2, c=3\r
+ iStat += EqnTestInt(_T("a + b * c"), 7, true);\r
+ iStat += EqnTestInt(_T("a * b + c"), 5, true);\r
+ iStat += EqnTestInt(_T("a<b && b>10"), 0, true);\r
+ iStat += EqnTestInt(_T("a<b && b<10"), 1, true);\r
+\r
+ iStat += EqnTestInt(_T("a + b << c"), 17, true);\r
+ iStat += EqnTestInt(_T("a << b + c"), 7, true);\r
+ iStat += EqnTestInt(_T("c * b < a"), 0, true);\r
+ iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true);\r
+ iStat += EqnTestInt(_T("2^2^3"), 256, true); \r
+\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ /** \brief Check muParser name restriction enforcement. */\r
+ int ParserTester::TestNames()\r
+ {\r
+ int iStat= 0,\r
+ iErr = 0;\r
+\r
+ mu::console() << "testing name restriction enforcement...";\r
+ \r
+ Parser p;\r
+\r
+ #define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \\r
+ iErr = 0; \\r
+ ParserTester::c_iCount++; \\r
+ try \\r
+ { \\r
+ p.Define##DOMAIN(EXPR, ARG); \\r
+ } \\r
+ catch(Parser::exception_type&) \\r
+ { \\r
+ iErr = (FAIL==false) ? 0 : 1; \\r
+ } \\r
+ iStat += iErr; \r
+ \r
+ // constant names\r
+ PARSER_THROWCHECK(Const, false, _T("0a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("9a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("+a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("-a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("a-"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("a*"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("a?"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a_min"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a_min0"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a_min9"), 1)\r
+ // variable names\r
+ value_type a;\r
+ p.ClearConst();\r
+ PARSER_THROWCHECK(Var, false, _T("123abc"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("9a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("0a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("+a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("-a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("?a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("!a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a+"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a-"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a*"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a?"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a_min"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)\r
+ // Postfix operators\r
+ // fail\r
+ PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)\r
+ // pass\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("_"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("#"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("&&"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("||"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("&"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("|"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("++"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("--"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?>"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1)\r
+ // Binary operator\r
+ // The following must fail with builtin operators activated\r
+ // p.EnableBuiltInOp(true); -> this is the default\r
+ p.ClearPostfixOprt();\r
+ PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2)\r
+ // without activated built in operators it should work\r
+ p.EnableBuiltInOprt(false);\r
+ PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2)\r
+ #undef PARSER_THROWCHECK\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestSyntax()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing syntax engine...");\r
+\r
+ iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+\r
+ iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula\r
+ iStat += EqnTest(_T("sqrt((4))"), 2, true); // Multiple brackets\r
+ iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or"\r
+ iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket \r
+ iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator\r
+ iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator\r
+ iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("--2"), 0, false); // double sign\r
+ iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token\r
+ iStat += EqnTest(_T("()"), 0, false); // empty bracket without a function\r
+ iStat += EqnTest(_T("5+()"), 0, false); // empty bracket without a function\r
+ iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function\r
+ iStat += EqnTest(_T("5t6"), 0, false); // unknown token\r
+ iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token\r
+ iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula\r
+ iStat += EqnTest(_T(",3"), 0, false); // unexpected comma\r
+ iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma\r
+ iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args\r
+ iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args\r
+ iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestVarConst()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing variable/constant detection...");\r
+\r
+ // Test if the result changes when a variable changes\r
+ iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 );\r
+ iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 );\r
+\r
+ // distinguish constants with same basename\r
+ iStat += EqnTest( _T("const"), 1, true);\r
+ iStat += EqnTest( _T("const1"), 2, true);\r
+ iStat += EqnTest( _T("const2"), 3, true);\r
+ iStat += EqnTest( _T("2*const"), 2, true);\r
+ iStat += EqnTest( _T("2*const1"), 4, true);\r
+ iStat += EqnTest( _T("2*const2"), 6, true);\r
+ iStat += EqnTest( _T("2*const+1"), 3, true);\r
+ iStat += EqnTest( _T("2*const1+1"), 5, true);\r
+ iStat += EqnTest( _T("2*const2+1"), 7, true);\r
+ iStat += EqnTest( _T("const"), 0, false);\r
+ iStat += EqnTest( _T("const1"), 0, false);\r
+ iStat += EqnTest( _T("const2"), 0, false);\r
+\r
+ // distinguish variables with same basename\r
+ iStat += EqnTest( _T("a"), 1, true);\r
+ iStat += EqnTest( _T("aa"), 2, true);\r
+ iStat += EqnTest( _T("2*a"), 2, true);\r
+ iStat += EqnTest( _T("2*aa"), 4, true);\r
+ iStat += EqnTest( _T("2*a-1"), 1, true);\r
+ iStat += EqnTest( _T("2*aa-1"), 3, true);\r
+\r
+ // custom value recognition\r
+ iStat += EqnTest( _T("0xff"), 255, true);\r
+ iStat += EqnTest( _T("0x97 + 0xff"), 406, true);\r
+\r
+ // Finally test querying of used variables\r
+ try\r
+ {\r
+ int idx;\r
+ mu::Parser p;\r
+ mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};\r
+ p.DefineVar( _T("a"), &vVarVal[0]);\r
+ p.DefineVar( _T("b"), &vVarVal[1]);\r
+ p.DefineVar( _T("c"), &vVarVal[2]);\r
+ p.DefineVar( _T("d"), &vVarVal[3]);\r
+ p.DefineVar( _T("e"), &vVarVal[4]);\r
+\r
+ // Test lookup of defined variables\r
+ // 4 used variables\r
+ p.SetExpr( _T("a+b+c+d") );\r
+ mu::varmap_type UsedVar = p.GetUsedVar();\r
+ int iCount = (int)UsedVar.size();\r
+ if (iCount!=4) \r
+ throw false;\r
+ \r
+ // the next check will fail if the parser \r
+ // erroneousely creates new variables internally\r
+ if (p.GetVar().size()!=5)\r
+ throw false;\r
+\r
+ mu::varmap_type::const_iterator item = UsedVar.begin();\r
+ for (idx=0; item!=UsedVar.end(); ++item)\r
+ {\r
+ if (&vVarVal[idx++]!=item->second) \r
+ throw false;\r
+ }\r
+\r
+ // Test lookup of undefined variables\r
+ p.SetExpr( _T("undef1+undef2+undef3") );\r
+ UsedVar = p.GetUsedVar();\r
+ iCount = (int)UsedVar.size();\r
+ if (iCount!=3) \r
+ throw false;\r
+\r
+ // the next check will fail if the parser \r
+ // erroneousely creates new variables internally\r
+ if (p.GetVar().size()!=5)\r
+ throw false;\r
+\r
+ for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)\r
+ {\r
+ if (item->second!=0) \r
+ throw false; // all pointers to undefined variables must be null\r
+ }\r
+\r
+ // 1 used variables\r
+ p.SetExpr( _T("a+b") );\r
+ UsedVar = p.GetUsedVar();\r
+ iCount = (int)UsedVar.size();\r
+ if (iCount!=2) throw false;\r
+ item = UsedVar.begin();\r
+ for (idx=0; item!=UsedVar.end(); ++item)\r
+ if (&vVarVal[idx++]!=item->second) throw false;\r
+\r
+ }\r
+ catch(...)\r
+ {\r
+ iStat += 1;\r
+ }\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestMultiArg()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing multiarg functions...");\r
+ \r
+ // Compound expressions\r
+ iStat += EqnTest( _T("1,2,3"), 3, true);\r
+ iStat += EqnTest( _T("a,b,c"), 3, true);\r
+ iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true);\r
+ iStat += EqnTest( _T("1,\n2,\n3"), 3, true);\r
+ iStat += EqnTest( _T("a,\nb,\nc"), 3, true);\r
+ iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true);\r
+ iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true);\r
+ iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true);\r
+ iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true);\r
+\r
+ // picking the right argument\r
+ iStat += EqnTest( _T("f1of1(1)"), 1, true);\r
+ iStat += EqnTest( _T("f1of2(1, 2)"), 1, true);\r
+ iStat += EqnTest( _T("f2of2(1, 2)"), 2, true);\r
+ iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true);\r
+ iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true);\r
+ iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true);\r
+ iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true);\r
+ iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true);\r
+ iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true);\r
+ iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true);\r
+ iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true);\r
+ iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true);\r
+ iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true);\r
+ iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true);\r
+ iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true);\r
+ // Too few arguments / Too many arguments\r
+ iStat += EqnTest( _T("1+ping()"), 11, true);\r
+ iStat += EqnTest( _T("ping()+1"), 11, true);\r
+ iStat += EqnTest( _T("2*ping()"), 20, true);\r
+ iStat += EqnTest( _T("ping()*2"), 20, true);\r
+ iStat += EqnTest( _T("ping(1,2)"), 0, false);\r
+ iStat += EqnTest( _T("1+ping(1,2)"), 0, false);\r
+ iStat += EqnTest( _T("f1of1(1,2)"), 0, false);\r
+ iStat += EqnTest( _T("f1of1()"), 0, false);\r
+ iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false);\r
+ iStat += EqnTest( _T("f1of2(1)"), 0, false);\r
+ iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false);\r
+ iStat += EqnTest( _T("f1of3(1)"), 0, false);\r
+ iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false);\r
+ iStat += EqnTest( _T("f1of4(1)"), 0, false);\r
+ iStat += EqnTest( _T("(1,2,3)"), 0, false);\r
+ iStat += EqnTest( _T("1,2,3"), 0, false);\r
+ iStat += EqnTest( _T("(1*a,2,3)"), 0, false);\r
+ iStat += EqnTest( _T("1,2*a,3"), 0, false);\r
+ \r
+ // correct calculation of arguments\r
+ iStat += EqnTest( _T("min(a, 1)"), 1, true);\r
+ iStat += EqnTest( _T("min(3*2, 1)"), 1, true);\r
+ iStat += EqnTest( _T("min(3*2, 1)"), 6, false);\r
+ iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true);\r
+ iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true);\r
+ iStat += EqnTest( _T("min(3*a+1, 1)"), 1, true);\r
+ iStat += EqnTest( _T("max(3*a+1, 1)"), 4, true);\r
+ iStat += EqnTest( _T("max(3*a+1, 1)*2"), 8, true);\r
+ iStat += EqnTest( _T("2*max(3*a+1, 1)+2"), 10, true);\r
+\r
+ // functions with Variable argument count\r
+ iStat += EqnTest( _T("sum(a)"), 1, true);\r
+ iStat += EqnTest( _T("sum(1,2,3)"), 6, true);\r
+ iStat += EqnTest( _T("sum(a,b,c)"), 6, true);\r
+ iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true);\r
+ iStat += EqnTest( _T("2*sum(1,2,3)"), 12, true);\r
+ iStat += EqnTest( _T("2*sum(1,2,3)+2"), 14, true);\r
+ iStat += EqnTest( _T("2*sum(-1,2,3)+2"), 10, true);\r
+ iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"), 6, true);\r
+ iStat += EqnTest( _T("2*sum(-1,10,-a)+2"), 18, true);\r
+ iStat += EqnTest( _T("2*sum(1,2,3)*2"), 24, true);\r
+ iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true);\r
+ iStat += EqnTest( _T("sum(1*3, 4, a+2)"), 10, true);\r
+ iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true);\r
+ iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true);\r
+\r
+ // some failures\r
+ iStat += EqnTest( _T("sum()"), 0, false);\r
+ iStat += EqnTest( _T("sum(,)"), 0, false);\r
+ iStat += EqnTest( _T("sum(1,2,)"), 0, false);\r
+ iStat += EqnTest( _T("sum(,1,2)"), 0, false);\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+ \r
+ return iStat;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestInfixOprt()\r
+ {\r
+ int iStat(0);\r
+ mu::console() << "testing infix operators...";\r
+\r
+ iStat += EqnTest( _T("-1"), -1, true);\r
+ iStat += EqnTest( _T("-(-1)"), 1, true);\r
+ iStat += EqnTest( _T("-(-1)*2"), 2, true);\r
+ iStat += EqnTest( _T("-(-2)*sqrt(4)"), 4, true);\r
+ iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true);\r
+ iStat += EqnTest( _T("-a"), -1, true);\r
+ iStat += EqnTest( _T("-(a)"), -1, true);\r
+ iStat += EqnTest( _T("-(-a)"), 1, true);\r
+ iStat += EqnTest( _T("-(-a)*2"), 2, true);\r
+ iStat += EqnTest( _T("-(8)"), -8, true);\r
+ iStat += EqnTest( _T("-8"), -8, true);\r
+ iStat += EqnTest( _T("-(2+1)"), -3, true);\r
+ iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true);\r
+ iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true);\r
+ iStat += EqnTest( _T("-sin(8)"), -0.989358, true);\r
+ iStat += EqnTest( _T("3-(-a)"), 4, true);\r
+ iStat += EqnTest( _T("3--a"), 4, true);\r
+ iStat += EqnTest( _T("-1*3"), -3, true);\r
+\r
+ // Postfix / infix priorities\r
+ iStat += EqnTest( _T("~2#"), 8, true);\r
+ iStat += EqnTest( _T("~f1of1(2)#"), 8, true);\r
+ iStat += EqnTest( _T("~(b)#"), 8, true);\r
+ iStat += EqnTest( _T("(~b)#"), 12, true);\r
+ iStat += EqnTest( _T("~(2#)"), 8, true);\r
+ iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true);\r
+ //\r
+ iStat += EqnTest( _T("-2^2"),-4, true);\r
+ iStat += EqnTest( _T("-(a+b)^2"),-9, true);\r
+ iStat += EqnTest( _T("(-3)^2"),9, true);\r
+ iStat += EqnTest( _T("-(-2^2)"),4, true);\r
+ iStat += EqnTest( _T("3+-3^2"),-6, true);\r
+ // The following assumes use of sqr as postfix operator ("§") together\r
+ // with a sign operator of low priority:\r
+ iStat += EqnTest( _T("-2'"), -4, true);\r
+ iStat += EqnTest( _T("-(1+1)'"),-4, true);\r
+ iStat += EqnTest( _T("2+-(1+1)'"),-2, true);\r
+ iStat += EqnTest( _T("2+-2'"), -2, true);\r
+ // This is the classic behaviour of the infix sign operator (here: "$") which is\r
+ // now deprecated:\r
+ iStat += EqnTest( _T("$2^2"),4, true);\r
+ iStat += EqnTest( _T("$(a+b)^2"),9, true);\r
+ iStat += EqnTest( _T("($3)^2"),9, true);\r
+ iStat += EqnTest( _T("$($2^2)"),-4, true);\r
+ iStat += EqnTest( _T("3+$3^2"),12, true);\r
+\r
+ // infix operators sharing the first few characters\r
+ iStat += EqnTest( _T("~ 123"), 123+2, true);\r
+ iStat += EqnTest( _T("~~ 123"), 123+2, true);\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestPostFix()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing postfix operators...");\r
+\r
+ // application\r
+ iStat += EqnTest( _T("3{m}+5"), 5.003, true);\r
+ iStat += EqnTest( _T("1000{m}"), 1, true);\r
+ iStat += EqnTest( _T("1000 {m}"), 1, true);\r
+ iStat += EqnTest( _T("(a){m}"), 1e-3, true);\r
+ iStat += EqnTest( _T("a{m}"), 1e-3, true);\r
+ iStat += EqnTest( _T("a {m}"), 1e-3, true);\r
+ iStat += EqnTest( _T("-(a){m}"), -1e-3, true);\r
+ iStat += EqnTest( _T("-2{m}"), -2e-3, true);\r
+ iStat += EqnTest( _T("-2 {m}"), -2e-3, true);\r
+ iStat += EqnTest( _T("f1of1(1000){m}"), 1, true);\r
+ iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true);\r
+ iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true);\r
+ iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true);\r
+ iStat += EqnTest( _T("2+(a*1000){m}"), 3, true);\r
+\r
+ // can postfix operators "m" und "meg" be told apart properly?\r
+ iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true); \r
+\r
+ // some incorrect results\r
+ iStat += EqnTest( _T("1000{m}"), 0.1, false);\r
+ iStat += EqnTest( _T("(a){m}"), 2, false);\r
+ // failure due to syntax checking\r
+ iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition\r
+ iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);\r
+ iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS);\r
+ \r
+ iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN);\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestExpression()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing expression samples...");\r
+\r
+ value_type b = 2;\r
+\r
+ // Optimization\r
+ iStat += EqnTest( _T("2*b*5"), 20, true);\r
+ iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true);\r
+ iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true);\r
+\r
+ // Addition auf cmVARMUL \r
+ iStat += EqnTest( _T("3+b"), b+3, true);\r
+ iStat += EqnTest( _T("b+3"), b+3, true);\r
+ iStat += EqnTest( _T("b*3+2"), b*3+2, true);\r
+ iStat += EqnTest( _T("3*b+2"), b*3+2, true);\r
+ iStat += EqnTest( _T("2+b*3"), b*3+2, true);\r
+ iStat += EqnTest( _T("2+3*b"), b*3+2, true);\r
+ iStat += EqnTest( _T("b+3*b"), b+3*b, true);\r
+ iStat += EqnTest( _T("3*b+b"), b+3*b, true);\r
+\r
+ iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true);\r
+ iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true);\r
+\r
+ iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true);\r
+ iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true);\r
+\r
+ // operator precedencs\r
+ iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true);\r
+ iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true);\r
+ iStat += EqnTest( _T("1+2*3"), 7, true);\r
+ iStat += EqnTest( _T("1+2*3"), 7, true);\r
+ iStat += EqnTest( _T("(1+2)*3"), 9, true);\r
+ iStat += EqnTest( _T("(1+2)*(-3)"), -9, true);\r
+ iStat += EqnTest( _T("2/4"), 0.5, true);\r
+\r
+ iStat += EqnTest( _T("exp(ln(7))"), 7, true);\r
+ iStat += EqnTest( _T("e^ln(7)"), 7, true);\r
+ iStat += EqnTest( _T("e^(ln(7))"), 7, true);\r
+ iStat += EqnTest( _T("(e^(ln(7)))"), 7, true);\r
+ iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true);\r
+ iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true);\r
+ iStat += EqnTest( _T("10^log(5)"), 5, true);\r
+ iStat += EqnTest( _T("10^log10(5)"), 5, true);\r
+ iStat += EqnTest( _T("2^log2(4)"), 4, true);\r
+ iStat += EqnTest( _T("-(sin(0)+1)"), -1, true);\r
+ iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true);\r
+\r
+ iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true);\r
+ iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true);\r
+ iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true);\r
+ iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true);\r
+\r
+ // long formula (Reference: Matlab)\r
+ iStat += EqnTest(\r
+ _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))")\r
+ _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/")\r
+ _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-")\r
+ _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6")\r
+ _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e")\r
+ _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true);\r
+\r
+ // long formula (Reference: Matlab)\r
+ iStat += EqnTest(\r
+ _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e")\r
+ _T(")+a)))*2.77)"), -2.16995656, true);\r
+\r
+ // long formula (Reference: Matlab)\r
+ iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true);\r
+ \r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl; \r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestIfThenElse()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing if-then-else operator...");\r
+\r
+ // Test error detection\r
+ iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); \r
+ iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); \r
+ iStat += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("a : b"), ecMISPLACED_COLON); \r
+ iStat += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON); \r
+ iStat += ThrowTest(_T("(1) ? 1 : 2 : 3"), ecMISPLACED_COLON); \r
+ iStat += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecUNASSIGNABLE_TOKEN); \r
+\r
+ iStat += EqnTest(_T("1 ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("a<b ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(a<b) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(1) ? 10 : 11"), 10, true);\r
+ iStat += EqnTest(_T("(0) ? 10 : 11"), 11, true);\r
+ iStat += EqnTest(_T("(1) ? a+b : c+d"), 3, true);\r
+ iStat += EqnTest(_T("(0) ? a+b : c+d"), 1, true);\r
+ iStat += EqnTest(_T("(1) ? 0 : 1"), 0, true);\r
+ iStat += EqnTest(_T("(0) ? 0 : 1"), 1, true);\r
+ iStat += EqnTest(_T("(a<b) ? 10 : 11"), 10, true);\r
+ iStat += EqnTest(_T("(a>b) ? 10 : 11"), 11, true);\r
+ iStat += EqnTest(_T("(a<b) ? c : d"), 3, true);\r
+ iStat += EqnTest(_T("(a>b) ? c : d"), -2, true);\r
+\r
+ iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true);\r
+ iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true);\r
+ iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true);\r
+ iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true);\r
+\r
+ iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true);\r
+ iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true);\r
+ iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true);\r
+ iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true);\r
+ iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true);\r
+ iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true);\r
+ iStat += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true);\r
+ iStat += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true);\r
+ iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true);\r
+ iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true);\r
+ iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true);\r
+ iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true);\r
+ iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true);\r
+ iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true);\r
+ iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true);\r
+\r
+ // todo: auch für muParserX hinzufügen!\r
+ iStat += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);\r
+ iStat += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);\r
+ iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);\r
+ iStat += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);\r
+\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true);\r
+ iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true);\r
+ iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true);\r
+ iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true);\r
+\r
+ // assignment operators\r
+ iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true);\r
+ iStat += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true);\r
+ iStat += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true);\r
+ iStat += EqnTest(_T("0 ? a=a+1 : 666, a"), 1, true);\r
+ iStat += EqnTest(_T("1?a=10:a=20, a"), 10, true);\r
+ iStat += EqnTest(_T("0?a=10:a=20, a"), 20, true);\r
+ iStat += EqnTest(_T("0?a=sum(3,4):10, a"), 1, true); // a should not change its value due to lazy calculation\r
+ \r
+ iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true);\r
+ iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true);\r
+ iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true);\r
+ iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true);\r
+\r
+ iStat += EqnTest(_T("a=1?5:b=1?3:4, a"), 5, true);\r
+ iStat += EqnTest(_T("a=1?5:b=1?3:4, b"), 2, true);\r
+ iStat += EqnTest(_T("a=0?5:b=1?3:4, a"), 3, true);\r
+ iStat += EqnTest(_T("a=0?5:b=1?3:4, b"), 3, true);\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl; \r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestException()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing error codes...");\r
+\r
+ iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);\r
+ iStat += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest(_T("()"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest(_T("3+()"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest(_T("sin(3,4)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest(_T("sin()"), ecTOO_FEW_PARAMS);\r
+ iStat += ThrowTest(_T("(1+2"), ecMISSING_PARENS);\r
+ iStat += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL);\r
+ iStat += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);\r
+ iStat += ThrowTest(_T("a+b+c=10"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest(_T("a=b=3"), ecUNEXPECTED_OPERATOR);\r
+\r
+#if defined(MUP_MATH_EXCEPTIONS)\r
+ // divide by zero whilst constant folding\r
+ iStat += ThrowTest(_T("1/0"), ecDIV_BY_ZERO);\r
+ // square root of a negative number\r
+ iStat += ThrowTest(_T("sqrt(-1)"), ecDOMAIN_ERROR);\r
+ // logarithms of zero\r
+ iStat += ThrowTest(_T("ln(0)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log2(0)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log10(0)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log(0)"), ecDOMAIN_ERROR);\r
+ // logarithms of negative values\r
+ iStat += ThrowTest(_T("ln(-1)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log2(-1)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log10(-1)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log(-1)"), ecDOMAIN_ERROR);\r
+#endif\r
+\r
+ // functions without parameter\r
+ iStat += ThrowTest( _T("3+ping(2)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("3+ping(a+2)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("3+ping(sin(a)+2)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("3+ping(1+sin(a))"), ecTOO_MANY_PARAMS);\r
+\r
+ // String function related\r
+ iStat += ThrowTest( _T("valueof(\"xxx\")"), 999, false);\r
+ iStat += ThrowTest( _T("valueof()"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest( _T("1+valueof(\"abc\""), ecMISSING_PARENS);\r
+ iStat += ThrowTest( _T("valueof(\"abc\""), ecMISSING_PARENS);\r
+ iStat += ThrowTest( _T("valueof(\"abc"), ecUNTERMINATED_STRING);\r
+ iStat += ThrowTest( _T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("valueof(3)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("sin(\"abc\")"), ecVAL_EXPECTED);\r
+ iStat += ThrowTest( _T("valueof(\"\\\"abc\\\"\")"), 999, false);\r
+ iStat += ThrowTest( _T("\"hello world\""), ecSTR_RESULT);\r
+ iStat += ThrowTest( _T("(\"hello world\")"), ecSTR_RESULT);\r
+ iStat += ThrowTest( _T("\"abcd\"+100"), ecOPRT_TYPE_CONFLICT);\r
+ iStat += ThrowTest( _T("\"a\"+\"b\""), ecOPRT_TYPE_CONFLICT);\r
+ iStat += ThrowTest( _T("strfun1(\"100\",3)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(\"100\",3,5)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(\"100\")"), ecTOO_FEW_PARAMS);\r
+ iStat += ThrowTest( _T("strfun3(\"100\",6)"), ecTOO_FEW_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(1,1)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun2(a,1)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun2(1,1,1)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(a,1,1)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun3(1,2,3)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(1, \"100\",3)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(\"1\", \"100\",3)"), ecVAL_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(\"1\", 3, \"100\")"), ecVAL_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(\"1\", \"100\", \"100\", \"100\")"), ecTOO_MANY_PARAMS);\r
+\r
+ // assignement operator\r
+ iStat += ThrowTest( _T("3=4"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("sin(8)=4"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("\"test\"=a"), ecUNEXPECTED_OPERATOR);\r
+\r
+ // <ibg 20090529>\r
+ // this is now legal, for reference see:\r
+ // https://sourceforge.net/forum/message.php?msg_id=7411373\r
+ // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); \r
+ // </ibg>\r
+\r
+ iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT);\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTester::AddTest(testfun_type a_pFun)\r
+ {\r
+ m_vTestFun.push_back(a_pFun);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTester::Run()\r
+ {\r
+ int iStat = 0;\r
+ try\r
+ {\r
+ for (int i=0; i<(int)m_vTestFun.size(); ++i)\r
+ iStat += (this->*m_vTestFun[i])();\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ mu::console() << "\n" << e.GetMsg() << endl;\r
+ mu::console() << e.GetToken() << endl;\r
+ Abort();\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << e.what() << endl;\r
+ Abort();\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << "Internal error";\r
+ Abort();\r
+ }\r
+\r
+ if (iStat==0) \r
+ {\r
+ mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl;\r
+ }\r
+ else \r
+ {\r
+ mu::console() << "Test failed with " << iStat \r
+ << " errors (" << ParserTester::c_iCount \r
+ << " expressions)" << endl;\r
+ }\r
+ ParserTester::c_iCount = 0;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)\r
+ {\r
+ ParserTester::c_iCount++;\r
+\r
+ try\r
+ {\r
+ value_type fVal[] = {1,1,1};\r
+ Parser p;\r
+\r
+ p.DefineVar( _T("a"), &fVal[0]);\r
+ p.DefineVar( _T("b"), &fVal[1]);\r
+ p.DefineVar( _T("c"), &fVal[2]);\r
+ p.DefinePostfixOprt( _T("{m}"), Milli);\r
+ p.DefinePostfixOprt( _T("m"), Milli);\r
+ p.DefineFun( _T("ping"), Ping);\r
+ p.DefineFun( _T("valueof"), ValueOf);\r
+ p.DefineFun( _T("strfun1"), StrFun1);\r
+ p.DefineFun( _T("strfun2"), StrFun2);\r
+ p.DefineFun( _T("strfun3"), StrFun3);\r
+ p.SetExpr(a_str);\r
+ p.Eval();\r
+ }\r
+ catch(ParserError &e)\r
+ {\r
+ // output the formula in case of an failed test\r
+ if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )\r
+ {\r
+ mu::console() << _T("\n ") \r
+ << _T("Expression: ") << a_str \r
+ << _T(" Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")")\r
+ << _T(" Expected:") << a_iErrc;\r
+ }\r
+\r
+ return (a_iErrc==e.GetCode()) ? 0 : 1;\r
+ }\r
+\r
+ // if a_bFail==false no exception is expected\r
+ bool bRet((a_bFail==false) ? 0 : 1);\r
+ if (bRet==1)\r
+ {\r
+ mu::console() << _T("\n ") \r
+ << _T("Expression: ") << a_str \r
+ << _T(" did evaluate; Expected error:") << a_iErrc;\r
+ }\r
+\r
+ return bRet; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Evaluate a tet expression. \r
+\r
+ \return 1 in case of a failure, 0 otherwise.\r
+ */\r
+ int ParserTester::EqnTestWithVarChange(const string_type &a_str, \r
+ double a_fVar1, \r
+ double a_fRes1, \r
+ double a_fVar2, \r
+ double a_fRes2)\r
+ {\r
+ ParserTester::c_iCount++;\r
+ value_type fVal[2] = {-999, -999 }; // should be equalinitially\r
+\r
+ try\r
+ {\r
+ Parser p;\r
+\r
+ // variable\r
+ value_type var = 0;\r
+ p.DefineVar( _T("a"), &var);\r
+ p.SetExpr(a_str);\r
+\r
+ var = a_fVar1;\r
+ fVal[0] = p.Eval();\r
+\r
+ var = a_fVar2;\r
+ fVal[1] = p.Eval();\r
+ \r
+ if ( fabs(a_fRes1-fVal[0]) > 0.0000000001)\r
+ throw std::runtime_error("incorrect result (first pass)");\r
+\r
+ if ( fabs(a_fRes2-fVal[1]) > 0.0000000001)\r
+ throw std::runtime_error("incorrect result (second pass)");\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");\r
+ return 1;\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");\r
+ return 1; // always return a failure since this exception is not expected\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
+ return 1; // exceptions other than ParserException are not allowed\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Evaluate a tet expression. \r
+\r
+ \return 1 in case of a failure, 0 otherwise.\r
+ */\r
+ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)\r
+ {\r
+ ParserTester::c_iCount++;\r
+ int iRet(0);\r
+ value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different\r
+\r
+ try\r
+ {\r
+ std::auto_ptr<Parser> p1;\r
+ Parser p2, p3; // three parser objects\r
+ // they will be used for testing copy and assihnment operators\r
+ // p1 is a pointer since i'm going to delete it in order to test if\r
+ // parsers after copy construction still refer to members of it.\r
+ // !! If this is the case this function will crash !!\r
+ \r
+ p1.reset(new mu::Parser()); \r
+ // Add constants\r
+ p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI);\r
+ p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E);\r
+ p1->DefineConst( _T("const"), 1);\r
+ p1->DefineConst( _T("const1"), 2);\r
+ p1->DefineConst( _T("const2"), 3);\r
+ // variables\r
+ value_type vVarVal[] = { 1, 2, 3, -2};\r
+ p1->DefineVar( _T("a"), &vVarVal[0]);\r
+ p1->DefineVar( _T("aa"), &vVarVal[1]);\r
+ p1->DefineVar( _T("b"), &vVarVal[1]);\r
+ p1->DefineVar( _T("c"), &vVarVal[2]);\r
+ p1->DefineVar( _T("d"), &vVarVal[3]);\r
+ \r
+ // custom value ident functions\r
+ p1->AddValIdent(&ParserTester::IsHexVal); \r
+\r
+ // functions\r
+ p1->DefineFun( _T("ping"), Ping);\r
+ p1->DefineFun( _T("f1of1"), f1of1); // one parameter\r
+ p1->DefineFun( _T("f1of2"), f1of2); // two parameter\r
+ p1->DefineFun( _T("f2of2"), f2of2);\r
+ p1->DefineFun( _T("f1of3"), f1of3); // three parameter\r
+ p1->DefineFun( _T("f2of3"), f2of3);\r
+ p1->DefineFun( _T("f3of3"), f3of3);\r
+ p1->DefineFun( _T("f1of4"), f1of4); // four parameter\r
+ p1->DefineFun( _T("f2of4"), f2of4);\r
+ p1->DefineFun( _T("f3of4"), f3of4);\r
+ p1->DefineFun( _T("f4of4"), f4of4);\r
+ p1->DefineFun( _T("f1of5"), f1of5); // five parameter\r
+ p1->DefineFun( _T("f2of5"), f2of5);\r
+ p1->DefineFun( _T("f3of5"), f3of5);\r
+ p1->DefineFun( _T("f4of5"), f4of5);\r
+ p1->DefineFun( _T("f5of5"), f5of5);\r
+\r
+ // binary operators\r
+ p1->DefineOprt( _T("add"), add, 0);\r
+ p1->DefineOprt( _T("++"), add, 0);\r
+ p1->DefineOprt( _T("&"), land, prLAND);\r
+\r
+ // sample functions\r
+ p1->DefineFun( _T("min"), Min);\r
+ p1->DefineFun( _T("max"), Max);\r
+ p1->DefineFun( _T("sum"), Sum);\r
+ p1->DefineFun( _T("valueof"), ValueOf);\r
+ p1->DefineFun( _T("atof"), StrToFloat);\r
+ p1->DefineFun( _T("strfun1"), StrFun1);\r
+ p1->DefineFun( _T("strfun2"), StrFun2);\r
+ p1->DefineFun( _T("strfun3"), StrFun3);\r
+ p1->DefineFun( _T("lastArg"), LastArg);\r
+ p1->DefineFun( _T("firstArg"), FirstArg);\r
+ p1->DefineFun( _T("order"), FirstArg);\r
+\r
+ // infix / postfix operator\r
+ // Note: Identifiers used here do not have any meaning \r
+ // they are mere placeholders to test certain features.\r
+ p1->DefineInfixOprt( _T("$"), sign, prPOW+1); // sign with high priority\r
+ p1->DefineInfixOprt( _T("~"), plus2); // high priority\r
+ p1->DefineInfixOprt( _T("~~"), plus2);\r
+ p1->DefinePostfixOprt( _T("{m}"), Milli);\r
+ p1->DefinePostfixOprt( _T("{M}"), Mega);\r
+ p1->DefinePostfixOprt( _T("m"), Milli);\r
+ p1->DefinePostfixOprt( _T("meg"), Mega);\r
+ p1->DefinePostfixOprt( _T("#"), times3);\r
+ p1->DefinePostfixOprt( _T("'"), sqr); \r
+ p1->SetExpr(a_str);\r
+\r
+ // Test bytecode integrity\r
+ // String parsing and bytecode parsing must yield the same result\r
+ fVal[0] = p1->Eval(); // result from stringparsing\r
+ fVal[1] = p1->Eval(); // result from bytecode\r
+ if (fVal[0]!=fVal[1])\r
+ throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") );\r
+\r
+ // Test copy and assignement operators\r
+ try\r
+ {\r
+ // Test copy constructor\r
+ std::vector<mu::Parser> vParser;\r
+ vParser.push_back(*(p1.get()));\r
+ mu::Parser p2 = vParser[0]; // take parser from vector\r
+ \r
+ // destroy the originals from p2\r
+ vParser.clear(); // delete the vector\r
+ p1.reset(0);\r
+\r
+ fVal[2] = p2.Eval();\r
+\r
+ // Test assignement operator\r
+ // additionally disable Optimizer this time\r
+ mu::Parser p3;\r
+ p3 = p2;\r
+ p3.EnableOptimizer(false);\r
+ fVal[3] = p3.Eval();\r
+\r
+ // Test Eval function for multiple return values\r
+ // use p2 since it has the optimizer enabled!\r
+ int nNum;\r
+ value_type *v = p2.Eval(nNum);\r
+ fVal[4] = v[nNum-1];\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << _T("\n ") << e.what() << _T("\n");\r
+ }\r
+\r
+ // limited floating point accuracy requires the following test\r
+ bool bCloseEnough(true);\r
+ for (unsigned i=0; i<sizeof(fVal)/sizeof(value_type); ++i)\r
+ {\r
+ bCloseEnough &= (fabs(a_fRes-fVal[i]) <= fabs(fVal[i]*0.00001));\r
+\r
+ // The tests equations never result in infinity, if they do thats a bug.\r
+ // reference:\r
+ // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825\r
+ if (numeric_limits<value_type>::has_infinity)\r
+ bCloseEnough &= (fabs(fVal[i]) != numeric_limits<value_type>::infinity());\r
+ }\r
+\r
+ iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;\r
+ \r
+ \r
+ if (iRet==1)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() \r
+ << _T(" (incorrect result; expected: ") << a_fRes\r
+ << _T(" ;calculated: ") << fVal[0] << _T(",") \r
+ << fVal[1] << _T(",")\r
+ << fVal[2] << _T(",")\r
+ << fVal[3] << _T(",")\r
+ << fVal[4] << _T(").");\r
+ }\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ if (a_fPass)\r
+ {\r
+ if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)");\r
+ else\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");\r
+ return 1;\r
+ }\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");\r
+ return 1; // always return a failure since this exception is not expected\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
+ return 1; // exceptions other than ParserException are not allowed\r
+ }\r
+\r
+ return iRet;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass)\r
+ {\r
+ ParserTester::c_iCount++;\r
+\r
+ value_type vVarVal[] = {1, 2, 3}; // variable values\r
+ value_type fVal[2] = {-99, -999}; // results: initially should be different\r
+ int iRet(0);\r
+\r
+ try\r
+ {\r
+ ParserInt p;\r
+ p.DefineConst( _T("const1"), 1);\r
+ p.DefineConst( _T("const2"), 2);\r
+ p.DefineVar( _T("a"), &vVarVal[0]);\r
+ p.DefineVar( _T("b"), &vVarVal[1]);\r
+ p.DefineVar( _T("c"), &vVarVal[2]);\r
+\r
+ p.SetExpr(a_str);\r
+ fVal[0] = p.Eval(); // result from stringparsing\r
+ fVal[1] = p.Eval(); // result from bytecode\r
+\r
+ if (fVal[0]!=fVal[1])\r
+ throw Parser::exception_type( _T("Bytecode corrupt.") );\r
+\r
+ iRet = ( (a_fRes==fVal[0] && a_fPass) || \r
+ (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;\r
+ if (iRet==1)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() \r
+ << _T(" (incorrect result; expected: ") << a_fRes \r
+ << _T(" ;calculated: ") << fVal[0]<< _T(").");\r
+ }\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ if (a_fPass)\r
+ {\r
+ mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();\r
+ iRet = 1;\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
+ iRet = 1; // exceptions other than ParserException are not allowed\r
+ }\r
+\r
+ return iRet;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Internal error in test class Test is going to be aborted. */\r
+ void ParserTester::Abort() const\r
+ {\r
+ mu::console() << _T("Test failed (internal error in test class)") << endl;\r
+ while (!getchar());\r
+ exit(-1);\r
+ }\r
+ } // namespace test\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#include <cassert>\r
+#include <cstdio>\r
+#include <cstring>\r
+#include <map>\r
+#include <stack>\r
+#include <string>\r
+\r
+#include "muParserTokenReader.h"\r
+#include "muParserBase.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser token reader implementation.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+\r
+ // Forward declaration\r
+ class ParserBase;\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor.\r
+\r
+ \sa Assign\r
+ \throw nothrow\r
+ */\r
+ ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) \r
+ { \r
+ Assign(a_Reader);\r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignement operator.\r
+\r
+ Self assignement will be suppressed otherwise #Assign is called.\r
+\r
+ \param a_Reader Object to copy to this token reader.\r
+ \throw nothrow\r
+ */\r
+ ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) \r
+ {\r
+ if (&a_Reader!=this)\r
+ Assign(a_Reader);\r
+\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assign state of a token reader to this token reader. \r
+ \r
+ \param a_Reader Object from which the state should be copied.\r
+ \throw nothrow\r
+ */\r
+ void ParserTokenReader::Assign(const ParserTokenReader &a_Reader)\r
+ {\r
+ m_pParser = a_Reader.m_pParser;\r
+ m_strFormula = a_Reader.m_strFormula;\r
+ m_iPos = a_Reader.m_iPos;\r
+ m_iSynFlags = a_Reader.m_iSynFlags;\r
+ \r
+ m_UsedVar = a_Reader.m_UsedVar;\r
+ m_pFunDef = a_Reader.m_pFunDef;\r
+ m_pConstDef = a_Reader.m_pConstDef;\r
+ m_pVarDef = a_Reader.m_pVarDef;\r
+ m_pStrVarDef = a_Reader.m_pStrVarDef;\r
+ m_pPostOprtDef = a_Reader.m_pPostOprtDef;\r
+ m_pInfixOprtDef = a_Reader.m_pInfixOprtDef;\r
+ m_pOprtDef = a_Reader.m_pOprtDef;\r
+ m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;\r
+ m_vIdentFun = a_Reader.m_vIdentFun;\r
+ m_pFactory = a_Reader.m_pFactory;\r
+ m_pFactoryData = a_Reader.m_pFactoryData;\r
+ m_iBrackets = a_Reader.m_iBrackets;\r
+ m_cArgSep = a_Reader.m_cArgSep;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor. \r
+ \r
+ Create a Token reader and bind it to a parser object. \r
+\r
+ \pre [assert] a_pParser may not be NULL\r
+ \post #m_pParser==a_pParser\r
+ \param a_pParent Parent parser object of the token reader.\r
+ */\r
+ ParserTokenReader::ParserTokenReader(ParserBase *a_pParent)\r
+ :m_pParser(a_pParent)\r
+ ,m_strFormula()\r
+ ,m_iPos(0)\r
+ ,m_iSynFlags(0)\r
+ ,m_bIgnoreUndefVar(false)\r
+ ,m_pFunDef(NULL)\r
+ ,m_pPostOprtDef(NULL)\r
+ ,m_pInfixOprtDef(NULL)\r
+ ,m_pOprtDef(NULL)\r
+ ,m_pConstDef(NULL)\r
+ ,m_pStrVarDef(NULL)\r
+ ,m_pVarDef(NULL)\r
+ ,m_pFactory(NULL)\r
+ ,m_pFactoryData(NULL)\r
+ ,m_vIdentFun()\r
+ ,m_UsedVar()\r
+ ,m_fZero(0)\r
+ ,m_iBrackets(0)\r
+ ,m_lastTok()\r
+ ,m_cArgSep(',')\r
+ {\r
+ assert(m_pParser);\r
+ SetParent(m_pParser);\r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ /** \brief Create instance of a ParserTokenReader identical with this \r
+ and return its pointer. \r
+\r
+ This is a factory method the calling function must take care of the object destruction.\r
+\r
+ \return A new ParserTokenReader object.\r
+ \throw nothrow\r
+ */\r
+ ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const\r
+ {\r
+ std::auto_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));\r
+ ptr->SetParent(a_pParent);\r
+ return ptr.release();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok)\r
+ {\r
+ m_lastTok = tok;\r
+ return m_lastTok;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::AddValIdent(identfun_type a_pCallback)\r
+ {\r
+ // Use push_front is used to give user defined callbacks a higher priority than\r
+ // the built in ones. Otherwise reading hex numbers would not work\r
+ // since the "0" in "0xff" would always be read first making parsing of \r
+ // the rest impossible.\r
+ // reference:\r
+ // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956\r
+ m_vIdentFun.push_front(a_pCallback);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)\r
+ {\r
+ m_pFactory = a_pFactory;\r
+ m_pFactoryData = pUserData;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the current position of the token reader in the formula string. \r
+\r
+ \return #m_iPos\r
+ \throw nothrow\r
+ */\r
+ int ParserTokenReader::GetPos() const\r
+ {\r
+ return m_iPos;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a reference to the formula. \r
+\r
+ \return #m_strFormula\r
+ \throw nothrow\r
+ */\r
+ const string_type& ParserTokenReader::GetExpr() const\r
+ {\r
+ return m_strFormula;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing the used variables only. */\r
+ varmap_type& ParserTokenReader::GetUsedVar() \r
+ {\r
+ return m_UsedVar;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize the token Reader. \r
+ \r
+ Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.\r
+ \pre [assert] triggered if a_szFormula==0\r
+ */\r
+ void ParserTokenReader::SetFormula(const string_type &a_strFormula)\r
+ {\r
+ m_strFormula = a_strFormula;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set Flag that contronls behaviour in case of undefined variables beeing found. \r
+ \r
+ If true, the parser does not throw an exception if an undefined variable is found. \r
+ otherwise it does. This variable is used internally only!\r
+ It supresses a "undefined variable" exception in GetUsedVar(). \r
+ Those function should return a complete list of variables including \r
+ those the are not defined by the time of it's call.\r
+ */\r
+ void ParserTokenReader::IgnoreUndefVar(bool bIgnore)\r
+ {\r
+ m_bIgnoreUndefVar = bIgnore;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Reset the token reader to the start of the formula. \r
+\r
+ The syntax flags will be reset to a value appropriate for the \r
+ start of a formula.\r
+ \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR\r
+ \throw nothrow\r
+ \sa ESynCodes\r
+ */\r
+ void ParserTokenReader::ReInit()\r
+ {\r
+ m_iPos = 0;\r
+ m_iSynFlags = sfSTART_OF_LINE;\r
+ m_iBrackets = 0;\r
+ m_UsedVar.clear();\r
+ m_lastTok = token_type();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Read the next token from the string. */ \r
+ ParserTokenReader::token_type ParserTokenReader::ReadNextToken()\r
+ {\r
+ assert(m_pParser);\r
+\r
+ std::stack<int> FunArgs;\r
+ const char_type *szFormula = m_strFormula.c_str();\r
+ token_type tok;\r
+\r
+ // Ignore all non printable characters when reading the expression\r
+ while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) \r
+ ++m_iPos;\r
+\r
+ if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula\r
+ if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator\r
+ if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token\r
+ if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens\r
+ if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators\r
+ if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens\r
+ if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens\r
+ if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables\r
+ if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens\r
+ if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators\r
+ if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators\r
+\r
+ // Check String for undefined variable token. Done only if a \r
+ // flag is set indicating to ignore undefined variables.\r
+ // This is a way to conditionally avoid an error if \r
+ // undefined variables occur. \r
+ // (The GetUsedVar function must suppress the error for\r
+ // undefined variables in order to collect all variable \r
+ // names including the undefined ones.)\r
+ if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) \r
+ return SaveBeforeReturn(tok);\r
+\r
+ // Check for unknown token\r
+ // \r
+ // !!! From this point on there is no exit without an exception possible...\r
+ // \r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd!=m_iPos)\r
+ Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);\r
+\r
+ Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));\r
+ return token_type(); // never reached\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::SetParent(ParserBase *a_pParent)\r
+ {\r
+ m_pParser = a_pParent; \r
+ m_pFunDef = &a_pParent->m_FunDef;\r
+ m_pOprtDef = &a_pParent->m_OprtDef;\r
+ m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;\r
+ m_pPostOprtDef = &a_pParent->m_PostOprtDef;\r
+ m_pVarDef = &a_pParent->m_VarDef;\r
+ m_pStrVarDef = &a_pParent->m_StrVarDef;\r
+ m_pConstDef = &a_pParent->m_ConstDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Extract all characters that belong to a certain charset.\r
+\r
+ \param a_szCharSet [in] Const char array of the characters allowed in the token. \r
+ \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.\r
+ \param a_iPos [in] Position in the string from where to start reading.\r
+ \return The Position of the first character not listed in a_szCharSet.\r
+ \throw nothrow\r
+ */\r
+ int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, \r
+ string_type &a_sTok, \r
+ int a_iPos) const\r
+ {\r
+ int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);\r
+\r
+ if (iEnd==(int)string_type::npos)\r
+ iEnd = (int)m_strFormula.length();\r
+ \r
+ // Assign token string if there was something found\r
+ if (a_iPos!=iEnd)\r
+ a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);\r
+\r
+ return iEnd;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check Expression for the presence of a binary operator token.\r
+ \r
+ Userdefined binary operator "++" gives inconsistent parsing result for\r
+ the equations "a++b" and "a ++ b" if alphabetic characters are allowed\r
+ in operator tokens. To avoid this this function checks specifically\r
+ for operator tokens.\r
+ */\r
+ int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, \r
+ int a_iPos) const\r
+ {\r
+ int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidInfixOprtChars(), a_iPos);\r
+ if (iEnd==(int)string_type::npos)\r
+ iEnd = (int)m_strFormula.length();\r
+\r
+ // Assign token string if there was something found\r
+ if (a_iPos!=iEnd)\r
+ {\r
+ a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);\r
+ return iEnd;\r
+ }\r
+ else\r
+ {\r
+ // There is still the chance of having to deal with an operator consisting exclusively\r
+ // of alphabetic characters.\r
+ return ExtractToken(MUP_CHARS, a_sTok, a_iPos);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a built in operator or other token can be found\r
+ \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.\r
+ \return true if an operator token has been found.\r
+ */\r
+ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)\r
+ {\r
+ const char_type **const pOprtDef = m_pParser->GetOprtDef(),\r
+ *const szFormula = m_strFormula.c_str();\r
+\r
+ // Compare token with function and operator strings\r
+ // check string for operator/function\r
+ for (int i=0; pOprtDef[i]; i++)\r
+ {\r
+ std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );\r
+ if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )\r
+ {\r
+ switch(i)\r
+ {\r
+ //case cmAND:\r
+ //case cmOR:\r
+ //case cmXOR:\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ: \r
+ case cmEQ:\r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV:\r
+ case cmPOW:\r
+ case cmASSIGN:\r
+ //if (len!=sTok.length())\r
+ // continue;\r
+\r
+ // The assignement operator need special treatment\r
+ if (i==cmASSIGN && m_iSynFlags & noASSIGN)\r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);\r
+\r
+ if (!m_pParser->HasBuiltInOprt()) continue;\r
+ if (m_iSynFlags & noOPT) \r
+ {\r
+ // Maybe its an infix operator not an operator\r
+ // Both operator types can share characters in \r
+ // their identifiers\r
+ if ( IsInfixOpTok(a_Tok) ) \r
+ return true;\r
+\r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);\r
+ }\r
+\r
+ m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;\r
+ m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;\r
+ break;\r
+\r
+ case cmBO:\r
+ if (m_iSynFlags & noBO)\r
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
+ \r
+ if (m_lastTok.GetCode()==cmFUNC)\r
+ m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;\r
+ else\r
+ m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE;\r
+\r
+ ++m_iBrackets;\r
+ break;\r
+\r
+ case cmBC:\r
+ if (m_iSynFlags & noBC)\r
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
+\r
+ m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;\r
+\r
+ if (--m_iBrackets<0)\r
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
+ break;\r
+\r
+ case cmELSE:\r
+ if (m_iSynFlags & noELSE)\r
+ Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);\r
+\r
+ m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;\r
+ break;\r
+\r
+ case cmIF:\r
+ if (m_iSynFlags & noIF)\r
+ Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);\r
+\r
+ m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;\r
+ break;\r
+\r
+ default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...\r
+ Error(ecINTERNAL_ERROR);\r
+ } // switch operator id\r
+\r
+ m_iPos += (int)len;\r
+ a_Tok.Set( (ECmdCode)i, pOprtDef[i] );\r
+ return true;\r
+ } // if operator string found\r
+ } // end of for all operator strings\r
+ \r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ bool ParserTokenReader::IsArgSep(token_type &a_Tok)\r
+ {\r
+ const char_type* szFormula = m_strFormula.c_str();\r
+\r
+ if (szFormula[m_iPos]==m_cArgSep)\r
+ {\r
+ // copy the separator into null terminated string\r
+ char_type szSep[2];\r
+ szSep[0] = m_cArgSep;\r
+ szSep[1] = 0;\r
+\r
+ if (m_iSynFlags & noARG_SEP)\r
+ Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);\r
+\r
+ m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;\r
+ m_iPos++;\r
+ a_Tok.Set(cmARG_SEP, szSep);\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check for End of Formula.\r
+\r
+ \return true if an end of formula is found false otherwise.\r
+ \param a_Tok [out] If an eof is found the corresponding token will be stored there.\r
+ \throw nothrow\r
+ \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok\r
+ */\r
+ bool ParserTokenReader::IsEOF(token_type &a_Tok)\r
+ {\r
+ const char_type* szFormula = m_strFormula.c_str();\r
+\r
+ // check for EOF\r
+ if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)\r
+ {\r
+ if ( m_iSynFlags & noEND )\r
+ Error(ecUNEXPECTED_EOF, m_iPos);\r
+\r
+ if (m_iBrackets>0)\r
+ Error(ecMISSING_PARENS, m_iPos, _T(")"));\r
+\r
+ m_iSynFlags = 0;\r
+ a_Tok.Set(cmEND);\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a string position contains a unary infix operator. \r
+ \return true if a function token has been found false otherwise.\r
+ */\r
+ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok)\r
+ {\r
+ string_type sTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ // iteraterate over all postfix operator strings\r
+ funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();\r
+ for ( ; it!=m_pInfixOprtDef->rend(); ++it)\r
+ {\r
+ if (sTok.find(it->first)!=0)\r
+ continue;\r
+\r
+ a_Tok.Set(it->second, it->first);\r
+ m_iPos += (int)it->first.length();\r
+\r
+ if (m_iSynFlags & noINFIXOP) \r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());\r
+\r
+ m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+\r
+/*\r
+ a_Tok.Set(item->second, sTok);\r
+ m_iPos = (int)iEnd;\r
+\r
+ if (m_iSynFlags & noINFIXOP) \r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());\r
+\r
+ m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; \r
+ return true;\r
+*/\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check whether the token at a given position is a function token.\r
+ \param a_Tok [out] If a value token is found it will be placed here.\r
+ \throw ParserException if Syntaxflags do not allow a function at a_iPos\r
+ \return true if a function token has been found false otherwise.\r
+ \pre [assert] m_pParser!=0\r
+ */\r
+ bool ParserTokenReader::IsFunTok(token_type &a_Tok)\r
+ {\r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ funmap_type::const_iterator item = m_pFunDef->find(strTok);\r
+ if (item==m_pFunDef->end())\r
+ return false;\r
+\r
+ // Check if the next sign is an opening bracket\r
+ const char_type *szFormula = m_strFormula.c_str();\r
+ if (szFormula[iEnd]!='(')\r
+ return false;\r
+\r
+ a_Tok.Set(item->second, strTok);\r
+\r
+ m_iPos = (int)iEnd;\r
+ if (m_iSynFlags & noFUN)\r
+ Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());\r
+\r
+ m_iSynFlags = noANY ^ noBO;\r
+ return true;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a string position contains a binary operator.\r
+ \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.\r
+ \return true if an operator token has been found.\r
+ */\r
+ bool ParserTokenReader::IsOprt(token_type &a_Tok)\r
+ {\r
+ const char_type *const szExpr = m_strFormula.c_str();\r
+ string_type strTok;\r
+\r
+ int iEnd = ExtractOperatorToken(strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ // Check if the operator is a built in operator, if so ignore it here\r
+ const char_type **const pOprtDef = m_pParser->GetOprtDef();\r
+ for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)\r
+ {\r
+ if (string_type(pOprtDef[i])==strTok)\r
+ return false;\r
+ }\r
+\r
+ // Note:\r
+ // All tokens in oprt_bin_maptype are have been sorted by their length\r
+ // Long operators must come first! Otherwise short names (like: "add") that\r
+ // are part of long token names (like: "add123") will be found instead \r
+ // of the long ones.\r
+ // Length sorting is done with ascending length so we use a reverse iterator here.\r
+ funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();\r
+ for ( ; it!=m_pOprtDef->rend(); ++it)\r
+ {\r
+ const string_type &sID = it->first;\r
+ if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )\r
+ {\r
+ a_Tok.Set(it->second, strTok);\r
+\r
+ // operator was found\r
+ if (m_iSynFlags & noOPT) \r
+ {\r
+ // An operator was found but is not expected to occur at\r
+ // this position of the formula, maybe it is an infix \r
+ // operator, not a binary operator. Both operator types\r
+ // can share characters in their identifiers.\r
+ if ( IsInfixOpTok(a_Tok) ) \r
+ return true;\r
+ else\r
+ {\r
+ // nope, no infix operator\r
+ return false;\r
+ //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); \r
+ }\r
+\r
+ }\r
+\r
+ m_iPos += (int)sID.length();\r
+ m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noBC | noASSIGN;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a string position contains a unary post value operator. */\r
+ bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)\r
+ {\r
+ // <ibg 20110629> Do not check for postfix operators if they are not allowed at\r
+ // the current expression index.\r
+ //\r
+ // This will fix the bug reported here: \r
+ //\r
+ // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979\r
+ //\r
+ if (m_iSynFlags & noPOSTOP)\r
+ return false;\r
+ // </ibg>\r
+\r
+ // Tricky problem with equations like "3m+5":\r
+ // m is a postfix operator, + is a valid sign for postfix operators and \r
+ // for binary operators parser detects "m+" as operator string and \r
+ // finds no matching postfix operator.\r
+ // \r
+ // This is a special case so this routine slightly differs from the other\r
+ // token readers.\r
+ \r
+ // Test if there could be a postfix operator\r
+ string_type sTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ // iteraterate over all postfix operator strings\r
+ funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();\r
+ for ( ; it!=m_pPostOprtDef->rend(); ++it)\r
+ {\r
+ if (sTok.find(it->first)!=0)\r
+ continue;\r
+\r
+ a_Tok.Set(it->second, sTok);\r
+ m_iPos += (int)it->first.length();\r
+\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check whether the token at a given position is a value token.\r
+\r
+ Value tokens are either values or constants.\r
+\r
+ \param a_Tok [out] If a value token is found it will be placed here.\r
+ \return true if a value token has been found.\r
+ */\r
+ bool ParserTokenReader::IsValTok(token_type &a_Tok)\r
+ {\r
+ assert(m_pConstDef);\r
+ assert(m_pParser);\r
+\r
+ string_type strTok;\r
+ value_type fVal(0);\r
+ int iEnd(0);\r
+ \r
+ // 2.) Check for user defined constant\r
+ // Read everything that could be a constant name\r
+ iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd!=m_iPos)\r
+ {\r
+ valmap_type::const_iterator item = m_pConstDef->find(strTok);\r
+ if (item!=m_pConstDef->end())\r
+ {\r
+ m_iPos = iEnd;\r
+ a_Tok.SetVal(item->second, strTok);\r
+\r
+ if (m_iSynFlags & noVAL)\r
+ Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);\r
+\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; \r
+ return true;\r
+ }\r
+ }\r
+\r
+ // 3.call the value recognition functions provided by the user\r
+ // Call user defined value recognition functions\r
+ std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();\r
+ for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)\r
+ {\r
+ int iStart = m_iPos;\r
+ if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )\r
+ {\r
+ strTok.assign(m_strFormula.c_str(), iStart, m_iPos);\r
+ if (m_iSynFlags & noVAL)\r
+ Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);\r
+\r
+ a_Tok.SetVal(fVal, strTok);\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check wheter a token at a given position is a variable token. \r
+ \param a_Tok [out] If a variable token has been found it will be placed here.\r
+ \return true if a variable token has been found.\r
+ */\r
+ bool ParserTokenReader::IsVarTok(token_type &a_Tok)\r
+ {\r
+ if (!m_pVarDef->size())\r
+ return false;\r
+\r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ varmap_type::const_iterator item = m_pVarDef->find(strTok);\r
+ if (item==m_pVarDef->end())\r
+ return false;\r
+\r
+ if (m_iSynFlags & noVAR)\r
+ Error(ecUNEXPECTED_VAR, m_iPos, strTok);\r
+\r
+ m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);\r
+\r
+ m_iPos = iEnd;\r
+ a_Tok.SetVar(item->second, strTok);\r
+ m_UsedVar[item->first] = item->second; // Add variable to used-var-list\r
+\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;\r
+\r
+// Zur Info hier die SynFlags von IsVal():\r
+// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; \r
+ return true;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)\r
+ {\r
+ if (!m_pStrVarDef || !m_pStrVarDef->size())\r
+ return false;\r
+\r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ strmap_type::const_iterator item = m_pStrVarDef->find(strTok);\r
+ if (item==m_pStrVarDef->end())\r
+ return false;\r
+\r
+ if (m_iSynFlags & noSTR)\r
+ Error(ecUNEXPECTED_VAR, m_iPos, strTok);\r
+\r
+ m_iPos = iEnd;\r
+ if (!m_pParser->m_vStringVarBuf.size())\r
+ Error(ecINTERNAL_ERROR);\r
+\r
+ a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );\r
+\r
+ m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP);\r
+ return true;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check wheter a token at a given position is an undefined variable. \r
+\r
+ \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.\r
+ \return true if a variable token has been found.\r
+ \throw nothrow\r
+ */\r
+ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok)\r
+ {\r
+ string_type strTok;\r
+ int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );\r
+ if ( iEnd==m_iPos )\r
+ return false;\r
+\r
+ if (m_iSynFlags & noVAR)\r
+ {\r
+ // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the \r
+ // token identifier. \r
+ // related bug report:\r
+ // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979\r
+ Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);\r
+ }\r
+\r
+ // If a factory is available implicitely create new variables\r
+ if (m_pFactory)\r
+ {\r
+ value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);\r
+ a_Tok.SetVar(fVar, strTok );\r
+\r
+ // Do not use m_pParser->DefineVar( strTok, fVar );\r
+ // in order to define the new variable, it will clear the\r
+ // m_UsedVar array which will kill previousely defined variables\r
+ // from the list\r
+ // This is safe because the new variable can never override an existing one\r
+ // because they are checked first!\r
+ (*m_pVarDef)[strTok] = fVar;\r
+ m_UsedVar[strTok] = fVar; // Add variable to used-var-list\r
+ }\r
+ else\r
+ {\r
+ a_Tok.SetVar((value_type*)&m_fZero, strTok);\r
+ m_UsedVar[strTok] = 0; // Add variable to used-var-list\r
+ }\r
+\r
+ m_iPos = iEnd;\r
+\r
+ // Call the variable factory in order to let it define a new parser variable\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;\r
+ return true;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check wheter a token at a given position is a string.\r
+ \param a_Tok [out] If a variable token has been found it will be placed here.\r
+ \return true if a string token has been found.\r
+ \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok\r
+ \throw nothrow\r
+ */\r
+ bool ParserTokenReader::IsString(token_type &a_Tok)\r
+ {\r
+ if (m_strFormula[m_iPos]!='"') \r
+ return false;\r
+\r
+ string_type strBuf(&m_strFormula[m_iPos+1]);\r
+ std::size_t iEnd(0), iSkip(0);\r
+\r
+ // parser over escaped '\"' end replace them with '"'\r
+ for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd))\r
+ {\r
+ if (strBuf[iEnd-1]!='\\') break;\r
+ strBuf.replace(iEnd-1, 2, _T("\"") );\r
+ iSkip++;\r
+ }\r
+\r
+ if (iEnd==string_type::npos)\r
+ Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") );\r
+\r
+ string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);\r
+\r
+ if (m_iSynFlags & noSTR)\r
+ Error(ecUNEXPECTED_STR, m_iPos, strTok);\r
+\r
+ m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer\r
+ a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());\r
+\r
+ m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen\r
+ m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND );\r
+\r
+ return true;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Create an error containing the parse error position.\r
+\r
+ This function will create an Parser Exception object containing the error text and its position.\r
+\r
+ \param a_iErrc [in] The error code of type #EErrorCodes.\r
+ \param a_iPos [in] The position where the error was detected.\r
+ \param a_strTok [in] The token string representation associated with the error.\r
+ \throw ParserException always throws thats the only purpose of this function.\r
+ */\r
+ void ParserTokenReader::Error( EErrorCodes a_iErrc, \r
+ int a_iPos, \r
+ const string_type &a_sTok) const\r
+ {\r
+ m_pParser->Error(a_iErrc, a_iPos, a_sTok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::SetArgSep(char_type cArgSep)\r
+ {\r
+ m_cArgSep = cArgSep;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ char_type ParserTokenReader::GetArgSep() const\r
+ {\r
+ return m_cArgSep;\r
+ }\r
+} // namespace mu\r
+\r
-## ---------------------------------------------------------------------
+# ---------------------------------------------------------------------
## $Id$
##
## Copyright (C) 2013 by the deal.II authors
SET(BOOST_FOLDER "${CMAKE_SOURCE_DIR}/bundled/boost-1.49.0")
-#
-# FunctionParser project:
-#
-
-SET(FEATURE_FUNCTIONPARSER_HAVE_BUNDLED TRUE)
-
-OPTION(DEAL_II_FORCE_BUNDLED_FUNCTIONPARSER
- "Always use the bundled functionparser library instead of an external one."
- OFF)
-
-SET(FUNCTIONPARSER_FOLDER "${CMAKE_SOURCE_DIR}/bundled/functionparser/")
#
# Threading Building Blocks library
OFF)
SET(UMFPACK_FOLDER "${CMAKE_SOURCE_DIR}/bundled/umfpack")
+
+
+#
+# muparser
+#
+SET(FEATURE_MUPARSER_HAVE_BUNDLED TRUE)
+
+OPTION(DEAL_II_FORCE_BUNDLED_MUPARSER
+ "Always use the bundled functionparser library instead of an external one."
+ OFF)
+
+SET(MUPARSER_FOLDER "${CMAKE_SOURCE_DIR}/bundled/muparser_v2_2_3/")
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
ENDIF()
+#
+# Microsoft Visual C++ has a bug where the resulting object
+# from calling std::bind does not have a const operator(),
+# so we cannot pass such objects as const references as we
+# usually do with input arguments of other functions.
+#
+# - Wolfgang Bangerth, 2014
+#
+IF(DEAL_II_WITH_CXX11)
+ PUSH_CMAKE_REQUIRED("${DEAL_II_CXX11_FLAG}")
+ CHECK_CXX_COMPILER_BUG(
+ "
+ #include <functional>
+
+ void f(int, int) {}
+
+ template <typename F>
+ void g(const F &func)
+ {
+ func(1);
+ }
+
+ int main ()
+ {
+ g (std::bind(&f, std::placeholders::_1, 1));
+ }
+ "
+ DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+ )
+ RESET_CMAKE_REQUIRED()
+ELSE()
+ CHECK_CXX_COMPILER_BUG(
+ "
+ #include <functional>
+ #include \"${BOOST_FOLDER}/include/boost/bind.hpp\"
+
+ void f(int, int) {}
+
+ template <typename F>
+ void g(const F &func)
+ {
+ func(1);
+ }
+
+ int main ()
+ {
+ using boost::bind;
+ using boost::reference_wrapper;
+
+ // now also import the _1, _2 placeholders from the global namespace
+ // into the current one as suggested above
+ using ::_1;
+
+ g (boost::bind(&f, boost::_1, 1));
+ }
+ "
+ DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+ )
+ENDIF()
+
+
#
# in intel (at least 13.1 and 14), vectorization causes
# wrong code. See https://code.google.com/p/dealii/issues/detail?id=156
COND_SET_TO_YES(DEAL_II_WITH_FUNCTIONPARSER MAKEFILE_enableparser)
COND_SET_TO_YES(BUILD_SHARED_LIBS MAKEFILE_enableshared)
- COND_SET_TO_YES(DEAL_II_WITH_PETSC MAKEFILE_PETSC)
- COND_SET_TO_YES(DEAL_II_WITH_SLEPC MAKEFILE_SLEPC)
- COND_SET_TO_YES(DEAL_II_WITH_TRILINOS MAKEFILE_TRILINOS)
- COND_SET_TO_YES(DEAL_II_WITH_HDF5 MAKEFILE_HDF5)
+ COND_SET_TO_YES(DEAL_II_WITH_ARPACK MAKEFILE_ARPACK)
COND_SET_TO_YES(DEAL_II_WITH_BLAS MAKEFILE_BLAS)
- COND_SET_TO_YES(DEAL_II_WITH_MUMPS MAKEFILE_MUMPS)
+ COND_SET_TO_YES(DEAL_II_WITH_HDF5 MAKEFILE_HDF5)
COND_SET_TO_YES(DEAL_II_WITH_LAPACK MAKEFILE_LAPACK)
- COND_SET_TO_YES(DEAL_II_WITH_ARPACK MAKEFILE_ARPACK)
COND_SET_TO_YES(DEAL_II_WITH_METIS MAKEFILE_METIS)
- COND_SET_TO_YES(DEAL_II_WITH_UMFPACK MAKEFILE_UMFPACK)
- COND_SET_TO_YES(DEAL_II_WITH_P4EST MAKEFILE_P4EST)
COND_SET_TO_YES(DEAL_II_WITH_MPI MAKEFILE_MPI)
+ COND_SET_TO_YES(DEAL_II_WITH_MUMPS MAKEFILE_MUMPS)
+ COND_SET_TO_YES(DEAL_II_WITH_P4EST MAKEFILE_P4EST)
+ COND_SET_TO_YES(DEAL_II_WITH_PETSC MAKEFILE_PETSC)
+ COND_SET_TO_YES(DEAL_II_WITH_SLEPC MAKEFILE_SLEPC)
+ COND_SET_TO_YES(DEAL_II_WITH_TRILINOS MAKEFILE_TRILINOS)
+ COND_SET_TO_YES(DEAL_II_WITH_UMFPACK MAKEFILE_UMFPACK)
#
# For binary dir:
#
# TODO: Also necessary for external lib, use preference toggle
#
- FIND_SYSTEM_LIBRARY(dl_LIBRARY NAMES dl)
- MARK_AS_ADVANCED(dl_LIBRARY)
- IF(NOT dl_LIBRARY MATCHES "-NOTFOUND")
- LIST(APPEND THREADS_LIBRARIES ${dl_LIBRARY})
- ENDIF()
+ LIST(APPEND THREADS_LIBRARIES ${CMAKE_DL_LIBS})
LIST(APPEND THREADS_BUNDLED_INCLUDE_DIRS ${TBB_FOLDER}/include)
ENDMACRO()
+++ /dev/null
-## ---------------------------------------------------------------------
-## $Id$
-##
-## Copyright (C) 2012 - 2014 by the deal.II authors
-##
-## This file is part of the deal.II library.
-##
-## The deal.II library is free software; you can use it, redistribute
-## it, and/or modify it under the terms of the GNU Lesser General
-## Public License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-## The full text of the license can be found in the file LICENSE at
-## the top level of the deal.II distribution.
-##
-## ---------------------------------------------------------------------
-
-#
-# Configuration for functionparser
-#
-
-MACRO(FEATURE_FUNCTIONPARSER_FIND_EXTERNAL var)
- MESSAGE(STATUS
- "No module available for finding functionparser externally."
- )
-ENDMACRO()
-
-
-MACRO(FEATURE_FUNCTIONPARSER_CONFIGURE_BUNDLED)
- SET(FUNCTIONPARSER_BUNDLED_INCLUDE_DIRS ${FUNCTIONPARSER_FOLDER})
-ENDMACRO()
-
-
-MACRO(FEATURE_FUNCTIONPARSER_ERROR_MESSAGE)
- MESSAGE(FATAL_ERROR "\n"
- "No module available for finding functionparser externally.\n"
- "Disable DEAL_II_WITH_FUNCTIONPARSER, or enable DEAL_II_ALLOW_BUNDLED.\n\n"
- )
-ENDMACRO()
-
-
-CONFIGURE_FEATURE(FUNCTIONPARSER)
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2013 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Configuration for the MUPARSER library:
+#
+
+MACRO(FEATURE_MUPARSER_CONFIGURE_BUNDLED)
+ SET(MUPARSER_BUNDLED_INCLUDE_DIRS ${MUPARSER_FOLDER}/include)
+ENDMACRO()
+
+CONFIGURE_FEATURE(MUPARSER)
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2013 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Try to find the MUPARSER library
+#
+# This module exports
+#
+# MUPARSER_LIBRARIES
+# MUPARSER_INCLUDE_DIRS
+# MUPARSER_VERSION
+# MUPARSER_VERSION_MAJOR
+# MUPARSER_VERSION_MINOR
+# MUPARSER_VERSION_SUBMINOR
+#
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+SET_IF_EMPTY(MUPARSER_DIR "$ENV{MUPARSER_DIR}")
+
+FIND_LIBRARY(MUPARSER_LIBRARY
+ NAMES muparser muparserd
+ HINTS ${MUPARSER_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
+ )
+
+FIND_PATH(MUPARSER_INCLUDE_DIR muParserDef.h
+ HINTS ${MUPARSER_DIR}
+ PATH_SUFFIXES include
+ )
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(MUPARSER DEFAULT_MSG
+ MUPARSER_LIBRARY
+ MUPARSER_INCLUDE_DIR
+ )
+
+IF(MUPARSER_FOUND)
+ SET(MUPARSER_LIBRARIES ${MUPARSER_LIBRARY})
+ SET(MUPARSER_INCLUDE_DIRS ${MUPARSER_INCLUDE_DIR})
+
+ FILE(STRINGS "${MUPARSER_INCLUDE_DIR}/muParserDef.h" MUPARSER_VERSION_STRING
+ REGEX "#define MUP_VERSION _T"
+ )
+ STRING(REGEX REPLACE ".*\"([0-9]+)\\.[0-9]+\\..*" "\\1"
+ MUPARSER_VERSION_MAJOR "${MUPARSER_VERSION_STRING}"
+ )
+ STRING(REGEX REPLACE ".*\\.([0-9]+)\\..*" "\\1"
+ MUPARSER_VERSION_MINOR "${MUPARSER_VERSION_STRING}"
+ )
+ STRING(REGEX REPLACE ".*\\.[0-9]+\\.([0-9]+)\".*" "\\1"
+ MUPARSER_VERSION_SUBMINOR "${MUPARSER_VERSION_STRING}"
+ )
+ SET(MUPARSER_VERSION
+ "${MUPARSER_VERSION_MAJOR}.${MUPARSER_VERSION_MINOR}.${MUPARSER_VERSION_SUBMINOR}"
+ )
+
+ MARK_AS_ADVANCED(MUPARSER_DIR)
+ELSE()
+ SET(MUPARSER_DIR "" CACHE PATH
+ "An optional hint to a MUPARSER installation"
+ )
+ENDIF()
_var MATCHES "^(COMPAT_FILES|DOCUMENTATION|EXAMPLES|MESH_CONVERTER|PARAMETER_GUI)" OR
_var MATCHES "^(ARPACK|BOOST|FUNCTIONPARSER|HDF5|METIS|MPI|MUMPS)_" OR
_var MATCHES "^(NETCDF|P4EST|PETSC|SLEPC|THREADS|TBB|TRILINOS)_" OR
- _var MATCHES "^(UMFPACK|ZLIB|LAPACK)_" OR
+ _var MATCHES "^(UMFPACK|ZLIB|LAPACK|MUPARSER)_" OR
_var MATCHES "^(CMAKE|DEAL_II)_(C|CXX|Fortran|BUILD)_(COMPILER|FLAGS)" OR
_var MATCHES "^CMAKE_BUILD_TYPE$" OR
_var MATCHES "MAKEOPTS" OR
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# friend struct Implementation;
# };)
# -w177 declared but not referenced
+# -w191 type qualifier is meaningless on cast type
+# Warnings from this warn about code like this:
+# static_cast<T const * const>(p)
+# There are many places in boost that do this kind of stuff
+# -w193 zero used for undefined preprocessing identifier "..."
+# This happens when using undefined preprocessor names in
+# conditions such as
+# #if (abc && def)
+# instead of
+# #if (defined(abc) && defined(def))
+# The standard says that in such cases, the undefined symbol
+# is assumed to be zero. The warning is in principle
+# useful, but the pattern appears exceedingly often in the TBB
# -w279 controlling expression is constant
# -w327 NULL reference is not allowed
# (the compiler is correct here in that statements like
# (happens in boost)
# -w1478 deprecation warning
# -w1572 floating-point equality and inequality comparisons are unreliable
+# -w2259 non-pointer conversion from "double" to "float" may
+# lose significant bits
+# -w21 type qualifiers are meaningless in this declaration
# -w2536 type qualifiers are meaningless here
#
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd68")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd135")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd175")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd177")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd191")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd193")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd279")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd327")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd383")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd1418")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd1478")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd1572")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd2259")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd21")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd2536")
+# Also disable the following warnings that we frequently
+# trigger writing dimension independent code:
+# -w111 statement is unreachable
+# Happens in code that is guarded by a check on 'dim'
+# -w128 loop is not reachable from preceding
+# Same as above
+# -w185 dynamic initialization in unreachable code
+# When initializing a local variable in code
+# that is executed only for one specific dimension
+# -w280 selector expression is constant
+# When writing 'switch(dim)'
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd111")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd128")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd185")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd280")
+
+
+
IF(DEAL_II_STATIC_EXECUTABLE)
#
# To produce a static executable, we have to statically link intel's
--- /dev/null
+// vector update of the form y += alpha*x with a scalar, x,y vectors
+void daxpy_ (const int* n, const double* alpha, const double* x,
+ const int* incx, double* y, const int* incy);
+
+// General Matrix
+// Matrix vector product
+void dgemv_ (const char* trans, const int* m, const int* n,
+ const double* alpha, const double* A, const int* lda,
+ const double* x, const int* incx,
+ const double* b, double* y, const int* incy);
+
+// Matrix matrix product
+void dgemm_ (const char* transa, const char* transb,
+ const int* m, const int* n, const int* k,
+ const double* alpha, const double* A, const int* lda,
+ const double* B, const int* ldb,
+ const double* beta, double* C, const int* ldc);
+
+// Compute LU factorization
+void dgetrf_ (const int* m, const int* n, double* A,
+ const int* lda, int* ipiv, int* info);
+// Apply forward/backward substitution to LU factorization
+void dgetrs_ (const char* trans, const int* n, const int* nrhs,
+ const double* A, const int* lda, const int* ipiv,
+ double* b, const int* ldb, int* info);
+// Invert matrix from LU factorization
+void dgetri_ (const int* n, double* A, const int* lda,
+ int* ipiv, double* inv_work, const int* lwork, int* info);
+
+// Compute QR factorization (Householder)
+void dgeqrf_ (const int* m, const int* n, double* A,
+ const int* lda, double* tau, double* work,
+ const int* lwork, int* info);
+// Compute vector Q^T B, where Q is the result from dgeqrf_
+void dormqr_ (const char* side, const char* trans, const int* m,
+ const int* n, const int* k, const double* A, const int* lda,
+ const double* tau, double* B, const int* ldb,
+ double* work, const int* lwork, int* info);
+// Compute matrix Q from the result of dgeqrf_
+void dorgqr_ (const int* m, const int* n, const int* k, const double* A,
+ const int* lda, const double* tau, double* work, const int* lwork,
+ int* info);
+// Compute Rx = b
+void dtrtrs_ (const char* uplo, const char* trans,
+ const char* diag, const int* n, const int* n_rhs,
+ const double* A, const int* lda, double* B, const int* ldb,
+ int* info);
+
+// Compute eigenvalues and vectors
+void dgeev_ (const char* jobvl, const char* jobvr,
+ const int* n, double* A, const int* lda,
+ double* lambda_re, double* lambda_im,
+ double* vl, const int* ldvl,
+ double* vr, const int* ldva,
+ double* work, const int* lwork,
+ int* info);
+// Compute eigenvalues and vectors (expert)
+void dgeevx_ (const char* balanc, const char* jobvl, const char* jobvr,
+ const char* sense,
+ const int* n, double* A, const int* lda,
+ double* lambda_re, double* lambda_im,
+ double* vl, const int* ldvl,
+ double* vr, const int* ldvr,
+ int* ilo, int* ihi,
+ double* scale, double* abnrm,
+ double* rconde, double* rcondv,
+ double* work, const int* lwork,
+ int* iwork, int* info);
+// Eigenvalues for a symmetric matrix
+void dsyev_ (const char *jobz, const char *uplo, const int *n,
+ double *A, const int *lda, double *w,
+ double *work, const int *lwork, int *info);
+// Same functionality as dsyev_ but with more options: E.g.
+// Compute only eigenvalues in a specific interval,
+// Compute only eigenvalues with a specific index,
+// Set tolerance for eigenvalue computation
+void dsyevx_ (const char* jobz, const char* range,
+ const char* uplo, const int* n, double* A, const int* lda,
+ const double* vl, const double* vu,
+ const int* il, const int* iu, const double* abstol,
+ int* m, double* w, double* z,
+ const int* ldz, double* work, const int* lwork, int* iwork,
+ int* ifail, int* info);
+// Generalized eigenvalues and eigenvectors of
+// 1: A*x = lambda*B*x; 2: A*B*x = lambda*x; 3: B*A*x = lambda*x
+// A and B are symmetric and B is definite
+void dsygv_ (const int* itype, const char* jobz, const char* uplo,
+ const int* n, double* A, const int* lda, double* B,
+ const int* ldb, double* w, double* work,
+ const int* lwork, int* info);
+// Same functionality as dsygv_ but with more options: E.g.
+// Compute only eigenvalues in a specific interval,
+// Compute only eigenvalues with a specific index,
+// Set tolerance for eigenvalue computation
+void dsygvx_ (const int* itype, const char* jobz, const char* range,
+ const char* uplo, const int* n, double* A, const int* lda,
+ double* B, const int* ldb, const double* vl, const double* vu,
+ const int* il, const int* iu, const double* abstol,
+ int* m, double* w, double* z,
+ const int* ldz, double* work, const int* lwork, int* iwork,
+ int* ifail, int* info);
+
+// Compute singular value decomposition using divide and conquer
+void dgesdd_ (const char* jobz,
+ const int* m, const int* n, double* A, const int* lda,
+ double* s,
+ double* u, const int* ldu,
+ double* vt, const int* ldvt,
+ double* work, const int* lwork,
+ int* iwork,
+ int* info);
+
+// Compute singular value decomposition
+void dgesvd_ (int* jobu, int* jobvt,
+ const int* n, const int* m, double* A, const int* lda,
+ double* s,
+ double* u, const int* ldu,
+ double* vt, const int* ldvt,
+ double* work, const int* lwork,
+ int* info);
+
+// Solve a least squares problem using SVD
+void dgelsd_ (const int* m, const int* n, const int* nrhs,
+ const double* A, const int* lda,
+ double* B, const int* ldb,
+ double* s, const double* rcond,
+ int* rank,
+ double* work, const int* lwork, int* iwork,
+ int* info);
+
+// Symmetric tridiagonal matrix
+void dstev_ (const char* jobz, const int* n,
+ double* d, double* e, double* z,
+ const int* ldz, double* work,
+ int* info);
+
--- /dev/null
+#!/usr/bin/python
+
+# run this script on all headers of deal.II to fix comment line wrapping for
+# doxygen comments.
+# Example:
+# cd include
+# find . -name "*h" -print | while read file;do ../contrib/utilities/wrapcomments.py $file >temp;mv temp $file;done
+
+from __future__ import print_function
+import textwrap
+import sys
+import string
+wrapper = textwrap.TextWrapper()
+
+# take an array of lines and wrap them to 78 columns and let each lines start
+# with @p startwith
+def wrap_block(lines, startwith):
+ longline = " ".join(lines)
+ wrapper.initial_indent = startwith
+ wrapper.subsequent_indent = startwith
+ wrapper.width = 78
+ return wrapper.wrap(longline)
+
+# strips whitespace and leading "*" from each lines
+def remove_junk(lines):
+ out = []
+ for line in lines:
+ line = line.strip()
+ if line.startswith("*"):
+ line = line[1:].strip()
+ out.append(line)
+ return out
+
+# returns True if at least one entry in @p list is contained in @p str
+def one_in(list, str):
+ for li in list:
+ if li in str:
+ return True
+ return False
+
+# returns True if @p str starts with one of the entries in @p list
+def starts_with_one(list, str):
+ for li in list:
+ if str.startswith(li):
+ return True
+ return False
+
+# take a doxygen comment block "/** bla ... */" given as a list of lines and
+# format it in a pretty way rewrapping lines while taking care to keep certain
+# structure.
+def format_block(lines, infostr=""):
+ if len(lines)==1 and "/*" in lines[0] and "*/" in lines[0]:
+ return lines
+
+ if (not "/**" in lines[0]
+ or not "*/" in lines[-1]):
+ print("%s not a code block"%infostr, file=sys.stderr)
+ return lines
+
+ for line in lines[1:-1]:
+ assert(not "/*" in line)
+ assert(not "*/" in line)
+
+ lines[-1]=lines[-1].replace("**/","*/")
+
+ if not lines[0].strip().startswith("/**"):
+ print ("%s error, ignoring code block with junk in same line before"%infostr, file=sys.stderr)
+ return lines
+ if not lines[-1].strip().endswith("*/"):
+ print ("%s error, ignoring code block not ending at end of line"%infostr, file=sys.stderr)
+ return lines
+
+ if lines[0].strip()!="/**":
+ #print ("%s warning code block not starting in separate line"%infostr, file=sys.stderr)
+ idx = string.find(lines[0],"/**")
+ temp = [lines[0][0:idx+3], lines[0][idx+3:]]
+ temp.extend(lines[1:])
+ lines = temp
+ if lines[-1].strip()!="*/":
+ #print ("%s warning code block not ending in separate line"%infostr, file=sys.stderr)
+ idx = string.find(lines[-1],"*/")
+ temp = lines[0:-1]
+ temp.append(lines[-1][0:idx])
+ temp.append(lines[-1][idx:])
+ lines = temp
+
+ idx = string.find(lines[0],"/**")
+ start = lines[0][:idx]+" * "
+
+ out = [lines[0]]
+ idx = 1
+ endidx = len(lines)-1
+ curlines = []
+
+ ops_startline = ["<li>", "@param", "@returns", "@warning", "@ingroup", "@author", "@date", "@related", "@deprecated"]
+
+ ops_separate_line = ["<ul>", "</ul>", "@{", "@}"]
+
+ while idx<endidx:
+ if one_in(ops_separate_line, lines[idx]):
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ thisline = remove_junk([lines[idx]])[0]
+ for it in ops_separate_line:
+ if it in thisline and thisline!=it:
+ print ("%s warning %s not in separate line"%(infostr, it), file=sys.stderr)
+ out.append(start + thisline)
+ elif one_in(ops_startline, lines[idx]):
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ thisline = remove_junk([lines[idx]])[0]
+ if not starts_with_one(ops_startline, thisline):
+ for it in ops_startline:
+ if it in thisline:
+ print ("%s warning %s not at start of line"%(infostr, it), file=sys.stderr)
+ curlines.append(lines[idx])
+ elif one_in(["@code", "@verbatim", "@f["], lines[idx]):
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ while True:
+ thisline = lines[idx].rstrip()
+ if thisline.strip()=="*":
+ thisline = start
+ elif thisline.strip()=="@code" or thisline.strip()=="@endcode":
+ thisline = start + thisline.strip()
+ elif thisline.strip()[0:2]!="* ":
+ if thisline[0:len(start)].strip()=="":
+ # just a missing *, so keep old indentation
+ thisline = start + thisline[len(start):]
+ else:
+ # no way to recover indentation:
+ print ("%s Error: wrong formatting inside @code block"%infostr, file=sys.stderr)
+ thisline = start + thisline.strip()
+ else:
+ thisline = start + thisline.strip()[2:]
+ out.append(thisline.rstrip())
+ if one_in(["@endcode", "@endverbatim", "@f]"], lines[idx]):
+ break
+ idx += 1
+ elif lines[idx].strip()=="*":
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ out.append(start[:-1]) #skip whitespace at the end
+ else:
+ curlines.append(lines[idx])
+ idx += 1
+
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+
+ out.append(start[0:-2] + lines[-1].strip())
+
+ return out
+
+
+# test the routines:
+lineI = [" * blub", \
+ " * two three ", \
+ " * four"]
+lineO = ["blub", \
+ "two three", \
+ "four"]
+assert(remove_junk(lineI)==lineO)
+
+lineI = ["blub", \
+ "two three", \
+ "four"]
+lineO = [" * blub two three four"]
+assert(wrap_block(lineI," * ")==lineO)
+
+lineI = [" * 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0 1 2",\
+ " * A 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0"]
+assert(wrap_block(remove_junk(lineI)," * ")==lineI)
+
+lineI = [" * Structure which is passed to Triangulation::create_triangulation. It",\
+ " * contains all data needed to construct a cell, namely the indices of the",\
+ " * vertices and the material indicator."]
+assert(wrap_block(remove_junk(lineI)," * ")==lineI)
+
+lineI = [" /**", \
+ " * blub", \
+ " * two three", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub two three four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+lineI = [" /**", \
+ " * blub", \
+ " * two three", \
+ " * ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub two three", \
+ " *", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+lineI = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineI)
+
+lineI = [" /**", \
+ " * blub", \
+ " * @code ", \
+ " * two three", \
+ " * two three ", \
+ " * ", \
+ " * two three", \
+ " * @endcode ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * two three", \
+ " *", \
+ " * two three", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+lineI = [" /**", \
+ " * blub", \
+ " @code ", \
+ " two three", \
+ " @endcode ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+
+lineI = [" /**", \
+ " * blub", \
+ " * @code ", \
+ " * two three", \
+ " * two three ", \
+ " * ", \
+ " two three", \
+ " ", \
+ " * @endcode ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * two three", \
+ " *", \
+ " * two three", \
+ " *", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+
+
+lineI = [" /**", \
+ " * blub", \
+ " * <ul>", \
+ " * <li> bla", \
+ " * <li> blub", \
+ " * </ul>", \
+ " */"]
+assert(format_block(lineI)==lineI)
+
+lineI = [" /** @addtogroup Exceptions", \
+ " * @{ */"]
+lineO = [" /**", \
+ " * @addtogroup Exceptions", \
+ " * @{", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+
+# now open the file and do the work
+
+
+args=sys.argv
+args.pop(0)
+
+if len(args)!=1:
+ print("Usage: wrapcomments.py infile >outfile")
+ exit(0)
+
+f = open(args[0])
+lines = f.readlines()
+f.close()
+
+out = []
+cur = []
+inblock = False
+lineidx = 0
+for line in lines:
+ lineidx += 1
+ line = line.replace("\n","")
+ if not inblock and "/**" in line:
+ inblock = True
+ cur = []
+ if inblock:
+ cur.append(line)
+ else:
+ out.append(line)
+ if inblock and "*/" in line:
+ out.extend(format_block(cur, args[0]+":%d"%lineidx))
+ cur = []
+ inblock = False
+
+assert(cur==[])
+
+for line in out:
+ print (line)
+
+
+
+
+
<li>
<a href="http://bluebox.ippt.pan.pl/~tyoung/"
- target="_top">Toby Young</a>,
+ target="_top">Toby D. Young</a>,
Polish Academy of Sciences, Poland
</li>
<li><em>Benjamin Shelton Kirk:</em>
Tecplot output.
-
+
+ <li><em>Angela Klewinghaus:</em> FE_TraceQ, a family of face
+ elements which are the traces of H<sup>1</sup>-conforming
+ finite elements.
+
<li><em>Katharina Kormann:</em>
Support for arbitrary nodes in FE_Q. Matrix-free
framework. step-37 and step-48 tutorial programs.
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>deal.II Development Navigation Bar</title>
<link href="../screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta http-equiv="content-language" content="en">
<p>
<a href="http://www.dealii.org/websvn/log.php?repname=deal.II+Repository&path=%2F&isdir=1&" target="_top">Recent changes</a><br />
<a href="http://cdash.kyomu.43-1.org/index.php?project=deal.II" target="body">CDash</a><br />
- <a href="http://www.dealii.org/cgi-bin/regression_quick.pl" target="body">Regression tests</a><br />
<a href="http://www.math.clemson.edu/~heister/bench" target="body">Performance tests</a><br />
</p>
that future changes do not break what we have just checked in. Machines
running tests send results
back home and these are then converted into
- <a href="http://dealii.mathsim.eu/cgi-bin/regression_quick.pl"
+ <a href="http://cdash.kyomu.43-1.org/index.php?project=deal.II"
target="body">a webpage showing the status of our regression tests</a>.
</p>
COMPONENT documentation
)
+INSTALL(FILES
+ ${CMAKE_SOURCE_DIR}/doc/deal.ico
+ DESTINATION ${DEAL_II_DOCHTML_RELDIR}/doxygen/deal.II
+ COMPONENT documentation
+ )
+
INSTALL(DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/deal.II
DESTINATION ${DEAL_II_DOCHTML_RELDIR}/doxygen
* represent quantities that will most definitely not be larger than 4 billion.
*
* The data type we define for these indices to keep the bulk
- * of the code base free of <code>#ifdef</code>s is types::global_dof_index.
+ * of the code base free of <code>\#ifdef</code>s is types::global_dof_index.
* If deal.II is configured as normal, this type is <code>unsigned int</code>,
* but can be switched to <code>unsigned long long int</code> if the right
* flag is provided (see the ReadMe file). This page is intended to clarify
* to the documentation pertaining to each of them:
*
* <ol>
- *
* <li> <b>%Triangulation</b>: Triangulations are collections of
* cells and their lower-dimensional boundary objects. Cells are
* images of the reference hypercube [0,1]<sup>dim</sup> under a
* The classes that describe triangulations and cells are located
* and documented in the @ref grid module. Iterators are described
* in the @ref Iterators module.
- *
- *
* <li> <b>Finite Element</b>: Finite element classes describe the
* properties of a finite element space as defined on the unit
* cell. This includes, for example, how many degrees of freedom are
* points on the unit cell.
*
* The finite element classes are described in the @ref feall module.
- *
- *
* <li> <b>%Quadrature</b>: As with finite elements, quadrature
* objects are defined on the unit cell. They only describe the
* location of quadrature points on the unit cell, and the weights
*
* The documentation of the classes describing particular quadrature
* formulas is found in the @ref Quadrature module.
- *
- *
* <li> <b>%DoFHandler</b>: %DoFHandler objects are the confluence
* of triangulations and finite elements: the finite element class
* describes how many degrees of freedom it needs per vertex, line,
* imply constraints on degrees of freedom, such as for hanging nodes
* or nodes at which boundary conditions apply; dealing with such
* constraints is described in the @ref constraints module.
- *
- *
* <li> <b>%Mapping</b>: The next step in a finite element program
* is that one would want to compute matrix and right hand side
* entries or other quantities on each cell of a triangulation,
* derivative and Jacobian determinants.
*
* These classes are all described in the @ref mapping module.
- *
- *
* <li> <b>%FEValues</b>: The next step is to actually take a finite
* element and evaluate its shape functions and their gradients at
* the points defined by a quadrature formula when mapped to the
* cells, and FESubfaceValues for evaluation on parts of faces of
* cells. All these classes are described in the @ref feaccess
* module.
- *
- *
* <li> <b>Linear Systems</b>: If one knows how to evaluate the
* values and gradients of shape functions on individual cells using
* FEValues and friends, and knows how to get the global numbers of
* of classes for this purpose, as well as with interfaces to other
* software packages that offer similar functionality. Documentation
* to this end can be found in the @ref LAC module.
- *
- *
* <li> <b>Linear Solvers</b>: In order to determine the solution of
* a finite-dimensional, linear system of equations, one needs
* linear solvers. In finite element applications, they are
* frequently iterative, but sometimes one may also want to use
* direct or sparse direct solvers. deal.II has quite a number of
* these. They are documented in the @ref Solvers module.
- *
- *
* <li> <b>Output</b>: Finally, once one has obtained a solution of
* a finite element problem on a given triangulation, one will often
* want to postprocess it using a visualization program. This
*
* A description of the classes that do so is given in the @ref
* output module.
- *
* </ol>
*
* In addition, deal.II has a number of groups of classes that go
if (m'</head>')
{
- print '<link rel="SHORTCUT ICON" href="http://www.dealii.org/deal.ico"></link>', "\n";
+ print '<link rel="SHORTCUT ICON" href="deal.ico"></link>', "\n";
print '<meta name="author" content="The deal.II Authors <authors@dealii.org>"></meta>', "\n";
print '<meta name="copyright" content="Copyright (C) 1998 - ', $year, ' by the deal.II authors"></meta>', "\n";
print '<meta name="deal.II-version" content="@DEAL_II_PACKAGE_VERSION@"></meta>', "\n";
</p>
<ol>
+ <li> Removed: Class PointerMatrixBase (and, consequently, the various
+ classes derived from it) had comparison operators that were intended to
+ work generically for any kind of derived class. However, the implementation
+ used a scheme that was not robust enough to handle the various situations
+ that derived classes implemented and, consequently, was not always correct.
+ These operators were not previously used inside the library and, likely,
+ were not widely used in applications either. They have now been removed.
+ <br>
+ (Wolfgang Bangerth, 2014/02/15)
+ </li>
+
+ <li> The change from functionparser to muparser introduced a small number of
+ incompatibilies: units, use_degress, and recursion with 'eval' are not
+ longer supported. Comparing for equality is done using '==' instead of '='.
+ <br>
+ (Timo Heister, 2014/02/10)
+ </li>
+
<li> Changed: The various classes generating graphical output, such
as DataOut or DataOutStack, are all derived from a common interface
class DataOutInterface which, in turn was derived from DataOutBase
<ol>
+
+ <li> Changed: the functionparser library bundled with deal.II got replaced
+ by the muparser library.
+ <br>
+ (Timo Heister, 2014/02/10)
+ </li>
+
<li> Changed: It was possible to call DoFAccessor::set_active_fe_index()
on non-active cells. However, this made no sense: Since degrees of
freedoms only exist on active cells
<h3>Specific improvements</h3>
<ol>
+
+ <li> Fixed: step-32 had a piece of code where we accessed an internal
+ representation of how Trilinos vectors are actually stored. This is poor
+ style and has been rewritten.
+ <br>
+ (Wolfgang Bangerth, 2014/03/14)
+ </li>
+
+ <li> Fixed: VectorTools::project_boundary_values_curl_conforming contained
+ a bug for some cases. This is now fixed.
+ <br>
+ (Markus Bürg, 2014/03/10)
+ </li>
+
+ <li> Fixed: ParameterHandler will no longer output an error if the file
+ to be read ends with "end" without a newline.
+ <br>
+ (Timo Heister, 2014/02/28)
+ </li>
+
+ <li>Improved: DoFRenumbering::Cuthill_McKee can now run with distributed
+ triangulations with the renumbering only done within each processor's
+ subdomain.
+ <br>
+ (Martin Kronbichler, 2014/02/20)
+
+ <li>Fixed: There was an indexing error in GridIn::read_vtk() that triggered
+ for some input files. This is now fixed.
+ <br>
+ (Mayank Sabharwal, 2014/02/19)
+
+ <li>New: There is a new namespace TimeStepping for the algorithms that do time
+ integrations. In this new namespace, several Runge-Kutta methods have been
+ implemented: explicit methods, implicit methods, and embedded explicit methods.
+ <br>
+ (Damien Lebrun-Grandie, Bruno Turcksin, 2014/02/17)
+
+ <li>New: There is now a class FEEvaluationDGP that implements matrix-free
+ evaluation routines by truncated tensor products for FE_DGP elements.
+ <br>
+ (Martin Kronbichler, 2014/02/17)
+
+ <li>Changed: The InverseMatrixRichardson used to eat all exceptions
+ that may have been produced by the underlying Richardson solver, leaving
+ no trace that the underlying solver may have failed when you call functions
+ such as InverseMatrixRichardson::vmult(). These exceptions are now propagated
+ out to the caller.
+ <br>
+ (Wolfgang Bangerth, 2014/02/16)
+
+
+ <li>New: FE_TraceQ implements finite elements on faces, which
+ correspond to the traces of H<sup>1</sup>-conforming elements.
+ <br>
+ (Angela Klewinghaus, 2014/02/14)
+
+ <li>New: FE_FaceQ and FE_FaceP now also work in 1D (with a single dof
+ on each vertex).
+ <br>
+ (Martin Kronbichler, 2014/02/11)
+
+ <li>Fixed: FE_DGQ::has_support_on_face returned a wrong number for element
+ degree larger than 1 in 1D. This is now fixed.
+ <br>
+ (Martin Kronbichler, 2014/02/10)
+
<li>Changed: DerivativeApproximation used to be a class that only had
static members. It is now a namespace.
<br>
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
- <link href="../screen.css" rel="StyleSheet">
<title>The deal.II news page</title>
+
+ <link href="../screen.css" rel="StyleSheet">
+
<meta name="copyright" content="Copyright (C) 2000 - 2013 by the deal.II Authors">
<meta name="date" content="$Date$">
<meta name="keywords" content="deal.II">
<meta name="svn_id" content="$Id$">
-</head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <!- Include stylesheets ->
+ <link href="/mockup/htdocs/css/bootstrap.min.css" type="text/css" rel="stylesheet"/>
+ <link href="/mockup/htdocs/css/global.less" type="text/less" rel="stylesheet"/>
+ <link href="/mockup/htdocs/css/index.less" type="text/less" rel="stylesheet"/>
+
+ <!- LESS needs to come after the stylesheets ->
+ <script src="/mockup/htdocs/js/less-1.4.1.min.js"></script>
+</head>
+
<body>
+
+<!--#include virtual="/mockup/htdocs/header.include" -->
+
<h2>News on <acronym>deal.II</acronym></h2>
<p>
</body>
+ <!- Some JQuery needs to come after the body ->
+ <script src="js/jquery.min.js"></script>
+ <script src="js/bootstrap.min.js"></script>
+ <script src="js/accordion.js"></script>
</html>
<a href="#2011">2011</a>
<a href="#2012">2012</a>
<a href="#2013">2013</a>
+ <a href="#2014">2014</a>
<br>
<a href="#2000">2000</a>
<a href="#2001">2001</a>
SIAM J. Numer. Anal. 52 (2014), no. 1, 103-124.
</li>
+
+ <li> F. Wang
+ <br>
+ <strong>Regularizing Inverse Problems
+ </strong>
+ <br>
+ Ph.D. thesis, Texas A&M University, 2014.
+ </li>
+
+ <li> K. Wang
+ <br>
+ <strong>Parallel Markov Chain Monte Carlo Methods for Large
+ Scale Inverse Problems
+ </strong>
+ <br>
+ Ph.D. thesis, Texas A&M University, 2014.
+ </li>
+
+ <li> Y. Zhang
+ <br>
+ <strong>SP<sub>N</sub> Model Error and Iterative Solution Techniques
+ </strong>
+ <br>
+ Ph.D. thesis, Texas A&M University, 2014.
+ </li>
+
</ol>
<title>deal.II CMake documentation</title>
<link href="../screen.css" rel="StyleSheet">
<meta name="author" content="the deal.II authors <authors @ dealii.org>">
- <meta name="copyright" content="Copyright (C) 2012, 2013 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 2012, 2013, 2014 by the deal.II authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta name="keywords" content="deal.II">
DEAL_II_WITH_LAPACK
DEAL_II_WITH_METIS
DEAL_II_WITH_MUMPS
+DEAL_II_WITH_MUPARSER
DEAL_II_WITH_MPI
DEAL_II_WITH_NETCDF
DEAL_II_WITH_P4EST
LAPACK_DIR (and BLAS_DIR),
METIS_DIR,
MUMPS_DIR (and SCALAPACK_DIR, BLACS_DIR),
+MUPARSER_DIR,
P4EST_DIR (and SC_DIR),
PETSC_DIR and PETSC_ARCH (forming ${PETSC_DIR}/${PETSC_ARCH}),
SLEPC_DIR (forming ${SLEPC_DIR}/${PETSC_ARCH}),
a way to provide a link interface that is suitable for static
linkage of executables. Enabling this option forces
<code>BUILD_SHARED_LIBS=OFF</code> and
- <code>DEAL_II_PERFER_STATIC_LIBS</code>.
+ <code>DEAL_II_PREFER_STATIC_LIBS=ON</code>.
<li>
<code>CMAKE_INSTALL_RPATH_USE_LINK_PATH</code>: If set
DEAL_II_WITH_METIS
DEAL_II_WITH_MPI
DEAL_II_WITH_MUMPS
+DEAL_II_WITH_MUPARSER
DEAL_II_WITH_NETCDF
DEAL_II_WITH_P4EST
DEAL_II_WITH_PETSC
// the global matrix from local contributions. This works, but the same
// can be done in a slightly simpler way if we already take care of these
// constraints at the time of copying local contributions into the global
- // matrix. To this end, we here do not just compute the constraints do to
+ // matrix. To this end, we here do not just compute the constraints due to
// hanging nodes, but also due to zero boundary conditions. We will use
// this set of constraints later on to help us copy local contributions
// correctly into the global linear system right away, without the need
DoFTools::make_hanging_node_constraints (mg_dof_handler, hanging_node_constraints);
DoFTools::make_hanging_node_constraints (mg_dof_handler, constraints);
- typename FunctionMap<dim>::type dirichlet_boundary;
+ typename FunctionMap<dim>::type dirichlet_boundary_functions;
ZeroFunction<dim> homogeneous_dirichlet_bc (1);
- dirichlet_boundary[0] = &homogeneous_dirichlet_bc;
+ dirichlet_boundary_functions[0] = &homogeneous_dirichlet_bc;
VectorTools::interpolate_boundary_values (static_cast<const DoFHandler<dim>&>(mg_dof_handler),
- dirichlet_boundary,
+ dirichlet_boundary_functions,
constraints);
constraints.close ();
hanging_node_constraints.close ();
// about the boundary values as well, so we pass the
// <code>dirichlet_boundary</code> here as well.
mg_constrained_dofs.clear();
- mg_constrained_dofs.initialize(mg_dof_handler, dirichlet_boundary);
+ mg_constrained_dofs.initialize(mg_dof_handler, dirichlet_boundary_functions);
// Now for the things that concern the multigrid data structures. First,
}
+ // For the right-hand side we use the fact that the shape
+ // functions are only non-zero in one component (because our
+ // elements are primitive). Instead of multiplying the tensor
+ // representing the dim+1 values of shape function i with the
+ // whole right-hand side vector, we only look at the only
+ // non-zero component. The Function
+ // FiniteElement::system_to_component_index(i) will return
+ // which component this shape function lives in (0=x velocity,
+ // 1=y velocity, 2=pressure in 2d), which we use to pick out
+ // the correct component of the right-hand side vector to
+ // multiply with.
+
const unsigned int component_i =
fe.system_to_component_index(i).first;
local_rhs(i) += fe_values.shape_value(i,q) *
// global right hand side to zero, before we fill them:
cell_matrix = 0;
cell_rhs = 0;
-
- // Then finally assemble the matrix: For the Laplace problem, the matrix
- // on each cell is the integral over the gradients of shape function i
- // and j. Since we do not integrate, but rather use quadrature, this is
- // the sum over all quadrature points of the integrands times the
- // determinant of the Jacobian matrix at the quadrature point times the
- // weight of this quadrature point. You can get the gradient of shape
- // function $i$ at quadrature point q_point by using
- // <code>fe_values.shape_grad(i,q_point)</code>; this gradient is a
- // 2-dimensional vector (in fact it is of type Tensor@<1,dim@>, with
- // here dim=2) and the product of two such vectors is the scalar
- // product, i.e. the product of the two shape_grad function calls is the
- // dot product. This is in turn multiplied by the Jacobian determinant
- // and the quadrature point weight (that one gets together by the call
- // to FEValues::JxW() ). Finally, this is repeated for all shape
- // functions $i$ and $j$:
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- cell_matrix(i,j) += (fe_values.shape_grad (i, q_point) *
- fe_values.shape_grad (j, q_point) *
- fe_values.JxW (q_point));
-
- // We then do the same thing for the right hand side. Here, the integral
- // is over the shape function i times the right hand side function,
- // which we choose to be the function with constant value one (more
- // interesting examples will be considered in the following
- // programs). Again, we compute the integral by quadrature, which
- // transforms the integral to a sum over all quadrature points of the
- // value of the shape function at that point times the right hand side
- // function, here the constant function equal to one, times the Jacobian
- // determinant times the weight of that quadrature point:
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- cell_rhs(i) += (fe_values.shape_value (i, q_point) *
- 1 *
- fe_values.JxW (q_point));
-
+
+ // Now it is time to start integration over the cell, which we
+ // do by looping over all quadrature points, which we will
+ // number by q_index.
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
+ {
+ // First assemble the matrix: For the Laplace problem, the
+ // matrix on each cell is the integral over the gradients of
+ // shape function i and j. Since we do not integrate, but
+ // rather use quadrature, this is the sum over all
+ // quadrature points of the integrands times the determinant
+ // of the Jacobian matrix at the quadrature point times the
+ // weight of this quadrature point. You can get the gradient
+ // of shape function $i$ at quadrature point with number q_index by
+ // using <code>fe_values.shape_grad(i,q_index)</code>; this
+ // gradient is a 2-dimensional vector (in fact it is of type
+ // Tensor@<1,dim@>, with here dim=2) and the product of two
+ // such vectors is the scalar product, i.e. the product of
+ // the two shape_grad function calls is the dot
+ // product. This is in turn multiplied by the Jacobian
+ // determinant and the quadrature point weight (that one
+ // gets together by the call to FEValues::JxW() ). Finally,
+ // this is repeated for all shape functions $i$ and $j$:
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += (fe_values.shape_grad (i, q_index) *
+ fe_values.shape_grad (j, q_index) *
+ fe_values.JxW (q_index));
+
+ // We then do the same thing for the right hand side. Here,
+ // the integral is over the shape function i times the right
+ // hand side function, which we choose to be the function
+ // with constant value one (more interesting examples will
+ // be considered in the following programs).
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_rhs(i) += (fe_values.shape_value (i, q_index) *
+ 1 *
+ fe_values.JxW (q_index));
+ }
// Now that we have the contribution of this cell, we have to transfer
// it to the global matrix and right hand side. To this end, we first
// have to find out which global numbers the degrees of freedom on this
};
double global_temperature[2];
- for (unsigned int i=0; i<distributed_temperature_solution.local_size(); ++i)
+ for (unsigned int i=distributed_temperature_solution.local_range().first;
+ i < distributed_temperature_solution.local_range().second; ++i)
{
temperature[0] = std::min<double> (temperature[0],
- distributed_temperature_solution.trilinos_vector()[0][i]);
+ distributed_temperature_solution(i));
temperature[1] = std::max<double> (temperature[1],
- distributed_temperature_solution.trilinos_vector()[0][i]);
+ distributed_temperature_solution(i));
}
temperature[0] *= -1.0;
#include <deal.II/fe/fe_dgp.h>
#include <deal.II/fe/fe_dgq.h>
#include <deal.II/dofs/dof_tools.h>
-#include <deal.II/multigrid/mg_dof_handler.h>
// The include files for using the MeshWorker framework
#include <deal.II/meshworker/dof_info.h>
Triangulation<dim> triangulation;
const MappingQ1<dim> mapping;
const FiniteElement<dim> &fe;
- MGDoFHandler<dim> mg_dof_handler;
- DoFHandler<dim> &dof_handler;
+ DoFHandler<dim> dof_handler;
// Then, we have the matrices and vectors related to the global discrete
// system.
:
mapping(),
fe(fe),
- mg_dof_handler(triangulation),
- dof_handler(mg_dof_handler),
+ dof_handler(triangulation),
estimates(1)
{
GridGenerator::hyper_cube_slit(triangulation, -1, 1);
// First, we use the finite element to distribute degrees of freedom over
// the mesh and number them.
dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs(fe);
unsigned int n_dofs = dof_handler.n_dofs();
// Then, we already know the size of the vectors representing finite
// element functions.
{
// These are roughly the same lines as above for the global matrix,
// now for each level.
- CompressedSparsityPattern c_sparsity(mg_dof_handler.n_dofs(level));
- MGTools::make_flux_sparsity_pattern(mg_dof_handler, c_sparsity, level);
+ CompressedSparsityPattern c_sparsity(dof_handler.n_dofs(level));
+ MGTools::make_flux_sparsity_pattern(dof_handler, c_sparsity, level);
mg_sparsity[level].copy_from(c_sparsity);
mg_matrix[level].reinit(mg_sparsity[level]);
if (level>0)
{
CompressedSparsityPattern ci_sparsity;
- ci_sparsity.reinit(mg_dof_handler.n_dofs(level-1), mg_dof_handler.n_dofs(level));
- MGTools::make_flux_sparsity_pattern_edge(mg_dof_handler, ci_sparsity, level);
+ ci_sparsity.reinit(dof_handler.n_dofs(level-1), dof_handler.n_dofs(level));
+ MGTools::make_flux_sparsity_pattern_edge(dof_handler, ci_sparsity, level);
mg_sparsity_dg_interface[level].copy_from(ci_sparsity);
mg_matrix_dg_up[level].reinit(mg_sparsity_dg_interface[level]);
mg_matrix_dg_down[level].reinit(mg_sparsity_dg_interface[level]);
info_box.add_update_flags_all(update_flags);
info_box.initialize(fe, mapping);
- MeshWorker::DoFInfo<dim> dof_info(mg_dof_handler);
+ MeshWorker::DoFInfo<dim> dof_info(dof_handler);
// Obviously, the assembler needs to be replaced by one filling level
// matrices. Note that it automatically fills the edge matrices as well.
assembler.initialize_fluxes(mg_matrix_dg_up, mg_matrix_dg_down);
MatrixIntegrator<dim> integrator;
- // Here is the other difference to the previous function: we run over all
- // cells, not only the active ones. And we use <tt>mg_dof_handler</tt>,
- // since we need the degrees of freedom on each level, not the global
- // numbering.
+ // Here is the other difference to the previous function: we run
+ // over all cells, not only the active ones. And we use functions
+ // ending on <code>_mg</code> since we need the degrees of freedom
+ // on each level, not the global numbering.
MeshWorker::integration_loop<dim, dim> (
- mg_dof_handler.begin(), mg_dof_handler.end(),
+ dof_handler.begin_mg(), dof_handler.end_mg(),
dof_info, info_box,
integrator, assembler);
}
// preconditioner. First, we need transfer between grid levels. The object
// we are using here generates sparse matrices for these transfers.
MGTransferPrebuilt<Vector<double> > mg_transfer;
- mg_transfer.build_matrices(mg_dof_handler);
+ mg_transfer.build_matrices(dof_handler);
// Then, we need an exact solver for the matrix on the coarsest level.
FullMatrix<double> coarse_matrix;
// Now, we are ready to set up the V-cycle operator and the multilevel
// preconditioner.
- Multigrid<Vector<double> > mg(mg_dof_handler, mgmatrix,
+ Multigrid<Vector<double> > mg(dof_handler, mgmatrix,
mg_coarse, mg_transfer,
mg_smoother, mg_smoother);
// Let us not forget the edge matrices needed because of the adaptive
// which can be used as a regular preconditioner,
PreconditionMG<dim, Vector<double>,
MGTransferPrebuilt<Vector<double> > >
- preconditioner(mg_dof_handler, mg, mg_transfer);
+ preconditioner(dof_handler, mg, mg_transfer);
// and use it to solve the system.
solver.solve(matrix, solution, right_hand_side, preconditioner);
}
setup_system();
deallog << "DoFHandler " << dof_handler.n_dofs() << " dofs, level dofs";
for (unsigned int l=0; l<triangulation.n_levels(); ++l)
- deallog << ' ' << mg_dof_handler.n_dofs(l);
+ deallog << ' ' << dof_handler.n_dofs(l);
deallog << std::endl;
deallog << "Assemble matrix" << std::endl;
// difference to how we did things in step-3: Instead of using a
// constant right hand side with value 1, we use the object representing
// the right hand side and evaluate it at the quadrature points:
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += (fe_values.shape_grad (i, q_point) *
- fe_values.shape_grad (j, q_point) *
- fe_values.JxW (q_point));
+ cell_matrix(i,j) += (fe_values.shape_grad (i, q_index) *
+ fe_values.shape_grad (j, q_index) *
+ fe_values.JxW (q_index));
- cell_rhs(i) += (fe_values.shape_value (i, q_point) *
- right_hand_side.value (fe_values.quadrature_point (q_point)) *
- fe_values.JxW (q_point));
+ cell_rhs(i) += (fe_values.shape_value (i, q_index) *
+ right_hand_side.value (fe_values.quadrature_point (q_index)) *
+ fe_values.JxW (q_index));
}
// As a final remark to these loops: when we assemble the local
// contributions into <code>cell_matrix(i,j)</code>, we have to multiply
- // the gradients of shape functions $i$ and $j$ at point q_point and
+ // the gradients of shape functions $i$ and $j$ at point number
+ // q_index and
// multiply it with the scalar weights JxW. This is what actually
- // happens: <code>fe_values.shape_grad(i,q_point)</code> returns a
+ // happens: <code>fe_values.shape_grad(i,q_index)</code> returns a
// <code>dim</code> dimensional vector, represented by a
// <code>Tensor@<1,dim@></code> object, and the operator* that
// multiplies it with the result of
- // <code>fe_values.shape_grad(j,q_point)</code> makes sure that the
+ // <code>fe_values.shape_grad(j,q_index)</code> makes sure that the
// <code>dim</code> components of the two vectors are properly
// contracted, and the result is a scalar floating point number that
// then is multiplied with the weights. Internally, this operator* makes
// We've chosen by default a SSOR preconditioner as it appears to
// provide the fastest solver convergence characteristics for this
- // problem on a single-thread machine. However, for multicore
- // computing, the Jacobi preconditioner which is multithreaded may
- // converge quicker for larger linear systems.
+ // problem on a single-thread machine. However, this might not be
+ // true for different problem sizes.
PreconditionSelector<SparseMatrix<double>, Vector<double> >
preconditioner (parameters.preconditioner_type,
parameters.preconditioner_relaxation);
coefficient.value_list (fe_values.get_quadrature_points(),
coefficient_values);
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += (coefficient_values[q_point] *
- fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) *
- fe_values.JxW(q_point));
+ cell_matrix(i,j) += (coefficient_values[q_index] *
+ fe_values.shape_grad(i,q_index) *
+ fe_values.shape_grad(j,q_index) *
+ fe_values.JxW(q_index));
- cell_rhs(i) += (fe_values.shape_value(i,q_point) *
+ cell_rhs(i) += (fe_values.shape_value(i,q_index) *
1.0 *
- fe_values.JxW(q_point));
+ fe_values.JxW(q_index));
}
\\
- (\nabla w, \mathbf{c} u_h)_{\mathcal{T}}
+ (w, \nabla \cdot \mathbf{q}_h)_{\mathcal{T}}
- + (w, (\mathbf{c}\cdot\mathbf{n}) \hat{u}_H)_{\mathcal{T}}
+ + (w, (\mathbf{c}\cdot\mathbf{n}) \hat{u}_H)_{\partial \mathcal{T}}
+ \left<w, \tau (u_h - \hat{u}_h)\right>_{\partial \mathcal{T}}
&=&
(w, f)_{\mathcal{T}},
coefficient.value_list (fe_values.get_quadrature_points(),
coefficient_values);
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += (coefficient_values[q_point] *
- fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) *
- fe_values.JxW(q_point));
+ cell_matrix(i,j) += (coefficient_values[q_index] *
+ fe_values.shape_grad(i,q_index) *
+ fe_values.shape_grad(j,q_index) *
+ fe_values.JxW(q_index));
- cell_rhs(i) += (fe_values.shape_value(i,q_point) *
+ cell_rhs(i) += (fe_values.shape_value(i,q_index) *
1.0 *
- fe_values.JxW(q_point));
+ fe_values.JxW(q_index));
}
// Finally, transfer the contributions from @p cell_matrix and
// quartic function, for which a 3 point Gauss formula is sufficient since it
// integrates polynomials up to order 5 exactly.)
//
-// Secondly, the function wants a list of boundaries where we have imposed
-// Neumann value, and the corresponding Neumann values. This information is
+// Secondly, the function wants a list of boundary indicators for those
+// boundaries where we have imposed Neumann values of the kind
+// $\partial_n u(\mathbf x) = h(\mathbf x)$, along with a function $h(\mathbf x)$
+// for each such boundary. This information is
// represented by an object of type <code>FunctionMap::type</code> that is
-// essentially a map from boundary indicators to function objects describing
-// Neumann boundary values (in the present example program, we do not use
+// a typedef to a map from boundary indicators to function objects describing
+// the Neumann boundary values. In the present example program, we do not use
// Neumann boundary values, so this map is empty, and in fact constructed
// using the default constructor of the map in the place where the function
-// call expects the respective function argument).
+// call expects the respective function argument.
//
// The output, as mentioned is a vector of values for all cells. While it may
-// make sense to compute the *value* of a degree of freedom very accurately,
-// it is usually not helpful to compute the *error indicator* corresponding to
-// a cell particularly accurately. We therefore typically use a vector of
-// floats instead of a vector of doubles to represent error indicators.
+// make sense to compute the <b>value</b> of a solution degree of freedom
+// very accurately, it is usually not necessary to compute the <b>error indicator</b>
+// corresponding to the solution on a cell particularly accurately. We therefore
+// typically use a vector of floats instead of a vector of doubles to represent
+// error indicators.
template <int dim>
void Step6<dim>::refine_grid ()
{
$x_1=(-\frac 12,\frac 12)$,
$x_2=(-\frac 12,-\frac 12)$, and
$x_3=(\frac 12,-\frac 12)$.
-The half width is set to $\sigma=\frac 13$.
+The half width is set to $\sigma=\frac {1}{8}$.
We further choose $\Gamma_1=\Gamma \cap\{\{x=1\} \cup \{y=1\}\}$, and there
set $g_1$ such that it resembles the exact values of $u$. Likewise, we choose
The program generates two kinds of output. The first are the output
-files <code>solution-adaptive-q1.gmv</code>,
-<code>solution-global-q1.gmv</code>, and
-<code>solution-global-q2.gmv</code>. We show the latter in a 3d view
+files <code>solution-adaptive-q1.vtk</code>,
+<code>solution-global-q1.vtk</code>, and
+<code>solution-global-q2.vtk</code>. We show the latter in a 3d view
here:
@code
examples/\step-7> make run
-============================ Running \step-7
Solving with Q1 elements, adaptive refinement
=============================================
Cycle 0:
- Number of active cells: 4
- Number of degrees of freedom: 9
+ Number of active cells: 64
+ Number of degrees of freedom: 81
Cycle 1:
- Number of active cells: 13
- Number of degrees of freedom: 22
+ Number of active cells: 124
+ Number of degrees of freedom: 157
Cycle 2:
- Number of active cells: 31
- Number of degrees of freedom: 46
+ Number of active cells: 280
+ Number of degrees of freedom: 341
Cycle 3:
- Number of active cells: 64
- Number of degrees of freedom: 87
+ Number of active cells: 577
+ Number of degrees of freedom: 690
Cycle 4:
- Number of active cells: 127
- Number of degrees of freedom: 160
+ Number of active cells: 1099
+ Number of degrees of freedom: 1264
Cycle 5:
- Number of active cells: 244
- Number of degrees of freedom: 297
+ Number of active cells: 2191
+ Number of degrees of freedom: 2452
Cycle 6:
- Number of active cells: 466
- Number of degrees of freedom: 543
-
-cycle cells dofs L2 H1 Linfty
- 0 4 9 1.198e+00 2.732e+00 1.383e+00
- 1 13 22 8.795e-02 1.193e+00 1.816e-01
- 2 31 46 8.147e-02 1.167e+00 1.654e-01
- 3 64 87 7.702e-02 1.077e+00 1.310e-01
- 4 127 160 4.643e-02 7.988e-01 6.745e-02
- 5 244 297 2.470e-02 5.568e-01 3.668e-02
- 6 466 543 1.622e-02 4.107e-01 2.966e-02
+ Number of active cells: 4165
+ Number of degrees of freedom: 4510
+Cycle 7:
+ Number of active cells: 7915
+ Number of degrees of freedom: 8440
+Cycle 8:
+ Number of active cells: 15196
+ Number of degrees of freedom: 15912
+
+cycle cells dofs L2 H1 Linfty
+ 0 64 81 1.576e-01 1.418e+00 2.707e-01
+ 1 124 157 4.285e-02 1.285e+00 1.469e-01
+ 2 280 341 1.593e-02 7.909e-01 8.034e-02
+ 3 577 690 9.359e-03 5.096e-01 2.784e-02
+ 4 1099 1264 2.865e-03 3.038e-01 9.822e-03
+ 5 2191 2452 1.480e-03 2.106e-01 5.679e-03
+ 6 4165 4510 6.907e-04 1.462e-01 2.338e-03
+ 7 7915 8440 4.743e-04 1.055e-01 1.442e-03
+ 8 15196 15912 1.920e-04 7.468e-02 7.259e-04
Solving with Q1 elements, global refinement
===========================================
Cycle 0:
- Number of active cells: 4
- Number of degrees of freedom: 9
-Cycle 1:
- Number of active cells: 16
- Number of degrees of freedom: 25
-Cycle 2:
Number of active cells: 64
Number of degrees of freedom: 81
-Cycle 3:
+Cycle 1:
Number of active cells: 256
Number of degrees of freedom: 289
-Cycle 4:
+Cycle 2:
Number of active cells: 1024
Number of degrees of freedom: 1089
-Cycle 5:
+Cycle 3:
Number of active cells: 4096
Number of degrees of freedom: 4225
-Cycle 6:
+Cycle 4:
Number of active cells: 16384
Number of degrees of freedom: 16641
-cycle cells dofs L2 H1 Linfty
- 0 4 9 1.198e+00 2.732e+00 1.383e+00
- 1 16 25 8.281e-02 1.190e+00 1.808e-01
- 2 64 81 8.142e-02 1.129e+00 1.294e-01
- 3 256 289 2.113e-02 5.828e-01 4.917e-02
- 4 1024 1089 5.319e-03 2.934e-01 1.359e-02
- 5 4096 4225 1.332e-03 1.469e-01 3.482e-03
- 6 16384 16641 3.332e-04 7.350e-02 8.758e-04
-
-n cells H1 L2
- 0 4 2.732e+00 - 1.198e+00 - -
- 1 16 1.190e+00 1.20 8.281e-02 14.47 3.86
- 2 64 1.129e+00 0.08 8.142e-02 1.02 0.02
- 3 256 5.828e-01 0.95 2.113e-02 3.85 1.95
- 4 1024 2.934e-01 0.99 5.319e-03 3.97 1.99
- 5 4096 1.469e-01 1.00 1.332e-03 3.99 2.00
- 6 16384 7.350e-02 1.00 3.332e-04 4.00 2.00
+cycle cells dofs L2 H1 Linfty
+ 0 64 81 1.576e-01 1.418e+00 2.707e-01
+ 1 256 289 4.280e-02 1.285e+00 1.444e-01
+ 2 1024 1089 1.352e-02 7.556e-01 7.772e-02
+ 3 4096 4225 3.423e-03 3.822e-01 2.332e-02
+ 4 16384 16641 8.586e-04 1.917e-01 6.097e-03
+
+n cells H1 L2
+0 64 1.418e+00 - - 1.576e-01 - -
+1 256 1.285e+00 1.10 0.14 4.280e-02 3.68 1.88
+2 1024 7.556e-01 1.70 0.77 1.352e-02 3.17 1.66
+3 4096 3.822e-01 1.98 0.98 3.423e-03 3.95 1.98
+4 16384 1.917e-01 1.99 1.00 8.586e-04 3.99 2.00
Solving with Q2 elements, global refinement
===========================================
Cycle 0:
- Number of active cells: 4
- Number of degrees of freedom: 25
-Cycle 1:
- Number of active cells: 16
- Number of degrees of freedom: 81
-Cycle 2:
Number of active cells: 64
Number of degrees of freedom: 289
-Cycle 3:
+Cycle 1:
Number of active cells: 256
Number of degrees of freedom: 1089
-Cycle 4:
+Cycle 2:
Number of active cells: 1024
Number of degrees of freedom: 4225
-Cycle 5:
+Cycle 3:
Number of active cells: 4096
Number of degrees of freedom: 16641
-Cycle 6:
+Cycle 4:
Number of active cells: 16384
Number of degrees of freedom: 66049
-cycle cells dofs L2 H1 Linfty
- 0 4 25 1.433e+00 2.445e+00 1.286e+00
- 1 16 81 7.912e-02 1.168e+00 1.728e-01
- 2 64 289 7.755e-03 2.511e-01 1.991e-02
- 3 256 1089 9.969e-04 6.235e-02 2.764e-03
- 4 1024 4225 1.265e-04 1.571e-02 3.527e-04
- 5 4096 16641 1.587e-05 3.937e-03 4.343e-05
- 6 16384 66049 1.986e-06 9.847e-04 5.402e-06
-
-n cells H1 L2
- 0 4 2.445e+00 - 1.433e+00 - -
- 1 16 1.168e+00 1.07 7.912e-02 18.11 4.18
- 2 64 2.511e-01 2.22 7.755e-03 10.20 3.35
- 3 256 6.235e-02 2.01 9.969e-04 7.78 2.96
- 4 1024 1.571e-02 1.99 1.265e-04 7.88 2.98
- 5 4096 3.937e-03 2.00 1.587e-05 7.97 2.99
- 6 16384 9.847e-04 2.00 1.986e-06 7.99 3.00
+cycle cells dofs L2 H1 Linfty
+ 0 64 289 1.606e-01 1.278e+00 3.029e-01
+ 1 256 1089 7.638e-03 5.248e-01 4.816e-02
+ 2 1024 4225 8.601e-04 1.086e-01 4.827e-03
+ 3 4096 16641 1.107e-04 2.756e-02 7.802e-04
+ 4 16384 66049 1.393e-05 6.915e-03 9.971e-05
+
+n cells H1 L2
+0 64 1.278e+00 - - 1.606e-01 - -
+1 256 5.248e-01 2.43 1.28 7.638e-03 21.03 4.39
+2 1024 1.086e-01 4.83 2.27 8.601e-04 8.88 3.15
+3 4096 2.756e-02 3.94 1.98 1.107e-04 7.77 2.96
+4 16384 6.915e-03 3.99 1.99 1.393e-05 7.94 2.99
+
+Solving with Q2 elements, adaptive refinement
+===========================================
+
+Cycle 0:
+ Number of active cells: 64
+ Number of degrees of freedom: 289
+Cycle 1:
+ Number of active cells: 124
+ Number of degrees of freedom: 577
+Cycle 2:
+ Number of active cells: 289
+ Number of degrees of freedom: 1353
+Cycle 3:
+ Number of active cells: 547
+ Number of degrees of freedom: 2531
+Cycle 4:
+ Number of active cells: 1057
+ Number of degrees of freedom: 4919
+Cycle 5:
+ Number of active cells: 2059
+ Number of degrees of freedom: 9223
+Cycle 6:
+ Number of active cells: 3913
+ Number of degrees of freedom: 17887
+Cycle 7:
+ Number of active cells: 7441
+ Number of degrees of freedom: 33807
+Cycle 8:
+ Number of active cells: 14212
+ Number of degrees of freedom: 64731
+
+cycle cells dofs L2 H1 Linfty
+ 0 64 289 1.606e-01 1.278e+00 3.029e-01
+ 1 124 577 7.891e-03 5.256e-01 4.852e-02
+ 2 289 1353 1.070e-03 1.155e-01 4.868e-03
+ 3 547 2531 5.962e-04 5.101e-02 1.876e-03
+ 4 1057 4919 1.977e-04 3.094e-02 7.923e-04
+ 5 2059 9223 7.738e-05 1.974e-02 7.270e-04
+ 6 3913 17887 2.925e-05 8.772e-03 1.463e-04
+ 7 7441 33807 1.024e-05 4.121e-03 8.567e-05
+ 8 14212 64731 3.761e-06 2.108e-03 2.167e-05
@endcode
-Finally, the program generated various LaTeX tables. We show here
-the convergence table of the Q2 element with global refinement, after
-converting the format to HTML:
-
-
-
-<TABLE CELLPADDING=3 BORDER="1" ALIGN="CENTER">
-<TR><TD ALIGN="CENTER" COLSPAN=2>
-n cells</TD>
-<TD ALIGN="CENTER" COLSPAN=2><I>H</I><SUP>1</SUP>-error</TD>
-<TD ALIGN="CENTER" COLSPAN=3><I>L</I><SUP>2</SUP>-error</TD>
-</TR>
-<TR><TD ALIGN="CENTER">0</TD>
-<TD ALIGN="RIGHT">4</TD>
-<TD ALIGN="CENTER">2.445e+00</TD>
-<TD ALIGN="CENTER">-</TD>
-<TD ALIGN="CENTER">1.433e+00</TD>
-<TD ALIGN="CENTER">-</TD>
-<TD ALIGN="CENTER">-</TD>
-</TR>
-<TR><TD ALIGN="CENTER">1</TD>
-<TD ALIGN="RIGHT">16</TD>
-<TD ALIGN="CENTER">1.168e+00</TD>
-<TD ALIGN="CENTER">1.07</TD>
-<TD ALIGN="CENTER">7.912e-02</TD>
-<TD ALIGN="CENTER">18.11</TD>
-<TD ALIGN="CENTER">4.18</TD>
-</TR>
-<TR><TD ALIGN="CENTER">2</TD>
-<TD ALIGN="RIGHT">64</TD>
-<TD ALIGN="CENTER">2.511e-01</TD>
-<TD ALIGN="CENTER">2.22</TD>
-<TD ALIGN="CENTER">7.755e-03</TD>
-<TD ALIGN="CENTER">10.20</TD>
-<TD ALIGN="CENTER">3.35</TD>
-</TR>
-<TR><TD ALIGN="CENTER">3</TD>
-<TD ALIGN="RIGHT">256</TD>
-<TD ALIGN="CENTER">6.235e-02</TD>
-<TD ALIGN="CENTER">2.01</TD>
-<TD ALIGN="CENTER">9.969e-04</TD>
-<TD ALIGN="CENTER">7.78</TD>
-<TD ALIGN="CENTER">2.96</TD>
-</TR>
-<TR><TD ALIGN="CENTER">4</TD>
-<TD ALIGN="RIGHT">1024</TD>
-<TD ALIGN="CENTER">1.571e-02</TD>
-<TD ALIGN="CENTER">1.99</TD>
-<TD ALIGN="CENTER">1.265e-04</TD>
-<TD ALIGN="CENTER">7.88</TD>
-<TD ALIGN="CENTER">2.98</TD>
-</TR>
-<TR><TD ALIGN="CENTER">5</TD>
-<TD ALIGN="RIGHT">4096</TD>
-<TD ALIGN="CENTER">3.937e-03</TD>
-<TD ALIGN="CENTER">2.00</TD>
-<TD ALIGN="CENTER">1.587e-05</TD>
-<TD ALIGN="CENTER">7.97</TD>
-<TD ALIGN="CENTER">2.99</TD>
-</TR>
-<TR><TD ALIGN="CENTER">6</TD>
-<TD ALIGN="RIGHT">16384</TD>
-<TD ALIGN="CENTER">9.847e-04</TD>
-<TD ALIGN="CENTER">2.00</TD>
-<TD ALIGN="CENTER">1.986e-06</TD>
-<TD ALIGN="CENTER">7.99</TD>
-<TD ALIGN="CENTER">3.00</TD>
-</TR>
-</TABLE>
+Finally, the program also generated LaTeX versions of the tables (not shown
+here).
+
+
+<h3> Possible extensions </h3>
+
+<h4> Higher Order Elements </h4>
+
+Go ahead and run the program with higher order elements (Q3, Q4, ...). You
+will notice that assertions in several parts of the code will trigger (for
+example in the generation of the filename for the data output). After fixing
+these you will not see the correct convergence orders that the theory
+predicts. This is because the orders for the quadrature formulas are
+hard-coded in this program and this order is not enough for higher order
+discretizations. What is a good way to pick the orders dynamically?
+
+<h4> Convergence Comparison </h4>
+
+Is Q1 or Q2 better? What about adaptive versus global refinement? A (somewhat
+unfair but typical) metric to compare them, is to look at the error as a
+function of the number of unknowns.
+
+To see this, create a plot in log-log style with the number of unknowns on the
+x axis and the L2 error on the y axis. You can add reference lines for
+$h^2=N^{-1}$ and $h^3=N^{-3/2}$ and check that global and adaptive refinement
+follow those.
+
+Note that changing the half width of the peaks influences if adaptive or
+global refinement is more efficient (if the solution is very smooth, local
+refinement does not give any advantage over global refinement). Verify this.
+Finally, a more fair comparison would be to plot runtime (switch to release
+mode first!) instead of number of unknowns on the x axis. Picking a better
+linear solver might be appropriate though.
// concrete instantiation by substituting <code>dim</code> with a concrete
// value:
template <int dim>
- const double SolutionBase<dim>::width = 1./3.;
+ const double SolutionBase<dim>::width = 1./8.;
// <code>run()</code> function further below. (The default value of
// boundary indicators is <code>0</code>, so faces can only have an
// indicator equal to <code>1</code> if we have explicitly set it.)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary()
+ for (unsigned int face_number=0; face_number<GeometryInfo<dim>::faces_per_cell; ++face_number)
+ if (cell->face(face_number)->at_boundary()
&&
- (cell->face(face)->boundary_indicator() == 1))
+ (cell->face(face_number)->boundary_indicator() == 1))
{
// If we came into here, then we have found an external face
// belonging to Gamma2. Next, we have to compute the values of
// need for the computation of the contour integral. This is
// done using the <code>reinit</code> function which we already
// know from the FEValue class:
- fe_face_values.reinit (cell, face);
+ fe_face_values.reinit (cell, face_number);
// And we can then perform the integration by using a loop over
// all quadrature points.
// since we have Neumann boundary conditions on part of the boundaries, but
// since we don't have a function here that describes the Neumann values (we
// only construct these values from the exact solution when assembling the
- // matrix), we omit this detail even though they would not be hard to add.
+ // matrix), we omit this detail even though doing this in a strictly correct
+ // way would not be hard to add.
//
// At the end of the switch, we have a default case that looks slightly
// strange: an <code>Assert</code> statement with a <code>false</code>
{
Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
- typename FunctionMap<dim>::type neumann_boundary;
KellyErrorEstimator<dim>::estimate (dof_handler,
QGauss<dim-1>(3),
- neumann_boundary,
+ typename FunctionMap<dim>::type(),
solution,
estimated_error_per_cell);
template <int dim>
void HelmholtzProblem<dim>::run ()
{
- for (unsigned int cycle=0; cycle<7; ++cycle)
+ const unsigned int n_cycles = (refinement_mode==global_refinement)?5:9;
+ for (unsigned int cycle=0; cycle<n_cycles; ++cycle)
{
if (cycle == 0)
{
GridGenerator::hyper_cube (triangulation, -1, 1);
- triangulation.refine_global (1);
+ triangulation.refine_global (3);
typename Triangulation<dim>::cell_iterator
cell = triangulation.begin (),
endc = triangulation.end();
for (; cell!=endc; ++cell)
- for (unsigned int face=0;
- face<GeometryInfo<dim>::faces_per_cell;
- ++face)
- if ((std::fabs(cell->face(face)->center()(0) - (-1)) < 1e-12)
+ for (unsigned int face_number=0;
+ face_number<GeometryInfo<dim>::faces_per_cell;
+ ++face_number)
+ if ((std::fabs(cell->face(face_number)->center()(0) - (-1)) < 1e-12)
||
- (std::fabs(cell->face(face)->center()(1) - (-1)) < 1e-12))
- cell->face(face)->set_boundary_indicator (1);
+ (std::fabs(cell->face(face_number)->center()(1) - (-1)) < 1e-12))
+ cell->face(face_number)->set_boundary_indicator (1);
}
else
refine_grid ();
// After the last iteration we output the solution on the finest
// grid. This is done using the following sequence of statements which we
// have already discussed in previous examples. The first step is to
- // generate a suitable filename (called <code>gmv_filename</code> here,
- // since we want to output data in GMV format; we add the prefix to
+ // generate a suitable filename (called <code>vtk_filename</code> here,
+ // since we want to output data in VTK format; we add the prefix to
// distinguish the filename from that used for other output files further
// down below). Here, we augment the name by the mesh refinement
// algorithm, and as above we make sure that we abort the program if
// another refinement method is added and not handled by the following
// switch statement:
- std::string gmv_filename;
+ std::string vtk_filename;
switch (refinement_mode)
{
case global_refinement:
- gmv_filename = "solution-global";
+ vtk_filename = "solution-global";
break;
case adaptive_refinement:
- gmv_filename = "solution-adaptive";
+ vtk_filename = "solution-adaptive";
break;
default:
Assert (false, ExcNotImplemented());
switch (fe->degree)
{
case 1:
- gmv_filename += "-q1";
+ vtk_filename += "-q1";
break;
case 2:
- gmv_filename += "-q2";
+ vtk_filename += "-q2";
break;
default:
}
// Once we have the base name for the output file, we add an extension
- // appropriate for GMV output, open a file, and add the solution vector to
+ // appropriate for VTK output, open a file, and add the solution vector to
// the object that will do the actual output:
- gmv_filename += ".gmv";
- std::ofstream output (gmv_filename.c_str());
+ vtk_filename += ".vtk";
+ std::ofstream output (vtk_filename.c_str());
DataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
// way as above.
//
// With the intermediate format so generated, we can then actually write
- // the graphical output in GMV format:
+ // the graphical output:
data_out.build_patches (fe->degree);
- data_out.write_gmv (output);
+ data_out.write_vtk (output);
// @sect5{Output of convergence tables}
convergence_table
.evaluate_convergence_rates("L2", ConvergenceTable::reduction_rate_log2);
convergence_table
+ .evaluate_convergence_rates("H1", ConvergenceTable::reduction_rate);
+ convergence_table
.evaluate_convergence_rates("H1", ConvergenceTable::reduction_rate_log2);
// Each of these function calls produces an additional column that is
// merged with the original column (in our example the `L2' and the
std::cout << std::endl;
}
+ {
+ std::cout << "Solving with Q2 elements, adaptive refinement" << std::endl
+ << "===========================================" << std::endl
+ << std::endl;
+
+ FE_Q<dim> fe(2);
+ HelmholtzProblem<dim>
+ helmholtz_problem_2d (fe, HelmholtzProblem<dim>::adaptive_refinement);
+
+ helmholtz_problem_2d.run ();
+ std::cout << std::endl;
+ }
}
catch (std::exception &exc)
{
{
Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
- typename FunctionMap<dim>::type neumann_boundary;
KellyErrorEstimator<dim>::estimate (dof_handler,
QGauss<dim-1>(2),
- neumann_boundary,
+ typename FunctionMap<dim>::type(),
solution,
estimated_error_per_cell);
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: named_data.h 30036 2013-07-18 16:55:32Z maier $
+//
+// Copyright (C) 2000 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__any_data_h
+#define __deal2__any_data_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/subscriptor.h>
+
+#include <boost/any.hpp>
+#include <vector>
+#include <algorithm>
+#include <typeinfo>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * Store any amount of any type of data accessible by an identifier string.
+ *
+ * @todo Deprecate access by index after NamedData has been deprecated
+ * for long enough, then change to a map.
+ */
+class AnyData :
+ public Subscriptor
+{
+ public:
+ /// Number of stored data objects.
+ unsigned int size() const;
+
+ /// Add a new data object
+ template <typename type>
+ void add(type entry, const std::string& name);
+
+ /**
+ * @brief Merge the data of another NamedData to the end of this object.
+ */
+ void merge(const AnyData& other);
+
+ /**
+ * @brief Access to stored data object by name.
+ */
+ template <typename type>
+ type entry (const std::string& name);
+
+ /// Read-only access to stored data object by name.
+ template <typename type>
+ const type entry (const std::string& name) const;
+
+ /// Dedicated read only access by name.
+ template <typename type>
+ const type read (const std::string& name) const;
+
+ /**
+ * @brief Access to stored data object by index.
+ */
+ template <typename type>
+ type entry (const unsigned int i);
+
+ /// Read-only access to stored data object by index.
+ template <typename type>
+ const type entry (const unsigned int i) const;
+
+ /// Dedicated read only access.
+ template <typename type>
+ const type read (const unsigned int i) const;
+
+ /// Name of object at index.
+ const std::string &name(const unsigned int i) const;
+
+ /// Find index of a named object
+ unsigned int find(const std::string &name) const;
+
+ /// Find out if object is of a certain type
+ template <typename type>
+ bool is_type(const unsigned int i) const;
+
+ /// The requested type and the stored type are different
+ DeclException2(ExcTypeMismatch,
+ char*, char*,
+ << "The requested type " << arg1
+ << " and the stored type " << arg2
+ << " must coincide");
+
+ private:
+ /// The stored data
+ std::vector<boost::any> data;
+ /// The names of the stored data
+ std::vector<std::string> names;
+};
+
+
+unsigned int
+inline
+AnyData::size () const
+{
+ AssertDimension(data.size(), names.size());
+ return data.size();
+}
+
+
+template <typename type>
+inline
+type
+AnyData::entry (const unsigned int i)
+{
+ AssertIndexRange(i, size());
+ type* p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::entry (const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type* p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::read(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type* p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+inline
+const std::string&
+AnyData::name(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ return names[i];
+}
+
+
+inline
+unsigned int
+AnyData::find(const std::string& n) const
+{
+ typename std::vector<std::string>::const_iterator it =
+ std::find(names.begin(), names.end(), n);
+
+ Assert(it != names.end(), ExcMessage("An entry with this name does not exist"));
+
+ return it - names.begin();
+}
+
+
+template <typename type>
+inline
+bool
+AnyData::is_type(const unsigned int i) const
+{
+ return data[i].type() == typeid(type);
+}
+
+
+template <typename type>
+inline
+type
+AnyData::entry (const std::string& n)
+{
+ const unsigned int i = find(n);
+ type* p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::entry (const std::string& n) const
+{
+ const unsigned int i = find(n);
+ const type* p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::read(const std::string& n) const
+{
+ const unsigned int i = find(n);
+ const type* p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+void
+AnyData::add(type ent, const std::string& n)
+{
+ boost::any e = ent;
+ data.push_back(e);
+ names.push_back(n);
+}
+
+
+inline
+void
+AnyData::merge(const AnyData& other)
+{
+ for (unsigned int i=0; i<other.size(); ++i)
+ {
+ names.push_back(other.names[i]);
+ data.push_back(other.data[i]);
+ }
+}
+
+
+//----------------------------------------------------------------------//
+
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
#include <deal.II/base/smartpointer.h>
#include <deal.II/lac/solver_control.h>
#include <deal.II/algorithms/operator.h>
+#include <deal.II/algorithms/any_data.h>
DEAL_II_NAMESPACE_OPEN
* #inverse_derivative. It is up to this object to implement
* reassembling accordingly.
*
- * <h3>Contents of the NamedData objects</h3>
+ * <h3>Contents of the AnyData objects</h3>
*
* The only value used by the Newton method is the first vector in the
* parameter <tt>out</tt> of operator()(). It serves as the start
* down to the objects
* #residual and #inverse_derivative.
*/
- virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in);
+ virtual void operator() (AnyData &out, const AnyData &in);
+
+ /**
+ * @deprecated Use the function using AnyData
+ */
+ virtual void operator() (NamedData<VECTOR*> &out, const NamedData<VECTOR*> &in);
virtual void notify(const Event &);
template <class VECTOR>
void
Newton<VECTOR>::operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in)
+ {
+ Operator<VECTOR>::operator() (out, in);
+ }
+
+ template <class VECTOR>
+ void
+ Newton<VECTOR>::operator() (AnyData &out, const AnyData &in)
{
Assert (out.size() == 1, ExcNotImplemented());
deallog.push ("Newton");
- VECTOR &u = *out(0);
+ VECTOR &u = *out.entry<VECTOR*>(0);
if (debug>2)
deallog << "u: " << u.l2_norm() << std::endl;
typename VectorMemory<VECTOR>::Pointer res(mem);
res->reinit(u);
- NamedData<VECTOR *> src1;
- NamedData<VECTOR *> src2;
- VECTOR *p = &u;
- src1.add(p, "Newton iterate");
+ AnyData src1;
+ AnyData src2;
+ src1.add<const VECTOR*>(&u, "Newton iterate");
src1.merge(in);
- p = res;
- src2.add(p, "Newton residual");
+ src2.add<const VECTOR*>(res, "Newton residual");
src2.merge(src1);
- NamedData<VECTOR *> out1;
- out1.add(p, "Residual");
- p = Du;
- NamedData<VECTOR *> out2;
- out2.add(p, "Update");
+ AnyData out1;
+ out1.add<VECTOR*>(res, "Residual");
+ AnyData out2;
+ out2.add<VECTOR*>(Du, "Update");
unsigned int step = 0;
// fill res with (f(u), v)
#define __deal2__operator_h
#include <deal.II/base/config.h>
+#include <deal.II/algorithms/any_data.h>
#include <deal.II/base/named_data.h>
#include <deal.II/base/event.h>
namespace Algorithms
{
/**
+ * @todo Update this documentation and the one of Operator
+ *
* The abstract base class of all algorithms in this library. An
* operator is an object with an operator(), which transforms a set
* of named vectors into another set of named vectors.
* the innermost method in such a nested system will have to compute a
* residual using values from all outer iterations. Since the depth
* and order of such a nesting is hardly predictable when designing a
- * general tool, we use NamedData to access these vectors. Typically,
+ * general tool, we use AnyData to access these vectors. Typically,
* the first vector in <tt>out</tt> contains the start vector when
* operator()() is called, and the solution when the function
* returns. The object <tt>in</tt> is providing additional information
* and forwarded to the inner Operator objects of the nested
* iteration.
*
- * @author Guido Kanschat, 2010
+ * @author Guido Kanschat
+ * @date 2014
*/
- template <class VECTOR>
- class Operator : public Subscriptor
+ class OperatorBase : public Subscriptor
{
public:
/**
* The virtual destructor.
*/
- ~Operator();
+ ~OperatorBase();
/**
* The actual operation, which
* is implemented in a derived class.
*/
- virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in) = 0;
+ virtual void operator() (AnyData &out, const AnyData &in) = 0;
/**
* Register an event triggered
void clear_events();
protected:
/**
- * Accumulate reasons for
- * reassembling here. If any of
+ * Accumulate events here. If any of
* those is set, the function
* solve() of a terminal
* application must take care
* of reassembling the matrix.
*/
Event notifications;
+
+ };
+
+ /**
+ * @deprecated This class has been replaced by OperatorBase.
+ *
+ * The abstract base class of all algorithms in this library. An
+ * operator is an object with an operator(), which transforms a set
+ * of named vectors into another set of named vectors.
+ *
+ * Furthermore, an operator can be notified of parameter changes by
+ * the calling routine. The outer iteration can notify() the Operator
+ * of an Event, which could be for instance a change of mesh, a
+ * different time step size or too slow convergence of Newton's
+ * method, which would then trigger reassembling of a matrix or
+ * similar things.
+ *
+ * <h3>Usage for nested iterations</h3>
+ *
+ * This is probably the most prominent use for Operator, where an
+ * outer iterative method calls an inner solver and so on. Typically,
+ * the innermost method in such a nested system will have to compute a
+ * residual using values from all outer iterations. Since the depth
+ * and order of such a nesting is hardly predictable when designing a
+ * general tool, we use NamedData to access these vectors. Typically,
+ * the first vector in <tt>out</tt> contains the start vector when
+ * operator()() is called, and the solution when the function
+ * returns. The object <tt>in</tt> is providing additional information
+ * and forwarded to the inner Operator objects of the nested
+ * iteration.
+ *
+ * @author Guido Kanschat, 2010
+ */
+ template <class VECTOR>
+ class Operator : public OperatorBase
+ {
+ public:
+ Operator();
+
+ /**
+ * Implementation of the function in the base class in order to do
+ * compatibility conversions between the old and the new
+ * interface.
+ */
+ virtual void operator() (AnyData &out, const AnyData &in);
+
+ /**
+ * @deprecated It is in particular this function which should not be used anymore.
+ *
+ * The actual operation, which
+ * is implemented in a derived class.
+ */
+ virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in);
+
+ private:
+ /**
+ * While we are providing compatibility functions to the old
+ * interface, this variable will ensure there is no endless loop.
+ */
+ bool compatibility_flag;
};
/**
OutputOperator<VECTOR> &operator<< (unsigned int step);
/**
- * Output all the vectors in NamedData.
+ * Output all the vectors in AnyData.
+ */
+ virtual OutputOperator<VECTOR> &operator<< (const AnyData& vectors);
+
+ /**
+ * @deprecated Output all the vectors in NamedData.
*/
virtual OutputOperator<VECTOR> &operator<< (const NamedData<VECTOR *> &vectors);
protected:
#include <deal.II/algorithms/operator.h>
+#include <deal.II/base/logstream.h>
DEAL_II_NAMESPACE_OPEN
namespace Algorithms
{
template <class VECTOR>
- Operator<VECTOR>::~Operator()
+ Operator<VECTOR>::Operator()
+ : compatibility_flag(false)
{}
-
template <class VECTOR>
- void Operator<VECTOR>::notify(const Event &e)
+ void
+ Operator<VECTOR>::operator() (AnyData& out, const AnyData& in)
{
- notifications += e;
+ // Had this function been overloaded in a derived clas, it would
+ // not have been called. Therefore, we have to start the
+ // compatibility engine. But before, we have to avoid an endless loop.
+ Assert(!compatibility_flag, ExcMessage("Compatibility resolution of Operator generates and endless loop\n"
+ "Please provide an operator() in a derived class"));
+ compatibility_flag = true;
+
+ NamedData<VECTOR*> new_out;
+ for (unsigned int i=0;i<out.size();++i)
+ {
+ if (out.is_type<VECTOR*>(i))
+ new_out.add(out.entry<VECTOR*>(i), out.name(i));
+ else
+ deallog << "Cannot convert AnyData argument " << out.name(i) << " to NamedData"
+ << std::endl;
+ }
+
+ NamedData<VECTOR*> new_in;
+ for (unsigned int i=0;i<in.size();++i)
+ {
+ // deallog << "Convert " << in.name(i) << std::endl;
+ if (in.is_type<VECTOR*>(i))
+ {
+ // This const cast is due to the wrong constness handling
+ // in NamedData. As soon as NamedData is gone, this code
+ // will not be necessary anymore. And deprecating begins
+ // now.
+ VECTOR* p = const_cast<VECTOR*> (in.entry<VECTOR*>(i));
+ new_in.add(p, in.name(i));
+ }
+ else if (in.is_type<const VECTOR*>(i))
+ {
+ // This const cast is due to the wrong constness handling
+ // in NamedData. As soon as NamedData is gone, this code
+ // will not be necessary anymore. And deprecating begins
+ // now.
+ VECTOR* p = const_cast<VECTOR*> (in.entry<const VECTOR*>(i));
+ new_in.add(p, in.name(i));
+ }
+ else
+ deallog << "Cannot convert AnyData argument " << in.name(i)
+ << " to NamedData" << std::endl;
+ }
+ this->operator() (new_out, new_in);
+ compatibility_flag = false;
}
template <class VECTOR>
void
- Operator<VECTOR>::clear_events ()
+ Operator<VECTOR>::operator() (NamedData<VECTOR*>& out, const NamedData<VECTOR*>& in)
{
- notifications.clear();
+ // Had this function been overloaded in a derived clas, it would
+ // not have been called. Therefore, we have to start the
+ // compatibility engine. But before, we have to avoid an endless loop.
+ Assert(!compatibility_flag, ExcMessage("Compatibility resolution of Operator generates and endless loop\n"
+ "Please provide an operator() in a derived class"));
+ compatibility_flag = true;
+
+ AnyData new_out;
+ for (unsigned int i=0;i<out.size();++i)
+ new_out.add(out(i), out.name(i));
+
+ AnyData new_in;
+ for (unsigned int i=0;i<in.size();++i)
+ new_in.add(in(i), in.name(i));
+
+ this->operator() (new_out, new_in);
+ compatibility_flag = false;
}
os =&stream;
}
+ template <class VECTOR>
+ OutputOperator<VECTOR> &
+ OutputOperator<VECTOR>::operator<< (const AnyData& vectors)
+ {
+ if (os == 0)
+ {
+ //TODO: make this possible
+ //deallog << ' ' << step;
+ //for (unsigned int i=0;i<vectors.size();++i)
+ // vectors(i)->print(deallog);
+ //deallog << std::endl;
+ }
+ else
+ {
+ (*os) << ' ' << step;
+ for (unsigned int i=0; i<vectors.size(); ++i)
+ {
+ if (vectors.is_type<VECTOR*>(i))
+ {
+ const VECTOR& v = *vectors.entry<VECTOR*>(i);
+ for (unsigned int j=0; j<v.size(); ++j)
+ (*os) << ' ' << v(j);
+ }
+ else if (vectors.is_type<const VECTOR*>(i))
+ {
+ const VECTOR& v = *vectors.entry<const VECTOR*>(i);
+ for (unsigned int j=0; j<v.size(); ++j)
+ (*os) << ' ' << v(j);
+ }
+ }
+ (*os) << std::endl;
+ }
+ return *this;
+ }
+
+
template <class VECTOR>
OutputOperator<VECTOR> &
OutputOperator<VECTOR>::operator<< (const NamedData<VECTOR *> &vectors)
* should contain the initial
* value in first position. <tt>out</tt>
*/
+ virtual void operator() (AnyData &out, const AnyData &in);
+
+ /**
+ * @deprecated Use the function with AnyData arguments
+ */
virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in);
/**
virtual void notify(const Event &);
/**
- * Define an operator which
- * will output the result in
- * each step. Note that no
- * output will be generated
- * without this.
+ * Define an operator which will output the result in each
+ * step. Note that no output will be generated without this.
*/
void set_output(OutputOperator<VECTOR> &output);
*/
const double &step_size() const;
/**
- * The weight between implicit
- * and explicit part.
+ * The weight between implicit and explicit part.
*/
const double &theta() const;
/**
- * The data handed to the
- * #op_explicit time stepping
- * operator.
+ * The data handed to the #op_explicit time stepping operator.
*
- * The time in here is the time
- * at the beginning of the
- * current step, the time step
- * is (1-#theta) times the
- * actual time step.
+ * The time in here is the time at the beginning of the current
+ * step, the time step is (1-#theta) times the actual time step.
*/
const TimestepData &explicit_data() const;
/**
- * The data handed to the
- * #op_implicit time stepping
- * operator.
+ * The data handed to the #op_implicit time stepping operator.
*
- * The time in here is the time
- * at the beginning of the
- * current step, the time step
- * is #theta times the
- * actual time step.
+ * The time in here is the time at the beginning of the current
+ * step, the time step is #theta times the actual time step.
*/
const TimestepData &implicit_data() const;
private:
/**
- * The object controlling the
- * time step size and computing
- * the new time in each step.
+ * The object controlling the time step size and computing the new
+ * time in each step.
*/
TimestepControl control;
/**
- * The control parameter theta in the
- * range <tt>[0,1]</tt>.
+ * The control parameter theta in the range <tt>[0,1]</tt>. It
+ * defaults to 0.5.
*/
double vtheta;
/**
- * Use adaptive #theta if
- * <tt>true</tt>.
+ * Use adaptive #theta if <tt>true</tt>. Not yet implemented.
*/
bool adaptive;
/**
- * The data for the explicit
- * part of the scheme.
+ * The data for the explicit part of the scheme.
*/
TimestepData d_explicit;
/**
- * The data for the implicit
- * part of the scheme.
+ * The data for the implicit part of the scheme.
*/
TimestepData d_implicit;
/**
- * The operator computing the
- * explicit part of the
- * scheme. This will receive in
- * its input data the value at
- * the current time with name
- * "Current time solution". It
- * should obtain the current
- * time and time step size from
- * explicit_data().
+ * The operator computing the explicit part of the scheme. This
+ * will receive in its input data the value at the current time
+ * with name "Current time solution". It should obtain the current
+ * time and time step size from explicit_data().
*
- * Its return value is
- * <i>Mu+cAu</i>, where
- * <i>u</i> is the current
- * state vector, <i>M</i> the
- * mass matrix, <i>A</i> the
- * operator in space and
- * <i>c</i> is the time step
- * size in explicit_data().
+ * Its return value is <i>Mu+cAu</i>, where <i>u</i> is the
+ * current state vector, <i>M</i> the mass matrix, <i>A</i> the
+ * operator in space and <i>c</i> is the time step size in
+ * explicit_data().
*/
SmartPointer<Operator<VECTOR>, ThetaTimestepping<VECTOR> > op_explicit;
/**
- * The operator solving the
- * implicit part of the
- * scheme. It will receive in
- * its input data the vector
- * "Previous time". Information on the
- * timestep should be obtained
- * from implicit_data().
+ * The operator solving the implicit part of the scheme. It will
+ * receive in its input data the vector "Previous
+ * time". Information on the timestep should be obtained from
+ * implicit_data().
*
- * Its return value is the
- * solution <i>u</i> of
- * <i>Mu-cAu=f</i>, where
- * <i>f</i> is the dual space
- * vector found in the
- * "Previous time" entry of the
- * input data, <i>M</i> the
- * mass matrix, <i>A</i> the
- * operator in space and
- * <i>c</i> is the time step
+ * Its return value is the solution <i>u</i> of <i>Mu-cAu=f</i>,
+ * where <i>f</i> is the dual space vector found in the "Previous
+ * time" entry of the input data, <i>M</i> the mass matrix,
+ * <i>A</i> the operator in space and <i>c</i> is the time step
* size in explicit_data().
*/
SmartPointer<Operator<VECTOR>, ThetaTimestepping<VECTOR> > op_implicit;
/**
- * The operator writing the
- * output in each time step
+ * The operator writing the output in each time step
*/
SmartPointer<OutputOperator<VECTOR>, ThetaTimestepping<VECTOR> > output;
};
return d_implicit;
}
+
+ template <class VECTOR>
+ inline
+ TimestepControl &
+ ThetaTimestepping<VECTOR>::timestep_control ()
+ {
+ return control;
+ }
+
template <class VECTOR>
inline
void ThetaTimestepping<VECTOR>::set_output (OutputOperator<VECTOR> &out)
template <class VECTOR>
void
ThetaTimestepping<VECTOR>::operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in)
+ {
+ Operator<VECTOR>::operator() (out, in);
+ }
+
+
+ template <class VECTOR>
+ void
+ ThetaTimestepping<VECTOR>::operator() (AnyData &out, const AnyData &in)
{
Assert(!adaptive, ExcNotImplemented());
deallog.push ("Theta");
+
+ VECTOR& solution = *out.entry<VECTOR*>(0);
GrowingVectorMemory<VECTOR> mem;
typename VectorMemory<VECTOR>::Pointer aux(mem);
- aux->reinit(*out(0));
+ aux->reinit(solution);
control.restart();
// The data used to compute the
// vector associated with the old
// timestep
- VECTOR *p = out(0);
- NamedData<VECTOR *> src1;
- src1.add(p, "Previous iterate");
+ AnyData src1;
+ src1.add<const VECTOR*>(&solution, "Previous iterate");
src1.merge(in);
- NamedData<VECTOR *> src2;
- src2.add(p, "Previous iterate");
+ AnyData src2;
+ src2.add<const VECTOR*>(&solution, "Previous iterate");
- p = aux;
- NamedData<VECTOR *> out1;
- out1.add(p, "Result");
- // The data provided to the inner
- // solver
- src2.add(p, "Previous time");
+ AnyData out1;
+ out1.add<VECTOR*>(aux, "Solution");
+ // The data provided to the inner solver
+ src2.add<const VECTOR*>(aux, "Previous time");
src2.merge(in);
if (output != 0)
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef __deal2__aligned_vector_h
+#define __deal2__aligned_vector_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/std_cxx1x/type_traits.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/memory_consumption.h>
+#include <deal.II/base/parallel.h>
+
+#include <cstring>
+
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+#include <mm_malloc.h>
+#endif
+
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * This is a replacement class for std::vector to be used in combination with
+ * VectorizedArray and derived data types. It allocates memory aligned to
+ * addresses of a vectorized data type (in order to avoid segmentation faults
+ * when a variable of type VectorizedArray which the compiler assumes to be
+ * aligned to certain memory addresses does not actually follow these
+ * rules). This could also be achieved by proving std::vector with a
+ * user-defined allocator. On the other hand, writing an own small vector
+ * class lets us implement parallel copy and move operations with TBB, insert
+ * deal.II-style assertions, and cut some unnecessary functionality. Note that
+ * this vector is a bit more memory-consuming than std::vector because of
+ * alignment, so it is recommended to only use this vector on long vectors.
+ *
+ * @p author Katharina Kormann, Martin Kronbichler, 2011
+ */
+template < class T >
+class AlignedVector
+{
+public:
+ /**
+ * Declare standard types used in all containers. These types parallel those
+ * in the <tt>C++</tt> standard libraries <tt>vector<...></tt> class.
+ */
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type *iterator;
+ typedef const value_type *const_iterator;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef std::size_t size_type;
+
+ /**
+ * Empty constructor. Sets the vector size to zero.
+ */
+ AlignedVector ();
+
+ /**
+ * Sets the vector size to the given size and initializes all elements with
+ * T().
+ */
+ AlignedVector (const size_type size,
+ const T &init = T());
+
+ /**
+ * Destructor.
+ */
+ ~AlignedVector ();
+
+ /**
+ * Copy constructor.
+ */
+ AlignedVector (const AlignedVector<T> &vec);
+
+ /**
+ * Assignment to the input vector @p vec.
+ */
+ AlignedVector &
+ operator = (const AlignedVector<T> &vec);
+
+ /**
+ * Change the size of the vector. It keeps old elements previously available
+ * but does not initialize the newly allocated memory, leaving it in an
+ * undefined state.
+ */
+ void resize_fast (const size_type size);
+
+ /**
+ * Change the size of the vector. It keeps old elements previously
+ * available, and initializes each element with the specified data. If the
+ * new vector size is shorter than the old one, the memory is not released
+ * unless the new size is zero.
+ */
+ void resize (const size_type size_in,
+ const T &init = T());
+
+ /**
+ * Reserve memory space for @p size elements. If the argument @p size is set
+ * to zero, all previously allocated memory is released.
+ *
+ * In order to avoid too frequent reallocation (which involves copy of the
+ * data), this function doubles the amount of memory occupied when the given
+ * size is larger than the previously allocated size.
+ */
+ void reserve (const size_type size_alloc);
+
+ /**
+ * Releases all previously allocated memory and leaves the vector in a state
+ * equivalent to the state after the default constructor has been called.
+ */
+ void clear ();
+
+ /**
+ * Inserts an element at the end of the vector, increasing the vector size
+ * by one. Note that the allocated size will double whenever the previous
+ * space is not enough to hold the new element.
+ */
+ void push_back (const T in_data);
+
+ /**
+ * Returns the last element of the vector (read and write access).
+ */
+ reference back ();
+
+ /**
+ * Returns the last element of the vector (read-only access).
+ */
+ const_reference back () const;
+
+ /**
+ * Inserts several elements at the end of the vector given by a range of
+ * elements.
+ */
+ template <typename ForwardIterator>
+ void insert_back (ForwardIterator begin,
+ ForwardIterator end);
+
+ /**
+ * Swaps the given vector with the calling vector.
+ */
+ void swap (AlignedVector<T> &vec);
+
+ /**
+ * Returns whether the vector is empty, i.e., its size is zero.
+ */
+ bool empty () const;
+
+ /**
+ * Returns the size of the vector.
+ */
+ size_type size () const;
+
+ /**
+ * Returns the capacity of the vector, i.e., the size this vector can hold
+ * without reallocation. Note that capacity() >= size().
+ */
+ size_type capacity () const;
+
+ /**
+ * Read-write access to entry @p index in the vector.
+ */
+ reference
+ operator [] (const size_type index);
+
+ /**
+ * Read-only access to entry @p index in the vector.
+ */
+ const_reference operator [] (const size_type index) const;
+
+ /**
+ * Returns a read and write pointer to the beginning of the data array.
+ */
+ iterator begin ();
+
+ /**
+ * Returns a read and write pointer to the end of the data array.
+ */
+ iterator end ();
+
+ /**
+ * Returns a read-only pointer to the beginning of the data array.
+ */
+ const_iterator begin () const;
+
+ /**
+ * Returns a read-only pointer to the end of the data array.
+ */
+ const_iterator end () const;
+
+ /**
+ * Returns the memory consumption of the allocated memory in this class. If
+ * the underlying type @p T allocates memory by itself, this memory is not
+ * counted.
+ */
+ size_type memory_consumption () const;
+
+private:
+
+ /**
+ * Pointer to actual class data.
+ */
+ T *_data;
+
+ /**
+ * Pointer to the end of valid data fields.
+ */
+ T *_end_data;
+
+ /**
+ * Pointer to the end of the allocated memory.
+ */
+ T *_end_allocated;
+};
+
+
+// ------------------------------- inline functions --------------------------
+
+/**
+ * This namespace defines the copy and set functions used in
+ * AlignedVector. These functions operate in parallel when there are enough
+ * elements in the vector.
+ */
+namespace internal
+{
+ /**
+ * Move and class that actually issues the copy commands in
+ * AlignedVector. This class is based on the specialized for loop base class
+ * ParallelForLoop in parallel.h whose purpose is the following: When
+ * calling a parallel for loop on AlignedVector with apply_to_subranges, it
+ * generates different code for every different argument we might choose (as
+ * it is templated). This gives a lot of code (e.g. it triples the memory
+ * required for compiling the file matrix_free.cc and the final object size
+ * is several times larger) which is completely useless. Therefore, this
+ * class channels all copy commands through one call to apply_to_subrange
+ * for all possible types, which makes the copy operation much cleaner
+ * (thanks to a virtual function, whose cost is negligible in this context).
+ *
+ * @relates AlignedVector
+ */
+ template <typename T>
+ class AlignedVectorMove : private parallel::ParallelForInteger
+ {
+ static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
+ public:
+ /**
+ * Constructor. Issues a parallel call if there are sufficiently many
+ * elements, otherwise work in serial. Copies the data from source to
+ * destination and then calls destructor on the source. If the optional
+ * argument is set to true, the source is left untouched instead.
+ */
+ AlignedVectorMove (T *source_begin,
+ T *source_end,
+ T *destination,
+ bool copy_only = false)
+ :
+ source_ (source_begin),
+ destination_ (destination),
+ copy_only_ (copy_only)
+ {
+ Assert (source_end >= source_begin, ExcInternalError());
+ const std::size_t size = source_end - source_begin;
+ if (size < minimum_parallel_grain_size)
+ apply_to_subrange (0, size);
+ else
+ apply_parallel (0, size, minimum_parallel_grain_size);
+ }
+
+ /**
+ * This method moves elements from the source to the destination given in
+ * the constructor on a subrange given by two integers.
+ */
+ virtual void apply_to_subrange (const std::size_t begin,
+ const std::size_t end) const
+ {
+ // for classes trivial assignment can use memcpy. cast element to
+ // (void*) to silence compiler warning for virtual classes (they will
+ // never arrive here because they are non-trivial).
+
+ if (std_cxx1x::is_trivial<T>::value == true)
+ std::memcpy ((void*)(destination_+begin), source_+begin,
+ (end-begin)*sizeof(T));
+ else if (copy_only_ == false)
+ for (std::size_t i=begin; i<end; ++i)
+ {
+ // initialize memory (copy construct), and destruct
+ new (&destination_[i]) T(source_[i]);
+ source_[i].~T();
+ }
+ else
+ for (std::size_t i=begin; i<end; ++i)
+ {
+ new (&destination_[i]) T(source_[i]);
+ }
+ }
+
+ private:
+ T *source_;
+ T *destination_;
+ const bool copy_only_;
+ };
+
+ /**
+ * Class that issues the set commands for AlignedVector.
+ *
+ * @relates AlignedVector
+ */
+ template <typename T>
+ class AlignedVectorSet : private parallel::ParallelForInteger
+ {
+ static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
+ public:
+ /**
+ * Constructor. Issues a parallel call if there are sufficiently many
+ * elements, otherwise work in serial.
+ */
+ AlignedVectorSet (const std::size_t size,
+ const T &element,
+ T *destination)
+ :
+ element_ (element),
+ destination_ (destination),
+ trivial_element (false)
+ {
+ if (size == 0)
+ return;
+
+ if (std_cxx1x::is_trivial<T>::value == true)
+ {
+ const unsigned char zero [sizeof(T)] = {};
+ // cast element to (void*) to silence compiler warning for virtual
+ // classes (they will never arrive here because they are
+ // non-trivial).
+ if (std::memcmp(zero, (void*)&element, sizeof(T)) == 0)
+ trivial_element = true;
+ }
+ if (size < minimum_parallel_grain_size)
+ apply_to_subrange (0, size);
+ else
+ apply_parallel (0, size, minimum_parallel_grain_size);
+ }
+
+ private:
+
+ /**
+ * This sets elements on a subrange given by two integers.
+ */
+ virtual void apply_to_subrange (const std::size_t begin,
+ const std::size_t end) const
+ {
+ // for classes with trivial assignment of zero can use memset. cast
+ // element to (void*) to silence compiler warning for virtual
+ // classes (they will never arrive here because they are
+ // non-trivial).
+ if (std_cxx1x::is_trivial<T>::value == true && trivial_element)
+ std::memset ((void*)(destination_+begin), 0, (end-begin)*sizeof(T));
+ else
+ // initialize memory and set
+ for (std::size_t i=begin; i<end; ++i)
+ new (&destination_[i]) T(element_);
+ }
+
+ const T &element_;
+ mutable T *destination_;
+ bool trivial_element;
+ };
+} // end of namespace internal
+
+
+#ifndef DOXYGEN
+
+
+template < class T >
+inline
+AlignedVector<T>::AlignedVector ()
+ :
+ _data (0),
+ _end_data (0),
+ _end_allocated (0)
+{}
+
+
+
+template < class T >
+inline
+AlignedVector<T>::AlignedVector (const size_type size,
+ const T &init)
+ :
+ _data (0),
+ _end_data (0),
+ _end_allocated (0)
+{
+ if (size > 0)
+ resize (size, init);
+}
+
+
+
+template < class T >
+inline
+AlignedVector<T>::~AlignedVector ()
+{
+ clear();
+}
+
+
+
+template < class T >
+inline
+AlignedVector<T>::AlignedVector (const AlignedVector<T> &vec)
+ :
+ _data (0),
+ _end_data (0),
+ _end_allocated (0)
+{
+ // do not invalidate old data
+ resize_fast (vec._end_data - vec._data);
+ internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
+}
+
+
+
+template < class T >
+inline
+AlignedVector<T>&
+AlignedVector<T>::operator = (const AlignedVector<T> &vec)
+{
+ clear();
+ resize_fast (vec._end_data - vec._data);
+ internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
+ return *this;
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::resize_fast (const size_type size)
+{
+ reserve (size);
+ _end_data = _data + size;
+}
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::resize (const size_type size_in,
+ const T &init)
+{
+ const size_type old_size = size();
+ if (std_cxx1x::is_trivial<T>::value == false && size_in < old_size)
+ {
+ // call destructor on fields that are released
+ while (_end_data != _data+size_in)
+ (--_end_data)->~T();
+ }
+
+ resize_fast (size_in);
+ // now _size is set correctly, need to set the
+ // values
+ if (size_in > old_size)
+ internal::AlignedVectorSet<T> (size_in-old_size, init,
+ _data+old_size);
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::reserve (const size_type size_alloc)
+{
+ const size_type old_size = _end_data - _data;
+ const size_type allocated_size = _end_allocated - _data;
+ if (size_alloc > allocated_size)
+ {
+ // if we continuously increase the size of the vector, we might be
+ // reallocating a lot of times. therefore, try to increase the size more
+ // aggressively
+ size_type new_size = size_alloc;
+ if (size_alloc < (2 * allocated_size))
+ new_size = 2 * allocated_size;
+
+ const size_type size_actual_allocate = new_size * sizeof(T);
+
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+
+ // allocate and align along 64-byte boundaries (this is enough for all
+ // levels of vectorization currently supported by deal.II)
+ T *new_data = static_cast<T *>(_mm_malloc (size_actual_allocate, 64));
+#else
+ T *new_data = static_cast<T *>(malloc (size_actual_allocate));
+#endif
+ if (new_data == 0)
+ throw std::bad_alloc();
+
+ // copy data in case there was some content before and release the old
+ // memory with the function corresponding to the one used for allocating
+ std::swap (_data, new_data);
+ _end_data = _data + old_size;
+ _end_allocated = _data + new_size;
+ if (_end_data != _data)
+ {
+ internal::AlignedVectorMove<T>(new_data, new_data + old_size,
+ _data);
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+ _mm_free(new_data);
+#else
+ free(new_data);
+#endif
+ }
+ }
+ else if (size_alloc == 0)
+ clear();
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::clear ()
+{
+ if (_data != 0)
+ {
+ if (std_cxx1x::is_trivial<T>::value == false)
+ while (_end_data != _data)
+ (--_end_data)->~T();
+
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+ _mm_free(_data);
+#else
+ free(_data);
+#endif
+ }
+ _data = 0;
+ _end_data = 0;
+ _end_allocated = 0;
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::push_back (const T in_data)
+{
+ Assert (_end_data <= _end_allocated, ExcInternalError());
+ if (_end_data == _end_allocated)
+ reserve (std::max(2*capacity(),static_cast<size_type>(16)));
+ if (std_cxx1x::is_trivial<T>::value == false)
+ new (_end_data) T;
+ *_end_data++ = in_data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::reference
+AlignedVector<T>::back ()
+{
+ AssertIndexRange (0, size());
+ T *field = _end_data - 1;
+ return *field;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_reference
+AlignedVector<T>::back () const
+{
+ AssertIndexRange (0, size());
+ const T *field = _end_data - 1;
+ return *field;
+}
+
+
+
+template < class T >
+template <typename ForwardIterator>
+inline
+void
+AlignedVector<T>::insert_back (ForwardIterator begin,
+ ForwardIterator end)
+{
+ const unsigned int old_size = size();
+ reserve (old_size + (end-begin));
+ for ( ; begin != end; ++begin, ++_end_data)
+ {
+ if (std_cxx1x::is_trivial<T>::value == false)
+ new (_end_data) T;
+ *_end_data = *begin;
+ }
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::swap (AlignedVector<T> &vec)
+{
+ std::swap (_data, vec._data);
+ std::swap (_end_data, vec._end_data);
+ std::swap (_end_allocated, vec._end_allocated);
+}
+
+
+
+template < class T >
+inline
+bool
+AlignedVector<T>::empty () const
+{
+ return _end_data == _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::size_type
+AlignedVector<T>::size () const
+{
+ return _end_data - _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::size_type
+AlignedVector<T>::capacity () const
+{
+ return _end_allocated - _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::reference
+AlignedVector<T>::operator [] (const size_type index)
+{
+ AssertIndexRange (index, size());
+ return _data[index];
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_reference
+AlignedVector<T>::operator [] (const size_type index) const
+{
+ AssertIndexRange (index, size());
+ return _data[index];
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::iterator
+AlignedVector<T>::begin ()
+{
+ return _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::iterator
+AlignedVector<T>::end ()
+{
+ return _end_data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_iterator
+AlignedVector<T>::begin () const
+{
+ return _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_iterator
+AlignedVector<T>::end () const
+{
+ return _end_data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::size_type
+AlignedVector<T>::memory_consumption () const
+{
+ size_type memory = sizeof(this);
+ memory += sizeof(T) * capacity();
+ return memory;
+}
+
+
+#endif // ifndef DOXYGEN
+
+
+/**
+ * Relational operator == for AlignedVector
+ *
+ * @relates AlignedVector
+ */
+template < class T >
+bool operator == (const AlignedVector<T> &lhs,
+ const AlignedVector<T> &rhs)
+{
+ if (lhs.size() != rhs.size())
+ return false;
+ for (typename AlignedVector<T>::const_iterator lit = lhs.begin(),
+ rit = rhs.begin(); lit != lhs.end(); ++lit, ++rit)
+ if (*lit != *rit)
+ return false;
+ return true;
+}
+
+
+
+
+/**
+ * Relational operator != for AlignedVector
+ *
+ * @relates AlignedVector
+ */
+template < class T >
+bool operator != (const AlignedVector<T> &lhs,
+ const AlignedVector<T> &rhs)
+{
+ return !(operator==(lhs, rhs));
+}
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
* Configured in setup_deal_ii.cmake: *
**************************************/
-/* Defined to the full name of this package. */
+/** Defined to the full name of this package. */
#define DEAL_II_PACKAGE_NAME "@DEAL_II_PACKAGE_NAME@"
-/* Defined to the version of this package. */
+/** Defined to the version of this package. */
#define DEAL_II_PACKAGE_VERSION "@DEAL_II_PACKAGE_VERSION@"
-/* Major version number of deal.II */
+/** Major version number of deal.II */
#define DEAL_II_VERSION_MAJOR @DEAL_II_VERSION_MAJOR@
#define DEAL_II_MAJOR @DEAL_II_VERSION_MAJOR@
-/* Minor version number of deal.II */
+/** Minor version number of deal.II */
#define DEAL_II_VERSION_MINOR @DEAL_II_VERSION_MINOR@
#define DEAL_II_MINOR @DEAL_II_VERSION_MINOR@
* Configured in check_1_compiler_features: *
********************************************/
-/* Defined if the compiler can use arithmetic operations on vectorized data types */
+/** Defined if the compiler can use arithmetic operations on vectorized data types */
#cmakedefine DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
-/* Defined if vector iterators are just plain pointers */
+/** Defined if vector iterators are just plain pointers */
#cmakedefine DEAL_II_VECTOR_ITERATOR_IS_POINTER
-/* Define if the compiler provides __builtin_expect */
+/** Define if the compiler provides __builtin_expect */
#cmakedefine HAVE_BUILTIN_EXPECT
-/* Define if the compiler provides __verbose_terminate_handler */
+/** Define if the compiler provides __verbose_terminate_handler */
#cmakedefine HAVE_VERBOSE_TERMINATE
-/* Define if deal.II is linked against a libc that provides stacktrace
+/** Define if deal.II is linked against a libc that provides stacktrace
* debug information that can be printed out in the exception class
* */
#cmakedefine HAVE_GLIBC_STACKTRACE
-/* Defined if the std c++ library provides a demangler conforming to the
+/** Defined if the std c++ library provides a demangler conforming to the
* GCC libstdc++ interface.
*/
#cmakedefine HAVE_LIBSTDCXX_DEMANGLER
-/* If already available, do not define at all. Otherwise, define to
+/** If already available, do not define at all. Otherwise, define to
* __func__ if that is available. In all other cases, indicate that no
* information about the present function is available for this compiler.
*/
#cmakedefine __PRETTY_FUNCTION__ @__PRETTY_FUNCTION__@
-/* If the compiler supports it, then this variable is defined to a string
+/** If the compiler supports it, then this variable is defined to a string
* that when written after a function name makes the compiler emit a warning
* whenever this function is used somewhere that its use is deprecated.
*/
* Configured in check_1_cpu_features: *
***************************************/
-/* Defined if the system stores words with the most significant byte first */
+/** Defined if the system stores words with the most significant byte first */
#cmakedefine DEAL_II_WORDS_BIGENDIAN
-/* Equal to 0 in the generic case, equal to 1 if CPU compiled for supports
+/** Equal to 0 in the generic case, equal to 1 if CPU compiled for supports
* SSE2, equal to 2 if CPU compiled for supports AVX
*/
#define DEAL_II_COMPILER_VECTORIZATION_LEVEL @DEAL_II_COMPILER_VECTORIZATION_LEVEL@
* Configured in check_1_cxx_features: *
***************************************/
-/* Defined if the compiler we use supports the C++2011 standard well enough
+/** Defined if the compiler we use supports the C++2011 standard well enough
* to allow using the standard library classes instead of the corresponding
* BOOST classes.
*/
#cmakedefine DEAL_II_WITH_CXX11
#ifdef DEAL_II_WITH_CXX11
-/* Compatibility definition (with naming from deal.II 8.0): */
+/** Compatibility definition (with naming from deal.II 8.0): */
# define DEAL_II_USE_CXX11
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_CAN_USE_CXX11
# define DEAL_II_CAN_USE_CXX1X
#endif
-/* Defined if C++11 is enabled and the standard library supports
+/** Defined if C++11 is enabled and the standard library supports
* template<typename T> std::is_trivially_copyable<T>
*/
#cmakedefine DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE
-/* Defined if isnan is available */
+/** Defined if isnan is available */
#cmakedefine HAVE_ISNAN
-/* Defined if _isnan is available */
+/** Defined if _isnan is available */
#cmakedefine HAVE_UNDERSCORE_ISNAN
-/* Defined if std::isfinite is available */
+/** Defined if std::isfinite is available */
#cmakedefine DEAL_II_HAVE_ISFINITE
* Configured in check_1_system_features: *
******************************************/
-/* Defined if you have the <sys/resource.h> header file */
+/** Defined if you have the <sys/resource.h> header file */
#cmakedefine HAVE_SYS_RESOURCE_H
-/* Defined if you have the <sys/time.h> header file. */
+/** Defined if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H
-/* Defined if you have the <sys/times.h> header file. */
+/** Defined if you have the <sys/times.h> header file. */
#cmakedefine HAVE_SYS_TIMES_H
-/* Defined if you have the <sys/types.h> header file. */
+/** Defined if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H
-/* Defined if you have the <unistd.h> header file. */
+/** Defined if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H
-/* Defined if you have the "gethostname" function. */
+/** Defined if you have the "gethostname" function. */
#cmakedefine HAVE_GETHOSTNAME
-/* Defined if you have the "getpid' function. */
+/** Defined if you have the "getpid' function. */
#cmakedefine HAVE_GETPID
-/* Defined if you have the "rand_r" function */
+/** Defined if you have the "rand_r" function */
#cmakedefine HAVE_RAND_R
-/* Defined if you have the "times" function. */
+/** Defined if you have the "times" function. */
#cmakedefine HAVE_TIMES
-/* Defined if you have the "jn" function. */
+/** Defined if you have the "jn" function. */
#cmakedefine HAVE_JN
-/* Defined if deal.II was configured on a native Windows platform. */
+/** Defined if deal.II was configured on a native Windows platform. */
#cmakedefine DEAL_II_MSVC
-/* Disable a bunch of warnings for Microsoft Visual C++. */
+/** Disable a bunch of warnings for Microsoft Visual C++. */
#ifdef _MSC_VER
# pragma warning( disable : 4244 ) /* implied downcasting from double to float */
# pragma warning( disable : 4267 ) /* implied downcasting from size_t to unsigned int */
# pragma warning( disable : 4789 ) /* destination of memory copy is too small */
# pragma warning( disable : 4808 ) /* case 'value' is not a valid value for switch condition of type 'bool */
-/* Also make sure we don't let MS Windows headers define min/max as
+/** Also make sure we don't let MS Windows headers define min/max as
macros, see http://support.microsoft.com/kb/143208 */
# define NOMINMAX
#endif /*_MSC_VER*/
* Configured in check_3_compiler_bugs: *
****************************************/
-/* Defined if we have to work around a bug with some compilers that will not
+/** Defined if we have to work around a bug with some compilers that will not
* allow us to specify a fully specialized class of a template as a friend.
* See the aclocal.m4 file in the top-level directory for a description of
* this bug.
* */
#cmakedefine DEAL_II_TEMPL_SPEC_FRIEND_BUG
-/* Defined if the compiler refuses to allow the explicit specialization of
+/** Defined if the compiler refuses to allow the explicit specialization of
* static member arrays. For the exact failure mode, look at aclocal.m4 in the
* top-level directory.
*/
#cmakedefine DEAL_II_MEMBER_ARRAY_SPECIALIZATION_BUG
-/* Defined if the compiler refuses to allow the explicit specialization of
+/** Defined if the compiler refuses to allow the explicit specialization of
* static member variables.
*/
#cmakedefine DEAL_II_MEMBER_VAR_SPECIALIZATION_BUG
-/* Defined if the compiler does not honor the explicit keyword on template
+/** Defined if the compiler does not honor the explicit keyword on template
* constructors.
*/
#cmakedefine DEAL_II_EXPLICIT_CONSTRUCTOR_BUG
-/* Defined if the compiler has a bug in deducing the type of pointers to const
+/** Defined if the compiler has a bug in deducing the type of pointers to const
* member functions.
*/
#cmakedefine DEAL_II_CONST_MEMBER_DEDUCTION_BUG
-/* Defined if the compiler gets an internal error compiling some code that
+/** Defined if the compiler gets an internal error compiling some code that
* involves boost::bind
*/
#cmakedefine DEAL_II_BOOST_BIND_COMPILER_BUG
-/* Defined if the compiler incorrectly deduces a constexpr as not being a
+/**
+ * Defined if there is no const operator() in the class type returned
+ * by std::bind.
+ */
+#cmakedefine DEAL_II_BOOST_BIND_NO_CONST_OP_PARENTHESES
+
+/** Defined if the compiler incorrectly deduces a constexpr as not being a
* constant integral expression under certain optimization (notably
* gcc-4.8.1 on Windows and Mac)
*/
#cmakedefine DEAL_II_WITH_ARPACK
#ifdef DEAL_II_WITH_ARPACK
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_ARPACK
#endif
#cmakedefine DEAL_II_WITH_FUNCTIONPARSER
#ifdef DEAL_II_WITH_FUNCTIONPARSER
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_FUNCTIONPARSER
#endif
#cmakedefine DEAL_II_WITH_HDF5
#ifdef DEAL_II_WITH_HDF5
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_HAVE_HDF5
#endif
#cmakedefine DEAL_II_WITH_LAPACK
#ifdef DEAL_II_WITH_LAPACK
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBLAPACK
/* Defined if the corresponding BLAS or LAPACK function is available */
#cmakedefine DEAL_II_WITH_METIS
#ifdef DEAL_II_WITH_METIS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_METIS
#endif
#cmakedefine DEAL_II_WITH_MPI
#ifdef DEAL_II_WITH_MPI
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_COMPILER_SUPPORTS_MPI
#endif
#cmakedefine DEAL_II_WITH_MUMPS
#ifdef DEAL_II_WITH_MUMPS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_MUMPS
#endif
+/*************************************************
+ * Configured in configure_functionparser.cmake: *
+ *************************************************/
+
+#cmakedefine DEAL_II_WITH_MUPARSER
+
+
/*****************************************
* Configured in configure_netcdf.cmake: *
*****************************************/
#cmakedefine DEAL_II_WITH_NETCDF
#ifdef DEAL_II_WITH_NETCDF
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBNETCDF
#endif
#cmakedefine DEAL_II_WITH_P4EST
#ifdef DEAL_II_WITH_P4EST
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_P4EST
# define DEAL_II_P4EST_VERSION_MAJOR @P4EST_VERSION_MAJOR@
#cmakedefine DEAL_II_WITH_PETSC
#ifdef DEAL_II_WITH_PETSC
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_PETSC
#endif
#cmakedefine DEAL_II_WITH_SLEPC
#ifdef DEAL_II_WITH_SLEPC
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_SLEPC
#endif
#cmakedefine DEAL_II_WITH_THREADS
#ifdef DEAL_II_WITH_THREADS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_MT
#endif
*/
#cmakedefine DEAL_II_USE_MT_POSIX
-/* Defined if POSIX is supported but not the newer POSIX barrier functions.
+/** Defined if POSIX is supported but not the newer POSIX barrier functions.
* Barriers will then not work in the library, but the other threading
* functionality is available.
*/
#cmakedefine DEAL_II_WITH_ZLIB
#ifdef DEAL_II_WITH_ZLIB
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBZ
#endif
#cmakedefine DEAL_II_WITH_TRILINOS
#ifdef DEAL_II_WITH_TRILINOS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_TRILINOS
#endif
#cmakedefine DEAL_II_WITH_UMFPACK
#ifdef DEAL_II_WITH_UMFPACK
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBUMFPACK
#endif
*
* <tt>values</tt> shall have the right size beforehand, i.e.
* #n_components.
+ *
+ * The default implementation will call value() for each component.
*/
virtual void vector_value (const Point<dim> &p,
Vector<double> &values) const;
#include <deal.II/base/function.h>
#include <deal.II/base/tensor.h>
#include <deal.II/base/point.h>
+#include <deal.II/base/thread_local_storage.h>
#include <vector>
#include <map>
-namespace fparser
+namespace mu
{
- class FunctionParser;
+ class Parser;
}
DEAL_II_NAMESPACE_OPEN
/**
* This class implements a function object that gets its value by parsing a
- * string describing this function. It is a wrapper class for the fparser
- * library (see http://warp.povusers.org/FunctionParser/). This class
- * lets you evaluate strings such as "sqrt(1-x^2+y^2)" for given values of
- * 'x' and 'y'. Some of the information contained here is copied verbatim
- * from the fparser.txt file that comes with the fparser library. Please refer
- * also to that file both for clarifications on how this wrapper works, as
- * well as for any issue regarding the license that applies to this class.
- * This class is used in the step-33 and step-36
- * tutorial programs (the latter being much simpler to understand).
- *
- * By using this class you indicate that you accept the terms of the license
- * that comes with the fparser library. If you do not agree with them, you
- * should not use this class or configure the deal.II library without the
- * function parser (see the ReadMe file of deal.II on instructions for this).
- *
- * The following example shows how to use this class:
+ * string describing this function. It is a wrapper class for the muparser
+ * library (see http://muparser.beltoforion.de/). This class lets you evaluate
+ * strings such as "sqrt(1-x^2+y^2)" for given values of 'x' and 'y'. Please
+ * refer to the muparser documentation for more information. This class is
+ * used in the step-33 and step-36 tutorial programs (the latter being much
+ * simpler to understand).
+ *
+ * The following examples shows how to use this class:
* @code
- // Define some constants that will be used by the function parser
- std::map<std::string,double> constants;
- constants["pi"] = numbers::PI;
-
- // Define the variables that will be used inside the expressions
- std::string variables = "x,y,z";
-
- // Define the expressions of the individual components of a
- // vector valued function with two components:
- std::vector<std::string> expressions(2);
- expressions[0] = "sin(2*pi*x)+sinh(pi*z)";
- expressions[1] = "sin(2*pi*y)*exp(x^2)";
-
- // Generate an empty function for these two components.
- ParsedFunction<3> vector_function(2);
-
- // And populate it with the newly created objects.
- vector_function.initialize(variables,
- expressions,
- constants);
- @endcode
-
- * FunctionParser also provides an option to use <b>units</b> in expressions.
- * We illustrate the use of this functionality with the following example:
+ * // set up problem:
+ * std::string variables = "x,y";
+ * std::string expression = "cos(x)+sqrt(y)";
+ * std::map<std::string,double> constants;
+ *
+ * // FunctionParser with 2 variables and 1 component:
+ * FunctionParser<2> fp(1);
+ * fp.initialize(variables,
+ * expression,
+ * constants);
+ *
+ * // Point at which we want to evaluate the function
+ * Point<2> point(0.0, 4.0);
+ *
+ * // evaluate the expression at 'point':
+ * double result = fp.value(point);
+ *
+ * deallog << "Function '" << expression << "'"
+ * << " @ " << point
+ * << " is " << result << std::endl;
+ * @endcode
+ * The second example is a bit more complex:
* @code
- // Define some constants that will be used by the function parser
- std::map<std::string> constants;
- std::map<std::string> units;
- constants["PI"] = numbers::PI;
- units["cm"] = 10;
- units["m"] = 1000;
-
- // Define the variables that will be used inside the expressions
- std::string variables = "x,y";
-
- // Define the expressions of the individual components of a
- // vector valued function with two components:
- std::vector<std::string> expressions(1);
- expressions[0] = "x cm + y m + PI cm";
-
- // Generate an empty function for these two components.
- FunctionParser<2> vector_function;
-
- // And populate it with the newly created objects.
- vector_function.initialize(variables,
- expressions,
- constants,
- units); //An extra argument here
-
- // Point at which we want to evaluate the function
- Point<2> point(2.0, 3.0);
-
- // Output the evaluated function
- std::cout << "Function " << "[" << expressions[0] << "]" <<
- " @point " << "[" << point << "]" << " is " <<
- "[" << vector_function.value(point) << "]" << std::endl;
-
+ * // Define some constants that will be used by the function parser
+ * std::map<std::string,double> constants;
+ * constants["pi"] = numbers::PI;
+ *
+ * // Define the variables that will be used inside the expressions
+ * std::string variables = "x,y,z";
+ *
+ * // Define the expressions of the individual components of a
+ * // vector valued function with two components:
+ * std::vector<std::string> expressions(2);
+ * expressions[0] = "sin(2*pi*x)+sinh(pi*z)";
+ * expressions[1] = "sin(2*pi*y)*exp(x^2)";
+ *
+ * // function parser with 3 variables and 2 components
+ * FunctionParser<3> vector_function(2);
+ *
+ * // And populate it with the newly created objects.
+ * vector_function.initialize(variables,
+ * expressions,
+ * constants);
+ *
+ * // Point at which we want to evaluate the function
+ * Point<3> point(0.0, 1.0, 1.0);
+ *
+ * // This Vector will store the result
+ * Vector<double> result(2);
+ *
+ * // Fill 'result' by evaluating the function
+ * vector_function.vector_value(point, result);
+ *
+ * // We can also only evaluate the 2nd component:
+ * double c = vector_function.value(point, 1);
+ *
+ * // Output the evaluated function
+ * deallog << "Function '" << expressions[0] << "," << expressions[1] << "'"
+ * << " @ " << point
+ * << " is " << result << std::endl;
* @endcode
*
- * Units are similar to <b>constants</b> in the way they are passed to the
- * parser, i.e. via std::map<std::string,double>. But units are slightly different
- * in that they have a higher precedence than any other operator
- * (except parentheses). Thus for example "5/2in" is parsed as "5/(2*300)".
- * (If you actually do want 5/2 inches, it has to be written as "(5/2)in".)
- *
- * Overall, the main point of units is to make input expressions more readable
- * since expressing, say, length as 10cm looks more natural than 10*cm.
- *
- * Beware that the user has full control over units as well as full
- * responsibility for "sanity" of the parsed expressions, because the parser
- * does NOT know anything about the physical nature of units and one would not
- * be warned when adding kilometers to kilograms.
- *
- * The <b>units</b> argument to the initialize function is <b>optional</b>, i.e. the
- * user does NOT have to use this functionality.
- *
- * For more information on this feature, please see
- * contrib/functionparser/fparser.txt
-
-
- *
- * See http://warp.povusers.org/FunctionParser/ for an
- * explanation on how the underlying library works.
- *
-
- From the fparser.txt file:
- @verbatim
-
- The library is intended to be very fast. It byte-compiles the
- function string at parse time and interprets this byte-code at
- evaluation time. The evaluation is straightforward and no recursions
- are done (uses stack arithmetic). Empirical tests show that it indeed
- is very fast (specially compared to libraries which evaluate functions
- by just interpreting the raw function string).
-
- @endverbatim
- *
- * This class overloads the virtual methods value() and
- * vector_value() of the Function base class with the byte compiled versions
- * of the expressions given to the initialize() methods. Note that the class
- * will not work unless you first call the initialize() method that accepts
- * the text description of the function as an argument (among other
- * things). The reason for this is that this text description may be read from
- * an input file, and may therefore not be available at object construction
- * time yet.
- *
- * The syntax to describe a function follows usual programming practice,
- * and is explained in this snippet from the fparser.txt file:
- @verbatim
- The function string understood by the class is very similar to the C-syntax.
- Arithmetic float expressions can be created from float literals, variables
- or functions using the following operators in this order of precedence:
-
- () expressions in parentheses first
- -A unary minus
- A^B exponentiation (A raised to the power B)
- A*B A/B A%B multiplication, division and modulo
- A+B A-B addition and subtraction
- A=B A<B A>B comparison between A and B (result is either 0 or 1)
- A&B result is 1 if int(A) and int(B) differ from 0, else 0.
- A|B result is 1 if int(A) or int(B) differ from 0, else 0.
-
- Since the unary minus has higher precedence than any other operator, for
- example the following expression is valid: x*-y
- Note that the '=' comparison can be inaccurate due to floating point
- precision problems (eg. "sqrt(100)=10" probably returns 0, not 1).
-
- The class supports these functions:
-
- abs(A) : Absolute value of A. If A is negative, returns -A otherwise
- returns A.
- acos(A) : Arc-cosine of A. Returns the angle, measured in radians,
- whose cosine is A.
- acosh(A) : Same as acos() but for hyperbolic cosine.
- asin(A) : Arc-sine of A. Returns the angle, measured in radians, whose
- sine is A.
- asinh(A) : Same as asin() but for hyperbolic sine.
- atan(A) : Arc-tangent of (A). Returns the angle, measured in radians,
- whose tangent is (A).
- atan2(A,B): Arc-tangent of A/B. The two main differences to atan() is
- that it will return the right angle depending on the signs of
- A and B (atan() can only return values between -pi/2 and pi/2),
- and that the return value of pi/2 and -pi/2 are possible.
- atanh(A) : Same as atan() but for hyperbolic tangent.
- ceil(A) : Ceiling of A. Returns the smallest integer greater than A.
- Rounds up to the next higher integer.
- cos(A) : Cosine of A. Returns the cosine of the angle A, where A is
- measured in radians.
- cosh(A) : Same as cos() but for hyperbolic cosine.
- cot(A) : Cotangent of A (equivalent to 1/tan(A)).
- csc(A) : Cosecant of A (equivalent to 1/sin(A)).
- eval(...) : This a recursive call to the function to be evaluated. The
- number of parameters must be the same as the number of parameters
- taken by the function. Usually called inside if() to avoid
- infinite recursion.
- exp(A) : Exponential of A. Returns the value of e raised to the power
- A where e is the base of the natural logarithm, i.e. the
- non-repeating value approximately equal to 2.71828182846.
- floor(A) : Floor of A. Returns the largest integer less than A. Rounds
- down to the next lower integer.
- if(A,B,C) : If int(A) differs from 0, the return value of this function is B,
- else C. Only the parameter which needs to be evaluated is
- evaluated, the other parameter is skipped; this makes it safe to
- use eval() in them.
- int(A) : Rounds A to the closest integer. 0.5 is rounded to 1.
- log(A) : Natural (base e) logarithm of A.
- log10(A) : Base 10 logarithm of A.
- max(A,B) : If A>B, the result is A, else B.
- min(A,B) : If A<B, the result is A, else B.
- sec(A) : Secant of A (equivalent to 1/cos(A)).
- sin(A) : Sine of A. Returns the sine of the angle A, where A is
- measured in radians.
- sinh(A) : Same as sin() but for hyperbolic sine.
- sqrt(A) : Square root of A. Returns the value whose square is A.
- tan(A) : Tangent of A. Returns the tangent of the angle A, where A
- is measured in radians.
- tanh(A) : Same as tan() but for hyperbolic tangent.
-
-
- Examples of function string understood by the class:
-
- "1+2"
- "x-1"
- "-sin(sqrt(x^2+y^2))"
- "sqrt(XCoord*XCoord + YCoord*YCoord)"
-
- An example of a recursive function is the factorial function:
-
- "if(n>1, n*eval(n-1), 1)"
-
- Note that a recursive call has some overhead, which makes it a bit slower
- than any other operation. It may be a good idea to avoid recursive functions
- in very time-critical applications. Recursion also takes some memory, so
- extremely deep recursions should be avoided (eg. millions of nested recursive
- calls).
-
- Also note that the if() function is the only place where making a recursive
- call is safe. In any other place it will cause an infinite recursion (which
- will make the program eventually run out of memory).
- @endverbatim
+ * This class overloads the virtual methods value() and vector_value() of the
+ * Function base class with the byte compiled versions of the expressions
+ * given to the initialize() methods. Note that the class will not work unless
+ * you first call the initialize() method that accepts the text description of
+ * the function as an argument (among other things).
+ *
+ * The syntax to describe a function follows usual programming practice, and
+ * is explained in this snippet from the fparser.txt file:
+ * @verbatim
+ * The function string understood by the class is very similar to the C-syntax.
+ * Arithmetic float expressions can be created from float literals, variables
+ * or functions using the following operators in this order of precedence:
+ *
+ * -A unary minus
+ * A^B exponentiation (A raised to the power B)
+ * A*B A/B A%B multiplication, division and modulo
+ * A+B A-B addition and subtraction
+ * A==B A<B A>B comparison between A and B (result is either 0 or 1)
+ * A&&B A||B logical 'and' and 'or'
+ * A&B A|B same, implemented for compatibility
+ *
+ * Since the unary minus has higher precedence than any other operator, for
+ * example the following expression is valid: x*-y
+ *
+ * Note that the '==' comparison can be inaccurate due to floating point
+ * precision problems, so it should be avoided (eg. "sqrt(100)=10" probably
+ * returns 0, not 1).
+ *
+ * The class supports these functions:
+ *
+ * abs(A) : Absolute value of A. If A is negative, returns -A otherwise
+ * returns A.
+ * acos(A) : Arc-cosine of A. Returns the angle, measured in radians,
+ * whose cosine is A.
+ * acosh(A) : Same as acos() but for hyperbolic cosine.
+ * asin(A) : Arc-sine of A. Returns the angle, measured in radians, whose
+ * sine is A.
+ * asinh(A) : Same as asin() but for hyperbolic sine.
+ * atan(A) : Arc-tangent of (A). Returns the angle, measured in radians,
+ * whose tangent is (A).
+ * atan2(A,B): Arc-tangent of A/B. The two main differences to atan() is
+ * that it will return the right angle depending on the signs of
+ * A and B (atan() can only return values between -pi/2 and pi/2),
+ * and that the return value of pi/2 and -pi/2 are possible.
+ * atanh(A) : Same as atan() but for hyperbolic tangent.
+ * ceil(A) : Ceiling of A. Returns the smallest integer greater than A.
+ * Rounds up to the next higher integer.
+ * cos(A) : Cosine of A. Returns the cosine of the angle A, where A is
+ * measured in radians.
+ * cosh(A) : Same as cos() but for hyperbolic cosine.
+ * cot(A) : Cotangent of A (equivalent to 1/tan(A)).
+ * csc(A) : Cosecant of A (equivalent to 1/sin(A)).
+ * exp(A) : Exponential of A. Returns the value of e raised to the power
+ * A where e is the base of the natural logarithm, i.e. the
+ * non-repeating value approximately equal to 2.71828182846.
+ * floor(A) : Floor of A. Returns the largest integer less than A. Rounds
+ * down to the next lower integer.
+ * if(A,B,C) : If int(A) differs from 0, the return value of this function is B,
+ * else C. Only the parameter which needs to be evaluated is
+ * evaluated, the other parameter is skipped; this makes it safe to
+ * use eval() in them.
+ * int(A) : Rounds A to the closest integer. 0.5 is rounded to 1.
+ * log(A) : Natural (base e) logarithm of A.
+ * log10(A) : Base 10 logarithm of A.
+ * max(A,B) : If A>B, the result is A, else B.
+ * min(A,B) : If A<B, the result is A, else B.
+ * sec(A) : Secant of A (equivalent to 1/cos(A)).
+ * sin(A) : Sine of A. Returns the sine of the angle A, where A is
+ * measured in radians.
+ * sinh(A) : Same as sin() but for hyperbolic sine.
+ * sqrt(A) : Square root of A. Returns the value whose square is A.
+ * tan(A) : Tangent of A. Returns the tangent of the angle A, where A
+ * is measured in radians.
+ * tanh(A) : Same as tan() but for hyperbolic tangent.
+ *
+ *
+ * Examples of function string understood by the class:
+ *
+ * "1+2"
+ * "x-1"
+ * "-sin(sqrt(x^2+y^2))"
+ * "sqrt(XCoord*XCoord + YCoord*YCoord)"
+ * @endverbatim
+ *
+ * For a wrapper of the FunctionParser class that supports ParameterHandler,
+ * see ParsedFunction.
*
* Vector-valued functions can either be declared using strings where the
* function components are separated by semicolons, or using a vector of
* strings each defining one vector component.
*
* An example of time dependent scalar function is the following:
- @code
-
- // Empty constants object
- std::map<std::string> constants;
-
- // Variables that will be used inside the expressions
- std::string variables = "x,y,t";
-
- // Define the expression of the scalar time dependent function.
- std::string expression = "exp(y*x)*exp(-t)";
-
- // Generate an empty scalar function
- FunctionParser<2> function;
-
- // And populate it with the newly created objects.
- function.initialize(variables,
- expression,
- constants,
- true); // This tells the parser that
- // it is a time-dependent function
- // and there is another variable
- // to be taken into account (t).
-
- @endcode
-
- * The following is another example of how to instantiate a
- * vector valued function by using a single string:
- @code
-
- // Empty constants object
- std::map<std::string> constants;
-
- // Variables that will be used inside the expressions
- std::string variables = "x,y";
-
- // Define the expression of the vector valued function.
- std::string expression = "cos(2*pi*x)*y^2; sin(2*pi*x)*exp(y)";
-
- // Generate an empty vector valued function
- FunctionParser<2> function(2);
-
- // And populate it with the newly created objects.
- function.initialize(variables,
- expression,
- constants);
-
- @endcode
+ * @code
+ * // Empty constants object
+ * std::map<std::string> constants;
+ *
+ * // Variables that will be used inside the expressions
+ * std::string variables = "x,y,t";
+ *
+ * // Define the expression of the scalar time dependent function.
+ * std::string expression = "exp(y*x)*exp(-t)";
+ *
+ * // Generate an empty scalar function
+ * FunctionParser<2> function;
+ *
+ * // And populate it with the newly created objects.
+ * function.initialize(variables,
+ * expression,
+ * constants,
+ * true); // This tells the parser that
+ * // it is a time-dependent function
+ * // and there is another variable
+ * // to be taken into account (t).
+ * @endcode
+ *
+ * The following is another example of how to instantiate a vector valued
+ * function by using a single string:
+ * @code
+ * // Empty constants object
+ * std::map<std::string> constants;
+ *
+ * // Variables that will be used inside the expressions
+ * std::string variables = "x,y";
+ *
+ * // Define the expression of the vector valued function.
+ * std::string expression = "cos(2*pi*x)*y^2; sin(2*pi*x)*exp(y)";
+ *
+ * // Generate an empty vector valued function
+ * FunctionParser<2> function(2);
+ *
+ * // And populate it with the newly created objects.
+ * function.initialize(variables,
+ * expression,
+ * constants);
+ * @endcode
*
*
* @ingroup functions
- * @author Luca Heltai, 2005
+ * @author Luca Heltai, Timo Heister 2005, 2014
*/
template <int dim>
class FunctionParser : public Function<dim>
{
-public:
- /**
- * Constructor for Parsed
- * functions. Its arguments are
- * the same of the base class
- * Function. The only difference
- * is that this object needs to
- * be initialized with
- * initialize() method before you
- * can use it. If an attempt to
- * use this function is made
- * before the initialize() method
- * has been called, then an
- * exception is thrown.
- */
- FunctionParser (const unsigned int n_components = 1,
- const double initial_time = 0.0);
-
- /**
- * Destructor. Explicitly delete
- * the FunctionParser objects
- * (there is one for each
- * component of the function).
- */
- ~FunctionParser();
-
- /**
- * Type for the constant
- * map. Used by the initialize()
- * method.
- */
- typedef std::map<std::string, double> ConstMap;
-
- /**
- * Iterator for the constants
- * map. Used by the initialize()
- * method.
- */
- typedef ConstMap::iterator ConstMapIterator;
-
- /**
- * Initialize the function. This methods
- * accepts the following parameters:
- *
- * <b>vars</b>: a string with
- * the variables that will be used by the
- * expressions to be evaluated. Note that
- * the variables can have any name (of
- * course different from the function
- * names defined above!), but the order
- * IS important. The first variable will
- * correspond to the first component of
- * the point in which the function is
- * evaluated, the second variable to the
- * second component and so forth. If this
- * function is also time dependent, then
- * it is necessary to specify it by
- * setting the <tt>time_dependent</tt> parameter
- * to true. An exception is thrown if
- * the number of variables specified here
- * is different from dim (if this
- * function is not time-dependent) or
- * from dim+1 (if it is time-dependent).
- *
- * <b>expressions</b>: a list of strings
- * containing the expressions that will
- * be byte compiled by the internal
- * parser (FunctionParser). Note that the
- * size of this vector must match exactly
- * the number of components of the
- * FunctionParser, as declared in the
- * constructor. If this is not the case,
- * an exception is thrown.
- *
- *
- * <b>constants</b>: a map of constants
- * used to pass any necessary constant
- * that we want to specify in our
- * expressions (in the example above the
- * number pi). An expression is valid if
- * and only if it contains only defined
- * variables and defined constants (other
- * than the functions specified
- * above). If a constant is given whose
- * name is not valid (eg:
- * <tt>constants["sin"] = 1.5;</tt>) an
- * exception is thrown.
- *
- * <b>time_dependent</b>. If this is a
- * time dependent function, then the last
- * variable declared in <b>vars</b> is
- * assumed to be the time variable, and
- * this->get_time() is used to initialize
- * it when evaluating the
- * function. Naturally the number of
- * variables parsed by the initialize()
- * method in this case is dim+1. The
- * value of this parameter defaults to
- * false, i.e. do not consider time.
- *
- * <b>use_degrees</b>. Parameter to
- * decide if the trigonometric functions
- * work in radians or degrees. The
- * default for this parameter is false,
- * i.e. use radians and not degrees.
- */
- void initialize (const std::string &vars,
- const std::vector<std::string> &expressions,
- const ConstMap &constants,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
-
- /**
- * Initialize the function. Same as
- * above, but with an additional argument
- * <b> units </b> - a map of units passed to
- * FunctionParser via AddUnint.
- *
- * Can be used as "3cm".
- * Have higher precedence in parsing, i.e.
- * if cm=10 then 3/2cm is 3 /(2*10).
- * See contrib/functionparser/fparser.txt
- * for more details.
- */
- void initialize (const std::string &vars,
- const std::vector<std::string> &expressions,
- const ConstMap &constants,
- const ConstMap &units,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
- /**
- * Initialize the function. Same as
- * above, but accepts a string rather
- * than a vector of strings. If this is a
- * vector valued function, its
- * components are expected to be
- * separated by a semicolon. An exception
- * is thrown if this method is called and
- * the number of components successfully
- * parsed does not match the number of
- * components of the base function.
- */
- void initialize (const std::string &vars,
- const std::string &expression,
- const ConstMap &constants,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
- /**
- * Initialize the function. Same as
- * above, but with <b>units</b>.
- */
-
- void initialize (const std::string &vars,
- const std::string &expression,
- const ConstMap &constants,
- const ConstMap &units,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
- /**
- * A function that returns
- * default names for variables,
- * to be used in the first
- * argument of the initialize()
- * functions: it returns "x" in
- * 1d, "x,y" in 2d, and "x,y,z"
- * in 3d.
- */
- static
- std::string
- default_variable_names ();
-
- /**
- * Return the value of the
- * function at the given
- * point. Unless there is only
- * one component (i.e. the
- * function is scalar), you
- * should state the component you
- * want to have evaluated; it
- * defaults to zero, i.e. the
- * first component.
- */
- virtual double value (const Point<dim> &p,
- const unsigned int component = 0) const;
-
- /**
- * Return all components of a
- * vector-valued function at the
- * given point @p p.
- *
- * <tt>values</tt> shall have the
- * right size beforehand,
- * i.e. #n_components.
- */
- virtual void vector_value (const Point<dim> &p,
- Vector<double> &values) const;
-
- /** @addtogroup Exceptions
- * @{ */
- DeclException2 (ExcParseError,
- int, char *,
- << "Parsing Error at Column " << arg1
- << ". The parser said: " << arg2);
-
- DeclException2 (ExcInvalidExpressionSize,
- int, int,
- << "The number of components (" << arg1
- << ") is not equal to the number of expressions ("
- << arg2 << ").");
-
- //@}
-private:
- /**
- * A pointer to the actual
- * function parsers. The pointer is
- * to an array of parsers, not
- * just a single one. The length of
- * the array equals the number of
- * vector components.
- */
- fparser::FunctionParser *fp;
-
- /**
- * State of usability. This
- * variable is checked every time
- * the function is called for
- * evaluation. It's set to true
- * in the initialize() methods.
- */
- bool initialized;
-
- /**
- * Number of variables. If this
- * is also a function of time,
- * then the number of variables
- * is dim+1, otherwise it is
- * dim. In the case that this is
- * a time dependent function, the
- * time is supposed to be the
- * last variable. If #n_vars is
- * not identical to the number of
- * the variables parsed by the
- * initialize() method, then an
- * exception is thrown.
- */
- unsigned int n_vars;
+ public:
+ /**
+ * Constructor for Parsed functions. Its arguments are the same of the
+ * base class Function. The only difference is that this object needs to
+ * be initialized with initialize() method before you can use it. If an
+ * attempt to use this function is made before the initialize() method has
+ * been called, then an exception is thrown.
+ */
+ FunctionParser (const unsigned int n_components = 1,
+ const double initial_time = 0.0);
+
+ /**
+ * Destructor. Explicitly delete the FunctionParser objects (there is one
+ * for each component of the function).
+ */
+ ~FunctionParser();
+
+ /**
+ * Type for the constant map. Used by the initialize() method.
+ */
+ typedef std::map<std::string, double> ConstMap;
+
+ /**
+ * Iterator for the constants map. Used by the initialize() method.
+ */
+ typedef ConstMap::iterator ConstMapIterator;
+
+ /**
+ * Initialize the function. This methods accepts the following
+ * parameters:
+ *
+ * <b>vars</b>: a string with the variables that will be used by the
+ * expressions to be evaluated. Note that the variables can have any name
+ * (of course different from the function names defined above!), but the
+ * order IS important. The first variable will correspond to the first
+ * component of the point in which the function is evaluated, the second
+ * variable to the second component and so forth. If this function is also
+ * time dependent, then it is necessary to specify it by setting the
+ * <tt>time_dependent</tt> parameter to true. An exception is thrown if
+ * the number of variables specified here is different from dim (if this
+ * function is not time-dependent) or from dim+1 (if it is time-
+ * dependent).
+ *
+ * <b>expressions</b>: a list of strings containing the expressions that
+ * will be byte compiled by the internal parser (FunctionParser). Note
+ * that the size of this vector must match exactly the number of
+ * components of the FunctionParser, as declared in the constructor. If
+ * this is not the case, an exception is thrown.
+ *
+ *
+ * <b>constants</b>: a map of constants used to pass any necessary
+ * constant that we want to specify in our expressions (in the example
+ * above the number pi). An expression is valid if and only if it contains
+ * only defined variables and defined constants (other than the functions
+ * specified above). If a constant is given whose name is not valid (eg:
+ * <tt>constants["sin"] = 1.5;</tt>) an exception is thrown.
+ *
+ * <b>time_dependent</b>. If this is a time dependent function, then the
+ * last variable declared in <b>vars</b> is assumed to be the time
+ * variable, and this->get_time() is used to initialize it when evaluating
+ * the function. Naturally the number of variables parsed by the
+ * initialize() method in this case is dim+1. The value of this parameter
+ * defaults to false, i.e. do not consider time.
+ */
+ void initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const ConstMap &constants,
+ const bool time_dependent = false);
+
+ /**
+ * Same as above, but with an additional parameter: <b>use_degrees</b>.
+ * Parameter to decide if the trigonometric functions work in radians or
+ * degrees. The default for this parameter is false, i.e. use radians and
+ * not degrees.
+ *
+ * @note: this function is deprecated. Use the function without this
+ * argument instead (which has the default use_degrees=false).
+ */
+ void initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const ConstMap &constants,
+ const bool time_dependent,
+ const bool use_degrees) DEAL_II_DEPRECATED;
+
+
+ /**
+ * Initialize the function. Same as above, but with an additional argument
+ * <b> units </b> - a map of units passed to FunctionParser via AddUnint.
+ *
+ * Can be used as "3cm". Have higher precedence in parsing, i.e. if cm=10
+ * then 3/2cm is 3 /(2*10). See contrib/functionparser/fparser.txt for
+ * more details.
+ */
+ void initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const ConstMap &constants,
+ const ConstMap &units,
+ const bool time_dependent = false,
+ const bool use_degrees = false) DEAL_II_DEPRECATED;
+
+ /**
+ * Initialize the function. Same as above, but accepts a string rather
+ * than a vector of strings. If this is a vector valued function, its
+ * components are expected to be separated by a semicolon. An exception is
+ * thrown if this method is called and the number of components
+ * successfully parsed does not match the number of components of the base
+ * function.
+ */
+ void initialize (const std::string &vars,
+ const std::string &expression,
+ const ConstMap &constants,
+ const bool time_dependent = false);
+
+ /**
+ * Same as above, but with an additional parameter: <b>use_degrees</b>.
+ * Parameter to decide if the trigonometric functions work in radians or
+ * degrees. The default for this parameter is false, i.e. use radians and
+ * not degrees.
+ *
+ * @note: this function is deprecated. Use the function without this
+ * argument instead (which has the default use_degrees=false).
+ */
+ void initialize (const std::string &vars,
+ const std::string &expression,
+ const ConstMap &constants,
+ const bool time_dependent,
+ const bool use_degrees) DEAL_II_DEPRECATED;
+ /**
+ * Initialize the function. Same as above, but with <b>units</b>.
+ */
+
+ void initialize (const std::string &vars,
+ const std::string &expression,
+ const ConstMap &constants,
+ const ConstMap &units,
+ const bool time_dependent = false,
+ const bool use_degrees = false) DEAL_II_DEPRECATED;
+
+ /**
+ * A function that returns default names for variables, to be used in the
+ * first argument of the initialize() functions: it returns "x" in 1d,
+ * "x,y" in 2d, and "x,y,z" in 3d.
+ */
+ static
+ std::string
+ default_variable_names ();
+
+ /**
+ * Return the value of the function at the given point. Unless there is
+ * only one component (i.e. the function is scalar), you should state the
+ * component you want to have evaluated; it defaults to zero, i.e. the
+ * first component.
+ */
+ virtual double value (const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ /**
+ * Return all components of a vector-valued function at the given point @p
+ * p.
+ *
+ * <tt>values</tt> shall have the right size beforehand, i.e.
+ * #n_components.
+ */
+ virtual void vector_value (const Point<dim> &p,
+ Vector<double> &values) const;
+
+ /**
+ * @addtogroup Exceptions
+ * @{
+ */
+ DeclException2 (ExcParseError,
+ int, char *,
+ << "Parsing Error at Column " << arg1
+ << ". The parser said: " << arg2);
+
+ DeclException2 (ExcInvalidExpressionSize,
+ int, int,
+ << "The number of components (" << arg1
+ << ") is not equal to the number of expressions ("
+ << arg2 << ").");
+
+ //@}
+ private:
+#ifdef DEAL_II_WITH_MUPARSER
+ /**
+ * place for the variables for each thread
+ */
+ mutable Threads::ThreadLocalStorage<std::vector<double> > vars;
+ /**
+ * the muParser objects for each thread (and one for each component)
+ */
+ mutable Threads::ThreadLocalStorage<std::vector<mu::Parser> > fp;
+
+ /**
+ * keep track of all the constants, required to initialize fp in each
+ * thread
+ */
+ std::map< std::string, double > constants;
+ /**
+ * variable names, required to initialize fp in each thread
+ */
+ std::vector<std::string> var_names;
+ /**
+ * the expressions, required to initialize fp in each thread
+ */
+ std::vector<std::string> expressions;
+ /**
+ * this function will initialize fp on the current thread
+ */
+ void init_muparser() const;
+#endif
+
+ /**
+ * State of usability. This variable is checked every time the function is
+ * called for evaluation. It's set to true in the initialize() methods.
+ */
+ bool initialized;
+
+ /**
+ * Number of variables. If this is also a function of time, then the
+ * number of variables is dim+1, otherwise it is dim. In the case that
+ * this is a time dependent function, the time is supposed to be the last
+ * variable. If #n_vars is not identical to the number of the variables
+ * parsed by the initialize() method, then an exception is thrown.
+ */
+ unsigned int n_vars;
};
FunctionParser<dim>::default_variable_names ()
{
switch (dim)
- {
- case 1:
- return "x";
- case 2:
- return "x,y";
- case 3:
- return "x,y,z";
- default:
- Assert (false, ExcNotImplemented());
- }
+ {
+ case 1:
+ return "x";
+ case 2:
+ return "x,y";
+ case 3:
+ return "x,y,z";
+ default:
+ Assert (false, ExcNotImplemented());
+ }
return "";
}
/**
* Constructs the IndexSet from a text based representation given by the
- * stream @param in written by the write() function.
+ * stream @p in written by the write() function.
*/
void read(std::istream &in);
/**
* Constructs the IndexSet from a binary representation given by the stream
- * @param in written by the write_block() function.
+ * @p in written by the write_block() function.
*/
void block_read(std::istream &in);
namespace Utilities
{
/**
- * A namespace for utility functions that
- * abstract certain operations using the
- * Message Passing Interface (MPI) or
- * provide fallback operations in
- * case deal.II is configured not to use
- * MPI at all.
+ * A namespace for utility functions that abstract certain operations using
+ * the Message Passing Interface (MPI) or provide fallback operations in
+ * case deal.II is configured not to use MPI at all.
*
* @ingroup utilities
*/
namespace MPI
{
/**
- * Return the number of MPI processes
- * there exist in the given communicator
- * object. If this is a sequential job,
- * it returns 1.
+ * Return the number of MPI processes there exist in the given
+ * communicator object. If this is a sequential job, it returns 1.
*/
unsigned int n_mpi_processes (const MPI_Comm &mpi_communicator);
/**
- * Return the number of the present MPI
- * process in the space of processes
- * described by the given
- * communicator. This will be a unique
- * value for each process between zero
- * and (less than) the number of all
- * processes (given by
- * get_n_mpi_processes()).
+ * Return the number of the present MPI process in the space of processes
+ * described by the given communicator. This will be a unique value for
+ * each process between zero and (less than) the number of all processes
+ * (given by get_n_mpi_processes()).
*/
unsigned int this_mpi_process (const MPI_Comm &mpi_communicator);
/**
- * Consider an unstructured
- * communication pattern where
- * every process in an MPI
- * universe wants to send some
- * data to a subset of the other
- * processors. To do that, the
- * other processors need to know
- * who to expect messages
- * from. This function computes
- * this information.
+ * Consider an unstructured communication pattern where every process in
+ * an MPI universe wants to send some data to a subset of the other
+ * processors. To do that, the other processors need to know who to expect
+ * messages from. This function computes this information.
*
- * @param mpi_comm A communicator
- * that describes the processors
- * that are going to communicate
- * with each other.
+ * @param mpi_comm A communicator that describes the processors that are
+ * going to communicate with each other.
*
- * @param destinations The list
- * of processors the current
- * process wants to send
- * information to. This list need
- * not be sorted in any way. If
- * it contains duplicate entries
- * that means that multiple
- * messages are intended for a
- * given destination.
+ * @param destinations The list of processors the current process wants to
+ * send information to. This list need not be sorted in any way. If it
+ * contains duplicate entries that means that multiple messages are
+ * intended for a given destination.
*
- * @return A list of processors
- * that have indicated that they
- * want to send something to the
- * current processor. The
- * resulting list is not
- * sorted. It may contain
- * duplicate entries if
- * processors enter the same
- * destination more than once in
- * their destinations list.
+ * @return A list of processors that have indicated that they want to send
+ * something to the current processor. The resulting list is not sorted.
+ * It may contain duplicate entries if processors enter the same
+ * destination more than once in their destinations list.
*/
std::vector<unsigned int>
compute_point_to_point_communication_pattern (const MPI_Comm &mpi_comm,
const std::vector<unsigned int> &destinations);
/**
- * Given a communicator, generate a new
- * communicator that contains the same
- * set of processors but that has a
- * different, unique identifier.
+ * Given a communicator, generate a new communicator that contains the
+ * same set of processors but that has a different, unique identifier.
*
- * This functionality can be used to
- * ensure that different objects, such as
- * distributed matrices, each have unique
- * communicators over which they can
- * interact without interfering with each
- * other.
+ * This functionality can be used to ensure that different objects, such
+ * as distributed matrices, each have unique communicators over which they
+ * can interact without interfering with each other.
*
- * When no longer needed, the
- * communicator created here needs to
- * be destroyed using
- * <code>MPI_Comm_free</code>.
+ * When no longer needed, the communicator created here needs to be
+ * destroyed using <code>MPI_Comm_free</code>.
*/
MPI_Comm duplicate_communicator (const MPI_Comm &mpi_communicator);
/**
- * Return the sum over all processors of the value @p t. This function
- * is collective over all processors given in the communicator. If
- * deal.II is not configured for use of MPI, this function simply
- * returns the value of @p t. This function corresponds to the
- * <code>MPI_Allreduce</code> function, i.e. all processors receive
- * the result of this operation.
+ * Return the sum over all processors of the value @p t. This function is
+ * collective over all processors given in the communicator. If deal.II is
+ * not configured for use of MPI, this function simply returns the value
+ * of @p t. This function corresponds to the <code>MPI_Allreduce</code>
+ * function, i.e. all processors receive the result of this operation.
*
- * @note Sometimes, not all processors need a results and in that case
- * one would call the <code>MPI_Reduce</code> function instead of the
+ * @note Sometimes, not all processors need a results and in that case one
+ * would call the <code>MPI_Reduce</code> function instead of the
* <code>MPI_Allreduce</code> function. The latter is at most twice as
* expensive, so if you are concerned about performance, it may be
- * worthwhile investigating whether your algorithm indeed needs the
- * result everywhere or whether you could get away with calling the
- * current function and getting the result everywhere.
+ * worthwhile investigating whether your algorithm indeed needs the result
+ * everywhere or whether you could get away with calling the current
+ * function and getting the result everywhere.
*
- * @note This function is only implemented for certain template
- * arguments <code>T</code>, namely <code>float, double, int,
- * unsigned int</code>.
+ * @note This function is only implemented for certain template arguments
+ * <code>T</code>, namely <code>float, double, int, unsigned int</code>.
*/
template <typename T>
T sum (const T &t,
const MPI_Comm &mpi_communicator);
/**
- * Like the previous function,
- * but take the sums over the
- * elements of an array
- * of length N. In other words,
- * the i-th element of the
- * results array is the sum over
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the sums over the elements of an
+ * array of length N. In other words, the i-th element of the results
+ * array is the sum over the i-th entries of the input arrays from each
+ * processor.
*/
template <typename T, unsigned int N>
inline
T (&sums)[N]);
/**
- * Like the previous function,
- * but take the sums over the
- * elements of a std::vector. In other words,
- * the i-th element of the
- * results array is the sum over
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the sums over the elements of a
+ * std::vector. In other words, the i-th element of the results array is
+ * the sum over the i-th entries of the input arrays from each processor.
*/
template <typename T>
inline
/**
* Return the maximum over all processors of the value @p t. This function
- * is collective over all processors given in the communicator. If
- * deal.II is not configured for use of MPI, this function simply
- * returns the value of @p t. This function corresponds to the
- * <code>MPI_Allreduce</code> function, i.e. all processors receive
- * the result of this operation.
+ * is collective over all processors given in the communicator. If deal.II
+ * is not configured for use of MPI, this function simply returns the
+ * value of @p t. This function corresponds to the
+ * <code>MPI_Allreduce</code> function, i.e. all processors receive the
+ * result of this operation.
*
- * @note Sometimes, not all processors need a results and in that case
- * one would call the <code>MPI_Reduce</code> function instead of the
+ * @note Sometimes, not all processors need a results and in that case one
+ * would call the <code>MPI_Reduce</code> function instead of the
* <code>MPI_Allreduce</code> function. The latter is at most twice as
* expensive, so if you are concerned about performance, it may be
- * worthwhile investigating whether your algorithm indeed needs the
- * result everywhere or whether you could get away with calling the
- * current function and getting the result everywhere.
+ * worthwhile investigating whether your algorithm indeed needs the result
+ * everywhere or whether you could get away with calling the current
+ * function and getting the result everywhere.
*
- * @note This function is only implemented for certain template
- * arguments <code>T</code>, namely <code>float, double, int,
- * unsigned int</code>.
+ * @note This function is only implemented for certain template arguments
+ * <code>T</code>, namely <code>float, double, int, unsigned int</code>.
*/
template <typename T>
T max (const T &t,
const MPI_Comm &mpi_communicator);
/**
- * Like the previous function,
- * but take the maxima over the
- * elements of an array
- * of length N. In other words,
- * the i-th element of the
- * results array is the maximum of
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the maxima over the elements of an
+ * array of length N. In other words, the i-th element of the results
+ * array is the maximum of the i-th entries of the input arrays from each
+ * processor.
*/
template <typename T, unsigned int N>
inline
T (&maxima)[N]);
/**
- * Like the previous function,
- * but take the maximum over the
- * elements of a std::vector. In other words,
- * the i-th element of the
- * results array is the maximum over
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the maximum over the elements of a
+ * std::vector. In other words, the i-th element of the results array is
+ * the maximum over the i-th entries of the input arrays from each
+ * processor.
*/
template <typename T>
inline
std::vector<T> &maxima);
/**
- * Data structure to store the result of
- * min_max_avg().
+ * Data structure to store the result of min_max_avg().
*/
struct MinMaxAvg
{
};
/**
- * Returns sum, average, minimum,
- * maximum, processor id of minimum and
- * maximum as a collective operation of
- * on the given MPI communicator @p
- * mpi_communicator . Each processor's
- * value is given in @p my_value and
- * the result will be returned.
- * The result is available on all
- * machines.
+ * Returns sum, average, minimum, maximum, processor id of minimum and
+ * maximum as a collective operation of on the given MPI communicator @p
+ * mpi_communicator . Each processor's value is given in @p my_value and
+ * the result will be returned. The result is available on all machines.
*
- * @note Sometimes, not all processors need a results and in that case
- * one would call the <code>MPI_Reduce</code> function instead of the
+ * @note Sometimes, not all processors need a results and in that case one
+ * would call the <code>MPI_Reduce</code> function instead of the
* <code>MPI_Allreduce</code> function. The latter is at most twice as
* expensive, so if you are concerned about performance, it may be
- * worthwhile investigating whether your algorithm indeed needs the
- * result everywhere or whether you could get away with calling the
- * current function and getting the result everywhere.
+ * worthwhile investigating whether your algorithm indeed needs the result
+ * everywhere or whether you could get away with calling the current
+ * function and getting the result everywhere.
*/
MinMaxAvg
min_max_avg (const double my_value,
/**
- * A class that is used to initialize the
- * MPI system at the beginning of a
- * program and to shut it down again at
- * the end. It also allows you to control
- * the number threads used in each MPI
- * task.
+ * A class that is used to initialize the MPI system at the beginning of a
+ * program and to shut it down again at the end. It also allows you to
+ * control the number threads used in each MPI task.
*
- * If deal.II is configured with PETSc,
- * the library will also be initialized
- * in the beginning and destructed at the
- * end automatically (internally by calling
- * PetscInitialize() and PetscFinalize()).
+ * If deal.II is configured with PETSc, the library will also be
+ * initialized in the beginning and destructed at the end automatically
+ * (internally by calling PetscInitialize() and PetscFinalize()).
*
- * If a program uses MPI one would
- * typically just create an object of
- * this type at the beginning of
- * <code>main()</code>. The constructor
- * of this class then runs
- * <code>MPI_Init()</code> with the given
- * arguments. At the end of the program,
- * the compiler will invoke the
- * destructor of this object which in
- * turns calls <code>MPI_Finalize</code>
- * to shut down the MPI system.
+ * If a program uses MPI one would typically just create an object of this
+ * type at the beginning of <code>main()</code>. The constructor of this
+ * class then runs <code>MPI_Init()</code> with the given arguments. At
+ * the end of the program, the compiler will invoke the destructor of this
+ * object which in turns calls <code>MPI_Finalize</code> to shut down the
+ * MPI system.
*
* This class is used in step-32, for example.
*/
{
public:
/**
- * Constructor. Takes the arguments
- * from the command line (in case of
- * MPI, the number of processes is
- * specified there), and sets up a
- * respective communicator by calling
- * <tt>MPI_Init()</tt>. This
- * constructor can only be called once
- * in a program, since MPI cannot be
+ * Constructor. Takes the arguments from the command line (in case of
+ * MPI, the number of processes is specified there), and sets up a
+ * respective communicator by calling <tt>MPI_Init()</tt>. This
+ * constructor can only be called once in a program, since MPI cannot be
* initialized twice.
*
- * This constructor sets max_num_threads
- * to 1 (see other constructor).
+ * This constructor sets max_num_threads to 1 (see other constructor).
*/
MPI_InitFinalize (int &argc,
char ** &argv) /*DEAL_II_DEPRECATED*/;
/**
- * Initialize MPI (and optionally PETSc)
- * and set the number of threads used by deal.II (and TBB) to the given
- * parameter. If set to numbers::invalid_unsigned_int, the number
- * of threads is determined by TBB. When in doubt, set this value
- * to 1.
+ * Initialize MPI (and optionally PETSc) and set the number of threads
+ * used by deal.II (and TBB) to the given parameter. If set to
+ * numbers::invalid_unsigned_int, the number of threads is determined by
+ * TBB. When in doubt, set this value to 1.
+ *
+ * This will call MultithreadInfo::set_thread_limit() with @p
+ * max_num_threads, so the environment variable DEAL_II_NUM_THREADS will
+ * be respected.
*/
MPI_InitFinalize (int &argc,
char ** &argv,
unsigned int max_num_threads);
/**
- * Destructor. Calls
- * <tt>MPI_Finalize()</tt> in
- * case this class owns the MPI
- * process.
+ * Destructor. Calls <tt>MPI_Finalize()</tt> in case this class owns the
+ * MPI process.
*/
~MPI_InitFinalize();
private:
/**
- * This flag tells the class
- * whether it owns the MPI
- * process (i.e., it has been
- * constructed using the
- * argc/argv input, or it has
- * been copied). In the former
- * case, the command
- * <tt>MPI_Finalize()</tt> will
+ * This flag tells the class whether it owns the MPI process (i.e., it
+ * has been constructed using the argc/argv input, or it has been
+ * copied). In the former case, the command <tt>MPI_Finalize()</tt> will
* be called at destruction.
*/
const bool owns_mpi;
{
#ifdef DEAL_II_WITH_MPI
/**
- * Return the corresponding MPI data
- * type id for the argument given.
+ * Return the corresponding MPI data type id for the argument given.
*/
inline MPI_Datatype mpi_type_id (const int *)
{
*/
unsigned int n_default_threads DEAL_II_DEPRECATED;
- /*
+ /**
* Returns the number of threads to use. This is governed by the number
* of cores the system has (n_cpus) and can be further restricted by
* set_thread_limit().
/**
+ * @deprecated The use of this class is deprecated and AnyData should
+ * be used instead. It is not only more flexible, the way constness
+ * was assured in this class never worked the way it was
+ * intended. Therefore, the according checks have been disabled.
+ *
* This class is a collection of DATA objects. Each of the pointers
* has a name associated, enabling identification by this name rather
* than the index in the vector only.
void
NamedData<DATA>::add(DATA &v, const std::string &n)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
names.push_back(n);
data.push_back(v);
}
void
NamedData<DATA>::add(const DATA &v, const std::string &n)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
DATA &aux = const_cast<DATA &>(v);
data.push_back(aux);
names.push_back(n);
void
NamedData<DATA>::merge(NamedData<DATA2> &other)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
for (unsigned int i=0; i<other.size(); ++i)
{
void
NamedData<DATA>::merge(const NamedData<DATA2> &other)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
for (unsigned int i=0; i<other.size(); ++i)
{
names.push_back(other.name(i));
DATA &
NamedData<DATA>::operator() (unsigned int i)
{
- Assert(!is_constant, ExcConstantObject());
+ // Remove this assertion, since is_const() does not really assert
+ // what we would like to. This can only be fixed by using constness
+ // in AnyData.
+
+ // Assert(!is_constant, ExcConstantObject());
AssertIndexRange(i, size());
return data[i];
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// warnings about unused arguments
(void) grainsize;
+# ifndef DEAL_II_BIND_NO_CONST_OP_PARENTHESES
f (begin, end);
+# else
+ // work around a problem with MS VC++ where there is no const
+ // operator() in Function
+ Function(f) (begin, end);
+# endif
#else
tbb::parallel_for (tbb::blocked_range<RangeType>
(begin, end, grainsize),
// warnings about unused arguments
(void) grainsize;
- return f(begin,end);
+# ifndef DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+ f (begin, end);
+# else
+ // work around a problem with MS VC++ where there is no const
+ // operator() in Function
+ Function(f) (begin, end);
+# endif
#else
internal::ReductionOnSubranges<ResultType,Function>
reductor (f, std::plus<ResultType>(), 0);
<< "Global index " << arg1
<< " neither owned nor ghost on proc " << arg2);
- private: /**
- * The global size of the vector over all
- * processors
- */
+ private:
+ /**
+ * The global size of the vector over all processors
+ */
const types::global_dof_index global_size;
/**
* @code
* #include <deal.II/base/path_search.h>
*
- DEAL_II_NAMESPACE_OPEN
- * PathSearch search("MESH");
+ * dealii::PathSearch search("MESH");
* std::string full_name = search.find("grid");
* std::ifstream in(full_name.c_str());
* ...
return tt;
}
+
+
+/**
+ * Multiplication of a tensor of general rank by a scalar
+ * complex<double> from the left.
+ *
+ * @relates Tensor
+ */
+template <int rank, int dim>
+ inline
+ Tensor<rank,dim,std::complex<double> >
+ operator * (const std::complex<double> factor,
+ const Tensor<rank,dim> &t)
+{
+ Tensor<rank,dim,std::complex<double> > tt;
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = factor * t[d];
+ return tt;
+}
+
+
+
+/**
+ * Multiplication of a tensor of general rank by a scalar
+ * complex<double> from the right.
+ *
+ * @relates Tensor
+ */
+template <int rank, int dim>
+ inline
+ Tensor<rank,dim,std::complex<double> >
+ operator * (const Tensor<rank,dim> &t,
+ const std::complex<double> factor)
+{
+ Tensor<rank,dim,std::complex<double> > tt;
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = t[d] * factor;
+ return tt;
+}
+
+
+
DEAL_II_NAMESPACE_CLOSE
#endif
}
+
+/**
+ * Multiplication of a tensor of rank 1 by a scalar complex<double>
+ * from the right.
+ *
+ * @relates Tensor<1,dim,Number>
+ */
+template <int dim>
+inline
+Tensor<1,dim,std::complex<double> >
+ operator * (const Tensor<1,dim> &t,
+ const std::complex<double> factor)
+{
+ Tensor<1,dim,std::complex<double> > tt (false);
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = t[d] * factor;
+ return tt;
+}
+
+
+
+/**
+ * Multiplication of a tensor of rank 1 by a scalar complex<double>
+ * from the left.
+ *
+ * @relates Tensor<1,dim,Number>
+ */
+template <int dim>
+inline
+Tensor<1,dim,std::complex<double> >
+ operator * (const std::complex<double> factor,
+ const Tensor<1,dim> &t)
+{
+ Tensor<1,dim,std::complex<double> > tt (false);
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = t[d] * factor;
+ return tt;
+}
+
+
+
DEAL_II_NAMESPACE_CLOSE
#endif
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.h 32217 2014-01-15 16:34:36Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__time_stepping_h
+#define __deal2__time_stepping_h
+
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/std_cxx1x/function.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * Namespace containing the time stepping methods.
+ *
+ * @author Bruno Turcksin
+ * @date 2014
+ */
+
+namespace TimeStepping
+{
+ /**
+ * Runge-Kutta methods available:
+ * - Explicit methods:
+ * - FORWARD_EULER: first order
+ * - RK_THIRD_ORDER: third order Runge-Kutta
+ * - RK_CLASSIC_FOURTH_ORDER: classical fourth order Runge-Kutta
+ * - Implicit methods:
+ * - BACKWARD_EULER: first order
+ * - IMPLICIT_MIDPOINT: second order
+ * - CRANK_NICHOLSON: second order
+ * - SDIRK_TWO_STAGES: second order
+ * - Embedded explicit methods:
+ * - HEUN_EULER: second order
+ * - BOGACKI_SHAMPINE: third order
+ * - DOPRI: Dormand-Prince fifth order (method used by ode45 in MATLAB)
+ * - FEHLBERG: fifth order
+ * - CASH_KARP: firth order
+ */
+ enum runge_kutta_method { FORWARD_EULER, RK_THIRD_ORDER, RK_CLASSIC_FOURTH_ORDER,
+ BACKWARD_EULER, IMPLICIT_MIDPOINT, CRANK_NICOLSON,
+ SDIRK_TWO_STAGES, HEUN_EULER, BOGACKI_SHAMPINE, DOPRI,
+ FEHLBERG, CASH_KARP
+ };
+
+
+
+ /**
+ * Reason for exiting evolve_one_time_step when using an embedded
+ * method: DELTA_T (the time step is in the valid range), MIN_DELTA_T (the
+ * time step was increased to the minimum acceptable time step), MAX_DELTA_T
+ * (the time step was reduced to the maximum acceptable time step).
+ */
+ enum embedded_runge_kutta_time_step { DELTA_T, MIN_DELTA_T, MAX_DELTA_T };
+
+
+
+ /**
+ * Abstract class for time stepping methods. These methods assume that the
+ * equation has the form: \f$ \frac{\partial y}{\partial t} = f(t,y) \f$.
+ */
+ template <typename VECTOR>
+ class TimeStepping
+ {
+ public:
+ /**
+ * Purely virtual function. This function is used to advance from time @p
+ * t to t+ @p delta_t. @p F is a vector of functions \f$ f(t,y) \f$ that should be
+ * integrated, the input parameters are the time t and the vector y and the
+ * output is value of f at this point. @p J_inverse is a vector
+ * functions that compute the inverse of the Jacobians associated to the
+ * implicit problems. The input parameters are the
+ * time, \f$ \tau \f$, and a vector. The output is the value of function
+ * at this point. This function returns the time at the end of the
+ * time step.
+ */
+ virtual double evolve_one_time_step(
+ std::vector<std_cxx1x::function<VECTOR (const double, const VECTOR &)> > &F,
+ std::vector<std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> > & J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y) = 0;
+
+ /**
+ * Empty structure used to store informations.
+ */
+ struct Status {};
+
+ /**
+ * Purely virtual function that return Status.
+ */
+ virtual const Status &get_status() const = 0;
+ };
+
+
+
+ /**
+ * Base class for the Runge-Kutta method
+ *
+ * @author Damien Lebrun-Grandie, Bruno Turcksin
+ * @date 2014
+ */
+ template <typename VECTOR>
+ class RungeKutta : public TimeStepping<VECTOR>
+ {
+ public:
+ /**
+ * Purely virtual method used to initialize the Runge-Kutta method.
+ */
+ virtual void initialize(runge_kutta_method method) = 0;
+ /**
+ * This function is used to advance from time @p
+ * t to t+ @p delta_t. @p F is a vector of functions \f$ f(t,y) \f$ that should be
+ * integrated, the input parameters are the time t and the vector y and the
+ * output is value of f at this point. @p J_inverse is a vector
+ * functions that compute the inverse of the Jacobians associated to the
+ * implicit problems. The input parameters are the
+ * time, \f$ \tau \f$, and a vector. The output is the value of function
+ * at this point. This function returns the time at the end of the
+ * time step. When using Runge-Kutta methods, @p F and @ J_inverse can
+ * only contain one element.
+ */
+ double evolve_one_time_step(
+ std::vector<std_cxx1x::function<VECTOR (const double, const VECTOR &)> > &F,
+ std::vector<std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> > & J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * Purely virtual function. This function is used to advance from time @p t
+ * to t+ @p delta_t. @p f is the function \f$ f(t,y) \f$ that should be
+ * integrated, the input parameters are the time t and the vector y and the
+ * output is value of f at this point. @p id_minus_tau_J_inverse is a function
+ * that computes \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix,
+ * \f$ \tau \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameters are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ virtual double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y) = 0;
+
+ protected:
+ /**
+ * Number of stages of the Runge-Kutta method.
+ */
+ unsigned int n_stages;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> b;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> c;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<std::vector<double> > a;
+ };
+
+
+
+ /**
+ * ExplicitRungeKutta is derived from RungeKutta and implement the explicit methods.
+ */
+ template <typename VECTOR>
+ class ExplicitRungeKutta : public RungeKutta<VECTOR>
+ {
+ public:
+ using RungeKutta<VECTOR>::evolve_one_time_step;
+
+ /**
+ * Default constructor. initialize(runge_kutta_method) needs to be called
+ * before the object can be used.
+ */
+ ExplicitRungeKutta() {};
+
+ /**
+ * Constructor. This function calls initialize(runge_kutta_method).
+ */
+ ExplicitRungeKutta(runge_kutta_method method);
+
+ /**
+ * Initialize the explicit Runge-Kutta method.
+ */
+ void initialize(runge_kutta_method method);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t. @p f
+ * is the function \f$ f(t,y) \f$ that should be integrated, the input
+ * parameters are the time t and the vector y and the output is value of
+ * f at this point. @p id_minus_tau_J_inverse is a function that computes
+ * \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix, \f$ \tau
+ * \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameter are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t.
+ * This function is similar to the one derived from RungeKutta, but
+ * does not required id_minus_tau_J_inverse because it is not used for
+ * explicit methods. evolve_one_time_step returns the time at the end of the
+ * time step.
+ */
+ double evolve_one_time_step(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * This structure stores the name of the method used.
+ */
+ struct Status : public TimeStepping<VECTOR>::Status
+ {
+ runge_kutta_method method;
+ };
+
+ /**
+ * Return the status of the current object.
+ */
+ const Status &get_status() const;
+
+ private:
+ /**
+ * Compute the different stages needed.
+ */
+ void compute_stages(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages) const;
+
+ /**
+ * Status structure of the object.
+ */
+ Status status;
+ };
+
+
+
+ /**
+ * This class is derived from RungeKutta and implement the implicit
+ * methods. This class works only for Diagonal Implicit Runge-Kutta
+ * (DIRK) methods.
+ */
+ template <typename VECTOR>
+ class ImplicitRungeKutta : public RungeKutta<VECTOR>
+ {
+ public:
+ using RungeKutta<VECTOR>::evolve_one_time_step;
+
+ /**
+ * Default constructor. initialize(runge_kutta_method) and
+ * set_newton_solver_parameters(unsigned int,double)
+ * need to be called before the object can be used.
+ */
+ ImplicitRungeKutta() {};
+
+ /**
+ * Constructor. This function calls initialize(runge_kutta_method) and
+ * initialize the maximum number of iterations and the tolerance of the
+ * Newton solver.
+ */
+ ImplicitRungeKutta(runge_kutta_method method, unsigned int max_it=100, double tolerance=1e-6);
+
+ /**
+ * Initialize the implicit Runge-Kutta method.
+ */
+ void initialize(runge_kutta_method method);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t. @p f
+ * is the function \f$ f(t,y) \f$ that should be integrated, the input
+ * parameters are the time t and the vector y and the output is value of
+ * f at this point. @p id_minus_tau_J_inverse is a function that computes
+ * \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix, \f$ \tau
+ * \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameters are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * Set the maximum number of iterations and the tolerance used by the
+ * Newton solver.
+ */
+ void set_newton_solver_parameters(unsigned int max_it, double tolerance);
+
+ /**
+ * Structure that stores the name of the method, the number of
+ * Newton iterations and the norm of the residual when exiting the
+ * Newton solver.
+ */
+ struct Status : public TimeStepping<VECTOR>::Status
+ {
+ runge_kutta_method method;
+ unsigned int n_iterations;
+ double norm_residual;
+ };
+
+ /**
+ * Return the status of the current object.
+ */
+ const Status &get_status() const;
+
+ private:
+ /**
+ * Compute the different stages needed.
+ */
+ void compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y,
+ std::vector<VECTOR> &f_stages);
+
+ /**
+ * Newton solver used for the implicit stages.
+ */
+ void newton_solve(std_cxx1x::function<void (const VECTOR &,VECTOR &)> get_residual,
+ std_cxx1x::function<VECTOR (const VECTOR &)> id_minus_tau_J_inverse,
+ VECTOR &y);
+
+ /**
+ * Compute the residual needed by the Newton solver.
+ */
+ void compute_residual(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ const VECTOR &old_y,
+ const VECTOR &y,
+ VECTOR &tendency,
+ VECTOR &residual) const;
+
+ /**
+ * When using SDIRK, there is no need to compute the linear combination
+ * of the stages. Thus, when this flag is true, the linear combination
+ * is skipped.
+ */
+ bool skip_linear_combi;
+
+ /**
+ * Maximum number of iterations of the Newton solver.
+ */
+ unsigned int max_it;
+
+ /**
+ * Tolerance of the Newton solver.
+ */
+ double tolerance;
+
+ /**
+ * Status structure of the object.
+ */
+ Status status;
+ };
+
+
+
+ /**
+ * This is class is derived from RungeKutta and implement embedded explicit
+ * methods.
+ */
+ template <typename VECTOR>
+ class EmbeddedExplicitRungeKutta : public RungeKutta<VECTOR>
+ {
+ public:
+ using RungeKutta<VECTOR>::evolve_one_time_step;
+
+ /**
+ * Default constructor. initialize(runge_kutta_method) and
+ * set_time_adaptation_parameters(double, double, double, double, double, double)
+ * need to be called before the object can be used.
+ */
+ EmbeddedExplicitRungeKutta() {};
+
+ /**
+ * Constructor. This function calls initialize(runge_kutta_method) and
+ * initialize the parameters needed for time adaptation.
+ */
+ EmbeddedExplicitRungeKutta(runge_kutta_method method,
+ double coarsen_param = 1.2,
+ double refine_param = 0.8,
+ double min_delta = 1e-14,
+ double max_delta = 1e100,
+ double refine_tol = 1e-8,
+ double coarsen_tol = 1e-12);
+
+ /**
+ * Destructor.
+ */
+ ~EmbeddedExplicitRungeKutta()
+ {
+ free_memory();
+ }
+
+ /**
+ * If necessary, deallocate memory allocated by the object.
+ */
+ void free_memory();
+
+ /**
+ * Initialize the embedded explicit Runge-Kutta method.
+ */
+ void initialize(runge_kutta_method method);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t. @p f
+ * is the function \f$ f(t,y) \f$ that should be integrated, the input
+ * parameters are the time t and the vector y and the output is value of
+ * f at this point. @p id_minus_tau_J_inverse is a function that computes
+ * \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix, \f$ \tau
+ * \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameters are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t.
+ * This function is similar to the one derived from TimeStepping, but
+ * does not required id_minus_tau_J_inverse because it is not used for
+ * explicit methods. evolve_one_time_step returns the time at the end of the
+ * time step.
+ */
+ double evolve_one_time_step(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * Set the parameters necessary for the time adaptation.
+ */
+ void set_time_adaptation_parameters(double coarsen_param,
+ double refine_param,
+ double min_delta,
+ double max_delta,
+ double refine_tol,
+ double coarsen_tol);
+
+ /**
+ * Structure that stores the name of the method, the reason to exit
+ * evolve_one_time_step, the number of iteration inside n_iterations, a guess
+ * of what the next time step should be, and an estimate of the norm of
+ * the error.
+ */
+ struct Status : public TimeStepping<VECTOR>::Status
+ {
+ runge_kutta_method method;
+ embedded_runge_kutta_time_step exit_delta_t;
+ unsigned int n_iterations;
+ double delta_t_guess;
+ double error_norm;
+ };
+
+ /**
+ * Return the status of the current object.
+ */
+ const Status &get_status() const;
+
+ private:
+ /**
+ * Compute the different stages needed.
+ */
+ void compute_stages(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages);
+
+ /**
+ * This parameter is the factor (>1) by which the time step is
+ * multiplied when the time stepping can be coarsen.
+ */
+ double coarsen_param;
+
+ /**
+ * This parameter is the factor (<1) by which the time step is
+ * multiplied when the time stepping must be refined.
+ */
+ double refine_param;
+
+ /**
+ * Smallest time step allowed.
+ */
+ double min_delta_t;
+
+ /**
+ * Largest time step allowed.
+ */
+ double max_delta_t;
+
+ /**
+ * Refinement tolerance: if the error estimate is larger than
+ * refine_tol, the time step is refined.
+ */
+ double refine_tol;
+
+ /**
+ * Coarsening tolerance: if the error estimate is smaller than
+ * coarse_tol, the time step is coarsen.
+ */
+ double coarsen_tol;
+
+ /**
+ * If the flag is true, the last stage is the same as the first stage
+ * and one evaluation of f can be saved.
+ */
+ bool last_same_as_first;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> b1;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> b2;
+
+ /**
+ * If the last_same_as_first flag is set to true, the last stage is
+ * saved and reused as the first stage of the next time step.
+ */
+ VECTOR *last_stage;
+
+ /**
+ * Status structure of the object.
+ */
+ Status status;
+ };
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.h 32217 2014-01-15 16:34:36Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__time_stepping_templates_h
+#define __deal2__time_stepping_templates_h
+
+#include <deal.II/base/std_cxx1x/bind.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/time_stepping.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace TimeStepping
+{
+ // ----------------------------------------------------------------------
+ // RungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ double RungeKutta<VECTOR>::evolve_one_time_step(
+ std::vector<std_cxx1x::function<VECTOR (const double, const VECTOR &)> > &F,
+ std::vector<std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> > & J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ AssertThrow(F.size()==0,
+ ExcMessage("RungeKutta methods cannot handle more that one function to integate."));
+ AssertThrow(J_inverse.size()==0,
+ ExcMessage("RungeKutta methods cannot handle more that one function to integate."));
+
+ return evolve_one_time_step(F[0],J_inverse[0],t,delta_t,y);
+ }
+
+
+
+ // ----------------------------------------------------------------------
+ // ExplicitRungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ ExplicitRungeKutta<VECTOR>::ExplicitRungeKutta(runge_kutta_method method)
+ {
+ initialize(method);
+ }
+
+
+
+ template <typename VECTOR>
+ void ExplicitRungeKutta<VECTOR>::initialize(runge_kutta_method method)
+ {
+ status.method = method;
+
+ switch (method)
+ {
+ case (FORWARD_EULER) :
+ {
+ this->n_stages = 1;
+ this->b.push_back(1.0);
+ this->c.push_back(0.0);
+
+ break;
+ }
+ case (RK_THIRD_ORDER) :
+ {
+ this->n_stages = 3;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ this->b.push_back(1.0/6.0);
+ this->b.push_back(2.0/3.0);
+ this->b.push_back(1.0/6.0);
+ this->c.push_back(0.0);
+ this->c.push_back(0.5);
+ this->c.push_back(1.0);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = -1.0;
+ tmp[1] = 2.0;
+ this->a.push_back(tmp);
+
+ break;
+ }
+ case (RK_CLASSIC_FOURTH_ORDER) :
+ {
+ this->n_stages = 4;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.0;
+ tmp[1] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[1] = 0.0;
+ tmp[2] = 1.0;
+ this->a.push_back(tmp);
+ this->b.push_back(1.0/6.0);
+ this->b.push_back(1.0/3.0);
+ this->b.push_back(1.0/3.0);
+ this->b.push_back(1.0/6.0);
+ this->c.push_back(0.0);
+ this->c.push_back(0.5);
+ this->c.push_back(0.5);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ default :
+ {
+ AssertThrow(false,ExcMessage("Unimplemented explicit Runge-Kutta method."));
+ }
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ double ExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ return evolve_one_time_step(f,t,delta_t,y);
+ }
+
+
+
+ template <typename VECTOR>
+ double ExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ std::vector<VECTOR> f_stages(this->n_stages,y);
+ // Compute the different stages needed.
+ compute_stages(f,t,delta_t,y,f_stages);
+
+ // Linear combinations of the stages.
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ y.sadd(1.,delta_t*this->b[i],f_stages[i]);
+
+ return (t+delta_t);
+ }
+
+
+
+ template <typename VECTOR>
+ const typename ExplicitRungeKutta<VECTOR>::Status &ExplicitRungeKutta<VECTOR>::get_status() const
+ {
+ return status;
+ }
+
+
+
+ template <typename VECTOR>
+ void ExplicitRungeKutta<VECTOR>::compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages) const
+ {
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ {
+ VECTOR Y(y);
+ for (unsigned int j=0; j<i; ++j)
+ Y.sadd(1.,delta_t*this->a[i][j],f_stages[j]);
+ // Evaluate the function f at the point (t+c[i]*delta_t,Y).
+ f_stages[i] = f(t+this->c[i]*delta_t,Y);
+ }
+ }
+
+
+
+ // ----------------------------------------------------------------------
+ // ImplicitRungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ ImplicitRungeKutta<VECTOR>::ImplicitRungeKutta(runge_kutta_method method,
+ unsigned int max_it,
+ double tolerance)
+ :
+ RungeKutta<VECTOR> (),
+ skip_linear_combi(false),
+ max_it(max_it),
+ tolerance(tolerance)
+ {
+ initialize(method);
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::initialize(runge_kutta_method method)
+ {
+ status.method = method;
+
+ switch (method)
+ {
+ case (BACKWARD_EULER) :
+ {
+ this->n_stages = 1;
+ this->a.push_back(std::vector<double>(1, 1.0));
+ this->b.push_back(1.0);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ case (IMPLICIT_MIDPOINT) :
+ {
+ this->a.push_back(std::vector<double>(1, 0.5));
+ this->b.push_back(1.0);
+ this->c.push_back(0.5);
+ this->n_stages = 1;
+
+ break;
+ }
+ case (CRANK_NICOLSON) :
+ {
+ this->n_stages = 2;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ this->a.push_back(std::vector<double>(1, 0.0));
+ this->a.push_back(std::vector<double>(2, 0.5));
+ this->b.push_back(0.5);
+ this->b.push_back(0.5);
+ this->c.push_back(0.0);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ case (SDIRK_TWO_STAGES) :
+ {
+ this->n_stages = 2;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ double const gamma = 1.0 - 1.0 / std::sqrt(2.0);
+ this->b.push_back(1.0 - gamma);
+ this->b.push_back(gamma);
+ this->a.push_back(std::vector<double>(1, gamma));
+ this->a.push_back(this->b);
+ this->c.push_back(gamma);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ default :
+ {
+ AssertThrow(false,ExcMessage("Unimplemented implicit Runge-Kutta method."));
+ }
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ double ImplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ VECTOR old_y(y);
+ std::vector<VECTOR> f_stages(this->n_stages,y);
+ // Compute the different stages needed.
+ compute_stages(f,id_minus_tau_J_inverse,t,delta_t,y,f_stages);
+
+ // If necessary, compute the linear combinations of the stages.
+ if (skip_linear_combi==false)
+ {
+ y = old_y;
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ y.sadd(1.,delta_t*this->b[i],f_stages[i]);
+ }
+
+ return (t+delta_t);
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::set_newton_solver_parameters(unsigned int max_it_, double tolerance_)
+ {
+ max_it = max_it_;
+ tolerance = tolerance_;
+ }
+
+
+
+ template <typename VECTOR>
+ const typename ImplicitRungeKutta<VECTOR>::Status &ImplicitRungeKutta<VECTOR>::get_status() const
+ {
+ return status;
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y,
+ std::vector<VECTOR> &f_stages)
+ {
+ VECTOR z(y);
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ {
+ VECTOR old_y(z);
+ for (unsigned int j=0; j<i; ++j)
+ old_y.sadd(1.,delta_t*this->a[i][j],f_stages[j]);
+
+ // Solve the nonlinear system using Newton's method
+ const double new_t = t+this->c[i]*delta_t;
+ const double new_delta_t = this->a[i][i]*delta_t;
+ newton_solve(std_cxx1x::bind(&ImplicitRungeKutta<VECTOR>::compute_residual,this,f,new_t,new_delta_t,
+ std_cxx1x::cref(old_y),std_cxx1x::_1,std_cxx1x::ref(f_stages[i]),std_cxx1x::_2),
+ std_cxx1x::bind(id_minus_tau_J_inverse,new_t,new_delta_t,std_cxx1x::_1),y);
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::newton_solve(
+ std_cxx1x::function<void (const VECTOR &,VECTOR &)> get_residual,
+ std_cxx1x::function<VECTOR (const VECTOR &)> id_minus_tau_J_inverse,
+ VECTOR &y)
+ {
+ VECTOR residual(y);
+ get_residual(y,residual);
+ unsigned int i=0;
+ const double initial_residual_norm = residual.l2_norm();
+ double norm_residual = initial_residual_norm;
+ while (i<max_it)
+ {
+ y.sadd(1.0,-1.0,id_minus_tau_J_inverse(residual));
+ get_residual(y,residual);
+ norm_residual = residual.l2_norm();
+ if (norm_residual < tolerance)
+ break;
+ ++i;
+ }
+ status.n_iterations = i+1;
+ status.norm_residual = norm_residual;
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::compute_residual(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ const VECTOR &old_y,
+ const VECTOR &y,
+ VECTOR &tendency,
+ VECTOR &residual) const
+ {
+ // The tendency is stored to save one evaluation of f.
+ tendency = f(t,y);
+ residual = tendency;
+ residual.sadd(delta_t,1.0,old_y);
+ residual.sadd(1.0,-1.,y);
+ }
+
+
+
+ // ----------------------------------------------------------------------
+ // EmbeddedExplicitRungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ EmbeddedExplicitRungeKutta<VECTOR>::EmbeddedExplicitRungeKutta(runge_kutta_method method,
+ double coarsen_param,
+ double refine_param,
+ double min_delta,
+ double max_delta,
+ double refine_tol,
+ double coarsen_tol)
+ :
+ coarsen_param(coarsen_param),
+ refine_param(refine_param),
+ min_delta_t(min_delta),
+ max_delta_t(max_delta),
+ refine_tol(refine_tol),
+ coarsen_tol(coarsen_tol),
+ last_same_as_first(false),
+ last_stage(NULL)
+ {
+ initialize(method);
+ }
+
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::initialize(runge_kutta_method method)
+ {
+ status.method = method;
+
+ switch (method)
+ {
+ case (HEUN_EULER) :
+ {
+ this->n_stages = 2;
+ this->a.push_back(std::vector<double>());
+ this->a.push_back(std::vector<double>(1, 1.0));
+ this->c.push_back(0.0);
+ this->c.push_back(1.0);
+ b1.push_back(0.5);
+ b1.push_back(0.5);
+ b2.push_back(1.0);
+ b2.push_back(0.0);
+
+ break;
+ }
+ case (BOGACKI_SHAMPINE) :
+ {
+ last_same_as_first = true;
+ this->n_stages = 4;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.0;
+ tmp[1] = 0.75;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 2.0/9.0;
+ tmp[1] = 1.0/3.0;
+ tmp[2] = 4.0/9.0;
+ this->a.push_back(tmp);
+ this->c.push_back(0.0);
+ this->c.push_back(0.5);
+ this->c.push_back(0.75);
+ this->c.push_back(1.0);
+ this->b1.push_back(2.0/9.0);
+ this->b1.push_back(1.0/3.0);
+ this->b1.push_back(4.0/9.0);
+ this->b1.push_back(0.0);
+ this->b2.push_back(7.0/24.0);
+ this->b2.push_back(0.25);
+ this->b2.push_back(1.0/3.0);
+ this->b2.push_back(0.125);
+
+ break;
+ }
+ case (DOPRI) :
+ {
+ last_same_as_first = true;
+ this->n_stages = 7;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 1./5.;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 3./40.;
+ tmp[1] = 9./40.;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 44./45.;
+ tmp[1] = -56./15.;
+ tmp[2] = 32./9.;
+ this->a.push_back(tmp);
+ tmp.resize(4);
+ tmp[0] = 19372./6561.;
+ tmp[1] = -25360./2187.;
+ tmp[2] = 64448./6561.;
+ tmp[3] = -212./729.;
+ this->a.push_back(tmp);
+ tmp.resize(5);
+ tmp[0] = -9017./3168.;
+ tmp[1] = -355./33.;
+ tmp[2] = 46732./5247.;
+ tmp[3] = 49./176.;
+ tmp[4] = -5103./18656;
+ this->a.push_back(tmp);
+ tmp.resize(6);
+ tmp[0] = 35./384.;
+ tmp[1] = 0.;
+ tmp[2] = 500./1113.;
+ tmp[3] = 125./192.;
+ tmp[4] = -2187./6784.;
+ tmp[5] = 11./84.;
+ this->a.push_back(tmp);
+ this->c.push_back(0.);
+ this->c.push_back(1./5.);
+ this->c.push_back(3./10.);
+ this->c.push_back(4./5.);
+ this->c.push_back(8./9.);
+ this->c.push_back(1.);
+ this->c.push_back(1.);
+ this->b1.push_back(35./384.);
+ this->b1.push_back(0.);
+ this->b1.push_back(500./1113.);
+ this->b1.push_back(125./192.);
+ this->b1.push_back(-2187./6784.);
+ this->b1.push_back(11./84.);
+ this->b1.push_back(0.);
+ this->b2.push_back(5179./57600.);
+ this->b2.push_back(0.);
+ this->b2.push_back(7571./16695.);
+ this->b2.push_back(393./640.);
+ this->b2.push_back(-92097./339200.);
+ this->b2.push_back(187./2100.);
+ this->b2.push_back(1./40.);
+
+ break;
+ }
+ case (FEHLBERG) :
+ {
+ this->n_stages = 6;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.25;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.09375;
+ tmp[1] = 0.28125;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 1932.0/2197.0;
+ tmp[1] = -7200.0/2197.0;
+ tmp[2] = 7296.0/2197.0;
+ this->a.push_back(tmp);
+ tmp.resize(4);
+ tmp[0] = 439.0/216.0;
+ tmp[1] = -8.0;
+ tmp[2] = 3680.0/513.0;
+ tmp[3] = -845.0/4104.0;
+ this->a.push_back(tmp);
+ tmp.resize(5);
+ tmp[0] = -8.0/27.0;
+ tmp[1] = 2.0;
+ tmp[2] = -3544.0/2565.0;
+ tmp[3] = 1859.0/4104.0;
+ tmp[4] = -0.275;
+ this->a.push_back(tmp);
+ this->c.push_back(0.0);
+ this->c.push_back(0.25);
+ this->c.push_back(0.375);
+ this->c.push_back(12.0/13.0);
+ this->c.push_back(1.0);
+ this->c.push_back(0.5);
+ this->b1.push_back(16.0/135.0);
+ this->b1.push_back(0.0);
+ this->b1.push_back(6656.0/12825.0);
+ this->b1.push_back(28561.0/56430.0);
+ this->b1.push_back(-0.18);
+ this->b1.push_back(2.0/55.0);
+ this->b2.push_back(25.0/216.0);
+ this->b2.push_back(0.0);
+ this->b2.push_back(1408.0/2565.0);
+ this->b2.push_back(2197.0/4104.0);
+ this->b2.push_back(-0.2);
+ this->b2.push_back(0.0);
+
+ break;
+ }
+ case (CASH_KARP) :
+ {
+ this->n_stages = 6;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.2;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.075;
+ tmp[1] = 0.225;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 0.3;
+ tmp[1] = -0.9;
+ tmp[2] = 1.2;
+ this->a.push_back(tmp);
+ tmp.resize(4);
+ tmp[0] = -11.0/54.0;
+ tmp[1] = 2.5;
+ tmp[2] = -70.0/27.0;
+ tmp[3] = 35.0/27.0;
+ this->a.push_back(tmp);
+ tmp.resize(5);
+ tmp[0] = 1631.0/55296.0;
+ tmp[1] = 175.0/512.0;
+ tmp[2] = 575.0/13824.0;
+ tmp[3] = 44275.0/110592.0;
+ tmp[4] = 253.0/4096.0;
+ this->a.push_back(tmp);
+ this->c.push_back(0.0);
+ this->c.push_back(0.2);
+ this->c.push_back(0.3);
+ this->c.push_back(0.6);
+ this->c.push_back(1.0);
+ this->c.push_back(0.875);
+ this->b1.push_back(37.0/378.0);
+ this->b1.push_back(0.0);
+ this->b1.push_back(250.0/621.0);
+ this->b1.push_back(125.0/594.0);
+ this->b1.push_back(0.0);
+ this->b1.push_back(512.0/1771.0);
+ this->b2.push_back(2825.0/27648.0);
+ this->b2.push_back(0.0);
+ this->b2.push_back(18575.0/48384.0);
+ this->b2.push_back(13525.0/55296.0);
+ this->b2.push_back(277.0/14336.0);
+ this->b2.push_back(0.25);
+
+ break;
+ }
+ default :
+ {
+ AssertThrow(false,ExcMessage("Unimplemented Embedded Runge-Kutta method."));
+ }
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::free_memory()
+ {
+ if (last_stage!=NULL)
+ delete last_stage;
+
+ last_stage = NULL;
+ }
+
+
+
+ template <typename VECTOR>
+ double EmbeddedExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ return evolve_one_time_step(f,t,delta_t,y);
+ }
+
+
+
+ template <typename VECTOR>
+ double EmbeddedExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t, double delta_t, VECTOR &y)
+ {
+ bool done = false;
+ unsigned int count = 0;
+ double error_norm = 0.;
+ VECTOR old_y(y);
+ VECTOR error(y);
+ std::vector<VECTOR> f_stages(this->n_stages,y);
+
+ while (!done)
+ {
+ error = 0.;
+ y = old_y;
+ // Compute the different stages needed.
+ compute_stages(f,t,delta_t,y,f_stages);
+
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ {
+ y.sadd(1.,delta_t*this->b1[i],f_stages[i]);
+ error.sadd(1.,delta_t*(b2[i]-b1[i]),f_stages[i]);
+ }
+
+ error_norm = error.l2_norm();
+ // Check if the norm of error is less than the coarsening tolerance
+ if (error_norm<coarsen_tol)
+ {
+ done = true;
+ // Increase the guessed time step
+ double new_delta_t = delta_t*coarsen_param;
+ // Check that the guessed time step is smaller than the maximum time
+ // step allowed.
+ if (new_delta_t>max_delta_t)
+ {
+ status.exit_delta_t = MAX_DELTA_T;
+ status.delta_t_guess = max_delta_t;
+ }
+ else
+ {
+ status.exit_delta_t = DELTA_T;
+ status.delta_t_guess = delta_t;
+ }
+ }
+ // Check if the norm of error is less than the refining tolerance
+ else if (error_norm<refine_tol)
+ {
+ done = true;
+ status.exit_delta_t = DELTA_T;
+ status.delta_t_guess = delta_t;
+ }
+ else
+ {
+ // If the time step is already the smallest acceptable, exit.
+ if (delta_t==min_delta_t)
+ {
+ done = true;
+ status.exit_delta_t = MIN_DELTA_T;
+ status.delta_t_guess = delta_t;
+ }
+ // Reduce the time step.
+ else
+ {
+ delta_t *= refine_param;
+ if (delta_t<min_delta_t)
+ delta_t = min_delta_t;
+ }
+ }
+
+ ++count;
+ }
+
+ // Save the last stage if necessary
+ if (last_same_as_first==true)
+ {
+ if (last_stage==NULL)
+ last_stage = new VECTOR(f_stages.back());
+ else
+ *last_stage = f_stages.back();
+ }
+
+ status.n_iterations = count;
+ status.error_norm = error_norm;
+
+ return (t+delta_t);
+ }
+
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::set_time_adaptation_parameters(double coarsen_param_,
+ double refine_param_,
+ double min_delta_,
+ double max_delta_,
+ double refine_tol_,
+ double coarsen_tol_)
+ {
+ coarsen_param = coarsen_param_;
+ refine_param = refine_param_;
+ min_delta_t = min_delta_;
+ max_delta_t = max_delta_;
+ refine_tol = refine_tol_;
+ coarsen_tol = coarsen_tol_;
+ }
+
+
+
+ template <typename VECTOR>
+ const typename EmbeddedExplicitRungeKutta<VECTOR>::Status &EmbeddedExplicitRungeKutta<VECTOR>::get_status() const
+ {
+ return status;
+ }
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages)
+ {
+ VECTOR Y(y);
+ unsigned int i = 0;
+
+ // If the last stage is the same as the first, we can skip the evaluation
+ // of the first stage.
+ if (last_same_as_first==true)
+ {
+ if (last_stage!=NULL)
+ {
+ f_stages[0] = *last_stage;
+ i = 1;
+ }
+ }
+
+ for (; i<this->n_stages; ++i)
+ {
+ Y = y;
+ for (unsigned int j = 0; j < i; ++j)
+ Y.sadd(1.0,delta_t*this->a[i][j],f_stages[j]);
+ f_stages[i] = f(t+this->c[i]*delta_t,Y);
+ }
+ }
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
/**
- * Fills the @param stats structure with
+ * Fills the @p stats structure with
* information about the memory
* consumption of this process. This is
* only implemented on Linux.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#define __deal2__vectorization_h
#include <deal.II/base/config.h>
-#include <deal.II/base/std_cxx1x/type_traits.h>
#include <deal.II/base/exceptions.h>
-#include <deal.II/base/memory_consumption.h>
-#include <deal.II/base/parallel.h>
#include <cmath>
-#include <cstring>
// Note:
// The flag DEAL_II_COMPILER_VECTORIZATION_LEVEL is essentially constructed
// according to the following scheme
+// #ifdef __AVX512F__
+// #define DEAL_II_COMPILER_VECTORIZATION_LEVEL 3
// #ifdef __AVX__
// #define DEAL_II_COMPILER_VECTORIZATION_LEVEL 2
// #elif defined (__SSE2__)
// In addition to checking the flags __AVX__ and __SSE2__, a configure test
// ensures that these feature are not only present but also working properly.
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL == 2 // AVX
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 2 // AVX, AVX-512
#include <immintrin.h>
-#include <mm_malloc.h>
#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL == 1 // SSE2
#include <emmintrin.h>
-#include <mm_malloc.h>
#endif
DEAL_II_NAMESPACE_OPEN
-// for safety, also check that __AVX__ is defined in case the user manually
+// for safety, also check that __AVX512F__ is defined in case the user manually
// set some conflicting compile flags which prevent compilation
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL == 2 && defined(__AVX__)
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL == 3 && defined(__AVX512F__)
+
+/**
+ * Specialization of VectorizedArray class for double and AVX-512.
+ */
+template <>
+class VectorizedArray<double>
+{
+public:
+ /**
+ * This gives the number of vectors collected in this class.
+ */
+ static const unsigned int n_array_elements = 8;
+
+ /**
+ * This function can be used to set all data fields to a given scalar.
+ */
+ VectorizedArray &
+ operator = (const double x)
+ {
+ data = _mm256_set_pd(x, x, x, x, x, x, x, x);
+ return *this;
+ }
+
+ /**
+ * Access operator.
+ */
+ double &
+ operator [] (const unsigned int comp)
+ {
+ AssertIndexRange (comp, 8);
+ return *(reinterpret_cast<double *>(&data)+comp);
+ }
+
+ /**
+ * Constant access operator.
+ */
+ const double &
+ operator [] (const unsigned int comp) const
+ {
+ AssertIndexRange (comp, 8);
+ return *(reinterpret_cast<const double *>(&data)+comp);
+ }
+
+ /**
+ * Addition.
+ */
+ VectorizedArray &
+ operator += (const VectorizedArray &vec)
+ {
+ // if the compiler supports vector arithmetics, we can simply use +=
+ // operator on the given data type. Otherwise, we need to use the built-in
+ // intrinsic command for __m512d
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data += vec.data;
+#else
+ data = _mm512_add_pd(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Subtraction.
+ */
+ VectorizedArray &
+ operator -= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data -= vec.data;
+#else
+ data = _mm512_sub_pd(data,vec.data);
+#endif
+ return *this;
+ }
+ /**
+ * Multiplication.
+ */
+ VectorizedArray &
+ operator *= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data *= vec.data;
+#else
+ data = _mm512_mul_pd(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Division.
+ */
+ VectorizedArray &
+ operator /= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data /= vec.data;
+#else
+ data = _mm512_div_pd(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Actual data field. Since this class represents a POD data type, it
+ * remains public.
+ */
+ __m512d data;
+
+private:
+ /**
+ * Returns the square root of this field. Not for use in user code. Use
+ * sqrt(x) instead.
+ */
+ VectorizedArray
+ get_sqrt () const
+ {
+ VectorizedArray res;
+ res.data = _mm512_sqrt_pd(data);
+ return res;
+ }
+
+ /**
+ * Returns the absolute value of this field. Not for use in user code. Use
+ * abs(x) instead.
+ */
+ VectorizedArray
+ get_abs () const
+ {
+ // to compute the absolute value, perform bitwise andnot with -0. This
+ // will leave all value and exponent bits unchanged but force the sign
+ // value to +.
+ __m256d mask = _mm256_set_pd (-0., -0., -0., -0., -0., -0., -0., -0.);
+ VectorizedArray res;
+ res.data = _mm256_andnot_pd(mask, data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise maximum of this field and another one. Not for
+ * use in user code. Use max(x,y) instead.
+ */
+ VectorizedArray
+ get_max (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_max_pd (data, other.data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise minimum of this field and another one. Not for
+ * use in user code. Use min(x,y) instead.
+ */
+ VectorizedArray
+ get_min (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_min_pd (data, other.data);
+ return res;
+ }
+
+ /**
+ * Make a few functions friends.
+ */
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::sqrt (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::abs (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::max (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::min (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+};
+
+
+
+/**
+ * Specialization for float and AVX.
+ */
+template<>
+class VectorizedArray<float>
+{
+public:
+ /**
+ * This gives the number of vectors collected in this class.
+ */
+ static const unsigned int n_array_elements = 16;
+
+ /**
+ * This function can be used to set all data fields to a given scalar.
+ */
+ VectorizedArray &
+ operator = (const float x)
+ {
+ data = _mm256_set_ps(x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x);
+ return *this;
+ }
+
+ /**
+ * Access operator.
+ */
+ float &
+ operator [] (const unsigned int comp)
+ {
+ AssertIndexRange (comp, 16);
+ return *(reinterpret_cast<float *>(&data)+comp);
+ }
+
+ /**
+ * Constant access operator.
+ */
+ const float &
+ operator [] (const unsigned int comp) const
+ {
+ AssertIndexRange (comp, 16);
+ return *(reinterpret_cast<const float *>(&data)+comp);
+ }
+
+ /**
+ * Addition.
+ */
+ VectorizedArray &
+ operator += (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data += vec.data;
+#else
+ data = _mm512_add_ps(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Subtraction.
+ */
+ VectorizedArray &
+ operator -= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data -= vec.data;
+#else
+ data = _mm512_sub_ps(data,vec.data);
+#endif
+ return *this;
+ }
+ /**
+ * Multiplication.
+ */
+ VectorizedArray &
+ operator *= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data *= vec.data;
+#else
+ data = _mm512_mul_ps(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Division.
+ */
+ VectorizedArray &
+ operator /= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data /= vec.data;
+#else
+ data = _mm512_div_ps(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Actual data field. Since this class represents a POD data type, it
+ * remains public.
+ */
+ __m512 data;
+
+private:
+
+ /**
+ * Returns the square root of this field. Not for use in user code. Use
+ * sqrt(x) instead.
+ */
+ VectorizedArray
+ get_sqrt () const
+ {
+ VectorizedArray res;
+ res.data = _mm512_sqrt_ps(data);
+ return res;
+ }
+
+ /**
+ * Returns the absolute value of this field. Not for use in user code. Use
+ * abs(x) instead.
+ */
+ VectorizedArray
+ get_abs () const
+ {
+ // to compute the absolute value, perform
+ // bitwise andnot with -0. This will leave all
+ // value and exponent bits unchanged but force
+ // the sign value to +.
+ __m256 mask = _mm512_setzero_ps (-0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f,
+ -0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f);
+ VectorizedArray res;
+ res.data = _mm512_andnot_ps(mask, data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise maximum of this field and another one. Not for
+ * use in user code. Use max(x,y) instead.
+ */
+ VectorizedArray
+ get_max (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_max_ps (data, other.data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise minimum of this field and another one. Not for
+ * use in user code. Use min(x,y) instead.
+ */
+ VectorizedArray
+ get_min (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_min_ps (data, other.data);
+ return res;
+ }
+
+ /**
+ * Make a few functions friends.
+ */
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::sqrt (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::abs (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::max (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::min (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+};
+
+
+#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL == 2 && defined(__AVX__)
/**
* Specialization of VectorizedArray class for double and AVX.
-/**
- * This namespace defines the copy and set functions used in
- * AlignedVector. These functions operate in parallel when there are enough
- * elements in the vector.
- */
-namespace internal
-{
- /**
- * Move and class that actually issues the copy commands in
- * AlignedVector. This class is based on the specialized for loop base class
- * ParallelForLoop in parallel.h whose purpose is the following: When
- * calling a parallel for loop on AlignedVector with apply_to_subranges, it
- * generates different code for every different argument we might choose (as
- * it is templated). This gives a lot of code (e.g. it triples the memory
- * required for compiling the file matrix_free.cc and the final object size
- * is several times larger) which is completely useless. Therefore, this
- * class channels all copy commands through one call to apply_to_subrange
- * for all possible types, which makes the copy operation much cleaner
- * (thanks to a virtual function, whose cost is negligible in this context).
- *
- * @relates AlignedVector
- */
- template <typename T>
- class AlignedVectorMove : private parallel::ParallelForInteger
- {
- static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
- public:
- /**
- * Constructor. Issues a parallel call if
- * there are sufficiently many elements,
- * otherwise work in serial. Copies the data
- * from source to destination and then calls
- * destructor on the source. If the optional
- * argument is set to true, the source is left
- * untouched instead.
- */
- AlignedVectorMove (T *source_begin,
- T *source_end,
- T *destination,
- bool copy_only = false)
- :
- source_ (source_begin),
- destination_ (destination),
- copy_only_ (copy_only)
- {
- Assert (source_end >= source_begin, ExcInternalError());
- const std::size_t size = source_end - source_begin;
- if (size < minimum_parallel_grain_size)
- apply_to_subrange (0, size);
- else
- apply_parallel (0, size, minimum_parallel_grain_size);
- }
-
- /**
- * This method moves elements from the source
- * to the destination given in the constructor
- * on a subrange given by two integers.
- */
- virtual void apply_to_subrange (const std::size_t begin,
- const std::size_t end) const
- {
- // for classes trivial assignment can use
- // memcpy
- if (std_cxx1x::is_trivial<T>::value == true)
- std::memcpy (destination_+begin, source_+begin, (end-begin)*sizeof(T));
- else if (copy_only_ == false)
- for (std::size_t i=begin; i<end; ++i)
- {
- // initialize memory, copy, and destruct
- new (&destination_[i]) T;
- destination_[i] = source_[i];
- source_[i].~T();
- }
- else
- for (std::size_t i=begin; i<end; ++i)
- {
- new (&destination_[i]) T;
- destination_[i] = source_[i];
- }
- }
-
- private:
- T *source_;
- T *destination_;
- const bool copy_only_;
- };
-
- /**
- * Class that issues the set commands for AlignedVector.
- *
- * @relates AlignedVector
- */
- template <typename T>
- class AlignedVectorSet : private parallel::ParallelForInteger
- {
- static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
- public:
- /**
- * Constructor. Issues a parallel call if
- * there are sufficiently many elements,
- * otherwise work in serial.
- */
- AlignedVectorSet (const std::size_t size,
- const T &element,
- T *destination)
- :
- element_ (element),
- destination_ (destination),
- trivial_element (false)
- {
- if (size == 0)
- return;
-
- if (std_cxx1x::is_trivial<T>::value == true)
- {
- const unsigned char zero [sizeof(T)] = {};
- if (std::memcmp(zero, &element, sizeof(T)) == 0)
- trivial_element = true;
- }
- if (size < minimum_parallel_grain_size)
- apply_to_subrange (0, size);
- else
- apply_parallel (0, size, minimum_parallel_grain_size);
- }
-
- private:
-
- /**
- * This sets elements on a subrange given by
- * two integers.
- */
- virtual void apply_to_subrange (const std::size_t begin,
- const std::size_t end) const
- {
- // for classes with trivial assignment of zero
- // can use memset
- if (std_cxx1x::is_trivial<T>::value == true && trivial_element)
- std::memset (destination_+begin, 0, (end-begin)*sizeof(T));
- else
- for (std::size_t i=begin; i<end; ++i)
- {
- // initialize memory and set
- new (&destination_[i]) T;
- destination_[i] = element_;
- }
- }
-
- const T &element_;
- mutable T *destination_;
- bool trivial_element;
- };
-} // end of namespace internal
-
-
-/**
- * This is a replacement class for std::vector to be used in combination with
- * VectorizedArray and derived data types. It allocates memory aligned to
- * addresses of a vectorized data type (for SSE, this is necessary in order to
- * avoid segfaults, and for AVX it considerably increases performance). This
- * could also be achieved by proving std::vector with a user-defined
- * allocator. On the other hand, writing an own small vector class lets us
- * insert assertions more easily, and cut some unnecessary functionality. Note
- * that this vector is a bit more memory-consuming than std::vector because of
- * alignment, so it is recommended to only use this vector on long vectors.
- *
- * @p author Katharina Kormann, Martin Kronbichler, 2011
- */
-template < class T >
-class AlignedVector
-{
-public:
- /**
- * Declare standard types used in all
- * containers. These types parallel those
- * in the <tt>C++</tt> standard libraries
- * <tt>vector<...></tt> class.
- */
- typedef T value_type;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
- typedef value_type *iterator;
- typedef const value_type *const_iterator;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- typedef std::size_t size_type;
-
- /**
- * Empty constructor. Sets the vector size to
- * zero.
- */
- AlignedVector ()
- :
- _data (0),
- _end_data (0),
- _end_allocated (0)
- {};
-
- /**
- * Sets the vector size to the given size and
- * initializes all elements with T().
- */
- AlignedVector (const size_type size)
- :
- _data (0),
- _end_data (0),
- _end_allocated (0)
- {
- if (size > 0)
- resize (size);
- }
-
- /**
- * Destructor.
- */
- ~AlignedVector ()
- {
- clear();
- }
-
- /**
- * Copy constructor.
- */
- AlignedVector (const AlignedVector<T> &vec)
- :
- _data (0),
- _end_data (0),
- _end_allocated (0)
- {
- // do not invalidate old data
- resize_fast (vec._end_data - vec._data);
- internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
- }
-
- /**
- * Assignment to the input vector @p vec.
- */
- AlignedVector &
- operator = (const AlignedVector<T> &vec)
- {
- clear();
- resize_fast (vec._end_data - vec._data);
- internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
- return *this;
- }
-
- /**
- * Change the size of the vector. It keeps old
- * elements previously available but does not
- * initialize the newly allocated memory,
- * leaving it in an undefined state.
- */
- void resize_fast (const size_type size)
- {
- reserve (size);
- _end_data = _data + size;
- }
-
- /**
- * Change the size of the vector. It keeps old
- * elements previously available, and
- * initializes each element with the specified
- * data. If the new vector size is shorter
- * than the old one, the memory is not
- * released unless the new size is zero.
- */
- void resize (const size_type size_in,
- const T &init = T())
- {
- const size_type old_size = size();
- if (std_cxx1x::is_trivial<T>::value == false && size_in < old_size)
- {
- // call destructor on fields that are released
- while (_end_data != _data+size_in)
- (--_end_data)->~T();
- }
-
- resize_fast (size_in);
- // now _size is set correctly, need to set the
- // values
- if (size_in > old_size)
- internal::AlignedVectorSet<T> (size_in-old_size, init,
- _data+old_size);
- }
-
- /**
- * Reserve memory space for @p size
- * elements. If the argument @p size is set to
- * zero, all previously allocated memory is
- * released.
- *
- * In order to avoid too frequent reallocation
- * (which involves copy of the data), this
- * function doubles the amount of memory
- * occupied when the given size is larger than
- * the previously allocated size.
- */
- void reserve (const size_type size_alloc)
- {
- const size_type old_size = _end_data - _data;
- const size_type allocated_size = _end_allocated - _data;
- if (size_alloc > allocated_size)
- {
- // if we continuously increase the size of the
- // vector, we might be reallocating a lot of
- // times. therefore, try to increase the size
- // more aggressively
- size_type new_size = size_alloc;
- if (size_alloc < (2 * allocated_size))
- new_size = 2 * allocated_size;
-
- const size_type size_actual_allocate = new_size * sizeof(T);
-
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
-
- // allocate and align along boundaries of the
- // size of VectorizedArray<double>, which is
- // 16 bytes for SSE and 32 bytes for AVX
- T *new_data = static_cast<T *>(_mm_malloc (size_actual_allocate,
- sizeof(VectorizedArray<double>)));
-#else
- T *new_data = static_cast<T *>(malloc (size_actual_allocate));
-#endif
- if (new_data == 0)
- throw std::bad_alloc();
-
- // copy data in case there was some content
- // before and release the old memory with the
- // function corresponding to the one used for
- // allocating
- std::swap (_data, new_data);
- _end_data = _data + old_size;
- _end_allocated = _data + new_size;
- if (_end_data != _data)
- {
- internal::AlignedVectorMove<T>(new_data, new_data + old_size,
- _data);
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
- _mm_free(new_data);
-#else
- free(new_data);
-#endif
- }
- }
- else if (size_alloc == 0)
- clear();
- }
-
- /**
- * Releases all previously allocated memory
- * and leaves the vector in a state equivalent
- * to the state after the default constructor
- * has been called.
- */
- void clear ()
- {
- if (_data != 0)
- {
- if (std_cxx1x::is_trivial<T>::value == false)
- while (_end_data != _data)
- (--_end_data)->~T();
-
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
- _mm_free(_data);
-#else
- free(_data);
-#endif
- }
- _data = 0;
- _end_data = 0;
- _end_allocated = 0;
- };
-
- /**
- * Inserts an element at the end of the
- * vector, increasing the vector size by
- * one. Note that the allocated size will
- * double whenever the previous space is not
- * enough to hold the new element.
- */
- void push_back (const T in_data)
- {
- Assert (_end_data <= _end_allocated, ExcInternalError());
- if (_end_data == _end_allocated)
- reserve (std::max(2*capacity(),static_cast<size_type>(16)));
- if (std_cxx1x::is_trivial<T>::value == false)
- new (_end_data) T;
- *_end_data++ = in_data;
- }
-
- /**
- * Returns the last element of the vector
- * (read and write access).
- */
- reference back ()
- {
- AssertIndexRange (0, size());
- T *field = _end_data - 1;
- return *field;
- }
-
- /**
- * Returns the last element of the vector
- * (read-only access).
- */
- const_reference back () const
- {
- AssertIndexRange (0, size());
- const T *field = _end_data - 1;
- return *field;
- }
-
- /**
- * Inserts several elements at the end of the
- * vector given by a range of elements.
- */
- template <typename ForwardIterator>
- void insert_back (ForwardIterator begin,
- ForwardIterator end)
- {
- const unsigned int old_size = size();
- reserve (old_size + (end-begin));
- for ( ; begin != end; ++begin, ++_end_data)
- {
- if (std_cxx1x::is_trivial<T>::value == false)
- new (_end_data) T;
- *_end_data = *begin;
- }
- }
-
- /**
- * Swaps the given vector with the calling
- * vector.
- */
- void swap (AlignedVector<T> &vec)
- {
- std::swap (_data, vec._data);
- std::swap (_end_data, vec._end_data);
- std::swap (_end_allocated, vec._end_allocated);
- }
-
- /**
- * Returns the size of the vector.
- */
- size_type size () const
- {
- return _end_data - _data;
- }
-
- /**
- * Returns the capacity of the vector, i.e.,
- * the size this vector can hold without
- * reallocation. Note that capacity() >=
- * size().
- */
- size_type capacity () const
- {
- return _end_allocated - _data;
- }
-
- /**
- * Read-write access to entry @p index in the
- * vector.
- */
- reference
- operator [] (const size_type index)
- {
- AssertIndexRange (index, size());
- return _data[index];
- };
-
- /**
- * Read-only access to entry @p index in the
- * vector.
- */
- const_reference operator [] (const size_type index) const
- {
- AssertIndexRange (index, size());
- return _data[index];
- };
-
- /**
- * Returns a read and write pointer to the
- * beginning of the data array.
- */
- iterator begin ()
- {
- return _data;
- }
-
- /**
- * Returns a read and write pointer to the
- * end of the data array.
- */
- iterator end ()
- {
- return _end_data;
- }
-
- /**
- * Returns a read-only pointer to the
- * beginning of the data array.
- */
- const_iterator begin () const
- {
- return _data;
- }
-
- /**
- * Returns a read-only pointer to the
- * end of the data array.
- */
- const_iterator end () const
- {
- return _end_data;
- }
-
- /**
- * Returns the memory consumption of the
- * allocated memory in this class. If the
- * underlying type @p T allocates memory by
- * itself, this memory is not counted.
- */
- size_type memory_consumption () const
- {
- size_type memory = sizeof(this);
- memory += sizeof(T) * capacity();
- return memory;
- }
-
-private:
-
- /**
- * Pointer to actual class data.
- */
- T *_data;
-
- /**
- * Pointer to the end of valid data fields.
- */
- T *_end_data;
-
- /**
- * Pointer to the end of the allocated memory.
- */
- T *_end_allocated;
-};
-
-
DEAL_II_NAMESPACE_CLOSE
/**
* Renumber the degrees of freedom according to the Cuthill-McKee method,
- * eventually using the reverse numbering scheme.
+ * possibly using the reverse numbering scheme.
*
* See the general documentation of this class for details on the different
* methods.
* As an example of the results of this algorithm, take a look at the
* comparison of various algorithms in the documentation of the
* DoFRenumbering namespace.
+ *
+ * If the given DoFHandler uses a distributed triangulation (i.e., if
+ * dof_handler.locally_owned() is not the complete index set), the
+ * renumbering is performed on each processor's degrees of freedom
+ * individually.
*/
template <class DH>
void
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* This function generates a matrix such that when a vector of data
* with as many elements as there are degrees of freedom of this
* component on the coarse grid is multiplied to this matrix, we
- * obtain a vector with as many elements are there are global
+ * obtain a vector with as many elements as there are global
* degrees of freedom on the fine grid. All the elements of the
* other components of the finite element fields on the fine grid
* are not touched.
/**
- * Declare a data type which denotes a mapping between a boundary indicator
- * and the function denoting the boundary values on this part of the
- * boundary. This type is required in many functions where depending on the
- * boundary indicator, different functions are used. An example is boundary
- * value interpolation.
+ * This class declares a local typedef that denotes a mapping between a boundary indicator
+ * (see @ref GlossBoundaryIndicator) that is used to describe what kind of boundary
+ * condition holds on a particular piece of the boundary,
+ * and the function describing the actual function that provides the boundary
+ * values on this part of the boundary. This type is required in many functions
+ * in the library where, for example, we need to know about the functions $h_i(\mathbf x)$
+ * used in boundary conditions
+ * @f{align*}
+ * \mathbf n \cdot \nabla u = h_i \qquad \qquad \text{on}\ \Gamma_i\subset\partial\Omega.
+ * @f}
+ * An example is the function KellyErrorEstimator::estimate() that allows us
+ * to provide a set of functions $h_i$ for all those boundary indicators $i$ for
+ * which the boundary condition is supposed to be of Neumann type. Of course,
+ * the same kind of principle can be applied to cases where we care about
+ * Dirichlet values, where one needs to provide a map from boundary indicator $i$
+ * to Dirichlet function $h_i$ if the boundary conditions are given as
+ * @f{align*}
+ * u = h_i \qquad \qquad \text{on}\ \Gamma_i\subset\partial\Omega.
+ * @f}
+ * This is, for example, the case for the VectorTools::interpolate() functions.
+ *
+ * Tutorial programs step-6, step-7 and step-8 show examples of how to use
+ * function arguments of this type in situations where we actually have an empty
+ * map (i.e., we want to describe that <i>no</i> part of the boundary is a
+ * Neumann boundary). step-16 actually uses it in a case where one of the
+ * parts of the boundary uses a boundary indicator for which we want to use
+ * a function object.
*
* It seems odd at first to declare this typedef inside a class, rather than
* declaring a typedef at global scope. The reason is that C++ does not allow
* to define templated typedefs, where here in fact we want a typdef that
- * depends on the space dimension.
+ * depends on the space dimension. (Defining templated typedefs is something that
+ * is possible starting with the C++11 standard, but that wasn't possible within
+ * the C++98 standard in place when this programming pattern was conceived.)
*
* @ingroup functions
* @author Wolfgang Bangerth, Ralf Hartmann, 2001
* requirement that they be one at a certain point and zero at all the
* points associated with the other shape functions.
*
- * In composed elements (i.e. for the FESystem class, the result will be
- * true if all all the base elements have defined support points.
+ * In composed elements (i.e. for the FESystem class), the result will be
+ * true if all all the base elements have defined support points. FE_Nothing
+ * is a special case in FESystems, because it has 0 support points and
+ * has_support_points() is false, but an FESystem containing an FE_Nothing
+ * among other elements will return true.
*/
bool has_support_points () const;
*
* @param dofs_per_object Number of dofs on geometrical objects for each
* dimension. In this vector, entry 0 refers to dofs on vertices, entry 1 on
- * lines and so on. Its length must be <i>dim+1</i>. @param n_components
- * Number of vector components of the element. @param degree Maximal
- * polynomial degree in a single direction. @param conformity The finite
- * element space has continuity of this Sobolev space. @param n_blocks
- * obsolete and ignored.
+ * lines and so on. Its length must be <i>dim+1</i>.
+ *
+ * @param n_components Number of vector components of the element.
+ *
+ * @param degree Maximal polynomial degree in a single direction.
+ *
+ * @param conformity The finite element space has continuity of this Sobolev
+ * space.
+ *
+ * @param n_blocks obsolete and ignored.
*/
FiniteElementData (const std::vector<unsigned int> &dofs_per_object,
const unsigned int n_components,
#include <deal.II/base/config.h>
#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/base/thread_management.h>
#include <deal.II/fe/fe_poly.h>
DEAL_II_NAMESPACE_OPEN
const unsigned int subface,
FullMatrix<double> &matrix) const;
+ /**
+ * Projection from a fine grid space onto a coarse grid space. Overrides the
+ * respective method in FiniteElement, implementing lazy evaluation
+ * (initialize when requested).
+ *
+ * If this projection operator is associated with a matrix @p P, then the
+ * restriction of this matrix @p P_i to a single child cell is returned
+ * here.
+ *
+ * The matrix @p P is the concatenation or the sum of the cell matrices @p
+ * P_i, depending on the #restriction_is_additive_flags. This distinguishes
+ * interpolation (concatenation) and projection with respect to scalar
+ * products (summation).
+ *
+ * Row and column indices are related to coarse grid and fine grid spaces,
+ * respectively, consistent with the definition of the associated operator.
+ */
+ virtual const FullMatrix<double> &
+ get_restriction_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case=RefinementCase<dim>::isotropic_refinement) const;
+
+ /**
+ * Embedding matrix between grids. Overrides the respective method in
+ * FiniteElement, implementing lazy evaluation (initialize when queried).
+ *
+ * The identity operator from a coarse grid space into a fine grid space is
+ * associated with a matrix @p P. The restriction of this matrix @p P_i to a
+ * single child cell is returned here.
+ *
+ * The matrix @p P is the concatenation, not the sum of the cell matrices @p
+ * P_i. That is, if the same non-zero entry <tt>j,k</tt> exists in in two
+ * different child matrices @p P_i, the value should be the same in both
+ * matrices and it is copied into the matrix @p P only once.
+ *
+ * Row and column indices are related to fine grid and coarse grid spaces,
+ * respectively, consistent with the definition of the associated operator.
+ *
+ * These matrices are used by routines assembling the prolongation matrix
+ * for multi-level methods. Upon assembling the transfer matrix between
+ * cells using this matrix array, zero elements in the prolongation matrix
+ * are discarded and will not fill up the transfer matrix.
+ */
+ virtual const FullMatrix<double> &
+ get_prolongation_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case=RefinementCase<dim>::isotropic_refinement) const;
+
/**
* @name Functions to support hp
* @{
void rotate_indices (std::vector<unsigned int> &indices,
const char direction) const;
+ /*
+ * Mutex for protecting initialization of restriction and embedding matrix.
+ */
+ mutable Threads::Mutex mutex;
+
/**
* Allow access from other dimensions.
*/
FiniteElementDomination::Domination
compare_for_face_domination (const FiniteElement<dim,spacedim> &fe_other) const;
-
/**
* Returns a list of constant modes of the element. For this element, it
* simply returns one row with all entries set to true.
+/**
+ * Specialization of FE_FaceQ for 1D. In that case, the finite element only
+ * consists of one degree of freedom in each of the two faces (= vertices) of
+ * a cell, irrespective of the degree. However, this element still accepts a
+ * degree in its constructor and also returns that degree. This way,
+ * dimension-independent programming with trace elements is also possible in
+ * 1D (even though there is no computational benefit at all from it in 1D).
+ *
+ * @ingroup fe
+ * @author Guido Kanschat, Martin Kronbichler
+ * @date 2014
+ */
+template <int spacedim>
+class FE_FaceQ<1,spacedim> : public FiniteElement<1,spacedim>
+{
+public:
+ /**
+ * Constructor.
+ */
+ FE_FaceQ (const unsigned int p);
+
+ /**
+ * Clone method.
+ */
+ virtual FiniteElement<1,spacedim> *clone() const;
+
+ /**
+ * Return a string that uniquely identifies a finite element. This class
+ * returns <tt>FE_FaceQ<dim>(degree)</tt>, with <tt>dim</tt> and
+ * <tt>degree</tt> replaced by appropriate values.
+ */
+ virtual std::string get_name () const;
+
+ /**
+ * Return the matrix interpolating from a face of of one element to the face
+ * of the neighboring element. The size of the matrix is then
+ * <tt>source.dofs_per_face</tt> times <tt>this->dofs_per_face</tt>. This
+ * element only provides interpolation matrices for elements of the same
+ * type and FE_Nothing. For all other elements, an exception of type
+ * FiniteElement<dim,spacedim>::ExcInterpolationNotImplemented is thrown.
+ */
+ virtual void
+ get_face_interpolation_matrix (const FiniteElement<1,spacedim> &source,
+ FullMatrix<double> &matrix) const;
+
+ /**
+ * Return the matrix interpolating from a face of of one element to the face
+ * of the neighboring element. The size of the matrix is then
+ * <tt>source.dofs_per_face</tt> times <tt>this->dofs_per_face</tt>. This
+ * element only provides interpolation matrices for elements of the same
+ * type and FE_Nothing. For all other elements, an exception of type
+ * FiniteElement<dim,spacedim>::ExcInterpolationNotImplemented is thrown.
+ */
+ virtual void
+ get_subface_interpolation_matrix (const FiniteElement<1,spacedim> &source,
+ const unsigned int subface,
+ FullMatrix<double> &matrix) const;
+
+ /**
+ * Check for non-zero values on a face.
+ *
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero values on the face @p face_index.
+ *
+ * Implementation of the interface in FiniteElement
+ */
+ virtual bool has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const;
+
+ /**
+ * Return whether this element implements its hanging node constraints in
+ * the new way, which has to be used to make elements "hp compatible".
+ */
+ virtual bool hp_constraints_are_implemented () const;
+
+ /**
+ * Return whether this element dominates the one given as argument when they
+ * meet at a common face, whether it is the other way around, whether
+ * neither dominates, or if either could dominate.
+ *
+ * For a definition of domination, see FiniteElementBase::Domination and in
+ * particular the @ref hp_paper "hp paper".
+ */
+ virtual
+ FiniteElementDomination::Domination
+ compare_for_face_domination (const FiniteElement<1,spacedim> &fe_other) const;
+
+ /**
+ * Returns a list of constant modes of the element. For this element, it
+ * simply returns one row with all entries set to true.
+ */
+ virtual Table<2,bool> get_constant_modes () const;
+
+protected:
+ virtual
+ typename Mapping<1,spacedim>::InternalDataBase *
+ get_data (const UpdateFlags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<1> &quadrature) const ;
+
+ typename Mapping<1,spacedim>::InternalDataBase *
+ get_face_data (const UpdateFlags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<0>& quadrature) const ;
+
+ typename Mapping<1,spacedim>::InternalDataBase *
+ get_subface_data (const UpdateFlags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<0>& quadrature) const ;
+
+ virtual void
+ fill_fe_values (const Mapping<1,spacedim> &mapping,
+ const typename Triangulation<1,spacedim>::cell_iterator &cell,
+ const Quadrature<1> &quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &mapping_internal,
+ typename Mapping<1,spacedim>::InternalDataBase &fe_internal,
+ FEValuesData<1,spacedim> &data,
+ CellSimilarity::Similarity &cell_similarity) const;
+
+ virtual void
+ fill_fe_face_values (const Mapping<1,spacedim> &mapping,
+ const typename Triangulation<1,spacedim>::cell_iterator &cell,
+ const unsigned int face_no,
+ const Quadrature<0> &quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &mapping_internal,
+ typename Mapping<1,spacedim>::InternalDataBase &fe_internal,
+ FEValuesData<1,spacedim> &data) const ;
+
+ virtual void
+ fill_fe_subface_values (const Mapping<1,spacedim> &mapping,
+ const typename Triangulation<1,spacedim>::cell_iterator &cell,
+ const unsigned int face_no,
+ const unsigned int sub_no,
+ const Quadrature<0> &quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &mapping_internal,
+ typename Mapping<1,spacedim>::InternalDataBase &fe_internal,
+ FEValuesData<1,spacedim> &data) const ;
+
+
+ /**
+ * Determine the values that need to be computed on the unit cell to be able
+ * to compute all values required by <tt>flags</tt>.
+ *
+ * For the purpuse of this function, refer to the documentation in
+ * FiniteElement.
+ *
+ * This class assumes that shape functions of this FiniteElement do
+ * <em>not</em> depend on the actual shape of the cells in real
+ * space. Therefore, the effect in this element is as follows: if
+ * <tt>update_values</tt> is set in <tt>flags</tt>, copy it to the
+ * result. All other flags of the result are cleared, since everything else
+ * must be computed for each cell.
+ */
+ virtual UpdateFlags update_once (const UpdateFlags flags) const;
+
+ /**
+ * Determine the values that need to be computed on every cell to be able to
+ * compute all values required by <tt>flags</tt>.
+ *
+ * For the purpuse of this function, refer to the documentation in
+ * FiniteElement.
+ *
+ * This class assumes that shape functions of this FiniteElement do
+ * <em>not</em> depend on the actual shape of the cells in real space.
+ *
+ * The effect in this element is as follows:
+ * <ul>
+ *
+ * <li> if <tt>update_gradients</tt> is set, the result will contain
+ * <tt>update_gradients</tt> and <tt>update_covariant_transformation</tt>.
+ * The latter is required to transform the gradient on the unit cell to the
+ * real cell. Remark, that the action required by
+ * <tt>update_covariant_transformation</tt> is actually performed by the
+ * Mapping object used in conjunction with this finite element.
+ *
+ * <li> if <tt>update_hessians</tt> is set, the result will contain
+ * <tt>update_hessians</tt> and <tt>update_covariant_transformation</tt>.
+ * The rationale is the same as above and no higher derivatives of the
+ * transformation are required, since we use difference quotients for the
+ * actual computation.
+ *
+ * </ul>
+ */
+ virtual UpdateFlags update_each (const UpdateFlags flags) const;
+
+private:
+ /**
+ * Return vector with dofs per vertex, line, quad, hex.
+ */
+ static std::vector<unsigned int> get_dpo_vector (const unsigned int deg);
+};
+
+
/**
* A finite element, which is a Legendre element of complete polynomials on
};
+
+/**
+ * FE_FaceP in 1D, i.e., with degrees of freedom on the element vertices.
+ */
+template <int spacedim>
+class FE_FaceP<1,spacedim> : public FE_FaceQ<1,spacedim>
+{
+public:
+ /**
+ * Constructor.
+ */
+ FE_FaceP (const unsigned int p);
+
+ /**
+ * Returns the name of the element
+ */
+ std::string get_name() const;
+};
+
+
DEAL_II_NAMESPACE_CLOSE
#endif
* The effect in this element is
* as follows:
* <ul>
-
- * <li> if
- * <tt>update_gradients</tt> is
- * set, the result will contain
- * <tt>update_gradients</tt> and
- * <tt>update_covariant_transformation</tt>.
- * The latter is required to
- * transform the gradient on the
- * unit cell to the real
- * cell. Remark, that the action
- * required by
- * <tt>update_covariant_transformation</tt>
- * is actually performed by the
- * Mapping object used in
- * conjunction with this finite
- * element. <li> if
- * <tt>update_hessians</tt>
- * is set, the result will
- * contain
- * <tt>update_hessians</tt>
- * and
- * <tt>update_covariant_transformation</tt>.
- * The rationale is the same as
- * above and no higher
- * derivatives of the
- * transformation are required,
- * since we use difference
- * quotients for the actual
- * computation.
+ *
+ * <li> if <tt>update_gradients</tt> is set, the result will contain
+ * <tt>update_gradients</tt> and <tt>update_covariant_transformation</tt>.
+ * The latter is required to transform the gradient on the unit cell to the
+ * real cell. Remark, that the action required by
+ * <tt>update_covariant_transformation</tt> is actually performed by the
+ * Mapping object used in conjunction with this finite element.
+ *
+ * <li> if <tt>update_hessians</tt> is set, the result will contain
+ * <tt>update_hessians</tt> and <tt>update_covariant_transformation</tt>.
+ * The rationale is the same as above and no higher derivatives of the
+ * transformation are required, since we use difference quotients for the
+ * actual computation.
*
* </ul>
*/
UpdateFlags
FE_PolyFace<POLY,dim,spacedim>::update_once (const UpdateFlags) const
{
- // for this kind of elements, only
- // the values can be precomputed
- // once and for all. set this flag
- // if the values are requested at
- // all
+ // for this kind of elements, only the values can be precomputed once and
+ // for all. set this flag if the values are requested at all
return update_default;
}
const UpdateFlags flags(fe_data.update_once | fe_data.update_each);
- const unsigned int foffset = fe_data.shape_values.size() * face;
if (flags & update_values)
for (unsigned int i=0; i<quadrature.size(); ++i)
{
- for (unsigned int k=0; k<this->dofs_per_cell; ++k)
+ for (unsigned int k=0; k<this->dofs_per_cell; ++k)
data.shape_values(k,i) = 0.;
- for (unsigned int k=0; k<fe_data.shape_values.size(); ++k)
- data.shape_values(foffset+k,i) = fe_data.shape_values[k][i];
+ switch (dim)
+ {
+ case 3:
+ {
+ // Fill data for quad shape functions
+ if (this->dofs_per_quad !=0)
+ {
+ const unsigned int foffset = this->first_quad_index + this->dofs_per_quad * face;
+ for (unsigned int k=0; k<this->dofs_per_quad; ++k)
+ data.shape_values(foffset+k,i) = fe_data.shape_values[k+this->first_face_quad_index][i];
+ }
+ }
+ case 2:
+ {
+ // Fill data for line shape functions
+ if (this->dofs_per_line != 0)
+ {
+ const unsigned int foffset = this->first_line_index;
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_face; ++line)
+ {
+ for (unsigned int k=0; k<this->dofs_per_line; ++k)
+ data.shape_values(foffset+GeometryInfo<dim>::face_to_cell_lines(face, line)*this->dofs_per_line+k,i) = fe_data.shape_values[k+(line*this->dofs_per_line)+this->first_face_line_index][i];
+ }
+ }
+ }
+ case 1:
+ {
+ // Fill data for vertex shape functions
+ if (this->dofs_per_vertex != 0)
+ for (unsigned int lvertex=0; lvertex<GeometryInfo<dim>::vertices_per_face; ++lvertex)
+ data.shape_values(GeometryInfo<dim>::face_to_cell_vertices(face, lvertex),i) = fe_data.shape_values[lvertex][i];
+ break;
+ }
+ }
}
}
/**
* Compute the embedding matrices on faces needed for constraint matrices.
*
- * @param fe The finite element for which to compute these matrices. @param
- * matrices An array of <i>GeometryInfo<dim>::subfaces_per_face =
+ * @param fe The finite element for which to compute these matrices.
+ *
+ * @param matrices An array of <i>GeometryInfo<dim>::subfaces_per_face =
* 2<sup>dim-1</sup></i> FullMatrix objects,holding the embedding matrix for
- * each subface. @param face_coarse The number of the face on the coarse
- * side of the face for which this is computed. @param face_fine The number
- * of the face on the refined side of the face for which this is computed.
+ * each subface.
+ *
+ * @param face_coarse The number of the face on the coarse side of the face
+ * for which this is computed.
+ *
+ * @param face_fine The number of the face on the refined side of the face
+ * for which this is computed.
*
* @warning This function will be used in computing constraint matrices. It
* is not sufficiently tested yet.
* correct size, which is equal to the number of degrees of freedom in the
* finite element.
*/
+
+ template <int dim>
+ void
+ hierarchic_to_lexicographic_numbering (unsigned int degree,
+ std::vector<unsigned int> &h2l);
+
template <int dim>
void
hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe_data,
* The name must be in the form which is returned by the
* FiniteElement::get_name function, where a few modifications are allowed:
*
- * <ul><li> Dimension template parameters <2> etc. can be
+ * <ul>
+ * <li> Dimension template parameters <2> etc. can be
* omitted. Alternatively, the explicit number can be replaced by
* <tt>dim</tt> or <tt>d</tt>. If a number is given, it <b>must</b> match
* the template parameter of this function.
*
* <li> The powers used for FESystem may either be numbers or can be
- * replaced by <tt>dim</tt> or <tt>d</tt>. </ul>
+ * replaced by <tt>dim</tt> or <tt>d</tt>.
+ * </ul>
*
* If no finite element can be reconstructed from this string, an exception
* of type @p FETools::ExcInvalidFEName is thrown.
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2000 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__fe_trace_h
+#define __deal2__fe_trace_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/fe/fe_poly_face.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * A finite element, which is the trace of Fe_Q elements, that is
+ * a tensor product of polynomials on the faces,
+ * undefined in the interior of the cells and continuous. The basis functions on
+ * the faces are from Polynomials::LagrangeEquidistant
+ *
+ * This finite element is the trace space of FE_Q on the
+ * faces.
+ *
+ * @note Since these are only finite elements on faces, only
+ * FEFaceValues and FESubfaceValues will be able to extract reasonable
+ * values from any face polynomial. In order to make the use of
+ * FESystem simpler, FEValues objects will not fail using this finite
+ * element space, but all shape function values extracted will equal
+ * to zero.
+ *
+ * @todo Polynomials::LagrangeEquidistant should be and will be
+ * replaced by Polynomials::LagrangeGaussLobatto as soon as such a
+ * polynomial set exists.
+ * @todo so far, hanging nodes are not implemented
+ *
+ */
+
+template <int dim, int spacedim=dim>
+class FE_TraceQ : public FE_PolyFace<TensorProductPolynomials<dim-1>, dim, spacedim>
+{
+public:
+ /**
+ * Constructor for tensor product
+ * polynomials of degree
+ * <tt>p</tt>. The shape
+ * functions created using this
+ * constructor correspond to
+ * Legendre polynomials in each
+ * coordinate direction.
+ */
+ FE_TraceQ(unsigned int p);
+
+ virtual FiniteElement<dim,spacedim> *clone() const;
+
+ /**
+ * Return a string that uniquely
+ * identifies a finite
+ * element. This class returns
+ * <tt>FE_DGQ<dim>(degree)</tt>, with
+ * <tt>dim</tt> and <tt>degree</tt>
+ * replaced by appropriate
+ * values.
+ */
+ virtual std::string get_name () const;
+
+ /**
+ * Check for non-zero values on a face.
+ *
+ * This function returns
+ * @p true, if the shape
+ * function @p shape_index has
+ * non-zero values on the face
+ * @p face_index.
+ *
+ * Implementation of the
+ * interface in
+ * FiniteElement
+ */
+ virtual bool has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const;
+
+private:
+ /**
+ * Return vector with dofs per
+ * vertex, line, quad, hex.
+ */
+ static std::vector<unsigned int> get_dpo_vector (const unsigned int deg);
+};
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
* <h3>References</h3>
*
* A general publication on differential geometry and finite elements
- * is the survey <ul><li>Douglas N. Arnold, Richard S. Falk, and
+ * is the survey
+ * <ul>
+ * <li>Douglas N. Arnold, Richard S. Falk, and
* Ragnar Winther. <i>Finite element exterior calculus: from
* Hodge theory to numerical stability.</i>
* Bull. Amer. Math. Soc. (N.S.), 47:281-354, 2010. <a
* href="http://dx.doi.org/10.1090/S0273-0979-10-01278-4">DOI:
- * 10.1090/S0273-0979-10-01278-4</a>.</ul>
+ * 10.1090/S0273-0979-10-01278-4</a>.
+ * </ul>
*
* The description of the Piola transform has been taken from the <a
* href="http://www.math.uh.edu/~rohop/spring_05/downloads/">lecture
*/
struct Svg
{
+ /// Height of the plot in SVG units, computed from width if zero. Defaults to 1000
+ unsigned int height;
+ /// The width of the plot. Computed automatically from height if zero (default)
+ unsigned int width;
/// Thickness of the lines between cells
unsigned int line_thickness;
/// Thickness of lines at the boundary
/// Interpret the level number of the cells as altitude over the x-y-plane (useful in the perpspective view).
bool convert_level_number_to_height;
+ /// The factor determining the vertical distance between levels (default = 0.3)
+ float level_height_factor;
+
/**
* Cell labeling (fixed order).
*
*/
/**
- * Return the @p
- * RefinementCase<dim> this cell
- * was flagged to be refined
- * with.
+ * Return the @p RefinementCase<dim> this cell was flagged to be refined
+ * with. The return value of this function can be compared to a bool to
+ * check if this cell is flagged for any kind of refinement. For example, if
+ * you have previously called cell->set_refine_flag() for a cell, then you
+ * will enter the 'if' block in the following snippet:
+ *
+ * @code
+ * if (cell->refine_flag_set())
+ * {
+ * // yes, this cell is marked for refinement.
+ * }
+ * @endcode
*/
RefinementCase<dim> refine_flag_set () const;
* Flag the cell pointed to for
* refinement. This function is
* only allowed for active
- * cells.
+ * cells. Keeping the default value for @p ref_case will mark this cell for
+ * isotropic refinement.
*/
void set_refine_flag (const RefinementCase<dim> ref_case = RefinementCase<dim>::isotropic_refinement) const;
* but rather one of the derived classes TriaIterator or
* TriaActiveIterator.
*
- * <ul> <li> TriaRawIterator objects point to lines, cells, etc in the
+ * <ul>
+ * <li> TriaRawIterator objects point to lines, cells, etc in the
* lists whether they are used or not (in the vectors, also
* <i>dead</i> objects are stored, since deletion in vectors is
* expensive and we also do not want to destroy the ordering induced
* parameter), which really does the access to data. An Accessor
* has to fulfil some requirements:
*
- * <ul> <li> It must have two members named <tt>present_level</tt> and
+ * <ul>
+ * <li> It must have two members named <tt>present_level</tt> and
* <tt>present_index</tt> storing the address of the element in the
* triangulation presently pointed to. These data have to be
* accessible by all triangulation iterators listed above.
* Print the block structure as a
* LaTeX-array. This output will
* not be very intuitive, since
- * the matrix object lacks
- * important information. What
- * you see is an entry for each
+ * the current object lacks
+ * knowledge about what the individual blocks represent or
+ * how they should be named. Instead, what
+ * you will see is an entry for each
* block showing all the matrices
- * with their multiplicaton
+ * with their multiplication
* factors and possibly transpose
- * mark. The matrices itself are
- * numbered successively upon
- * being entred. If the same
+ * marks. The matrices itself are
+ * named successively as they are encountered. If the same
* matrix is entered several
* times, it will be listed with
- * the same number everytime.
+ * different names.
+ *
+ * As an example, consider the following code:
+ * @code
+ * FullMatrix<double> A1(4,4);
+ * FullMatrix<double> A2(4,4);
+ * FullMatrix<double> B(4,3);
+ * FullMatrix<double> C(3,3);
+ *
+ * BlockMatrixArray<double> block(2,2);
+ *
+ * block.enter(A1,0,0);
+ * block.enter(A2,0,0,2,true);
+ * block.enter(B,0,1,-3.);
+ * block.enter(B,0,1,-3.,true);
+ * block.enter(C,1,1,1.,true);
+ *
+ * block.print_latex(std::cout);
+ * @endcode
+ * The current function will then produce output of the following
+ * kind:
+ * @code
+ * \begin{array}{cc}
+ * M0+2xM1^T & -3xM2-3xM3^T\\
+ * & M4^T
+ * \end{array}
+ * @endcode
+ * Note how the individual blocks here are just numbered successively
+ * as <code>M0</code> to <code>M4</code> and that the output misses
+ * the fact that <code>M2</code> and <code>M3</code> are, in fact,
+ * the same matrix. Nevertheless, the output at least gives some
+ * kind of idea of the block structure of this matrix.
*/
template <class STREAM>
void print_latex (STREAM &out) const;
}
-template<typename number>
-struct BlockMatrixArrayPointerMatrixLess
-{
- bool operator () (const PointerMatrixBase<Vector<number> > *a,
- const PointerMatrixBase<Vector<number> > *b) const
- {
- return *a < *b;
- }
-};
-
-
template <typename number>
template <class STREAM>
inline
Table<2,std::string> array(n_block_rows(), n_block_cols());
- typedef std::map<const PointerMatrixBase<Vector<number> > *,
- std::string, BlockMatrixArrayPointerMatrixLess<number> > NameMap;
+ typedef std::map<const PointerMatrixBase<Vector<number> > *, std::string> NameMap;
NameMap matrix_names;
typename std::vector<Entry>::const_iterator m = entries.begin();
{
out << '\t' << array(i,j);
if (j==n_block_cols()-1)
- out << "\\\\" << std::endl;
+ {
+ if (i != n_block_rows() - 1)
+ out << "\\\\" << std::endl;
+ else
+ out << std::endl;
+ }
else
out << " &";
}
(void)d; // removes -Wunused-parameter warning in optimized mode
if (this->n_elements() != 0)
- std::memset (&this->values[0], 0, this->n_elements()*sizeof(number));
+ this->reset_values();
return *this;
}
* it is fast.
*
* @code
- * // Declare related objects
- *
+ * // Declare related objects
* SparseMatrix<double> A;
* Vector<double> x;
* Vector<double> b;
* GrowingVectorMemory<Vector<double> > mem;
-
+ *
* ReductionControl inner_control (10, 1.e-30, 1.e-2);
* PreconditionSSOR <SparseMatrix<double> > inner_precondition;
* inner_precondition.initialize (A, 1.2);
* quadratic matrices #m1 and #m2 of arbitrary types and implements
* matrix-vector multiplications for the product
* <i>M<sub>1</sub>M<sub>2</sub></i> by performing multiplication with
- * both factors consecutively.
+ * both factors consecutively. Because the types of the matrices are
+ * opaque (i.e., they can be arbitrary), you can stack products of three
+ * or more matrices by making one of the two matrices an object of the
+ * current type handles be a ProductMatrix itself.
*
- * Here an example multiplying two different FullMatrix objects:
+ * Here is an example multiplying two different FullMatrix objects:
* @include product_matrix.cc
*
* @author Guido Kanschat, 2000, 2001, 2002, 2005
const MATRIX2 &m2,
VectorMemory<VECTOR> &mem);
+ /**
+ * Destructor.
+ */
+ ~ProductMatrix();
+
/**
* Change the matrices.
*/
void initialize(const MATRIX1 &m1, const MATRIX2 &m2,
VectorMemory<VECTOR> &mem);
- /**
- * Destructor.
- */
- ~ProductMatrix();
-
// Doc in PointerMatrixBase
void clear();
const VECTOR &v) const;
/**
- * Tranposed matrix-vector
+ * Transposed matrix-vector
* product <i>w = m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
*/
const VECTOR &v) const;
/**
- * Adding, tranposed
+ * Adding, transposed
* matrix-vector product <i>w +=
* m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
* Memory for auxiliary vector.
*/
SmartPointer<VectorMemory<VECTOR>,ProductMatrix<VECTOR> > mem;
- /**
- * Return some kind of
- * identifier.
- */
- virtual const void *get() const;
};
/**
- * A matrix that is the scaled version of another matrix.
+ * A matrix that is the multiple of another matrix.
*
* Matrix-vector products of this matrix are composed of those of the
- * original matrix and scaling by a constant factor.
+ * original matrix with the vector and then scaling of the result by
+ * a constant factor.
*
* @author Guido Kanschat, 2007
*/
void initialize (const MATRIX &M, const double factor);
/**
- * Delete internal matrix pointer.
+ * Reset the object to its original state.
*/
void clear ();
/**
* Constructor leaving an
- * unitialized
+ * uninitialized
* matrix. initialize() must be
* called, before the matrix can
* be used.
const VectorType &v) const;
/**
- * Tranposed matrix-vector
+ * Transposed matrix-vector
* product <i>w = m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
*/
const VectorType &v) const;
/**
- * Adding, tranposed
+ * Adding, transposed
* matrix-vector product <i>w +=
* m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
* Memory for auxiliary vector.
*/
SmartPointer<VectorMemory<VectorType>,ProductSparseMatrix<number,vector_number> > mem;
- /**
- * Return some kind of
- * identifier.
- */
- virtual const void *get() const;
};
* BlockVector, then an additional parameter selects a single
* component for this operation.
*
+ * In mathematical terms, this class acts as if it was the matrix
+ * $I-\frac 1n{\mathbf 1}_n{\mathbf 1}_n^T$ where ${\mathbf 1}_n$ is
+ * a vector of size $n$ that has only ones as its entries. Thus,
+ * taking the dot product between a vector $\mathbf v$ and
+ * $\frac 1n {\mathbf 1}_n$ yields the <i>mean value</i> of the entries
+ * of ${\mathbf v}$. Consequently,
+ * $ \left[I-\frac 1n{\mathbf 1}_n{\mathbf 1}_n^T\right] \mathbf v
+ * = \mathbf v - \left[\frac 1n \mathbf v} \cdot {\mathbf 1}_n\right]{\mathbf 1}_n$
+ * subtracts from every vector element the mean value of all elements.
+ *
* @author Guido Kanschat, 2002, 2003
*/
class MeanValueFilter : public Subscriptor
* Constructor, optionally
* selecting a component.
*/
- MeanValueFilter(size_type component = numbers::invalid_size_type);
+ MeanValueFilter(const size_type component = numbers::invalid_size_type);
/**
* Subtract mean value from @p v.
/**
* Component for filtering block vectors.
*/
- size_type component;
+ const size_type component;
};
/**
- * Inverse matrix computed approximately by using the SolverRichardson
- * iterative solver. In particular, the function
- * SolverRichardson::Tsolve() allows for the implementation of
- * transpose matrix vector products.
+ * Objects of this type represent the inverse of a matrix as
+ * computed approximately by using the SolverRichardson
+ * iterative solver. In other words, if you set up an object
+ * of the current type for a matrix $A$, then calling the
+ * vmult() function with arguments $v,w$ amounts to setting
+ * $w=A^{-1}v$ by solving the linear system $Aw=v$ using the
+ * Richardson solver with a preconditioner that can be chosen. Similarly,
+ * this class allows to also multiple with the transpose of the
+ * inverse (i.e., the inverse of the transpose) using the function
+ * SolverRichardson::Tsolve().
*
- * The functions vmult() and Tvmult() appoximate the inverse
+ * The functions vmult() and Tvmult() approximate the inverse
* iteratively starting with the vector <tt>dst</tt>. Functions
* vmult_add() and Tvmult_add() start the iteration with a zero
- * vector.
+ * vector. All of the matrix-vector multiplication functions
+ * expect that the Richardson solver with the given preconditioner
+ * actually converge. If the Richardson solver does not converge
+ * within the specified number of iterations, the exception that will
+ * result in the solver will simply be propagated to the caller of
+ * the member function of the current class.
+ *
+ * @note A more powerful version of this class is provided by the
+ * IterativeInverse class.
*
* @note Instantiations for this template are provided for <tt>@<float@> and
* @<double@></tt>; others can be generated in application programs (see the
}
-template<class VECTOR>
-const void *
-ProductMatrix<VECTOR>::get () const
-{
- return (void *) m1;
-}
-
//---------------------------------------------------------------------------
Assert (matrix != 0, ExcNotInitialized());
Assert (precondition != 0, ExcNotInitialized());
dst = 0.;
- try
- {
- solver.solve(*matrix, dst, src, *precondition);
- }
- catch (...)
- {}
+ solver.solve(*matrix, dst, src, *precondition);
}
Assert (precondition != 0, ExcNotInitialized());
VECTOR *aux = mem.alloc();
aux->reinit(dst);
- try
- {
- solver.solve(*matrix, *aux, src, *precondition);
- }
- catch (...)
- {}
+
+ solver.solve(*matrix, *aux, src, *precondition);
+
dst += *aux;
mem.free(aux);
}
Assert (matrix != 0, ExcNotInitialized());
Assert (precondition != 0, ExcNotInitialized());
dst = 0.;
- try
- {
- solver.Tsolve(*matrix, dst, src, *precondition);
- }
- catch (...)
- {}
+ solver.Tsolve(*matrix, dst, src, *precondition);
}
Assert (precondition != 0, ExcNotInitialized());
VECTOR *aux = mem.alloc();
aux->reinit(dst);
- try
- {
- solver.Tsolve(*matrix, *aux, src, *precondition);
- }
- catch (...)
- {}
+
+ solver.Tsolve(*matrix, *aux, src, *precondition);
+
dst += *aux;
mem.free(aux);
}
#include <deal.II/lac/vector_view.h>
#include <cstring>
+#include <iomanip>
DEAL_II_NAMESPACE_OPEN
std::size_t memory_consumption () const;
//@}
+ /**
+ * Exception
+ */
+ DeclException3 (ExcNonMatchingElements,
+ double, double, unsigned int,
+ << "Called compress(VectorOperation::insert), but"
+ << " the element received from a remote processor, value "
+ << std::setprecision(16) << arg1
+ << ", does not match with the value "
+ << std::setprecision(16) << arg2
+ << " on the owner processor " << arg3);
+
private:
/**
* Local part of all_zero().
std::abs(local_element(j) - *read_position) <
std::abs(local_element(j)) * 1000. *
std::numeric_limits<Number>::epsilon(),
- ExcMessage("Inserted elements do not match."));
+ ExcNonMatchingElements(*read_position, local_element(j),
+ part.this_mpi_process()));
AssertDimension(read_position-import_data,part.n_import_indices());
}
Vector &
Vector::operator = (const Vector &v)
{
+ // make sure left- and right-hand side of the assignment are compress()'ed:
+ Assert(v.last_action == VectorOperation::unknown,
+ internal::VectorReference::ExcWrongMode (VectorOperation::unknown,
+ v.last_action));
+ Assert(last_action == VectorOperation::unknown,
+ internal::VectorReference::ExcWrongMode (VectorOperation::unknown,
+ last_action));
+
+
if (v.size()==0)
{
// this happens if v has not been initialized to something useful:
virtual ~PointerMatrixBase ();
/**
- * Reset pointer and release the
- * matrix pointed to.
+ * Reset the object to its original state.
*/
virtual void clear () = 0;
- /**
- * Find out if two matrices point
- * to the same object.
- */
- bool operator == (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if two matrices do
- * not point to the same object.
- */
- bool operator != (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * less.
- */
- bool operator < (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * less or equal.
- */
- bool operator <= (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * greater.
- */
- bool operator > (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * greater or equal.
- */
- bool operator >= (const PointerMatrixBase<VECTOR> &) const;
-
-
/**
* Matrix-vector product.
*/
const VECTOR &src) const = 0;
/**
- * Tranposed matrix-vector product.
+ * Transposed matrix-vector product.
*/
virtual void Tvmult (VECTOR &dst,
const VECTOR &src) const = 0;
const VECTOR &src) const = 0;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*/
virtual void Tvmult_add (VECTOR &dst,
const VECTOR &src) const = 0;
-
-private:
- /**
- * Get the pointer for comparison.
- */
- virtual const void *get() const = 0;
};
/**
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product.
+ * Transposed matrix-vector product.
*/
virtual void Tvmult (VECTOR &dst,
const VECTOR &src) const;
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*/
virtual void Tvmult_add (VECTOR &dst,
const VECTOR &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The pointer to the actual matrix.
*/
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product.
+ * Transposed matrix-vector product.
*/
virtual void Tvmult (VECTOR &dst,
const VECTOR &src) const;
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*/
virtual void Tvmult_add (VECTOR &dst,
const VECTOR &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The backup memory if none was provided.
*/
const Vector<number> &src) const;
/**
- * Tranposed matrix-vector
+ * Transposed matrix-vector
* product, actually the
* multiplication of the vector
* representing this matrix with
const Vector<number> &src) const;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*
* The dimension of <tt>src</tt>
const Vector<number> &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The pointer to the actual matrix.
*/
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator == (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() == other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator != (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() != other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator < (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() < other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator <= (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() <= other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator > (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() > other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator >= (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() >= other.get());
-}
-
-
//----------------------------------------------------------------------//
}
-template<class MATRIX, class VECTOR>
-inline const void *
-PointerMatrix<MATRIX, VECTOR>::get () const
-{
- return m;
-}
-
//----------------------------------------------------------------------//
}
-template<class MATRIX, class VECTOR>
-inline const void *
-PointerMatrixAux<MATRIX, VECTOR>::get () const
-{
- return m;
-}
-
-
//----------------------------------------------------------------------//
}
-template<typename number>
-inline const void *
-PointerMatrixVector<number>::get () const
-{
- return m;
-}
-
-
-
DEAL_II_NAMESPACE_CLOSE
#endif
* yourself, you should also rename this function to avoid programs relying
* on outdated information!
*
- * @internal @deprecated Use iterator or const_iterator instead!
+ * @deprecated Use iterator or const_iterator instead!
*/
number global_entry (const size_type i) const DEAL_II_DEPRECATED;
/**
* Same as above, but with write access. You certainly know what you do?
*
- * @internal @deprecated Use iterator or const_iterator instead!
+ * @deprecated Use iterator or const_iterator instead!
*/
number &global_entry (const size_type i) DEAL_II_DEPRECATED;
const VECTOR &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The pointer to the actual matrix.
*/
}
-template<class MATRIX, class VECTOR>
-inline const void *
-TransposeMatrix<MATRIX, VECTOR>::get () const
-{
- return m;
-}
-
-
-
DEAL_II_NAMESPACE_CLOSE
#endif
DeclException3 (ExcAccessToNonLocalElement,
size_type, size_type, size_type,
<< "You tried to access element " << arg1
- << " of a distributed vector, but it is not stored on "
- << "the current processor. Note: the elements stored "
+ << " of a distributed vector, but this element is not stored "
+ << "on the current processor. Note: The elements stored "
<< "on the current processor are within the range "
<< arg2 << " through " << arg3
<< " but Trilinos vectors need not store contiguous "
*/
const_iterator end () const;
+ //@}
+
+
+ /**
+ * @name 3: Modification of vectors
+ */
+ //@{
+
/**
* A collective set operation: instead of setting individual elements of a
* vector, this function allows to set a whole set of elements at
*/
void set (const std::vector<size_type> &indices,
const ::dealii::Vector<TrilinosScalar> &values);
- //@}
-
-
- /**
- * @name 3: Modification of vectors
- */
- //@{
/**
* This collective set operation is of lower level and can handle anything
const TrilinosScalar *values);
/**
- * A collective add operation: This funnction adds a whole set of values
+ * A collective add operation: This function adds a whole set of values
* stored in @p values to the vector components specified by @p indices.
*/
void add (const std::vector<size_type> &indices,
* Simple vector addition, equal to the <tt>operator +=</tt>.
*
* Though, if the second argument <tt>allow_different_maps</tt> is set,
- * then it is possible to add data from a different map.
+ * then it is possible to add data from a vector that uses a different
+ * map, i.e., a vector whose elements are split across processors
+ * differently. This may include vectors with ghost elements, for example.
+ * In general, however, adding vectors with a different element-to-processor
+ * map requires communicating data among processors and, consequently,
+ * is a slower operation than when using vectors using the same map.
*/
void add (const VectorBase &V,
const bool allow_different_maps = false);
/**
- * Simple addition of a multiple of a vector, i.e. <tt>*this = a*V</tt>.
+ * Simple addition of a multiple of a vector, i.e. <tt>*this += a*V</tt>.
*/
void add (const TrilinosScalar a,
const VectorBase &V);
/**
- * Multiple addition of scaled vectors, i.e. <tt>*this = a*V + b*W</tt>.
+ * Multiple addition of scaled vectors, i.e. <tt>*this += a*V + b*W</tt>.
*/
void add (const TrilinosScalar a,
const VectorBase &V,
bool has_ghosts;
/**
- * An Epetra distibuted vector type. Requires an existing Epetra_Map for
- * storing data.
+ * Pointer to the actual Epetra vector object. This may represent a
+ * vector that is in fact distributed among multiple processors. The
+ * object requires an existing Epetra_Map for
+ * storing data when setting it up.
*/
std_cxx1x::shared_ptr<Epetra_FEVector> vector;
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
- const int ierr = vector->Update(1., *(v.vector), s);
-
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ if(local_size() == v.local_size())
+ {
+ const int ierr = vector->Update(1., *(v.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+ else
+ {
+ VectorBase tmp = v;
+ tmp *= s;
+ this->add(tmp, true);
+ }
}
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
-
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
Assert (numbers::is_finite(a), ExcNumberNotFinite());
- const int ierr = vector->Update(a, *(v.vector), s);
-
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ if(local_size() == v.local_size())
+ {
+ const int ierr = vector->Update(a, *(v.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+ else
+ {
+ (*this)*=s;
+ VectorBase tmp = v;
+ tmp *= a;
+ this->add(tmp, true);
+ }
}
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
- Assert (local_size() == w.local_size(),
- ExcDimensionMismatch(local_size(), w.local_size()));
-
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
+ Assert (size() == w.size(),
+ ExcDimensionMismatch (size(), w.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
Assert (numbers::is_finite(a), ExcNumberNotFinite());
Assert (numbers::is_finite(b), ExcNumberNotFinite());
-
- const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
-
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ if(local_size() == v.local_size() && local_size() == w.local_size())
+ {
+ const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+ else
+ {
+ (*this)*=s;
+ {
+ VectorBase tmp = v;
+ tmp *= a;
+ this->add(tmp, true);
+ }
+ {
+ VectorBase tmp = w;
+ tmp *= b;
+ this->add(tmp, true);
+ }
+ }
}
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
- Assert (local_size() == w.local_size(),
- ExcDimensionMismatch(local_size(), w.local_size()));
- Assert (local_size() == x.local_size(),
- ExcDimensionMismatch(local_size(), x.local_size()));
-
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
+ Assert (size() == w.size(),
+ ExcDimensionMismatch (size(), w.size()));
+ Assert (size() == x.size(),
+ ExcDimensionMismatch (size(), x.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
Assert (numbers::is_finite(a), ExcNumberNotFinite());
Assert (numbers::is_finite(b), ExcNumberNotFinite());
Assert (numbers::is_finite(c), ExcNumberNotFinite());
- // Update member can only
- // input two other vectors so
- // do it in two steps
- const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
-
- const int jerr = vector->Update(c, *(x.vector), 1.);
- Assert (jerr == 0, ExcTrilinosError(jerr));
- (void)jerr; // removes -Wunused-parameter warning in optimized mode
+ if(local_size() == v.local_size()
+ && local_size() == w.local_size()
+ && local_size() == x.local_size())
+ {
+ // Update member can only
+ // input two other vectors so
+ // do it in two steps
+ const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ const int jerr = vector->Update(c, *(x.vector), 1.);
+ Assert (jerr == 0, ExcTrilinosError(jerr));
+ (void)jerr; // removes -Wunused-parameter warning in optimized mode
+ }
+ else
+ {
+ (*this)*=s;
+ {
+ VectorBase tmp = v;
+ tmp *= a;
+ this->add(tmp, true);
+ }
+ {
+ VectorBase tmp = w;
+ tmp *= b;
+ this->add(tmp, true);
+ }
+ {
+ VectorBase tmp = x;
+ tmp *= c;
+ this->add(tmp, true);
+ }
+ }
}
// If we don't have the same map, copy.
if (vector->Map().SameAs(v.vector->Map())==false)
{
- *vector = *v.vector;
- *this *= a;
+ this->sadd(0., a, v);
}
else
{
// If we don't have the same map, copy.
if (vector->Map().SameAs(v.vector->Map())==false)
{
- *vector = *v.vector;
- sadd(a, b, w);
+ sadd(0., a, v, b, w);
}
else
{
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/template_constraints.h>
#include <deal.II/base/symmetric_tensor.h>
#include <deal.II/base/vectorization.h>
+#include <deal.II/base/smartpointer.h>
#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/shape_info.h>
+#include <deal.II/matrix_free/mapping_fe_evaluation.h>
DEAL_II_NAMESPACE_OPEN
+// forward declarations
namespace internal
{
DeclException0 (ExcAccessToUninitializedField);
-
- template <typename FEEval>
- void do_evaluate (FEEval &, const bool, const bool, const bool);
- template <typename FEEval>
- void do_integrate (FEEval &, const bool, const bool);
}
/**
* This is the base class for the FEEvaluation classes. This class is a base
- * class and needs usually not be called in user code. Use one of the derived
- * classes FEEvaluationGeneral, FEEvaluation or FEEvaluationGL instead. It
- * implements a reinit method that is used to set pointers so that operations
- * on quadrature points can be performed quickly, access functions to vectors
- * for the @p read_dof_values, @p set_dof_values, and @p
- * distributed_local_to_global functions, as well as methods to access values
- * and gradients of finite element functions.
+ * class and needs usually not be called in user code. It does not have any
+ * public constructor. Use one of the derived classes FEEvaluationGeneral,
+ * FEEvaluation, FEEvaluationGL, or FEEvaluationDGP instead. It implements a
+ * reinit method that is used to set pointers so that operations on quadrature
+ * points can be performed quickly, access functions to vectors for the @p
+ * read_dof_values, @p set_dof_values, and @p distributed_local_to_global
+ * functions, as well as methods to access values and gradients of finite
+ * element functions.
*
- * This class has five template arguments:
+ * This class has three template arguments:
*
* @param dim Dimension in which this class is to be used
*
- * @param dofs_per_cell Number of degrees of freedom of the FE per cell,
- * usually (fe_degree+1)^dim for elements based on a tensor
- * product
- *
- * @param n_q_points Number of points in the quadrature formula, usually
- * (fe_degree+1)^dim for tensor-product quadrature formulas
- *
* @param n_components Number of vector components when solving a system of
* PDEs. If the same operation is applied to several
* components of a PDE (e.g. a vector Laplace equation), they
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
class FEEvaluationBase
{
public:
typedef Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
/**
* @name 1: General operations
*/
internal::MatrixFreeFunctions::CellType get_cell_type() const;
+ /**
+ * Returns a reference to the ShapeInfo object currently in use.
+ */
+ const internal::MatrixFreeFunctions::ShapeInfo<Number> &
+ get_shape_info() const;
+
+ /**
+ * Fills the JxW values currently used.
+ */
+ void
+ fill_JxW_values(AlignedVector<VectorizedArray<Number> > &JxW_values) const;
+
//@}
/**
* ConstraintMatrix::distribute. When accessing vector entries during the
* solution of linear systems, the temporary solution should always have
* homogeneous constraints and this method is the correct one.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on).
*/
template <typename VectorType>
void read_dof_values (const VectorType &src);
* function is also necessary when inhomogeneous constraints are to be used,
* as MatrixFree can only handle homogeneous constraints. Note that if
* vectorization is enabled, the DoF values for several cells are set.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on). In that case, no constraints can be
+ * processed as these are not available here.
*/
template <typename VectorType>
void read_dof_values_plain (const VectorType &src);
* Takes the values stored internally on dof values of the current cell and
* sums them into the vector @p dst. The function also applies constraints
* during the write operation. The functionality is hence similar to the
- * function ConstraintMatrix::distribute_local_to_global. Note that if
- * vectorization is enabled, the DoF values for several cells are used.
+ * function ConstraintMatrix::distribute_local_to_global. If vectorization
+ * is enabled, the DoF values for several cells are used.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on). In that case, no constraints can be
+ * processed as these are not available here.
*/
template<typename VectorType>
void distribute_local_to_global (VectorType &dst) const;
* and sums them into the collection of vectors vector @p dst, starting at
* index @p first_index. The function also applies constraints during the
* write operation. The functionality is hence similar to the function
- * ConstraintMatrix::distribute_local_to_global. Note that if vectorization
- * is enabled, the DoF values for several cells are used.
+ * ConstraintMatrix::distribute_local_to_global. If vectorization is
+ * enabled, the DoF values for several cells are used.
*/
template<typename VectorType>
void distribute_local_to_global (std::vector<VectorType> &dst,
* during the write operation. The functionality is hence similar to the
* function ConstraintMatrix::distribute_local_to_global. Note that if
* vectorization is enabled, the DoF values for several cells are used.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on). In that case, no constraints can be
+ * processed as these are not available here.
*/
template<typename VectorType>
void set_dof_values (VectorType &dst) const;
* select the appropriate components.
*/
FEEvaluationBase (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ */
+ FEEvaluationBase (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationBase (const FEEvaluationBase &other);
/**
* A unified function to read from and write into vectors based on the given
void read_dof_values_plain (const VectorType *src_data[]);
/**
- * Internal data fields that store the values. Since all array lengths are
- * known at compile time and since they are rarely more than a few
- * kilobytes, allocate them on the stack. This makes it possible to cheaply
- * set up a FEEvaluation object and write thread-safe programs by letting
- * each thread own a private object of this type.
+ * Internal data fields that store the values. Derived classes will know the
+ * length of all arrays at compile time and allocate the memory on the
+ * stack. This makes it possible to cheaply set up a FEEvaluation object and
+ * write thread-safe programs by letting each thread own a private object of
+ * this type. In this base class, only pointers to the actual data are
+ * stored.
*
* This field stores the values for local degrees of freedom (e.g. after
* reading out from a vector but before applying unit cell transformations
* or before distributing them into a result vector). The methods
* get_dof_value() and submit_dof_value() read from or write to this field.
*/
- VectorizedArray<Number> values_dofs[n_components][dofs_per_cell>0?dofs_per_cell:1];
+ VectorizedArray<Number>* values_dofs[n_components];
/**
* This field stores the values of the finite element function on quadrature
* integrating. The methods get_value() and submit_value() access this
* field.
*/
- VectorizedArray<Number> values_quad[n_components][n_q_points>0?n_q_points:1];
+ VectorizedArray<Number>* values_quad[n_components];
/**
* This field stores the gradients of the finite element function on
* some specializations like get_symmetric_gradient() or get_divergence())
* access this field.
*/
- VectorizedArray<Number> gradients_quad[n_components][dim][n_q_points>0?n_q_points:1];
+ VectorizedArray<Number>* gradients_quad[n_components][dim];
/**
* This field stores the Hessians of the finite element function on
* quadrature points after applying unit cell transformations. The methods
* get_hessian(), get_laplacian(), get_hessian_diagonal() access this field.
*/
- VectorizedArray<Number> hessians_quad[n_components][(dim*(dim+1))/2][n_q_points>0?n_q_points:1];
+ VectorizedArray<Number>* hessians_quad[n_components][(dim*(dim+1))/2];
/**
* Stores the number of the quadrature formula of the present cell.
const unsigned int active_quad_index;
/**
- * Stores a reference to the underlying data.
+ * Stores a pointer to the underlying data.
*/
- const MatrixFree<dim,Number> &matrix_info;
+ const MatrixFree<dim,Number> *matrix_info;
/**
- * Stores a reference to the underlying DoF indices and constraint
+ * Stores a pointer to the underlying DoF indices and constraint
* description for the component specified at construction. Also contained
* in matrix_info, but it simplifies code if we store a reference to it.
*/
- const internal::MatrixFreeFunctions::DoFInfo &dof_info;
+ const internal::MatrixFreeFunctions::DoFInfo *dof_info;
/**
- * Stores a reference to the underlying transformation data from unit to
+ * Stores a pointer to the underlying transformation data from unit to
* real cells for the given quadrature formula specified at construction.
* Also contained in matrix_info, but it simplifies code if we store a
* reference to it.
*/
- const internal::MatrixFreeFunctions::MappingInfo<dim,Number> &mapping_info;
+ const internal::MatrixFreeFunctions::MappingInfo<dim,Number> *mapping_info;
+
+ /**
+ * In case the class is initialized from MappingFEEvaluation instead of
+ * MatrixFree, this data structure holds the evaluated shape data.
+ */
+ std_cxx1x::shared_ptr<internal::MatrixFreeFunctions::ShapeInfo<Number> > stored_shape_info;
/**
- * Stores a reference to the unit cell data, i.e., values, gradients and
+ * Stores a pointer to the unit cell shape data, i.e., values, gradients and
* Hessians in 1D at the quadrature points that constitute the tensor
* product. Also contained in matrix_info, but it simplifies code if we
* store a reference to it.
*/
- const internal::MatrixFreeFunctions::ShapeInfo<Number> &data;
+ const internal::MatrixFreeFunctions::ShapeInfo<Number> *data;
/**
* A pointer to the Cartesian Jacobian information of the present cell. Only
* stared. Used to control exceptions when uninitialized data is used.
*/
bool gradients_quad_submitted;
+
+ /**
+ * Geometry data generated by FEValues on the fly.
+ */
+ SmartPointer<const MappingFEEvaluation<dim,Number> > mapped_geometry;
+
+ /**
+ * A pointer to the underlying DoFHandler.
+ */
+ const DoFHandler<dim> *dof_handler;
+
+ /**
+ * For a DoFHandler with more than one finite element, select at which
+ * component this data structure should start.
+ */
+ const unsigned int first_selected_component;
+
+ /**
+ * A temporary data structure necessary to read degrees of freedom when no
+ * MatrixFree object was given at initialization.
+ */
+ mutable std::vector<types::global_dof_index> local_dof_indices;
};
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
-class FEEvaluationAccess :
- public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+template <int dim, int n_components_, typename Number>
+class FEEvaluationAccess : public FEEvaluationBase<dim,n_components_,Number>
{
public:
typedef Number number_type;
typedef Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
- typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,
- Number> BaseClass;
+ typedef FEEvaluationBase<dim,n_components_, Number> BaseClass;
protected:
/**
* the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationAccess (const FEEvaluationAccess &other);
};
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
-class FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number> :
- public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,1,Number>
+template <int dim, typename Number>
+class FEEvaluationAccess<dim,1,Number> : public FEEvaluationBase<dim,1,Number>
{
public:
typedef Number number_type;
typedef VectorizedArray<Number> value_type;
typedef Tensor<1,dim,VectorizedArray<Number> > gradient_type;
static const unsigned int dimension = dim;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
- typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,1,Number> BaseClass;
+ typedef FEEvaluationBase<dim,1,Number> BaseClass;
/**
* Returns the value stored for the local degree of freedom with index @p
* the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationAccess (const FEEvaluationAccess &other);
};
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
-class FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number> :
- public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,dim,Number>
+template <int dim, typename Number>
+class FEEvaluationAccess<dim,dim,Number> : public FEEvaluationBase<dim,dim,Number>
{
public:
typedef Number number_type;
typedef Tensor<2,dim,VectorizedArray<Number> > gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = dim;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
- typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,dim,Number> BaseClass;
+ typedef FEEvaluationBase<dim,dim,Number> BaseClass;
/**
* Returns the gradient of a finite element function at quadrature point
* the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationAccess (const FEEvaluationAccess &other);
};
*/
template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
int n_components_ = 1, typename Number = double >
-class FEEvaluationGeneral :
- public FEEvaluationAccess<dim,
- Utilities::fixed_int_power<fe_degree+1,dim>::value,
- Utilities::fixed_int_power<n_q_points_1d,dim>::value,
- n_components_,Number>
+class FEEvaluationGeneral : public FEEvaluationAccess<dim, n_components_,Number>
{
public:
- typedef FEEvaluationAccess<dim,
- Utilities::fixed_int_power<fe_degree+1,dim>::value,
- Utilities::fixed_int_power<n_q_points_1d,dim>::value,
- n_components_, Number> BaseClass;
+ typedef FEEvaluationAccess<dim, n_components_, Number> BaseClass;
typedef Number number_type;
typedef typename BaseClass::value_type value_type;
typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
- static const unsigned int n_q_points = BaseClass::n_q_points;
+ static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
/**
* Constructor. Takes all data stored in MatrixFree. If applied to problems
const unsigned int fe_no = 0,
const unsigned int quad_no = 0);
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationGeneral (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationGeneral (const FEEvaluationGeneral &other);
+
/**
* Evaluates the function values, the gradients, and the Laplacians of the
* FE function given at the DoF values in the input vector at the quadrature
Point<dim,VectorizedArray<Number> >
quadrature_point (const unsigned int q_point) const;
-protected:
-
/**
* Internal function that applies the function values of the tensor product
* in a given coordinate direction (first template argument), from
void apply_hessians (const VectorizedArray<Number> in [],
VectorizedArray<Number> out []);
+protected:
+
+ /**
+ * Internally stored variables for the different data fields.
+ */
+ VectorizedArray<Number> my_data_array[n_components*(dofs_per_cell+(dim*dim+2*dim+1)*n_q_points)];
+
+private:
/**
- * Friend declaration.
+ * Sets the pointers from the data array to values_dof, etc.
*/
- template <typename FEEval> friend void
- internal::do_evaluate (FEEval &, const bool, const bool, const bool);
- template <typename FEEval> friend void
- internal::do_integrate (FEEval &, const bool, const bool);
+ void set_data_pointers();
};
* functions that make it much faster (between 5 and 500, depending on the
* polynomial order).
*
+ * This class can be used in two different ways. The first way is to
+ * initialize it from a MatrixFree object that caches everything related to
+ * the degrees of freedom and the mapping information. This way, it is
+ * possible to use vectorization for applying a vector operation for several
+ * cells at once. The second form of usage is to initialize it from geometry
+ * information generated by FEValues, which is stored in the class
+ * MappingFEEvaluation. Here, the operations can only work on a single cell, but
+ * possibly be vectorized by combining several operations (e.g. when
+ * performing matrix assembly).
+ *
* This class is a specialization of FEEvaluationGeneral designed for standard
* FE_Q or FE_DGQ elements and quadrature points symmetric around 0.5 (like
* Gauss quadrature), and hence the most common situation. Note that many of
const unsigned int fe_no = 0,
const unsigned int quad_no = 0);
+ /**
+ * Copy constructor
+ */
+ FEEvaluation (const FEEvaluation &other);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ */
+ FEEvaluation (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
/**
* Evaluates the function values, the gradients, and the Laplacians of the
* FE function given at the DoF values in the input vector at the quadrature
void integrate (const bool integrate_val,
const bool integrate_grad);
-protected:
-
/**
* Internal function that applies the function values of the tensor product
* in a given coordinate direction (first template argument), from
void apply_hessians (const VectorizedArray<Number> in [],
VectorizedArray<Number> out []);
+protected:
VectorizedArray<Number> shape_val_evenodd[fe_degree+1][(n_q_points_1d+1)/2];
VectorizedArray<Number> shape_gra_evenodd[fe_degree+1][(n_q_points_1d+1)/2];
VectorizedArray<Number> shape_hes_evenodd[fe_degree+1][(n_q_points_1d+1)/2];
+private:
/**
- * Friend declarations.
+ * Fills the fields shapve_???_evenodd, called in the constructor.
*/
- template <typename FEEval> friend void
- internal::do_evaluate (FEEval &, const bool, const bool, const bool);
- template <typename FEEval> friend void
- internal::do_integrate (FEEval &, const bool, const bool);
+ void compute_even_odd_factors();
};
const unsigned int fe_no = 0,
const unsigned int quad_no = 0);
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ */
+ FEEvaluationGL (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationGL (const FEEvaluationGL &other);
+
/**
* Evaluates the function values, the gradients, and the Hessians of the FE
* function given at the DoF values in the input vector at the quadrature
void integrate (const bool integrate_val,
const bool integrate_grad);
-protected:
/**
* Internal function that applies the gradient operation of the tensor
* product in a given coordinate direction (first template argument), from
+namespace internal
+{
+ namespace MatrixFreeFunctions
+ {
+ // a helper function to compute the number of DoFs of a DGP element at compile
+ // time, depending on the degree
+ template <int dim, int degree>
+ struct DGP_dofs_per_cell
+ {
+ // this division is always without remainder
+ static const unsigned int value =
+ (DGP_dofs_per_cell<dim-1,degree>::value * (degree+dim)) / dim;
+ };
+
+ // base specialization: 1d elements have 'degree+1' degrees of freedom
+ template <int degree>
+ struct DGP_dofs_per_cell<1,degree>
+ {
+ static const unsigned int value = degree+1;
+ };
+ }
+}
+
+
+
+/**
+ * The class that provides all functions necessary to evaluate functions at
+ * quadrature points and cell integrations. In functionality, this class is
+ * similar to FEValues<dim>, however, it includes a lot of specialized
+ * functions that make it much faster (between 5 and 500 times as fast,
+ * depending on the polynomial order). Access to the data fields is provided
+ * through functionality in the class FEEvaluationAccess.
+ *
+ * This class is an extension of FEEvaluationGeneral to work with elements of
+ * complete polynomial degree p, FE_DGP. In this case, the polynomial basis is
+ * a truncated tensor product, so the evaluate and integrate routines use a
+ * truncation.
+ *
+ * @author Martin Kronbichler, 2014
+ */
+template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
+ int n_components_ = 1, typename Number = double >
+class FEEvaluationDGP :
+ public FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
+{
+public:
+ typedef FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number> BaseClass;
+ typedef Number number_type;
+ typedef typename BaseClass::value_type value_type;
+ typedef typename BaseClass::gradient_type gradient_type;
+ static const unsigned int dimension = dim;
+ static const unsigned int n_components = n_components_;
+ static const unsigned int dofs_per_cell = internal::MatrixFreeFunctions::DGP_dofs_per_cell<dim,fe_degree>::value;
+ static const unsigned int n_q_points = BaseClass::n_q_points;
+
+ /**
+ * Constructor. Takes all data stored in MatrixFree. If applied to problems
+ * with more than one finite element or more than one quadrature formula
+ * selected during construction of @p matrix_free, @p fe_no and @p quad_no
+ * allow to select the appropriate components.
+ */
+ FEEvaluationDGP (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ */
+ FEEvaluationDGP (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationDGP (const FEEvaluationDGP &other);
+
+ /**
+ * Evaluates the function values, the gradients, and the Hessians of the FE
+ * function given at the DoF values in the input vector at the quadrature
+ * points of the unit cell. The function arguments specify which parts shall
+ * actually be computed. Needs to be called before the functions @p
+ * get_value(), @p get_gradient() or @p get_laplacian give useful
+ * information (unless these values have been set manually).
+ */
+ void evaluate (const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl = false);
+
+ /**
+ * This function takes the values and/or gradients that are stored on
+ * quadrature points, tests them by all the basis functions/gradients on the
+ * cell and performs the cell integration. The two function arguments @p
+ * integrate_val and @p integrate_grad are used to enable/disable some of
+ * values or gradients.
+ */
+ void integrate (const bool integrate_val,
+ const bool integrate_grad);
+};
+
/*----------------------- Inline functions ----------------------------------*/
#ifndef DOXYGEN
+
/*----------------------- FEEvaluationBase ----------------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::FEEvaluationBase (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no_in,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points)
:
quad_no (quad_no_in),
n_fe_components (data_in.get_dof_info(fe_no_in).n_components),
active_fe_index (data_in.get_dof_info(fe_no_in).fe_index_from_dofs_per_cell
- (dofs_per_cell_ * n_fe_components)),
+ (dofs_per_cell * n_fe_components)),
active_quad_index (data_in.get_mapping_info().
mapping_data_gen[quad_no_in].
- quad_index_from_n_q_points(n_q_points_)),
- matrix_info (data_in),
- dof_info (data_in.get_dof_info(fe_no_in)),
- mapping_info (data_in.get_mapping_info()),
- data (data_in.get_shape_info
+ quad_index_from_n_q_points(n_q_points)),
+ matrix_info (&data_in),
+ dof_info (&data_in.get_dof_info(fe_no_in)),
+ mapping_info (&data_in.get_mapping_info()),
+ data (&data_in.get_shape_info
(fe_no_in, quad_no_in, active_fe_index,
active_quad_index)),
cartesian_data (0),
jacobian (0),
J_value (0),
- quadrature_weights (mapping_info.mapping_data_gen[quad_no].
+ quadrature_weights (mapping_info->mapping_data_gen[quad_no].
quadrature_weights[active_quad_index].begin()),
quadrature_points (0),
jacobian_grad (0),
jacobian_grad_upper(0),
cell (numbers::invalid_unsigned_int),
cell_type (internal::MatrixFreeFunctions::undefined),
- cell_data_number (0)
+ cell_data_number (0),
+ dof_handler (0),
+ first_selected_component (0)
{
- Assert (matrix_info.mapping_initialized() == true,
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ values_dofs[c] = 0;
+ values_quad[c] = 0;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients_quad[c][d] = 0;
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ hessians_quad[c][d] = 0;
+ }
+ Assert (matrix_info->mapping_initialized() == true,
ExcNotInitialized());
- AssertDimension (matrix_info.get_size_info().vectorization_length,
+ AssertDimension (matrix_info->get_size_info().vectorization_length,
VectorizedArray<Number>::n_array_elements);
+ AssertDimension (data->dofs_per_cell,
+ dof_info->dofs_per_cell[active_fe_index]/n_fe_components);
+ AssertDimension (data->n_q_points,
+ mapping_info->mapping_data_gen[quad_no].n_q_points[active_quad_index]);
Assert (n_fe_components == 1 ||
n_components == 1 ||
n_components == n_fe_components,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationBase<dim,n_components_,Number>
+::FEEvaluationBase (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler_in,
+ const unsigned int first_selected_component)
+ :
+ quad_no (-1),
+ n_fe_components (n_components_),
+ active_fe_index (-1),
+ active_quad_index (-1),
+ matrix_info (0),
+ dof_info (0),
+ mapping_info (0),
+ stored_shape_info (new internal::MatrixFreeFunctions::ShapeInfo<Number>(geometry.get_quadrature(), dof_handler_in.get_fe(), 0)),
+ data (stored_shape_info.get()),
+ cartesian_data (0),
+ jacobian (geometry.get_inverse_jacobians().begin()),
+ J_value (geometry.get_JxW_values().begin()),
+ quadrature_weights (0),
+ quadrature_points (geometry.get_quadrature_points().begin()),
+ jacobian_grad (0),
+ jacobian_grad_upper(0),
+ cell (0),
+ cell_type (internal::MatrixFreeFunctions::general),
+ cell_data_number (0),
+ mapped_geometry (&geometry),
+ dof_handler (&dof_handler_in),
+ first_selected_component (first_selected_component)
+{
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ values_dofs[c] = 0;
+ values_quad[c] = 0;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients_quad[c][d] = 0;
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ hessians_quad[c][d] = 0;
+ }
+ Assert(dof_handler->get_fe().element_multiplicity(0) == 1 ||
+ dof_handler->get_fe().element_multiplicity(0)-first_selected_component >= n_components_,
+ ExcMessage("The underlying element must at least contain as many "
+ "components as requested by this class"));
+}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationBase<dim,n_components_,Number>
+::FEEvaluationBase (const FEEvaluationBase<dim,n_components_,Number> &other)
+ :
+ quad_no (other.quad_no),
+ n_fe_components (other.n_fe_components),
+ active_fe_index (other.active_fe_index),
+ active_quad_index (other.active_quad_index),
+ matrix_info (other.matrix_info),
+ dof_info (other.dof_info),
+ mapping_info (other.mapping_info),
+ stored_shape_info (other.stored_shape_info),
+ data (other.data),
+ cartesian_data (other.cartesian_data),
+ jacobian (other.jacobian),
+ J_value (other.J_value),
+ quadrature_weights (other.quadrature_weights),
+ quadrature_points (other.quadrature_points),
+ jacobian_grad (other.jacobian_grad),
+ jacobian_grad_upper(other.jacobian_grad_upper),
+ cell (other.cell),
+ cell_type (other.cell_type),
+ cell_data_number (other.cell_data_number),
+ mapped_geometry (other.mapped_geometry),
+ dof_handler (other.dof_handler),
+ first_selected_component (other.first_selected_component)
+{
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ values_dofs[c] = 0;
+ values_quad[c] = 0;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients_quad[c][d] = 0;
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ hessians_quad[c][d] = 0;
+ }
+}
+
+
+
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
-::reinit (const unsigned int cell_in)
+FEEvaluationBase<dim,n_components_,Number>::reinit (const unsigned int cell_in)
{
- AssertIndexRange (cell_in, dof_info.row_starts.size()-1);
- AssertDimension (((dof_info.cell_active_fe_index.size() > 0) ?
- dof_info.cell_active_fe_index[cell_in] : 0),
+ Assert (mapped_geometry == 0, ExcMessage("FEEvaluation was initialized without a matrix-free object. Integer indexing is not possible"));
+ if (mapped_geometry != 0)
+ return;
+ Assert (dof_info != 0, ExcNotInitialized());
+ Assert (mapping_info != 0, ExcNotInitialized());
+ AssertIndexRange (cell_in, dof_info->row_starts.size()-1);
+ AssertDimension (((dof_info->cell_active_fe_index.size() > 0) ?
+ dof_info->cell_active_fe_index[cell_in] : 0),
active_fe_index);
cell = cell_in;
- cell_type = mapping_info.get_cell_type(cell);
- cell_data_number = mapping_info.get_cell_data_index(cell);
+ cell_type = mapping_info->get_cell_type(cell);
+ cell_data_number = mapping_info->get_cell_data_index(cell);
- if (mapping_info.quadrature_points_initialized == true)
+ if (mapping_info->quadrature_points_initialized == true)
{
- AssertIndexRange (cell_data_number, mapping_info.
+ AssertIndexRange (cell_data_number, mapping_info->
mapping_data_gen[quad_no].rowstart_q_points.size());
- const unsigned int index = mapping_info.mapping_data_gen[quad_no].
+ const unsigned int index = mapping_info->mapping_data_gen[quad_no].
rowstart_q_points[cell];
- AssertIndexRange (index, mapping_info.mapping_data_gen[quad_no].
+ AssertIndexRange (index, mapping_info->mapping_data_gen[quad_no].
quadrature_points.size());
quadrature_points =
- &mapping_info.mapping_data_gen[quad_no].quadrature_points[index];
+ &mapping_info->mapping_data_gen[quad_no].quadrature_points[index];
}
if (cell_type == internal::MatrixFreeFunctions::cartesian)
{
- cartesian_data = &mapping_info.cartesian_data[cell_data_number].first;
- J_value = &mapping_info.cartesian_data[cell_data_number].second;
+ cartesian_data = &mapping_info->cartesian_data[cell_data_number].first;
+ J_value = &mapping_info->cartesian_data[cell_data_number].second;
}
else if (cell_type == internal::MatrixFreeFunctions::affine)
{
- jacobian = &mapping_info.affine_data[cell_data_number].first;
- J_value = &mapping_info.affine_data[cell_data_number].second;
+ jacobian = &mapping_info->affine_data[cell_data_number].first;
+ J_value = &mapping_info->affine_data[cell_data_number].second;
}
else
{
- const unsigned int rowstart = mapping_info.
+ const unsigned int rowstart = mapping_info->
mapping_data_gen[quad_no].rowstart_jacobians[cell_data_number];
- AssertIndexRange (rowstart, mapping_info.
+ AssertIndexRange (rowstart, mapping_info->
mapping_data_gen[quad_no].jacobians.size());
jacobian =
- &mapping_info.mapping_data_gen[quad_no].jacobians[rowstart];
- if (mapping_info.JxW_values_initialized == true)
+ &mapping_info->mapping_data_gen[quad_no].jacobians[rowstart];
+ if (mapping_info->JxW_values_initialized == true)
{
- AssertIndexRange (rowstart, mapping_info.
+ AssertIndexRange (rowstart, mapping_info->
mapping_data_gen[quad_no].JxW_values.size());
- J_value = &(mapping_info.mapping_data_gen[quad_no].
+ J_value = &(mapping_info->mapping_data_gen[quad_no].
JxW_values[rowstart]);
}
- if (mapping_info.second_derivatives_initialized == true)
+ if (mapping_info->second_derivatives_initialized == true)
{
- AssertIndexRange(rowstart, mapping_info.
+ AssertIndexRange(rowstart, mapping_info->
mapping_data_gen[quad_no].jacobians_grad_diag.size());
- jacobian_grad = &mapping_info.mapping_data_gen[quad_no].
+ jacobian_grad = &mapping_info->mapping_data_gen[quad_no].
jacobians_grad_diag[rowstart];
- AssertIndexRange(rowstart, mapping_info.
+ AssertIndexRange(rowstart, mapping_info->
mapping_data_gen[quad_no].jacobians_grad_upper.size());
- jacobian_grad_upper = &mapping_info.mapping_data_gen[quad_no].
+ jacobian_grad_upper = &mapping_info->mapping_data_gen[quad_no].
jacobians_grad_upper[rowstart];
}
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
unsigned int
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_cell_data_number () const
{
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
internal::MatrixFreeFunctions::CellType
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
-::get_cell_type () const
+FEEvaluationBase<dim,n_components_,Number>::get_cell_type () const
{
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
return cell_type;
+template <int dim, int n_components_, typename Number>
+inline
+const internal::MatrixFreeFunctions::ShapeInfo<Number> &
+FEEvaluationBase<dim,n_components_,Number>::get_shape_info() const
+{
+ Assert(data != 0, ExcInternalError());
+ return *data;
+}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+void
+FEEvaluationBase<dim,n_components_,Number>
+::fill_JxW_values(AlignedVector<VectorizedArray<Number> > &JxW_values) const
+{
+ AssertDimension(JxW_values.size(), data->n_q_points);
+ Assert (this->J_value != 0, ExcNotImplemented());
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian ||
+ this->cell_type == internal::MatrixFreeFunctions::affine)
+ {
+ Assert (this->mapping_info != 0, ExcNotImplemented());
+ VectorizedArray<Number> J = this->J_value[0];
+ for (unsigned int q=0; q<this->data->n_q_points; ++q)
+ JxW_values[q] = J * this->quadrature_weights[q];
+ }
+ else
+ for (unsigned int q=0; q<data->n_q_points; ++q)
+ JxW_values[q] = this->J_value[q];
+}
+
+
+
namespace internal
{
// write access to generic vectors that have operator ().
res = vector_access (const_cast<const VectorType &>(vec), index);
}
+ template <typename VectorType>
+ void process_dof_global (const types::global_dof_index index,
+ VectorType &vec,
+ Number &res) const
+ {
+ res = const_cast<const VectorType &>(vec)(index);
+ }
+
void pre_constraints (const Number &,
Number &res) const
{
vector_access (vec, index) += res;
}
+ template <typename VectorType>
+ void process_dof_global (const types::global_dof_index index,
+ VectorType &vec,
+ Number &res) const
+ {
+ vec(index) += res;
+ }
+
void pre_constraints (const Number &input,
Number &res) const
{
vector_access (vec, index) = res;
}
+ template <typename VectorType>
+ void process_dof_global (const types::global_dof_index index,
+ VectorType &vec,
+ Number &res) const
+ {
+ vec(index) = res;
+ }
+
void pre_constraints (const Number &,
Number &) const
{
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType, typename VectorOperation>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_write_operation (const VectorOperation &operation,
VectorType *src[]) const
{
// into the local data field or write local data into the vector. Certain
// operations are no-ops for the given use case.
- Assert (matrix_info.indices_initialized() == true,
+ // Case 1: No MatrixFree object given, simple case because we do not need to
+ // process constraints and need not care about vectorization
+ if (matrix_info == 0)
+ {
+ Assert (dof_handler != 0, ExcNotInitialized());
+ typename DoFHandler<dim>::cell_iterator cell (&dof_handler->get_tria(),
+ mapped_geometry->get_cell()->level(),
+ mapped_geometry->get_cell()->index(),
+ dof_handler);
+ local_dof_indices.resize(dof_handler->get_fe().dofs_per_cell);
+ cell->get_dof_indices(local_dof_indices);
+
+ unsigned int index = first_selected_component * this->data->dofs_per_cell;
+ for (unsigned int comp = 0; comp<n_components; ++comp)
+ {
+ for (unsigned int i=0; i<this->data->dofs_per_cell; ++i, ++index)
+ {
+ operation.process_dof_global(local_dof_indices[this->data->lexicographic_numbering[index]],
+ *src[0], values_dofs[comp][i][0]);
+ for (unsigned int v=1; v<VectorizedArray<Number>::n_array_elements; ++v)
+ operation.process_empty(values_dofs[comp][i][v]);
+ }
+ }
+ return;
+ }
+
+ Assert (dof_info != 0, ExcNotInitialized());
+ Assert (matrix_info->indices_initialized() == true,
ExcNotInitialized());
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
// loop over all local dofs. ind_local holds local number on cell, index
// iterates over the elements of index_local_to_global and dof_indices
// points to the global indices stored in index_local_to_global
- const unsigned int *dof_indices = dof_info.begin_indices(cell);
+ const unsigned int *dof_indices = dof_info->begin_indices(cell);
const std::pair<unsigned short,unsigned short> *indicators =
- dof_info.begin_indicators(cell);
+ dof_info->begin_indicators(cell);
const std::pair<unsigned short,unsigned short> *indicators_end =
- dof_info.end_indicators(cell);
+ dof_info->end_indicators(cell);
unsigned int ind_local = 0;
+ const unsigned int dofs_per_cell = this->data->dofs_per_cell;
- const unsigned int n_irreg_components_filled = dof_info.row_starts[cell][2];
+ const unsigned int n_irreg_components_filled = dof_info->row_starts[cell][2];
const bool at_irregular_cell = n_irreg_components_filled > 0;
// scalar case (or case when all components have the same degrees of freedom
const unsigned int n_local_dofs =
VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
- internal::check_vector_compatibility (*src[comp], dof_info);
+ internal::check_vector_compatibility (*src[comp], *dof_info);
Number *local_data [n_components];
for (unsigned int comp=0; comp<n_components; ++comp)
local_data[comp] =
value[comp]);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
operation.process_constraint (*dof_indices, *data_val,
{
// no constraint at all: loop bounds are known, compiler can
// unroll without checks
- AssertDimension (dof_info.end_indices(cell)-dof_indices,
+ AssertDimension (dof_info->end_indices(cell)-dof_indices,
static_cast<int>(n_local_dofs));
for (unsigned int j=0; j<n_local_dofs; ++j)
for (unsigned int comp=0; comp<n_components; ++comp)
value[comp]);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
}
for (; ind_local<n_local_dofs; ++dof_indices)
{
- Assert (dof_indices != dof_info.end_indices(cell),
+ Assert (dof_indices != dof_info->end_indices(cell),
ExcInternalError());
// non-constrained case: copy the data from the global vector,
// the first component, then all entries to the second one, and so
// on. This is ensured by the way MatrixFree reads out the indices.
{
- internal::check_vector_compatibility (*src[0], dof_info);
+ internal::check_vector_compatibility (*src[0], *dof_info);
Assert (n_fe_components == n_components_, ExcNotImplemented());
const unsigned int n_local_dofs =
dofs_per_cell*VectorizedArray<Number>::n_array_elements * n_components;
operation.pre_constraints (local_data[ind_local], value);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
operation.process_constraint (*dof_indices, *data_val,
for (; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
operation.process_dof (*dof_indices, *src[0],
local_data[ind_local]);
- Assert (dof_indices == dof_info.end_indices(cell),
+ Assert (dof_indices == dof_info->end_indices(cell),
ExcInternalError());
}
else
{
// no constraint at all: loop bounds are known, compiler can
// unroll without checks
- AssertDimension (dof_info.end_indices(cell)-dof_indices,
+ AssertDimension (dof_info->end_indices(cell)-dof_indices,
static_cast<int>(n_local_dofs));
for (unsigned int j=0; j<n_local_dofs; ++j)
operation.process_dof (dof_indices[j], *src[0],
operation.pre_constraints (local_data[ind_local], value);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
operation.process_constraint (*dof_indices, *data_val,
}
for (; ind_local<n_local_dofs; ++dof_indices)
{
- Assert (dof_indices != dof_info.end_indices(cell),
+ Assert (dof_indices != dof_info->end_indices(cell),
ExcInternalError());
// non-constrained case: copy the data from the global vector,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values (const VectorType &src)
{
// select between block vectors and non-block vectors. Note that the number
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values (const std::vector<VectorType> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values (const std::vector<VectorType *> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const VectorType &src)
{
// select between block vectors and non-block vectors. Note that the number
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const std::vector<VectorType> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const std::vector<VectorType *> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::distribute_local_to_global (VectorType &dst) const
{
Assert (dof_values_initialized==true,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::distribute_local_to_global (std::vector<VectorType> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::distribute_local_to_global (std::vector<VectorType *> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::set_dof_values (VectorType &dst) const
{
Assert (dof_values_initialized==true,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::set_dof_values (std::vector<VectorType> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::set_dof_values (std::vector<VectorType *> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const VectorType *src[])
{
+ // Case without MatrixFree initialization object
+ if (matrix_info == 0)
+ {
+ internal::VectorReader<Number> reader;
+ read_write_operation (reader, src);
+ return;
+ }
+
// this is different from the other three operations because we do not use
// constraints here, so this is a separate function.
- Assert (matrix_info.indices_initialized() == true,
+ Assert (dof_info != 0, ExcNotInitialized());
+ Assert (matrix_info->indices_initialized() == true,
ExcNotInitialized());
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- Assert (dof_info.store_plain_indices == true, ExcNotInitialized());
+ Assert (dof_info->store_plain_indices == true, ExcNotInitialized());
// loop over all local dofs. ind_local holds local number on cell, index
// iterates over the elements of index_local_to_global and dof_indices
// points to the global indices stored in index_local_to_global
- const unsigned int *dof_indices = dof_info.begin_indices_plain(cell);
+ const unsigned int *dof_indices = dof_info->begin_indices_plain(cell);
+ const unsigned int dofs_per_cell = this->data->dofs_per_cell;
- const unsigned int n_irreg_components_filled = dof_info.row_starts[cell][2];
+ const unsigned int n_irreg_components_filled = dof_info->row_starts[cell][2];
const bool at_irregular_cell = n_irreg_components_filled > 0;
// scalar case (or case when all components have the same degrees of freedom
const unsigned int n_local_dofs =
VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
- internal::check_vector_compatibility (*src[comp], dof_info);
+ internal::check_vector_compatibility (*src[comp], *dof_info);
Number *local_src_number [n_components];
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp] = &values_dofs[comp][0][0];
// the first component, then all entries to the second one, and so
// on. This is ensured by the way MatrixFree reads out the indices.
{
- internal::check_vector_compatibility (*src[0], dof_info);
+ internal::check_vector_compatibility (*src[0], *dof_info);
Assert (n_fe_components == n_components_, ExcNotImplemented());
const unsigned int n_local_dofs =
dofs_per_cell * VectorizedArray<Number>::n_array_elements * n_components;
/*------------------------------ access to data fields ----------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_dof_values () const
{
return &values_dofs[0][0];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_dof_values ()
{
#ifdef DEBUG
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_values () const
{
Assert (values_quad_initialized || values_quad_submitted,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_values ()
{
#ifdef DEBUG
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_gradients () const
{
Assert (gradients_quad_initialized || gradients_quad_submitted,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_gradients ()
{
#ifdef DEBUG
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_hessians () const
{
Assert (hessians_quad_initialized, ExcNotInitialized());
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_hessians ()
{
return &hessians_quad[0][0][0];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_dof_value (const unsigned int dof) const
{
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
Tensor<1,n_components_,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; comp++)
return_value[comp] = this->values_dofs[comp][dof];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_value (const unsigned int q_point) const
{
Assert (this->values_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; comp++)
return_value[comp] = this->values_quad[comp][q_point];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_gradient (const unsigned int q_point) const
{
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > grad_out (false);
{
// compute tmp = hess_unit(u) * J^T. do this manually because we do not
// store the lower diagonal because of symmetry
- template <int dim, int n_q_points, typename Number>
+ template <typename Number>
+ inline
+ void
+ hessian_unit_times_jac (const Tensor<2,1,VectorizedArray<Number> > &jac,
+ const VectorizedArray<Number> *const hessians_quad[1],
+ const unsigned int q_point,
+ VectorizedArray<Number> (&tmp)[1][1])
+ {
+ tmp[0][0] = jac[0][0] * hessians_quad[0][q_point];
+ }
+
+ template <typename Number>
inline
void
- hessian_unit_times_jac (const Tensor<2,dim,VectorizedArray<Number> > &jac,
- const VectorizedArray<Number> hessians_quad[][n_q_points],
- const unsigned int q_point,
- VectorizedArray<Number> tmp[dim][dim])
+ hessian_unit_times_jac (const Tensor<2,2,VectorizedArray<Number> > &jac,
+ const VectorizedArray<Number> *const hessians_quad[3],
+ const unsigned int q_point,
+ VectorizedArray<Number> (&tmp)[2][2])
{
- for (unsigned int d=0; d<dim; ++d)
+ for (unsigned int d=0; d<2; ++d)
{
- switch (dim)
- {
- case 1:
- tmp[0][0] = jac[0][0] * hessians_quad[0][q_point];
- break;
- case 2:
- tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
- jac[d][1] * hessians_quad[2][q_point]);
- tmp[1][d] = (jac[d][0] * hessians_quad[2][q_point] +
- jac[d][1] * hessians_quad[1][q_point]);
- break;
- case 3:
- tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
- jac[d][1] * hessians_quad[3][q_point] +
- jac[d][2] * hessians_quad[4][q_point]);
- tmp[1][d] = (jac[d][0] * hessians_quad[3][q_point] +
- jac[d][1] * hessians_quad[1][q_point] +
- jac[d][2] * hessians_quad[5][q_point]);
- tmp[2][d] = (jac[d][0] * hessians_quad[4][q_point] +
- jac[d][1] * hessians_quad[5][q_point] +
- jac[d][2] * hessians_quad[2][q_point]);
- break;
- default:
- Assert (false, ExcNotImplemented());
- }
+ tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
+ jac[d][1] * hessians_quad[2][q_point]);
+ tmp[1][d] = (jac[d][0] * hessians_quad[2][q_point] +
+ jac[d][1] * hessians_quad[1][q_point]);
+ }
+ }
+
+ template <typename Number>
+ inline
+ void
+ hessian_unit_times_jac (const Tensor<2,3,VectorizedArray<Number> > &jac,
+ const VectorizedArray<Number> *const hessians_quad[6],
+ const unsigned int q_point,
+ VectorizedArray<Number> (&tmp)[3][3])
+ {
+ for (unsigned int d=0; d<3; ++d)
+ {
+ tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
+ jac[d][1] * hessians_quad[3][q_point] +
+ jac[d][2] * hessians_quad[4][q_point]);
+ tmp[1][d] = (jac[d][0] * hessians_quad[3][q_point] +
+ jac[d][1] * hessians_quad[1][q_point] +
+ jac[d][2] * hessians_quad[5][q_point]);
+ tmp[2][d] = (jac[d][0] * hessians_quad[4][q_point] +
+ jac[d][1] * hessians_quad[5][q_point] +
+ jac[d][2] * hessians_quad[2][q_point]);
}
}
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,Tensor<2,dim,VectorizedArray<Number> > >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_hessian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<2,dim,VectorizedArray<Number> > hessian_out [n_components];
// cell with general Jacobian
else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- Assert (this->mapping_info.second_derivatives_initialized == true,
+ Assert (this->mapping_info->second_derivatives_initialized == true,
ExcNotInitialized());
const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_hessian_diagonal (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > hessian_out (false);
// cell with general Jacobian
else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- Assert (this->mapping_info.second_derivatives_initialized == true,
+ Assert (this->mapping_info->second_derivatives_initialized == true,
ExcNotInitialized());
const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_laplacian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,VectorizedArray<Number> > laplacian_out (false);
const Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > hess_diag
= get_hessian_diagonal(q_point);
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::submit_dof_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
const unsigned int dof)
{
#ifdef DEBUG
this->dof_values_initialized = true;
#endif
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
for (unsigned int comp=0; comp<n_components; comp++)
this->values_dofs[comp][dof] = val_in[comp];
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::submit_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->values_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::general)
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::submit_gradient (const Tensor<1,n_components_,
Tensor<1,dim,VectorizedArray<Number> > >grad_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::integrate_value () const
{
#ifdef DEBUG
Tensor<1,n_components_,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; ++comp)
return_value[comp] = this->values_quad[comp][0];
+ const unsigned int n_q_points = this->data->n_q_points;
for (unsigned int q=1; q<n_q_points; ++q)
for (unsigned int comp=0; comp<n_components; ++comp)
return_value[comp] += this->values_quad[comp][q];
/*----------------------- FEEvaluationAccess --------------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationAccess<dim,n_components_,Number>
::FEEvaluationAccess (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points)
:
- FEEvaluationBase <dim,dofs_per_cell_,n_q_points_,n_components_,Number>
- (data_in, fe_no, quad_no_in)
+ FEEvaluationBase <dim,n_components_,Number>
+ (data_in, fe_no, quad_no_in, dofs_per_cell, n_q_points)
+{}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationAccess<dim,n_components_,Number>
+::FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ FEEvaluationBase <dim,n_components_,Number> (geometry, dof_handler, first_selected_component)
+{}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationAccess<dim,n_components_,Number>
+::FEEvaluationAccess (const FEEvaluationAccess<dim,n_components_,Number> &other)
+ :
+ FEEvaluationBase <dim,n_components_,Number>(other)
{}
/*-------------------- FEEvaluationAccess scalar ----------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::FEEvaluationAccess (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points)
+ :
+ FEEvaluationBase <dim,1,Number>
+ (data_in, fe_no, quad_no_in, dofs_per_cell, n_q_points)
+{}
+
+
+
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,1,Number>
+::FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
:
- FEEvaluationBase <dim,dofs_per_cell_,n_q_points_,1,Number>
- (data_in, fe_no, quad_no_in)
+ FEEvaluationBase <dim,1,Number> (geometry, dof_handler, first_selected_component)
{}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,1,Number>
+::FEEvaluationAccess (const FEEvaluationAccess<dim,1,Number>&other)
+ :
+ FEEvaluationBase <dim,1,Number>(other)
+{}
+
+
+
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_dof_value (const unsigned int dof) const
{
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
return this->values_dofs[0][dof];
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_value (const unsigned int q_point) const
{
Assert (this->values_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
return this->values_quad[0][q_point];
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<1,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_gradient (const unsigned int q_point) const
{
// could use the base class gradient, but that involves too many inefficient
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,dim,VectorizedArray<Number> > grad_out (false);
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_hessian (const unsigned int q_point) const
{
return BaseClass::get_hessian(q_point)[0];
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<1,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_hessian_diagonal (const unsigned int q_point) const
{
return BaseClass::get_hessian_diagonal(q_point)[0];
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_laplacian (const unsigned int q_point) const
{
return BaseClass::get_laplacian(q_point)[0];
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::submit_dof_value (const VectorizedArray<Number> val_in,
const unsigned int dof)
{
#ifdef DEBUG
this->dof_values_initialized = true;
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
#endif
this->values_dofs[0][dof] = val_in;
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::submit_value (const VectorizedArray<Number> val_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->values_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::general)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::submit_gradient (const Tensor<1,dim,VectorizedArray<Number> > grad_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::integrate_value () const
{
return BaseClass::integrate_value()[0];
/*----------------- FEEvaluationAccess vector-valued ------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::FEEvaluationAccess (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points)
+ :
+ FEEvaluationBase <dim,dim,Number>
+ (data_in, fe_no, quad_no_in, dofs_per_cell, n_q_points)
+{}
+
+
+
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,dim,Number>
+::FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ FEEvaluationBase <dim,dim,Number> (geometry, dof_handler, first_selected_component)
+{}
+
+
+
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,dim,Number>
+::FEEvaluationAccess (const FEEvaluationAccess<dim,dim,Number>&other)
:
- FEEvaluationBase <dim,dofs_per_cell_,n_q_points_,dim,Number>
- (data_in, fe_no, quad_no_in)
+ FEEvaluationBase <dim,dim,Number>(other)
{}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_gradient (const unsigned int q_point) const
{
return BaseClass::get_gradient (q_point);
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_divergence (const unsigned int q_point) const
{
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
VectorizedArray<Number> divergence;
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
SymmetricTensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_symmetric_gradient (const unsigned int q_point) const
{
// copy from generic function into dim-specialization function
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<1,dim==2?1:dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_curl (const unsigned int q_point) const
{
// copy from generic function into dim-specialization function
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_hessian_diagonal (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
return BaseClass::get_hessian_diagonal (q_point);
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<3,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_hessian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
return BaseClass::get_hessian(q_point);
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_gradient (const Tensor<2,dim,VectorizedArray<Number> > grad_in,
const unsigned int q_point)
{
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_gradient (const Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > >
grad_in,
const unsigned int q_point)
BaseClass::submit_gradient(grad_in, q_point);
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- typename Number>
+
+
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_divergence (const VectorizedArray<Number> div_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_symmetric_gradient(const SymmetricTensor<2,dim,VectorizedArray<Number> >
sym_grad,
const unsigned int q_point)
// that saves some operations
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl,
const unsigned int q_point)
{
const unsigned int fe_no,
const unsigned int quad_no)
:
- BaseClass (data_in, fe_no, quad_no)
+ BaseClass (data_in, fe_no, quad_no, dofs_per_cell, n_q_points)
{
+ set_data_pointers();
+
#ifdef DEBUG
// print error message when the dimensions do not match. Propose a possible
// fix
- if (dofs_per_cell != this->data.dofs_per_cell ||
- n_q_points != this->data.n_q_points)
+ if ((dofs_per_cell != this->data->dofs_per_cell &&
+ internal::MatrixFreeFunctions::DGP_dofs_per_cell<dim,fe_degree>::value !=
+ this->data->dofs_per_cell)
+ ||
+ n_q_points != this->data->n_q_points)
{
std::string message =
"-------------------------------------------------------\n";
// points
unsigned int proposed_dof_comp = numbers::invalid_unsigned_int,
proposed_quad_comp = numbers::invalid_unsigned_int;
- if (dofs_per_cell == this->matrix_info.get_dof_info(fe_no).dofs_per_cell[this->active_fe_index])
+ if (dofs_per_cell == this->data->dofs_per_cell)
proposed_dof_comp = fe_no;
else
- for (unsigned int no=0; no<this->matrix_info.n_components(); ++no)
- if (this->matrix_info.get_dof_info(no).dofs_per_cell[this->active_fe_index]
+ for (unsigned int no=0; no<this->matrix_info->n_components(); ++no)
+ if (this->matrix_info->get_dof_info(no).dofs_per_cell[this->active_fe_index]
== dofs_per_cell)
{
proposed_dof_comp = no;
break;
}
if (n_q_points ==
- this->mapping_info.mapping_data_gen[quad_no].n_q_points[this->active_quad_index])
+ this->mapping_info->mapping_data_gen[quad_no].n_q_points[this->active_quad_index])
proposed_quad_comp = quad_no;
else
- for (unsigned int no=0; no<this->mapping_info.mapping_data_gen.size(); ++no)
- if (this->mapping_info.mapping_data_gen[no].n_q_points[this->active_quad_index]
+ for (unsigned int no=0; no<this->mapping_info->mapping_data_gen.size(); ++no)
+ if (this->mapping_info->mapping_data_gen[no].n_q_points[this->active_quad_index]
== n_q_points)
{
proposed_quad_comp = no;
}
// ok, did not find the numbers specified by the template arguments in
// the given list. Suggest correct template arguments
- const unsigned int proposed_fe_degree = static_cast<unsigned int>(std::pow(1.001*this->data.dofs_per_cell,1./dim))-1;
- const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->data.n_q_points,1./dim));
+ const unsigned int proposed_fe_degree = static_cast<unsigned int>(std::pow(1.001*this->data->dofs_per_cell,1./dim))-1;
+ const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->data->n_q_points,1./dim));
message += "Wrong template arguments:\n";
message += " Did you mean FEEvaluation<dim,";
message += Utilities::int_to_string(proposed_fe_degree) + ",";
correct_pos += " \n";
message += " " + correct_pos;
- Assert (dofs_per_cell == this->data.dofs_per_cell &&
- n_q_points == this->data.n_q_points,
+ Assert (dofs_per_cell == this->data->dofs_per_cell &&
+ n_q_points == this->data->n_q_points,
ExcMessage(message));
}
AssertDimension (n_q_points,
- this->mapping_info.mapping_data_gen[this->quad_no].
+ this->mapping_info->mapping_data_gen[this->quad_no].
n_q_points[this->active_quad_index]);
- AssertDimension (dofs_per_cell * this->n_fe_components,
- this->dof_info.dofs_per_cell[this->active_fe_index]);
+ AssertDimension (this->data->dofs_per_cell * this->n_fe_components,
+ this->dof_info->dofs_per_cell[this->active_fe_index]);
#endif
}
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluationGeneral (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+{
+ set_data_pointers();
+
+ Assert ((dofs_per_cell == this->data->dofs_per_cell ||
+ internal::MatrixFreeFunctions::DGP_dofs_per_cell<dim,fe_degree>::value ==
+ this->data->dofs_per_cell
+ )
+ &&
+ n_q_points == this->data->n_q_points,
+ ExcMessage("Underlying element and template arguments do not match"));
+}
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluationGeneral (const FEEvaluationGeneral &other)
+ :
+ BaseClass (other)
+{
+ set_data_pointers();
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+void
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::set_data_pointers()
+{
+ // set the pointers to the correct position in the data array
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ this->values_dofs[c] = &my_data_array[c*dofs_per_cell];
+ this->values_quad[c] = &my_data_array[n_components*dofs_per_cell+c*n_q_points];
+ for (unsigned int d=0; d<dim; ++d)
+ this->gradients_quad[c][d] = &my_data_array[n_components*(dofs_per_cell+n_q_points)
+ +
+ (c*dim+d)*n_q_points];
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ this->hessians_quad[c][d] = &my_data_array[n_components*((dim+1)*n_q_points+dofs_per_cell)
+ +
+ (c*(dim*dim+dim)+d)*n_q_points];
+ }
+}
+
+
+
namespace internal
{
// evaluates the given shape data in 1d-3d using the tensor product
{
for (int i1=0; i1<n_blocks1; ++i1)
{
- Number xp[mid], xm[mid];
+ Number xp[mid>0?mid:1], xm[mid>0?mid:1];
for (int i=0; i<mid; ++i)
{
if (dof_to_quad == true && type == 1)
// This performs the evaluation of function values, gradients and Hessians
// for tensor-product finite elements. The operation is used for both
// FEEvaluationGeneral and FEEvaluation, which provide different functions
- // apply_values, apply_gradients in the individual coordinate directions
+ // apply_values, apply_gradients in the individual coordinate directions.
+ // use different versions for 1d, 2d, 3d to avoid nasty compiler warnings
template <typename FEEval>
inline
void
do_evaluate (FEEval &fe_eval,
+ VectorizedArray<typename FEEval::number_type>* values_dofs[],
+ VectorizedArray<typename FEEval::number_type>* values_quad[],
+ VectorizedArray<typename FEEval::number_type>* gradients_quad[][1],
+ VectorizedArray<typename FEEval::number_type>* hessians_quad[][1],
const bool evaluate_val,
const bool evaluate_grad,
- const bool evaluate_lapl)
+ const bool evaluate_lapl,
+ internal::int2type<1>)
{
- Assert (fe_eval.cell != numbers::invalid_unsigned_int,
- ExcNotInitialized());
- Assert (fe_eval.dof_values_initialized == true,
- internal::ExcAccessToUninitializedField());
+ const unsigned int n_components = FEEval::n_components;
+
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ if (evaluate_val == true)
+ fe_eval.template apply_values<0,true,false>
+ (values_dofs[c], fe_eval.values_quad[c]);
+ if (evaluate_grad == true)
+ fe_eval.template apply_gradients<0,true,false>
+ (values_dofs[c], fe_eval.gradients_quad[c][0]);
+ if (evaluate_lapl == true)
+ fe_eval.template apply_hessians<0,true,false>
+ (values_dofs[c], fe_eval.hessians_quad[c][0]);
+ }
+ }
+
+ template <typename FEEval>
+ inline
+ void
+ do_evaluate (FEEval &fe_eval,
+ VectorizedArray<typename FEEval::number_type>* values_dofs[],
+ VectorizedArray<typename FEEval::number_type>* values_quad[],
+ VectorizedArray<typename FEEval::number_type>* gradients_quad[][2],
+ VectorizedArray<typename FEEval::number_type>* hessians_quad[][3],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl,
+ internal::int2type<2>)
+ {
const unsigned int temp_size = FEEval::dofs_per_cell > FEEval::n_q_points ?
FEEval::dofs_per_cell : FEEval::n_q_points;
const unsigned int n_components = FEEval::n_components;
- const unsigned int dim = FEEval::dimension;
for (unsigned int c=0; c<n_components; c++)
{
VectorizedArray<typename FEEval::number_type> temp1[temp_size];
VectorizedArray<typename FEEval::number_type> temp2[temp_size];
- switch (dim)
+ // grad x
+ if (evaluate_grad == true)
{
- case 3:
-
- if (evaluate_grad == true)
- {
- // grad x
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.gradients_quad[c][0]);
- }
-
- if (evaluate_lapl == true)
- {
- // grad xz
- if (evaluate_grad == false)
- {
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
- }
- fe_eval.template apply_gradients<2,true,false>
- (temp2, fe_eval.hessians_quad[c][4]);
-
- // grad xy
- fe_eval.template apply_gradients<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.hessians_quad[c][3]);
-
- // grad xx
- fe_eval.template apply_hessians<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.hessians_quad[c][0]);
- }
-
- // grad y
- fe_eval.template apply_values<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- if (evaluate_grad == true)
- {
- fe_eval.template apply_gradients<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.gradients_quad[c][1]);
- }
-
- if (evaluate_lapl == true)
- {
- // grad yz
- if (evaluate_grad == false)
- fe_eval.template apply_gradients<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_gradients<2,true,false>
- (temp2, fe_eval.hessians_quad[c][5]);
-
- // grad yy
- fe_eval.template apply_hessians<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.hessians_quad[c][1]);
- }
-
- // grad z: can use the values applied in x direction stored in temp1
+ fe_eval.template apply_gradients<0,true,false>
+ (values_dofs[c], temp1);
fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
- if (evaluate_grad == true)
- fe_eval.template apply_gradients<2,true,false>
- (temp2, fe_eval.gradients_quad[c][2]);
+ (temp1, gradients_quad[c][0]);
+ }
+ if (evaluate_lapl == true)
+ {
+ // grad xy
+ if (evaluate_grad == false)
+ fe_eval.template apply_gradients<0,true,false>
+ (values_dofs[c], temp1);
+ fe_eval.template apply_gradients<1,true,false>
+ (temp1, hessians_quad[c][2]);
- // grad zz: can use the values applied in x and y direction stored
- // in temp2
- if (evaluate_lapl == true)
- fe_eval.template apply_hessians<2,true,false>
- (temp2, fe_eval.hessians_quad[c][2]);
+ // grad xx
+ fe_eval.template apply_hessians<0,true,false>
+ (values_dofs[c], temp1);
+ fe_eval.template apply_values<1,true,false>
+ (temp1, hessians_quad[c][0]);
+ }
- // val: can use the values applied in x & y direction stored in temp2
- if (evaluate_val == true)
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.values_quad[c]);
+ // grad y
+ fe_eval.template apply_values<0,true,false>
+ (values_dofs[c], temp1);
+ if (evaluate_grad == true)
+ fe_eval.template apply_gradients<1,true,false>
+ (temp1, gradients_quad[c][1]);
+
+ // grad yy
+ if (evaluate_lapl == true)
+ fe_eval.template apply_hessians<1,true,false>
+ (temp1, hessians_quad[c][1]);
+
+ // val: can use values applied in x
+ if (evaluate_val == true)
+ fe_eval.template apply_values<1,true,false>
+ (temp1, values_quad[c]);
+ }
+ }
- break;
+ template <typename FEEval>
+ inline
+ void
+ do_evaluate (FEEval &fe_eval,
+ VectorizedArray<typename FEEval::number_type>* values_dofs[],
+ VectorizedArray<typename FEEval::number_type>* values_quad[],
+ VectorizedArray<typename FEEval::number_type>* gradients_quad[][3],
+ VectorizedArray<typename FEEval::number_type>* hessians_quad[][6],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl,
+ internal::int2type<3>)
+ {
+ const unsigned int temp_size = FEEval::dofs_per_cell > FEEval::n_q_points ?
+ FEEval::dofs_per_cell : FEEval::n_q_points;
+ const unsigned int n_components = FEEval::n_components;
- case 2:
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ VectorizedArray<typename FEEval::number_type> temp1[temp_size];
+ VectorizedArray<typename FEEval::number_type> temp2[temp_size];
+ if (evaluate_grad == true)
+ {
// grad x
- if (evaluate_grad == true)
+ fe_eval.template apply_gradients<0,true,false>
+ (values_dofs[c], temp1);
+ fe_eval.template apply_values<1,true,false>
+ (temp1, temp2);
+ fe_eval.template apply_values<2,true,false>
+ (temp2, gradients_quad[c][0]);
+ }
+
+ if (evaluate_lapl == true)
+ {
+ // grad xz
+ if (evaluate_grad == false)
{
fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
+ (values_dofs[c], temp1);
fe_eval.template apply_values<1,true,false>
- (temp1, fe_eval.gradients_quad[c][0]);
- }
- if (evaluate_lapl == true)
- {
- // grad xy
- if (evaluate_grad == false)
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_gradients<1,true,false>
- (temp1, fe_eval.hessians_quad[c][2]);
-
- // grad xx
- fe_eval.template apply_hessians<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, fe_eval.hessians_quad[c][0]);
+ (temp1, temp2);
}
+ fe_eval.template apply_gradients<2,true,false>
+ (temp2, hessians_quad[c][4]);
+
+ // grad xy
+ fe_eval.template apply_gradients<1,true,false>
+ (temp1, temp2);
+ fe_eval.template apply_values<2,true,false>
+ (temp2, hessians_quad[c][3]);
+
+ // grad xx
+ fe_eval.template apply_hessians<0,true,false>
+ (values_dofs[c], temp1);
+ fe_eval.template apply_values<1,true,false>
+ (temp1, temp2);
+ fe_eval.template apply_values<2,true,false>
+ (temp2, hessians_quad[c][0]);
+ }
- // grad y
- fe_eval.template apply_values<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- if (evaluate_grad == true)
+ // grad y
+ fe_eval.template apply_values<0,true,false>
+ (values_dofs[c], temp1);
+ if (evaluate_grad == true)
+ {
+ fe_eval.template apply_gradients<1,true,false>
+ (temp1, temp2);
+ fe_eval.template apply_values<2,true,false>
+ (temp2, gradients_quad[c][1]);
+ }
+
+ if (evaluate_lapl == true)
+ {
+ // grad yz
+ if (evaluate_grad == false)
fe_eval.template apply_gradients<1,true,false>
- (temp1, fe_eval.gradients_quad[c][1]);
+ (temp1, temp2);
+ fe_eval.template apply_gradients<2,true,false>
+ (temp2, hessians_quad[c][5]);
// grad yy
- if (evaluate_lapl == true)
- fe_eval.template apply_hessians<1,true,false>
- (temp1, fe_eval.hessians_quad[c][1]);
-
- // val: can use values applied in x
- if (evaluate_val == true)
- fe_eval.template apply_values<1,true,false>
- (temp1, fe_eval.values_quad[c]);
-
- break;
-
- case 1:
- if (evaluate_val == true)
- fe_eval.template apply_values<0,true,false>
- (fe_eval.values_dofs[c], fe_eval.values_quad[c]);
- if (evaluate_grad == true)
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], fe_eval.gradients_quad[c][0]);
- if (evaluate_lapl == true)
- fe_eval.template apply_hessians<0,true,false>
- (fe_eval.values_dofs[c], fe_eval.hessians_quad[c][0]);
- break;
-
- default:
- Assert (false, ExcNotImplemented());
+ fe_eval.template apply_hessians<1,true,false>
+ (temp1, temp2);
+ fe_eval.template apply_values<2,true,false>
+ (temp2, hessians_quad[c][1]);
}
- }
-#ifdef DEBUG
- if (evaluate_val == true)
- fe_eval.values_quad_initialized = true;
- if (evaluate_grad == true)
- fe_eval.gradients_quad_initialized = true;
- if (evaluate_lapl == true)
- fe_eval.hessians_quad_initialized = true;
-#endif
+ // grad z: can use the values applied in x direction stored in temp1
+ fe_eval.template apply_values<1,true,false>
+ (temp1, temp2);
+ if (evaluate_grad == true)
+ fe_eval.template apply_gradients<2,true,false>
+ (temp2, gradients_quad[c][2]);
+
+ // grad zz: can use the values applied in x and y direction stored
+ // in temp2
+ if (evaluate_lapl == true)
+ fe_eval.template apply_hessians<2,true,false>
+ (temp2, hessians_quad[c][2]);
+
+ // val: can use the values applied in x & y direction stored in temp2
+ if (evaluate_val == true)
+ fe_eval.template apply_values<2,true,false>
+ (temp2, values_quad[c]);
+ }
}
inline
void
do_integrate (FEEval &fe_eval,
+ VectorizedArray<typename FEEval::number_type>* values_dofs[],
+ VectorizedArray<typename FEEval::number_type>* values_quad[],
+ VectorizedArray<typename FEEval::number_type>* gradients_quad[][1],
const bool integrate_val,
- const bool integrate_grad)
+ const bool integrate_grad,
+ internal::int2type<1>)
{
- Assert (fe_eval.cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- if (integrate_val == true)
- Assert (fe_eval.values_quad_submitted == true,
- ExcAccessToUninitializedField());
- if (integrate_grad == true)
- Assert (fe_eval.gradients_quad_submitted == true,
- ExcAccessToUninitializedField());
+ const unsigned int n_components = FEEval::n_components;
+
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ if (integrate_grad == true)
+ fe_eval.template apply_gradients<0,false,false>
+ (gradients_quad[c][0], fe_eval.values_dofs[c]);
+ if (integrate_val == true)
+ {
+ if (integrate_grad == true)
+ fe_eval.template apply_values<0,false,true>
+ (values_quad[c], values_dofs[c]);
+ else
+ fe_eval.template apply_values<0,false,false>
+ (values_quad[c], values_dofs[c]);
+ }
+ }
+ }
+ template <typename FEEval>
+ inline
+ void
+ do_integrate (FEEval &fe_eval,
+ VectorizedArray<typename FEEval::number_type>* values_dofs[],
+ VectorizedArray<typename FEEval::number_type>* values_quad[],
+ VectorizedArray<typename FEEval::number_type>* gradients_quad[][2],
+ const bool integrate_val,
+ const bool integrate_grad,
+ internal::int2type<2>)
+ {
const unsigned int temp_size = FEEval::dofs_per_cell > FEEval::n_q_points ?
FEEval::dofs_per_cell : FEEval::n_q_points;
const unsigned int n_components = FEEval::n_components;
- const unsigned int dim = FEEval::dimension;
-
for (unsigned int c=0; c<n_components; c++)
{
VectorizedArray<typename FEEval::number_type> temp1[temp_size];
VectorizedArray<typename FEEval::number_type> temp2[temp_size];
- switch (dim)
+ // val
+ if (integrate_val == true)
+ fe_eval.template apply_values<0,false,false>
+ (values_quad[c], temp1);
+ if (integrate_grad == true)
{
- case 3:
-
+ //grad x
if (integrate_val == true)
- {
- // val
- fe_eval.template apply_values<0,false,false>
- (fe_eval.values_quad[c], temp1);
- }
- if (integrate_grad == true)
- {
- // grad x: can sum to temporary value in temp1
- if (integrate_val == true)
- fe_eval.template apply_gradients<0,false,true>
- (fe_eval.gradients_quad[c][0], temp1);
- else
- fe_eval.template apply_gradients<0,false,false>
- (fe_eval.gradients_quad[c][0], temp1);
- }
- if (integrate_val || integrate_grad)
- fe_eval.template apply_values<1,false,false>
- (temp1, temp2);
- if (integrate_grad == true)
- {
- // grad y: can sum to temporary x value in temp2
- fe_eval.template apply_values<0,false,false>
- (fe_eval.gradients_quad[c][1], temp1);
- fe_eval.template apply_gradients<1,false,true>
- (temp1, temp2);
- }
- if (integrate_val || integrate_grad)
- fe_eval.template apply_values<2,false,false>
- (temp2, fe_eval.values_dofs[c]);
- if (integrate_grad == true)
- {
- // grad z: can sum to temporary x and y value in output
- fe_eval.template apply_values<0,false,false>
- (fe_eval.gradients_quad[c][2], temp1);
- fe_eval.template apply_values<1,false,false>
- (temp1, temp2);
- fe_eval.template apply_gradients<2,false,true>
- (temp2, fe_eval.values_dofs[c]);
- }
+ fe_eval.template apply_gradients<0,false,true>
+ (gradients_quad[c][0], temp1);
+ else
+ fe_eval.template apply_gradients<0,false,false>
+ (gradients_quad[c][0], temp1);
+ }
+ if (integrate_val || integrate_grad)
+ fe_eval.template apply_values<1,false,false>
+ (temp1, values_dofs[c]);
+ if (integrate_grad == true)
+ {
+ // grad y
+ fe_eval.template apply_values<0,false,false>
+ (gradients_quad[c][1], temp1);
+ fe_eval.template apply_gradients<1,false,true>
+ (temp1, values_dofs[c]);
+ }
+ }
+ }
- break;
+ template <typename FEEval>
+ inline
+ void
+ do_integrate (FEEval &fe_eval,
+ VectorizedArray<typename FEEval::number_type>* values_dofs[],
+ VectorizedArray<typename FEEval::number_type>* values_quad[],
+ VectorizedArray<typename FEEval::number_type>* gradients_quad[][3],
+ const bool integrate_val,
+ const bool integrate_grad,
+ internal::int2type<3>)
+ {
+ const unsigned int temp_size = FEEval::dofs_per_cell > FEEval::n_q_points ?
+ FEEval::dofs_per_cell : FEEval::n_q_points;
+ const unsigned int n_components = FEEval::n_components;
- case 2:
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ VectorizedArray<typename FEEval::number_type> temp1[temp_size];
+ VectorizedArray<typename FEEval::number_type> temp2[temp_size];
+ if (integrate_val == true)
+ {
// val
+ fe_eval.template apply_values<0,false,false>
+ (values_quad[c], temp1);
+ }
+ if (integrate_grad == true)
+ {
+ // grad x: can sum to temporary value in temp1
if (integrate_val == true)
- fe_eval.template apply_values<0,false,false>
- (fe_eval.values_quad[c], temp1);
- if (integrate_grad == true)
- {
- //grad x
- if (integrate_val == true)
- fe_eval.template apply_gradients<0,false,true>
- (fe_eval.gradients_quad[c][0], temp1);
- else
- fe_eval.template apply_gradients<0,false,false>
- (fe_eval.gradients_quad[c][0], temp1);
- }
- if (integrate_val || integrate_grad)
- fe_eval.template apply_values<1,false,false>
- (temp1, fe_eval.values_dofs[c]);
- if (integrate_grad == true)
- {
- // grad y
- fe_eval.template apply_values<0,false,false>
- (fe_eval.gradients_quad[c][1], temp1);
- fe_eval.template apply_gradients<1,false,true>
- (temp1, fe_eval.values_dofs[c]);
- }
-
- break;
-
- case 1:
-
- if (integrate_grad == true)
+ fe_eval.template apply_gradients<0,false,true>
+ (gradients_quad[c][0], temp1);
+ else
fe_eval.template apply_gradients<0,false,false>
- (fe_eval.gradients_quad[c][0], fe_eval.values_dofs[c]);
- if (integrate_val == true)
- {
- if (integrate_grad == true)
- fe_eval.template apply_values<0,false,true>
- (fe_eval.values_quad[c], fe_eval.values_dofs[c]);
- else
- fe_eval.template apply_values<0,false,false>
- (fe_eval.values_quad[c], fe_eval.values_dofs[c]);
- }
- break;
-
- default:
- Assert (false, ExcNotImplemented());
+ (gradients_quad[c][0], temp1);
+ }
+ if (integrate_val || integrate_grad)
+ fe_eval.template apply_values<1,false,false>
+ (temp1, temp2);
+ if (integrate_grad == true)
+ {
+ // grad y: can sum to temporary x value in temp2
+ fe_eval.template apply_values<0,false,false>
+ (gradients_quad[c][1], temp1);
+ fe_eval.template apply_gradients<1,false,true>
+ (temp1, temp2);
+ }
+ if (integrate_val || integrate_grad)
+ fe_eval.template apply_values<2,false,false>
+ (temp2, values_dofs[c]);
+ if (integrate_grad == true)
+ {
+ // grad z: can sum to temporary x and y value in output
+ fe_eval.template apply_values<0,false,false>
+ (gradients_quad[c][2], temp1);
+ fe_eval.template apply_values<1,false,false>
+ (temp1, temp2);
+ fe_eval.template apply_gradients<2,false,true>
+ (temp2, values_dofs[c]);
}
}
-
-#ifdef DEBUG
- fe_eval.dof_values_initialized = true;
-#endif
}
} // end of namespace internal
const bool evaluate_grad,
const bool evaluate_lapl)
{
- internal::do_evaluate (*this, evaluate_val, evaluate_grad, evaluate_lapl);
+ Assert (this->dof_values_initialized == true,
+ internal::ExcAccessToUninitializedField());
+ internal::do_evaluate (*this, this->values_dofs, this->values_quad,
+ this->gradients_quad, this->hessians_quad,
+ evaluate_val, evaluate_grad, evaluate_lapl,
+ internal::int2type<dim>());
+
+#ifdef DEBUG
+ if (evaluate_val == true)
+ this->values_quad_initialized = true;
+ if (evaluate_grad == true)
+ this->gradients_quad_initialized = true;
+ if (evaluate_lapl == true)
+ this->hessians_quad_initialized = true;
+#endif
}
::integrate (const bool integrate_val,
const bool integrate_grad)
{
- internal::do_integrate (*this, integrate_val, integrate_grad);
+ if (integrate_val == true)
+ Assert (this->values_quad_submitted == true,
+ internal::ExcAccessToUninitializedField());
+ if (integrate_grad == true)
+ Assert (this->gradients_quad_submitted == true,
+ internal::ExcAccessToUninitializedField());
+
+ internal::do_integrate (*this, this->values_dofs, this->values_quad,
+ this->gradients_quad, integrate_val, integrate_grad,
+ internal::int2type<dim>());
+
+#ifdef DEBUG
+ this->dof_values_initialized = true;
+#endif
}
FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
::quadrature_point (const unsigned int q) const
{
- Assert (this->mapping_info.quadrature_points_initialized == true,
+ Assert (this->mapping_info->quadrature_points_initialized == true,
ExcNotInitialized());
AssertIndexRange (q, n_q_points);
{
internal::apply_tensor_product<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_values.begin(), in, out);
+ (this->data->shape_values.begin(), in, out);
}
{
internal::apply_tensor_product<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_gradients.begin(), in, out);
+ (this->data->shape_gradients.begin(), in, out);
}
{
internal::apply_tensor_product<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_hessians.begin(), in, out);
+ (this->data->shape_hessians.begin(), in, out);
}
const unsigned int quad_no)
:
BaseClass (data_in, fe_no, quad_no)
+{
+ compute_even_odd_factors();
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluation (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+{
+ compute_even_odd_factors();
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluation (const FEEvaluation &other)
+ :
+ BaseClass (other)
+{
+ compute_even_odd_factors();
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+void
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::compute_even_odd_factors()
{
// check whether element is appropriate
#ifdef DEBUG
const unsigned int n_dofs_1d = fe_degree + 1;
for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
for (unsigned int j=0; j<n_q_points_1d; ++j)
- Assert (std::fabs(this->data.shape_values[i*n_q_points_1d+j][0] -
- this->data.shape_values[(n_dofs_1d-i)*n_q_points_1d
+ Assert (std::fabs(this->data->shape_values[i*n_q_points_1d+j][0] -
+ this->data->shape_values[(n_dofs_1d-i)*n_q_points_1d
-j-1][0]) < zero_tol,
ExcMessage(error_message));
if (n_q_points_1d%2 == 1 && n_dofs_1d%2 == 1)
{
for (int i=0; i<static_cast<int>(n_dofs_1d/2); ++i)
- Assert (std::fabs(this->data.shape_values[i*n_q_points_1d+
+ Assert (std::fabs(this->data->shape_values[i*n_q_points_1d+
n_q_points_1d/2][0]) < zero_tol,
ExcMessage(error_message));
- Assert (std::fabs(this->data.shape_values[(n_dofs_1d/2)*n_q_points_1d+
+ Assert (std::fabs(this->data->shape_values[(n_dofs_1d/2)*n_q_points_1d+
n_q_points_1d/2][0]-1.)< zero_tol,
ExcMessage(error_message));
}
// quadrature point
for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
for (unsigned int j=0; j<n_q_points_1d; ++j)
- Assert (std::fabs(this->data.shape_gradients[i*n_q_points_1d+j][0] +
- this->data.shape_gradients[(n_dofs_1d-i)*n_q_points_1d-
+ Assert (std::fabs(this->data->shape_gradients[i*n_q_points_1d+j][0] +
+ this->data->shape_gradients[(n_dofs_1d-i)*n_q_points_1d-
j-1][0]) < zero_tol,
ExcMessage(error_message));
if (n_dofs_1d%2 == 1 && n_q_points_1d%2 == 1)
- Assert (std::fabs(this->data.shape_gradients[(n_dofs_1d/2)*n_q_points_1d+
+ Assert (std::fabs(this->data->shape_gradients[(n_dofs_1d/2)*n_q_points_1d+
(n_q_points_1d/2)][0]) < zero_tol,
ExcMessage(error_message));
// symmetry for Laplacian
for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
for (unsigned int j=0; j<n_q_points_1d; ++j)
- Assert (std::fabs(this->data.shape_hessians[i*n_q_points_1d+j][0] -
- this->data.shape_hessians[(n_dofs_1d-i)*n_q_points_1d-
+ Assert (std::fabs(this->data->shape_hessians[i*n_q_points_1d+j][0] -
+ this->data->shape_hessians[(n_dofs_1d-i)*n_q_points_1d-
j-1][0]) < zero_tol,
ExcMessage(error_message));
#endif
// Compute symmetric and skew-symmetric part of shape values for even-odd
// decomposition
- for (unsigned int i=0; i<(fe_degree+1)/2; ++i)
+ for (int i=0; i<(fe_degree+1)/2; ++i)
for (unsigned int q=0; q<(n_q_points_1d+1)/2; ++q)
{
shape_val_evenodd[i][q] =
- 0.5 * (this->data.shape_values[i*n_q_points_1d+q] +
- this->data.shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
+ 0.5 * (this->data->shape_values[i*n_q_points_1d+q] +
+ this->data->shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
shape_val_evenodd[fe_degree-i][q] =
- 0.5 * (this->data.shape_values[i*n_q_points_1d+q] -
- this->data.shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
+ 0.5 * (this->data->shape_values[i*n_q_points_1d+q] -
+ this->data->shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
shape_gra_evenodd[i][q] =
- 0.5 * (this->data.shape_gradients[i*n_q_points_1d+q] +
- this->data.shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
+ 0.5 * (this->data->shape_gradients[i*n_q_points_1d+q] +
+ this->data->shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
shape_gra_evenodd[fe_degree-i][q] =
- 0.5 * (this->data.shape_gradients[i*n_q_points_1d+q] -
- this->data.shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
+ 0.5 * (this->data->shape_gradients[i*n_q_points_1d+q] -
+ this->data->shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
shape_hes_evenodd[i][q] =
- 0.5 * (this->data.shape_hessians[i*n_q_points_1d+q] +
- this->data.shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
+ 0.5 * (this->data->shape_hessians[i*n_q_points_1d+q] +
+ this->data->shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
shape_hes_evenodd[fe_degree-i][q] =
- 0.5 * (this->data.shape_hessians[i*n_q_points_1d+q] -
- this->data.shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
+ 0.5 * (this->data->shape_hessians[i*n_q_points_1d+q] -
+ this->data->shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
}
if (fe_degree % 2 == 0)
for (unsigned int q=0; q<(n_q_points_1d+1)/2; ++q)
{
shape_val_evenodd[fe_degree/2][q] =
- this->data.shape_values[(fe_degree/2)*n_q_points_1d+q];
+ this->data->shape_values[(fe_degree/2)*n_q_points_1d+q];
shape_gra_evenodd[fe_degree/2][q] =
- this->data.shape_gradients[(fe_degree/2)*n_q_points_1d+q];
+ this->data->shape_gradients[(fe_degree/2)*n_q_points_1d+q];
shape_hes_evenodd[fe_degree/2][q] =
- this->data.shape_hessians[(fe_degree/2)*n_q_points_1d+q];
+ this->data->shape_hessians[(fe_degree/2)*n_q_points_1d+q];
}
}
const bool evaluate_grad,
const bool evaluate_lapl)
{
- internal::do_evaluate (*this, evaluate_val, evaluate_grad, evaluate_lapl);
+ Assert (this->dof_values_initialized == true,
+ internal::ExcAccessToUninitializedField());
+ internal::do_evaluate (*this, this->values_dofs, this->values_quad,
+ this->gradients_quad, this->hessians_quad,
+ evaluate_val, evaluate_grad, evaluate_lapl,
+ internal::int2type<dim>());
+
+#ifdef DEBUG
+ if (evaluate_val == true)
+ this->values_quad_initialized = true;
+ if (evaluate_grad == true)
+ this->gradients_quad_initialized = true;
+ if (evaluate_lapl == true)
+ this->hessians_quad_initialized = true;
+#endif
}
FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
::integrate (bool integrate_val,bool integrate_grad)
{
- internal::do_integrate (*this, integrate_val, integrate_grad);
+ if (integrate_val == true)
+ Assert (this->values_quad_submitted == true,
+ internal::ExcAccessToUninitializedField());
+ if (integrate_grad == true)
+ Assert (this->gradients_quad_submitted == true,
+ internal::ExcAccessToUninitializedField());
+
+ internal::do_integrate (*this, this->values_dofs, this->values_quad,
+ this->gradients_quad, integrate_val, integrate_grad,
+ internal::int2type<dim>());
+
+#ifdef DEBUG
+ this->dof_values_initialized = true;
+#endif
}
if (fe_degree > 1 || n_q_points_1d > 3)
internal::apply_tensor_product_evenodd<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add, 0>
- (shape_val_evenodd, in, out);
+ (&shape_val_evenodd[0], in, out);
else
internal::apply_tensor_product_values<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_values.begin(), in, out);
+ (this->data->shape_values.begin(), in, out);
}
if (fe_degree > 1 || n_q_points_1d > 3)
internal::apply_tensor_product_evenodd<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add, 1>
- (shape_gra_evenodd, in, out);
+ (&shape_gra_evenodd[0], in, out);
else
internal::apply_tensor_product_gradients<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_gradients.begin(), in, out);
+ (this->data->shape_gradients.begin(), in, out);
}
if (fe_degree > 1 || n_q_points_1d > 3)
internal::apply_tensor_product_evenodd<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add, 2>
- (shape_hes_evenodd, in, out);
+ (&shape_hes_evenodd[0], in, out);
else
internal::apply_tensor_product_hessians<dim,fe_degree,n_q_points_1d,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_hessians.begin(), in, out);
+ (this->data->shape_hessians.begin(), in, out);
}
for (unsigned int j=0; j<n_points_1d; ++j)
if (i!=j)
{
- Assert (std::fabs(this->data.shape_values[i*n_points_1d+j][0])<zero_tol,
+ Assert (std::fabs(this->data->shape_values[i*n_points_1d+j][0])<zero_tol,
ExcMessage (error_mess.c_str()));
}
else
{
- Assert (std::fabs(this->data.shape_values[i*n_points_1d+
+ Assert (std::fabs(this->data->shape_values[i*n_points_1d+
j][0]-1.)<zero_tol,
ExcMessage (error_mess.c_str()));
}
for (unsigned int i=1; i<n_points_1d-1; ++i)
- Assert (std::fabs(this->data.shape_gradients[i*n_points_1d+i][0])<zero_tol,
+ Assert (std::fabs(this->data->shape_gradients[i*n_points_1d+i][0])<zero_tol,
ExcMessage (error_mess.c_str()));
- Assert (std::fabs(this->data.shape_gradients[n_points_1d-1][0]-
+ Assert (std::fabs(this->data->shape_gradients[n_points_1d-1][0]-
(n_points_1d%2==0 ? -1. : 1.)) < zero_tol,
ExcMessage (error_mess.c_str()));
#endif
+template <int dim, int fe_degree, int n_components_, typename Number>
+inline
+FEEvaluationGL<dim,fe_degree,n_components_,Number>
+::FEEvaluationGL (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+{}
+
+
+
+template <int dim, int fe_degree, int n_components_, typename Number>
+inline
+FEEvaluationGL<dim,fe_degree,n_components_,Number>
+::FEEvaluationGL (const FEEvaluationGL &other)
+ :
+ BaseClass (other)
+{}
+
+
+
template <int dim, int fe_degree, int n_components_, typename Number>
inline
void
{
internal::apply_tensor_product_gradients_gl<dim,fe_degree,
VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_gradients.begin(), in, out);
+ (this->data->shape_gradients.begin(), in, out);
+}
+
+
+
+/*------------------------- FEEvaluationDGP ---------------------------------*/
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluationDGP<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluationDGP (const MatrixFree<dim,Number> &data_in,
+ const unsigned int fe_no,
+ const unsigned int quad_no)
+ :
+ BaseClass (data_in, fe_no, quad_no)
+{
+ // reset values_dofs pointer as it has wider gaps in the base class
+ for (unsigned int c=0; c<n_components_; ++c)
+ this->values_dofs[c] = &this->my_data_array[c*dofs_per_cell];
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluationDGP<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluationDGP (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+{
+ for (unsigned int c=0; c<n_components_; ++c)
+ this->values_dofs[c] = &this->my_data_array[c*dofs_per_cell];
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+FEEvaluationDGP<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::FEEvaluationDGP (const FEEvaluationDGP &other)
+ :
+ BaseClass (other)
+{
+ for (unsigned int c=0; c<n_components_; ++c)
+ this->values_dofs[c] = &this->my_data_array[c*dofs_per_cell];
+}
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+void
+FEEvaluationDGP<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::evaluate (const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl)
+{
+ Assert (this->dof_values_initialized == true,
+ internal::ExcAccessToUninitializedField());
+
+ // expand dof_values to tensor product
+ VectorizedArray<Number> data_array[n_components*BaseClass::dofs_per_cell];
+ VectorizedArray<Number> *expanded_dof_values[n_components];
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c] = &data_array[c*BaseClass::dofs_per_cell];
+
+ unsigned int count_p = 0, count_q = 0;
+ for (unsigned int i=0; i<(dim>2?fe_degree+1:1); ++i)
+ {
+ for (unsigned int j=0; j<(dim>1?fe_degree+1-i:1); ++j)
+ {
+ for (unsigned int k=0; k<fe_degree+1-j-i; ++k, ++count_p, ++count_q)
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c][count_q] = this->values_dofs[c][count_p];
+ for (unsigned int k=fe_degree+1-j-i; k<fe_degree+1; ++k, ++count_q)
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c][count_q] = VectorizedArray<Number>();
+ }
+ for (unsigned int j=fe_degree+1-i; j<fe_degree+1; ++j)
+ for (unsigned int k=0; k<fe_degree+1; ++k, ++count_q)
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c][count_q] = VectorizedArray<Number>();
+ }
+ AssertDimension(count_q, BaseClass::dofs_per_cell);
+ AssertDimension(count_p, dofs_per_cell);
+
+ internal::do_evaluate (*this, expanded_dof_values, this->values_quad,
+ this->gradients_quad, this->hessians_quad,
+ evaluate_val, evaluate_grad, evaluate_lapl,
+ internal::int2type<dim>());
+
+#ifdef DEBUG
+ if (evaluate_val == true)
+ this->values_quad_initialized = true;
+ if (evaluate_grad == true)
+ this->gradients_quad_initialized = true;
+ if (evaluate_lapl == true)
+ this->hessians_quad_initialized = true;
+#endif
}
+
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
+inline
+void
+FEEvaluationDGP<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::integrate (bool integrate_val,bool integrate_grad)
+{
+ if (integrate_val == true)
+ Assert (this->values_quad_submitted == true,
+ internal::ExcAccessToUninitializedField());
+ if (integrate_grad == true)
+ Assert (this->gradients_quad_submitted == true,
+ internal::ExcAccessToUninitializedField());
+
+ VectorizedArray<Number> data_array[n_components*BaseClass::dofs_per_cell];
+ VectorizedArray<Number> *expanded_dof_values[n_components];
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c] = &data_array[c*BaseClass::dofs_per_cell];
+ internal::do_integrate (*this, expanded_dof_values, this->values_quad,
+ this->gradients_quad, integrate_val, integrate_grad,
+ internal::int2type<dim>());
+
+ // truncate tensor product
+ unsigned int count_p = 0, count_q = 0;
+ for (unsigned int i=0; i<(dim>2?fe_degree+1:1); ++i)
+ {
+ for (unsigned int j=0; j<(dim>1?fe_degree+1-i:1); ++j)
+ {
+ for (unsigned int k=0; k<fe_degree+1-j-i; ++k, ++count_p, ++count_q)
+ {
+ for (unsigned int c=0; c<n_components; ++c)
+ this->values_dofs[c][count_p] = expanded_dof_values[c][count_q];
+ }
+ count_q += j+i;
+ }
+ count_q += i*(fe_degree+1);
+ }
+ AssertDimension(count_q, BaseClass::dofs_per_cell);
+ AssertDimension(count_p, dofs_per_cell);
+
+#ifdef DEBUG
+ this->dof_values_initialized = true;
+#endif
+}
+
+
+
#endif // ifndef DOXYGEN
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef __deal2__matrix_free_mapping_fe_evaluation_h
+#define __deal2__matrix_free_mapping_fe_evaluation_h
+
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/subscriptor.h>
+#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
+#include <deal.II/matrix_free/shape_info.h>
+#include <deal.II/matrix_free/mapping_info.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/fe_nothing.h>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * This class provides evaluated mapping information using standard deal.II
+ * information in a form that FEEvaluation and friends can use for vectorized
+ * access. Since no vectorization over cells is available with the
+ * DoFHandler/Triangulation cell iterators, the interface to FEEvaluation's
+ * vectorization model is to use @p VectorizedArray::n_array_element copies of
+ * the same element. This interface is thus primarily useful for evaluating
+ * several operators on the same cell, e.g., when assembling cell matrices.
+ *
+ * As opposed to the standard Mapping classes in deal.II, this class does not
+ * actually provide a boundary description that can be used to evaluate the
+ * geometry, but it rather provides the evaluated geometry from a given
+ * deal.II mapping (as passed to the constructor of this class) in a form
+ * accessible to FEEvaluation.
+ *
+ * @author Martin Kronbichler, 2014
+ */
+template <int dim, typename Number=double>
+class MappingFEEvaluation : public Subscriptor
+{
+public:
+ /**
+ * Constructor, similar to FEValues. Since this class only evaluates the
+ * geometry, no finite element has to be specified and the simplest element,
+ * FE_Nothing, is used internally for the underlying FEValues object.
+ */
+ MappingFEEvaluation (const Mapping<dim> &mapping,
+ const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags);
+
+ /**
+ * Constructor. Instead of providing a mapping, use MappingQ1.
+ */
+ MappingFEEvaluation (const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags);
+
+ /**
+ * Initialize with the given cell iterator. This works for all type of
+ * iterators that can be converted into a Triangulation::cell_iterator
+ * (DoFHandler::cell_iterator or Triangulation::cell_iterator).
+ */
+ template <typename ITERATOR>
+ void reinit(ITERATOR cell);
+
+ /**
+ * Return a triangulation iterator to the current cell.
+ */
+ typename Triangulation<dim>::cell_iterator get_cell () const;
+
+ /**
+ * Return a reference to the underlying FEValues object that evaluates
+ * certain quantities (only mapping-related ones like Jacobians or mapped
+ * quadrature points are accessible, as no finite element data is actually
+ * used).
+ */
+ const FEValues<dim>& get_fe_values () const;
+
+ /**
+ * Return a vector of inverse transpose Jacobians. For compatibility with
+ * FEEvaluation, it returns tensors of vectorized arrays, even though all
+ * components are equal.
+ */
+ const AlignedVector<Tensor<2,dim,VectorizedArray<Number> > >&
+ get_inverse_jacobians() const;
+
+ /**
+ * Return a vector of quadrature weights times the Jacobian determinant
+ * (JxW). For compatibility with FEEvaluation, it returns tensors of
+ * vectorized arrays, even though all components are equal.
+ */
+ const AlignedVector<VectorizedArray<Number> >&
+ get_JxW_values() const;
+
+ /**
+ * Return a vector of quadrature points in real space on the given
+ * cell. For compatibility with FEEvaluation, it returns tensors of
+ * vectorized arrays, even though all components are equal.
+ */
+ const AlignedVector<Point<dim,VectorizedArray<Number> > >&
+ get_quadrature_points() const;
+
+ /**
+ * Return a vector of quadrature points in real space on the given
+ * cell. For compatibility with FEEvaluation, it returns tensors of
+ * vectorized arrays, even though all components are equal.
+ */
+ const AlignedVector<Tensor<1,dim,VectorizedArray<Number> > >&
+ get_normal_vectors() const;
+
+ /**
+ * Return a reference to 1D quadrature underlying this object.
+ */
+ const Quadrature<1>&
+ get_quadrature () const;
+
+private:
+ /**
+ * Dummy finite element object necessary for initializing the FEValues
+ * object.
+ */
+ FE_Nothing<dim> fe_dummy;
+
+ /**
+ * An underlying FEValues object that performs the (scalar) evaluation.
+ */
+ FEValues<dim> fe_values;
+
+ /**
+ * Get 1D quadrature formula to be used for reinitializing shape info.
+ */
+ const Quadrature<1> quadrature_1d;
+
+ /**
+ * Inverse Jacobians, stored in vectorized array form.
+ */
+ AlignedVector<Tensor<2,dim,VectorizedArray<Number> > > inverse_jacobians;
+
+ /**
+ * Stored Jacobian determinants and quadrature weights
+ */
+ AlignedVector<VectorizedArray<Number> > jxw_values;
+
+ /**
+ * Stored quadrature points
+ */
+ AlignedVector<Point<dim,VectorizedArray<Number> > > quadrature_points;
+
+ /**
+ * Stored normal vectors (for face integration)
+ */
+ AlignedVector<Tensor<1,dim,VectorizedArray<Number> > > normal_vectors;
+};
+
+
+/*----------------------- Inline functions ----------------------------------*/
+
+template <int dim, typename Number>
+inline
+MappingFEEvaluation<dim,Number>::MappingFEEvaluation (const Mapping<dim> &mapping,
+ const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags)
+ :
+ fe_values(mapping, fe_dummy, Quadrature<dim>(quadrature),
+ internal::MatrixFreeFunctions::MappingInfo<dim,Number>::compute_update_flags(update_flags)),
+ quadrature_1d(quadrature),
+ inverse_jacobians(fe_values.get_quadrature().size()),
+ jxw_values(fe_values.get_quadrature().size()),
+ quadrature_points(fe_values.get_quadrature().size()),
+ normal_vectors(fe_values.get_quadrature().size())
+{
+ Assert(!(fe_values.get_update_flags() & update_jacobian_grads),
+ ExcNotImplemented());
+}
+
+
+
+template <int dim, typename Number>
+inline
+MappingFEEvaluation<dim,Number>::MappingFEEvaluation (const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags)
+ :
+ fe_values(fe_dummy, Quadrature<dim>(quadrature),
+ internal::MatrixFreeFunctions::MappingInfo<dim,Number>::compute_update_flags(update_flags)),
+ quadrature_1d(quadrature),
+ inverse_jacobians(fe_values.get_quadrature().size()),
+ jxw_values(fe_values.get_quadrature().size()),
+ quadrature_points(fe_values.get_quadrature().size()),
+ normal_vectors(fe_values.get_quadrature().size())
+{
+ Assert(!(fe_values.get_update_flags() & update_jacobian_grads),
+ ExcNotImplemented());
+}
+
+
+
+template <int dim, typename Number>
+template <typename ITERATOR>
+inline
+void
+MappingFEEvaluation<dim,Number>::reinit(ITERATOR cell)
+{
+ fe_values.reinit(static_cast<typename Triangulation<dim>::cell_iterator>(cell));
+ for (unsigned int q=0; q<fe_values.get_quadrature().size(); ++q)
+ {
+ if (fe_values.get_update_flags() & update_inverse_jacobians)
+ for (unsigned int d=0; d<dim; ++d)
+ for (unsigned int e=0; e<dim; ++e)
+ inverse_jacobians[q][d][e] = fe_values.inverse_jacobian(q)[e][d];
+ if (fe_values.get_update_flags() & update_quadrature_points)
+ for (unsigned int d=0; d<dim; ++d)
+ quadrature_points[q][d] = fe_values.quadrature_point(q)[d];
+ if (fe_values.get_update_flags() & update_normal_vectors)
+ for (unsigned int d=0; d<dim; ++d)
+ normal_vectors[q][d] = fe_values.normal_vector(q)[d];
+ if (fe_values.get_update_flags() & update_JxW_values)
+ jxw_values[q] = fe_values.JxW(q);
+ }
+}
+
+
+
+template <int dim, typename Number>
+inline
+typename Triangulation<dim>::cell_iterator
+MappingFEEvaluation<dim,Number>::get_cell() const
+{
+ return fe_values.get_cell();
+}
+
+
+
+template <int dim, typename Number>
+inline
+const FEValues<dim>&
+MappingFEEvaluation<dim,Number>::get_fe_values() const
+{
+ return fe_values;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<Tensor<2,dim,VectorizedArray<Number> > >&
+MappingFEEvaluation<dim,Number>::get_inverse_jacobians() const
+{
+ return inverse_jacobians;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<Tensor<1,dim,VectorizedArray<Number> > >&
+MappingFEEvaluation<dim,Number>::get_normal_vectors() const
+{
+ return normal_vectors;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<Point<dim,VectorizedArray<Number> > >&
+MappingFEEvaluation<dim,Number>::get_quadrature_points() const
+{
+ return quadrature_points;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<VectorizedArray<Number> >&
+MappingFEEvaluation<dim,Number>::get_JxW_values() const
+{
+ return jxw_values;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const Quadrature<1>&
+MappingFEEvaluation<dim,Number>::get_quadrature() const
+{
+ return quadrature_1d;
+}
+
+
+#ifndef DOXYGEN
+
+
+#endif // ifndef DOXYGEN
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/exceptions.h>
#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
#include <deal.II/hp/q_collection.h>
#include <deal.II/fe/fe.h>
#include <deal.II/fe/mapping.h>
* Helper function to determine which update flags must be set in the
* internal functions to initialize all data as requested by the user.
*/
- UpdateFlags
+ static UpdateFlags
compute_update_flags (const UpdateFlags update_flags,
- const std::vector<dealii::hp::QCollection<1> > &quad) const;
+ const std::vector<dealii::hp::QCollection<1> > &quad =
+ std::vector<dealii::hp::QCollection<1> >());
/**
* Returns the type of a given cell as detected during initialization.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
UpdateFlags
MappingInfo<dim,Number>::
compute_update_flags (const UpdateFlags update_flags,
- const std::vector<dealii::hp::QCollection<1> > &quad) const
+ const std::vector<dealii::hp::QCollection<1> > &quad)
{
// this class is build around the evaluation this class is build around
// the evaluation of inverse gradients, so compute them in any case
// one quadrature point on the first component, but more points on later
// components, we need to have Jacobian gradients anyway in order to
// determine whether the Jacobian is constant throughout a cell
- bool formula_with_one_point = false;
- for (unsigned int i=0; i<quad[0].size(); ++i)
- if (quad[0][i].size() == 1)
- {
- formula_with_one_point = true;
- break;
- }
- if (formula_with_one_point == true)
- for (unsigned int comp=1; comp<quad.size(); ++comp)
- for (unsigned int i=0; i<quad[comp].size(); ++i)
- if (quad[comp][i].size() > 1)
+ if (quad.empty() == false)
+ {
+ bool formula_with_one_point = false;
+ for (unsigned int i=0; i<quad[0].size(); ++i)
+ if (quad[0][i].size() == 1)
{
- new_flags |= update_jacobian_grads;
- goto end_set;
+ formula_with_one_point = true;
+ break;
}
-end_set:
+ if (formula_with_one_point == true)
+ for (unsigned int comp=1; comp<quad.size(); ++comp)
+ for (unsigned int i=0; i<quad[comp].size(); ++i)
+ if (quad[comp][i].size() > 1)
+ {
+ new_flags |= update_jacobian_grads;
+ }
+ }
return new_flags;
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
const std::vector<hp::QCollection<1> > &quad,
const typename MatrixFree<dim,Number>::AdditionalData additional_data)
{
+
+ // Reads out the FE information and stores the shape function values,
+ // gradients and Hessians for quadrature points.
+ {
+ const unsigned int n_fe = dof_handler.size();
+ const unsigned int n_quad = quad.size();
+ shape_info.reinit (TableIndices<4>(n_fe, n_quad, 1, 1));
+ for (unsigned int no=0; no<n_fe; no++)
+ for (unsigned int nq =0; nq<n_quad; nq++)
+ {
+ AssertDimension (quad[nq].size(), 1);
+ shape_info(no,nq,0,0).reinit(quad[nq][0], dof_handler[no]->get_fe());
+ }
+ }
+
if (additional_data.initialize_indices == true)
{
clear();
}
}
- // Reads out the FE information and stores the shape function values,
- // gradients and Hessians for quadrature points.
- const unsigned int n_fe = dof_handler.size();
- const unsigned int n_quad = quad.size();
- shape_info.reinit (TableIndices<4>(n_fe, n_quad, 1, 1));
- for (unsigned int no=0; no<n_fe; no++)
- {
- const FiniteElement<dim> &fe = dof_handler[no]->get_fe();
- for (unsigned int nq =0; nq<n_quad; nq++)
- {
- AssertDimension (quad[nq].size(), 1);
- shape_info(no,nq,0,0).reinit(quad[nq][0], fe.base_element(0));
- }
- }
-
// Evaluates transformations from unit to real cell, Jacobian determinants,
// quadrature points in real space, based on the ordering of the cells
// determined in @p extract_local_to_global_indices. The algorithm assumes
const std::vector<hp::QCollection<1> > &quad,
const typename MatrixFree<dim,Number>::AdditionalData additional_data)
{
+ // Reads out the FE information and stores the shape function values,
+ // gradients and Hessians for quadrature points.
+ {
+ const unsigned int n_components = dof_handler.size();
+ const unsigned int n_quad = quad.size();
+ unsigned int n_fe_in_collection = 0;
+ for (unsigned int i=0; i<n_components; ++i)
+ n_fe_in_collection = std::max (n_fe_in_collection,
+ dof_handler[i]->get_fe().size());
+ unsigned int n_quad_in_collection = 0;
+ for (unsigned int q=0; q<n_quad; ++q)
+ n_quad_in_collection = std::max (n_quad_in_collection, quad[q].size());
+ shape_info.reinit (TableIndices<4>(n_components, n_quad,
+ n_fe_in_collection,
+ n_quad_in_collection));
+ for (unsigned int no=0; no<n_components; no++)
+ for (unsigned int fe_no=0; fe_no<dof_handler[no]->get_fe().size(); ++fe_no)
+ for (unsigned int nq =0; nq<n_quad; nq++)
+ for (unsigned int q_no=0; q_no<quad[nq].size(); ++q_no)
+ shape_info(no,nq,fe_no,q_no).reinit (quad[nq][q_no],
+ dof_handler[no]->get_fe()[fe_no]);
+ }
+
if (additional_data.initialize_indices == true)
{
clear();
}
}
- // Reads out the FE information and stores the shape function values,
- // gradients and Hessians for quadrature points.
- const unsigned int n_components = dof_handler.size();
- const unsigned int n_quad = quad.size();
- unsigned int n_fe_in_collection = 0;
- for (unsigned int i=0; i<n_components; ++i)
- n_fe_in_collection = std::max (n_fe_in_collection,
- dof_handler[i]->get_fe().size());
- unsigned int n_quad_in_collection = 0;
- for (unsigned int q=0; q<n_quad; ++q)
- n_quad_in_collection = std::max (n_quad_in_collection, quad[q].size());
- shape_info.reinit (TableIndices<4>(n_components, n_quad,
- n_fe_in_collection,
- n_quad_in_collection));
- for (unsigned int no=0; no<n_components; no++)
- for (unsigned int fe_no=0; fe_no<dof_handler[no]->get_fe().size(); ++fe_no)
- {
- const FiniteElement<dim> &fe = dof_handler[no]->get_fe()[fe_no];
- for (unsigned int nq =0; nq<n_quad; nq++)
- for (unsigned int q_no=0; q_no<quad[nq].size(); ++q_no)
- shape_info(no,nq,fe_no,q_no).reinit (quad[nq][q_no],
- fe.base_element(0));
- }
-
// Evaluates transformations from unit to real cell, Jacobian determinants,
// quadrature points in real space, based on the ordering of the cells
// determined in @p extract_local_to_global_indices.
template <int dim, typename Number>
void MatrixFree<dim,Number>::initialize_indices
(const std::vector<const ConstraintMatrix *> &constraint,
- const std::vector<IndexSet> &locally_owned_set)
+ const std::vector<IndexSet> &locally_owned_set)
{
const unsigned int n_fe = dof_handlers.n_dof_handlers;
const unsigned int n_active_cells = cell_level_index.size();
fes.back()->dofs_per_cell);
}
- lexicographic_inv[no].resize (fes.size());
for (unsigned int fe_index = 0; fe_index<fes.size(); ++fe_index)
{
const FiniteElement<dim> &fe = *fes[fe_index];
Assert (fe.n_base_elements() == 1,
- ExcMessage ("MatrixFree only works for DoFHandler with one base element"));
+ ExcMessage ("MatrixFree currently only works for DoFHandler with one base element"));
const unsigned int n_fe_components = fe.element_multiplicity (0);
// cache number of finite elements and dofs_per_cell
dof_info[no].dimension = dim;
dof_info[no].n_components = n_fe_components;
- // get permutation that gives lexicographic renumbering of the cell
- // dofs renumber (this is necessary for FE_Q, for example, since
- // there the vertex DoFs come first, which is incompatible with the
- // lexicographic ordering necessary to apply tensor products
- // efficiently)
- const FE_Poly<TensorProductPolynomials<dim>,dim,dim> *fe_poly =
- dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>
- (&fe.base_element(0));
- const FE_Poly<TensorProductPolynomials<dim,Polynomials::
- PiecewisePolynomial<double> >,dim,dim> *fe_poly_piece =
- dynamic_cast<const FE_Poly<TensorProductPolynomials<dim,
- Polynomials::PiecewisePolynomial<double> >,dim,dim>*>
- (&fe.base_element(0));
-
- // This class currently only works for elements derived from
- // FE_Poly<TensorProductPolynomials<dim>,dim,dim> or piecewise
- // polynomials. For any other element, the dynamic casts above will
- // fail and give fe_poly == 0.
- Assert (fe_poly != 0 || fe_poly_piece != 0, ExcNotImplemented());
- if (n_fe_components == 1)
- {
- if (fe_poly != 0)
- lexicographic_inv[no][fe_index] =
- fe_poly->get_poly_space_numbering_inverse();
- else
- lexicographic_inv[no][fe_index] =
- fe_poly_piece->get_poly_space_numbering_inverse();
- AssertDimension (lexicographic_inv[no][fe_index].size(),
- dof_info[no].dofs_per_cell[fe_index]);
- }
- else
- {
- // ok, we have more than one component
- Assert (n_fe_components > 1, ExcInternalError());
- std::vector<unsigned int> scalar_lex =
- fe_poly != 0 ? fe_poly->get_poly_space_numbering() :
- fe_poly_piece->get_poly_space_numbering();
- AssertDimension (scalar_lex.size() * n_fe_components,
- dof_info[no].dofs_per_cell[fe_index]);
- std::vector<unsigned int> lexicographic (dof_info[no].dofs_per_cell[fe_index]);
- for (unsigned int comp=0; comp<n_fe_components; ++comp)
- for (unsigned int i=0; i<scalar_lex.size(); ++i)
- lexicographic[fe.component_to_system_index(comp,i)]
- = scalar_lex.size () * comp + scalar_lex[i];
-
- // invert numbering
- lexicographic_inv[no][fe_index] =
- Utilities::invert_permutation(lexicographic);
- }
- AssertDimension (lexicographic_inv[no][fe_index].size(),
+ AssertDimension (shape_info(no,0,fe_index,0).lexicographic_numbering.size(),
dof_info[no].dofs_per_cell[fe_index]);
}
local_dof_indices.resize (dof_info[no].dofs_per_cell[0]);
cell_it->get_dof_indices(local_dof_indices);
dof_info[no].read_dof_indices (local_dof_indices,
- lexicographic_inv[no][0],
+ shape_info(no,0,0,0).lexicographic_numbering,
*constraint[no], counter,
constraint_values,
cell_at_boundary);
local_dof_indices.resize (dof_info[no].dofs_per_cell[0]);
cell_it->get_mg_dof_indices(local_dof_indices);
dof_info[no].read_dof_indices (local_dof_indices,
- lexicographic_inv[no][0],
+ shape_info(no,0,0,0).lexicographic_numbering,
*constraint[no], counter,
constraint_values,
cell_at_boundary);
local_dof_indices.resize (cell_it->get_fe().dofs_per_cell);
cell_it->get_dof_indices(local_dof_indices);
dof_info[no].read_dof_indices (local_dof_indices,
- lexicographic_inv[no][cell_it->active_fe_index()],
+ shape_info(no,0,cell_it->active_fe_index(),0).lexicographic_numbering,
*constraint[no], counter,
constraint_values,
cell_at_boundary);
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef __deal2__matrix_free_operators_h
+#define __deal2__matrix_free_operators_h
+
+
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/vectorization.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace MatrixFreeOperators
+{
+ /**
+ * This class implements the operation of the action of the inverse of a mass
+ * matrix on an element for the special case of an evaluation object with as
+ * many quadrature points as there are cell degrees of freedom. It uses
+ * algorithms from FEEvaluation and produces the exact mass matrix for DGQ
+ * elements. This algorithm uses tensor products of inverse 1D shape matrices
+ * over quadrature points, so the inverse operation is exactly as expensive as
+ * applying the forward operator on each cell. Of course, for continuous
+ * finite elements this operation does not produce the inverse of a mass
+ * operation as the coupling between the elements cannot be considered by this
+ * operation.
+ *
+ * The equation may contain variable coefficients, so the user is required to
+ * provide an array for the inverse of the local coefficient (this class
+ * provide a helper method 'fill_inverse_JxW_values' to get the inverse of a
+ * constant-coefficient operator).
+ *
+ * @author Martin Kronbichler, 2014
+ */
+ template <int dim, int fe_degree, int n_components = 1, typename Number = double>
+ class CellwiseInverseMassMatrix
+ {
+ public:
+ /**
+ * Constructor. Initializes the shape information from the ShapeInfo field
+ * in the class FEEval.
+ */
+ CellwiseInverseMassMatrix (const FEEvaluationBase<dim,n_components,Number> &fe_eval);
+
+ /**
+ * Applies the inverse mass matrix operation on an input array. It is
+ * assumed that the passed input and output arrays are of correct size,
+ * namely FEEval::dofs_per_cell * n_components long. The inverse of the
+ * local coefficient (also containing the inverse JxW values) must be passed
+ * as first argument. Passing more than one component in the coefficient is
+ * allowed.
+ */
+ void apply(const AlignedVector<VectorizedArray<Number> > &inverse_coefficient,
+ const unsigned int n_actual_components,
+ const VectorizedArray<Number> *in_array,
+ VectorizedArray<Number> *out_array) const;
+
+ /**
+ * Fills the given array with the inverse of the JxW values, i.e., a mass
+ * matrix with coefficient 1. Non-unit coefficients must be multiplied (in
+ * inverse form) to this array.
+ */
+ void fill_inverse_JxW_values(AlignedVector<VectorizedArray<Number> > &inverse_jxw) const;
+
+ private:
+ /**
+ * A reference to the FEEvaluation object for getting the JxW_values.
+ */
+ const FEEvaluationBase<dim,n_components,Number> &fe_eval;
+
+ /**
+ * A structure to hold inverse shape functions, put into an aligned vector
+ * in order to make sure it can be allocated.
+ */
+ struct Inverse1DShape
+ {
+ VectorizedArray<Number> evenodd[fe_degree+1][fe_degree/2+1];
+ };
+ AlignedVector<Inverse1DShape> inverse_shape;
+ };
+
+
+
+ // ------------------------------------ inline functions ---------------------
+
+ template <int dim, int fe_degree, int n_components, typename Number>
+ inline
+ CellwiseInverseMassMatrix<dim,fe_degree,n_components,Number>
+ ::CellwiseInverseMassMatrix (const FEEvaluationBase<dim,n_components,Number> &fe_eval)
+ :
+ fe_eval (fe_eval)
+ {
+ FullMatrix<double> shapes_1d(fe_degree+1, fe_degree+1);
+ for (unsigned int i=0, c=0; i<shapes_1d.m(); ++i)
+ for (unsigned int j=0; j<shapes_1d.n(); ++j, ++c)
+ shapes_1d(i,j) = fe_eval.get_shape_info().shape_values_number[c];
+ shapes_1d.gauss_jordan();
+ inverse_shape.resize(1);
+ for (int i=0; i<(fe_degree+1)/2; ++i)
+ for (unsigned int q=0; q<(fe_degree+2)/2; ++q)
+ {
+ inverse_shape[0].evenodd[i][q] =
+ 0.5 * (shapes_1d(i,q) + shapes_1d(i,fe_degree-q));
+ inverse_shape[0].evenodd[fe_degree-i][q] =
+ 0.5 * (shapes_1d(i,q) - shapes_1d(i,fe_degree-q));
+ }
+ if (fe_degree % 2 == 0)
+ for (unsigned int q=0; q<(fe_degree+2)/2; ++q)
+ inverse_shape[0].evenodd[fe_degree/2][q] = shapes_1d(fe_degree/2,q);
+ }
+
+
+
+ template <int dim, int fe_degree, int n_components, typename Number>
+ inline
+ void
+ CellwiseInverseMassMatrix<dim,fe_degree,n_components,Number>
+ ::fill_inverse_JxW_values(AlignedVector<VectorizedArray<Number> > &inverse_jxw) const
+ {
+ const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ Assert(inverse_jxw.size() > 0 &&
+ inverse_jxw.size() % dofs_per_cell == 0,
+ ExcMessage("Expected diagonal to be a multiple of scalar dof per cells"));
+
+ // temporarily reduce size of inverse_jxw to dofs_per_cell to get JxW values
+ // from fe_eval (will not reallocate any memory)
+ const unsigned int previous_size = inverse_jxw.size();
+ inverse_jxw.resize(dofs_per_cell);
+ fe_eval.fill_JxW_values(inverse_jxw);
+
+ // invert
+ inverse_jxw.resize_fast(previous_size);
+ for (unsigned int q=0; q<dofs_per_cell; ++q)
+ inverse_jxw[q] = 1./inverse_jxw[q];
+ // copy values to rest of vector
+ for (unsigned int q=dofs_per_cell; q<previous_size; )
+ for (unsigned int i=0; i<dofs_per_cell; ++i, ++q)
+ inverse_jxw[q] = inverse_jxw[i];
+ }
+
+
+
+ template <int dim, int fe_degree, int n_components, typename Number>
+ inline
+ void
+ CellwiseInverseMassMatrix<dim,fe_degree,n_components,Number>
+ ::apply(const AlignedVector<VectorizedArray<Number> > &inverse_coefficients,
+ const unsigned int n_actual_components,
+ const VectorizedArray<Number> *in_array,
+ VectorizedArray<Number> *out_array) const
+ {
+ const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ Assert(inverse_coefficients.size() > 0 &&
+ inverse_coefficients.size() % dofs_per_cell == 0,
+ ExcMessage("Expected diagonal to be a multiple of scalar dof per cells"));
+ if (inverse_coefficients.size() != dofs_per_cell)
+ AssertDimension(n_actual_components * dofs_per_cell, inverse_coefficients.size());
+
+ Assert(dim == 2 || dim == 3, ExcNotImplemented());
+
+ const unsigned int shift_coefficient =
+ inverse_coefficients.size() > dofs_per_cell ? dofs_per_cell : 0;
+ const VectorizedArray<Number> *inv_coefficient = &inverse_coefficients[0];
+ VectorizedArray<Number> temp_data_field[dofs_per_cell];
+ for (unsigned int d=0; d<n_actual_components; ++d)
+ {
+ const VectorizedArray<Number>* in = in_array+d*dofs_per_cell;
+ VectorizedArray<Number>* out = out_array+d*dofs_per_cell;
+ internal::apply_tensor_product_evenodd<dim,fe_degree,fe_degree+1,
+ VectorizedArray<Number>,0,false,false,2>
+ (inverse_shape[0].evenodd, in, temp_data_field);
+ internal::apply_tensor_product_evenodd<dim,fe_degree,fe_degree+1,
+ VectorizedArray<Number>,1,false,false,2>
+ (inverse_shape[0].evenodd, temp_data_field, out);
+
+ if (dim == 3)
+ {
+ internal::apply_tensor_product_evenodd<dim,fe_degree,fe_degree+1,
+ VectorizedArray<Number>,2,false,false,2>
+ (inverse_shape[0].evenodd, out, temp_data_field);
+ for (unsigned int q=0; q<dofs_per_cell; ++q)
+ temp_data_field[q] *= inv_coefficient[q];
+ internal::apply_tensor_product_evenodd<dim,fe_degree,fe_degree+1,
+ VectorizedArray<Number>,2,true,false,2>
+ (inverse_shape[0].evenodd, temp_data_field, out);
+ }
+ else if (dim == 2)
+ for (unsigned int q=0; q<dofs_per_cell; ++q)
+ out[q] *= inv_coefficient[q];
+
+ internal::apply_tensor_product_evenodd<dim,fe_degree,fe_degree+1,
+ VectorizedArray<Number>,1,true,false,2>
+ (inverse_shape[0].evenodd, out, temp_data_field);
+ internal::apply_tensor_product_evenodd<dim,fe_degree,fe_degree+1,
+ VectorizedArray<Number>,0,true,false,2>
+ (inverse_shape[0].evenodd, temp_data_field, out);
+
+ inv_coefficient += shift_coefficient;
+ }
+ }
+
+} // end of namespace MatrixFreeOperators
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/exceptions.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
#include <deal.II/fe/fe.h>
#include <deal.II/matrix_free/helper_functions.h>
*/
ShapeInfo ();
+ /**
+ * Constructor that initializes the data fields using the reinit method.
+ */
+ template <int dim>
+ ShapeInfo (const Quadrature<1> &quad,
+ const FiniteElement<dim> &fe,
+ const unsigned int base_element = 0);
+
/**
* Initializes the data fields. Takes a one-dimensional quadrature
* formula and a finite element as arguments and evaluates the shape
*/
template <int dim>
void reinit (const Quadrature<1> &quad,
- const FiniteElement<dim> &fe_dim);
+ const FiniteElement<dim> &fe_dim,
+ const unsigned int base_element = 0);
/**
* Returns the memory consumption of this
*/
std::vector<Number> shape_gradient_number;
+ /**
+ * Renumbering from deal.II's numbering of cell degrees of freedom to
+ * lexicographic numbering used inside the FEEvaluation schemes of the
+ * underlying element in the DoFHandler. For vector-valued elements, the
+ * renumbering starts with a lexicographic numbering of the first
+ * component, then everything of the second component, and so on.
+ */
+ std::vector<unsigned int> lexicographic_numbering;
+
/**
* Stores the number of quadrature points in
* @p dim dimensions for a cell.
unsigned int dofs_per_face;
};
+
+
+ // ------------------------------------------ inline functions
+
+ template <typename Number>
+ template <int dim>
+ inline
+ ShapeInfo<Number>::ShapeInfo (const Quadrature<1> &quad,
+ const FiniteElement<dim> &fe_in,
+ const unsigned int base_element_number)
+ :
+ n_q_points (0),
+ dofs_per_cell (0)
+ {
+ reinit (quad, fe_in, base_element_number);
+ }
+
+
+
} // end of namespace MatrixFreeFunctions
} // end of namespace internal
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/tensor_product_polynomials.h>
#include <deal.II/base/polynomials_piecewise.h>
#include <deal.II/fe/fe_poly.h>
+#include <deal.II/fe/fe_dgp.h>
#include <deal.II/matrix_free/shape_info.h>
template <int dim>
void
ShapeInfo<Number>::reinit (const Quadrature<1> &quad,
- const FiniteElement<dim> &fe)
+ const FiniteElement<dim> &fe_in,
+ const unsigned int base_element_number)
{
- Assert (fe.n_components() == 1,
+ const FiniteElement<dim> *fe = &fe_in;
+ if (fe_in.n_components() > 1)
+ fe = &fe_in.base_element(base_element_number);
+
+ Assert (fe->n_components() == 1,
ExcMessage("FEEvaluation only works for scalar finite elements."));
- const unsigned int n_dofs_1d = fe.degree+1,
+
+ const unsigned int n_dofs_1d = fe->degree+1,
n_q_points_1d = quad.size();
- AssertDimension(fe.dofs_per_cell, Utilities::fixed_power<dim>(n_dofs_1d));
- std::vector<unsigned int> lexicographic (fe.dofs_per_cell);
// renumber (this is necessary for FE_Q, for example, since there the
// vertex DoFs come first, which is incompatible with the lexicographic
// ordering necessary to apply tensor products efficiently)
+ std::vector<unsigned int> scalar_lexicographic;
{
+ // find numbering to lexicographic
+ Assert(fe->n_components() == 1,
+ ExcMessage("Expected a scalar element"));
+
const FE_Poly<TensorProductPolynomials<dim>,dim,dim> *fe_poly =
- dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>(&fe);
+ dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>(fe);
+
const FE_Poly<TensorProductPolynomials<dim,Polynomials::
- PiecewisePolynomial<double> >,dim,dim> *fe_poly_piece =
+ PiecewisePolynomial<double> >,dim,dim> *fe_poly_piece =
dynamic_cast<const FE_Poly<TensorProductPolynomials<dim,
- Polynomials::PiecewisePolynomial<double> >,dim,dim>*> (&fe);
- Assert (fe_poly != 0 || fe_poly_piece, ExcNotImplemented());
- lexicographic = fe_poly != 0 ?
- fe_poly->get_poly_space_numbering_inverse() :
- fe_poly_piece->get_poly_space_numbering_inverse();
+ Polynomials::PiecewisePolynomial<double> >,dim,dim>*> (fe);
+
+ const FE_DGP<dim> *fe_dgp = dynamic_cast<const FE_DGP<dim>*>(fe);
+
+ if (fe_poly != 0)
+ scalar_lexicographic = fe_poly->get_poly_space_numbering_inverse();
+ else if (fe_poly_piece != 0)
+ scalar_lexicographic = fe_poly_piece->get_poly_space_numbering_inverse();
+ else if (fe_dgp != 0)
+ {
+ scalar_lexicographic.resize(fe_dgp->dofs_per_cell);
+ for (unsigned int i=0; i<fe_dgp->dofs_per_cell; ++i)
+ scalar_lexicographic[i] = i;
+ }
+ else
+ Assert(false, ExcNotImplemented());
+
+ // Finally store the renumbering into the member variable of this
+ // class
+ if (fe_in.n_components() == 1)
+ lexicographic_numbering = scalar_lexicographic;
+ else
+ {
+ // have more than one component, get the inverse
+ // permutation, invert it, sort the components one after one,
+ // and invert back
+ std::vector<unsigned int> scalar_inv =
+ Utilities::invert_permutation(scalar_lexicographic);
+ std::vector<unsigned int> lexicographic (fe_in.dofs_per_cell);
+ for (unsigned int comp=0; comp<fe_in.n_components(); ++comp)
+ for (unsigned int i=0; i<scalar_inv.size(); ++i)
+ lexicographic[fe_in.component_to_system_index(comp,i)]
+ = scalar_inv.size () * comp + scalar_inv[i];
+
+ // invert numbering again
+ lexicographic_numbering =
+ Utilities::invert_permutation(lexicographic);
+ }
// to evaluate 1D polynomials, evaluate along the line where y=z=0,
// assuming that shape_value(0,Point<dim>()) == 1. otherwise, need
// other entry point (e.g. generating a 1D element by reading the
// name, as done before r29356)
- Assert(std::fabs(fe.shape_value(lexicographic[0], Point<dim>())-1) < 1e-13,
+ Assert(std::fabs(fe->shape_value(scalar_lexicographic[0],
+ Point<dim>())-1) < 1e-13,
ExcInternalError());
}
n_q_points = Utilities::fixed_power<dim>(n_q_points_1d);
- dofs_per_cell = Utilities::fixed_power<dim>(n_dofs_1d);
+ dofs_per_cell = fe->dofs_per_cell;
n_q_points_face = dim>1?Utilities::fixed_power<dim-1>(n_q_points_1d):1;
- dofs_per_face = dim>1?Utilities::fixed_power<dim-1>(n_dofs_1d):1;
+ dofs_per_face = fe->dofs_per_face;
const unsigned int array_size = n_dofs_1d*n_q_points_1d;
this->shape_gradients.resize_fast (array_size);
{
// need to reorder from hierarchical to lexicographic to get the
// DoFs correct
- const unsigned int my_i = lexicographic[i];
+ const unsigned int my_i = scalar_lexicographic[i];
for (unsigned int q=0; q<n_q_points_1d; ++q)
{
// fill both vectors with
// non-vectorized fields
Point<dim> q_point;
q_point[0] = quad.get_points()[q][0];
- shape_values_number[i*n_q_points_1d+q] = fe.shape_value(my_i,q_point);
- shape_gradient_number[i*n_q_points_1d+q] = fe.shape_grad (my_i,q_point)[0];
+ shape_values_number[i*n_q_points_1d+q] = fe->shape_value(my_i,q_point);
+ shape_gradient_number[i*n_q_points_1d+q] = fe->shape_grad (my_i,q_point)[0];
shape_values [i*n_q_points_1d+q] =
shape_values_number [i*n_q_points_1d+q];
shape_gradients[i*n_q_points_1d+q] =
shape_gradient_number[i*n_q_points_1d+q];
shape_hessians[i*n_q_points_1d+q] =
- fe.shape_grad_grad(my_i,q_point)[0][0];
+ fe->shape_grad_grad(my_i,q_point)[0][0];
q_point[0] *= 0.5;
- subface_value[0][i*n_q_points_1d+q] = fe.shape_value(my_i,q_point);
+ subface_value[0][i*n_q_points_1d+q] = fe->shape_value(my_i,q_point);
q_point[0] += 0.5;
- subface_value[1][i*n_q_points_1d+q] = fe.shape_value(my_i,q_point);
+ subface_value[1][i*n_q_points_1d+q] = fe->shape_value(my_i,q_point);
}
Point<dim> q_point;
- this->face_value[0][i] = fe.shape_value(my_i,q_point);
- this->face_gradient[0][i] = fe.shape_grad(my_i,q_point)[0];
+ this->face_value[0][i] = fe->shape_value(my_i,q_point);
+ this->face_gradient[0][i] = fe->shape_grad(my_i,q_point)[0];
q_point[0] = 1;
- this->face_value[1][i] = fe.shape_value(my_i,q_point);
- this->face_gradient[1][i] = fe.shape_grad(my_i,q_point)[0];
+ this->face_value[1][i] = fe->shape_value(my_i,q_point);
+ this->face_gradient[1][i] = fe->shape_grad(my_i,q_point)[0];
}
// face information
}
case 2:
{
- for (unsigned int i=0; i<n_dofs_1d; i++)
+ for (unsigned int i=0; i<this->dofs_per_face; i++)
{
this->face_indices(0,i) = n_dofs_1d*i;
this->face_indices(1,i) = n_dofs_1d*i + n_dofs_1d-1;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*
* // first declare the vectors
* // to be used later
- * vector<string> solution_names;
+ * std::vector<std::string> solution_names;
* solution_names.push_back ("u");
* solution_names.push_back ("v");
* data_out_stack.declare_data_vector (solution_names,
* component and therefore more than one
* name needs to be given. However, you
* can also call this function with a
- * <tt>vector<string></tt> containing only one
+ * <tt>std::vector@<std::string@></tt> containing only one
* element if the finite element has
* only one component.
*/
* component and therefore more than one
* name needs to be given. However, you
* can also call this function with a
- * <tt>vector<string></tt> containing only one
+ * <tt>std::vector@<std::string@></tt> containing only one
* element if the finite element has
* only one component.
*
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2007 - 2013 by the deal.II authors
+// Copyright (C) 2007 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
+ * This class provides an interface to compute derived quantities from
+ * a solution that can then be output in graphical formats for visualization,
+ * using facilities such as the DataOut class.
+ *
* For the (graphical) output of a FE solution one frequently wants to include
* derived quantities, which are calculated from the values of the solution
* and possibly the first and second derivates of the solution. Examples are
- * the calculation Mach numbers from velocity and density in supersonic flow
+ * the calculation of Mach numbers from velocity and density in supersonic flow
* computations, or the computation of the magnitude of a complex-valued
* solution as demonstrated in step-29. Other uses are shown in step-32 and
* step-33. This class offers the interface to perform such
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
* Compute the constraints that correspond to boundary conditions of the
- * form $\vec n \times \vec u=0$, i.e. flow normal to the boundary if $\vec
- * u$ is a vector-valued quantity. This function constrains exactly those
+ * form $\vec n \times \vec u=0$. This corresponds to flow with no tangential
+ * component, i.e. flow is parallel to the normal vector to the boundary if $\vec
+ * u$ is a vector-valued quantity.
+ *
+ * This function constrains exactly those
* vector-valued components that are left unconstrained by
* compute_no_normal_flux_constraints, and leaves the one component
* unconstrained that is constrained by compute_no_normal_flux_constraints.
+ values[q_point] (first_vector_component + 1)
* tangentials[q_point] (1))
* (fe_values[vec].value (fe.face_to_cell_index (i, face), q_point)
- * tangentials[q_point])
- / std::sqrt (jacobians[q_point][0][face_coordinate_direction[face]]
- * jacobians[q_point][0][face_coordinate_direction[face]]
- + jacobians[q_point][1][face_coordinate_direction[face]]
- * jacobians[q_point][1][face_coordinate_direction[face]]);
+ * tangentials[q_point]);
if (q_point == 0)
dofs_processed[i] = true;
namespace Algorithms
{
+ OperatorBase::~OperatorBase()
+ {}
+
+ void OperatorBase::notify(const Event &e)
+ {
+ notifications += e;
+ }
+
+ void
+ OperatorBase::clear_events ()
+ {
+ notifications.clear();
+ }
+
+
#include "operator.inst"
}
tensor_product_polynomials_const.cc
thread_management.cc
timer.cc
+ time_stepping.cc
utilities.cc
)
SET(_inst
data_out_base.inst.in
+ time_stepping.inst.in
)
FILE(GLOB _header
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
Point<3> v_min, v_max, v_inter;
// Use the Bubblesort algorithm to sort the points with respect to the third coordinate
- int i, j;
-
- for (i = 0; i < 2; ++i)
+ for (int i = 0; i < 2; ++i)
{
- for (j = 0; j < 2-i; ++j)
+ for (int j = 0; j < 2-i; ++j)
{
if (points[j][2] > points[j + 1][2])
{
}
// max. and min. heigth of solution
- typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
- Assert(patch!=patches.end(), ExcInternalError());
- double hmin=patch->data(0,0);
- double hmax=patch->data(0,0);
+ Assert(patches.size()>0, ExcInternalError());
+ double hmin=patches[0].data(0,0);
+ double hmax=patches[0].data(0,0);
- for (; patch != patches.end(); ++patch)
+ for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
+ patch != patches.end(); ++patch)
{
const unsigned int n_subdivisions = patch->n_subdivisions;
#include <deal.II/base/utilities.h>
#include <deal.II/lac/vector.h>
-#ifdef DEAL_II_WITH_FUNCTIONPARSER
-#include <fparser.hh>
-namespace fparser
-{
- class FunctionParser: public ::FunctionParser
- {};
-}
+
+#ifdef DEAL_II_WITH_MUPARSER
+#include <muParser.h>
#else
namespace fparser
class FunctionParser
{};
}
-
#endif
DEAL_II_NAMESPACE_OPEN
FunctionParser<dim>::FunctionParser(const unsigned int n_components,
const double initial_time)
:
- Function<dim>(n_components, initial_time),
- fp (0)
-{
- fp = new fparser::FunctionParser[n_components];
-}
+ Function<dim>(n_components, initial_time)
+{}
template <int dim>
FunctionParser<dim>::~FunctionParser()
-{
- delete[] fp;
-}
+{}
-
-#ifdef DEAL_II_WITH_FUNCTIONPARSER
+#ifdef DEAL_II_WITH_MUPARSER
template <int dim>
void FunctionParser<dim>::initialize (const std::string &variables,
const std::vector<std::string> &expressions,
use_degrees);
}
+template <int dim>
+void FunctionParser<dim>::initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const std::map<std::string, double> &constants,
+ const bool time_dependent)
+ {
+ initialize(vars, expressions, constants, time_dependent, false);
+ }
+
+namespace internal
+{
+ // convert double into int
+ int mu_round(double val)
+ {
+ return static_cast<int>(val + ((val>=0.0) ? 0.5 : -0.5) );
+ }
+
+ double mu_if(double condition, double thenvalue, double elsevalue)
+ {
+ if (mu_round(condition))
+ return thenvalue;
+ else
+ return elsevalue;
+ }
+
+ double mu_or(double left, double right)
+ {
+ return (mu_round(left)) || (mu_round(right));
+ }
+
+ double mu_and(double left, double right)
+ {
+ return (mu_round(left)) && (mu_round(right));
+ }
+
+ double mu_int(double value)
+ {
+ return static_cast<double>(mu_round(value));
+ }
+ double mu_ceil(double value)
+ {
+ return ceil(value);
+ }
+ double mu_floor(double value)
+ {
+ return floor(value);
+ }
+ double mu_cot(double value)
+ {
+ return 1.0/tan(value);
+ }
+ double mu_csc(double value)
+ {
+ return 1.0/sin(value);
+ }
+ double mu_sec(double value)
+ {
+ return 1.0/cos(value);
+ }
+ double mu_log(double value)
+ {
+ return log(value);
+ }
+
+
+
+}
+template <int dim>
+void FunctionParser<dim>:: init_muparser() const
+{
+ if (fp.get().size()>0)
+ return;
+
+ fp.get().resize(this->n_components);
+ vars.get().resize(var_names.size());
+ for (unsigned int i=0; i<this->n_components; ++i)
+ {
+ std::map< std::string, double >::const_iterator
+ constant = constants.begin(),
+ endc = constants.end();
+
+ for (; constant != endc; ++constant)
+ {
+ fp.get()[i].DefineConst(constant->first.c_str(), constant->second);
+ }
+
+ for (unsigned int iv=0;iv<var_names.size();++iv)
+ fp.get()[i].DefineVar(var_names[iv].c_str(), &vars.get()[iv]);
+
+ // define some compatibility functions:
+ fp.get()[i].DefineFun("if",internal::mu_if, true);
+ fp.get()[i].DefineOprt("|", internal::mu_or, 1);
+ fp.get()[i].DefineOprt("&", internal::mu_and, 2);
+ fp.get()[i].DefineFun("int", internal::mu_int, true);
+ fp.get()[i].DefineFun("ceil", internal::mu_ceil, true);
+ fp.get()[i].DefineFun("cot", internal::mu_cot, true);
+ fp.get()[i].DefineFun("csc", internal::mu_csc, true);
+ fp.get()[i].DefineFun("floor", internal::mu_floor, true);
+ fp.get()[i].DefineFun("sec", internal::mu_sec, true);
+ fp.get()[i].DefineFun("log", internal::mu_log, true);
+
+ try
+ {
+ fp.get()[i].SetExpr(expressions[i]);
+ }
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: " << e.GetMsg() << "\n";
+ std::cerr << "Formula: " << e.GetExpr() << "\n";
+ std::cerr << "Token: " << e.GetToken() << "\n";
+ std::cerr << "Position: " << e.GetPos() << "\n";
+ std::cerr << "Errc: " << e.GetCode() << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg().c_str()));
+ }
+ }
+}
template <int dim>
void FunctionParser<dim>::initialize (const std::string &variables,
const bool time_dependent,
const bool use_degrees)
{
+
+ this->fp.clear(); // this will reset all thread-local objects
+
+ this->constants = constants;
+ this->var_names = Utilities::split_string_list(variables, ',');
+ this->expressions = expressions;
+ AssertThrow(((time_dependent)?dim+1:dim) == var_names.size(),
+ ExcMessage("wrong number of variables"));
+ AssertThrow(!use_degrees, ExcNotImplemented());
+
// We check that the number of
// components of this function
// matches the number of components
ExcInvalidExpressionSize(this->n_components,
expressions.size()) );
+ // we no longer support units:
+ AssertThrow(units.size()==0, ExcNotImplemented());
-
- for (unsigned int i=0; i<this->n_components; ++i)
- {
-
- // Add the various units to
- // the parser.
- std::map< std::string, double >::const_iterator
- unit = units.begin(),
- endu = units.end();
- for (; unit != endu; ++unit)
- {
- const bool success = fp[i].AddUnit(unit->first, unit->second);
- AssertThrow (success,
- ExcMessage("Invalid Unit Name [error adding a unit]"));
- }
-
-
-
- // Add the various constants to
- // the parser.
- std::map< std::string, double >::const_iterator
- constant = constants.begin(),
- endc = constants.end();
- for (; constant != endc; ++constant)
- {
- const bool success = fp[i].AddConstant(constant->first, constant->second);
- AssertThrow (success, ExcMessage("Invalid Constant Name"));
- }
-
- const int ret_value = fp[i].Parse(expressions[i],
- variables,
- use_degrees);
- AssertThrow (ret_value == -1,
- ExcParseError(ret_value, fp[i].ErrorMsg()));
-
- // The fact that the parser did
- // not throw an error does not
- // mean that everything went
- // ok... we can still have
- // problems with the number of
- // variables...
- }
// Now we define how many variables
// we expect to read in. We
// distinguish between two cases:
else
n_vars = dim;
- /*
- // Let's check if the number of
- // variables is correct...
- AssertThrow (n_vars == fp[0].NVars(),
- ! ~~~~~~~
- ! not available anymore in fparser-4.5, maier 2012
- ExcDimensionMismatch(n_vars,fp[0].NVars()));
- */
-
+ init_muparser();
+
// Now set the initialization bit.
initialized = true;
}
+template <int dim>
+void FunctionParser<dim>::initialize (const std::string &vars,
+ const std::string &expression,
+ const std::map<std::string, double> &constants,
+ const bool time_dependent)
+{
+ initialize(vars, expression, constants, time_dependent, false);
+}
template <int dim>
Assert (component < this->n_components,
ExcIndexRange(component, 0, this->n_components));
- // Statically allocate dim+1
- // double variables.
- double vars[dim+1];
+ // initialize if not done so on this thread yet:
+ init_muparser();
for (unsigned int i=0; i<dim; ++i)
- vars[i] = p(i);
-
- // We need the time variable only
- // if the number of variables is
- // different from the dimension. In
- // this case it can only be dim+1,
- // otherwise an exception would
- // have already been thrown
+ vars.get()[i] = p(i);
if (dim != n_vars)
- vars[dim] = this->get_time();
-
- double my_value = fp[component].Eval((double *)vars);
+ vars.get()[dim] = this->get_time();
- AssertThrow (fp[component].EvalError() == 0,
- ExcMessage(fp[component].ErrorMsg()));
- return my_value;
+ try
+ {
+ return fp.get()[component].Eval();
+ }
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: " << e.GetMsg() << "\n";
+ std::cerr << "Formula: " << e.GetExpr() << "\n";
+ std::cerr << "Token: " << e.GetToken() << "\n";
+ std::cerr << "Position: " << e.GetPos() << "\n";
+ std::cerr << "Errc: " << e.GetCode() << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg().c_str()));
+ return 0.0;
+ }
}
Assert (values.size() == this->n_components,
ExcDimensionMismatch (values.size(), this->n_components));
- // Statically allocates dim+1
- // double variables.
- double vars[dim+1];
+
+ // initialize if not done so on this thread yet:
+ init_muparser();
for (unsigned int i=0; i<dim; ++i)
- vars[i] = p(i);
-
- // We need the time variable only
- // if the number of variables is
- // different from the dimension. In
- // this case it can only be dim+1,
- // otherwise an exception would
- // have already been thrown
+ vars.get()[i] = p(i);
if (dim != n_vars)
- vars[dim] = this->get_time();
-
+ vars.get()[dim] = this->get_time();
+
for (unsigned int component = 0; component < this->n_components;
++component)
- {
- values(component) = fp[component].Eval((double *)vars);
- AssertThrow(fp[component].EvalError() == 0,
- ExcMessage(fp[component].ErrorMsg()));
- }
+ values(component) = fp.get()[component].Eval();
}
#else
+
template <int dim>
void
FunctionParser<dim>::initialize(const std::string &,
Assert(false, ExcNeedsFunctionparser());
}
+template <int dim>
+void
+FunctionParser<dim>::initialize(const std::string &,
+ const std::vector<std::string> &,
+ const std::map<std::string, double> &,
+ const bool)
+{
+ Assert(false, ExcNeedsFunctionparser());
+}
+
+template <int dim>
+void
+FunctionParser<dim>::initialize(const std::string &,
+ const std::string &,
+ const std::map<std::string, double> &,
+ const bool)
+{
+ Assert(false, ExcNeedsFunctionparser());
+}
+
+
template <int dim>
double FunctionParser<dim>::value (
int lineno=0;
bool status = true;
- while (input)
+ while (getline (input, line))
{
++lineno;
- getline (input, line);
status &= scan_line (line, filename, lineno);
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2000 - 2013 by the deal.II authors
+// Copyright (C) 2000 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/thread_management.h>
#include <cmath>
+#include <algorithm>
#include <limits>
DEAL_II_NAMESPACE_OPEN
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.cc 30037 2013-07-18 16:55:40Z maier $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/time_stepping.templates.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/petsc_parallel_vector.h>
+#include <deal.II/lac/petsc_parallel_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/trilinos_parallel_block_vector.h>
+
+DEAL_II_NAMESPACE_OPEN
+namespace TimeStepping
+{
+#include "time_stepping.inst"
+}
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.inst.in 30049 2013-07-18 19:42:40Z maier $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+for (S : REAL_SCALARS; V : DEAL_II_VEC_TEMPLATES)
+{
+ template class ExplicitRungeKutta<V<S> >;
+ template class ImplicitRungeKutta<V<S> >;
+ template class EmbeddedExplicitRungeKutta<V<S> >;
+}
+
+for (S : REAL_SCALARS; V : DEAL_II_VEC_TEMPLATES)
+{
+ template class ExplicitRungeKutta<parallel::distributed::V<S> >;
+ template class ImplicitRungeKutta<parallel::distributed::V<S> >;
+ template class EmbeddedExplicitRungeKutta<parallel::distributed::V<S> >;
+}
+
+for (V : EXTERNAL_SEQUENTIAL_VECTORS)
+{
+ template class ExplicitRungeKutta<V>;
+ template class ImplicitRungeKutta<V>;
+ template class EmbeddedExplicitRungeKutta<V>;
+}
+
+for (V : EXTERNAL_PARALLEL_VECTORS)
+{
+ template class ExplicitRungeKutta<V>;
+ template class ImplicitRungeKutta<V>;
+ template class EmbeddedExplicitRungeKutta<V>;
+}
types<2>::balance_type btype,
p4est_init_t init_fn);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ p4est_gloidx_t (&partition) (types<2>::forest *p4est,
+ int partition_for_coarsening,
+ p4est_weight_t weight_fn);
+#else
static
void (&partition) (types<2>::forest *p4est,
int partition_for_coarsening,
p4est_weight_t weight_fn);
+#endif
static
void (&save) (const char *filename,
types<2>::forest *p4est,
int save_data);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<2>::forest *(&load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<2>::connectivity **p4est);
+#else
static
types<2>::forest *(&load) (const char *filename,
MPI_Comm mpicomm,
int load_data,
void *user_pointer,
types<2>::connectivity **p4est);
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ int (&connectivity_save) (const char *filename,
+ types<2>::connectivity *connectivity);
+#else
static
void (&connectivity_save) (const char *filename,
types<2>::connectivity *connectivity);
+#endif
static
int (&connectivity_is_valid) (types<2>::connectivity *connectivity);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<2>::connectivity *(&connectivity_load) (const char *filename,
+ long unsigned *length);
+#else
static
types<2>::connectivity *(&connectivity_load) (const char *filename,
long *length);
+#endif
static
unsigned int (&checksum) (types<2>::forest *p4est);
p4est_init_t init_fn)
= p4est_balance;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ p4est_gloidx_t (&functions<2>::partition) (types<2>::forest *p4est,
+ int partition_for_coarsening,
+ p4est_weight_t weight_fn)
+ = p4est_partition_ext;
+#else
void (&functions<2>::partition) (types<2>::forest *p4est,
int partition_for_coarsening,
p4est_weight_t weight_fn)
= p4est_partition_ext;
+#endif
void (&functions<2>::save) (const char *filename,
types<2>::forest *p4est,
int save_data)
= p4est_save;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<2>::forest *
+ (&functions<2>::load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ std::size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<2>::connectivity **p4est)
+ = p4est_load_ext;
+#else
types<2>::forest *
(&functions<2>::load) (const char *filename,
MPI_Comm mpicomm,
void *user_pointer,
types<2>::connectivity **p4est)
= p4est_load;
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ int (&functions<2>::connectivity_save) (const char *filename,
+ types<2>::connectivity *connectivity)
+ = p4est_connectivity_save;
+#else
void (&functions<2>::connectivity_save) (const char *filename,
types<2>::connectivity *connectivity)
= p4est_connectivity_save;
+#endif
int (&functions<2>::connectivity_is_valid) (types<2>::connectivity
*connectivity)
= p4est_connectivity_is_valid;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<2>::connectivity *
+ (&functions<2>::connectivity_load) (const char *filename,
+ long unsigned *length)
+ = p4est_connectivity_load;
+#else
types<2>::connectivity *
(&functions<2>::connectivity_load) (const char *filename,
long *length)
= p4est_connectivity_load;
+#endif
unsigned int (&functions<2>::checksum) (types<2>::forest *p4est)
= p4est_checksum;
types<3>::balance_type btype,
p8est_init_t init_fn);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ p4est_gloidx_t (&partition) (types<3>::forest *p8est,
+ int partition_for_coarsening,
+ p8est_weight_t weight_fn);
+#else
static
void (&partition) (types<3>::forest *p8est,
int partition_for_coarsening,
p8est_weight_t weight_fn);
+#endif
static
void (&save) (const char *filename,
types<3>::forest *p4est,
int save_data);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<3>::forest *(&load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ std::size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<3>::connectivity **p4est);
+#else
static
types<3>::forest *(&load) (const char *filename,
MPI_Comm mpicomm,
int load_data,
void *user_pointer,
types<3>::connectivity **p4est);
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ int (&connectivity_save) (const char *filename,
+ types<3>::connectivity *connectivity);
+#else
static
void (&connectivity_save) (const char *filename,
types<3>::connectivity *connectivity);
+#endif
static
int (&connectivity_is_valid) (types<3>::connectivity *connectivity);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<3>::connectivity *(&connectivity_load) (const char *filename,
+ long unsigned *length);
+#else
static
types<3>::connectivity *(&connectivity_load) (const char *filename,
long *length);
+#endif
static
unsigned int (&checksum) (types<3>::forest *p8est);
p8est_init_t init_fn)
= p8est_balance;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ p4est_gloidx_t (&functions<3>::partition) (types<3>::forest *p8est,
+ int partition_for_coarsening,
+ p8est_weight_t weight_fn)
+ = p8est_partition_ext;
+#else
void (&functions<3>::partition) (types<3>::forest *p8est,
int partition_for_coarsening,
p8est_weight_t weight_fn)
= p8est_partition_ext;
+#endif
void (&functions<3>::save) (const char *filename,
types<3>::forest *p4est,
int save_data)
= p8est_save;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<3>::forest *
+ (&functions<3>::load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ std::size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<3>::connectivity **p4est)
+ = p8est_load_ext;
+#else
types<3>::forest *
(&functions<3>::load) (const char *filename,
MPI_Comm mpicomm,
void *user_pointer,
types<3>::connectivity **p4est)
= p8est_load;
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ int (&functions<3>::connectivity_save) (const char *filename,
+ types<3>::connectivity *connectivity)
+ = p8est_connectivity_save;
+#else
void (&functions<3>::connectivity_save) (const char *filename,
types<3>::connectivity *connectivity)
= p8est_connectivity_save;
+#endif
int (&functions<3>::connectivity_is_valid) (types<3>::connectivity
*connectivity)
= p8est_connectivity_is_valid;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<3>::connectivity *
+ (&functions<3>::connectivity_load) (const char *filename,
+ long unsigned *length)
+ = p8est_connectivity_load;
+#else
types<3>::connectivity *
(&functions<3>::connectivity_load) (const char *filename,
long *length)
= p8est_connectivity_load;
+#endif
unsigned int (&functions<3>::checksum) (types<3>::forest *p8est)
= p8est_checksum;
// orientation
//
// while we're at it, also copy the neighborship information between cells
- typename Triangulation<dim>::active_cell_iterator
+ typename Triangulation<dim, spacedim>::active_cell_iterator
cell = triangulation.begin_active(),
endc = triangulation.end();
for (; cell != endc; ++cell)
Assert(version == 2, ExcMessage("Incompatible version found in .info file."));
Assert(this->n_cells(0) == n_coarse_cells, ExcMessage("Number of coarse cells differ!"));
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+#else
+ AssertThrow(numcpus <= Utilities::MPI::n_mpi_processes (mpi_communicator),
+ ExcMessage("parallel::distributed::Triangulation::load() only supports loading "
+ "saved data with a greater or equal number of processes than were used to "
+ "save() when using p4est 0.3.4.2."));
+#endif
attached_data_size = 0;
n_attached_datas = 0;
n_attached_deserialize = attached_count;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ parallel_forest = dealii::internal::p4est::functions<dim>::load_ext (
+ filename, mpi_communicator,
+ attached_size, attached_size>0,
+ 1, 0,
+ this,
+ &connectivity);
+#else
parallel_forest = dealii::internal::p4est::functions<dim>::load (
filename, mpi_communicator,
attached_size, attached_size>0,
this,
&connectivity);
-
+#endif
if (numcpus != Utilities::MPI::n_mpi_processes (mpi_communicator))
{
// We are changing the number of CPUs so we need to repartition.
for (i = 0; i < l; i++)
{
typename dealii::Triangulation<dim,spacedim>::cell_iterator cell (triangulation, i, dealii_index);
- child_id = internal::p4est::functions<dim>::quadrant_ancestor_id (&quad, i + 1);
+ child_id = dealii::internal::p4est::functions<dim>::quadrant_ancestor_id (&quad, i + 1);
Assert (cell->has_children (), ExcMessage ("p4est quadrant does not correspond to a cell!"));
dealii_index = cell->child_index(child_id);
}
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
- level_cell_iterator cell = begin(level),
- endcell = end(level);
- for ( ; cell != endcell; ++cell)
+ for (level_cell_iterator cell = begin(level); cell != end(level); ++cell)
for (unsigned int line=0; line < GeometryInfo<2>::faces_per_cell; ++line)
cell->face(line)->set_user_flag();
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
-
- level_cell_iterator cell = begin(level),
- endcell = end(level);
- for ( ; cell != endcell ; ++cell)
+ for (level_cell_iterator cell = begin(level) ; cell != end(level) ; ++cell)
for (unsigned int line=0; line < GeometryInfo<3>::lines_per_cell; ++line)
cell->line(line)->set_user_flag();
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
- level_cell_iterator cell = begin(level),
- endcell = end(level);
- for ( ; cell != endcell ; ++cell)
+ for (level_cell_iterator cell = begin(level) ; cell != end(level); ++cell)
for (unsigned int quad=0; quad < GeometryInfo<3>::faces_per_cell; ++quad)
cell->face(quad)->set_user_flag();
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
- typename DoFHandler<2,spacedim>::level_cell_iterator cell = dof_handler.begin(level),
- endcell = dof_handler.end(level);
- for ( ; cell != endcell; ++cell)
+ for (typename DoFHandler<2,spacedim>::level_cell_iterator cell = dof_handler.begin(level);
+ cell != dof_handler.end(level); ++cell)
for (unsigned int line=0; line < GeometryInfo<2>::faces_per_cell; ++line)
cell->face(line)->set_user_flag();
tr->clear_user_flags ();
//mark all own cells for transfer
- typename DoFHandler<dim,spacedim>::active_cell_iterator
- cell, endc = dof_handler.end();
- for (cell = dof_handler.begin_active(); cell != endc; ++cell)
+ for (typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof_handler.begin_active();
+ cell != dof_handler.end(); ++cell)
if (!cell->is_artificial())
cell->set_user_flag();
//check that we are really done
{
std::vector<dealii::types::global_dof_index> local_dof_indices;
- typename DoFHandler<dim,spacedim>::active_cell_iterator
- cell, endc = dof_handler.end();
- for (cell = dof_handler.begin_active(); cell != endc; ++cell)
+ for (typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof_handler.begin_active();
+ cell != dof_handler.end(); ++cell)
if (!cell->is_artificial())
{
local_dof_indices.resize (cell->get_fe().dofs_per_cell);
const bool use_constraints,
const std::vector<types::global_dof_index> &starting_indices)
{
- std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
+ std::vector<types::global_dof_index> renumbering(dof_handler.locally_owned_dofs().n_elements(),
DH::invalid_dof_index);
compute_Cuthill_McKee(renumbering, dof_handler, reversed_numbering,
use_constraints, starting_indices);
const bool use_constraints,
const std::vector<types::global_dof_index> &starting_indices)
{
- // make the connection graph. in
- // more than 2d use an intermediate
- // compressed sparsity pattern
- // since the we don't have very
- // good estimates for
- // max_couplings_between_dofs() in
- // 3d and this then leads to
- // excessive memory consumption
+ // make the connection graph. in 2d/3d use an intermediate compressed
+ // sparsity pattern since the we don't have very good estimates for
+ // max_couplings_between_dofs() in 3d and this then leads to excessive
+ // memory consumption
//
- // note that if constraints are not
- // requested, then the
- // 'constraints' object will be
- // empty, and calling condense with
- // it is a no-op
+ // note that if constraints are not requested, then the 'constraints'
+ // object will be empty and nothing happens
ConstraintMatrix constraints;
if (use_constraints)
DoFTools::make_hanging_node_constraints (dof_handler, constraints);
constraints.close ();
+ IndexSet locally_owned = dof_handler.locally_owned_dofs();
SparsityPattern sparsity;
if (DH::dimension < 2)
{
else
{
CompressedSimpleSparsityPattern csp (dof_handler.n_dofs(),
- dof_handler.n_dofs());
+ dof_handler.n_dofs(),
+ dof_handler.locally_owned_dofs());
DoFTools::make_sparsity_pattern (dof_handler, csp, constraints);
- sparsity.copy_from (csp);
+
+ // If the index set is not complete, need to get indices in local
+ // index space.
+ if (dof_handler.locally_owned_dofs().n_elements() !=
+ dof_handler.locally_owned_dofs().size())
+ {
+ // Create sparsity pattern from csp by transferring its indices to
+ // processor-local index space and doing Cuthill-McKee there
+ std::vector<unsigned int> row_lengths(locally_owned.n_elements());
+ for (unsigned int i=0; i<locally_owned.n_elements(); ++i)
+ row_lengths[i] = csp.row_length(locally_owned.nth_index_in_set(i));
+ sparsity.reinit(locally_owned.n_elements(), locally_owned.n_elements(),
+ row_lengths);
+ std::vector<types::global_dof_index> row_entries;
+ for (unsigned int i=0; i<locally_owned.n_elements(); ++i)
+ {
+ const types::global_dof_index row = locally_owned.nth_index_in_set(i);
+ row_entries.resize(0);
+ for (CompressedSimpleSparsityPattern::row_iterator it =
+ csp.row_begin(row); it != csp.row_end(row); ++it)
+ if (*it != row && locally_owned.is_element(*it))
+ row_entries.push_back(locally_owned.index_within_set(*it));
+ sparsity.add_entries(i, row_entries.begin(), row_entries.end(),
+ true);
+ }
+ sparsity.compress();
+ }
+ else
+ sparsity.copy_from(csp);
}
// constraints are not needed anymore
if (reversed_numbering)
new_indices = Utilities::reverse_permutation (new_indices);
+
+ // convert indices back to global index space
+ for (std::size_t i=0; i<new_indices.size(); ++i)
+ new_indices[i] = locally_owned.nth_index_in_set(new_indices[i]);
}
tria->get_p4est_tree_to_coarse_cell_permutation() [c];
const typename DoFHandler<dim>::level_cell_iterator
- cell (tria, 0, coarse_cell_index, &dof_handler);
+ this_cell (tria, 0, coarse_cell_index, &dof_handler);
next_free = compute_hierarchical_recursive<dim> (next_free,
renumbering,
- cell,
+ this_cell,
locally_owned);
}
#else
component_numbering[i] = count++;
// First count the number of dofs in the current component.
+ constant_modes.clear ();
constant_modes.resize (n_components_selected, std::vector<bool>(n_selected_dofs,
false));
vertex_dof_count[vg] = 0;
// Create a mapping from all vertices to the ones used here
- unsigned int i=0;
+ unsigned int n_vertex_count=0;
for (unsigned int vg=0; vg<vertex_mapping.size(); ++vg)
if (vertex_dof_count[vg] != 0)
- vertex_mapping[vg] = i++;
+ vertex_mapping[vg] = n_vertex_count++;
// Compactify dof count
for (unsigned int vg=0; vg<vertex_mapping.size(); ++vg)
// Now that we have all the data, we reduce it to the part we actually
// want
- vertex_dof_count.resize(i);
+ vertex_dof_count.resize(n_vertex_count);
// At this point, the list of patches is ready. Now we enter the dofs
// into the sparsity pattern.
local_dof_indices_col(dofs_per_cell_col);
cell_row_child->get_dof_indices (local_dof_indices_row);
cell_col->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
+ for (unsigned int r=0; r<dofs_per_cell_row; ++r)
+ sparsity.add_entries (local_dof_indices_row[r],
local_dof_indices_col.begin(),
local_dof_indices_col.end());
}
local_dof_indices_col(dofs_per_cell_col);
cell_row->get_dof_indices (local_dof_indices_row);
cell_col_child->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
+ for (unsigned int r=0; r<dofs_per_cell_row; ++r)
+ sparsity.add_entries (local_dof_indices_row[r],
local_dof_indices_col.begin(),
local_dof_indices_col.end());
}
if (cell->neighbor_is_coarser(face))
continue;
- typename DH::face_iterator cell_face = cell->face(face);
const unsigned int
neighbor_face = cell->neighbor_of_neighbor(face);
if (cell->neighbor_is_coarser(face))
continue;
- typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
- cell_face = cell->face(face);
const unsigned int
neighbor_face = cell->neighbor_of_neighbor(face);
fe_system.cc
fe_tools.cc
fe_tools_interpolate.cc
+ fe_trace.cc
fe_values.cc
fe_values_inst2.cc
mapping_c1.cc
fe_system.inst.in
fe_tools.inst.in
fe_tools_interpolate.inst.in
+ fe_trace.inst.in
fe_values.decl.1.inst.in
fe_values.decl.2.inst.in
fe_values.impl.1.inst.in
for (unsigned int i=0; i<nc; ++i)
{
- if (!isotropic_restriction_only || ref_case==RefinementCase<dim>::isotropic_refinement)
+ if (this->restriction[ref_case-1][i].m() != this->dofs_per_cell
+ &&
+ (!isotropic_restriction_only || ref_case==RefinementCase<dim>::isotropic_refinement))
this->restriction[ref_case-1][i].reinit (this->dofs_per_cell,
this->dofs_per_cell);
- if (!isotropic_prolongation_only || ref_case==RefinementCase<dim>::isotropic_refinement)
+ if (this->prolongation[ref_case-1][i].m() != this->dofs_per_cell
+ &&
+ (!isotropic_prolongation_only || ref_case==RefinementCase<dim>::isotropic_refinement))
this->prolongation[ref_case-1][i].reinit (this->dofs_per_cell,
this->dofs_per_cell);
}
std::vector<ComponentMask>(FiniteElementData<dim>(
get_dpo_vector(degree),1, degree).dofs_per_cell, std::vector<bool>(1,true)))
{
- // Reinit the vectors of
- // restriction and prolongation
- // matrices to the right sizes
- this->reinit_restriction_and_prolongation_matrices();
-
- // Fill prolongation matrices with
- // embedding operators and
- // restriction with L2 projection
- //
- // we can call the respective
- // functions in the case
- // dim==spacedim, but they are not
- // currently implemented for the
- // codim-1 case. there's no harm
- // here, though, since these
- // matrices are independent of the
- // space dimension and so we can
- // copy them from the respective
- // elements (not cheap, but works)
- if (dim == spacedim)
- {
- FETools::compute_embedding_matrices (*this, this->prolongation);
- FETools::compute_projection_matrices (*this, this->restriction);
- }
- else
- {
- FE_DGQ<dim> tmp (degree);
- this->prolongation = tmp.prolongation;
- this->restriction = tmp.restriction;
- }
-
-
- // finally fill in support points
+ // fill in support points
if (degree == 0)
{
// constant elements, take
};
};
- // note: no face support points for
- // DG elements
+ // do not initialize embedding and restriction here. these matrices are
+ // initialized on demand in get_restriction_matrix and
+ // get_prolongation_matrix
+
+ // note: no face support points for DG elements
}
std::vector<ComponentMask>(FiniteElementData<dim>(
get_dpo_vector(points.size()-1),1, points.size()-1).dofs_per_cell, std::vector<bool>(1,true)))
{
- // Reinit the vectors of
- // restriction and prolongation
- // matrices to the right sizes
- this->reinit_restriction_and_prolongation_matrices();
- // Fill prolongation matrices with embedding operators
- FETools::compute_embedding_matrices<dim, double, spacedim> (*this, this->prolongation);
- // Fill restriction matrices with L2-projection
- FETools::compute_projection_matrices<dim, double, spacedim> (*this, this->restriction);
-
// Compute support points, which
// are the tensor product of the
// Lagrange interpolation points in
// the constructor.
Quadrature<dim> support_quadrature(points);
this->unit_support_points = support_quadrature.get_points();
+
+
+ // do not initialize embedding and restriction here. these matrices are
+ // initialized on demand in get_restriction_matrix and
+ // get_prolongation_matrix
}
+template <int dim, int spacedim>
+const FullMatrix<double> &
+FE_DGQ<dim,spacedim>
+::get_prolongation_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case) const
+{
+ Assert (refinement_case<RefinementCase<dim>::isotropic_refinement+1,
+ ExcIndexRange(refinement_case,0,RefinementCase<dim>::isotropic_refinement+1));
+ Assert (refinement_case!=RefinementCase<dim>::no_refinement,
+ ExcMessage("Prolongation matrices are only available for refined cells!"));
+ Assert (child<GeometryInfo<dim>::n_children(refinement_case),
+ ExcIndexRange(child,0,GeometryInfo<dim>::n_children(refinement_case)));
+
+ // initialization upon first request
+ if (this->prolongation[refinement_case-1][child].n() == 0)
+ {
+ Threads::Mutex::ScopedLock lock(this->mutex);
+
+ // if matrix got updated while waiting for the lock
+ if (this->prolongation[refinement_case-1][child].n() ==
+ this->dofs_per_cell)
+ return this->prolongation[refinement_case-1][child];
+
+ // now do the work. need to get a non-const version of data in order to
+ // be able to modify them inside a const function
+ FE_DGQ<dim,spacedim> &this_nonconst = const_cast<FE_DGQ<dim,spacedim>& >(*this);
+ if (refinement_case == RefinementCase<dim>::isotropic_refinement)
+ {
+ std::vector<std::vector<FullMatrix<double> > >
+ isotropic_matrices(RefinementCase<dim>::isotropic_refinement);
+ isotropic_matrices.back().
+ resize(GeometryInfo<dim>::n_children(RefinementCase<dim>(refinement_case)),
+ FullMatrix<double>(this->dofs_per_cell, this->dofs_per_cell));
+ if (dim == spacedim)
+ FETools::compute_embedding_matrices (*this, isotropic_matrices, true);
+ else
+ FETools::compute_embedding_matrices (FE_DGQ<dim>(this->degree),
+ isotropic_matrices, true);
+ this_nonconst.prolongation[refinement_case-1].swap(isotropic_matrices.back());
+ }
+ else
+ {
+ // must compute both restriction and prolongation matrices because
+ // we only check for their size and the reinit call initializes them
+ // all
+ this_nonconst.reinit_restriction_and_prolongation_matrices();
+ if (dim == spacedim)
+ {
+ FETools::compute_embedding_matrices (*this, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (*this, this_nonconst.restriction);
+ }
+ else
+ {
+ FE_DGQ<dim> tmp(this->degree);
+ FETools::compute_embedding_matrices (tmp, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (tmp, this_nonconst.restriction);
+ }
+ }
+ }
+
+ // finally return the matrix
+ return this->prolongation[refinement_case-1][child];
+}
+
+
+
+template <int dim, int spacedim>
+const FullMatrix<double> &
+FE_DGQ<dim,spacedim>
+::get_restriction_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case) const
+{
+ Assert (refinement_case<RefinementCase<dim>::isotropic_refinement+1,
+ ExcIndexRange(refinement_case,0,RefinementCase<dim>::isotropic_refinement+1));
+ Assert (refinement_case!=RefinementCase<dim>::no_refinement,
+ ExcMessage("Restriction matrices are only available for refined cells!"));
+ Assert (child<GeometryInfo<dim>::n_children(refinement_case),
+ ExcIndexRange(child,0,GeometryInfo<dim>::n_children(refinement_case)));
+
+ // initialization upon first request
+ if (this->restriction[refinement_case-1][child].n() == 0)
+ {
+ Threads::Mutex::ScopedLock lock(this->mutex);
+
+ // if matrix got updated while waiting for the lock...
+ if (this->restriction[refinement_case-1][child].n() ==
+ this->dofs_per_cell)
+ return this->restriction[refinement_case-1][child];
+
+ // now do the work. need to get a non-const version of data in order to
+ // be able to modify them inside a const function
+ FE_DGQ<dim,spacedim> &this_nonconst = const_cast<FE_DGQ<dim,spacedim>& >(*this);
+ if (refinement_case == RefinementCase<dim>::isotropic_refinement)
+ {
+ std::vector<std::vector<FullMatrix<double> > >
+ isotropic_matrices(RefinementCase<dim>::isotropic_refinement);
+ isotropic_matrices.back().
+ resize(GeometryInfo<dim>::n_children(RefinementCase<dim>(refinement_case)),
+ FullMatrix<double>(this->dofs_per_cell, this->dofs_per_cell));
+ if (dim == spacedim)
+ FETools::compute_projection_matrices (*this, isotropic_matrices, true);
+ else
+ FETools::compute_projection_matrices (FE_DGQ<dim>(this->degree),
+ isotropic_matrices, true);
+ this_nonconst.restriction[refinement_case-1].swap(isotropic_matrices.back());
+ }
+ else
+ {
+ // must compute both restriction and prolongation matrices because
+ // we only check for their size and the reinit call initializes them
+ // all
+ this_nonconst.reinit_restriction_and_prolongation_matrices();
+ if (dim == spacedim)
+ {
+ FETools::compute_embedding_matrices (*this, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (*this, this_nonconst.restriction);
+ }
+ else
+ {
+ FE_DGQ<dim> tmp(this->degree);
+ FETools::compute_embedding_matrices (tmp, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (tmp, this_nonconst.restriction);
+ }
+ }
+ }
+
+ // finally return the matrix
+ return this->restriction[refinement_case-1][child];
+}
+
+
+
template <int dim, int spacedim>
bool
FE_DGQ<dim, spacedim>::hp_constraints_are_implemented () const
// (==face 0 in some sense), the
// second on face 1:
return (((shape_index == 0) && (face_index == 0)) ||
- ((shape_index == 1) && (face_index == 1)));
+ ((shape_index == this->degree) && (face_index == 1)));
};
case 2:
+// ----------------------------- FE_FaceQ<1,spacedim> ------------------------
+
+template <int spacedim>
+FE_FaceQ<1,spacedim>::FE_FaceQ (const unsigned int degree)
+ :
+ FiniteElement<1,spacedim> (FiniteElementData<1>(get_dpo_vector(degree), 1, degree, FiniteElementData<1>::L2),
+ std::vector<bool>(1,true),
+ std::vector<ComponentMask> (1, ComponentMask(1,true)))
+{
+ this->unit_face_support_points.resize(1);
+
+ // initialize unit support points (this makes it possible to assign initial
+ // values to FE_FaceQ)
+ this->unit_support_points.resize(GeometryInfo<1>::faces_per_cell);
+ this->unit_support_points[1] = Point<1>(1.);
+}
+
+
+
+template <int spacedim>
+FiniteElement<1,spacedim> *
+FE_FaceQ<1,spacedim>::clone() const
+{
+ return new FE_FaceQ<1,spacedim>(this->degree);
+}
+
+
+
+template <int spacedim>
+std::string
+FE_FaceQ<1,spacedim>::get_name () const
+{
+ // note that the FETools::get_fe_from_name function depends on the
+ // particular format of the string this function returns, so they have to be
+ // kept in synch
+ std::ostringstream namebuf;
+ namebuf << "FE_FaceQ<1>(" << this->degree << ")";
+
+ return namebuf.str();
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::
+get_face_interpolation_matrix (const FiniteElement<1,spacedim> &source_fe,
+ FullMatrix<double> &interpolation_matrix) const
+{
+ get_subface_interpolation_matrix (source_fe, numbers::invalid_unsigned_int,
+ interpolation_matrix);
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::
+get_subface_interpolation_matrix (const FiniteElement<1,spacedim> &x_source_fe,
+ const unsigned int subface,
+ FullMatrix<double> &interpolation_matrix) const
+{
+ Assert (interpolation_matrix.n() == this->dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.n(),
+ this->dofs_per_face));
+ Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.m(),
+ x_source_fe.dofs_per_face));
+ interpolation_matrix(0,0) = 1.;
+}
+
+
+
+template <int spacedim>
+bool
+FE_FaceQ<1,spacedim>::has_support_on_face (
+ const unsigned int shape_index,
+ const unsigned int face_index) const
+{
+ AssertIndexRange(shape_index, 2);
+ return (face_index == shape_index);
+}
+
+
+
+template <int spacedim>
+std::vector<unsigned int>
+FE_FaceQ<1,spacedim>::get_dpo_vector (const unsigned int)
+{
+ std::vector<unsigned int> dpo(2, 0U);
+ dpo[0] = 1;
+ return dpo;
+}
+
+
+
+template <int spacedim>
+bool
+FE_FaceQ<1,spacedim>::hp_constraints_are_implemented () const
+{
+ return true;
+}
+
+
+
+template <int spacedim>
+FiniteElementDomination::Domination
+FE_FaceQ<1,spacedim>::
+compare_for_face_domination (const FiniteElement<1,spacedim> &fe_other) const
+{
+ return FiniteElementDomination::no_requirements;
+}
+
+
+
+template <int spacedim>
+Table<2,bool>
+FE_FaceQ<1,spacedim>::get_constant_modes () const
+{
+ Table<2,bool> constant_modes(1, this->dofs_per_cell);
+ for (unsigned int i=0; i<this->dofs_per_cell; ++i)
+ constant_modes(0,i) = true;
+ return constant_modes;
+}
+
+
+
+template <int spacedim>
+UpdateFlags
+FE_FaceQ<1,spacedim>::update_once (const UpdateFlags) const
+{
+ return update_default;
+}
+
+
+
+template <int spacedim>
+UpdateFlags
+FE_FaceQ<1,spacedim>::update_each (const UpdateFlags flags) const
+{
+ UpdateFlags out = flags & update_values;
+ if (flags & update_gradients)
+ out |= update_gradients | update_covariant_transformation;
+ if (flags & update_hessians)
+ out |= update_hessians | update_covariant_transformation;
+ if (flags & update_cell_normal_vectors)
+ out |= update_cell_normal_vectors | update_JxW_values;
+
+ return out;
+}
+
+
+
+template <int spacedim>
+typename Mapping<1,spacedim>::InternalDataBase *
+FE_FaceQ<1,spacedim>::get_data (
+ const UpdateFlags,
+ const Mapping<1,spacedim> &,
+ const Quadrature<1> &) const
+{
+ return new typename Mapping<1,spacedim>::InternalDataBase;
+}
+
+
+template <int spacedim>
+typename Mapping<1,spacedim>::InternalDataBase *
+FE_FaceQ<1,spacedim>::get_face_data (
+ const UpdateFlags update_flags,
+ const Mapping<1,spacedim> &,
+ const Quadrature<0>& quadrature) const
+{
+ // generate a new data object and initialize some fields
+ typename Mapping<1,spacedim>::InternalDataBase *data =
+ new typename Mapping<1,spacedim>::InternalDataBase;
+
+ // check what needs to be initialized only once and what on every
+ // cell/face/subface we visit
+ data->update_once = update_once(update_flags);
+ data->update_each = update_each(update_flags);
+ data->update_flags = data->update_once | data->update_each;
+
+ const UpdateFlags flags(data->update_flags);
+ const unsigned int n_q_points = quadrature.size();
+ AssertDimension(n_q_points, 1);
+
+ // No derivatives of this element are implemented.
+ if (flags & update_gradients || flags & update_hessians)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+ return data;
+}
+
+
+
+template <int spacedim>
+typename Mapping<1,spacedim>::InternalDataBase *
+FE_FaceQ<1,spacedim>::get_subface_data (
+ const UpdateFlags flags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<0>& quadrature) const
+{
+ return get_face_data (flags, mapping, quadrature);
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::fill_fe_values
+(const Mapping<1,spacedim> &,
+ const typename Triangulation<1,spacedim>::cell_iterator &,
+ const Quadrature<1> &,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ FEValuesData<1,spacedim> &,
+ CellSimilarity::Similarity &) const
+{
+ // Do nothing, since we do not have values in the interior
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::fill_fe_face_values (
+ const Mapping<1,spacedim> &,
+ const typename Triangulation<1,spacedim>::cell_iterator &,
+ const unsigned int face,
+ const Quadrature<0>& quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ typename Mapping<1,spacedim>::InternalDataBase &fedata,
+ FEValuesData<1,spacedim> &data) const
+{
+ const UpdateFlags flags(fedata.update_once | fedata.update_each);
+
+ const unsigned int foffset = face;
+ if (flags & update_values)
+ {
+ for (unsigned int k=0; k<this->dofs_per_cell; ++k)
+ data.shape_values(k,0) = 0.;
+ data.shape_values(foffset,0) = 1;
+ }
+}
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::fill_fe_subface_values (
+ const Mapping<1,spacedim> &,
+ const typename Triangulation<1,spacedim>::cell_iterator &,
+ const unsigned int ,
+ const unsigned int ,
+ const Quadrature<0>& ,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ FEValuesData<1,spacedim> &) const
+{
+ Assert(false, ExcMessage("Should not fille subface values in 1D"));
+}
+
+
+
// --------------------------------------- FE_FaceP --------------------------
template <int dim, int spacedim>
{}
+
template <int dim, int spacedim>
FiniteElement<dim,spacedim> *
FE_FaceP<dim,spacedim>::clone() const
}
+
template <int dim, int spacedim>
std::string
FE_FaceP<dim,spacedim>::get_name () const
+template <int spacedim>
+FE_FaceP<1,spacedim>::FE_FaceP (const unsigned int degree)
+ :
+ FE_FaceQ<1,spacedim> (degree)
+{}
+
+
+
+template <int spacedim>
+std::string
+FE_FaceP<1,spacedim>::get_name () const
+{
+ // note that the FETools::get_fe_from_name function depends on the
+ // particular format of the string this function returns, so they have to be
+ // kept in synch
+ std::ostringstream namebuf;
+ namebuf << "FE_FaceP<1>(" << this->degree << ")";
+
+ return namebuf.str();
+}
+
+
+
// explicit instantiations
#include "fe_face.inst"
template class FE_PolyFace<TensorProductPolynomials<deal_II_dimension-1> >;
template class FE_PolyFace<PolynomialSpace<deal_II_dimension-1>, deal_II_dimension>;
//template class FE_PolyFace<PolynomialsP<deal_II_dimension>, deal_II_dimension>;
- template class FE_FaceQ<deal_II_dimension>;
- template class FE_FaceP<deal_II_dimension>;
#endif
+ template class FE_FaceQ<deal_II_dimension,deal_II_dimension>;
+ template class FE_FaceP<deal_II_dimension,deal_II_dimension>;
}
// Initialize quadratures to obtain
// quadrature points later on.
const QGauss<dim - 1> reference_edge_quadrature (degree + 1);
- const unsigned int &
- n_edge_points = reference_edge_quadrature.size ();
+ const unsigned int n_edge_points = reference_edge_quadrature.size ();
const unsigned int n_boundary_points
= GeometryInfo<dim>::lines_per_cell * n_edge_points;
- const Quadrature<dim> &edge_quadrature
+ const Quadrature<dim> edge_quadrature
= QProjector<dim>::project_to_all_faces (reference_edge_quadrature);
this->generalized_face_support_points.resize (n_edge_points);
{
// In this case we only need support points
// on the faces of a cell.
- const Quadrature<dim> &edge_quadrature
- = QProjector<dim>::project_to_all_faces
- (reference_edge_quadrature);
-
this->generalized_support_points.resize (n_boundary_points);
for (unsigned int line = 0;
{
// if one of the base elements has no support points, then it makes no sense
// to define support points for the composed element, so return an empty
- // array to demonstrate that fact
+ // array to demonstrate that fact. Note that we ignore FE_Nothing in this logic.
for (unsigned int base_el=0; base_el<this->n_base_elements(); ++base_el)
- if (!base_element(base_el).has_support_points())
+ if (!base_element(base_el).has_support_points() && base_element(base_el).dofs_per_cell!=0)
{
this->unit_support_points.resize(0);
return;
= typename FiniteElementData<dim>::Conformity();
{
unsigned int index = 0;
- for (unsigned int index=0; index<fes.size(); ++index)
+ for (index=0; index<fes.size(); ++index)
if (multiplicities[index]>0)
{
total_conformity = fes[index]->conforming_space;
element.n_blocks()));
types::global_dof_index k=0;
- unsigned int i=0;
+ unsigned int count=0;
for (unsigned int b=0; b<element.n_base_elements(); ++b)
for (unsigned int m=0; m<element.element_multiplicity(b); ++m)
{
- block_data[i++] = (return_start_indices)
+ block_data[count++] = (return_start_indices)
? k
: (element.base_element(b).n_dofs_per_cell());
k += element.base_element(b).n_dofs_per_cell();
}
- Assert (i == element.n_blocks(), ExcInternalError());
+ Assert (count == element.n_blocks(), ExcInternalError());
std::vector<types::global_dof_index> start_indices(block_data.size());
k = 0;
// shape value on the cell.
std::vector<unsigned int> face_c_dofs(n);
std::vector<unsigned int> face_f_dofs(n);
- unsigned int k=0;
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
- {
- const unsigned int offset_c = GeometryInfo<dim>::face_to_cell_vertices(face_coarse, i)
- *fe.dofs_per_vertex;
- const unsigned int offset_f = GeometryInfo<dim>::face_to_cell_vertices(face_fine, i)
- *fe.dofs_per_vertex;
- for (unsigned int j=0; j<fe.dofs_per_vertex; ++j)
- {
- face_c_dofs[k] = offset_c + j;
- face_f_dofs[k] = offset_f + j;
- ++k;
- }
- }
- for (unsigned int i=1; i<=GeometryInfo<dim>::lines_per_face; ++i)
- {
- const unsigned int offset_c = fe.first_line_index
- + GeometryInfo<dim>::face_to_cell_lines(face_coarse, i-1)
- *fe.dofs_per_line;
- const unsigned int offset_f = fe.first_line_index
- + GeometryInfo<dim>::face_to_cell_lines(face_fine, i-1)
- *fe.dofs_per_line;
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
- {
- face_c_dofs[k] = offset_c + j;
- face_f_dofs[k] = offset_f + j;
- ++k;
- }
- }
- for (unsigned int i=1; i<=GeometryInfo<dim>::quads_per_face; ++i)
- {
- const unsigned int offset_c = fe.first_quad_index
- + face_coarse
- *fe.dofs_per_quad;
- const unsigned int offset_f = fe.first_quad_index
- + face_fine
- *fe.dofs_per_quad;
- for (unsigned int j=0; j<fe.dofs_per_quad; ++j)
- {
- face_c_dofs[k] = offset_c + j;
- face_f_dofs[k] = offset_f + j;
- ++k;
- }
- }
- Assert (k == fe.dofs_per_face, ExcInternalError());
+ {
+ unsigned int face_dof=0;
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
+ {
+ const unsigned int offset_c = GeometryInfo<dim>::face_to_cell_vertices(face_coarse, i)
+ *fe.dofs_per_vertex;
+ const unsigned int offset_f = GeometryInfo<dim>::face_to_cell_vertices(face_fine, i)
+ *fe.dofs_per_vertex;
+ for (unsigned int j=0; j<fe.dofs_per_vertex; ++j)
+ {
+ face_c_dofs[face_dof] = offset_c + j;
+ face_f_dofs[face_dof] = offset_f + j;
+ ++face_dof;
+ }
+ }
+ for (unsigned int i=1; i<=GeometryInfo<dim>::lines_per_face; ++i)
+ {
+ const unsigned int offset_c = fe.first_line_index
+ + GeometryInfo<dim>::face_to_cell_lines(face_coarse, i-1)
+ *fe.dofs_per_line;
+ const unsigned int offset_f = fe.first_line_index
+ + GeometryInfo<dim>::face_to_cell_lines(face_fine, i-1)
+ *fe.dofs_per_line;
+ for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ {
+ face_c_dofs[face_dof] = offset_c + j;
+ face_f_dofs[face_dof] = offset_f + j;
+ ++face_dof;
+ }
+ }
+ for (unsigned int i=1; i<=GeometryInfo<dim>::quads_per_face; ++i)
+ {
+ const unsigned int offset_c = fe.first_quad_index
+ + face_coarse
+ *fe.dofs_per_quad;
+ const unsigned int offset_f = fe.first_quad_index
+ + face_fine
+ *fe.dofs_per_quad;
+ for (unsigned int j=0; j<fe.dofs_per_quad; ++j)
+ {
+ face_c_dofs[face_dof] = offset_c + j;
+ face_f_dofs[face_dof] = offset_f + j;
+ ++face_dof;
+ }
+ }
+ Assert (face_dof == fe.dofs_per_face, ExcInternalError());
+ }
// Set up meshes, one with a single
// reference cell and refine it once
template <int dim>
void
- hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe,
- std::vector<unsigned int> &h2l)
+ hierarchic_to_lexicographic_numbering (unsigned int degree, std::vector<unsigned int>& h2l)
{
- Assert (h2l.size() == fe.dofs_per_cell,
- ExcDimensionMismatch (h2l.size(), fe.dofs_per_cell));
- h2l = hierarchic_to_lexicographic_numbering (fe);
- }
-
+ // number of support points in each
+ // direction
+ const unsigned int n = degree+1;
+ unsigned int dofs_per_cell = n;
+ for (unsigned int i=1;i<dim;++i)
+ dofs_per_cell *= n;
- template <int dim>
- std::vector<unsigned int>
- hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe)
- {
- Assert (fe.n_components() == 1, ExcInvalidFE());
-
- std::vector<unsigned int> h2l (fe.dofs_per_cell);
+ // Assert size maches degree
+ AssertDimension (h2l.size(), dofs_per_cell);
- const unsigned int dofs_per_cell = fe.dofs_per_cell;
// polynomial degree
- const unsigned int degree = fe.dofs_per_line+1;
- // number of grid points in each direction
- const unsigned int n = degree+1;
+ const unsigned int dofs_per_line = degree - 1;
// the following lines of code are somewhat odd, due to the way the
// hierarchic numbering is organized. if someone would really want to
h2l[next_index++] = n*n-1;
// left line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (1+i)*n;
// right line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (2+i)*n-1;
// bottom line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = 1+i;
// top line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n*(n-1)+i+1;
// inside quad
- Assert (fe.dofs_per_quad == fe.dofs_per_line*fe.dofs_per_line,
- ExcInternalError());
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = n*(i+1)+j+1;
- Assert (next_index == fe.dofs_per_cell, ExcInternalError());
+ Assert (next_index == dofs_per_cell, ExcInternalError());
break;
}
h2l[next_index++] = (n*n+n+1)*degree; // 7
// line 0
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (i+1)*n;
// line 1
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n-1+(i+1)*n;
// line 2
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = 1+i;
// line 3
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = 1+i+n*(n-1);
// line 4
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (n-1)*n*n+(i+1)*n;
// line 5
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (n-1)*(n*n+1)+(i+1)*n;
// line 6
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n*n*(n-1)+i+1;
// line 7
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n*n*(n-1)+i+1+n*(n-1);
// line 8
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (i+1)*n*n;
// line 9
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n-1+(i+1)*n*n;
// line 10
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (i+1)*n*n+n*(n-1);
// line 11
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n-1+(i+1)*n*n+n*(n-1);
// inside quads
- Assert (fe.dofs_per_quad == fe.dofs_per_line*fe.dofs_per_line,
- ExcInternalError());
// face 0
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (i+1)*n*n+n*(j+1);
// face 1
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (i+1)*n*n+n-1+n*(j+1);
// face 2, note the orientation!
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (j+1)*n*n+i+1;
// face 3, note the orientation!
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (j+1)*n*n+n*(n-1)+i+1;
// face 4
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = n*(i+1)+j+1;
// face 5
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (n-1)*n*n+n*(i+1)+j+1;
// inside hex
- Assert (fe.dofs_per_hex == fe.dofs_per_quad*fe.dofs_per_line,
- ExcInternalError());
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
- for (unsigned int k=0; k<fe.dofs_per_line; ++k)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
+ for (unsigned int k=0; k<dofs_per_line; ++k)
h2l[next_index++] = n*n*(i+1)+n*(j+1)+k+1;
- Assert (next_index == fe.dofs_per_cell, ExcInternalError());
+ Assert (next_index == dofs_per_cell, ExcInternalError());
break;
}
default:
Assert (false, ExcNotImplemented());
}
+ }
- return h2l;
+
+
+ template <int dim>
+ void
+ hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe,
+ std::vector<unsigned int> &h2l)
+ {
+ Assert (h2l.size() == fe.dofs_per_cell,
+ ExcDimensionMismatch (h2l.size(), fe.dofs_per_cell));
+ hierarchic_to_lexicographic_numbering<dim> (fe.dofs_per_line+1, h2l);
}
+ template <int dim>
+ std::vector<unsigned int>
+ hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe)
+ {
+ Assert (fe.n_components() == 1, ExcInvalidFE());
+ std::vector<unsigned int> h2l(fe.dofs_per_cell);
+ hierarchic_to_lexicographic_numbering<dim> (fe.dofs_per_line+1, h2l);
+ return (h2l);
+ }
+
template <int dim>
void
lexicographic_to_hierarchic_numbering (const FiniteElementData<dim> &fe,
FullMatrix<double> &);
#endif
+ template
+ void
+ hierarchic_to_lexicographic_numbering<deal_II_dimension>
+ (unsigned int,
+ std::vector<unsigned int> &);
+
template
void
hierarchic_to_lexicographic_numbering<deal_II_dimension>
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2000 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/grid/tria.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/dofs/dof_accessor.h>
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/fe/fe_poly_face.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/function.h>
+#include <deal.II/numerics/vector_tools.h>
+#include <deal.II/numerics/matrix_tools.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/compressed_sparsity_pattern.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/data_out_faces.h>
+#include <fstream>
+#include <iostream>
+
+
+#include <deal.II/fe/fe_face.h>
+#include <deal.II/fe/fe_poly_face.templates.h>
+#include <sstream>
+
+DEAL_II_NAMESPACE_OPEN
+
+/** FE-Class for continuous face functions
+* adaption of FE_Q and FE_FaceQ
+*/
+
+template <int dim, int spacedim=dim>
+class FE_TraceQ : public FE_PolyFace<TensorProductPolynomials<dim-1>, dim, spacedim>
+{
+ public:
+ /**
+ * Constructor for tensor product
+ * polynomials of degree
+ * <tt>p</tt>. The shape
+ * functions created using this
+ * constructor correspond to
+ * Legendre polynomials in each
+ * coordinate direction.
+ */
+ FE_TraceQ(unsigned int p);
+
+ virtual FiniteElement<dim,spacedim>* clone() const;
+
+ /**
+ * Return a string that uniquely
+ * identifies a finite
+ * element. This class returns
+ * <tt>FE_DGQ<dim>(degree)</tt> , with
+ * <tt>dim</tt> and <tt>degree</tt>
+ * replaced by appropriate
+ * values.
+ */
+ virtual std::string get_name () const;
+
+ /**
+ * Check for non-zero values on a face.
+ *
+ * This function returns
+ * @p true, if the shape
+ * function @p shape_index has
+ * non-zero values on the face
+ * @p face_index.
+ *
+ * Implementation of the
+ * interface in
+ * FiniteElement
+ */
+ virtual bool has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const;
+
+ private:
+ /**
+ * Return vector with dofs per
+ * vertex, line, quad, hex.
+ */
+ static std::vector<unsigned int> get_dpo_vector (const unsigned int deg);
+};
+
+
+template <int dim, int spacedim>
+FE_TraceQ<dim,spacedim>::FE_TraceQ (const unsigned int degree)
+ :
+ FE_PolyFace<TensorProductPolynomials<dim-1>, dim, spacedim> (
+ TensorProductPolynomials<dim-1>(Polynomials::LagrangeEquidistant::generate_complete_basis(degree)),
+ FiniteElementData<dim>(get_dpo_vector(degree), 1, degree, FiniteElementData<dim>::L2),
+ std::vector<bool>(1,true))
+{
+ Assert (degree > 0,
+ ExcMessage ("FE_Trace can only be used for polynomial degrees "
+ "greater than zero"));
+ std::vector<unsigned int> renumber (this->dofs_per_face);
+ FETools::hierarchic_to_lexicographic_numbering<dim-1> (degree, renumber);
+ this->poly_space.set_numbering(renumber);
+}
+
+
+template <int dim, int spacedim>
+FiniteElement<dim,spacedim>*
+FE_TraceQ<dim,spacedim>::clone() const
+{
+ return new FE_TraceQ<dim,spacedim>(this->degree);
+}
+
+
+template <int dim, int spacedim>
+std::string
+FE_TraceQ<dim,spacedim>::get_name () const
+{
+ // note that the
+ // FETools::get_fe_from_name
+ // function depends on the
+ // particular format of the string
+ // this function returns, so they
+ // have to be kept in synch
+
+ std::ostringstream namebuf;
+ namebuf << "FE_TraceQ<" << dim << ">(" << this->degree << ")";
+
+ return namebuf.str();
+}
+
+template <int dim, int spacedim>
+bool
+FE_TraceQ<dim,spacedim>::has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const
+{
+ Assert (shape_index < this->dofs_per_cell,
+ ExcIndexRange (shape_index, 0, this->dofs_per_cell));
+ Assert (face_index < GeometryInfo<dim>::faces_per_cell,
+ ExcIndexRange (face_index, 0, GeometryInfo<dim>::faces_per_cell));
+
+ // let's see whether this is a
+ // vertex
+ if (shape_index < this->first_line_index)
+ {
+ // for Q elements, there is
+ // one dof per vertex, so
+ // shape_index==vertex_number. check
+ // whether this vertex is
+ // on the given face. thus,
+ // for each face, give a
+ // list of vertices
+ const unsigned int vertex_no = shape_index;
+ Assert (vertex_no < GeometryInfo<dim>::vertices_per_cell,
+ ExcInternalError());
+
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_face; ++v)
+ if (GeometryInfo<dim>::face_to_cell_vertices(face_index, v) == vertex_no)
+ return true;
+
+ return false;
+ }
+ else if (shape_index < this->first_quad_index)
+ // ok, dof is on a line
+ {
+ const unsigned int line_index
+ = (shape_index - this->first_line_index) / this->dofs_per_line;
+ Assert (line_index < GeometryInfo<dim>::lines_per_cell,
+ ExcInternalError());
+
+ // in 2d, the line is the
+ // face, so get the line
+ // index
+ if (dim == 2)
+ return (line_index == face_index);
+ else if (dim == 3)
+ {
+ // see whether the
+ // given line is on the
+ // given face.
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
+ if (GeometryInfo<3>::face_to_cell_lines(face_index, l) == line_index)
+ return true;
+
+ return false;
+ }
+ else
+ Assert (false, ExcNotImplemented());
+ }
+ else if (shape_index < this->first_hex_index)
+ // dof is on a quad
+ {
+ const unsigned int quad_index
+ = (shape_index - this->first_quad_index) / this->dofs_per_quad;
+ Assert (static_cast<signed int>(quad_index) <
+ static_cast<signed int>(GeometryInfo<dim>::quads_per_cell),
+ ExcInternalError());
+
+ // in 2d, cell bubble are
+ // zero on all faces. but
+ // we have treated this
+ // case above already
+ Assert (dim != 2, ExcInternalError());
+
+ // in 3d,
+ // quad_index=face_index
+ if (dim == 3)
+ return (quad_index == face_index);
+ else
+ Assert (false, ExcNotImplemented());
+ }
+ else
+ // dof on hex
+ {
+ // can only happen in 3d,
+ // but this case has
+ // already been covered
+ // above
+ Assert (false, ExcNotImplemented());
+ return false;
+ }
+
+ // we should not have gotten here
+ Assert (false, ExcInternalError());
+ return false;
+}
+
+template <int dim, int spacedim>
+std::vector<unsigned int>
+FE_TraceQ<dim,spacedim>::get_dpo_vector (const unsigned int deg)
+{
+ AssertThrow(deg>0,ExcMessage("FE_TraceQ needs to be of degree > 0."));
+ std::vector<unsigned int> dpo(dim+1, 1U);
+ dpo[dim]=0;
+ dpo[0]=1;
+ for (unsigned int i=1;i<dim;++i)
+ dpo[i] = dpo[i-1]*(deg-1);
+ return dpo;
+}
+
+// explicit instantiations
+#include "fe_trace.inst"
+
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2000 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+for (deal_II_dimension : DIMENSIONS)
+ {
+#if deal_II_dimension > 1
+ template class FE_TraceQ<deal_II_dimension>;
+#endif
+ }
cell->face(i)->set_boundary_indicator(1);
for (unsigned int j=0; j<GeometryInfo<3>::lines_per_face; ++j)
{
- const Point<3> vertices[2]
+ const Point<3> line_vertices[2]
= { cell->face(i)->line(j)->vertex(0),
cell->face(i)->line(j)->vertex(1)
};
- if ((std::fabs(vertices[0].distance(center)-radius) >
+ if ((std::fabs(line_vertices[0].distance(center)-radius) >
1e-5*radius)
||
- (std::fabs(vertices[1].distance(center)-radius) >
+ (std::fabs(line_vertices[1].distance(center)-radius) >
1e-5*radius))
cell->face(i)->line(j)->set_boundary_indicator(1);
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
std::map<int, int> quad_indices; // # quad in unv (key) ---> # quad in deal.II (value)
std::map<int, int> line_indices; // # line in unv(key) ---> # line in deal.II (value)
- unsigned int no_vertices, no_quads=0,no_lines=0;
+ unsigned int no_vertices, no_quads=0, no_lines=0;
std::string keyword;
in >> keyword;
- unsigned int total_cells, no_cells = 0, type, j = 0;// declaring counters, refer to the order of declaring variables for an idea of what is what!
+ unsigned int total_cells, no_cells = 0, type;// declaring counters, refer to the order of declaring variables for an idea of what is what!
///////////////////Processing the CELLS section that contains cells(cells) and bound_quads(subcelldata)///////////////////////
cells.push_back(CellData<dim>());
- for (j = 0; j < type; j++) //loop to feed data
+ for (unsigned int j = 0; j < type; j++) //loop to feed data
in >> cells.back().vertices[j];
cells.back().material_id = 0;
- for (j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
{
cells.back().vertices[j] = vertex_indices[cells.back().vertices[j]];
}
{
subcelldata.boundary_quads.push_back(CellData<2>());
- int no_quads = 0;
- for (j = 0; j < type; j++) //loop to feed the data to the boundary
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data to the boundary
{
in >> subcelldata.boundary_quads.back().vertices[j];
}
{
subcelldata.boundary_quads.back().vertices[j] = vertex_indices[subcelldata.boundary_quads.back().vertices[j]];
}
- quad_indices[count] = count + 1;
+ quad_indices[no_quads] = no_quads + 1;
no_quads++;
}
{
cells.push_back(CellData<dim>());
- for (j = 0; j < type; j++) //loop to feed data
+ for (unsigned int j = 0; j < type; j++) //loop to feed data
in >> cells.back().vertices[j];
cells.back().material_id = 0;
- for (j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
{
cells.back().vertices[j] = vertex_indices[cells.back().vertices[j]];
}
//If this is encountered, the pointer comes out of the loop
//and starts processing boundaries.
subcelldata.boundary_lines.push_back(CellData<1>());
- int no_lines = 0;
- for (j = 0; j < type; j++) //loop to feed the data to the boundary
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data to the boundary
{
in >> subcelldata.boundary_lines.back().vertices[j];
}
{
subcelldata.boundary_lines.back().vertices[j] = vertex_indices[subcelldata.boundary_lines.back().vertices[j]];
}
- line_indices[count] = count + 1;
+ line_indices[no_lines] = no_lines + 1;
no_lines++;
}
const unsigned int n_lines = (n_entities%2 == 0)?(n_entities/2):((n_entities+1)/2);
- for (unsigned int no_line = 0; no_line < n_lines; no_line++)
+ for (unsigned int line = 0; line < n_lines; line++)
{
unsigned int n_fragments;
- if (no_line == n_lines-1)
+ if (line == n_lines-1)
n_fragments = (n_entities%2 == 0)?(2):(1);
else
n_fragments = 2;
AssertThrow(n_vars>=dim,
ExcMessage("Tecplot file must contain at least one variable for each dimension"));
- for (unsigned int i=1; i<dim; ++i)
- AssertThrow(tecplot2deal[i]>0,
+ for (unsigned int d=1; d<dim; ++d)
+ AssertThrow(tecplot2deal[d]>0,
ExcMessage("Tecplot file must contain at least one variable for each dimension."));
}
else if (Utilities::match_at_string_start(entries[i],"ZONETYPE=ORDERED"))
#include <deal.II/grid/grid_out.h>
#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/exceptions.h>
#include <deal.II/base/point.h>
#include <deal.II/base/quadrature.h>
#include <deal.II/base/qprojector.h>
const bool label_material_id,
const bool label_subdomain_id,
const bool draw_colorbar,
- const bool draw_legend) :
- line_thickness(line_thickness),
- boundary_line_thickness(boundary_line_thickness),
- margin(margin),
- background(background),
- azimuth_angle(azimuth_angle),
- polar_angle(polar_angle),
- coloring(coloring),
- convert_level_number_to_height(convert_level_number_to_height),
- label_level_number(label_level_number),
- label_cell_index(label_cell_index),
- label_material_id(label_material_id),
- label_subdomain_id(label_subdomain_id),
- label_level_subdomain_id(false),
- draw_colorbar(draw_colorbar),
- draw_legend(draw_legend)
+ const bool draw_legend)
+ :
+ height(1000),
+ width(0),
+ line_thickness(line_thickness),
+ boundary_line_thickness(boundary_line_thickness),
+ margin(margin),
+ background(background),
+ azimuth_angle(azimuth_angle),
+ polar_angle(polar_angle),
+ coloring(coloring),
+ convert_level_number_to_height(convert_level_number_to_height),
+ level_height_factor(0.3f),
+ label_level_number(label_level_number),
+ label_cell_index(label_cell_index),
+ label_material_id(label_material_id),
+ label_subdomain_id(label_subdomain_id),
+ label_level_subdomain_id(false),
+ draw_colorbar(draw_colorbar),
+ draw_legend(draw_legend)
{}
MathGL::MathGL ()
// grid to 4000 and adapt the number of width
// elements with respect to the bounding box of
// the given triangulation.
- const unsigned int height = 4000; // TODO [CW]: consider other options, especially if the polar angle approaches 90°
- unsigned int width;
+ unsigned int height = svg_flags.height;
+ unsigned int width = svg_flags.width;
+ Assert (height != 0 || width != 0, ExcMessage("You have to set at least one of width and height"));
unsigned int margin_in_percent = 0;
if (svg_flags.margin || svg_flags.background == GridOutFlags::Svg::dealii)
// initial font size for cell labels
unsigned int cell_label_font_size;
- // font size for date, time, legend, and colorbar
- unsigned int font_size = static_cast<unsigned int>(.5 + (height/100.) * 1.75);
-
// get date and time
// time_t time_stamp;
// tm *now;
float x_dimension_perspective, y_dimension_perspective;
- Triangulation<2,2>::cell_iterator cell = tria.begin(), endc = tria.end();
-
// auxiliary variables for the bounding box and the range of cell levels
- double x_min = cell->vertex(0)[0];
- double x_max = cell->vertex(0)[0];
- double y_min = cell->vertex(0)[1];
- double y_max = cell->vertex(0)[1];
+ double x_min = tria.begin()->vertex(0)[0];
+ double x_max = tria.begin()->vertex(0)[0];
+ double y_min = tria.begin()->vertex(0)[1];
+ double y_max = tria.begin()->vertex(0)[1];
double x_dimension, y_dimension;
- min_level = cell->level();
- max_level = cell->level();
+ min_level = max_level = tria.begin()->level();
// auxiliary array for the materials being used (material ids 255 max.)
unsigned int materials[256];
// bounding box of the given triangulation and check
// the cells for material id, level number, subdomain id
// (, and level subdomain id).
- for (; cell != endc; ++cell)
+ for (Triangulation<2,2>::cell_iterator cell = tria.begin(); cell != tria.end(); ++cell)
{
for (unsigned int vertex_index = 0; vertex_index < 4; vertex_index++)
{
// determine the bounding box of the given triangulation on the projection plane of the camera viewing system
- cell = tria.begin();
- endc = tria.end();
-
- point[0] = cell->vertex(0)[0];
- point[1] = cell->vertex(0)[1];
+ point[0] = tria.begin()->vertex(0)[0];
+ point[1] = tria.begin()->vertex(0)[1];
point[2] = 0;
float min_level_min_vertex_distance = 0;
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)tria.begin()->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
y_max_perspective = projection_decomposition[1];
y_min_perspective = projection_decomposition[1];
- for (; cell != endc; ++cell)
+ for (Triangulation<2,2>::cell_iterator cell = tria.begin(); cell != tria.end(); ++cell)
{
point[0] = cell->vertex(0)[0];
point[1] = cell->vertex(0)[1];
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
x_dimension_perspective = x_max_perspective - x_min_perspective;
y_dimension_perspective = y_max_perspective - y_min_perspective;
- cell_label_font_size = static_cast<unsigned int>((int)(.5 + (height/100.) * 2.75) * 9. * (min_level_min_vertex_distance / std::min(x_dimension, y_dimension)));
-
-
// create the svg file with an internal style sheet
- width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
+ if (width == 0)
+ width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
+ else if (height == 0)
+ height = static_cast<unsigned int>(.5 + width * (y_dimension_perspective / x_dimension_perspective));
unsigned int additional_width = 0;
+ // font size for date, time, legend, and colorbar
+ unsigned int font_size = static_cast<unsigned int>(.5 + (height/100.) * 1.75);
+ cell_label_font_size = static_cast<unsigned int>((int)(.5 + (height/100.) * 2.75) * 9. * (min_level_min_vertex_distance / std::min(x_dimension, y_dimension)));
if (svg_flags.draw_legend && (svg_flags.label_level_number || svg_flags.label_cell_index || svg_flags.label_material_id || svg_flags.label_subdomain_id || svg_flags.label_level_subdomain_id ))
{
out << "]]></style>" << '\n' << '\n';
// background rectangle
- out << " <rect class=\"background\" width=\"" << width + additional_width << "\" height=\"" << height << "\"/>" << '\n';
+ out << " <rect class=\"background\" width=\"" << width << "\" height=\"" << height << "\"/>" << '\n';
if (svg_flags.background == GridOutFlags::Svg::dealii)
{
for (unsigned int level_index = min_level; level_index <= max_level; level_index++)
{
- Triangulation<2,2>::cell_iterator cell = tria.begin(level_index), endc = tria.end(level_index);
+ Triangulation<2,2>::cell_iterator
+ cell = tria.begin(level_index),
+ endc = tria.end(level_index);
for (; cell != endc; ++cell)
{
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
float distance_to_camera = sqrt(pow(point[0] - camera_position[0], 2.) + pow(point[1] - camera_position[1], 2.) + pow(point[2] - camera_position[2], 2.));
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
case 2:
{
- typename dealii::Triangulation<dim>::active_cell_iterator
- cell=tria.begin_active(),
- endc=tria.end();
-
- for (; cell!=endc; ++cell)
+ for (typename dealii::Triangulation<dim>::active_cell_iterator
+ cell=tria.begin_active();
+ cell!=tria.end(); ++cell)
for (unsigned int line_no=0;
line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
{
// boundary faces and
// generate the info from
// them
- typename dealii::Triangulation<dim>::active_cell_iterator
- cell=tria.begin_active ();
- const typename dealii::Triangulation<dim>::active_cell_iterator
- end=tria.end ();
- for (; cell!=end; ++cell)
+ for (typename dealii::Triangulation<dim>::active_cell_iterator
+ cell=tria.begin_active();
+ cell!=tria.end(); ++cell)
for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
{
const typename dealii::Triangulation<dim>::face_iterator
// rotation to get the new
// cube
unsigned int temp[8];
- for (unsigned int i=0; i<8; ++i)
- temp[i] = the_cell.nodes[CubePermutations[perm_num][i]];
- for (unsigned int i=0; i<8; ++i)
- the_cell.nodes[i] = temp[i];
+ for (unsigned int v=0; v<8; ++v)
+ temp[v] = the_cell.nodes[CubePermutations[perm_num][v]];
+ for (unsigned int v=0; v<8; ++v)
+ the_cell.nodes[v] = temp[v];
}
}
} // namespace GridReordering3d
// is for.
if (!found && cells_searched < n_cells)
{
- find_active_cell_around_point_internal(container, searched_cells, adjacent_cells);
+ find_active_cell_around_point_internal<dim,Container,spacedim>
+ (container, searched_cells, adjacent_cells);
}
}
// the cells in adjacent_cells.
if (!found && cells_searched < n_cells)
{
- find_active_cell_around_point_internal(container, searched_cells, adjacent_cells);
+ find_active_cell_around_point_internal<dim,hp::DoFHandler,spacedim>
+ (container, searched_cells, adjacent_cells);
}
}
do
{
bool changed = false;
- typename Container<dim-1,spacedim>::active_cell_iterator
- cell = surface_mesh.begin_active(),
- endc = surface_mesh.end();
- for (; cell!=endc; ++cell)
+ for (typename Container<dim-1,spacedim>::active_cell_iterator
+ cell = surface_mesh.begin_active(); cell!=surface_mesh.end(); ++cell)
if (surface_to_volume_mapping[cell]->has_children() == true )
{
cell->set_refine_flag ();
const_cast<Triangulation<dim-1,spacedim>&>(get_tria(surface_mesh))
.execute_coarsening_and_refinement();
- typename Container<dim-1,spacedim>::cell_iterator
- cell = surface_mesh.begin(),
- endc = surface_mesh.end();
- for (; cell!=endc; ++cell)
- for (unsigned int c=0; c<cell->n_children(); c++)
- if (surface_to_volume_mapping.find(cell->child(c)) == surface_to_volume_mapping.end())
- surface_to_volume_mapping[cell->child(c)]
- = surface_to_volume_mapping[cell]->child(c);
+ for (typename Container<dim-1,spacedim>::cell_iterator
+ surface_cell = surface_mesh.begin(); surface_cell!=surface_mesh.end(); ++surface_cell)
+ for (unsigned int c=0; c<surface_cell->n_children(); c++)
+ if (surface_to_volume_mapping.find(surface_cell->child(c)) == surface_to_volume_mapping.end())
+ surface_to_volume_mapping[surface_cell->child(c)]
+ = surface_to_volume_mapping[surface_cell]->child(c);
}
else
break;
// not implemented at
// present for dim=3 or
// higher
+ // TODO: you can steal the code to do this from GridTools::transform()
Assert (dim<=2, ExcNotImplemented());
// compute where the common
for (unsigned int q=0; q<triangulation.faces->quads.cells.size(); ++q)
for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
{
- const int index=triangulation.faces->quads.cells[q].face(l);
- if (index==old_index_0)
+ const int this_index=triangulation.faces->quads.cells[q].face(l);
+ if (this_index==old_index_0)
triangulation.faces->quads.cells[q].set_face(l,new_index_0);
- else if (index==old_index_1)
+ else if (this_index==old_index_1)
triangulation.faces->quads.cells[q].set_face(l,new_index_1);
}
// now we have to copy
for (unsigned int h=0; h<triangulation.levels[l]->cells.cells.size(); ++h)
for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
{
- const int index=triangulation.levels[l]->cells.cells[h].face(q);
- if (index==switch_1_index)
+ const int face_index=triangulation.levels[l]->cells.cells[h].face(q);
+ if (face_index==switch_1_index)
triangulation.levels[l]->cells.cells[h].set_face(q,switch_2_index);
- else if (index==switch_2_index)
+ else if (face_index==switch_2_index)
triangulation.levels[l]->cells.cells[h].set_face(q,switch_1_index);
}
// now we have to copy
// at the outset of the
// next iteration) for
// refinement
- for (unsigned int line=0;
- line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (!cell->line(line)->has_children() &&
+ for (unsigned int l=0;
+ l<GeometryInfo<dim>::lines_per_cell; ++l)
+ if (!cell->line(l)->has_children() &&
(GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(),
- line)
+ l)
!=RefinementCase<1>::no_refinement))
- cell->line(line)->set_user_flag();
+ cell->line(l)->set_user_flag();
break;
}
Assert (d==0, ExcScalarAssignmentOnlyForZeroValue());
if (this->n_elements() != 0)
- std::fill (this->values.begin(), this->values.end(), number());
+ this->reset_values();
state = LAPACKSupport::matrix;
return *this;
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_rows(), ExcDimensionMismatch(this->n_cols(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_rows(), ExcDimensionMismatch(this->n_cols(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_rows(), ExcDimensionMismatch(this->n_rows(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_rows(), ExcDimensionMismatch(this->n_rows(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_cols(), ExcDimensionMismatch(this->n_cols(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_cols(), ExcDimensionMismatch(this->n_cols(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_cols(), ExcDimensionMismatch(this->n_rows(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_cols(), ExcDimensionMismatch(this->n_rows(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
Assert(state == lu, ExcState(state));
Assert(this->n_rows() == this->n_cols(),
LACExceptions::ExcNotQuadratic());
+ AssertDimension(this->n_rows(), v.size());
const char *trans = transposed ? &T : &N;
const int nn = this->n_cols();
Assert(state == lu, ExcState(state));
Assert(B.state == matrix, ExcState(state));
Assert(this->n_rows() == this->n_cols(), LACExceptions::ExcNotQuadratic());
+ AssertDimension(this->n_rows(), B.n_rows());
const char *trans = transposed ? &T : &N;
const int nn = this->n_cols();
}
-template<typename number, typename vnumber>
-const void *
-ProductSparseMatrix<number, vnumber>::get () const
-{
- return &*m1;
-}
-
-
template class ProductSparseMatrix<double, double>;
template class ProductSparseMatrix<double, float>;
template class ProductSparseMatrix<float, double>;
{
ForwardIterator it = begin;
bool has_larger_entries = false;
- std::size_t k=rowstart[row];
+ // skip diagonal
+ std::size_t k=rowstart[row]+store_diagonal_first_in_row;
for ( ; k<rowstart[row+1]; k++)
if (colnums[k] == invalid_entry)
break;
break;
}
if (has_larger_entries == false)
- for ( ; it != end; ++it, ++k)
+ for ( ; it != end; ++it)
{
+ if (store_diagonal_first_in_row && *it == row)
+ continue;
Assert (k <= rowstart[row+1],
ExcNotEnoughSpace(row, rowstart[row+1]-rowstart[row]));
- colnums[k] = *it;
+ colnums[k++] = *it;
}
else
// cannot just append the new range at the end, forward to the
// other function
- for (ForwardIterator it = begin; it != end; ++it)
- add (row, *it);
+ for (ForwardIterator p = begin; p != end; ++p)
+ add (row, *p);
}
}
else
- inline
void
SparseMatrix::compress (::dealii::VectorOperation::values operation)
{
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*this += v;
else
{
+ Assert (!has_ghost_elements(), ExcGhostsPresent());
AssertThrow (size() == v.size(),
ExcDimensionMismatch (size(), v.size()));
- Epetra_Import data_exchange (vector->Map(), v.vector->Map());
+ //HACK: For some reason the following doesn't work properly, so do it manually
+ // Epetra_Import data_exchange (vector->Map(), v.vector->Map());
+ // int ierr = vector->Import(*v.vector, data_exchange, Add);
+ // AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ // last_action = Add;
- int ierr = vector->Import(*v.vector, data_exchange, Add);
+ Epetra_MultiVector dummy(vector->Map(), 1, false);
+ Epetra_Import data_exchange (dummy.Map(), v.vector->Map());
+
+ int ierr = dummy.Import(*v.vector, data_exchange, Insert);
AssertThrow (ierr == 0, ExcTrilinosError(ierr));
- last_action = Insert;
+ ierr = vector->Update (1.0, dummy, 1.0);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
}
}
if (level_boundary)
{
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += fe.dofs_per_face;
continue;
}
// here.
if (flux_coupling != DoFTools::none)
{
- unsigned int increment = nfe.dofs_per_cell - nfe.dofs_per_face;
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += increment;
+ const unsigned int dof_increment = nfe.dofs_per_cell - nfe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += dof_increment;
}
// Do this only once per
// the coarse one.
neighbor_indices.resize(nfe.dofs_per_cell);
neighbor->get_mg_dof_indices(neighbor_indices);
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += nfe.dofs_per_face;
- for (unsigned int i=0; i<nfe.dofs_per_cell; ++i)
- row_lengths[neighbor_indices[i]] += fe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += nfe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<nfe.dofs_per_cell; ++local_dof)
+ row_lengths[neighbor_indices[local_dof]] += fe.dofs_per_face;
}
}
user_flags_triangulation.load_user_flags(old_flags);
if (level_boundary)
{
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += fe.dofs_per_face;
continue;
}
// here.
for (unsigned int base=0; base<nfe.n_base_elements(); ++base)
for (unsigned int mult=0; mult<nfe.element_multiplicity(base); ++mult)
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- if (couple_face[fe_index](fe.system_to_block_index(i).first,
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ if (couple_face[fe_index](fe.system_to_block_index(local_dof).first,
nfe.first_block_of_base(base) + mult) != DoFTools::none)
{
- unsigned int increment = nfe.base_element(base).dofs_per_cell
- - nfe.base_element(base).dofs_per_face;
- row_lengths[cell_indices[i]] += increment;
+ const unsigned int dof_increment = nfe.base_element(base).dofs_per_cell
+ - nfe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[local_dof]] += dof_increment;
}
// Do this only once per
neighbor->get_mg_dof_indices(neighbor_indices);
for (unsigned int base=0; base<nfe.n_base_elements(); ++base)
for (unsigned int mult=0; mult<nfe.element_multiplicity(base); ++mult)
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- if (couple_cell[fe_index](fe.system_to_component_index(i).first,
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ if (couple_cell[fe_index](fe.system_to_component_index(local_dof).first,
nfe.first_block_of_base(base) + mult) != DoFTools::none)
- row_lengths[cell_indices[i]]
+ row_lengths[cell_indices[local_dof]]
+= nfe.base_element(base).dofs_per_face;
for (unsigned int base=0; base<fe.n_base_elements(); ++base)
for (unsigned int mult=0; mult<fe.element_multiplicity(base); ++mult)
- for (unsigned int i=0; i<nfe.dofs_per_cell; ++i)
- if (couple_cell[fe_index](nfe.system_to_component_index(i).first,
+ for (unsigned int local_dof=0; local_dof<nfe.dofs_per_cell; ++local_dof)
+ if (couple_cell[fe_index](nfe.system_to_component_index(local_dof).first,
fe.first_block_of_base(base) + mult) != DoFTools::none)
- row_lengths[neighbor_indices[i]]
+ row_lengths[neighbor_indices[local_dof]]
+= fe.base_element(base).dofs_per_face;
}
}
// first fill dof_data
for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
{
- const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values
+ const FEValuesBase<DH::dimension,DH::space_dimension> &this_fe_patch_values
= data.get_present_fe_values (dataset);
const unsigned int n_components =
- fe_patch_values.get_fe().n_components();
+ this_fe_patch_values.get_fe().n_components();
const DataPostprocessor<DH::space_dimension> *postprocessor=this->dof_data[dataset]->postprocessor;
// at each point there is only one component of value,
// gradient etc.
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
std::vector<Point<DH::space_dimension> > dummy_normals;
// at each point there is a vector valued function and its
// derivative...
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients_system);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians_system);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
std::vector<Point<DH::space_dimension> > dummy_normals;
// reasons.
if (n_components == 1)
{
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
for (unsigned int q=0; q<n_q_points; ++q)
patch.data(offset,q) = data.patch_values[q];
else
{
data.resize_system_vectors(n_components);
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
for (unsigned int component=0; component<n_components;
++component)
DataVectorType actual_type = type;
if (type == type_automatic)
{
+ // in the rare case that someone has a DGP(0) attached, we can not decide what she wants here:
+ Assert((dofs == 0) || (triangulation->n_active_cells() != dofs->n_dofs()),
+ ExcMessage("Unable to determine the type of vector automatically because the number of DoFs "
+ "is equal to the number of cells. Please specify DataVectorType."));
+
if (vec.size() == triangulation->n_active_cells())
actual_type = type_cell_data;
else
// first fill dof_data
for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
{
- const FEValuesBase<dimension> &fe_patch_values
+ const FEValuesBase<dimension> &this_fe_patch_values
= data.get_present_fe_values (dataset);
const unsigned int n_components
- = fe_patch_values.get_fe().n_components();
+ = this_fe_patch_values.get_fe().n_components();
const DataPostprocessor<dim> *postprocessor=this->dof_data[dataset]->postprocessor;
if (postprocessor != 0)
{
// thus does not depend on the number of components of the data
// vector
if (update_flags & update_normal_vectors)
- data.patch_normals=fe_patch_values.get_normal_vectors();
+ data.patch_normals=this_fe_patch_values.get_normal_vectors();
if (n_components == 1)
{
// at each point there is only one component of value,
// gradient etc.
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
postprocessor->
compute_derived_quantities_scalar(data.patch_values,
// derivative...
data.resize_system_vectors(n_components);
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients_system);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians_system);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
postprocessor->
compute_derived_quantities_vector(data.patch_values_system,
// reasons.
if (n_components == 1)
{
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
for (unsigned int q=0; q<n_q_points; ++q)
patch.data(offset,q) = data.patch_values[q];
else
{
data.resize_system_vectors(n_components);
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
for (unsigned int component=0; component<n_components;
++component)
// reinit fe values object...
x_fe_midpoint_value.reinit (neighbor);
- const FEValues<dim> &fe_midpoint_value
+ const FEValues<dim> &neighbor_fe_midpoint_value
= x_fe_midpoint_value.get_present_fe_values();
// ...and get the value of the
// solution...
const typename DerivativeDescription::ProjectedDerivative
neighbor_midpoint_value
- = DerivativeDescription::get_projected_derivative (fe_midpoint_value,
+ = DerivativeDescription::get_projected_derivative (neighbor_fe_midpoint_value,
solution, component);
// ...and the place where it lives
const Point<dim>
- neighbor_center = fe_midpoint_value.quadrature_point(0);
+ neighbor_center = neighbor_fe_midpoint_value.quadrature_point(0);
// vector for the
// write column headings
- std::map <std::string, std::vector <std::vector <double> > >::iterator
- data_store_begin = data_store.begin ();
to_gnuplot << "# <Key> ";
if (indep_names.size() > 0)
}
}
- for (; data_store_begin != data_store.end (); data_store_begin++)
+ for (std::map <std::string, std::vector <std::vector <double> > >::iterator
+ data_store_begin = data_store.begin (); data_store_begin != data_store.end (); ++data_store_begin)
{
typename std::map <std::string, ComponentMask>::iterator mask = component_mask.find(data_store_begin->first);
unsigned int n_stored = mask->second.n_selected_components();
// write data stored for the point
for (unsigned int key = 0; key < dataset_key.size (); key++)
{
- std::map <std::string, std::vector <std::vector <double> > >::iterator
- data_store_begin = data_store.begin ();
to_gnuplot << dataset_key[key];
for (unsigned int component = 0; component < n_indep; component++)
to_gnuplot << " " << independent_values[component][key];
}
- for (; data_store_begin != data_store.end (); data_store_begin++)
+ for (std::map <std::string, std::vector <std::vector <double> > >::iterator
+ data_store_begin = data_store.begin ();
+ data_store_begin != data_store.end (); ++data_store_begin)
{
typename std::map <std::string, ComponentMask>::iterator mask = component_mask.find(data_store_begin->first);
unsigned int n_stored = mask->second.n_selected_components();
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.9)
+INCLUDE(${DEAL_II_SOURCE_DIR}/cmake/setup_testsubproject.cmake)
+PROJECT(testsuite CXX)
+INCLUDE(${DEAL_II_TARGET_CONFIG})
+DEAL_II_PICKUP_TESTS()
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: named_data.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2000 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+#include "../tests.h"
+#include <deal.II/algorithms/any_data.h>
+#include <deal.II/base/logstream.h>
+
+#include <fstream>
+
+double d1 = 17.;
+
+void fill(AnyData& data)
+{
+ int i = 7;
+ data.add(i, " i 7");
+ data.add<double>(d1, " d 17.");
+ data.add<double*>(&d1, " d* 17.");
+ data.add<const double*>(&d1, "cd* 17.");
+ d1 = 18.;
+}
+
+
+void extract(const AnyData& data)
+{
+ // This set of tests with old functionality. Remove when deprecating
+ // index access
+ for (unsigned int i=0;i<data.size();++i)
+ deallog << i << '\t' << data.name(i) << std::endl;
+ deallog << data.name(0)
+ << '\t' << data.entry<int>(0) << std::endl;
+ deallog << data.name(1)
+ << '\t' << data.entry<double>(1) << std::endl;
+ deallog << data.name(2)
+ << '\t' << *data.entry<double*>(2) << std::endl;
+ deallog << data.name(3)
+ << '\t' << *data.entry<const double*>(3) << std::endl;
+
+ // From here on keep after deprecation
+ int i1 = data.entry<int>(" i 7");
+ const int i2 = data.entry<const int>(" i 7");
+ double d = data.entry<double>(" d 17.");
+ double* p2 = data.entry<double*>(" d* 17.");
+ const double * p3 = data.entry<const double*>("cd* 17.");
+
+ deallog << i1 << std::endl
+ << i2 << std::endl
+ << d << std::endl
+ << *p2 << std::endl
+ << *p3 << std::endl;
+ // try
+ // {
+ // double* p3a = data.entry<double*>("cd* 17.");
+ // deallog << p3a;
+ // }
+ // // catch(ExceptionBase e)
+ // // {
+ // // deallog << e.what() << std::endl;
+ // // }
+ // catch(...)
+ // {
+ // deallog << "Exception duly thrown" << std::endl;
+ // }
+
+}
+
+int main()
+{
+ deal_II_exceptions::disable_abort_on_exception();
+
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ AnyData data;
+ fill(data);
+ extract(data);
+}
--- /dev/null
+
+DEAL::0 i 7
+DEAL::1 d 17.
+DEAL::2 d* 17.
+DEAL::3 cd* 17.
+DEAL:: i 7 7
+DEAL:: d 17. 17.0000
+DEAL:: d* 17. 18.0000
+DEAL::cd* 17. 18.0000
+DEAL::7
+DEAL::7
+DEAL::17.0000
+DEAL::18.0000
+DEAL::18.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2008 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#include "../tests.h"
+#include <deal.II/algorithms/operator.h>
+#include <deal.II/algorithms/newton.h>
+#include <deal.II/numerics/vector_tools.h>
+#include <deal.II/base/named_data.h>
+
+
+//test computing square root of 2 with newton's method
+
+using namespace dealii;
+
+class SquareRoot : public Subscriptor
+{
+public:
+ void start_vector (Vector<double> &start) const;
+ void residual (AnyData &out, const AnyData &in);
+ void solve (AnyData &out, const AnyData &in);
+};
+
+class SquareRootResidual : public
+ Algorithms::Operator<Vector<double> >
+{
+ SmartPointer<SquareRoot, SquareRootResidual>
+ discretization;
+public:
+
+ SquareRootResidual(SquareRoot &problem)
+ : discretization(&problem)
+ {}
+
+ virtual void operator ()(AnyData &out, const AnyData &in)
+ {
+ discretization->residual(out,in);
+ }
+};
+
+class SquareRootSolver : public
+ Algorithms::Operator<Vector<double> >
+{
+ SmartPointer<SquareRoot, SquareRootSolver>
+ solver;
+public:
+
+ SquareRootSolver(SquareRoot &problem)
+ : solver(&problem)
+ {}
+
+ virtual void operator ()(AnyData &out, const AnyData &in)
+ {
+ solver->solve(out,in);
+ }
+};
+
+void SquareRoot::residual (AnyData &out, const AnyData &in)
+{
+ Vector<double>& v = *out.entry<Vector<double>*>(0);
+ //residuum = 0
+ v(0) = 0.;
+ const Vector<double> &x = *in.entry<const Vector<double>*>("Newton iterate");
+ v(0) = x*x - 2.;
+}
+
+void SquareRoot::solve (AnyData &out, const AnyData &in)
+{
+ Vector<double>& v = *out.entry<Vector<double>*>(0);
+ v(0) = 0;
+ const Vector<double> &x = *in.entry<const Vector<double>*>("Newton iterate");
+ const Vector<double> &r = *in.entry<const Vector<double>*>("Newton residual");
+
+ v(0) = 1./2./x(0)* r(0);
+}
+
+
+
+void test ()
+{
+ SquareRoot square_root;
+ SquareRootSolver sq_solver (square_root);
+ SquareRootResidual sq_residual (square_root);
+
+ Algorithms::OutputOperator<Vector<double> > output;
+
+ Algorithms::Newton<Vector<double> > newton(
+ sq_residual,
+ sq_solver);
+ newton.initialize(output);
+
+ NamedData<Vector<double>*> in_data;
+ NamedData<Vector<double>*> out_data;
+
+ Vector<double> solution (1);
+ solution = 10.;
+ Vector<double> *p = &solution;
+ out_data.add(p, "solution");
+
+ newton.control.set_reduction(1.e-20);
+ newton.control.log_history(true);
+ newton.debug_vectors = true;
+ newton(out_data, in_data);
+ deallog << " square root " << (*out_data(0))(0) << std::endl;
+}
+
+
+
+
+int main()
+{
+ std::string logname = "output";
+ std::ofstream logfile(logname.c_str());
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ test ();
+}
--- /dev/null
+
+DEAL:Newton::Check 0 98.0000
+DEAL:Newton::Starting value 98.0000
+DEAL:Newton::Check 1 24.0100
+DEAL:Newton::Check 2 5.54095
+DEAL:Newton::Check 3 1.01785
+DEAL:Newton::Check 4 0.0858237
+DEAL:Newton::Check 5 0.000882829
+DEAL:Newton::Check 6 9.73804e-08
+DEAL:Newton::Check 7 0
+DEAL:Newton::Convergence step 7 value 0
+DEAL:: square root 1.41421
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: newton_01.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2008 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Test the compatibility functionality for Operator::operator()
+
+#include "../tests.h"
+#include <deal.II/algorithms/operator.h>
+#include <deal.II/lac/vector.h>
+
+using namespace Algorithms;
+
+class Op1 : public Operator<Vector<double> >
+{
+ public:
+ virtual void operator() (AnyData& out, const AnyData& in)
+ {
+ Vector<double>* u = out.entry<Vector<double>*>("u");
+ deallog << "u " << (*u)(0) << std::endl;
+
+ const Vector<double>* v = in.entry<Vector<double>*>("v");
+ deallog << "v " << (*v)(0) << std::endl;
+ }
+};
+
+class Op2 : public Operator<Vector<double> >
+{
+ public:
+ virtual void operator() (NamedData<Vector<double>*>& out,
+ const NamedData<Vector<double>*>& in)
+ {
+ Vector<double>* u = out(out.find("u"));
+ deallog << "u " << (*u)(0) << std::endl;
+
+ const Vector<double> * const v = in(in.find("v"));
+ deallog << "v " << (*v)(0) << std::endl;
+ }
+};
+
+void test(Operator<Vector<double> >& op)
+{
+ Vector<double> u(1);
+ Vector<double>* p = &u;
+ Vector<double> v(1);
+ u(0) = 3.;
+ v(0) = 7.;
+
+ AnyData o1;
+ o1.add (p, "u");
+ AnyData i1;
+ i1.add (&v, "v");
+
+ NamedData<Vector<double>*> o2;
+ o2.add (p, "u");
+ NamedData<Vector<double>*> i2;
+ i2.add (&v, "v");
+
+ deallog << "Call with AnyData" << std::endl;
+ op(o1, i1);
+ deallog << "Call with NamedData" << std::endl;
+ op(o2, i2);
+}
+
+int main()
+{
+ // deal_II_exceptions::disable_abort_on_exception();
+
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << "Operator with AnyData" << std::endl;
+ Op1 op1;
+ test(op1);
+
+ deallog << "Operator with NamedData" << std::endl;
+ Op2 op2;
+ test(op2);
+
+ // deallog << "Operator with NamedData" << std::endl;
+ // Op2 op2;
+ // test(op1);
+}
--- /dev/null
+
+DEAL::Operator with AnyData
+DEAL::Call with AnyData
+DEAL::u 3.00000
+DEAL::v 7.00000
+DEAL::Call with NamedData
+DEAL::u 3.00000
+DEAL::v 7.00000
+DEAL::Operator with NamedData
+DEAL::Call with AnyData
+DEAL::u 3.00000
+DEAL::v 7.00000
+DEAL::Call with NamedData
+DEAL::u 3.00000
+DEAL::v 7.00000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: theta_timestepping.cc 30050 2013-07-18 20:03:31Z maier $
+//
+// Copyright (C) 2005 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+// See documentation of ThetaTimestepping for documentation of this example
+
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/full_matrix.h>
+
+#include <deal.II/algorithms/operator.h>
+#include <deal.II/algorithms/theta_timestepping.h>
+
+#include <iostream>
+
+using namespace dealii;
+using namespace Algorithms;
+
+
+class Explicit
+ : public Operator<Vector<double> >
+{
+public:
+ Explicit(const FullMatrix<double> &matrix);
+ void operator() (NamedData<Vector<double>*> &out,
+ const NamedData<Vector<double>*> &in);
+
+ void initialize_timestep_data(const TimestepData &);
+private:
+ const TimestepData *timestep_data;
+ SmartPointer<const FullMatrix<double>, Explicit> matrix;
+ FullMatrix<double> m;
+};
+
+
+class Implicit
+ : public Operator<Vector<double> >
+{
+public:
+ Implicit(const FullMatrix<double> &matrix);
+ void operator() (NamedData<Vector<double>*> &out,
+ const NamedData<Vector<double>*> &in);
+
+ void initialize_timestep_data(const TimestepData &);
+private:
+ const TimestepData *timestep_data;
+ SmartPointer<const FullMatrix<double>, Implicit> matrix;
+ FullMatrix<double> m;
+};
+
+// End of declarations
+
+int main()
+{
+ std::string logname = "output";
+ std::ofstream logfile(logname.c_str());
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ FullMatrix<double> matrix(2);
+ matrix(0,0) = 0.;
+ matrix(1,1) = 0.;
+ matrix(0,1) = numbers::PI;
+ matrix(1,0) = -numbers::PI;
+
+ OutputOperator<Vector<double> > out;
+ out.initialize_stream(logfile);
+
+ Explicit op_explicit(matrix);
+ Implicit op_implicit(matrix);
+ ThetaTimestepping<Vector<double> > solver(op_explicit, op_implicit);
+ op_explicit.initialize_timestep_data(solver.explicit_data());
+ op_implicit.initialize_timestep_data(solver.implicit_data());
+ solver.timestep_control().start_step(0.1);
+ //solver.set_output(out);
+
+ Vector<double> value(2);
+ value(0) = 1.;
+ NamedData<Vector<double>*> indata;
+ NamedData<Vector<double>*> outdata;
+ Vector<double> *p = &value;
+ outdata.add(p, "value");
+ deallog << "Initial: " << value(0) << ' ' << value(1) << std::endl;
+ solver.notify(Events::initial);
+ solver(outdata, indata);
+ deallog << "Result: " << value(0) << ' ' << value(1)
+ << " Norm " << value.l2_norm() << std::endl;
+}
+
+
+Explicit::Explicit(const FullMatrix<double> &M)
+ :
+ matrix(&M)
+{
+ m.reinit(M.m(), M.n());
+}
+
+
+void
+Explicit::initialize_timestep_data(const TimestepData &t)
+{
+ timestep_data = &t;
+}
+
+
+void
+Explicit::operator() (NamedData<Vector<double>*> &out, const NamedData<Vector<double>*> &in)
+{
+ if (this->notifications.test(Events::initial) || this->notifications.test(Events::new_timestep_size))
+ {
+ m.equ(-timestep_data->step, *matrix);
+ for (unsigned int i=0; i<m.m(); ++i)
+ m(i,i) += 1.;
+ }
+ this->notifications.clear();
+ unsigned int i = in.find("Previous iterate");
+ m.vmult(*out(0), *in(i));
+}
+
+
+Implicit::Implicit(const FullMatrix<double> &M)
+ :
+ matrix(&M)
+{
+ m.reinit(M.m(), M.n());
+}
+
+
+void
+Implicit::initialize_timestep_data(const TimestepData &t)
+{
+ timestep_data = &t;
+}
+
+
+void
+Implicit::operator() (NamedData<Vector<double>*> &out, const NamedData<Vector<double>*> &in)
+{
+ if (this->notifications.test(Events::initial) || this->notifications.test(Events::new_timestep_size))
+ {
+ m.equ(timestep_data->step, *matrix);
+ for (unsigned int i=0; i<m.m(); ++i)
+ m(i,i) += 1.;
+ m.gauss_jordan();
+ }
+ this->notifications.clear();
+
+ unsigned int i = in.find("Previous time");
+ m.vmult(*out(0), *in(i));
+}
+
+
--- /dev/null
+
+DEAL::Initial: 1.00000 0
+DEAL:Theta::Time step:0.100000
+DEAL:Theta::Time step:0.200000
+DEAL:Theta::Time step:0.300000
+DEAL:Theta::Time step:0.400000
+DEAL:Theta::Time step:0.500000
+DEAL:Theta::Time step:0.600000
+DEAL:Theta::Time step:0.700000
+DEAL:Theta::Time step:0.800000
+DEAL:Theta::Time step:0.900000
+DEAL:Theta::Time step:1.00000
+DEAL::Result: -0.999676 0.0254599 Norm 1.00000
// This program tests the functionality of the function parser
// wrapper with respect to the ability to deal with units.
+// because units are deprecated and muparser can not deal with this,
+// recycle the test to use constants instead of units
#include "../tests.h"
#include <fstream>
deallog.depth_console(0);
deallog.threshold_double(1.e-10);
+
std::vector<std::string> function(1);
std::map<std::string, double> constants;
std::map<std::string, double> units;
constants["PI"] = 3.141592654;
- units["cm"] = 10;
- units["m"] = 1000;
+ constants["cm"] = 10;
+ constants["m"] = 1000;
Point<2> point(2.0, 3.0);
//initialized with units
FunctionParser<2> fp;
- function[0] = "x cm + y m + PI";
+ function[0] = "x * cm + y * m + PI";
fp.initialize(FunctionParser<2>::default_variable_names(),
function, constants, units);
+++ /dev/null
-
-DEAL::Function [x cm + y m + PI] @point [2.00000 3.00000] is [3023.14]
-DEAL::Function [x cm + y m + PI] @point [2.00000 3.00000] is [3023.14]
-DEAL::Function [x + y + PI] @point [2.00000 3.00000] is [8.14159]
-DEAL::Function [x + y + PI] @point [2.00000 3.00000] is [8.14159]
--- /dev/null
+
+DEAL::Function [x * cm + y * m + PI] @point [2.00000 3.00000] is [3023.14]
+DEAL::Function [x * cm + y * m + PI] @point [2.00000 3.00000] is [3023.14]
+DEAL::Function [x + y + PI] @point [2.00000 3.00000] is [8.14159]
+DEAL::Function [x + y + PI] @point [2.00000 3.00000] is [8.14159]
--- /dev/null
+#include "../tests.h"
+#include <fstream>
+#include <iomanip>
+#include <map>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/point.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/base/function_parser.h>
+
+// simple function parser example (this is the basis for the example code in the documentation)
+
+void test1()
+{
+ // set up problem:
+ std::string variables = "x,y";
+ std::string expression = "cos(x)+sqrt(y)";
+ std::map<std::string,double> constants;
+
+ // FunctionParser with 2 variables and 1 component:
+ FunctionParser<2> fp(1);
+ fp.initialize(variables,
+ expression,
+ constants);
+
+ // Point at which we want to evaluate the function
+ Point<2> point(0.0, 4.0);
+
+ // evaluate the expression at 'point':
+ double result = fp.value(point);
+
+ deallog << "Function '" << expression << "'"
+ << " @ " << point
+ << " is " << result << std::endl;
+}
+
+
+void test2()
+{
+ // Define some constants that will be used by the function parser
+ std::map<std::string,double> constants;
+ constants["pi"] = numbers::PI;
+
+ // Define the variables that will be used inside the expressions
+ std::string variables = "x,y,z";
+
+ // Define the expressions of the individual components of a
+ // vector valued function with two components:
+ std::vector<std::string> expressions(2);
+ expressions[0] = "sin(2*pi*x)+sinh(pi*z)";
+ expressions[1] = "sin(2*pi*y)*exp(x^2)";
+
+ // function parser with 3 variables and 2 components
+ FunctionParser<3> vector_function(2);
+
+ // And populate it with the newly created objects.
+ vector_function.initialize(variables,
+ expressions,
+ constants);
+
+ // Point at which we want to evaluate the function
+ Point<3> point(0.0, 1.0, 1.0);
+
+ // This Vector will store the result
+ Vector<double> result(2);
+
+ // Fill 'result' by evaluating the function
+ vector_function.vector_value(point, result);
+
+ // We can also only evaluate the 2nd component:
+ double c = vector_function.value(point, 1);
+
+ // Output the evaluated function
+ deallog << "Function '" << expressions[0] << "," << expressions[1] << "'"
+ << " @ " << point
+ << " is " << result << std::endl;
+ }
+
+
+int main()
+{
+ initlog();
+
+ test1();
+ test2();
+
+}
--- /dev/null
+
+DEAL::Function 'cos(x)+sqrt(y)' @ 0.00000 4.00000 is 3.00000
+DEAL::Function 'sin(2*pi*x)+sinh(pi*z),sin(2*pi*y)*exp(x^2)' @ 0.00000 1.00000 1.00000 is 11.5487 -2.44929e-16
+DEAL::
--- /dev/null
+#include "../tests.h"
+#include <fstream>
+#include <iomanip>
+#include <map>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/point.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/base/function_parser.h>
+
+// various checks (compatibility functionparser -> muparser)
+
+void eval(const std::string & exp, const Point<2> & p, double expected)
+{
+ std::string variables = "x,y";
+ std::map<std::string,double> constants;
+
+ FunctionParser<2> fp(1);
+ fp.initialize(variables,
+ exp,
+ constants);
+
+ double result = fp.value(p);
+ deallog << "'" << exp << "' @ " << p << " is " << result
+ << " ( expected " << expected << " )" << std::endl;
+ if (fabs(result-expected)>1e-10)
+ deallog << "ERROR!" << std::endl;
+
+
+
+}
+
+
+void test()
+{
+ eval("if(x<0.0,0.0,if(x>1.0,1.0,x))",Point<2>(0.5,0.0), 0.5);
+ eval("if(x<0.0,0.0,if(x>1.0,1.0,x))",Point<2>(-2.0,0.0), 0.0);
+ eval("if(x<0.0,0.0,if(x>1.0,1.0,x))",Point<2>(42.0,0.0), 1.0);
+
+ eval("if(x<1.0 | y<1.0,0,y)",Point<2>(0.5,1.5), 0.0);
+ eval("if(x<1.0 | y<1.0,0,y)",Point<2>(1.5,1.5), 1.5);
+ eval("if(x<1.0 | y<1.0,0,y)",Point<2>(1.5,0.5), 0.0);
+ eval("if(x<1.0 | y<1.0,0,y)",Point<2>(0.5,-2), 0.0);
+
+ eval("if(x<1.0 & y<1.0,0,y)",Point<2>(1.5,-2.0), -2.0);
+
+ double x,y;
+ x=1.0;
+ y=-3.1;
+ eval("atan2(x,y)",Point<2>(x,y), atan2(x,y));
+ x=-1.0;
+ y=3.1;
+ eval("atan2(x,y)",Point<2>(x,y), atan2(x,y));
+
+ eval("if(x==1.0,0,y)",Point<2>(1.0,-2.0), 0.0);
+ eval("if(x==1.0,0,y)",Point<2>(1.1,-2.0), -2.0);
+
+ eval("int(2.1)",Point<2>(1.1,-2.0), 2.0);
+ eval("int(-3.8)",Point<2>(1.1,-2.0), -4.0);
+
+ eval("abs(-2.3)",Point<2>(0,0), 2.3);
+ eval("acos(0.5)",Point<2>(0,0), acos(0.5));
+ eval("acosh(0.5)",Point<2>(0,0), acosh(0.5));
+ eval("asin(0.5)",Point<2>(0,0), asin(0.5));
+ eval("asinh(0.5)",Point<2>(0,0), asinh(0.5));
+ eval("atan(0.5)",Point<2>(0,0), atan(0.5));
+ eval("atanh(0.5)",Point<2>(0,0), atanh(0.5));
+ eval("ceil(0.5)",Point<2>(0,0), ceil(0.5));
+ eval("cos(0.5)",Point<2>(0,0), cos(0.5));
+ eval("cosh(0.5)",Point<2>(0,0), cosh(0.5));
+ eval("cot(0.5)",Point<2>(0,0), 1.0/tan(0.5));
+ eval("csc(0.5)",Point<2>(0,0), 1.0/sin(0.5));
+ eval("exp(0.5)",Point<2>(0,0), exp(0.5));
+ eval("floor(0.5)",Point<2>(0,0), floor(0.5));
+ eval("log(0.5)",Point<2>(0,0), log(0.5));
+ eval("log10(0.5)",Point<2>(0,0), log(0.5)/log(10.0));
+ eval("sec(0.5)",Point<2>(0,0), 1.0/cos(0.5));
+ eval("sin(0.5)",Point<2>(0,0), sin(0.5));
+ eval("sinh(0.5)",Point<2>(0,0), sinh(0.5));
+ eval("sqrt(0.5)",Point<2>(0,0), sqrt(0.5));
+ eval("tan(0.5)",Point<2>(0,0), tan(0.5));
+ eval("tanh(0.5)",Point<2>(0,0), tanh(0.5));
+
+
+}
+
+int main()
+{
+ initlog();
+
+ test();
+}
--- /dev/null
+
+DEAL::'if(x<0.0,0.0,if(x>1.0,1.0,x))' @ 0.500000 0.00000 is 0.500000 ( expected 0.500000 )
+DEAL::'if(x<0.0,0.0,if(x>1.0,1.0,x))' @ -2.00000 0.00000 is 0.00000 ( expected 0.00000 )
+DEAL::'if(x<0.0,0.0,if(x>1.0,1.0,x))' @ 42.0000 0.00000 is 1.00000 ( expected 1.00000 )
+DEAL::'if(x<1.0 | y<1.0,0,y)' @ 0.500000 1.50000 is 0.00000 ( expected 0.00000 )
+DEAL::'if(x<1.0 | y<1.0,0,y)' @ 1.50000 1.50000 is 1.50000 ( expected 1.50000 )
+DEAL::'if(x<1.0 | y<1.0,0,y)' @ 1.50000 0.500000 is 0.00000 ( expected 0.00000 )
+DEAL::'if(x<1.0 | y<1.0,0,y)' @ 0.500000 -2.00000 is 0.00000 ( expected 0.00000 )
+DEAL::'if(x<1.0 & y<1.0,0,y)' @ 1.50000 -2.00000 is -2.00000 ( expected -2.00000 )
+DEAL::'atan2(x,y)' @ 1.00000 -3.10000 is 2.82955 ( expected 2.82955 )
+DEAL::'atan2(x,y)' @ -1.00000 3.10000 is -0.312042 ( expected -0.312042 )
+DEAL::'if(x==1.0,0,y)' @ 1.00000 -2.00000 is 0.00000 ( expected 0.00000 )
+DEAL::'if(x==1.0,0,y)' @ 1.10000 -2.00000 is -2.00000 ( expected -2.00000 )
+DEAL::'int(2.1)' @ 1.10000 -2.00000 is 2.00000 ( expected 2.00000 )
+DEAL::'int(-3.8)' @ 1.10000 -2.00000 is -4.00000 ( expected -4.00000 )
+DEAL::'abs(-2.3)' @ 0.00000 0.00000 is 2.30000 ( expected 2.30000 )
+DEAL::'acos(0.5)' @ 0.00000 0.00000 is 1.04720 ( expected 1.04720 )
+DEAL::'acosh(0.5)' @ 0.00000 0.00000 is -nan ( expected -nan )
+DEAL::'asin(0.5)' @ 0.00000 0.00000 is 0.523599 ( expected 0.523599 )
+DEAL::'asinh(0.5)' @ 0.00000 0.00000 is 0.481212 ( expected 0.481212 )
+DEAL::'atan(0.5)' @ 0.00000 0.00000 is 0.463648 ( expected 0.463648 )
+DEAL::'atanh(0.5)' @ 0.00000 0.00000 is 0.549306 ( expected 0.549306 )
+DEAL::'ceil(0.5)' @ 0.00000 0.00000 is 1.00000 ( expected 1.00000 )
+DEAL::'cos(0.5)' @ 0.00000 0.00000 is 0.877583 ( expected 0.877583 )
+DEAL::'cosh(0.5)' @ 0.00000 0.00000 is 1.12763 ( expected 1.12763 )
+DEAL::'cot(0.5)' @ 0.00000 0.00000 is 1.83049 ( expected 1.83049 )
+DEAL::'csc(0.5)' @ 0.00000 0.00000 is 2.08583 ( expected 2.08583 )
+DEAL::'exp(0.5)' @ 0.00000 0.00000 is 1.64872 ( expected 1.64872 )
+DEAL::'floor(0.5)' @ 0.00000 0.00000 is 0.00000 ( expected 0.00000 )
+DEAL::'log(0.5)' @ 0.00000 0.00000 is -0.693147 ( expected -0.693147 )
+DEAL::'log10(0.5)' @ 0.00000 0.00000 is -0.301030 ( expected -0.301030 )
+DEAL::'sec(0.5)' @ 0.00000 0.00000 is 1.13949 ( expected 1.13949 )
+DEAL::'sin(0.5)' @ 0.00000 0.00000 is 0.479426 ( expected 0.479426 )
+DEAL::'sinh(0.5)' @ 0.00000 0.00000 is 0.521095 ( expected 0.521095 )
+DEAL::'sqrt(0.5)' @ 0.00000 0.00000 is 0.707107 ( expected 0.707107 )
+DEAL::'tan(0.5)' @ 0.00000 0.00000 is 0.546302 ( expected 0.546302 )
+DEAL::'tanh(0.5)' @ 0.00000 0.00000 is 0.462117 ( expected 0.462117 )
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: tensor_26.cc $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+// check Tensor<rank,dim,std::complex<double> > operator * (const Tensor<rank,dim> &t,
+// const std::complex<double> factor)
+// and
+// check Tensor<rank,dim,std::complex<double> > operator * (const std::complex<double> factor,
+// const Tensor<rank,dim> &t)
+// by multiplying on the left and on the right.
+
+#include "../tests.h"
+#include <deal.II/base/tensor.h>
+#include <deal.II/base/logstream.h>
+#include <fstream>
+#include <iomanip>
+
+
+template <int dim>
+void test_tensor ()
+{
+ // a real tensor
+ Tensor<1,dim,double> t (false);
+
+ for (unsigned int i=0; i<dim; ++i)
+ {
+ t[i] = 2*i+dim+1;
+ }
+
+ // multiply on the right by a complex<double>
+ const Tensor<1,dim,std::complex<double> > right =
+ t * std::complex<double> (1,2);
+
+ // multiply on the left by a complex<double>
+ const Tensor<1,dim,std::complex<double> > left =
+ std::complex<double> (1,2) * t;
+
+ // they should yield the same result
+ Assert (left == right, ExcInternalError ());
+
+ deallog << "dim = " << dim << std::endl
+ << left << " : " << right << std::endl;
+}
+
+
+int main ()
+{
+ std::ofstream logfile("output");
+ deallog << std::setprecision(3);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ test_tensor<1>();
+ test_tensor<2>();
+ test_tensor<3>();
+ test_tensor<4>();
+
+ deallog << "OK" << std::endl;
+}
+
--- /dev/null
+
+DEAL::dim = 1
+DEAL::(2.00,4.00) : (2.00,4.00)
+DEAL::dim = 2
+DEAL::(3.00,6.00) (5.00,10.0) : (3.00,6.00) (5.00,10.0)
+DEAL::dim = 3
+DEAL::(4.00,8.00) (6.00,12.0) (8.00,16.0) : (4.00,8.00) (6.00,12.0) (8.00,16.0)
+DEAL::dim = 4
+DEAL::(5.00,10.0) (7.00,14.0) (9.00,18.0) (11.0,22.0) : (5.00,10.0) (7.00,14.0) (9.00,18.0) (11.0,22.0)
+DEAL::OK
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: tensor_complex_06.cc $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+// check Tensor<1,dim,std::complex<double>>::operator*(Tensor<1,dim,std::complex<double> >)
+// These tests are simple enough to do by hand.
+
+#include "../tests.h"
+#include <deal.II/base/tensor.h>
+#include <deal.II/base/logstream.h>
+#include <fstream>
+#include <iomanip>
+
+template <int dim>
+void test_tensor_01 ()
+{
+ Tensor<1,dim,std::complex<double> > t (false);
+ for (unsigned int i=0; i<dim; ++i)
+ {
+ t[i] = std::complex<double> (i,1);
+ }
+ const Tensor<1,dim,std::complex<double> > res =
+ t * std::complex<double> (1,2);
+
+ deallog << "dim = " << dim << ": " << res << std::endl;
+}
+
+
+template <int dim>
+void test_tensor_02 ()
+{
+ Tensor<1,dim,std::complex<double> > t (false);
+ for (unsigned int i=0; i<dim; ++i)
+ {
+ t[i] = std::complex<double> (1,i);
+ }
+ const Tensor<1,dim,std::complex<double> > res =
+ t * std::complex<double> (1,2);
+
+ deallog << "dim = " << dim << ": " << res << std::endl;
+}
+
+int main ()
+{
+ std::ofstream logfile("output");
+ deallog << std::setprecision(3);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ deallog << "First test" << std::endl;
+
+ test_tensor_01<1>();
+ test_tensor_01<2>();
+ test_tensor_01<3>();
+
+ deallog << "Second test" << std::endl;
+
+ test_tensor_02<1>();
+ test_tensor_02<2>();
+ test_tensor_02<3>();
+
+ deallog << "OK" << std::endl;
+}
--- /dev/null
+
+DEAL::First test
+DEAL::dim = 1: (-2.00,1.00)
+DEAL::dim = 2: (-2.00,1.00) (-1.00,3.00)
+DEAL::dim = 3: (-2.00,1.00) (-1.00,3.00) (0.00,5.00)
+DEAL::Second test
+DEAL::dim = 1: (1.00,2.00)
+DEAL::dim = 2: (1.00,2.00) (-1.00,3.00)
+DEAL::dim = 3: (1.00,2.00) (-1.00,3.00) (-3.00,4.00)
+DEAL::OK
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping_01.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#include "../tests.h"
+#include <deal.II/base/time_stepping.h>
+#include <deal.II/lac/vector.h>
+
+// test Runge-Kutta methods
+Vector<double> f1(double const t, Vector<double> const &y)
+{
+ Vector<double> values(y);
+ for (unsigned int i=0; i<values.size(); ++i)
+ values[i] = 1.0;
+
+ return values;
+}
+
+Vector<double> f2(double const t, Vector<double> const &y)
+{
+ Vector<double> values(y);
+ for (unsigned int i=0; i<values.size(); ++i)
+ values[i] = 2.0*t;
+
+ return values;
+}
+
+Vector<double> f3(double const t, Vector<double> const &y)
+{
+ Vector<double> values(y);
+ for (unsigned int i=0; i<values.size(); ++i)
+ values[i] = 3.0*t*t;
+
+ return values;
+}
+
+Vector<double> f4(double const t, Vector<double> const &y)
+{
+ Vector<double> values(y);
+ for (unsigned int i=0; i<values.size(); ++i)
+ values[i] = 4.0*t*t*t;
+
+ return values;
+}
+
+Vector<double> f5(double const t, Vector<double> const &y)
+{
+ Vector<double> values(y);
+ for (unsigned int i=0; i<values.size(); ++i)
+ values[i] = 5.0*t*t*t*t;
+
+ return values;
+}
+
+Vector<double> id_minus_tau_J_inv1(double const t, double const tau, Vector<double> const &y)
+{
+ return y;
+}
+
+Vector<double> id_minus_tau_J_inv2(double const t, double const tau, Vector<double> const &y)
+{
+ return y;
+}
+
+Vector<double> id_minus_tau_J_inv3(double const t, double const tau, Vector<double> const &y)
+{
+ return y;
+}
+
+Vector<double> id_minus_tau_J_inv4(double const t, double const tau, Vector<double> const &y)
+{
+ return y;
+}
+
+Vector<double> id_minus_tau_J_inv5(double const t, double const tau, Vector<double> const &y)
+{
+ return y;
+}
+
+double my1(double const t)
+{
+ return t;
+}
+
+double my2(double const t)
+{
+ return t*t;
+}
+
+double my3(double const t)
+{
+ return t*t*t;
+}
+
+double my4(double const t)
+{
+ return t*t*t*t;
+}
+
+double my5(double const t)
+{
+ return t*t*t*t*t;
+}
+
+void test(TimeStepping::RungeKutta<Vector<double> > &solver,
+ std_cxx1x::function<Vector<double> (double const, Vector<double> const &)> f,
+ std_cxx1x::function<Vector<double> (double const, double const, Vector<double> const &)> id_minus_tau_J_inv,
+ std_cxx1x::function<double (double const)> my)
+{
+ unsigned int n_time_steps = 1;
+ unsigned int size = 1;
+ double initial_time = 0.0, final_time = 1.0;
+ double time_step = (final_time-initial_time)/static_cast<double> (n_time_steps);
+ double time = initial_time;
+ Vector<double> solution(size);
+ Vector<double> exact_solution(size);
+ for (unsigned int i=0; i<size; ++i)
+ {
+ solution[i] = my(initial_time);
+ exact_solution[i] = my(final_time);
+ }
+
+ for (unsigned int i=0; i<n_time_steps; ++i)
+ time = solver.evolve_one_time_step(f,id_minus_tau_J_inv,time,time_step,solution);
+
+ Vector<double> error(exact_solution);
+ error.sadd(1.0,-1.0,solution);
+ double error_norm = error.l2_norm();
+ deallog << error_norm <<std::endl;
+}
+
+void test2(TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > &solver,
+ std_cxx1x::function<Vector<double> (double const, Vector<double> const &)> f,
+ std_cxx1x::function<Vector<double> (double const, double const, Vector<double> const &)> id_minus_tau_J_inv,
+ std_cxx1x::function<double (double const)> my)
+{
+ double initial_time = 0.0, final_time = 1.0;
+ double time_step = 1.0;
+ unsigned int size = 1;
+ unsigned int n_time_steps = 0;
+ double time = initial_time;
+ Vector<double> solution(size);
+ Vector<double> exact_solution(size);
+ for (unsigned int i=0; i<size; ++i)
+ {
+ solution[i] = my(initial_time);
+ exact_solution[i] = my(final_time);
+ }
+
+
+ while (time<final_time)
+ {
+ if (time+time_step>final_time)
+ time_step = final_time - time;
+ time = solver.evolve_one_time_step(f,id_minus_tau_J_inv,time,time_step,solution);
+ time_step = solver.get_status().delta_t_guess;
+ }
+
+ Vector<double> error(exact_solution);
+ error.sadd(1.0,-1.0,solution);
+ double error_norm = error.l2_norm();
+ deallog<<error_norm<<std::endl;
+}
+
+int main()
+{
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ deallog<<"Forward Euler"<<std::endl;
+ TimeStepping::ExplicitRungeKutta<Vector<double> > fe(TimeStepping::FORWARD_EULER);
+ test(fe,f1,id_minus_tau_J_inv1,my1);
+
+ deallog<<"Runge-Kutta third order"<<std::endl;
+ TimeStepping::ExplicitRungeKutta<Vector<double> > rk3(TimeStepping::RK_THIRD_ORDER);
+ test(rk3,f3,id_minus_tau_J_inv3,my3);
+
+ deallog<<"Runge-Kutta fourth order"<<std::endl;
+ TimeStepping::ExplicitRungeKutta<Vector<double> > rk4(TimeStepping::RK_CLASSIC_FOURTH_ORDER);
+ test(rk4,f4,id_minus_tau_J_inv4,my4);
+
+ deallog<<"Backward Euler"<<std::endl;
+ TimeStepping::ImplicitRungeKutta<Vector<double> > be(TimeStepping::BACKWARD_EULER);
+ test(be,f1,id_minus_tau_J_inv1,my1);
+
+ deallog<<"Implicit midpoint"<<std::endl;
+ TimeStepping::ImplicitRungeKutta<Vector<double> > im(TimeStepping::IMPLICIT_MIDPOINT);
+ test(im,f2,id_minus_tau_J_inv2,my2);
+
+ deallog<<"Crank-Nicolson"<<std::endl;
+ TimeStepping::ImplicitRungeKutta<Vector<double> > cn(TimeStepping::CRANK_NICOLSON);
+ test(cn,f2,id_minus_tau_J_inv2,my2);
+
+ deallog<<"SDIRK"<<std::endl;
+ TimeStepping::ImplicitRungeKutta<Vector<double> > sdirk(TimeStepping::SDIRK_TWO_STAGES);
+ test(sdirk,f2,id_minus_tau_J_inv2,my2);
+
+ deallog<<"Heun-Euler"<<std::endl;
+ TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > he(TimeStepping::HEUN_EULER);
+ test2(he,f2,id_minus_tau_J_inv2,my2);
+
+ deallog<<"Bogacki-Shampine"<<std::endl;
+ TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > bs(TimeStepping::BOGACKI_SHAMPINE);
+ test2(bs,f3,id_minus_tau_J_inv3,my3);
+ bs.free_memory();
+
+ deallog<<"DOPRI"<<std::endl;
+ TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > dopri(TimeStepping::DOPRI);
+ test2(dopri,f5,id_minus_tau_J_inv5,my5);
+ dopri.free_memory();
+
+ deallog<<"Fehlberg"<<std::endl;
+ TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > fehlberg(TimeStepping::FEHLBERG);
+ test2(fehlberg,f5,id_minus_tau_J_inv5,my5);
+
+ deallog<<"Cash-Karp"<<std::endl;
+ TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > ck(TimeStepping::CASH_KARP);
+ test2(ck,f5,id_minus_tau_J_inv5,my5);
+
+ return 0;
+}
--- /dev/null
+
+DEAL::Forward Euler
+DEAL::0
+DEAL::Runge-Kutta third order
+DEAL::0
+DEAL::Runge-Kutta fourth order
+DEAL::0
+DEAL::Backward Euler
+DEAL::0
+DEAL::Implicit midpoint
+DEAL::0
+DEAL::Crank-Nicolson
+DEAL::0
+DEAL::SDIRK
+DEAL::0
+DEAL::Heun-Euler
+DEAL::0
+DEAL::Bogacki-Shampine
+DEAL::0
+DEAL::DOPRI
+DEAL::0
+DEAL::Fehlberg
+DEAL::0
+DEAL::Cash-Karp
+DEAL::0
#include <fstream>
#include <cmath>
-#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
void test ()
#include <cmath>
#include <deal.II/base/vectorization.h>
-
+#include <deal.II/base/aligned_vector.h>
void test ()
{
#include <fstream>
#include <cmath>
-#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
typedef AlignedVector<unsigned int> VEC;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005 - 2013 by the deal.II authors
+// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
FullMatrix<double> A2(4,4);
FullMatrix<double> B(4,3);
FullMatrix<double> C(3,3);
- PrimitiveVectorMemory<Vector<double> > mem;
- BlockMatrixArray<double> block(2,2,mem);
+ BlockMatrixArray<double> block(2,2);
block.enter(A1,0,0);
block.enter(A2,0,0,2,true);
DEAL::\begin{array}{cc}
-DEAL:: M0+2xM1^T & -3xM2-3xM2^T\\
-DEAL:: & M3^T\\
+DEAL:: M0+2xM1^T & -3xM2-3xM3^T\\
+DEAL:: & M4^T
DEAL::\end{array}
{
DataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", DataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", DataOut<dim>::type_cell_data);
data_out.build_patches ();
data_out.write_dx (deallog.get_file_stream());
DataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", DataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", DataOut<dim>::type_cell_data);
data_out.build_patches ();
data_out.write_dx (deallog.get_file_stream());
{
XDataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", XDataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", XDataOut<dim>::type_cell_data);
data_out.build_patches ();
{
{
XDataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", XDataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", XDataOut<dim>::type_cell_data);
data_out.build_patches ();
{
"node_data_2"),
DataOut<dim>::type_dof_data,
data_component_interpretation);
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_cell, "cell_data", DataOut<dim>::type_cell_data);
data_out.build_patches ();
data_out.write_vtk (deallog.get_file_stream());
// we pick only subdomain==0 which will
// skip the first of the four cells
FilteredDataOut<dim> data_out(0);
- data_out.attach_dof_handler (dof_handler);
+ data_out.attach_dof_handler(dof_handler);
- data_out.add_data_vector (cell_data, "cell_data");
+ data_out.add_data_vector (cell_data, "cell_data", DataOut<dim>::type_cell_data);
data_out.build_patches ();
data_out.write_deal_II_intermediate (deallog.get_file_stream());
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2003 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+// check that add_data_vector and type_automatic work correctly and confirm
+// that the Assert is triggered that checks, when we have dof_data and
+// cell_data with the same length.
+
+
+#include "../tests.h"
+#include <deal.II/lac/sparsity_pattern.h>
+#include <deal.II/numerics/data_out.h>
+
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/fe/fe_dgq.h>
+
+
+
+
+void test()
+{
+ Triangulation<2> tria;
+ GridGenerator::hyper_cube (tria);
+ tria.refine_global(1);
+
+ FE_DGQ<2> fe(0);
+ DoFHandler<2> dof_handler(tria);
+ dof_handler.distribute_dofs(fe);
+
+ std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs());
+ renumbering[0]=3;
+ renumbering[1]=2;
+ renumbering[2]=1;
+ renumbering[3]=0;
+
+ dof_handler.renumber_dofs(renumbering);
+
+
+ Vector<double> v_node(dof_handler.n_dofs());
+ Vector<double> v_cell(dof_handler.n_dofs());
+ for (unsigned int i=0;i<dof_handler.n_dofs();++i)
+ {
+ v_node[i]=i;
+ v_cell[i]=10+i;
+ }
+
+ //correct one is done if both are possible but specified
+ deallog << "*** Check cell and node data:" << std::endl;
+ {
+ DataOut<2> data_out;
+ data_out.attach_dof_handler (dof_handler);
+ data_out.add_data_vector (v_node, "node_data", DataOut<2>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", DataOut<2>::type_cell_data);
+ data_out.build_patches ();
+
+ data_out.write_vtk (deallog.get_file_stream());
+ }
+
+ //only tria, output correctly
+ deallog << "*** Check cell data only:" << std::endl;
+ {
+ DataOut<2> data_out;
+ data_out.attach_triangulation (tria);
+ data_out.add_data_vector (v_cell, "cell_data");
+ data_out.build_patches ();
+
+ data_out.write_vtk (deallog.get_file_stream());
+ }
+
+
+ //error if both
+ deallog << "*** should fail:" << std::endl;
+ try
+ {
+ DataOut<2> data_out;
+ data_out.attach_dof_handler (dof_handler);
+ data_out.add_data_vector (v_cell, "cell_data");
+ data_out.build_patches ();
+
+ data_out.write_vtk (deallog.get_file_stream());
+ }
+ catch (...)
+ {
+ deallog << "exception" << std::endl;
+ }
+
+ // works if we use the other add_data_vector:
+ deallog << "*** Check node data only:" << std::endl;
+ {
+ DataOut<2> data_out;
+ data_out.attach_dof_handler (dof_handler);
+ data_out.add_data_vector (dof_handler, v_node, "node_data");
+ data_out.build_patches ();
+
+ data_out.write_vtk (deallog.get_file_stream());
+ }
+
+
+
+}
+
+
+int main()
+{
+ deal_II_exceptions::disable_abort_on_exception();
+ initlog();
+ test();
+
+}
+
--- /dev/null
+
+DEAL::*** Check cell and node data:
+# vtk DataFile Version 3.0
+#This file was generated
+ASCII
+DATASET UNSTRUCTURED_GRID
+
+POINTS 16 double
+0.00000 0.00000 0
+0.500000 0.00000 0
+0.00000 0.500000 0
+0.500000 0.500000 0
+0.500000 0.00000 0
+1.00000 0.00000 0
+0.500000 0.500000 0
+1.00000 0.500000 0
+0.00000 0.500000 0
+0.500000 0.500000 0
+0.00000 1.00000 0
+0.500000 1.00000 0
+0.500000 0.500000 0
+1.00000 0.500000 0
+0.500000 1.00000 0
+1.00000 1.00000 0
+
+CELLS 4 20
+4 0 1 3 2
+4 4 5 7 6
+4 8 9 11 10
+4 12 13 15 14
+
+CELL_TYPES 4
+ 9 9 9 9
+POINT_DATA 16
+SCALARS node_data double 1
+LOOKUP_TABLE default
+3.00000 3.00000 3.00000 3.00000 2.00000 2.00000 2.00000 2.00000 1.00000 1.00000 1.00000 1.00000 0.00000 0.00000 0.00000 0.00000
+SCALARS cell_data double 1
+LOOKUP_TABLE default
+10.0000 10.0000 10.0000 10.0000 11.0000 11.0000 11.0000 11.0000 12.0000 12.0000 12.0000 12.0000 13.0000 13.0000 13.0000 13.0000
+DEAL::*** Check cell data only:
+# vtk DataFile Version 3.0
+#This file was generated
+ASCII
+DATASET UNSTRUCTURED_GRID
+
+POINTS 16 double
+0.00000 0.00000 0
+0.500000 0.00000 0
+0.00000 0.500000 0
+0.500000 0.500000 0
+0.500000 0.00000 0
+1.00000 0.00000 0
+0.500000 0.500000 0
+1.00000 0.500000 0
+0.00000 0.500000 0
+0.500000 0.500000 0
+0.00000 1.00000 0
+0.500000 1.00000 0
+0.500000 0.500000 0
+1.00000 0.500000 0
+0.500000 1.00000 0
+1.00000 1.00000 0
+
+CELLS 4 20
+4 0 1 3 2
+4 4 5 7 6
+4 8 9 11 10
+4 12 13 15 14
+
+CELL_TYPES 4
+ 9 9 9 9
+POINT_DATA 16
+SCALARS cell_data double 1
+LOOKUP_TABLE default
+10.0000 10.0000 10.0000 10.0000 11.0000 11.0000 11.0000 11.0000 12.0000 12.0000 12.0000 12.0000 13.0000 13.0000 13.0000 13.0000
+DEAL::*** should fail:
+DEAL::exception
+DEAL::*** Check node data only:
+# vtk DataFile Version 3.0
+#This file was generated
+ASCII
+DATASET UNSTRUCTURED_GRID
+
+POINTS 16 double
+0.00000 0.00000 0
+0.500000 0.00000 0
+0.00000 0.500000 0
+0.500000 0.500000 0
+0.500000 0.00000 0
+1.00000 0.00000 0
+0.500000 0.500000 0
+1.00000 0.500000 0
+0.00000 0.500000 0
+0.500000 0.500000 0
+0.00000 1.00000 0
+0.500000 1.00000 0
+0.500000 0.500000 0
+1.00000 0.500000 0
+0.500000 1.00000 0
+1.00000 1.00000 0
+
+CELLS 4 20
+4 0 1 3 2
+4 4 5 7 6
+4 8 9 11 10
+4 12 13 15 14
+
+CELL_TYPES 4
+ 9 9 9 9
+POINT_DATA 16
+SCALARS node_data double 1
+LOOKUP_TABLE default
+3.00000 3.00000 3.00000 3.00000 2.00000 2.00000 2.00000 2.00000 1.00000 1.00000 1.00000 1.00000 0.00000 0.00000 0.00000 0.00000
{
DataOutFaces<dim> data_out_faces;
data_out_faces.attach_dof_handler (dof_handler);
- data_out_faces.add_data_vector (v_node, "node_data");
- data_out_faces.add_data_vector (v_cell, "cell_data");
+ data_out_faces.add_data_vector (v_node, "node_data", DataOutFaces<dim>::type_dof_data);
+ data_out_faces.add_data_vector (v_cell, "cell_data", DataOutFaces<dim>::type_cell_data);
data_out_faces.build_patches ();
data_out_faces.write_dx (deallog.get_file_stream());
DataOutFaces<dim> data_out_faces;
data_out_faces.attach_dof_handler (dof_handler);
- data_out_faces.add_data_vector (v_node, "node_data");
- data_out_faces.add_data_vector (v_cell, "cell_data");
+ data_out_faces.add_data_vector (v_node, "node_data", DataOutFaces<dim>::type_dof_data);
+ data_out_faces.add_data_vector (v_cell, "cell_data", DataOutFaces<dim>::type_cell_data);
data_out_faces.build_patches ();
data_out_faces.write_dx (deallog.get_file_stream());
{
XDataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", XDataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", XDataOut<dim>::type_cell_data);
data_out.build_patches ();
{
{
XDataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", XDataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", XDataOut<dim>::type_cell_data);
data_out.build_patches ();
{
{
DataOutRotation<dim> data_out_rotation;
data_out_rotation.attach_dof_handler (dof_handler);
- data_out_rotation.add_data_vector (v_node, "node_data");
- data_out_rotation.add_data_vector (v_cell, "cell_data");
+ data_out_rotation.add_data_vector (v_node, "node_data", DataOutRotation<dim>::type_dof_data);
+ data_out_rotation.add_data_vector (v_cell, "cell_data", DataOutRotation<dim>::type_cell_data);
data_out_rotation.build_patches (4);
data_out_rotation.write_dx (deallog.get_file_stream());
DataOutRotation<dim> data_out_rotation;
data_out_rotation.attach_dof_handler (dof_handler);
- data_out_rotation.add_data_vector (v_node, "node_data");
- data_out_rotation.add_data_vector (v_cell, "cell_data");
+ data_out_rotation.add_data_vector (v_node, "node_data", DataOutRotation<dim>::type_dof_data);
+ data_out_rotation.add_data_vector (v_cell, "cell_data", DataOutRotation<dim>::type_cell_data);
data_out_rotation.build_patches (4);
data_out_rotation.write_dx (deallog.get_file_stream());
{
XDataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", XDataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", XDataOut<dim>::type_cell_data);
data_out.build_patches (4);
{
{
XDataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
- data_out.add_data_vector (v_node, "node_data");
- data_out.add_data_vector (v_cell, "cell_data");
+ data_out.add_data_vector (v_node, "node_data", XDataOut<dim>::type_dof_data);
+ data_out.add_data_vector (v_cell, "cell_data", XDataOut<dim>::type_cell_data);
data_out.build_patches (4);
{
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2002 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// ParameterHandler could not deal with missing endline at end of file
+// or can it?
+// http://code.google.com/p/dealii/issues/detail?id=126
+
+// this is a variant of parameter_handler_15 but in fact reads data
+// from a file
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/parameter_handler.h>
+#include <fstream>
+
+void test ()
+{
+ ParameterHandler foo;
+ foo.enter_subsection("bar");
+ foo.declare_entry("val", "1.0", dealii::Patterns::Double(), "");
+ foo.leave_subsection();
+
+ bool okay = foo.read_input(SOURCE_DIR "/parameter_handler_18.prm");
+ Assert(okay, ExcMessage("read_input failed"));
+
+ foo.enter_subsection("bar");
+ deallog << foo.get ("val") << std::endl;
+ foo.leave_subsection();
+}
+
+int main ()
+{
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ test ();
+
+ return 0;
+}
--- /dev/null
+
+DEAL::123.456
--- /dev/null
+# Listing of Parameters
+# ---------------------
+
+subsection bar
+ set val = 123.456
+end
\ No newline at end of file
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2005 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// tests step-51 (without output, without ChunkSparseMatrix, without
+// adaptivity) in 1d and 2d
+
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <fstream>
+std::ofstream logfile("output");
+
+
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/function.h>
+#include <deal.II/base/convergence_table.h>
+#include <deal.II/base/work_stream.h>
+#include <deal.II/base/tensor_function.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/solver_bicgstab.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_out.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_face.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <iomanip>
+#include <fstream>
+#include <cmath>
+
+
+namespace Step51
+{
+
+ using namespace dealii;
+
+ template <int dim>
+ class SolutionBase
+ {
+ protected:
+ static const unsigned int n_source_centers = 3;
+ static const Point<dim> source_centers[n_source_centers];
+ static const double width;
+ };
+
+
+ template <>
+ const Point<1>
+ SolutionBase<1>::source_centers[SolutionBase<1>::n_source_centers]
+ = { Point<1>(-1.0 / 3.0),
+ Point<1>(0.0),
+ Point<1>(+1.0 / 3.0)
+ };
+
+
+ template <>
+ const Point<2>
+ SolutionBase<2>::source_centers[SolutionBase<2>::n_source_centers]
+ = { Point<2>(-0.5, +0.5),
+ Point<2>(-0.5, -0.5),
+ Point<2>(+0.5, -0.5)
+ };
+
+ template <>
+ const Point<3>
+ SolutionBase<3>::source_centers[SolutionBase<3>::n_source_centers]
+ = { Point<3>(-0.5, +0.5, 0.25),
+ Point<3>(-0.6, -0.5, -0.125),
+ Point<3>(+0.5, -0.5, 0.5)
+ };
+
+ template <int dim>
+ const double SolutionBase<dim>::width = 1./5.;
+
+
+ template <int dim>
+ class Solution : public Function<dim>,
+ protected SolutionBase<dim>
+ {
+ public:
+ Solution () : Function<dim>() {}
+
+ virtual double value (const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ virtual Tensor<1,dim> gradient (const Point<dim> &p,
+ const unsigned int component = 0) const;
+ };
+
+
+
+ template <int dim>
+ double Solution<dim>::value (const Point<dim> &p,
+ const unsigned int) const
+ {
+ double return_value = 0;
+ for (unsigned int i=0; i<this->n_source_centers; ++i)
+ {
+ const Point<dim> x_minus_xi = p - this->source_centers[i];
+ return_value += std::exp(-x_minus_xi.square() /
+ (this->width * this->width));
+ }
+
+ return return_value /
+ Utilities::fixed_power<dim>(std::sqrt(2. * numbers::PI) * this->width);
+ }
+
+
+
+ template <int dim>
+ Tensor<1,dim> Solution<dim>::gradient (const Point<dim> &p,
+ const unsigned int) const
+ {
+ Tensor<1,dim> return_value;
+
+ for (unsigned int i=0; i<this->n_source_centers; ++i)
+ {
+ const Point<dim> x_minus_xi = p - this->source_centers[i];
+
+ return_value += (-2 / (this->width * this->width) *
+ std::exp(-x_minus_xi.square() /
+ (this->width * this->width)) *
+ x_minus_xi);
+ }
+
+ return return_value / Utilities::fixed_power<dim>(std::sqrt(2 * numbers::PI) *
+ this->width);
+ }
+
+
+
+ template <int dim>
+ class SolutionAndGradient : public Function<dim>,
+ protected SolutionBase<dim>
+ {
+ public:
+ SolutionAndGradient () : Function<dim>(dim) {}
+
+ virtual void vector_value (const Point<dim> &p,
+ Vector<double> &v) const;
+ };
+
+ template <int dim>
+ void SolutionAndGradient<dim>::vector_value (const Point<dim> &p,
+ Vector<double> &v) const
+ {
+ AssertDimension(v.size(), dim+1);
+ Solution<dim> solution;
+ Tensor<1,dim> grad = solution.gradient(p);
+ for (unsigned int d=0; d<dim; ++d)
+ v[d] = -grad[d];
+ v[dim] = solution.value(p);
+ }
+
+
+
+ template <int dim>
+ class ConvectionVelocity : public TensorFunction<1,dim>
+ {
+ public:
+ ConvectionVelocity() : TensorFunction<1,dim>() {}
+
+ virtual Tensor<1,dim> value (const Point<dim> &p) const;
+ };
+
+
+
+ template <int dim>
+ Tensor<1,dim>
+ ConvectionVelocity<dim>::value(const Point<dim> &p) const
+ {
+ Tensor<1,dim> convection;
+ switch (dim)
+ {
+ case 1:
+ convection[0] = 1;
+ break;
+ case 2:
+ convection[0] = p[1];
+ convection[1] = -p[0];
+ break;
+ case 3:
+ convection[0] = p[1];
+ convection[1] = -p[0];
+ convection[2] = 1;
+ break;
+ default:
+ Assert(false, ExcNotImplemented());
+ }
+ return convection;
+ }
+
+
+
+ template <int dim>
+ class RightHandSide : public Function<dim>,
+ protected SolutionBase<dim>
+ {
+ public:
+ RightHandSide () : Function<dim>() {}
+
+ virtual double value (const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ private:
+ const ConvectionVelocity<dim> convection_velocity;
+ };
+
+
+ template <int dim>
+ double RightHandSide<dim>::value (const Point<dim> &p,
+ const unsigned int) const
+ {
+ Tensor<1,dim> convection = convection_velocity.value(p);
+ double return_value = 0;
+ for (unsigned int i=0; i<this->n_source_centers; ++i)
+ {
+ const Point<dim> x_minus_xi = p - this->source_centers[i];
+
+ return_value +=
+ ((2*dim - 2*convection*x_minus_xi - 4*x_minus_xi.square()/
+ (this->width * this->width)) /
+ (this->width * this->width) *
+ std::exp(-x_minus_xi.square() /
+ (this->width * this->width)));
+ }
+
+ return return_value / Utilities::fixed_power<dim>(std::sqrt(2 * numbers::PI)
+ * this->width);
+ }
+
+
+ template <int dim>
+ class HDG
+ {
+ public:
+ HDG (const unsigned int degree);
+ void run ();
+
+ private:
+
+ void setup_system ();
+ void assemble_system (const bool reconstruct_trace = false);
+ void solve ();
+ void postprocess ();
+ void refine_grid (const unsigned int cylce);
+ void output_results (const unsigned int cycle);
+
+ struct PerTaskData;
+ struct ScratchData;
+
+ struct PostProcessScratchData;
+
+ void assemble_system_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ ScratchData &scratch,
+ PerTaskData &task_data);
+
+ void copy_local_to_global(const PerTaskData &data);
+
+ void postprocess_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ PostProcessScratchData &scratch,
+ unsigned int &empty_data);
+
+
+ Triangulation<dim> triangulation;
+
+ FESystem<dim> fe_local;
+ DoFHandler<dim> dof_handler_local;
+ Vector<double> solution_local;
+
+ FE_FaceQ<dim> fe;
+ DoFHandler<dim> dof_handler;
+ Vector<double> solution;
+ Vector<double> system_rhs;
+
+ FE_DGQ<dim> fe_u_post;
+ DoFHandler<dim> dof_handler_u_post;
+ Vector<double> solution_u_post;
+
+ ConstraintMatrix constraints;
+
+ SparsityPattern sparsity_pattern;
+ SparseMatrix<double> system_matrix;
+
+ ConvergenceTable convergence_table;
+ };
+
+
+ template <int dim>
+ HDG<dim>::HDG (const unsigned int degree) :
+ fe_local (FE_DGQ<dim>(degree), dim+1),
+ dof_handler_local (triangulation),
+ fe (degree),
+ dof_handler (triangulation),
+ fe_u_post (degree+1),
+ dof_handler_u_post (triangulation)
+ {}
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::setup_system ()
+ {
+ dof_handler_local.distribute_dofs(fe_local);
+ dof_handler.distribute_dofs(fe);
+ dof_handler_u_post.distribute_dofs(fe_u_post);
+
+ solution.reinit (dof_handler.n_dofs());
+ system_rhs.reinit (dof_handler.n_dofs());
+
+ solution_local.reinit (dof_handler_local.n_dofs());
+ solution_u_post.reinit (dof_handler_u_post.n_dofs());
+
+ constraints.clear ();
+ DoFTools::make_hanging_node_constraints (dof_handler, constraints);
+ typename FunctionMap<dim>::type boundary_functions;
+ Solution<dim> solution_function;
+ boundary_functions[0] = &solution_function;
+ VectorTools::project_boundary_values (dof_handler,
+ boundary_functions,
+ QGauss<dim-1>(fe.degree+1),
+ constraints);
+ constraints.close ();
+
+ {
+ CompressedSimpleSparsityPattern csp (dof_handler.n_dofs());
+ DoFTools::make_sparsity_pattern (dof_handler, csp,
+ constraints, false);
+ sparsity_pattern.copy_from(csp);
+ }
+ system_matrix.reinit (sparsity_pattern);
+ }
+
+
+
+ template <int dim>
+ struct HDG<dim>::PerTaskData
+ {
+ FullMatrix<double> cell_matrix;
+ Vector<double> cell_vector;
+ std::vector<types::global_dof_index> dof_indices;
+
+ bool trace_reconstruct;
+
+ PerTaskData(const unsigned int n_dofs, const bool trace_reconstruct)
+ : cell_matrix(n_dofs, n_dofs),
+ cell_vector(n_dofs),
+ dof_indices(n_dofs),
+ trace_reconstruct(trace_reconstruct)
+ {}
+ };
+
+
+
+ template <int dim>
+ struct HDG<dim>::ScratchData
+ {
+ FEValues<dim> fe_values_local;
+ FEFaceValues<dim> fe_face_values_local;
+ FEFaceValues<dim> fe_face_values;
+
+ FullMatrix<double> ll_matrix;
+ FullMatrix<double> lf_matrix;
+ FullMatrix<double> fl_matrix;
+ FullMatrix<double> tmp_matrix;
+ Vector<double> l_rhs;
+ Vector<double> tmp_rhs;
+
+ std::vector<Tensor<1,dim> > q_phi;
+ std::vector<double> q_phi_div;
+ std::vector<double> u_phi;
+ std::vector<Tensor<1,dim> > u_phi_grad;
+ std::vector<double> tr_phi;
+ std::vector<double> trace_values;
+
+ std::vector<std::vector<unsigned int> > fe_local_support_on_face;
+ std::vector<std::vector<unsigned int> > fe_support_on_face;
+
+ ConvectionVelocity<dim> convection_velocity;
+ RightHandSide<dim> right_hand_side;
+ const Solution<dim> exact_solution;
+
+ ScratchData(const FiniteElement<dim> &fe,
+ const FiniteElement<dim> &fe_local,
+ const QGauss<dim> &quadrature_formula,
+ const QGauss<dim-1> &face_quadrature_formula,
+ const UpdateFlags local_flags,
+ const UpdateFlags local_face_flags,
+ const UpdateFlags flags)
+ :
+ fe_values_local (fe_local, quadrature_formula, local_flags),
+ fe_face_values_local (fe_local, face_quadrature_formula, local_face_flags),
+ fe_face_values (fe, face_quadrature_formula, flags),
+ ll_matrix (fe_local.dofs_per_cell, fe_local.dofs_per_cell),
+ lf_matrix (fe_local.dofs_per_cell, fe.dofs_per_cell),
+ fl_matrix (fe.dofs_per_cell, fe_local.dofs_per_cell),
+ tmp_matrix (fe.dofs_per_cell, fe_local.dofs_per_cell),
+ l_rhs (fe_local.dofs_per_cell),
+ tmp_rhs (fe_local.dofs_per_cell),
+ q_phi (fe_local.dofs_per_cell),
+ q_phi_div (fe_local.dofs_per_cell),
+ u_phi (fe_local.dofs_per_cell),
+ u_phi_grad (fe_local.dofs_per_cell),
+ tr_phi (fe.dofs_per_cell),
+ trace_values(face_quadrature_formula.size()),
+ fe_local_support_on_face(GeometryInfo<dim>::faces_per_cell),
+ fe_support_on_face(GeometryInfo<dim>::faces_per_cell)
+ {
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int i=0; i<fe_local.dofs_per_cell; ++i)
+ {
+ if (fe_local.has_support_on_face(i,face))
+ {
+ fe_local_support_on_face[face].push_back(i);
+ }
+ }
+
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ {
+ if (fe.has_support_on_face(i,face))
+ {
+ fe_support_on_face[face].push_back(i);
+ }
+ }
+ }
+
+ ScratchData(const ScratchData &sd)
+ :
+ fe_values_local (sd.fe_values_local.get_fe(),
+ sd.fe_values_local.get_quadrature(),
+ sd.fe_values_local.get_update_flags()),
+ fe_face_values_local (sd.fe_face_values_local.get_fe(),
+ sd.fe_face_values_local.get_quadrature(),
+ sd.fe_face_values_local.get_update_flags()),
+ fe_face_values (sd.fe_face_values.get_fe(),
+ sd.fe_face_values.get_quadrature(),
+ sd.fe_face_values.get_update_flags()),
+ ll_matrix (sd.ll_matrix),
+ lf_matrix (sd.lf_matrix),
+ fl_matrix (sd.fl_matrix),
+ tmp_matrix (sd.tmp_matrix),
+ l_rhs (sd.l_rhs),
+ tmp_rhs (sd.tmp_rhs),
+ q_phi (sd.q_phi),
+ q_phi_div (sd.q_phi_div),
+ u_phi (sd.u_phi),
+ u_phi_grad (sd.u_phi_grad),
+ tr_phi (sd.tr_phi),
+ trace_values(sd.trace_values),
+ fe_local_support_on_face(sd.fe_local_support_on_face),
+ fe_support_on_face(sd.fe_support_on_face)
+ {}
+ };
+
+
+
+ template <int dim>
+ struct HDG<dim>::PostProcessScratchData
+ {
+ FEValues<dim> fe_values_local;
+ FEValues<dim> fe_values;
+
+ std::vector<double> u_values;
+ std::vector<Tensor<1,dim> > u_gradients;
+ FullMatrix<double> cell_matrix;
+
+ Vector<double> cell_rhs;
+ Vector<double> cell_sol;
+
+ PostProcessScratchData(const FiniteElement<dim> &fe,
+ const FiniteElement<dim> &fe_local,
+ const QGauss<dim> &quadrature_formula,
+ const UpdateFlags local_flags,
+ const UpdateFlags flags)
+ :
+ fe_values_local (fe_local, quadrature_formula, local_flags),
+ fe_values (fe, quadrature_formula, flags),
+ u_values (quadrature_formula.size()),
+ u_gradients (quadrature_formula.size()),
+ cell_matrix (fe.dofs_per_cell, fe.dofs_per_cell),
+ cell_rhs (fe.dofs_per_cell),
+ cell_sol (fe.dofs_per_cell)
+ {}
+
+ PostProcessScratchData(const PostProcessScratchData &sd)
+ :
+ fe_values_local (sd.fe_values_local.get_fe(),
+ sd.fe_values_local.get_quadrature(),
+ sd.fe_values_local.get_update_flags()),
+ fe_values (sd.fe_values.get_fe(),
+ sd.fe_values.get_quadrature(),
+ sd.fe_values.get_update_flags()),
+ u_values (sd.u_values),
+ u_gradients (sd.u_gradients),
+ cell_matrix (sd.cell_matrix),
+ cell_rhs (sd.cell_rhs),
+ cell_sol (sd.cell_sol)
+ {}
+ };
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::assemble_system (const bool trace_reconstruct)
+ {
+ const QGauss<dim> quadrature_formula(fe.degree+1);
+ const QGauss<dim-1> face_quadrature_formula(fe.degree+1);
+
+ const UpdateFlags local_flags (update_values | update_gradients |
+ update_JxW_values | update_quadrature_points);
+
+ const UpdateFlags local_face_flags (update_values);
+
+ const UpdateFlags flags ( update_values | update_normal_vectors |
+ update_quadrature_points |
+ update_JxW_values);
+
+ PerTaskData task_data (fe.dofs_per_cell,
+ trace_reconstruct);
+ ScratchData scratch (fe, fe_local,
+ quadrature_formula,
+ face_quadrature_formula,
+ local_flags,
+ local_face_flags,
+ flags);
+
+ WorkStream::run(dof_handler.begin_active(),
+ dof_handler.end(),
+ *this,
+ &HDG<dim>::assemble_system_one_cell,
+ &HDG<dim>::copy_local_to_global,
+ scratch,
+ task_data);
+ }
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::assemble_system_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ ScratchData &scratch,
+ PerTaskData &task_data)
+ {
+ typename DoFHandler<dim>::active_cell_iterator
+ loc_cell (&triangulation,
+ cell->level(),
+ cell->index(),
+ &dof_handler_local);
+
+ const unsigned int n_q_points = scratch.fe_values_local.get_quadrature().size();
+ const unsigned int n_face_q_points = scratch.fe_face_values_local.get_quadrature().size();
+
+ const unsigned int loc_dofs_per_cell = scratch.fe_values_local.get_fe().dofs_per_cell;
+
+ const FEValuesExtractors::Vector fluxes (0);
+ const FEValuesExtractors::Scalar scalar (dim);
+
+ scratch.ll_matrix = 0;
+ scratch.l_rhs = 0;
+ if (!task_data.trace_reconstruct)
+ {
+ scratch.lf_matrix = 0;
+ scratch.fl_matrix = 0;
+ task_data.cell_matrix = 0;
+ task_data.cell_vector = 0;
+ }
+ scratch.fe_values_local.reinit (loc_cell);
+
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ const double rhs_value
+ = scratch.right_hand_side.value(scratch.fe_values_local.quadrature_point(q));
+ const Tensor<1,dim> convection
+ = scratch.convection_velocity.value(scratch.fe_values_local.quadrature_point(q));
+ const double JxW = scratch.fe_values_local.JxW(q);
+ for (unsigned int k=0; k<loc_dofs_per_cell; ++k)
+ {
+ scratch.q_phi[k] = scratch.fe_values_local[fluxes].value(k,q);
+ scratch.q_phi_div[k] = scratch.fe_values_local[fluxes].divergence(k,q);
+ scratch.u_phi[k] = scratch.fe_values_local[scalar].value(k,q);
+ scratch.u_phi_grad[k] = scratch.fe_values_local[scalar].gradient(k,q);
+ }
+ for (unsigned int i=0; i<loc_dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<loc_dofs_per_cell; ++j)
+ scratch.ll_matrix(i,j) += (
+ scratch.q_phi[i] * scratch.q_phi[j]
+ -
+ scratch.q_phi_div[i] * scratch.u_phi[j]
+ +
+ scratch.u_phi[i] * scratch.q_phi_div[j]
+ -
+ (scratch.u_phi_grad[i] * convection) * scratch.u_phi[j]
+ ) * JxW;
+ scratch.l_rhs(i) += scratch.u_phi[i] * rhs_value * JxW;
+ }
+ }
+
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ {
+ scratch.fe_face_values_local.reinit(loc_cell, face);
+ scratch.fe_face_values.reinit(cell, face);
+
+ if (task_data.trace_reconstruct)
+ scratch.fe_face_values.get_function_values (solution, scratch.trace_values);
+
+ for (unsigned int q=0; q<n_face_q_points; ++q)
+ {
+ const double JxW = scratch.fe_face_values.JxW(q);
+ const Point<dim> quadrature_point =
+ scratch.fe_face_values.quadrature_point(q);
+ const Point<dim> normal = scratch.fe_face_values.normal_vector(q);
+ const Tensor<1,dim> convection
+ = scratch.convection_velocity.value(quadrature_point);
+
+ const double tau_stab = (5. +
+ std::abs(convection * normal));
+
+ for (unsigned int k=0; k<scratch.fe_local_support_on_face[face].size(); ++k)
+ {
+ const unsigned int kk=scratch.fe_local_support_on_face[face][k];
+ scratch.q_phi[k] = scratch.fe_face_values_local[fluxes].value(kk,q);
+ scratch.u_phi[k] = scratch.fe_face_values_local[scalar].value(kk,q);
+ }
+
+ if (!task_data.trace_reconstruct)
+ {
+ for (unsigned int k=0; k<scratch.fe_support_on_face[face].size(); ++k)
+ scratch.tr_phi[k] =
+ scratch.fe_face_values.shape_value(scratch.fe_support_on_face[face][k],q);
+ for (unsigned int i=0; i<scratch.fe_local_support_on_face[face].size(); ++i)
+ for (unsigned int j=0; j<scratch.fe_support_on_face[face].size(); ++j)
+ {
+ const unsigned int ii=scratch.fe_local_support_on_face[face][i];
+ const unsigned int jj=scratch.fe_support_on_face[face][j];
+ scratch.lf_matrix(ii,jj) += (
+ (scratch.q_phi[i] * normal
+ +
+ (convection * normal -
+ tau_stab) * scratch.u_phi[i])
+ * scratch.tr_phi[j]
+ ) * JxW;
+
+ scratch.fl_matrix(jj,ii) -= (
+ (scratch.q_phi[i] * normal
+ +
+ tau_stab * scratch.u_phi[i])
+ * scratch.tr_phi[j]
+ ) * JxW;
+ }
+
+ for (unsigned int i=0; i<scratch.fe_support_on_face[face].size(); ++i)
+ for (unsigned int j=0; j<scratch.fe_support_on_face[face].size(); ++j)
+ {
+ const unsigned int ii=scratch.fe_support_on_face[face][i];
+ const unsigned int jj=scratch.fe_support_on_face[face][j];
+ task_data.cell_matrix(ii,jj) += (
+ (convection * normal - tau_stab) *
+ scratch.tr_phi[i] * scratch.tr_phi[j]
+ ) * JxW;
+ }
+
+ if (cell->face(face)->at_boundary()
+ &&
+ (cell->face(face)->boundary_indicator() == 1))
+ {
+ const double neumann_value =
+ - scratch.exact_solution.gradient (quadrature_point) * normal
+ + convection * normal * scratch.exact_solution.value(quadrature_point);
+ for (unsigned int i=0; i<scratch.fe_support_on_face[face].size(); ++i)
+ {
+ const unsigned int ii=scratch.fe_support_on_face[face][i];
+ task_data.cell_vector(ii) += scratch.tr_phi[i] * neumann_value * JxW;
+ }
+ }
+ }
+
+ for (unsigned int i=0; i<scratch.fe_local_support_on_face[face].size(); ++i)
+ for (unsigned int j=0; j<scratch.fe_local_support_on_face[face].size(); ++j)
+ {
+ const unsigned int ii=scratch.fe_local_support_on_face[face][i];
+ const unsigned int jj=scratch.fe_local_support_on_face[face][j];
+ scratch.ll_matrix(ii,jj) += tau_stab * scratch.u_phi[i] * scratch.u_phi[j] * JxW;
+ }
+
+ if (task_data.trace_reconstruct)
+ for (unsigned int i=0; i<scratch.fe_local_support_on_face[face].size(); ++i)
+ {
+ const unsigned int ii=scratch.fe_local_support_on_face[face][i];
+ scratch.l_rhs(ii) -= (scratch.q_phi[i] * normal
+ +
+ scratch.u_phi[i] * (convection * normal - tau_stab)
+ ) * scratch.trace_values[q] * JxW;
+ }
+ }
+ }
+
+ scratch.ll_matrix.gauss_jordan();
+
+ if (task_data.trace_reconstruct == false)
+ {
+ scratch.fl_matrix.mmult(scratch.tmp_matrix, scratch.ll_matrix);
+ scratch.tmp_matrix.vmult_add(task_data.cell_vector, scratch.l_rhs);
+ scratch.tmp_matrix.mmult(task_data.cell_matrix, scratch.lf_matrix, true);
+ cell->get_dof_indices(task_data.dof_indices);
+ }
+ else
+ {
+ scratch.ll_matrix.vmult(scratch.tmp_rhs, scratch.l_rhs);
+ loc_cell->set_dof_values(scratch.tmp_rhs, solution_local);
+ }
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::copy_local_to_global(const PerTaskData &data)
+ {
+ if (data.trace_reconstruct == false)
+ constraints.distribute_local_to_global (data.cell_matrix,
+ data.cell_vector,
+ data.dof_indices,
+ system_matrix, system_rhs);
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::solve ()
+ {
+ SolverControl solver_control (system_matrix.m()*10,
+ 1e-12*system_rhs.l2_norm());
+ // do not output iteration numbers to log file because these are too
+ // sensitive
+ std::ostringstream stream;
+ deallog.attach(stream);
+ SolverBicgstab<> solver (solver_control, false);
+ solver.solve (system_matrix, solution, system_rhs,
+ PreconditionIdentity());
+ deallog.attach(logfile);
+
+ system_matrix.clear();
+
+ constraints.distribute(solution);
+
+ assemble_system(true);
+ }
+
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::postprocess()
+ {
+ {
+ const QGauss<dim> quadrature_formula(fe_u_post.degree+1);
+ const UpdateFlags local_flags (update_values);
+ const UpdateFlags flags ( update_values | update_gradients |
+ update_JxW_values);
+
+ PostProcessScratchData scratch (fe_u_post, fe_local,
+ quadrature_formula,
+ local_flags,
+ flags);
+
+ WorkStream::run(dof_handler_u_post.begin_active(),
+ dof_handler_u_post.end(),
+ std_cxx1x::bind (&HDG<dim>::postprocess_one_cell,
+ std_cxx1x::ref(*this),
+ std_cxx1x::_1, std_cxx1x::_2, std_cxx1x::_3),
+ std_cxx1x::function<void(const unsigned int &)>(),
+ scratch,
+ 0U);
+ }
+
+ Vector<float> difference_per_cell (triangulation.n_active_cells());
+
+ ComponentSelectFunction<dim> value_select (dim, dim+1);
+ VectorTools::integrate_difference (dof_handler_local,
+ solution_local,
+ SolutionAndGradient<dim>(),
+ difference_per_cell,
+ QGauss<dim>(fe.degree+2),
+ VectorTools::L2_norm,
+ &value_select);
+ const double L2_error = difference_per_cell.l2_norm();
+
+ ComponentSelectFunction<dim> gradient_select (std::pair<unsigned int,unsigned int>(0, dim),
+ dim+1);
+ VectorTools::integrate_difference (dof_handler_local,
+ solution_local,
+ SolutionAndGradient<dim>(),
+ difference_per_cell,
+ QGauss<dim>(fe.degree+2),
+ VectorTools::L2_norm,
+ &gradient_select);
+ const double grad_error = difference_per_cell.l2_norm();
+
+ VectorTools::integrate_difference (dof_handler_u_post,
+ solution_u_post,
+ Solution<dim>(),
+ difference_per_cell,
+ QGauss<dim>(fe.degree+3),
+ VectorTools::L2_norm);
+ const double post_error = difference_per_cell.l2_norm();
+
+ convergence_table.add_value("cells", triangulation.n_active_cells());
+ convergence_table.add_value("dofs", dof_handler.n_dofs());
+ convergence_table.add_value("val L2", L2_error);
+ convergence_table.add_value("grad L2", grad_error);
+ convergence_table.add_value("val L2-post", post_error);
+ }
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::postprocess_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ PostProcessScratchData &scratch,
+ unsigned int &)
+ {
+ typename DoFHandler<dim>::active_cell_iterator
+ loc_cell (&triangulation,
+ cell->level(),
+ cell->index(),
+ &dof_handler_local);
+
+ scratch.fe_values_local.reinit (loc_cell);
+ scratch.fe_values.reinit(cell);
+
+ FEValuesExtractors::Vector fluxes(0);
+ FEValuesExtractors::Scalar scalar(dim);
+
+ const unsigned int n_q_points = scratch.fe_values.get_quadrature().size();
+ const unsigned int dofs_per_cell = scratch.fe_values.dofs_per_cell;
+
+ scratch.fe_values_local[scalar].get_function_values(solution_local, scratch.u_values);
+ scratch.fe_values_local[fluxes].get_function_values(solution_local, scratch.u_gradients);
+
+ double sum = 0;
+ for (unsigned int i=1; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum += (scratch.fe_values.shape_grad(i,q) *
+ scratch.fe_values.shape_grad(j,q)
+ ) * scratch.fe_values.JxW(q);
+ scratch.cell_matrix(i,j) = sum;
+ }
+
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum -= (scratch.fe_values.shape_grad(i,q) * scratch.u_gradients[q]
+ ) * scratch.fe_values.JxW(q);
+ scratch.cell_rhs(i) = sum;
+ }
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum += scratch.fe_values.shape_value(j,q) * scratch.fe_values.JxW(q);
+ scratch.cell_matrix(0,j) = sum;
+ }
+ {
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum += scratch.u_values[q] * scratch.fe_values.JxW(q);
+ scratch.cell_rhs(0) = sum;
+ }
+
+ scratch.cell_matrix.gauss_jordan();
+ scratch.cell_matrix.vmult(scratch.cell_sol, scratch.cell_rhs);
+ cell->distribute_local_to_global(scratch.cell_sol, solution_u_post);
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::output_results (const unsigned int cycle)
+ {
+ // not included in test
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::refine_grid (const unsigned int cycle)
+ {
+ // only global refinement
+ triangulation.clear();
+ GridGenerator::subdivided_hyper_cube (triangulation, 2+(cycle%2), -1, 1);
+ triangulation.refine_global(3-dim+cycle/2);
+
+ typename Triangulation<dim>::cell_iterator
+ cell = triangulation.begin (),
+ endc = triangulation.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary())
+ for (unsigned int d=0; d<dim; ++d)
+ if ((std::fabs(cell->face(face)->center()(d) - (1)) < 1e-12))
+ cell->face(face)->set_boundary_indicator (1);
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::run ()
+ {
+ for (unsigned int cycle=0; cycle<12-3*dim; ++cycle)
+ {
+ refine_grid (cycle);
+ setup_system ();
+ assemble_system (false);
+ solve ();
+ postprocess();
+ output_results (cycle);
+ }
+
+ convergence_table.set_precision("val L2", 3);
+ convergence_table.set_scientific("val L2", true);
+ convergence_table.set_precision("grad L2", 3);
+ convergence_table.set_scientific("grad L2", true);
+ convergence_table.set_precision("val L2-post", 3);
+ convergence_table.set_scientific("val L2-post", true);
+
+ convergence_table
+ .evaluate_convergence_rates("val L2", "cells", ConvergenceTable::reduction_rate_log2, dim);
+ convergence_table
+ .evaluate_convergence_rates("grad L2", "cells", ConvergenceTable::reduction_rate_log2, dim);
+ convergence_table
+ .evaluate_convergence_rates("val L2-post", "cells", ConvergenceTable::reduction_rate_log2, dim);
+ convergence_table.write_text(deallog.get_file_stream());
+ }
+
+} // end of namespace Step51
+
+
+
+
+int main ()
+{
+ deallog << std::setprecision(6);
+ logfile << std::setprecision(6);
+
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ {
+ Step51::HDG<1> hdg_problem (1);
+ hdg_problem.run ();
+ }
+
+ {
+ Step51::HDG<1> hdg_problem (3);
+ hdg_problem.run ();
+ }
+
+ {
+ Step51::HDG<2> hdg_problem (1);
+ hdg_problem.run ();
+ }
+
+ {
+ Step51::HDG<2> hdg_problem (2);
+ hdg_problem.run ();
+ }
+
+ return 0;
+}
--- /dev/null
+
+
+
+
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+8 9 4.080e-01 - 1.722e+00 - 3.362e-01 -
+12 13 1.659e-01 2.22 8.766e-01 1.67 2.151e-02 6.78
+16 17 7.996e-02 2.54 4.531e-01 2.29 1.125e-02 2.25
+24 25 3.705e-02 1.90 2.028e-01 1.98 3.372e-03 2.97
+32 33 2.125e-02 1.93 1.140e-01 2.00 1.430e-03 2.98
+48 49 9.610e-03 1.96 5.048e-02 2.01 4.242e-04 3.00
+64 65 5.449e-03 1.97 2.831e-02 2.01 1.787e-04 3.00
+96 97 2.440e-03 1.98 1.253e-02 2.01 5.281e-05 3.01
+128 129 1.377e-03 1.99 7.035e-03 2.01 2.224e-05 3.01
+
+
+
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+8 9 2.141e-02 - 1.398e-01 - 3.487e-03 -
+12 13 6.701e-03 2.87 3.811e-02 3.21 4.976e-04 4.80
+16 17 1.693e-03 4.78 9.999e-03 4.65 1.085e-04 5.29
+24 25 3.501e-04 3.89 2.009e-03 3.96 1.440e-05 4.98
+32 33 1.126e-04 3.94 6.373e-04 3.99 3.412e-06 5.01
+48 49 2.256e-05 3.97 1.259e-04 4.00 4.472e-07 5.01
+64 65 7.179e-06 3.98 3.980e-05 4.00 1.057e-07 5.01
+96 97 1.425e-06 3.99 7.848e-06 4.00 1.386e-08 5.01
+128 129 4.519e-07 3.99 2.481e-06 4.00 3.284e-09 5.01
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+16 80 1.066e+01 - 1.571e+01 - 1.055e+01 -
+36 168 3.727e+00 2.59 7.998e+00 1.67 3.660e+00 2.61
+64 288 8.086e-01 5.31 4.228e+00 2.22 4.492e-01 7.29
+144 624 2.730e-01 2.68 1.867e+00 2.02 6.110e-02 4.92
+256 1088 1.493e-01 2.10 1.046e+00 2.01 2.878e-02 2.62
+576 2400 6.965e-02 1.88 4.847e-01 1.90 9.202e-03 2.81
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+16 120 7.645e-01 - 5.413e+00 - 2.667e-01 -
+36 252 4.745e-01 1.18 2.375e+00 2.03 3.501e-01 -0.67
+64 432 9.635e-02 5.54 7.772e-01 3.88 5.032e-02 6.74
+144 936 3.487e-02 2.51 2.718e-01 2.59 5.339e-03 5.53
+256 1632 1.920e-02 2.08 1.390e-01 2.33 1.731e-03 3.92
+576 3600 6.021e-03 2.86 4.291e-02 2.90 3.431e-04 3.99
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2005 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// tests step-51 (without output, without ChunkSparseMatrix, without
+// adaptivity) in 1d and 2d with FE_DGP/FE_FaceP
+
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <fstream>
+std::ofstream logfile("output");
+
+
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/function.h>
+#include <deal.II/base/convergence_table.h>
+#include <deal.II/base/work_stream.h>
+#include <deal.II/base/tensor_function.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/solver_bicgstab.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_out.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/fe/fe_dgp.h>
+#include <deal.II/fe/fe_face.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <iomanip>
+#include <fstream>
+#include <cmath>
+
+
+namespace Step51
+{
+
+ using namespace dealii;
+
+ template <int dim>
+ class SolutionBase
+ {
+ protected:
+ static const unsigned int n_source_centers = 3;
+ static const Point<dim> source_centers[n_source_centers];
+ static const double width;
+ };
+
+
+ template <>
+ const Point<1>
+ SolutionBase<1>::source_centers[SolutionBase<1>::n_source_centers]
+ = { Point<1>(-1.0 / 3.0),
+ Point<1>(0.0),
+ Point<1>(+1.0 / 3.0)
+ };
+
+
+ template <>
+ const Point<2>
+ SolutionBase<2>::source_centers[SolutionBase<2>::n_source_centers]
+ = { Point<2>(-0.5, +0.5),
+ Point<2>(-0.5, -0.5),
+ Point<2>(+0.5, -0.5)
+ };
+
+ template <>
+ const Point<3>
+ SolutionBase<3>::source_centers[SolutionBase<3>::n_source_centers]
+ = { Point<3>(-0.5, +0.5, 0.25),
+ Point<3>(-0.6, -0.5, -0.125),
+ Point<3>(+0.5, -0.5, 0.5)
+ };
+
+ template <int dim>
+ const double SolutionBase<dim>::width = 1./5.;
+
+
+ template <int dim>
+ class Solution : public Function<dim>,
+ protected SolutionBase<dim>
+ {
+ public:
+ Solution () : Function<dim>() {}
+
+ virtual double value (const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ virtual Tensor<1,dim> gradient (const Point<dim> &p,
+ const unsigned int component = 0) const;
+ };
+
+
+
+ template <int dim>
+ double Solution<dim>::value (const Point<dim> &p,
+ const unsigned int) const
+ {
+ double return_value = 0;
+ for (unsigned int i=0; i<this->n_source_centers; ++i)
+ {
+ const Point<dim> x_minus_xi = p - this->source_centers[i];
+ return_value += std::exp(-x_minus_xi.square() /
+ (this->width * this->width));
+ }
+
+ return return_value /
+ Utilities::fixed_power<dim>(std::sqrt(2. * numbers::PI) * this->width);
+ }
+
+
+
+ template <int dim>
+ Tensor<1,dim> Solution<dim>::gradient (const Point<dim> &p,
+ const unsigned int) const
+ {
+ Tensor<1,dim> return_value;
+
+ for (unsigned int i=0; i<this->n_source_centers; ++i)
+ {
+ const Point<dim> x_minus_xi = p - this->source_centers[i];
+
+ return_value += (-2 / (this->width * this->width) *
+ std::exp(-x_minus_xi.square() /
+ (this->width * this->width)) *
+ x_minus_xi);
+ }
+
+ return return_value / Utilities::fixed_power<dim>(std::sqrt(2 * numbers::PI) *
+ this->width);
+ }
+
+
+
+ template <int dim>
+ class SolutionAndGradient : public Function<dim>,
+ protected SolutionBase<dim>
+ {
+ public:
+ SolutionAndGradient () : Function<dim>(dim) {}
+
+ virtual void vector_value (const Point<dim> &p,
+ Vector<double> &v) const;
+ };
+
+ template <int dim>
+ void SolutionAndGradient<dim>::vector_value (const Point<dim> &p,
+ Vector<double> &v) const
+ {
+ AssertDimension(v.size(), dim+1);
+ Solution<dim> solution;
+ Tensor<1,dim> grad = solution.gradient(p);
+ for (unsigned int d=0; d<dim; ++d)
+ v[d] = -grad[d];
+ v[dim] = solution.value(p);
+ }
+
+
+
+ template <int dim>
+ class ConvectionVelocity : public TensorFunction<1,dim>
+ {
+ public:
+ ConvectionVelocity() : TensorFunction<1,dim>() {}
+
+ virtual Tensor<1,dim> value (const Point<dim> &p) const;
+ };
+
+
+
+ template <int dim>
+ Tensor<1,dim>
+ ConvectionVelocity<dim>::value(const Point<dim> &p) const
+ {
+ Tensor<1,dim> convection;
+ switch (dim)
+ {
+ case 1:
+ convection[0] = 1;
+ break;
+ case 2:
+ convection[0] = p[1];
+ convection[1] = -p[0];
+ break;
+ case 3:
+ convection[0] = p[1];
+ convection[1] = -p[0];
+ convection[2] = 1;
+ break;
+ default:
+ Assert(false, ExcNotImplemented());
+ }
+ return convection;
+ }
+
+
+
+ template <int dim>
+ class RightHandSide : public Function<dim>,
+ protected SolutionBase<dim>
+ {
+ public:
+ RightHandSide () : Function<dim>() {}
+
+ virtual double value (const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ private:
+ const ConvectionVelocity<dim> convection_velocity;
+ };
+
+
+ template <int dim>
+ double RightHandSide<dim>::value (const Point<dim> &p,
+ const unsigned int) const
+ {
+ Tensor<1,dim> convection = convection_velocity.value(p);
+ double return_value = 0;
+ for (unsigned int i=0; i<this->n_source_centers; ++i)
+ {
+ const Point<dim> x_minus_xi = p - this->source_centers[i];
+
+ return_value +=
+ ((2*dim - 2*convection*x_minus_xi - 4*x_minus_xi.square()/
+ (this->width * this->width)) /
+ (this->width * this->width) *
+ std::exp(-x_minus_xi.square() /
+ (this->width * this->width)));
+ }
+
+ return return_value / Utilities::fixed_power<dim>(std::sqrt(2 * numbers::PI)
+ * this->width);
+ }
+
+
+ template <int dim>
+ class HDG
+ {
+ public:
+ HDG (const unsigned int degree);
+ void run ();
+
+ private:
+
+ void setup_system ();
+ void assemble_system (const bool reconstruct_trace = false);
+ void solve ();
+ void postprocess ();
+ void refine_grid (const unsigned int cylce);
+ void output_results (const unsigned int cycle);
+
+ struct PerTaskData;
+ struct ScratchData;
+
+ struct PostProcessScratchData;
+
+ void assemble_system_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ ScratchData &scratch,
+ PerTaskData &task_data);
+
+ void copy_local_to_global(const PerTaskData &data);
+
+ void postprocess_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ PostProcessScratchData &scratch,
+ unsigned int &empty_data);
+
+
+ Triangulation<dim> triangulation;
+
+ FESystem<dim> fe_local;
+ DoFHandler<dim> dof_handler_local;
+ Vector<double> solution_local;
+
+ FE_FaceP<dim> fe;
+ DoFHandler<dim> dof_handler;
+ Vector<double> solution;
+ Vector<double> system_rhs;
+
+ FE_DGP<dim> fe_u_post;
+ DoFHandler<dim> dof_handler_u_post;
+ Vector<double> solution_u_post;
+
+ ConstraintMatrix constraints;
+
+ SparsityPattern sparsity_pattern;
+ SparseMatrix<double> system_matrix;
+
+ ConvergenceTable convergence_table;
+ };
+
+
+ template <int dim>
+ HDG<dim>::HDG (const unsigned int degree) :
+ fe_local (FE_DGP<dim>(degree), dim+1),
+ dof_handler_local (triangulation),
+ fe (degree),
+ dof_handler (triangulation),
+ fe_u_post (degree+1),
+ dof_handler_u_post (triangulation)
+ {}
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::setup_system ()
+ {
+ dof_handler_local.distribute_dofs(fe_local);
+ dof_handler.distribute_dofs(fe);
+ dof_handler_u_post.distribute_dofs(fe_u_post);
+
+ solution.reinit (dof_handler.n_dofs());
+ system_rhs.reinit (dof_handler.n_dofs());
+
+ solution_local.reinit (dof_handler_local.n_dofs());
+ solution_u_post.reinit (dof_handler_u_post.n_dofs());
+
+ constraints.clear ();
+ DoFTools::make_hanging_node_constraints (dof_handler, constraints);
+ typename FunctionMap<dim>::type boundary_functions;
+ Solution<dim> solution_function;
+ boundary_functions[0] = &solution_function;
+ VectorTools::project_boundary_values (dof_handler,
+ boundary_functions,
+ QGauss<dim-1>(fe.degree+1),
+ constraints);
+ constraints.close ();
+
+ {
+ CompressedSimpleSparsityPattern csp (dof_handler.n_dofs());
+ DoFTools::make_sparsity_pattern (dof_handler, csp,
+ constraints, false);
+ sparsity_pattern.copy_from(csp);
+ }
+ system_matrix.reinit (sparsity_pattern);
+ }
+
+
+
+ template <int dim>
+ struct HDG<dim>::PerTaskData
+ {
+ FullMatrix<double> cell_matrix;
+ Vector<double> cell_vector;
+ std::vector<types::global_dof_index> dof_indices;
+
+ bool trace_reconstruct;
+
+ PerTaskData(const unsigned int n_dofs, const bool trace_reconstruct)
+ : cell_matrix(n_dofs, n_dofs),
+ cell_vector(n_dofs),
+ dof_indices(n_dofs),
+ trace_reconstruct(trace_reconstruct)
+ {}
+ };
+
+
+
+ template <int dim>
+ struct HDG<dim>::ScratchData
+ {
+ FEValues<dim> fe_values_local;
+ FEFaceValues<dim> fe_face_values_local;
+ FEFaceValues<dim> fe_face_values;
+
+ FullMatrix<double> ll_matrix;
+ FullMatrix<double> lf_matrix;
+ FullMatrix<double> fl_matrix;
+ FullMatrix<double> tmp_matrix;
+ Vector<double> l_rhs;
+ Vector<double> tmp_rhs;
+
+ std::vector<Tensor<1,dim> > q_phi;
+ std::vector<double> q_phi_div;
+ std::vector<double> u_phi;
+ std::vector<Tensor<1,dim> > u_phi_grad;
+ std::vector<double> tr_phi;
+ std::vector<double> trace_values;
+
+ std::vector<std::vector<unsigned int> > fe_local_support_on_face;
+ std::vector<std::vector<unsigned int> > fe_support_on_face;
+
+ ConvectionVelocity<dim> convection_velocity;
+ RightHandSide<dim> right_hand_side;
+ const Solution<dim> exact_solution;
+
+ ScratchData(const FiniteElement<dim> &fe,
+ const FiniteElement<dim> &fe_local,
+ const QGauss<dim> &quadrature_formula,
+ const QGauss<dim-1> &face_quadrature_formula,
+ const UpdateFlags local_flags,
+ const UpdateFlags local_face_flags,
+ const UpdateFlags flags)
+ :
+ fe_values_local (fe_local, quadrature_formula, local_flags),
+ fe_face_values_local (fe_local, face_quadrature_formula, local_face_flags),
+ fe_face_values (fe, face_quadrature_formula, flags),
+ ll_matrix (fe_local.dofs_per_cell, fe_local.dofs_per_cell),
+ lf_matrix (fe_local.dofs_per_cell, fe.dofs_per_cell),
+ fl_matrix (fe.dofs_per_cell, fe_local.dofs_per_cell),
+ tmp_matrix (fe.dofs_per_cell, fe_local.dofs_per_cell),
+ l_rhs (fe_local.dofs_per_cell),
+ tmp_rhs (fe_local.dofs_per_cell),
+ q_phi (fe_local.dofs_per_cell),
+ q_phi_div (fe_local.dofs_per_cell),
+ u_phi (fe_local.dofs_per_cell),
+ u_phi_grad (fe_local.dofs_per_cell),
+ tr_phi (fe.dofs_per_cell),
+ trace_values(face_quadrature_formula.size()),
+ fe_local_support_on_face(GeometryInfo<dim>::faces_per_cell),
+ fe_support_on_face(GeometryInfo<dim>::faces_per_cell)
+ {
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int i=0; i<fe_local.dofs_per_cell; ++i)
+ {
+ if (fe_local.has_support_on_face(i,face))
+ {
+ fe_local_support_on_face[face].push_back(i);
+ }
+ }
+
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+ {
+ if (fe.has_support_on_face(i,face))
+ {
+ fe_support_on_face[face].push_back(i);
+ }
+ }
+ }
+
+ ScratchData(const ScratchData &sd)
+ :
+ fe_values_local (sd.fe_values_local.get_fe(),
+ sd.fe_values_local.get_quadrature(),
+ sd.fe_values_local.get_update_flags()),
+ fe_face_values_local (sd.fe_face_values_local.get_fe(),
+ sd.fe_face_values_local.get_quadrature(),
+ sd.fe_face_values_local.get_update_flags()),
+ fe_face_values (sd.fe_face_values.get_fe(),
+ sd.fe_face_values.get_quadrature(),
+ sd.fe_face_values.get_update_flags()),
+ ll_matrix (sd.ll_matrix),
+ lf_matrix (sd.lf_matrix),
+ fl_matrix (sd.fl_matrix),
+ tmp_matrix (sd.tmp_matrix),
+ l_rhs (sd.l_rhs),
+ tmp_rhs (sd.tmp_rhs),
+ q_phi (sd.q_phi),
+ q_phi_div (sd.q_phi_div),
+ u_phi (sd.u_phi),
+ u_phi_grad (sd.u_phi_grad),
+ tr_phi (sd.tr_phi),
+ trace_values(sd.trace_values),
+ fe_local_support_on_face(sd.fe_local_support_on_face),
+ fe_support_on_face(sd.fe_support_on_face)
+ {}
+ };
+
+
+
+ template <int dim>
+ struct HDG<dim>::PostProcessScratchData
+ {
+ FEValues<dim> fe_values_local;
+ FEValues<dim> fe_values;
+
+ std::vector<double> u_values;
+ std::vector<Tensor<1,dim> > u_gradients;
+ FullMatrix<double> cell_matrix;
+
+ Vector<double> cell_rhs;
+ Vector<double> cell_sol;
+
+ PostProcessScratchData(const FiniteElement<dim> &fe,
+ const FiniteElement<dim> &fe_local,
+ const QGauss<dim> &quadrature_formula,
+ const UpdateFlags local_flags,
+ const UpdateFlags flags)
+ :
+ fe_values_local (fe_local, quadrature_formula, local_flags),
+ fe_values (fe, quadrature_formula, flags),
+ u_values (quadrature_formula.size()),
+ u_gradients (quadrature_formula.size()),
+ cell_matrix (fe.dofs_per_cell, fe.dofs_per_cell),
+ cell_rhs (fe.dofs_per_cell),
+ cell_sol (fe.dofs_per_cell)
+ {}
+
+ PostProcessScratchData(const PostProcessScratchData &sd)
+ :
+ fe_values_local (sd.fe_values_local.get_fe(),
+ sd.fe_values_local.get_quadrature(),
+ sd.fe_values_local.get_update_flags()),
+ fe_values (sd.fe_values.get_fe(),
+ sd.fe_values.get_quadrature(),
+ sd.fe_values.get_update_flags()),
+ u_values (sd.u_values),
+ u_gradients (sd.u_gradients),
+ cell_matrix (sd.cell_matrix),
+ cell_rhs (sd.cell_rhs),
+ cell_sol (sd.cell_sol)
+ {}
+ };
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::assemble_system (const bool trace_reconstruct)
+ {
+ const QGauss<dim> quadrature_formula(fe.degree+1);
+ const QGauss<dim-1> face_quadrature_formula(fe.degree+1);
+
+ const UpdateFlags local_flags (update_values | update_gradients |
+ update_JxW_values | update_quadrature_points);
+
+ const UpdateFlags local_face_flags (update_values);
+
+ const UpdateFlags flags ( update_values | update_normal_vectors |
+ update_quadrature_points |
+ update_JxW_values);
+
+ PerTaskData task_data (fe.dofs_per_cell,
+ trace_reconstruct);
+ ScratchData scratch (fe, fe_local,
+ quadrature_formula,
+ face_quadrature_formula,
+ local_flags,
+ local_face_flags,
+ flags);
+
+ WorkStream::run(dof_handler.begin_active(),
+ dof_handler.end(),
+ *this,
+ &HDG<dim>::assemble_system_one_cell,
+ &HDG<dim>::copy_local_to_global,
+ scratch,
+ task_data);
+ }
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::assemble_system_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ ScratchData &scratch,
+ PerTaskData &task_data)
+ {
+ typename DoFHandler<dim>::active_cell_iterator
+ loc_cell (&triangulation,
+ cell->level(),
+ cell->index(),
+ &dof_handler_local);
+
+ const unsigned int n_q_points = scratch.fe_values_local.get_quadrature().size();
+ const unsigned int n_face_q_points = scratch.fe_face_values_local.get_quadrature().size();
+
+ const unsigned int loc_dofs_per_cell = scratch.fe_values_local.get_fe().dofs_per_cell;
+
+ const FEValuesExtractors::Vector fluxes (0);
+ const FEValuesExtractors::Scalar scalar (dim);
+
+ scratch.ll_matrix = 0;
+ scratch.l_rhs = 0;
+ if (!task_data.trace_reconstruct)
+ {
+ scratch.lf_matrix = 0;
+ scratch.fl_matrix = 0;
+ task_data.cell_matrix = 0;
+ task_data.cell_vector = 0;
+ }
+ scratch.fe_values_local.reinit (loc_cell);
+
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ const double rhs_value
+ = scratch.right_hand_side.value(scratch.fe_values_local.quadrature_point(q));
+ const Tensor<1,dim> convection
+ = scratch.convection_velocity.value(scratch.fe_values_local.quadrature_point(q));
+ const double JxW = scratch.fe_values_local.JxW(q);
+ for (unsigned int k=0; k<loc_dofs_per_cell; ++k)
+ {
+ scratch.q_phi[k] = scratch.fe_values_local[fluxes].value(k,q);
+ scratch.q_phi_div[k] = scratch.fe_values_local[fluxes].divergence(k,q);
+ scratch.u_phi[k] = scratch.fe_values_local[scalar].value(k,q);
+ scratch.u_phi_grad[k] = scratch.fe_values_local[scalar].gradient(k,q);
+ }
+ for (unsigned int i=0; i<loc_dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<loc_dofs_per_cell; ++j)
+ scratch.ll_matrix(i,j) += (
+ scratch.q_phi[i] * scratch.q_phi[j]
+ -
+ scratch.q_phi_div[i] * scratch.u_phi[j]
+ +
+ scratch.u_phi[i] * scratch.q_phi_div[j]
+ -
+ (scratch.u_phi_grad[i] * convection) * scratch.u_phi[j]
+ ) * JxW;
+ scratch.l_rhs(i) += scratch.u_phi[i] * rhs_value * JxW;
+ }
+ }
+
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ {
+ scratch.fe_face_values_local.reinit(loc_cell, face);
+ scratch.fe_face_values.reinit(cell, face);
+
+ if (task_data.trace_reconstruct)
+ scratch.fe_face_values.get_function_values (solution, scratch.trace_values);
+
+ for (unsigned int q=0; q<n_face_q_points; ++q)
+ {
+ const double JxW = scratch.fe_face_values.JxW(q);
+ const Point<dim> quadrature_point =
+ scratch.fe_face_values.quadrature_point(q);
+ const Point<dim> normal = scratch.fe_face_values.normal_vector(q);
+ const Tensor<1,dim> convection
+ = scratch.convection_velocity.value(quadrature_point);
+
+ const double tau_stab = (5. +
+ std::abs(convection * normal));
+
+ for (unsigned int k=0; k<scratch.fe_local_support_on_face[face].size(); ++k)
+ {
+ const unsigned int kk=scratch.fe_local_support_on_face[face][k];
+ scratch.q_phi[k] = scratch.fe_face_values_local[fluxes].value(kk,q);
+ scratch.u_phi[k] = scratch.fe_face_values_local[scalar].value(kk,q);
+ }
+
+ if (!task_data.trace_reconstruct)
+ {
+ for (unsigned int k=0; k<scratch.fe_support_on_face[face].size(); ++k)
+ scratch.tr_phi[k] =
+ scratch.fe_face_values.shape_value(scratch.fe_support_on_face[face][k],q);
+ for (unsigned int i=0; i<scratch.fe_local_support_on_face[face].size(); ++i)
+ for (unsigned int j=0; j<scratch.fe_support_on_face[face].size(); ++j)
+ {
+ const unsigned int ii=scratch.fe_local_support_on_face[face][i];
+ const unsigned int jj=scratch.fe_support_on_face[face][j];
+ scratch.lf_matrix(ii,jj) += (
+ (scratch.q_phi[i] * normal
+ +
+ (convection * normal -
+ tau_stab) * scratch.u_phi[i])
+ * scratch.tr_phi[j]
+ ) * JxW;
+
+ scratch.fl_matrix(jj,ii) -= (
+ (scratch.q_phi[i] * normal
+ +
+ tau_stab * scratch.u_phi[i])
+ * scratch.tr_phi[j]
+ ) * JxW;
+ }
+
+ for (unsigned int i=0; i<scratch.fe_support_on_face[face].size(); ++i)
+ for (unsigned int j=0; j<scratch.fe_support_on_face[face].size(); ++j)
+ {
+ const unsigned int ii=scratch.fe_support_on_face[face][i];
+ const unsigned int jj=scratch.fe_support_on_face[face][j];
+ task_data.cell_matrix(ii,jj) += (
+ (convection * normal - tau_stab) *
+ scratch.tr_phi[i] * scratch.tr_phi[j]
+ ) * JxW;
+ }
+
+ if (cell->face(face)->at_boundary()
+ &&
+ (cell->face(face)->boundary_indicator() == 1))
+ {
+ const double neumann_value =
+ - scratch.exact_solution.gradient (quadrature_point) * normal
+ + convection * normal * scratch.exact_solution.value(quadrature_point);
+ for (unsigned int i=0; i<scratch.fe_support_on_face[face].size(); ++i)
+ {
+ const unsigned int ii=scratch.fe_support_on_face[face][i];
+ task_data.cell_vector(ii) += scratch.tr_phi[i] * neumann_value * JxW;
+ }
+ }
+ }
+
+ for (unsigned int i=0; i<scratch.fe_local_support_on_face[face].size(); ++i)
+ for (unsigned int j=0; j<scratch.fe_local_support_on_face[face].size(); ++j)
+ {
+ const unsigned int ii=scratch.fe_local_support_on_face[face][i];
+ const unsigned int jj=scratch.fe_local_support_on_face[face][j];
+ scratch.ll_matrix(ii,jj) += tau_stab * scratch.u_phi[i] * scratch.u_phi[j] * JxW;
+ }
+
+ if (task_data.trace_reconstruct)
+ for (unsigned int i=0; i<scratch.fe_local_support_on_face[face].size(); ++i)
+ {
+ const unsigned int ii=scratch.fe_local_support_on_face[face][i];
+ scratch.l_rhs(ii) -= (scratch.q_phi[i] * normal
+ +
+ scratch.u_phi[i] * (convection * normal - tau_stab)
+ ) * scratch.trace_values[q] * JxW;
+ }
+ }
+ }
+
+ scratch.ll_matrix.gauss_jordan();
+
+ if (task_data.trace_reconstruct == false)
+ {
+ scratch.fl_matrix.mmult(scratch.tmp_matrix, scratch.ll_matrix);
+ scratch.tmp_matrix.vmult_add(task_data.cell_vector, scratch.l_rhs);
+ scratch.tmp_matrix.mmult(task_data.cell_matrix, scratch.lf_matrix, true);
+ cell->get_dof_indices(task_data.dof_indices);
+ }
+ else
+ {
+ scratch.ll_matrix.vmult(scratch.tmp_rhs, scratch.l_rhs);
+ loc_cell->set_dof_values(scratch.tmp_rhs, solution_local);
+ }
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::copy_local_to_global(const PerTaskData &data)
+ {
+ if (data.trace_reconstruct == false)
+ constraints.distribute_local_to_global (data.cell_matrix,
+ data.cell_vector,
+ data.dof_indices,
+ system_matrix, system_rhs);
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::solve ()
+ {
+ SolverControl solver_control (system_matrix.m()*10,
+ 1e-12*system_rhs.l2_norm());
+ std::ostringstream stream;
+ deallog.attach(stream);
+ SolverBicgstab<> solver (solver_control, false);
+ solver.solve (system_matrix, solution, system_rhs,
+ PreconditionIdentity());
+ deallog.attach(logfile);
+
+ system_matrix.clear();
+
+ constraints.distribute(solution);
+
+ assemble_system(true);
+ }
+
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::postprocess()
+ {
+ {
+ const QGauss<dim> quadrature_formula(fe_u_post.degree+1);
+ const UpdateFlags local_flags (update_values);
+ const UpdateFlags flags ( update_values | update_gradients |
+ update_JxW_values);
+
+ PostProcessScratchData scratch (fe_u_post, fe_local,
+ quadrature_formula,
+ local_flags,
+ flags);
+
+ WorkStream::run(dof_handler_u_post.begin_active(),
+ dof_handler_u_post.end(),
+ std_cxx1x::bind (&HDG<dim>::postprocess_one_cell,
+ std_cxx1x::ref(*this),
+ std_cxx1x::_1, std_cxx1x::_2, std_cxx1x::_3),
+ std_cxx1x::function<void(const unsigned int &)>(),
+ scratch,
+ 0U);
+ }
+
+ Vector<float> difference_per_cell (triangulation.n_active_cells());
+
+ ComponentSelectFunction<dim> value_select (dim, dim+1);
+ VectorTools::integrate_difference (dof_handler_local,
+ solution_local,
+ SolutionAndGradient<dim>(),
+ difference_per_cell,
+ QGauss<dim>(fe.degree+2),
+ VectorTools::L2_norm,
+ &value_select);
+ const double L2_error = difference_per_cell.l2_norm();
+
+ ComponentSelectFunction<dim> gradient_select (std::pair<unsigned int,unsigned int>(0, dim),
+ dim+1);
+ VectorTools::integrate_difference (dof_handler_local,
+ solution_local,
+ SolutionAndGradient<dim>(),
+ difference_per_cell,
+ QGauss<dim>(fe.degree+2),
+ VectorTools::L2_norm,
+ &gradient_select);
+ const double grad_error = difference_per_cell.l2_norm();
+
+ VectorTools::integrate_difference (dof_handler_u_post,
+ solution_u_post,
+ Solution<dim>(),
+ difference_per_cell,
+ QGauss<dim>(fe.degree+3),
+ VectorTools::L2_norm);
+ const double post_error = difference_per_cell.l2_norm();
+
+ convergence_table.add_value("cells", triangulation.n_active_cells());
+ convergence_table.add_value("dofs", dof_handler.n_dofs());
+ convergence_table.add_value("val L2", L2_error);
+ convergence_table.add_value("grad L2", grad_error);
+ convergence_table.add_value("val L2-post", post_error);
+ }
+
+
+
+ template <int dim>
+ void
+ HDG<dim>::postprocess_one_cell (const typename DoFHandler<dim>::active_cell_iterator &cell,
+ PostProcessScratchData &scratch,
+ unsigned int &)
+ {
+ typename DoFHandler<dim>::active_cell_iterator
+ loc_cell (&triangulation,
+ cell->level(),
+ cell->index(),
+ &dof_handler_local);
+
+ scratch.fe_values_local.reinit (loc_cell);
+ scratch.fe_values.reinit(cell);
+
+ FEValuesExtractors::Vector fluxes(0);
+ FEValuesExtractors::Scalar scalar(dim);
+
+ const unsigned int n_q_points = scratch.fe_values.get_quadrature().size();
+ const unsigned int dofs_per_cell = scratch.fe_values.dofs_per_cell;
+
+ scratch.fe_values_local[scalar].get_function_values(solution_local, scratch.u_values);
+ scratch.fe_values_local[fluxes].get_function_values(solution_local, scratch.u_gradients);
+
+ double sum = 0;
+ for (unsigned int i=1; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum += (scratch.fe_values.shape_grad(i,q) *
+ scratch.fe_values.shape_grad(j,q)
+ ) * scratch.fe_values.JxW(q);
+ scratch.cell_matrix(i,j) = sum;
+ }
+
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum -= (scratch.fe_values.shape_grad(i,q) * scratch.u_gradients[q]
+ ) * scratch.fe_values.JxW(q);
+ scratch.cell_rhs(i) = sum;
+ }
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum += scratch.fe_values.shape_value(j,q) * scratch.fe_values.JxW(q);
+ scratch.cell_matrix(0,j) = sum;
+ }
+ {
+ sum = 0;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ sum += scratch.u_values[q] * scratch.fe_values.JxW(q);
+ scratch.cell_rhs(0) = sum;
+ }
+
+ scratch.cell_matrix.gauss_jordan();
+ scratch.cell_matrix.vmult(scratch.cell_sol, scratch.cell_rhs);
+ cell->distribute_local_to_global(scratch.cell_sol, solution_u_post);
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::output_results (const unsigned int cycle)
+ {
+ // not included in test
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::refine_grid (const unsigned int cycle)
+ {
+ // only global refinement
+ triangulation.clear();
+ GridGenerator::subdivided_hyper_cube (triangulation, 2+(cycle%2), -1, 1);
+ triangulation.refine_global(3-dim+cycle/2);
+
+ typename Triangulation<dim>::cell_iterator
+ cell = triangulation.begin (),
+ endc = triangulation.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary())
+ for (unsigned int d=0; d<dim; ++d)
+ if ((std::fabs(cell->face(face)->center()(d) - (1)) < 1e-12))
+ cell->face(face)->set_boundary_indicator (1);
+ }
+
+
+
+ template <int dim>
+ void HDG<dim>::run ()
+ {
+ for (unsigned int cycle=0; cycle<12-3*dim; ++cycle)
+ {
+ refine_grid (cycle);
+ setup_system ();
+ assemble_system (false);
+ solve ();
+ postprocess();
+ output_results (cycle);
+ }
+
+ convergence_table.set_precision("val L2", 3);
+ convergence_table.set_scientific("val L2", true);
+ convergence_table.set_precision("grad L2", 3);
+ convergence_table.set_scientific("grad L2", true);
+ convergence_table.set_precision("val L2-post", 3);
+ convergence_table.set_scientific("val L2-post", true);
+
+ convergence_table
+ .evaluate_convergence_rates("val L2", "cells", ConvergenceTable::reduction_rate_log2, dim);
+ convergence_table
+ .evaluate_convergence_rates("grad L2", "cells", ConvergenceTable::reduction_rate_log2, dim);
+ convergence_table
+ .evaluate_convergence_rates("val L2-post", "cells", ConvergenceTable::reduction_rate_log2, dim);
+ convergence_table.write_text(deallog.get_file_stream());
+ }
+
+} // end of namespace Step51
+
+
+
+
+int main ()
+{
+ deallog << std::setprecision(6);
+ logfile << std::setprecision(6);
+
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ {
+ Step51::HDG<1> hdg_problem (1);
+ hdg_problem.run ();
+ }
+
+ {
+ Step51::HDG<1> hdg_problem (3);
+ hdg_problem.run ();
+ }
+
+ {
+ Step51::HDG<2> hdg_problem (1);
+ hdg_problem.run ();
+ }
+
+ {
+ Step51::HDG<2> hdg_problem (2);
+ hdg_problem.run ();
+ }
+
+ return 0;
+}
--- /dev/null
+
+
+
+
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+8 9 4.080e-01 - 1.722e+00 - 3.362e-01 -
+12 13 1.659e-01 2.22 8.766e-01 1.67 2.151e-02 6.78
+16 17 7.996e-02 2.54 4.531e-01 2.29 1.125e-02 2.25
+24 25 3.705e-02 1.90 2.028e-01 1.98 3.372e-03 2.97
+32 33 2.125e-02 1.93 1.140e-01 2.00 1.430e-03 2.98
+48 49 9.610e-03 1.96 5.048e-02 2.01 4.242e-04 3.00
+64 65 5.449e-03 1.97 2.831e-02 2.01 1.787e-04 3.00
+96 97 2.440e-03 1.98 1.253e-02 2.01 5.281e-05 3.01
+128 129 1.377e-03 1.99 7.035e-03 2.01 2.224e-05 3.01
+
+
+
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+8 9 2.141e-02 - 1.398e-01 - 3.487e-03 -
+12 13 6.701e-03 2.87 3.811e-02 3.21 4.976e-04 4.80
+16 17 1.693e-03 4.78 9.999e-03 4.65 1.085e-04 5.29
+24 25 3.501e-04 3.89 2.009e-03 3.96 1.440e-05 4.98
+32 33 1.126e-04 3.94 6.373e-04 3.99 3.412e-06 5.01
+48 49 2.256e-05 3.97 1.259e-04 4.00 4.472e-07 5.01
+64 65 7.179e-06 3.98 3.980e-05 4.00 1.057e-07 5.01
+96 97 1.425e-06 3.99 7.848e-06 4.00 1.386e-08 5.01
+128 129 4.519e-07 3.99 2.481e-06 4.00 3.285e-09 5.01
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+16 80 1.043e+01 - 1.616e+01 - 1.034e+01 -
+36 168 3.699e+00 2.56 8.081e+00 1.71 3.637e+00 2.58
+64 288 8.022e-01 5.31 4.671e+00 1.91 4.622e-01 7.17
+144 624 2.947e-01 2.47 2.255e+00 1.80 6.403e-02 4.88
+256 1088 1.638e-01 2.04 1.343e+00 1.80 2.937e-02 2.71
+576 2400 7.616e-02 1.89 6.522e-01 1.78 9.203e-03 2.86
+
+
+
+
+
+
+cells dofs val L2 grad L2 val L2-post
+16 120 8.296e-01 - 6.543e+00 - 4.572e-01 -
+36 252 5.045e-01 1.23 3.062e+00 1.87 3.570e-01 0.61
+64 432 1.736e-01 3.71 1.503e+00 2.47 6.468e-02 5.94
+144 936 5.584e-02 2.80 5.042e-01 2.69 1.006e-02 4.59
+256 1632 2.731e-02 2.49 2.274e-01 2.77 3.120e-03 4.07
+576 3600 8.582e-03 2.85 7.254e-02 2.82 6.213e-04 3.98
// is the tangential component of the
// perturbation induced in the
// velocity.
- tangential_derivative.reinit(dof_handler_q.n_dofs());
- tangential_velocity.reinit(dof_handler_q.n_dofs());
- error.reinit(dof_handler_q.n_dofs());
+ tangential_velocity.reinit(tria.n_active_cells());
+ tangential_derivative.reinit(tria.n_active_cells());
+ error.reinit(tria.n_active_cells());
QMidpoint<spacedim-1> q_midpoint;
QTrapez<spacedim-1> q_trapez;
const QIterated<spacedim-1> q_iterated(q_midpoint, 1);
DataOut<spacedim-1, DoFHandler<spacedim-1,spacedim> > dataout;
dataout.attach_dof_handler(dof_handler_q);
- dataout.add_data_vector(smooth_solution, "linear_potential");
- dataout.add_data_vector(tangential_derivative, "tangential_velocity");
- dataout.add_data_vector(error, "error");
+ dataout.add_data_vector(dof_handler_q, smooth_solution, "linear_potential");
+ dataout.add_data_vector(tangential_derivative, "tangential_velocity", DataOut<spacedim-1, DoFHandler<spacedim-1,spacedim> >::type_cell_data);
+ dataout.add_data_vector(error, "error", DataOut<spacedim-1, DoFHandler<spacedim-1,spacedim> >::type_cell_data);
dataout.build_patches();
// dataout.build_patches(fe_q.degree);
dataout.write_vtk(logfile);
POINT_DATA 40
SCALARS linear_potential double 1
LOOKUP_TABLE default
-3.77476e-15 3.77476e-15 5.09391 5.09391 9.68919 9.68919 13.3360 13.3360 15.6774 15.6774 16.4842 16.4842 15.6774 15.6774 13.3360 13.3360 9.68919 9.68919 5.09391 5.09391 1.77636e-15 1.77636e-15 -5.09391 -5.09391 -9.68919 -9.68919 -13.3360 -13.3360 -15.6774 -15.6774 -16.4842 -16.4842 -15.6774 -15.6774 -13.3360 -13.3360 -9.68919 -9.68919 -5.09391 -5.09391
+3.77476e-15 5.09391 5.09391 9.68919 9.68919 13.3360 13.3360 15.6774 15.6774 16.4842 16.4842 15.6774 15.6774 13.3360 13.3360 9.68919 9.68919 5.09391 5.09391 1.77636e-15 1.77636e-15 -5.09391 -5.09391 -9.68919 -9.68919 -13.3360 -13.3360 -15.6774 -15.6774 -16.4842 -16.4842 -15.6774 -15.6774 -13.3360 -13.3360 -9.68919 -9.68919 -5.09391 -5.09391 3.77476e-15
SCALARS tangential_velocity double 1
LOOKUP_TABLE default
2.61582 2.61582 2.35976 2.35976 1.87272 1.87272 1.20236 1.20236 0.414305 0.414305 -0.414305 -0.414305 -1.20236 -1.20236 -1.87272 -1.87272 -2.35976 -2.35976 -2.61582 -2.61582 -2.61582 -2.61582 -2.35976 -2.35976 -1.87272 -1.87272 -1.20236 -1.20236 -0.414305 -0.414305 0.414305 0.414305 1.20236 1.20236 1.87272 1.87272 2.35976 2.35976 2.61582 2.61582
POINT_DATA 80
SCALARS linear_potential double 1
LOOKUP_TABLE default
--2.22045e-16 -2.22045e-16 2.07761 2.07761 4.10406 4.10406 6.02946 6.02946 7.80639 7.80639 9.39110 9.39110 10.7446 10.7446 11.8335 11.8335 12.6310 12.6310 13.1175 13.1175 13.2810 13.2810 13.1175 13.1175 12.6310 12.6310 11.8335 11.8335 10.7446 10.7446 9.39110 9.39110 7.80639 7.80639 6.02946 6.02946 4.10406 4.10406 2.07761 2.07761 8.88178e-16 8.88178e-16 -2.07761 -2.07761 -4.10406 -4.10406 -6.02946 -6.02946 -7.80639 -7.80639 -9.39110 -9.39110 -10.7446 -10.7446 -11.8335 -11.8335 -12.6310 -12.6310 -13.1175 -13.1175 -13.2810 -13.2810 -13.1175 -13.1175 -12.6310 -12.6310 -11.8335 -11.8335 -10.7446 -10.7446 -9.39110 -9.39110 -7.80639 -7.80639 -6.02946 -6.02946 -4.10406 -4.10406 -2.07761 -2.07761
+-2.22045e-16 2.07761 2.07761 4.10406 4.10406 6.02946 6.02946 7.80639 7.80639 9.39110 9.39110 10.7446 10.7446 11.8335 11.8335 12.6310 12.6310 13.1175 13.1175 13.2810 13.2810 13.1175 13.1175 12.6310 12.6310 11.8335 11.8335 10.7446 10.7446 9.39110 9.39110 7.80639 7.80639 6.02946 6.02946 4.10406 4.10406 2.07761 2.07761 8.88178e-16 8.88178e-16 -2.07761 -2.07761 -4.10406 -4.10406 -6.02946 -6.02946 -7.80639 -7.80639 -9.39110 -9.39110 -10.7446 -10.7446 -11.8335 -11.8335 -12.6310 -12.6310 -13.1175 -13.1175 -13.2810 -13.2810 -13.1175 -13.1175 -12.6310 -12.6310 -11.8335 -11.8335 -10.7446 -10.7446 -9.39110 -9.39110 -7.80639 -7.80639 -6.02946 -6.02946 -4.10406 -4.10406 -2.07761 -2.07761 -2.22045e-16
SCALARS tangential_velocity double 1
LOOKUP_TABLE default
2.32093 2.32093 2.26378 2.26378 2.15089 2.15089 1.98503 1.98503 1.77030 1.77030 1.51198 1.51198 1.21643 1.21643 0.890926 0.890926 0.543485 0.543485 0.182661 0.182661 -0.182661 -0.182661 -0.543485 -0.543485 -0.890926 -0.890926 -1.21643 -1.21643 -1.51198 -1.51198 -1.77030 -1.77030 -1.98503 -1.98503 -2.15089 -2.15089 -2.26378 -2.26378 -2.32093 -2.32093 -2.32093 -2.32093 -2.26378 -2.26378 -2.15089 -2.15089 -1.98503 -1.98503 -1.77030 -1.77030 -1.51198 -1.51198 -1.21643 -1.21643 -0.890926 -0.890926 -0.543485 -0.543485 -0.182661 -0.182661 0.182661 0.182661 0.543485 0.543485 0.890926 0.890926 1.21643 1.21643 1.51198 1.51198 1.77030 1.77030 1.98503 1.98503 2.15089 2.15089 2.26378 2.26378 2.32093 2.32093
LOOKUP_TABLE default
0.327091 0.327091 0.319037 0.319037 0.303127 0.303127 0.279753 0.279753 0.249491 0.249491 0.213085 0.213085 0.171433 0.171433 0.125559 0.125559 0.0765940 0.0765940 0.0257426 0.0257426 -0.0257426 -0.0257426 -0.0765940 -0.0765940 -0.125559 -0.125559 -0.171433 -0.171433 -0.213085 -0.213085 -0.249491 -0.249491 -0.279753 -0.279753 -0.303127 -0.303127 -0.319037 -0.319037 -0.327091 -0.327091 -0.327091 -0.327091 -0.319037 -0.319037 -0.303127 -0.303127 -0.279753 -0.279753 -0.249491 -0.249491 -0.213085 -0.213085 -0.171433 -0.171433 -0.125559 -0.125559 -0.0765940 -0.0765940 -0.0257426 -0.0257426 0.0257426 0.0257426 0.0765940 0.0765940 0.125559 0.125559 0.171433 0.171433 0.213085 0.213085 0.249491 0.249491 0.279753 0.279753 0.303127 0.303127 0.319037 0.319037 0.327091 0.327091
DEAL:cg::Starting value 57.6585
-DEAL:cg::Convergence step 2 value 2.81863e-13
+DEAL:cg::Convergence step 2 value 2.81867e-13
# vtk DataFile Version 3.0
#This file was generated
ASCII
POINT_DATA 160
SCALARS linear_potential double 1
LOOKUP_TABLE default
--8.04912e-16 -8.04912e-16 0.913864 0.913864 1.82209 1.82209 2.71909 2.71909 3.59932 3.59932 4.45736 4.45736 5.28792 5.28792 6.08588 6.08588 6.84632 6.84632 7.56454 7.56454 8.23613 8.23613 8.85694 8.85694 9.42315 9.42315 9.93125 9.93125 10.3781 10.3781 10.7610 10.7610 11.0776 11.0776 11.3258 11.3258 11.5042 11.5042 11.6117 11.6117 11.6476 11.6476 11.6117 11.6117 11.5042 11.5042 11.3258 11.3258 11.0776 11.0776 10.7610 10.7610 10.3781 10.3781 9.93125 9.93125 9.42315 9.42315 8.85694 8.85694 8.23613 8.23613 7.56454 7.56454 6.84632 6.84632 6.08588 6.08588 5.28792 5.28792 4.45736 4.45736 3.59932 3.59932 2.71909 2.71909 1.82209 1.82209 0.913864 0.913864 1.69309e-15 1.69309e-15 -0.913864 -0.913864 -1.82209 -1.82209 -2.71909 -2.71909 -3.59932 -3.59932 -4.45736 -4.45736 -5.28792 -5.28792 -6.08588 -6.08588 -6.84632 -6.84632 -7.56454 -7.56454 -8.23613 -8.23613 -8.85694 -8.85694 -9.42315 -9.42315 -9.93125 -9.93125 -10.3781 -10.3781 -10.7610 -10.7610 -11.0776 -11.0776 -11.3258 -11.3258 -11.5042 -11.5042 -11.6117 -11.6117 -11.6476 -11.6476 -11.6117 -11.6117 -11.5042 -11.5042 -11.3258 -11.3258 -11.0776 -11.0776 -10.7610 -10.7610 -10.3781 -10.3781 -9.93125 -9.93125 -9.42315 -9.42315 -8.85694 -8.85694 -8.23613 -8.23613 -7.56454 -7.56454 -6.84632 -6.84632 -6.08588 -6.08588 -5.28792 -5.28792 -4.45736 -4.45736 -3.59932 -3.59932 -2.71909 -2.71909 -1.82209 -1.82209 -0.913864 -0.913864
+-8.04912e-16 0.913864 0.913864 1.82209 1.82209 2.71909 2.71909 3.59932 3.59932 4.45736 4.45736 5.28792 5.28792 6.08588 6.08588 6.84632 6.84632 7.56454 7.56454 8.23613 8.23613 8.85694 8.85694 9.42315 9.42315 9.93125 9.93125 10.3781 10.3781 10.7610 10.7610 11.0776 11.0776 11.3258 11.3258 11.5042 11.5042 11.6117 11.6117 11.6476 11.6476 11.6117 11.6117 11.5042 11.5042 11.3258 11.3258 11.0776 11.0776 10.7610 10.7610 10.3781 10.3781 9.93125 9.93125 9.42315 9.42315 8.85694 8.85694 8.23613 8.23613 7.56454 7.56454 6.84632 6.84632 6.08588 6.08588 5.28792 5.28792 4.45736 4.45736 3.59932 3.59932 2.71909 2.71909 1.82209 1.82209 0.913864 0.913864 1.74860e-15 1.74860e-15 -0.913864 -0.913864 -1.82209 -1.82209 -2.71909 -2.71909 -3.59932 -3.59932 -4.45736 -4.45736 -5.28792 -5.28792 -6.08588 -6.08588 -6.84632 -6.84632 -7.56454 -7.56454 -8.23613 -8.23613 -8.85694 -8.85694 -9.42315 -9.42315 -9.93125 -9.93125 -10.3781 -10.3781 -10.7610 -10.7610 -11.0776 -11.0776 -11.3258 -11.3258 -11.5042 -11.5042 -11.6117 -11.6117 -11.6476 -11.6476 -11.6117 -11.6117 -11.5042 -11.5042 -11.3258 -11.3258 -11.0776 -11.0776 -10.7610 -10.7610 -10.3781 -10.3781 -9.93125 -9.93125 -9.42315 -9.42315 -8.85694 -8.85694 -8.23613 -8.23613 -7.56454 -7.56454 -6.84632 -6.84632 -6.08588 -6.08588 -5.28792 -5.28792 -4.45736 -4.45736 -3.59932 -3.59932 -2.71909 -2.71909 -1.82209 -1.82209 -0.913864 -0.913864 -8.04912e-16
SCALARS tangential_velocity double 1
LOOKUP_TABLE default
2.16310 2.16310 2.14976 2.14976 2.12317 2.12317 2.08349 2.08349 2.03096 2.03096 1.96592 1.96592 1.88875 1.88875 1.79994 1.79994 1.70003 1.70003 1.58964 1.58964 1.46944 1.46944 1.34019 1.34019 1.20268 1.20268 1.05775 1.05775 0.906300 0.906300 0.749262 0.749262 0.587605 0.587605 0.422325 0.422325 0.254441 0.254441 0.0849883 0.0849883 -0.0849883 -0.0849883 -0.254441 -0.254441 -0.422325 -0.422325 -0.587605 -0.587605 -0.749262 -0.749262 -0.906300 -0.906300 -1.05775 -1.05775 -1.20268 -1.20268 -1.34019 -1.34019 -1.46944 -1.46944 -1.58964 -1.58964 -1.70003 -1.70003 -1.79994 -1.79994 -1.88875 -1.88875 -1.96592 -1.96592 -2.03096 -2.03096 -2.08349 -2.08349 -2.12317 -2.12317 -2.14976 -2.14976 -2.16310 -2.16310 -2.16310 -2.16310 -2.14976 -2.14976 -2.12317 -2.12317 -2.08349 -2.08349 -2.03096 -2.03096 -1.96592 -1.96592 -1.88875 -1.88875 -1.79994 -1.79994 -1.70003 -1.70003 -1.58964 -1.58964 -1.46944 -1.46944 -1.34019 -1.34019 -1.20268 -1.20268 -1.05775 -1.05775 -0.906300 -0.906300 -0.749262 -0.749262 -0.587605 -0.587605 -0.422325 -0.422325 -0.254441 -0.254441 -0.0849883 -0.0849883 0.0849883 0.0849883 0.254441 0.254441 0.422325 0.422325 0.587605 0.587605 0.749262 0.749262 0.906300 0.906300 1.05775 1.05775 1.20268 1.20268 1.34019 1.34019 1.46944 1.46944 1.58964 1.58964 1.70003 1.70003 1.79994 1.79994 1.88875 1.88875 1.96592 1.96592 2.03096 2.03096 2.08349 2.08349 2.12317 2.12317 2.14976 2.14976 2.16310 2.16310
POINT_DATA 320
SCALARS linear_potential double 1
LOOKUP_TABLE default
-3.05311e-15 3.05311e-15 0.424999 0.424999 0.849342 0.849342 1.27238 1.27238 1.69345 1.69345 2.11191 2.11191 2.52711 2.52711 2.93842 2.93842 3.34520 3.34520 3.74682 3.74682 4.14266 4.14266 4.53211 4.53211 4.91458 4.91458 5.28947 5.28947 5.65620 5.65620 6.01421 6.01421 6.36295 6.36295 6.70187 6.70187 7.03046 7.03046 7.34821 7.34821 7.65463 7.65463 7.94925 7.94925 8.23161 8.23161 8.50128 8.50128 8.75784 8.75784 9.00090 9.00090 9.23008 9.23008 9.44502 9.44502 9.64540 9.64540 9.83091 9.83091 10.0013 10.0013 10.1562 10.1562 10.2955 10.2955 10.4189 10.4189 10.5262 10.5262 10.6173 10.6173 10.6920 10.6920 10.7503 10.7503 10.7919 10.7919 10.8169 10.8169 10.8253 10.8253 10.8169 10.8169 10.7919 10.7919 10.7503 10.7503 10.6920 10.6920 10.6173 10.6173 10.5262 10.5262 10.4189 10.4189 10.2955 10.2955 10.1562 10.1562 10.0013 10.0013 9.83091 9.83091 9.64540 9.64540 9.44502 9.44502 9.23008 9.23008 9.00090 9.00090 8.75784 8.75784 8.50128 8.50128 8.23161 8.23161 7.94925 7.94925 7.65463 7.65463 7.34821 7.34821 7.03046 7.03046 6.70187 6.70187 6.36295 6.36295 6.01421 6.01421 5.65620 5.65620 5.28947 5.28947 4.91458 4.91458 4.53211 4.53211 4.14266 4.14266 3.74682 3.74682 3.34520 3.34520 2.93842 2.93842 2.52711 2.52711 2.11191 2.11191 1.69345 1.69345 1.27238 1.27238 0.849342 0.849342 0.424999 0.424999 6.38378e-16 6.38378e-16 -0.424999 -0.424999 -0.849342 -0.849342 -1.27238 -1.27238 -1.69345 -1.69345 -2.11191 -2.11191 -2.52711 -2.52711 -2.93842 -2.93842 -3.34520 -3.34520 -3.74682 -3.74682 -4.14266 -4.14266 -4.53211 -4.53211 -4.91458 -4.91458 -5.28947 -5.28947 -5.65620 -5.65620 -6.01421 -6.01421 -6.36295 -6.36295 -6.70187 -6.70187 -7.03046 -7.03046 -7.34821 -7.34821 -7.65463 -7.65463 -7.94925 -7.94925 -8.23161 -8.23161 -8.50128 -8.50128 -8.75784 -8.75784 -9.00090 -9.00090 -9.23008 -9.23008 -9.44502 -9.44502 -9.64540 -9.64540 -9.83091 -9.83091 -10.0013 -10.0013 -10.1562 -10.1562 -10.2955 -10.2955 -10.4189 -10.4189 -10.5262 -10.5262 -10.6173 -10.6173 -10.6920 -10.6920 -10.7503 -10.7503 -10.7919 -10.7919 -10.8169 -10.8169 -10.8253 -10.8253 -10.8169 -10.8169 -10.7919 -10.7919 -10.7503 -10.7503 -10.6920 -10.6920 -10.6173 -10.6173 -10.5262 -10.5262 -10.4189 -10.4189 -10.2955 -10.2955 -10.1562 -10.1562 -10.0013 -10.0013 -9.83091 -9.83091 -9.64540 -9.64540 -9.44502 -9.44502 -9.23008 -9.23008 -9.00090 -9.00090 -8.75784 -8.75784 -8.50128 -8.50128 -8.23161 -8.23161 -7.94925 -7.94925 -7.65463 -7.65463 -7.34821 -7.34821 -7.03046 -7.03046 -6.70187 -6.70187 -6.36295 -6.36295 -6.01421 -6.01421 -5.65620 -5.65620 -5.28947 -5.28947 -4.91458 -4.91458 -4.53211 -4.53211 -4.14266 -4.14266 -3.74682 -3.74682 -3.34520 -3.34520 -2.93842 -2.93842 -2.52711 -2.52711 -2.11191 -2.11191 -1.69345 -1.69345 -1.27238 -1.27238 -0.849342 -0.849342 -0.424999 -0.424999
+3.05311e-15 0.424999 0.424999 0.849342 0.849342 1.27238 1.27238 1.69345 1.69345 2.11191 2.11191 2.52711 2.52711 2.93842 2.93842 3.34520 3.34520 3.74682 3.74682 4.14266 4.14266 4.53211 4.53211 4.91458 4.91458 5.28947 5.28947 5.65620 5.65620 6.01421 6.01421 6.36295 6.36295 6.70187 6.70187 7.03046 7.03046 7.34821 7.34821 7.65463 7.65463 7.94925 7.94925 8.23161 8.23161 8.50128 8.50128 8.75784 8.75784 9.00090 9.00090 9.23008 9.23008 9.44502 9.44502 9.64540 9.64540 9.83091 9.83091 10.0013 10.0013 10.1562 10.1562 10.2955 10.2955 10.4189 10.4189 10.5262 10.5262 10.6173 10.6173 10.6920 10.6920 10.7503 10.7503 10.7919 10.7919 10.8169 10.8169 10.8253 10.8253 10.8169 10.8169 10.7919 10.7919 10.7503 10.7503 10.6920 10.6920 10.6173 10.6173 10.5262 10.5262 10.4189 10.4189 10.2955 10.2955 10.1562 10.1562 10.0013 10.0013 9.83091 9.83091 9.64540 9.64540 9.44502 9.44502 9.23008 9.23008 9.00090 9.00090 8.75784 8.75784 8.50128 8.50128 8.23161 8.23161 7.94925 7.94925 7.65463 7.65463 7.34821 7.34821 7.03046 7.03046 6.70187 6.70187 6.36295 6.36295 6.01421 6.01421 5.65620 5.65620 5.28947 5.28947 4.91458 4.91458 4.53211 4.53211 4.14266 4.14266 3.74682 3.74682 3.34520 3.34520 2.93842 2.93842 2.52711 2.52711 2.11191 2.11191 1.69345 1.69345 1.27238 1.27238 0.849342 0.849342 0.424999 0.424999 6.38378e-16 6.38378e-16 -0.424999 -0.424999 -0.849342 -0.849342 -1.27238 -1.27238 -1.69345 -1.69345 -2.11191 -2.11191 -2.52711 -2.52711 -2.93842 -2.93842 -3.34520 -3.34520 -3.74682 -3.74682 -4.14266 -4.14266 -4.53211 -4.53211 -4.91458 -4.91458 -5.28947 -5.28947 -5.65620 -5.65620 -6.01421 -6.01421 -6.36295 -6.36295 -6.70187 -6.70187 -7.03046 -7.03046 -7.34821 -7.34821 -7.65463 -7.65463 -7.94925 -7.94925 -8.23161 -8.23161 -8.50128 -8.50128 -8.75784 -8.75784 -9.00090 -9.00090 -9.23008 -9.23008 -9.44502 -9.44502 -9.64540 -9.64540 -9.83091 -9.83091 -10.0013 -10.0013 -10.1562 -10.1562 -10.2955 -10.2955 -10.4189 -10.4189 -10.5262 -10.5262 -10.6173 -10.6173 -10.6920 -10.6920 -10.7503 -10.7503 -10.7919 -10.7919 -10.8169 -10.8169 -10.8253 -10.8253 -10.8169 -10.8169 -10.7919 -10.7919 -10.7503 -10.7503 -10.6920 -10.6920 -10.6173 -10.6173 -10.5262 -10.5262 -10.4189 -10.4189 -10.2955 -10.2955 -10.1562 -10.1562 -10.0013 -10.0013 -9.83091 -9.83091 -9.64540 -9.64540 -9.44502 -9.44502 -9.23008 -9.23008 -9.00090 -9.00090 -8.75784 -8.75784 -8.50128 -8.50128 -8.23161 -8.23161 -7.94925 -7.94925 -7.65463 -7.65463 -7.34821 -7.34821 -7.03046 -7.03046 -6.70187 -6.70187 -6.36295 -6.36295 -6.01421 -6.01421 -5.65620 -5.65620 -5.28947 -5.28947 -4.91458 -4.91458 -4.53211 -4.53211 -4.14266 -4.14266 -3.74682 -3.74682 -3.34520 -3.34520 -2.93842 -2.93842 -2.52711 -2.52711 -2.11191 -2.11191 -1.69345 -1.69345 -1.27238 -1.27238 -0.849342 -0.849342 -0.424999 -0.424999 3.05311e-15
SCALARS tangential_velocity double 1
LOOKUP_TABLE default
2.08213 2.08213 2.07892 2.07892 2.07250 2.07250 2.06289 2.06289 2.05010 2.05010 2.03414 2.03414 2.01505 2.01505 1.99286 1.99286 1.96759 1.96759 1.93928 1.93928 1.90799 1.90799 1.87375 1.87375 1.83663 1.83663 1.79667 1.79667 1.75394 1.75394 1.70851 1.70851 1.66044 1.66044 1.60982 1.60982 1.55671 1.55671 1.50120 1.50120 1.44337 1.44337 1.38332 1.38332 1.32114 1.32114 1.25692 1.25692 1.19076 1.19076 1.12277 1.12277 1.05305 1.05305 0.981697 0.981697 0.908835 0.908835 0.834571 0.834571 0.759020 0.759020 0.682299 0.682299 0.604526 0.604526 0.525821 0.525821 0.446305 0.446305 0.366101 0.366101 0.285332 0.285332 0.204124 0.204124 0.122600 0.122600 0.0408877 0.0408877 -0.0408877 -0.0408877 -0.122600 -0.122600 -0.204124 -0.204124 -0.285332 -0.285332 -0.366101 -0.366101 -0.446305 -0.446305 -0.525821 -0.525821 -0.604526 -0.604526 -0.682299 -0.682299 -0.759020 -0.759020 -0.834571 -0.834571 -0.908835 -0.908835 -0.981697 -0.981697 -1.05305 -1.05305 -1.12277 -1.12277 -1.19076 -1.19076 -1.25692 -1.25692 -1.32114 -1.32114 -1.38332 -1.38332 -1.44337 -1.44337 -1.50120 -1.50120 -1.55671 -1.55671 -1.60982 -1.60982 -1.66044 -1.66044 -1.70851 -1.70851 -1.75394 -1.75394 -1.79667 -1.79667 -1.83663 -1.83663 -1.87375 -1.87375 -1.90799 -1.90799 -1.93928 -1.93928 -1.96759 -1.96759 -1.99286 -1.99286 -2.01505 -2.01505 -2.03414 -2.03414 -2.05010 -2.05010 -2.06289 -2.06289 -2.07250 -2.07250 -2.07892 -2.07892 -2.08213 -2.08213 -2.08213 -2.08213 -2.07892 -2.07892 -2.07250 -2.07250 -2.06289 -2.06289 -2.05010 -2.05010 -2.03414 -2.03414 -2.01505 -2.01505 -1.99286 -1.99286 -1.96759 -1.96759 -1.93928 -1.93928 -1.90799 -1.90799 -1.87375 -1.87375 -1.83663 -1.83663 -1.79667 -1.79667 -1.75394 -1.75394 -1.70851 -1.70851 -1.66044 -1.66044 -1.60982 -1.60982 -1.55671 -1.55671 -1.50120 -1.50120 -1.44337 -1.44337 -1.38332 -1.38332 -1.32114 -1.32114 -1.25692 -1.25692 -1.19076 -1.19076 -1.12277 -1.12277 -1.05305 -1.05305 -0.981697 -0.981697 -0.908835 -0.908835 -0.834571 -0.834571 -0.759020 -0.759020 -0.682299 -0.682299 -0.604526 -0.604526 -0.525821 -0.525821 -0.446305 -0.446305 -0.366101 -0.366101 -0.285332 -0.285332 -0.204124 -0.204124 -0.122600 -0.122600 -0.0408877 -0.0408877 0.0408877 0.0408877 0.122600 0.122600 0.204124 0.204124 0.285332 0.285332 0.366101 0.366101 0.446305 0.446305 0.525821 0.525821 0.604526 0.604526 0.682299 0.682299 0.759020 0.759020 0.834571 0.834571 0.908835 0.908835 0.981697 0.981697 1.05305 1.05305 1.12277 1.12277 1.19076 1.19076 1.25692 1.25692 1.32114 1.32114 1.38332 1.38332 1.44337 1.44337 1.50120 1.50120 1.55671 1.55671 1.60982 1.60982 1.66044 1.66044 1.70851 1.70851 1.75394 1.75394 1.79667 1.79667 1.83663 1.83663 1.87375 1.87375 1.90799 1.90799 1.93928 1.93928 1.96759 1.96759 1.99286 1.99286 2.01505 2.01505 2.03414 2.03414 2.05010 2.05010 2.06289 2.06289 2.07250 2.07250 2.07892 2.07892 2.08213 2.08213
numbering(i) = i;
DataOut<dim, DoFHandler<dim,spacedim> > dataout;
- dataout.attach_dof_handler(dof_handler);
- dataout.add_data_vector(numbering, "numbering");
+ dataout.add_data_vector(dof_handler, numbering, "numbering");
dataout.build_patches();
dataout.write_vtk(logfile);
}
POINT_DATA 62
SCALARS numbering double 1
LOOKUP_TABLE default
-0.00000 0.00000 1.00000 1.00000 2.00000 2.00000 3.00000 3.00000 4.00000 4.00000 5.00000 5.00000 6.00000 6.00000 7.00000 7.00000 8.00000 8.00000 9.00000 9.00000 10.0000 10.0000 11.0000 11.0000 12.0000 12.0000 13.0000 13.0000 14.0000 14.0000 15.0000 15.0000 16.0000 16.0000 17.0000 17.0000 18.0000 18.0000 19.0000 19.0000 20.0000 20.0000 21.0000 21.0000 22.0000 22.0000 23.0000 23.0000 24.0000 24.0000 25.0000 25.0000 26.0000 26.0000 27.0000 27.0000 28.0000 28.0000 29.0000 29.0000 30.0000 30.0000
+0.00000 1.00000 1.00000 2.00000 2.00000 3.00000 3.00000 4.00000 4.00000 5.00000 5.00000 6.00000 6.00000 7.00000 7.00000 8.00000 8.00000 9.00000 9.00000 10.0000 10.0000 11.0000 11.0000 12.0000 12.0000 13.0000 13.0000 14.0000 14.0000 15.0000 15.0000 16.0000 16.0000 17.0000 17.0000 18.0000 18.0000 19.0000 19.0000 20.0000 20.0000 21.0000 21.0000 22.0000 22.0000 23.0000 23.0000 24.0000 24.0000 25.0000 25.0000 26.0000 26.0000 27.0000 27.0000 28.0000 28.0000 29.0000 29.0000 30.0000 30.0000 0.00000
DEAL::Test<2,3>
# vtk DataFile Version 3.0
#This file was generated
// write graphical output
DataOut<dim, DoFHandler<dim,spacedim> > dataout;
- dataout.attach_dof_handler(dof_handler_help);
+ dataout.attach_triangulation(triangulation);
dataout.add_data_vector(projected_directional_derivative, "derivative");
dataout.build_patches();
dataout.write_vtk(logfile);
VectorTools::interpolate(dof_handler, cosine, interpolated_one);
DataOut<dim, DoFHandler<dim,spacedim> > dataout;
- dataout.attach_dof_handler(dof_handler);
- dataout.add_data_vector(interpolated_one, "numbering");
+ dataout.add_data_vector(dof_handler, interpolated_one, "numbering");
dataout.build_patches();
dataout.write_vtk(logfile);
}
POINT_DATA 62
SCALARS numbering double 1
LOOKUP_TABLE default
-6.12323e-17 6.12323e-17 0.0305550 0.0305550 0.103368 0.103368 0.173285 0.173285 0.196642 0.196642 0.158788 0.158788 0.0834524 0.0834524 0.0176029 0.0176029 0.00200973 0.00200973 0.0462882 0.0462882 0.123095 0.123095 0.184717 0.184717 0.192611 0.192611 0.141826 0.141826 0.0641634 0.0641634 0.00795761 0.00795761 0.00795761 0.00795761 0.0641634 0.0641634 0.141826 0.141826 0.192611 0.192611 0.184717 0.184717 0.123095 0.123095 0.0462882 0.0462882 0.00200973 0.00200973 0.0176029 0.0176029 0.0834524 0.0834524 0.158788 0.158788 0.196642 0.196642 0.173285 0.173285 0.103368 0.103368 0.0305550 0.0305550
+6.12323e-17 0.0305550 0.0305550 0.103368 0.103368 0.173285 0.173285 0.196642 0.196642 0.158788 0.158788 0.0834524 0.0834524 0.0176029 0.0176029 0.00200973 0.00200973 0.0462882 0.0462882 0.123095 0.123095 0.184717 0.184717 0.192611 0.192611 0.141826 0.141826 0.0641634 0.0641634 0.00795761 0.00795761 0.00795761 0.00795761 0.0641634 0.0641634 0.141826 0.141826 0.192611 0.192611 0.184717 0.184717 0.123095 0.123095 0.0462882 0.0462882 0.00200973 0.00200973 0.0176029 0.0176029 0.0834524 0.0834524 0.158788 0.158788 0.196642 0.196642 0.173285 0.173285 0.103368 0.103368 0.0305550 0.0305550 6.12323e-17
DEAL::Test<1,2>
# vtk DataFile Version 3.0
#This file was generated
VectorTools::project(dof_handler, constraints, quad, cosine, projected_one);
DataOut<dim, DoFHandler<dim,spacedim> > dataout;
- dataout.attach_dof_handler(dof_handler);
- dataout.add_data_vector(projected_one, "projection");
+ dataout.add_data_vector(dof_handler, projected_one, "projection");
dataout.build_patches();
dataout.write_vtk(logfile);
}
POINT_DATA 62
SCALARS projection double 1
LOOKUP_TABLE default
--6.51797e-05 -6.51797e-05 0.0318027 0.0318027 0.107769 0.107769 0.180745 0.180745 0.205132 0.205132 0.165612 0.165612 0.0869875 0.0869875 0.0182934 0.0182934 0.00203072 0.00203072 0.0482144 0.0482144 0.128357 0.128357 0.192681 0.192681 0.200923 0.200923 0.147906 0.147906 0.0668623 0.0668623 0.00823378 0.00823378 0.00823378 0.00823378 0.0668623 0.0668623 0.147906 0.147906 0.200923 0.200923 0.192681 0.192681 0.128357 0.128357 0.0482144 0.0482144 0.00203072 0.00203072 0.0182934 0.0182934 0.0869875 0.0869875 0.165612 0.165612 0.205132 0.205132 0.180745 0.180745 0.107769 0.107769 0.0318027 0.0318027
+-6.51797e-05 0.0318027 0.0318027 0.107769 0.107769 0.180745 0.180745 0.205132 0.205132 0.165612 0.165612 0.0869875 0.0869875 0.0182934 0.0182934 0.00203072 0.00203072 0.0482144 0.0482144 0.128357 0.128357 0.192681 0.192681 0.200923 0.200923 0.147906 0.147906 0.0668623 0.0668623 0.00823378 0.00823378 0.00823378 0.00823378 0.0668623 0.0668623 0.147906 0.147906 0.200923 0.200923 0.192681 0.192681 0.128357 0.128357 0.0482144 0.0482144 0.00203072 0.00203072 0.0182934 0.0182934 0.0869875 0.0869875 0.165612 0.165612 0.205132 0.205132 0.180745 0.180745 0.107769 0.107769 0.0318027 0.0318027 -6.51797e-05
DEAL::Test<2,3>, continous finite element q_1
# vtk DataFile Version 3.0
#This file was generated
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2010 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+/*
+ Test by Ross Kynch:
+
+ Solves curl(curl(u)) + u = f in 2D
+
+ exact solution is given by:
+ u(0) = cos(pi*x)*sin(pi*y) + C
+ u(1) = -sin(pi*x)*cos(pi(y) + C
+
+ f(0) = (2*pi^2 + 1)*cos(pi*x)*sin(pi*x) + C
+ f(1) = -(2*pi^2 + 1)*sin(pi*x)*cos(pi(y) + C
+
+ where C is some constant. (To change C, edit bc_constant in ExactSolution and
+ RightHandSide classes.)
+
+ The test solves these equations using the Nedelec element of higher order and
+ computes the error.
+
+ */
+#include "../tests.h"
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/function.h>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/convergence_table.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/sparse_direct.h>
+#include <deal.II/lac/compressed_sparsity_pattern.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+#include <deal.II/numerics/matrix_tools.h>
+#include <fstream>
+#include <iostream>
+#include <deal.II/fe/fe_nedelec.h>
+#include <deal.II/grid/grid_out.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/grid/grid_refinement.h>
+
+using namespace dealii;
+template <int dim>
+class MaxwellProblem
+{
+public:
+ MaxwellProblem (const unsigned int order);
+ ~MaxwellProblem ();
+ void run ();
+private:
+ double dotprod(const Tensor<1,dim> &A, const Tensor<1,dim> &B) const;
+ double dotprod(const Tensor<1,dim> &A, const Vector<double> &B) const;
+ void setup_system ();
+ void assemble_system ();
+ void solve ();
+ void process_solution(const unsigned int cycle);
+ Triangulation<dim> triangulation;
+ DoFHandler<dim> dof_handler;
+ FE_Nedelec<dim> fe;
+ ConstraintMatrix constraints;
+ SparsityPattern sparsity_pattern;
+ SparseMatrix<double> system_matrix;
+ Vector<double> solution;
+ Vector<double> system_rhs;
+
+ unsigned int p_order;
+ unsigned int quad_order;
+
+ ConvergenceTable convergence_table;
+};
+// EXACT SOLUTION CLASS
+template<int dim>
+class ExactSolution : public Function<dim>
+{
+public:
+ ExactSolution() : Function<dim>() {}
+ virtual double value (const Point<dim> &p,
+ const unsigned int component) const;
+ virtual void vector_value (const Point<dim> &p,
+ Vector<double> &result) const;
+ virtual void value_list (const std::vector<Point<dim> > &points,
+ std::vector<double> &values,
+ const unsigned int component) const;
+ virtual void vector_value_list (const std::vector<Point<dim> > &points,
+ std::vector<Vector<double> > &values) const;
+private:
+ const double PI = dealii::numbers::PI;
+ const double bc_constant = 0.1;
+};
+// RIGHT HAND SIDE CLASS
+template <int dim>
+class RightHandSide : public Function<dim>
+{
+public:
+ RightHandSide ();
+ virtual void vector_value (const Point<dim> &p,
+ Vector<double> &values) const;
+ virtual void vector_value_list (const std::vector<Point<dim> > &points,
+ std::vector<Vector<double> > &value_list) const;
+private:
+ const double PI = dealii::numbers::PI;
+ const double bc_constant = 0.1;
+};
+// DEFINE EXACT SOLUTION MEMBERS
+template<int dim>
+double ExactSolution<dim>::value(const Point<dim> &p,
+ const unsigned int component) const
+{
+ Assert (dim >= 2, ExcNotImplemented());
+ AssertIndexRange(component, dim);
+
+ double val = -1000;
+ switch(component) {
+ case 0: val = cos(PI*p(0))*sin(PI*p(1)) + bc_constant;
+ case 1: val = -sin(PI*p(0))*cos(PI*p(1)) + bc_constant;
+ }
+ return val;
+
+}
+template<int dim>
+void ExactSolution<dim>::vector_value(const Point<dim> &p,
+ Vector<double> &result) const
+{
+ Assert(dim >= 2, ExcNotImplemented());
+ result(0) = cos(PI*p(0))*sin(PI*p(1)) + bc_constant;
+ result(1) = -sin(PI*p(0))*cos(PI*p(1)) + bc_constant;
+
+}
+template <int dim>
+void ExactSolution<dim>::value_list (const std::vector<Point<dim> > &points,
+ std::vector<double> &values,
+ const unsigned int component) const
+{
+ Assert (values.size() == points.size(), ExcDimensionMismatch(values.size(), points.size()));
+ AssertIndexRange(component, dim);
+ for (unsigned int i=0; i<points.size(); ++i)
+ {
+ const Point<dim> &p = points[i];
+ switch(component)
+ {
+ case 0:
+ values[i] = cos(PI*p(0))*sin(PI*p(1)) + bc_constant;
+ case 1:
+ values[i] = -sin(PI*p(0))*cos(PI*p(1)) + bc_constant;
+ }
+ }
+}
+template <int dim>
+void ExactSolution<dim>::vector_value_list (const std::vector<Point<dim> > &points,
+ std::vector<Vector<double> > &values) const
+{
+ Assert (dim >= 2, ExcNotImplemented());
+ Assert (values.size() == points.size(), ExcDimensionMismatch(values.size(), points.size()));
+
+ for (unsigned int i=0; i<points.size(); ++i)
+ {
+ const Point<dim> &p = points[i];
+ values[i](0) = cos(PI*p(0))*sin(PI*p(1)) + bc_constant;
+ values[i](1) = -sin(PI*p(0))*cos(PI*p(1)) + bc_constant;
+ }
+}
+// END EXACT SOLUTION MEMBERS
+
+// DEFINE RIGHT HAND SIDE MEMBERS
+template <int dim>
+RightHandSide<dim>::RightHandSide () :
+Function<dim> (dim)
+{}
+template <int dim>
+inline
+void RightHandSide<dim>::vector_value (const Point<dim> &p,
+ Vector<double> &values) const
+{
+ Assert (values.size() == dim, ExcDimensionMismatch (values.size(), dim));
+ Assert (dim >= 2, ExcNotImplemented());
+
+ //2D solution
+ values(0) = (2*PI*PI + 1)*cos(PI*p(0))*sin(PI*p(1)) + bc_constant;
+ values(1) = -(2*PI*PI + 1)*sin(PI*p(0))*cos(PI*p(1)) + bc_constant;
+}
+template <int dim>
+void RightHandSide<dim>::vector_value_list (const std::vector<Point<dim> > &points,
+ std::vector<Vector<double> > &value_list) const
+{
+ Assert (value_list.size() == points.size(), ExcDimensionMismatch (value_list.size(), points.size()));
+ const unsigned int n_points = points.size();
+ for (unsigned int p=0; p<n_points; ++p)
+ {
+ RightHandSide<dim>::vector_value (points[p], value_list[p]);
+ }
+}
+// END RIGHT HAND SIDE MEMBERS
+
+template <int dim>
+MaxwellProblem<dim>::MaxwellProblem (const unsigned int order)
+:
+dof_handler (triangulation),
+fe (order)
+{
+ p_order = order;
+ quad_order = p_order+2;
+}
+template <int dim>
+MaxwellProblem<dim>::~MaxwellProblem ()
+{
+ dof_handler.clear ();
+}
+
+template<int dim>
+double MaxwellProblem<dim>::dotprod(const Tensor<1,dim> &A, const Tensor<1,dim> &B) const
+{
+ double return_val = 0;
+ for(unsigned int k = 0; k < dim; k++) {
+ return_val += A[k]*B[k];
+ }
+ return return_val;
+}
+
+template<int dim>
+double MaxwellProblem<dim>::dotprod(const Tensor<1,dim> &A, const Vector<double> &B) const
+{
+ double return_val = 0;
+ for(unsigned int k = 0; k < dim; k++) {
+ return_val += A[k]*B(k);
+ }
+ return return_val;
+}
+
+template <int dim>
+void MaxwellProblem<dim>::setup_system ()
+{
+ dof_handler.distribute_dofs (fe);
+ solution.reinit (dof_handler.n_dofs());
+ system_rhs.reinit (dof_handler.n_dofs());
+ constraints.clear ();
+ DoFTools::make_hanging_node_constraints (dof_handler,
+ constraints);
+ // FE_Nedelec boundary condition.
+ VectorTools::project_boundary_values_curl_conforming(dof_handler, 0, ExactSolution<dim>(), 0, constraints);
+
+ constraints.close ();
+ CompressedSparsityPattern c_sparsity(dof_handler.n_dofs());
+ DoFTools::make_sparsity_pattern(dof_handler,
+ c_sparsity,
+ constraints,false);
+
+ sparsity_pattern.copy_from(c_sparsity);
+ system_matrix.reinit (sparsity_pattern);
+}
+template <int dim>
+void MaxwellProblem<dim>::assemble_system ()
+{
+ const QGauss<dim> quadrature_formula(quad_order);
+ FEValues<dim> fe_values (fe, quadrature_formula,
+ update_values | update_gradients |
+ update_quadrature_points | update_JxW_values);
+ FEValuesViews::Vector<dim> fe_views(fe_values, 0);
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+ FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
+ Vector<double> cell_rhs (dofs_per_cell);
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ RightHandSide<dim> right_hand_side;
+ std::vector<Vector<double> > rhs_values (n_q_points,
+ Vector<double>(dim));
+ Tensor<1,dim> value_i, value_j;
+
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ {
+ cell_matrix = 0;
+ cell_rhs = 0;
+ fe_values.reinit (cell);
+ right_hand_side.vector_value_list (fe_values.get_quadrature_points(),
+ rhs_values);
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ {
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ value_i[0] = fe_values.shape_value_component(i,q_point,0);
+ value_i[1] = fe_values.shape_value_component(i,q_point,1);
+ if (dim == 3) {
+ value_i[2] = fe_values.shape_value_component(i,q_point,2);
+ }
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ value_j[0] = fe_values.shape_value_component(j,q_point,0);
+ value_j[1] = fe_values.shape_value_component(j,q_point,1);
+ if (dim == 3) {
+ value_j[2] = fe_values.shape_value_component(j,q_point,2);
+ }
+ cell_matrix(i,j) += ( fe_views.curl(i,q_point)[0]*fe_views.curl(j,q_point)[0]
+ + dotprod(value_i,value_j) )*fe_values.JxW(q_point);
+
+
+ }
+ cell_rhs(i) += dotprod(value_i,rhs_values[q_point])*fe_values.JxW(q_point);
+ }
+ }
+ cell->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global(cell_matrix,
+ cell_rhs,
+ local_dof_indices,
+ system_matrix, system_rhs);
+ }
+}
+template <int dim>
+void MaxwellProblem<dim>::solve ()
+{
+ /* CG:
+ SolverControl solver_control (1000, 1e-8);
+ SolverCG<> solver (solver_control);
+ PreconditionSSOR<> preconditioner;
+ preconditioner.initialize(system_matrix, 1.2);
+ solver.solve (system_matrix, solution, system_rhs,
+ preconditioner);
+ constraints.distribute (solution);
+ */
+
+ SparseDirectUMFPACK A_direct;
+ A_direct.initialize(system_matrix);
+
+ A_direct.vmult (solution, system_rhs);
+ constraints.distribute (solution);
+
+}
+template<int dim>
+void MaxwellProblem<dim>::process_solution(const unsigned int cycle)
+{
+ const ExactSolution<dim> exact_solution;
+ Vector<double> diff_per_cell(triangulation.n_active_cells());
+ VectorTools::integrate_difference(dof_handler, solution, exact_solution,
+ diff_per_cell, QGauss<dim>(quad_order), VectorTools::L2_norm);
+ const double L2_error = diff_per_cell.l2_norm();
+
+ convergence_table.add_value("cycle", cycle);
+ convergence_table.add_value("cells", triangulation.n_active_cells());
+ convergence_table.add_value("dofs", dof_handler.n_dofs());
+ convergence_table.add_value("L2 Error", L2_error);
+}
+
+template <int dim>
+void MaxwellProblem<dim>::run ()
+{
+ for (unsigned int cycle=0; cycle<3; ++cycle)
+ {
+ if (cycle == 0)
+ {
+ GridGenerator::hyper_cube (triangulation, -1, 1);
+ triangulation.refine_global (2);
+ }
+ else
+ triangulation.refine_global (1);
+ setup_system ();
+ assemble_system ();
+ solve ();
+ process_solution (cycle);
+ }
+ convergence_table.set_precision("L2 Error",8);
+ convergence_table.set_scientific("L2 Error",true);
+ convergence_table.write_text(deallog.get_file_stream());
+}
+
+int main ()
+{
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ MaxwellProblem<2> maxwell(4);
+ maxwell.run ();
+}
--- /dev/null
+
+cycle cells dofs L2 Error
+0 16 840 1.32580012e-04
+1 64 3280 4.19612400e-06
+2 256 12960 1.31545840e-07
DEAL::dim=2:
- 0 = 2.00000
+ 0 = 1.00000
1 = 0
- 4 = 1.00000
+ 4 = 0.500000
5 = 0
- 12 = 2.00000
+ 12 = 1.00000
13 = 0
- 14 = 1.00000
+ 14 = 0.500000
15 = 0
- 22 = 2.00000
+ 22 = 1.00000
23 = 0
- 26 = 1.00000
+ 26 = 0.500000
27 = 0
- 32 = 2.00000
+ 32 = 1.00000
33 = 0
- 34 = 1.00000
+ 34 = 0.500000
35 = 0
DEAL::dim=3:
0 = 1.00000
+++ /dev/null
-subsection Grid
- set Initial refinement = 4
- set Coarse mesh = square
-
- subsection Refinement
- set Refinement fraction = 0.95
- set Coarsening fraction = 0.01
- set Compare indicators globally = false
- set Maximum refinement = 0
- set Adapt mesh to dual solution = true
- set Primal to dual weight = 4
- set Initial energy estimator sweeps= 0
- end
-
- subsection Mesh smoothing
- set Cell number correction steps = 2
- set Top cell number deviation = 0.1
- set Bottom cell number deviation = 0.06
- end
-
- set Renumber dofs = true
-end
-
-
-
-subsection Equation data
- set Coefficient = kink
- set Initial u = bump
- set Initial v = zero
- set Boundary = zero
-end
-
-
-
-subsection Discretization
- set Primal FE = linear
- set Dual FE = quadratic
- subsection Time stepping
- set Primal method = theta
- set Dual method = theta
- set Theta = 0.5
- set Time step = 0.028
- set End time = 0.7
- end
-end
-
-
-
-subsection Solver
- set Preconditioning = ssor
- set Extrapolate old solutions = false
-end
-
-
-
-subsection Output
- set Format = eps
- set Directory = tmp
- set Directory for temporaries = tmp
- set Write solutions = all sweeps
- set Write steps interval = 25
- set Write stacked time steps = false
- set Write error as cell data = true
-
- subsection Error statistics
- set Produce error statistics = false
- set Number of intervals = 25
- set Interval spacing = logarithmic
- end
-end
-
-
-
-subsection Goal
- set Goal = Huyghens wave
- set Evaluate = Huyghens wave
-end
-
-
-set Refinement criterion = dual estimator
-set Sweeps = 3
#include <unistd.h>
-template <int dim>
-void write_vtk (const parallel::distributed::Triangulation<dim> &tria,
+template <int dim, int spacedim=dim>
+void write_vtk (const parallel::distributed::Triangulation<dim,spacedim> &tria,
const char *filename)
{
deallog << "Checksum: "
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: 2d_refinement_01.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2008 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Test Tria<2,3>
+
+#include "../tests.h"
+#include "coarse_grid_common.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/tensor.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/distributed/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_out.h>
+
+#include <fstream>
+
+
+template<int dim, int spacedim>
+void test(std::ostream & /*out*/)
+{
+ parallel::distributed::Triangulation<dim,spacedim> tr(MPI_COMM_WORLD);
+
+ GridGenerator::torus(tr, 1, 0.2);
+ tr.begin_active()->set_refine_flag();
+ tr.execute_coarsening_and_refinement ();
+
+ write_vtk(tr, "file");
+}
+
+
+int main(int argc, char *argv[])
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
+
+ initlog();
+
+ deallog.push("2-3");
+ test<2,3>(deallog.get_file_stream());
+ deallog.pop();
+}
template <int dim>
void test_2d_3d (std::vector<FiniteElement<dim> *> &fe_datas)
{
- // Face Q elements
- fe_datas.push_back(new FE_FaceQ<dim> (0));
- deallog << (*fe_datas.rbegin())->get_name() << std::endl;
- fe_datas.push_back(new FE_FaceQ<dim> (1));
- deallog << (*fe_datas.rbegin())->get_name() << std::endl;
- fe_datas.push_back(new FE_FaceQ<dim> (3));
- deallog << (*fe_datas.rbegin())->get_name() << std::endl;
- // Face P elements
- fe_datas.push_back(new FE_FaceP<dim> (0));
- deallog << (*fe_datas.rbegin())->get_name() << std::endl;
- fe_datas.push_back(new FE_FaceP<dim> (1));
- deallog << (*fe_datas.rbegin())->get_name() << std::endl;
- fe_datas.push_back(new FE_FaceP<dim> (3));
- deallog << (*fe_datas.rbegin())->get_name() << std::endl;
// Vector DG elements
fe_datas.push_back(
new FE_DGRaviartThomas<dim>(0));
FE_Q<dim> (2), 1));
deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+ // Face Q elements
+ fe_datas.push_back(new FE_FaceQ<dim> (0));
+ deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+ fe_datas.push_back(new FE_FaceQ<dim> (1));
+ deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+ fe_datas.push_back(new FE_FaceQ<dim> (3));
+ deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+ // Face P elements
+ fe_datas.push_back(new FE_FaceP<dim> (0));
+ deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+ fe_datas.push_back(new FE_FaceP<dim> (1));
+ deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+ fe_datas.push_back(new FE_FaceP<dim> (3));
+ deallog << (*fe_datas.rbegin())->get_name() << std::endl;
+
// Check vector elements in 2d and higher only
test_2d_3d (fe_datas);
DEAL::FE_DGP<1>(2)
DEAL::FESystem<1>[FE_Q<1>(2)^2]
DEAL::FESystem<1>[FE_Q<1>(1)^2-FE_Q<1>(2)]
+DEAL::FE_FaceQ<1>(0)
+DEAL::FE_FaceQ<1>(1)
+DEAL::FE_FaceQ<1>(3)
+DEAL::FE_FaceP<1>(0)
+DEAL::FE_FaceP<1>(1)
+DEAL::FE_FaceP<1>(3)
DEAL::FESystem<1>[FE_Q<1>(3)^2]
DEAL::FESystem<1>[FE_Q<1>(1)^2-FE_Q<1>(3)]
DEAL::FESystem<1>[FE_Q<1>(4)^2]
DEAL::face_to_cell_index:
DEAL::face_to_cell_index:
DEAL::support on face 0: 0
-DEAL::support on face 1: 1
+DEAL::support on face 1: 2
DEAL::
DEAL::fe_data[8]:FE_DGQ<1>(4)
DEAL::dofs_per_vertex=0
DEAL::face_to_cell_index:
DEAL::face_to_cell_index:
DEAL::support on face 0: 0
-DEAL::support on face 1: 1
+DEAL::support on face 1: 4
DEAL::
DEAL::fe_data[9]:FE_DGP<1>(1)
DEAL::dofs_per_vertex=0
DEAL::support on face 0: 0 1 2
DEAL::support on face 1: 3 4 5
DEAL::
-DEAL::fe_data[13]:FESystem<1>[FE_Q<1>(3)^2]
+DEAL::fe_data[13]:FE_FaceQ<1>(0)
+DEAL::dofs_per_vertex=1
+DEAL::dofs_per_line=0
+DEAL::dofs_per_quad=0
+DEAL::dofs_per_hex=0
+DEAL::first_line_index=2
+DEAL::first_quad_index=2
+DEAL::first_hex_index=2
+DEAL::first_face_line_index=1
+DEAL::first_face_quad_index=2
+DEAL::dofs_per_face=1
+DEAL::dofs_per_cell=2
+DEAL::primitive=yes
+DEAL::components=1
+DEAL::blocks=1:[2]->2
+DEAL::degree=0
+DEAL::conformity= L2
+DEAL::unit_support_points=2
+DEAL::unit_face_support_points=1
+DEAL::generalized_support_points=2
+DEAL::generalized_face_support_points=1
+DEAL::face_to_equivalent_cell_index: 0
+DEAL::face_to_cell_index: 0
+DEAL::face_to_cell_index: 1
+DEAL::support on face 0: 0
+DEAL::support on face 1: 1
+DEAL::
+DEAL::fe_data[14]:FE_FaceQ<1>(1)
+DEAL::dofs_per_vertex=1
+DEAL::dofs_per_line=0
+DEAL::dofs_per_quad=0
+DEAL::dofs_per_hex=0
+DEAL::first_line_index=2
+DEAL::first_quad_index=2
+DEAL::first_hex_index=2
+DEAL::first_face_line_index=1
+DEAL::first_face_quad_index=2
+DEAL::dofs_per_face=1
+DEAL::dofs_per_cell=2
+DEAL::primitive=yes
+DEAL::components=1
+DEAL::blocks=1:[2]->2
+DEAL::degree=1
+DEAL::conformity= L2
+DEAL::unit_support_points=2
+DEAL::unit_face_support_points=1
+DEAL::generalized_support_points=2
+DEAL::generalized_face_support_points=1
+DEAL::face_to_equivalent_cell_index: 0
+DEAL::face_to_cell_index: 0
+DEAL::face_to_cell_index: 1
+DEAL::support on face 0: 0
+DEAL::support on face 1: 1
+DEAL::
+DEAL::fe_data[15]:FE_FaceQ<1>(3)
+DEAL::dofs_per_vertex=1
+DEAL::dofs_per_line=0
+DEAL::dofs_per_quad=0
+DEAL::dofs_per_hex=0
+DEAL::first_line_index=2
+DEAL::first_quad_index=2
+DEAL::first_hex_index=2
+DEAL::first_face_line_index=1
+DEAL::first_face_quad_index=2
+DEAL::dofs_per_face=1
+DEAL::dofs_per_cell=2
+DEAL::primitive=yes
+DEAL::components=1
+DEAL::blocks=1:[2]->2
+DEAL::degree=3
+DEAL::conformity= L2
+DEAL::unit_support_points=2
+DEAL::unit_face_support_points=1
+DEAL::generalized_support_points=2
+DEAL::generalized_face_support_points=1
+DEAL::face_to_equivalent_cell_index: 0
+DEAL::face_to_cell_index: 0
+DEAL::face_to_cell_index: 1
+DEAL::support on face 0: 0
+DEAL::support on face 1: 1
+DEAL::
+DEAL::fe_data[16]:FE_FaceP<1>(0)
+DEAL::dofs_per_vertex=1
+DEAL::dofs_per_line=0
+DEAL::dofs_per_quad=0
+DEAL::dofs_per_hex=0
+DEAL::first_line_index=2
+DEAL::first_quad_index=2
+DEAL::first_hex_index=2
+DEAL::first_face_line_index=1
+DEAL::first_face_quad_index=2
+DEAL::dofs_per_face=1
+DEAL::dofs_per_cell=2
+DEAL::primitive=yes
+DEAL::components=1
+DEAL::blocks=1:[2]->2
+DEAL::degree=0
+DEAL::conformity= L2
+DEAL::unit_support_points=2
+DEAL::unit_face_support_points=1
+DEAL::generalized_support_points=2
+DEAL::generalized_face_support_points=1
+DEAL::face_to_equivalent_cell_index: 0
+DEAL::face_to_cell_index: 0
+DEAL::face_to_cell_index: 1
+DEAL::support on face 0: 0
+DEAL::support on face 1: 1
+DEAL::
+DEAL::fe_data[17]:FE_FaceP<1>(1)
+DEAL::dofs_per_vertex=1
+DEAL::dofs_per_line=0
+DEAL::dofs_per_quad=0
+DEAL::dofs_per_hex=0
+DEAL::first_line_index=2
+DEAL::first_quad_index=2
+DEAL::first_hex_index=2
+DEAL::first_face_line_index=1
+DEAL::first_face_quad_index=2
+DEAL::dofs_per_face=1
+DEAL::dofs_per_cell=2
+DEAL::primitive=yes
+DEAL::components=1
+DEAL::blocks=1:[2]->2
+DEAL::degree=1
+DEAL::conformity= L2
+DEAL::unit_support_points=2
+DEAL::unit_face_support_points=1
+DEAL::generalized_support_points=2
+DEAL::generalized_face_support_points=1
+DEAL::face_to_equivalent_cell_index: 0
+DEAL::face_to_cell_index: 0
+DEAL::face_to_cell_index: 1
+DEAL::support on face 0: 0
+DEAL::support on face 1: 1
+DEAL::
+DEAL::fe_data[18]:FE_FaceP<1>(3)
+DEAL::dofs_per_vertex=1
+DEAL::dofs_per_line=0
+DEAL::dofs_per_quad=0
+DEAL::dofs_per_hex=0
+DEAL::first_line_index=2
+DEAL::first_quad_index=2
+DEAL::first_hex_index=2
+DEAL::first_face_line_index=1
+DEAL::first_face_quad_index=2
+DEAL::dofs_per_face=1
+DEAL::dofs_per_cell=2
+DEAL::primitive=yes
+DEAL::components=1
+DEAL::blocks=1:[2]->2
+DEAL::degree=3
+DEAL::conformity= L2
+DEAL::unit_support_points=2
+DEAL::unit_face_support_points=1
+DEAL::generalized_support_points=2
+DEAL::generalized_face_support_points=1
+DEAL::face_to_equivalent_cell_index: 0
+DEAL::face_to_cell_index: 0
+DEAL::face_to_cell_index: 1
+DEAL::support on face 0: 0
+DEAL::support on face 1: 1
+DEAL::
+DEAL::fe_data[19]:FESystem<1>[FE_Q<1>(3)^2]
DEAL::dofs_per_vertex=2
DEAL::dofs_per_line=4
DEAL::dofs_per_quad=0
DEAL::support on face 0: 0 1
DEAL::support on face 1: 2 3
DEAL::
-DEAL::fe_data[14]:FESystem<1>[FE_Q<1>(1)^2-FE_Q<1>(3)]
+DEAL::fe_data[20]:FESystem<1>[FE_Q<1>(1)^2-FE_Q<1>(3)]
DEAL::dofs_per_vertex=3
DEAL::dofs_per_line=2
DEAL::dofs_per_quad=0
DEAL::support on face 0: 0 1 2
DEAL::support on face 1: 3 4 5
DEAL::
-DEAL::fe_data[15]:FESystem<1>[FE_Q<1>(4)^2]
+DEAL::fe_data[21]:FESystem<1>[FE_Q<1>(4)^2]
DEAL::dofs_per_vertex=2
DEAL::dofs_per_line=6
DEAL::dofs_per_quad=0
DEAL::support on face 0: 0 1
DEAL::support on face 1: 2 3
DEAL::
-DEAL::fe_data[16]:FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]^2]
+DEAL::fe_data[22]:FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]^2]
DEAL::dofs_per_vertex=4
DEAL::dofs_per_line=0
DEAL::dofs_per_quad=0
DEAL::support on face 0: 0 1 2 3
DEAL::support on face 1: 4 5 6 7
DEAL::
-DEAL::fe_data[17]:FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]-FESystem<1>[FE_DGQ<1>(1)^2]]
+DEAL::fe_data[23]:FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]-FESystem<1>[FE_DGQ<1>(1)^2]]
DEAL::dofs_per_vertex=2
DEAL::dofs_per_line=4
DEAL::dofs_per_quad=0
DEAL::support on face 0: 0 1 4 6
DEAL::support on face 1: 2 3 5 7
DEAL::
-DEAL::fe_data[18]:FESystem<1>[FESystem<1>[FE_Q<1>(1)-FE_Q<1>(2)]-FESystem<1>[FE_Q<1>(2)^2]-FESystem<1>[FE_DGQ<1>(2)^2]]
+DEAL::fe_data[24]:FESystem<1>[FESystem<1>[FE_Q<1>(1)-FE_Q<1>(2)]-FESystem<1>[FE_Q<1>(2)^2]-FESystem<1>[FE_DGQ<1>(2)^2]]
DEAL::dofs_per_vertex=4
DEAL::dofs_per_line=9
DEAL::dofs_per_quad=0
DEAL::face_to_cell_index: 0 1 2 3
DEAL::face_to_cell_index: 4 5 6 7
DEAL::support on face 0: 0 1 2 3 11 14
-DEAL::support on face 1: 4 5 6 7 12 15
+DEAL::support on face 1: 4 5 6 7 13 16
DEAL::
-DEAL::fe_data[19]:FESystem<1>[FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]^2]^2-FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]-FESystem<1>[FE_DGQ<1>(1)^2]]-FESystem<1>[FESystem<1>[FE_Q<1>(1)-FE_Q<1>(2)]-FESystem<1>[FE_Q<1>(2)^2]-FESystem<1>[FE_DGQ<1>(2)^2]]^2]
+DEAL::fe_data[25]:FESystem<1>[FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]^2]^2-FESystem<1>[FESystem<1>[FE_Q<1>(1)^2]-FESystem<1>[FE_DGQ<1>(1)^2]]-FESystem<1>[FESystem<1>[FE_Q<1>(1)-FE_Q<1>(2)]-FESystem<1>[FE_Q<1>(2)^2]-FESystem<1>[FE_DGQ<1>(2)^2]]^2]
DEAL::dofs_per_vertex=18
DEAL::dofs_per_line=22
DEAL::dofs_per_quad=0
DEAL::face_to_cell_index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
DEAL::face_to_cell_index: 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
DEAL::support on face 0: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 36 38 43 46 52 55
-DEAL::support on face 1: 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 37 39 44 47 53 56
+DEAL::support on face 1: 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 37 39 45 48 54 57
DEAL::
DEAL::FE_Q<2>(1)
DEAL::FE_Q<2>(2)
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include "../tests.h"
+#include "shapes.h"
+//#include "../deal.II/tests/tests.h"
+//#include "../deal.II/tests/fe/shapes.h"
+#include <deal.II/fe/fe_trace.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/mapping_q1.h>
+#include <fstream>
+#include <string>
+
+#define PRECISION 2
+
+
+template<int dim>
+void plot_FE_TraceQ_shape_functions()
+{
+ MappingQ1<dim> m;
+
+ FE_TraceQ<dim> tq1(1);
+ FE_TraceQ<dim> tq2(2);
+ FE_TraceQ<dim> tq3(3);
+ FE_TraceQ<dim> tq4(4);
+ FE_Q<dim> q1(1);
+ FE_Q<dim> q2(2);
+ FESystem<dim> sys1(tq1,1);
+ FESystem<dim> sys2(tq2,1);
+ FESystem<dim> sys11(tq1,1,q1,1);
+ FESystem<dim> sys22(tq2,1,q2,1);
+ plot_face_shape_functions(m, tq1, "TraceQ1", update_values);
+ plot_face_shape_functions(m, tq2, "TraceQ2", update_values);
+ plot_face_shape_functions(m, tq3, "TraceQ3", update_values);
+ plot_face_shape_functions(m, tq4, "TraceQ4", update_values);
+ plot_face_shape_functions(m, sys1, "System1", update_values);
+ plot_face_shape_functions(m, sys2, "System2", update_values);
+ plot_face_shape_functions(m, sys11, "System1-1", update_values);
+ plot_face_shape_functions(m, sys22, "System2-2", update_values);
+}
+
+
+int
+main()
+{
+ const std::string logname = "output";
+ std::ofstream logfile(logname.c_str());
+ deallog << std::setprecision(PRECISION) << std::fixed;
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ plot_FE_TraceQ_shape_functions<2>();
+ //plot_FE_TraceQ_shape_functions<3>();
+
+ return 0;
+}
--- /dev/null
+
+DEAL:Face2d-TraceQ1::0.00 0.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ1::0.00 0.12 1.75 1.00 1.25 1.00
+DEAL:Face2d-TraceQ1::0.00 0.25 1.50 1.00 1.50 1.00
+DEAL:Face2d-TraceQ1::0.00 0.38 1.25 1.00 1.75 1.00
+DEAL:Face2d-TraceQ1::0.00 0.50 1.00 1.00 2.00 1.00
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::0.50 0.00 1.00 1.00 2.00 1.00
+DEAL:Face2d-TraceQ1::0.50 0.06 1.00 1.00 1.88 1.12
+DEAL:Face2d-TraceQ1::0.50 0.12 1.00 1.00 1.75 1.25
+DEAL:Face2d-TraceQ1::0.50 0.19 1.00 1.00 1.62 1.38
+DEAL:Face2d-TraceQ1::0.50 0.25 1.00 1.00 1.50 1.50
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::0.50 0.25 1.00 1.00 1.50 1.50
+DEAL:Face2d-TraceQ1::0.50 0.31 1.00 1.00 1.38 1.62
+DEAL:Face2d-TraceQ1::0.50 0.38 1.00 1.00 1.25 1.75
+DEAL:Face2d-TraceQ1::0.50 0.44 1.00 1.00 1.12 1.88
+DEAL:Face2d-TraceQ1::0.50 0.50 1.00 1.00 1.00 2.00
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::0.00 0.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ1::0.12 0.00 1.75 1.25 1.00 1.00
+DEAL:Face2d-TraceQ1::0.25 0.00 1.50 1.50 1.00 1.00
+DEAL:Face2d-TraceQ1::0.38 0.00 1.25 1.75 1.00 1.00
+DEAL:Face2d-TraceQ1::0.50 0.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::0.00 0.50 1.00 1.00 2.00 1.00
+DEAL:Face2d-TraceQ1::0.12 0.50 1.00 1.00 1.75 1.25
+DEAL:Face2d-TraceQ1::0.25 0.50 1.00 1.00 1.50 1.50
+DEAL:Face2d-TraceQ1::0.38 0.50 1.00 1.00 1.25 1.75
+DEAL:Face2d-TraceQ1::0.50 0.50 1.00 1.00 1.00 2.00
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ1::
+DEAL:Face2d-TraceQ2::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.00 0.12 1.38 1.00 0.88 1.00 1.75 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.00 0.25 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.00 0.38 0.88 1.00 1.38 1.00 1.75 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::0.50 0.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.06 1.00 1.00 1.00 1.66 0.91 1.44 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.12 1.00 1.00 1.00 1.38 0.88 1.75 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.19 1.00 1.00 1.00 1.16 0.91 1.94 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.25 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::0.50 0.25 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.31 1.00 1.00 1.00 0.91 1.16 1.94 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.38 1.00 1.00 1.00 0.88 1.38 1.75 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.44 1.00 1.00 1.00 0.91 1.66 1.44 1.00 1.00
+DEAL:Face2d-TraceQ2::0.50 0.50 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.12 0.00 1.38 0.88 1.00 1.00 1.00 1.00 1.75 1.00
+DEAL:Face2d-TraceQ2::0.25 0.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00
+DEAL:Face2d-TraceQ2::0.38 0.00 0.88 1.38 1.00 1.00 1.00 1.00 1.75 1.00
+DEAL:Face2d-TraceQ2::0.50 0.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::0.12 0.50 1.00 1.00 1.38 0.88 1.00 1.00 1.00 1.75
+DEAL:Face2d-TraceQ2::0.25 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00
+DEAL:Face2d-TraceQ2::0.38 0.50 1.00 1.00 0.88 1.38 1.00 1.00 1.00 1.75
+DEAL:Face2d-TraceQ2::0.50 0.50 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ2::
+DEAL:Face2d-TraceQ3::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.00 0.12 1.12 1.00 1.04 1.00 2.05 0.79 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.00 0.25 0.94 1.00 0.94 1.00 1.56 1.56 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.00 0.38 1.04 1.00 1.12 1.00 0.79 2.05 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::0.50 0.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.06 1.00 1.00 1.00 1.00 1.44 1.06 1.80 0.69 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.12 1.00 1.00 1.00 1.00 1.12 1.04 2.05 0.79 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.19 1.00 1.00 1.00 1.00 0.97 0.98 1.92 1.13 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.25 1.00 1.00 1.00 1.00 0.94 0.94 1.56 1.56 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::0.50 0.25 1.00 1.00 1.00 1.00 0.94 0.94 1.56 1.56 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.31 1.00 1.00 1.00 1.00 0.98 0.97 1.13 1.92 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.38 1.00 1.00 1.00 1.00 1.04 1.12 0.79 2.05 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.44 1.00 1.00 1.00 1.00 1.06 1.44 0.69 1.80 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.50 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.12 0.00 1.12 1.04 1.00 1.00 1.00 1.00 1.00 1.00 2.05 0.79 1.00 1.00
+DEAL:Face2d-TraceQ3::0.25 0.00 0.94 0.94 1.00 1.00 1.00 1.00 1.00 1.00 1.56 1.56 1.00 1.00
+DEAL:Face2d-TraceQ3::0.38 0.00 1.04 1.12 1.00 1.00 1.00 1.00 1.00 1.00 0.79 2.05 1.00 1.00
+DEAL:Face2d-TraceQ3::0.50 0.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::0.12 0.50 1.00 1.00 1.12 1.04 1.00 1.00 1.00 1.00 1.00 1.00 2.05 0.79
+DEAL:Face2d-TraceQ3::0.25 0.50 1.00 1.00 0.94 0.94 1.00 1.00 1.00 1.00 1.00 1.00 1.56 1.56
+DEAL:Face2d-TraceQ3::0.38 0.50 1.00 1.00 1.04 1.12 1.00 1.00 1.00 1.00 1.00 1.00 0.79 2.05
+DEAL:Face2d-TraceQ3::0.50 0.50 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ3::
+DEAL:Face2d-TraceQ4::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.00 0.12 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.00 0.25 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.00 0.38 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::0.50 0.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.06 1.00 1.00 1.00 1.00 1.00 1.27 0.96 2.09 0.45 1.22 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.12 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.19 1.00 1.00 1.00 1.00 1.00 0.96 1.02 1.47 1.70 0.84 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.25 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::0.50 0.25 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.31 1.00 1.00 1.00 1.00 1.00 1.02 0.96 0.84 1.70 1.47 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.38 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.44 1.00 1.00 1.00 1.00 1.00 0.96 1.27 1.22 0.45 2.09 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.50 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.12 0.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.25 0.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.38 0.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.50 0.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.12 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-TraceQ4::0.25 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00
+DEAL:Face2d-TraceQ4::0.38 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00
+DEAL:Face2d-TraceQ4::0.50 0.50 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-TraceQ4::
+DEAL:Face2d-System1::0.00 0.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-System1::0.00 0.12 1.75 1.00 1.25 1.00
+DEAL:Face2d-System1::0.00 0.25 1.50 1.00 1.50 1.00
+DEAL:Face2d-System1::0.00 0.38 1.25 1.00 1.75 1.00
+DEAL:Face2d-System1::0.00 0.50 1.00 1.00 2.00 1.00
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::0.50 0.00 1.00 1.00 2.00 1.00
+DEAL:Face2d-System1::0.50 0.06 1.00 1.00 1.88 1.12
+DEAL:Face2d-System1::0.50 0.12 1.00 1.00 1.75 1.25
+DEAL:Face2d-System1::0.50 0.19 1.00 1.00 1.62 1.38
+DEAL:Face2d-System1::0.50 0.25 1.00 1.00 1.50 1.50
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::0.50 0.25 1.00 1.00 1.50 1.50
+DEAL:Face2d-System1::0.50 0.31 1.00 1.00 1.38 1.62
+DEAL:Face2d-System1::0.50 0.38 1.00 1.00 1.25 1.75
+DEAL:Face2d-System1::0.50 0.44 1.00 1.00 1.12 1.88
+DEAL:Face2d-System1::0.50 0.50 1.00 1.00 1.00 2.00
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::0.00 0.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-System1::0.12 0.00 1.75 1.25 1.00 1.00
+DEAL:Face2d-System1::0.25 0.00 1.50 1.50 1.00 1.00
+DEAL:Face2d-System1::0.38 0.00 1.25 1.75 1.00 1.00
+DEAL:Face2d-System1::0.50 0.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::0.00 0.50 1.00 1.00 2.00 1.00
+DEAL:Face2d-System1::0.12 0.50 1.00 1.00 1.75 1.25
+DEAL:Face2d-System1::0.25 0.50 1.00 1.00 1.50 1.50
+DEAL:Face2d-System1::0.38 0.50 1.00 1.00 1.25 1.75
+DEAL:Face2d-System1::0.50 0.50 1.00 1.00 1.00 2.00
+DEAL:Face2d-System1::
+DEAL:Face2d-System1::
+DEAL:Face2d-System2::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::0.00 0.12 1.38 1.00 0.88 1.00 1.75 1.00 1.00 1.00
+DEAL:Face2d-System2::0.00 0.25 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-System2::0.00 0.38 0.88 1.00 1.38 1.00 1.75 1.00 1.00 1.00
+DEAL:Face2d-System2::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::0.50 0.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::0.50 0.06 1.00 1.00 1.00 1.66 0.91 1.44 1.00 1.00
+DEAL:Face2d-System2::0.50 0.12 1.00 1.00 1.00 1.38 0.88 1.75 1.00 1.00
+DEAL:Face2d-System2::0.50 0.19 1.00 1.00 1.00 1.16 0.91 1.94 1.00 1.00
+DEAL:Face2d-System2::0.50 0.25 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::0.50 0.25 1.00 1.00 1.00 1.00 1.00 2.00 1.00 1.00
+DEAL:Face2d-System2::0.50 0.31 1.00 1.00 1.00 0.91 1.16 1.94 1.00 1.00
+DEAL:Face2d-System2::0.50 0.38 1.00 1.00 1.00 0.88 1.38 1.75 1.00 1.00
+DEAL:Face2d-System2::0.50 0.44 1.00 1.00 1.00 0.91 1.66 1.44 1.00 1.00
+DEAL:Face2d-System2::0.50 0.50 1.00 1.00 1.00 1.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::0.00 0.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::0.12 0.00 1.38 0.88 1.00 1.00 1.00 1.00 1.75 1.00
+DEAL:Face2d-System2::0.25 0.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 1.00
+DEAL:Face2d-System2::0.38 0.00 0.88 1.38 1.00 1.00 1.00 1.00 1.75 1.00
+DEAL:Face2d-System2::0.50 0.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::0.00 0.50 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::0.12 0.50 1.00 1.00 1.38 0.88 1.00 1.00 1.00 1.75
+DEAL:Face2d-System2::0.25 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00
+DEAL:Face2d-System2::0.38 0.50 1.00 1.00 0.88 1.38 1.00 1.00 1.00 1.75
+DEAL:Face2d-System2::0.50 0.50 1.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2::
+DEAL:Face2d-System2::
+DEAL:Face2d-System1-1::0.00 0.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::0.00 0.12 1.75 1.75 1.00 1.00 1.25 1.25 1.00 1.00
+DEAL:Face2d-System1-1::0.00 0.25 1.50 1.50 1.00 1.00 1.50 1.50 1.00 1.00
+DEAL:Face2d-System1-1::0.00 0.38 1.25 1.25 1.00 1.00 1.75 1.75 1.00 1.00
+DEAL:Face2d-System1-1::0.00 0.50 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::0.50 0.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::0.50 0.06 1.00 1.00 1.00 1.88 1.88 1.00 1.12 1.12
+DEAL:Face2d-System1-1::0.50 0.12 1.00 1.00 1.00 1.75 1.75 1.00 1.25 1.25
+DEAL:Face2d-System1-1::0.50 0.19 1.00 1.00 1.00 1.62 1.62 1.00 1.38 1.38
+DEAL:Face2d-System1-1::0.50 0.25 1.00 1.00 1.00 1.50 1.50 1.00 1.50 1.50
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::0.50 0.25 1.00 1.00 1.00 1.50 1.50 1.00 1.50 1.50
+DEAL:Face2d-System1-1::0.50 0.31 1.00 1.00 1.00 1.38 1.38 1.00 1.62 1.62
+DEAL:Face2d-System1-1::0.50 0.38 1.00 1.00 1.00 1.25 1.25 1.00 1.75 1.75
+DEAL:Face2d-System1-1::0.50 0.44 1.00 1.00 1.00 1.12 1.12 1.00 1.88 1.88
+DEAL:Face2d-System1-1::0.50 0.50 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::0.00 0.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::0.12 0.00 1.75 1.75 1.25 1.25 1.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::0.25 0.00 1.50 1.50 1.50 1.50 1.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::0.38 0.00 1.25 1.25 1.75 1.75 1.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::0.50 0.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::0.00 0.50 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00
+DEAL:Face2d-System1-1::0.12 0.50 1.00 1.00 1.00 1.00 1.75 1.75 1.25 1.25
+DEAL:Face2d-System1-1::0.25 0.50 1.00 1.00 1.00 1.00 1.50 1.50 1.50 1.50
+DEAL:Face2d-System1-1::0.38 0.50 1.00 1.00 1.00 1.00 1.25 1.25 1.75 1.75
+DEAL:Face2d-System1-1::0.50 0.50 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System1-1::
+DEAL:Face2d-System2-2::0.00 0.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.00 0.12 1.38 1.38 1.00 1.00 0.88 0.88 1.00 1.00 1.75 1.75 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.00 0.25 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.00 0.38 0.88 0.88 1.00 1.00 1.38 1.38 1.00 1.00 1.75 1.75 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.00 0.50 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::0.50 0.00 1.00 1.00 1.00 2.00 1.00 1.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.06 1.00 1.00 1.00 1.66 1.00 1.00 1.66 0.91 0.91 1.00 1.44 1.44 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.12 1.00 1.00 1.00 1.38 1.00 1.00 1.38 0.88 0.88 1.00 1.75 1.75 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.19 1.00 1.00 1.00 1.16 1.00 1.00 1.16 0.91 0.91 1.00 1.94 1.94 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.25 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::0.50 0.25 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.31 1.00 1.00 1.00 0.91 1.00 1.00 0.91 1.16 1.16 1.00 1.94 1.94 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.38 1.00 1.00 1.00 0.88 1.00 1.00 0.88 1.38 1.38 1.00 1.75 1.75 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.44 1.00 1.00 1.00 0.91 1.00 1.00 0.91 1.66 1.66 1.00 1.44 1.44 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::0.00 0.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.12 0.00 1.38 1.38 0.88 0.88 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.75 1.75 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.25 0.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.38 0.00 0.88 0.88 1.38 1.38 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.75 1.75 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.50 0.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::0.00 0.50 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::0.12 0.50 1.00 1.00 1.00 1.00 1.38 1.38 0.88 0.88 1.00 1.00 1.00 1.00 1.00 1.00 1.75 1.75 1.00
+DEAL:Face2d-System2-2::0.25 0.50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00
+DEAL:Face2d-System2-2::0.38 0.50 1.00 1.00 1.00 1.00 0.88 0.88 1.38 1.38 1.00 1.00 1.00 1.00 1.00 1.00 1.75 1.75 1.00
+DEAL:Face2d-System2-2::0.50 0.50 1.00 1.00 1.00 1.00 1.00 1.00 2.00 2.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00
+DEAL:Face2d-System2-2::
+DEAL:Face2d-System2-2::
-<svg width="5600" height="4000" xmlns="http://www.w3.org/2000/svg" version="1.1">
+<svg width="1400" height="1000" xmlns="http://www.w3.org/2000/svg" version="1.1">
<!-- internal style sheet -->
rect.r2{fill:rgb(255,0,0); stroke:rgb(25,25,25); stroke-width:2}
]]></style>
- <rect class="background" width="5600" height="4000"/>
+ <rect class="background" width="1000" height="1000"/>
<!-- cells -->
- <path class="p1" d="M 3680 2000 L 3680 1160 L 3198 1432 L 3260 2000 L 3680 2000"/>
- <text x="3455" y="1648" style="font-size:126">1,0,0</text>
- <line x1="3680" y1="2000" x2="3680" y2="1160"/>
- <path class="p1" d="M 3680 1160 L 3680 320 L 3137 863 L 3198 1432 L 3680 1160"/>
- <text x="3424" y="944" style="font-size:123">1,1,0</text>
- <line x1="3680" y1="1160" x2="3680" y2="320"/>
- <path class="p1" d="M 3680 320 L 2840 320 L 2568 802 L 3137 863 L 3680 320"/>
- <text x="3056" y="576" style="font-size:123">1,4,0</text>
- <line x1="3680" y1="320" x2="2840" y2="320"/>
- <path class="p1" d="M 2840 320 L 2000 320 L 2000 740 L 2568 802 L 2840 320"/>
- <text x="2352" y="545" style="font-size:126">1,5,0</text>
- <line x1="2840" y1="320" x2="2000" y2="320"/>
- <path class="p1" d="M 2000 320 L 1160 320 L 1432 802 L 2000 740 L 2000 320"/>
- <text x="1648" y="545" style="font-size:126">1,8,0</text>
- <line x1="2000" y1="320" x2="1160" y2="320"/>
- <path class="p1" d="M 1160 320 L 320 320 L 863 863 L 1432 802 L 1160 320"/>
- <text x="944" y="576" style="font-size:123">1,9,0</text>
- <line x1="1160" y1="320" x2="320" y2="320"/>
- <path class="p1" d="M 320 320 L 320 1160 L 802 1432 L 863 863 L 320 320"/>
- <text x="576" y="944" style="font-size:123">1,12,0</text>
- <line x1="320" y1="320" x2="320" y2="1160"/>
- <path class="p1" d="M 320 1160 L 320 2000 L 740 2000 L 802 1432 L 320 1160"/>
- <text x="545" y="1648" style="font-size:126">1,13,0</text>
- <line x1="320" y1="1160" x2="320" y2="2000"/>
- <path class="p1" d="M 320 2000 L 320 2840 L 802 2568 L 740 2000 L 320 2000"/>
- <text x="545" y="2352" style="font-size:126">1,16,0</text>
- <line x1="320" y1="2000" x2="320" y2="2840"/>
- <path class="p1" d="M 320 2840 L 320 3680 L 863 3137 L 802 2568 L 320 2840"/>
- <text x="576" y="3056" style="font-size:123">1,17,0</text>
- <line x1="320" y1="2840" x2="320" y2="3680"/>
- <path class="p1" d="M 320 3680 L 1160 3680 L 1432 3198 L 863 3137 L 320 3680"/>
- <text x="944" y="3424" style="font-size:123">1,20,0</text>
- <line x1="320" y1="3680" x2="1160" y2="3680"/>
- <path class="p1" d="M 1160 3680 L 2000 3680 L 2000 3260 L 1432 3198 L 1160 3680"/>
- <text x="1648" y="3455" style="font-size:126">1,21,0</text>
- <line x1="1160" y1="3680" x2="2000" y2="3680"/>
- <path class="p1" d="M 2000 3680 L 2840 3680 L 2568 3198 L 2000 3260 L 2000 3680"/>
- <text x="2352" y="3455" style="font-size:126">1,24,0</text>
- <line x1="2000" y1="3680" x2="2840" y2="3680"/>
- <path class="p1" d="M 2840 3680 L 3680 3680 L 3137 3137 L 2568 3198 L 2840 3680"/>
- <text x="3056" y="3424" style="font-size:123">1,25,0</text>
- <line x1="2840" y1="3680" x2="3680" y2="3680"/>
- <path class="p1" d="M 3680 3680 L 3680 2840 L 3198 2568 L 3137 3137 L 3680 3680"/>
- <text x="3424" y="3056" style="font-size:123">1,28,0</text>
- <line x1="3680" y1="3680" x2="3680" y2="2840"/>
- <path class="p1" d="M 3680 2840 L 3680 2000 L 3260 2000 L 3198 2568 L 3680 2840"/>
- <text x="3455" y="2352" style="font-size:126">1,29,0</text>
- <line x1="3680" y1="2840" x2="3680" y2="2000"/>
- <path class="p2" d="M 3260 2000 L 3229 1716 L 3004 1784 L 3050 2000 L 3260 2000"/>
- <text x="3136" y="1875" style="font-size:65">2,0,0</text>
- <path class="p2" d="M 3229 1716 L 3198 1432 L 2958 1567 L 3004 1784 L 3229 1716"/>
- <text x="3097" y="1625" style="font-size:64">2,1,0</text>
- <path class="p2" d="M 3050 2000 L 3004 1784 L 2778 1852 L 2840 2000 L 3050 2000"/>
- <text x="2918" y="1909" style="font-size:65">2,2,0</text>
- <line x1="2840" y1="2000" x2="2778" y2="1852"/>
- <path class="p2" d="M 3004 1784 L 2958 1567 L 2717 1703 L 2778 1852 L 3004 1784"/>
- <text x="2864" y="1726" style="font-size:65">2,3,0</text>
- <line x1="2778" y1="1852" x2="2717" y2="1703"/>
- <path class="p2" d="M 3198 1432 L 3168 1147 L 2912 1351 L 2958 1567 L 3198 1432"/>
- <text x="3059" y="1374" style="font-size:64">2,4,0</text>
- <path class="p2" d="M 3168 1147 L 3137 863 L 2865 1135 L 2912 1351 L 3168 1147"/>
- <text x="3020" y="1124" style="font-size:64">2,5,0</text>
- <path class="p2" d="M 2958 1567 L 2912 1351 L 2655 1555 L 2717 1703 L 2958 1567"/>
- <text x="2810" y="1544" style="font-size:65">2,6,0</text>
- <line x1="2717" y1="1703" x2="2655" y2="1555"/>
- <path class="p2" d="M 2912 1351 L 2865 1135 L 2594 1406 L 2655 1555 L 2912 1351"/>
- <text x="2757" y="1361" style="font-size:65">2,7,0</text>
- <line x1="2655" y1="1555" x2="2594" y2="1406"/>
- <path class="p2" d="M 3137 863 L 2853 832 L 2649 1088 L 2865 1135 L 3137 863"/>
- <text x="2876" y="980" style="font-size:64">2,8,0</text>
- <path class="p2" d="M 2853 832 L 2568 802 L 2433 1042 L 2649 1088 L 2853 832"/>
- <text x="2626" y="941" style="font-size:64">2,9,0</text>
- <path class="p2" d="M 2865 1135 L 2649 1088 L 2445 1345 L 2594 1406 L 2865 1135"/>
- <text x="2639" y="1243" style="font-size:65">2,10,0</text>
- <line x1="2594" y1="1406" x2="2445" y2="1345"/>
- <path class="p2" d="M 2649 1088 L 2433 1042 L 2297 1283 L 2445 1345 L 2649 1088"/>
- <text x="2456" y="1190" style="font-size:65">2,11,0</text>
- <line x1="2445" y1="1345" x2="2297" y2="1283"/>
- <path class="p2" d="M 2568 802 L 2284 771 L 2216 996 L 2433 1042 L 2568 802"/>
- <text x="2375" y="903" style="font-size:64">2,12,0</text>
- <path class="p2" d="M 2284 771 L 2000 740 L 2000 950 L 2216 996 L 2284 771"/>
- <text x="2125" y="864" style="font-size:65">2,13,0</text>
- <path class="p2" d="M 2433 1042 L 2216 996 L 2148 1222 L 2297 1283 L 2433 1042"/>
- <text x="2274" y="1136" style="font-size:65">2,14,0</text>
- <line x1="2297" y1="1283" x2="2148" y2="1222"/>
- <path class="p2" d="M 2216 996 L 2000 950 L 2000 1160 L 2148 1222 L 2216 996"/>
- <text x="2091" y="1082" style="font-size:65">2,15,0</text>
- <line x1="2148" y1="1222" x2="2000" y2="1160"/>
- <path class="p2" d="M 2000 740 L 1716 771 L 1784 996 L 2000 950 L 2000 740"/>
- <text x="1875" y="864" style="font-size:65">2,16,0</text>
- <path class="p2" d="M 1716 771 L 1432 802 L 1567 1042 L 1784 996 L 1716 771"/>
- <text x="1625" y="903" style="font-size:64">2,17,0</text>
- <path class="p2" d="M 2000 950 L 1784 996 L 1852 1222 L 2000 1160 L 2000 950"/>
- <text x="1909" y="1082" style="font-size:65">2,18,0</text>
- <line x1="2000" y1="1160" x2="1852" y2="1222"/>
- <path class="p2" d="M 1784 996 L 1567 1042 L 1703 1283 L 1852 1222 L 1784 996"/>
- <text x="1726" y="1136" style="font-size:65">2,19,0</text>
- <line x1="1852" y1="1222" x2="1703" y2="1283"/>
- <path class="p2" d="M 1432 802 L 1147 832 L 1351 1088 L 1567 1042 L 1432 802"/>
- <text x="1374" y="941" style="font-size:64">2,20,0</text>
- <path class="p2" d="M 1147 832 L 863 863 L 1135 1135 L 1351 1088 L 1147 832"/>
- <text x="1124" y="980" style="font-size:64">2,21,0</text>
- <path class="p2" d="M 1567 1042 L 1351 1088 L 1555 1345 L 1703 1283 L 1567 1042"/>
- <text x="1544" y="1190" style="font-size:65">2,22,0</text>
- <line x1="1703" y1="1283" x2="1555" y2="1345"/>
- <path class="p2" d="M 1351 1088 L 1135 1135 L 1406 1406 L 1555 1345 L 1351 1088"/>
- <text x="1361" y="1243" style="font-size:65">2,23,0</text>
- <line x1="1555" y1="1345" x2="1406" y2="1406"/>
- <path class="p2" d="M 863 863 L 832 1147 L 1088 1351 L 1135 1135 L 863 863"/>
- <text x="980" y="1124" style="font-size:64">2,24,0</text>
- <path class="p2" d="M 832 1147 L 802 1432 L 1042 1567 L 1088 1351 L 832 1147"/>
- <text x="941" y="1374" style="font-size:64">2,25,0</text>
- <path class="p2" d="M 1135 1135 L 1088 1351 L 1345 1555 L 1406 1406 L 1135 1135"/>
- <text x="1243" y="1361" style="font-size:65">2,26,0</text>
- <line x1="1406" y1="1406" x2="1345" y2="1555"/>
- <path class="p2" d="M 1088 1351 L 1042 1567 L 1283 1703 L 1345 1555 L 1088 1351"/>
- <text x="1190" y="1544" style="font-size:65">2,27,0</text>
- <line x1="1345" y1="1555" x2="1283" y2="1703"/>
- <path class="p2" d="M 802 1432 L 771 1716 L 996 1784 L 1042 1567 L 802 1432"/>
- <text x="903" y="1625" style="font-size:64">2,28,0</text>
- <path class="p2" d="M 771 1716 L 740 2000 L 950 2000 L 996 1784 L 771 1716"/>
- <text x="864" y="1875" style="font-size:65">2,29,0</text>
- <path class="p2" d="M 1042 1567 L 996 1784 L 1222 1852 L 1283 1703 L 1042 1567"/>
- <text x="1136" y="1726" style="font-size:65">2,30,0</text>
- <line x1="1283" y1="1703" x2="1222" y2="1852"/>
- <path class="p2" d="M 996 1784 L 950 2000 L 1160 2000 L 1222 1852 L 996 1784"/>
- <text x="1082" y="1909" style="font-size:65">2,31,0</text>
- <line x1="1222" y1="1852" x2="1160" y2="2000"/>
- <path class="p2" d="M 740 2000 L 771 2284 L 996 2216 L 950 2000 L 740 2000"/>
- <text x="864" y="2125" style="font-size:65">2,32,0</text>
- <path class="p2" d="M 771 2284 L 802 2568 L 1042 2433 L 996 2216 L 771 2284"/>
- <text x="903" y="2375" style="font-size:64">2,33,0</text>
- <path class="p2" d="M 950 2000 L 996 2216 L 1222 2148 L 1160 2000 L 950 2000"/>
- <text x="1082" y="2091" style="font-size:65">2,34,0</text>
- <line x1="1160" y1="2000" x2="1222" y2="2148"/>
- <path class="p2" d="M 996 2216 L 1042 2433 L 1283 2297 L 1222 2148 L 996 2216"/>
- <text x="1136" y="2274" style="font-size:65">2,35,0</text>
- <line x1="1222" y1="2148" x2="1283" y2="2297"/>
- <path class="p2" d="M 802 2568 L 832 2853 L 1088 2649 L 1042 2433 L 802 2568"/>
- <text x="941" y="2626" style="font-size:64">2,36,0</text>
- <path class="p2" d="M 832 2853 L 863 3137 L 1135 2865 L 1088 2649 L 832 2853"/>
- <text x="980" y="2876" style="font-size:64">2,37,0</text>
- <path class="p2" d="M 1042 2433 L 1088 2649 L 1345 2445 L 1283 2297 L 1042 2433"/>
- <text x="1190" y="2456" style="font-size:65">2,38,0</text>
- <line x1="1283" y1="2297" x2="1345" y2="2445"/>
- <path class="p2" d="M 1088 2649 L 1135 2865 L 1406 2594 L 1345 2445 L 1088 2649"/>
- <text x="1243" y="2639" style="font-size:65">2,39,0</text>
- <line x1="1345" y1="2445" x2="1406" y2="2594"/>
- <path class="p2" d="M 863 3137 L 1147 3168 L 1351 2912 L 1135 2865 L 863 3137"/>
- <text x="1124" y="3020" style="font-size:64">2,40,0</text>
- <path class="p2" d="M 1147 3168 L 1432 3198 L 1567 2958 L 1351 2912 L 1147 3168"/>
- <text x="1374" y="3059" style="font-size:64">2,41,0</text>
- <path class="p2" d="M 1135 2865 L 1351 2912 L 1555 2655 L 1406 2594 L 1135 2865"/>
- <text x="1361" y="2757" style="font-size:65">2,42,0</text>
- <line x1="1406" y1="2594" x2="1555" y2="2655"/>
- <path class="p2" d="M 1351 2912 L 1567 2958 L 1703 2717 L 1555 2655 L 1351 2912"/>
- <text x="1544" y="2810" style="font-size:65">2,43,0</text>
- <line x1="1555" y1="2655" x2="1703" y2="2717"/>
- <path class="p2" d="M 1432 3198 L 1716 3229 L 1784 3004 L 1567 2958 L 1432 3198"/>
- <text x="1625" y="3097" style="font-size:64">2,44,0</text>
- <path class="p2" d="M 1716 3229 L 2000 3260 L 2000 3050 L 1784 3004 L 1716 3229"/>
- <text x="1875" y="3136" style="font-size:65">2,45,0</text>
- <path class="p2" d="M 1567 2958 L 1784 3004 L 1852 2778 L 1703 2717 L 1567 2958"/>
- <text x="1726" y="2864" style="font-size:65">2,46,0</text>
- <line x1="1703" y1="2717" x2="1852" y2="2778"/>
- <path class="p2" d="M 1784 3004 L 2000 3050 L 2000 2840 L 1852 2778 L 1784 3004"/>
- <text x="1909" y="2918" style="font-size:65">2,47,0</text>
- <line x1="1852" y1="2778" x2="2000" y2="2840"/>
- <path class="p2" d="M 2000 3260 L 2284 3229 L 2216 3004 L 2000 3050 L 2000 3260"/>
- <text x="2125" y="3136" style="font-size:65">2,48,0</text>
- <path class="p2" d="M 2284 3229 L 2568 3198 L 2433 2958 L 2216 3004 L 2284 3229"/>
- <text x="2375" y="3097" style="font-size:64">2,49,0</text>
- <path class="p2" d="M 2000 3050 L 2216 3004 L 2148 2778 L 2000 2840 L 2000 3050"/>
- <text x="2091" y="2918" style="font-size:65">2,50,0</text>
- <line x1="2000" y1="2840" x2="2148" y2="2778"/>
- <path class="p2" d="M 2216 3004 L 2433 2958 L 2297 2717 L 2148 2778 L 2216 3004"/>
- <text x="2274" y="2864" style="font-size:65">2,51,0</text>
- <line x1="2148" y1="2778" x2="2297" y2="2717"/>
- <path class="p2" d="M 2568 3198 L 2853 3168 L 2649 2912 L 2433 2958 L 2568 3198"/>
- <text x="2626" y="3059" style="font-size:64">2,52,0</text>
- <path class="p2" d="M 2853 3168 L 3137 3137 L 2865 2865 L 2649 2912 L 2853 3168"/>
- <text x="2876" y="3020" style="font-size:64">2,53,0</text>
- <path class="p2" d="M 2433 2958 L 2649 2912 L 2445 2655 L 2297 2717 L 2433 2958"/>
- <text x="2456" y="2810" style="font-size:65">2,54,0</text>
- <line x1="2297" y1="2717" x2="2445" y2="2655"/>
- <path class="p2" d="M 2649 2912 L 2865 2865 L 2594 2594 L 2445 2655 L 2649 2912"/>
- <text x="2639" y="2757" style="font-size:65">2,55,0</text>
- <line x1="2445" y1="2655" x2="2594" y2="2594"/>
- <path class="p2" d="M 3137 3137 L 3168 2853 L 2912 2649 L 2865 2865 L 3137 3137"/>
- <text x="3020" y="2876" style="font-size:64">2,56,0</text>
- <path class="p2" d="M 3168 2853 L 3198 2568 L 2958 2433 L 2912 2649 L 3168 2853"/>
- <text x="3059" y="2626" style="font-size:64">2,57,0</text>
- <path class="p2" d="M 2865 2865 L 2912 2649 L 2655 2445 L 2594 2594 L 2865 2865"/>
- <text x="2757" y="2639" style="font-size:65">2,58,0</text>
- <line x1="2594" y1="2594" x2="2655" y2="2445"/>
- <path class="p2" d="M 2912 2649 L 2958 2433 L 2717 2297 L 2655 2445 L 2912 2649"/>
- <text x="2810" y="2456" style="font-size:65">2,59,0</text>
- <line x1="2655" y1="2445" x2="2717" y2="2297"/>
- <path class="p2" d="M 3198 2568 L 3229 2284 L 3004 2216 L 2958 2433 L 3198 2568"/>
- <text x="3097" y="2375" style="font-size:64">2,60,0</text>
- <path class="p2" d="M 3229 2284 L 3260 2000 L 3050 2000 L 3004 2216 L 3229 2284"/>
- <text x="3136" y="2125" style="font-size:65">2,61,0</text>
- <path class="p2" d="M 2958 2433 L 3004 2216 L 2778 2148 L 2717 2297 L 2958 2433"/>
- <text x="2864" y="2274" style="font-size:65">2,62,0</text>
- <line x1="2717" y1="2297" x2="2778" y2="2148"/>
- <path class="p2" d="M 3004 2216 L 3050 2000 L 2840 2000 L 2778 2148 L 3004 2216"/>
- <text x="2918" y="2091" style="font-size:65">2,63,0</text>
- <line x1="2778" y1="2148" x2="2840" y2="2000"/>
+ <path class="p1" d="M 920 500 L 920 290 L 800 358 L 815 500 L 920 500"/>
+ <text x="864" y="412" style="font-size:32">1,0,0</text>
+ <line x1="920" y1="500" x2="920" y2="290"/>
+ <path class="p1" d="M 920 290 L 920 80 L 784 216 L 800 358 L 920 290"/>
+ <text x="856" y="236" style="font-size:31">1,1,0</text>
+ <line x1="920" y1="290" x2="920" y2="80"/>
+ <path class="p1" d="M 920 80 L 710 80 L 642 200 L 784 216 L 920 80"/>
+ <text x="764" y="144" style="font-size:31">1,4,0</text>
+ <line x1="920" y1="80" x2="710" y2="80"/>
+ <path class="p1" d="M 710 80 L 500 80 L 500 185 L 642 200 L 710 80"/>
+ <text x="588" y="136" style="font-size:32">1,5,0</text>
+ <line x1="710" y1="80" x2="500" y2="80"/>
+ <path class="p1" d="M 500 80 L 290 80 L 358 200 L 500 185 L 500 80"/>
+ <text x="412" y="136" style="font-size:32">1,8,0</text>
+ <line x1="500" y1="80" x2="290" y2="80"/>
+ <path class="p1" d="M 290 80 L 80 80 L 216 216 L 358 200 L 290 80"/>
+ <text x="236" y="144" style="font-size:31">1,9,0</text>
+ <line x1="290" y1="80" x2="80" y2="80"/>
+ <path class="p1" d="M 80 80 L 80 290 L 200 358 L 216 216 L 80 80"/>
+ <text x="144" y="236" style="font-size:31">1,12,0</text>
+ <line x1="80" y1="80" x2="80" y2="290"/>
+ <path class="p1" d="M 80 290 L 80 500 L 185 500 L 200 358 L 80 290"/>
+ <text x="136" y="412" style="font-size:32">1,13,0</text>
+ <line x1="80" y1="290" x2="80" y2="500"/>
+ <path class="p1" d="M 80 500 L 80 710 L 200 642 L 185 500 L 80 500"/>
+ <text x="136" y="588" style="font-size:32">1,16,0</text>
+ <line x1="80" y1="500" x2="80" y2="710"/>
+ <path class="p1" d="M 80 710 L 80 920 L 216 784 L 200 642 L 80 710"/>
+ <text x="144" y="764" style="font-size:31">1,17,0</text>
+ <line x1="80" y1="710" x2="80" y2="920"/>
+ <path class="p1" d="M 80 920 L 290 920 L 358 800 L 216 784 L 80 920"/>
+ <text x="236" y="856" style="font-size:31">1,20,0</text>
+ <line x1="80" y1="920" x2="290" y2="920"/>
+ <path class="p1" d="M 290 920 L 500 920 L 500 815 L 358 800 L 290 920"/>
+ <text x="412" y="864" style="font-size:32">1,21,0</text>
+ <line x1="290" y1="920" x2="500" y2="920"/>
+ <path class="p1" d="M 500 920 L 710 920 L 642 800 L 500 815 L 500 920"/>
+ <text x="588" y="864" style="font-size:32">1,24,0</text>
+ <line x1="500" y1="920" x2="710" y2="920"/>
+ <path class="p1" d="M 710 920 L 920 920 L 784 784 L 642 800 L 710 920"/>
+ <text x="764" y="856" style="font-size:31">1,25,0</text>
+ <line x1="710" y1="920" x2="920" y2="920"/>
+ <path class="p1" d="M 920 920 L 920 710 L 800 642 L 784 784 L 920 920"/>
+ <text x="856" y="764" style="font-size:31">1,28,0</text>
+ <line x1="920" y1="920" x2="920" y2="710"/>
+ <path class="p1" d="M 920 710 L 920 500 L 815 500 L 800 642 L 920 710"/>
+ <text x="864" y="588" style="font-size:32">1,29,0</text>
+ <line x1="920" y1="710" x2="920" y2="500"/>
+ <path class="p2" d="M 815 500 L 807 429 L 751 446 L 763 500 L 815 500"/>
+ <text x="784" y="469" style="font-size:16">2,0,0</text>
+ <path class="p2" d="M 807 429 L 800 358 L 739 392 L 751 446 L 807 429"/>
+ <text x="774" y="406" style="font-size:16">2,1,0</text>
+ <path class="p2" d="M 763 500 L 751 446 L 695 463 L 710 500 L 763 500"/>
+ <text x="730" y="477" style="font-size:17">2,2,0</text>
+ <line x1="710" y1="500" x2="695" y2="463"/>
+ <path class="p2" d="M 751 446 L 739 392 L 679 426 L 695 463 L 751 446"/>
+ <text x="716" y="432" style="font-size:17">2,3,0</text>
+ <line x1="695" y1="463" x2="679" y2="426"/>
+ <path class="p2" d="M 800 358 L 792 287 L 728 338 L 739 392 L 800 358"/>
+ <text x="765" y="344" style="font-size:16">2,4,0</text>
+ <path class="p2" d="M 792 287 L 784 216 L 716 284 L 728 338 L 792 287"/>
+ <text x="755" y="281" style="font-size:16">2,5,0</text>
+ <path class="p2" d="M 739 392 L 728 338 L 664 389 L 679 426 L 739 392"/>
+ <text x="703" y="386" style="font-size:17">2,6,0</text>
+ <line x1="679" y1="426" x2="664" y2="389"/>
+ <path class="p2" d="M 728 338 L 716 284 L 648 352 L 664 389 L 728 338"/>
+ <text x="689" y="340" style="font-size:17">2,7,0</text>
+ <line x1="664" y1="389" x2="648" y2="352"/>
+ <path class="p2" d="M 784 216 L 713 208 L 662 272 L 716 284 L 784 216"/>
+ <text x="719" y="245" style="font-size:16">2,8,0</text>
+ <path class="p2" d="M 713 208 L 642 200 L 608 261 L 662 272 L 713 208"/>
+ <text x="656" y="235" style="font-size:16">2,9,0</text>
+ <path class="p2" d="M 716 284 L 662 272 L 611 336 L 648 352 L 716 284"/>
+ <text x="660" y="311" style="font-size:17">2,10,0</text>
+ <line x1="648" y1="352" x2="611" y2="336"/>
+ <path class="p2" d="M 662 272 L 608 261 L 574 321 L 611 336 L 662 272"/>
+ <text x="614" y="297" style="font-size:17">2,11,0</text>
+ <line x1="611" y1="336" x2="574" y2="321"/>
+ <path class="p2" d="M 642 200 L 571 193 L 554 249 L 608 261 L 642 200"/>
+ <text x="594" y="226" style="font-size:16">2,12,0</text>
+ <path class="p2" d="M 571 193 L 500 185 L 500 238 L 554 249 L 571 193"/>
+ <text x="531" y="216" style="font-size:16">2,13,0</text>
+ <path class="p2" d="M 608 261 L 554 249 L 537 305 L 574 321 L 608 261"/>
+ <text x="568" y="284" style="font-size:17">2,14,0</text>
+ <line x1="574" y1="321" x2="537" y2="305"/>
+ <path class="p2" d="M 554 249 L 500 238 L 500 290 L 537 305 L 554 249"/>
+ <text x="523" y="270" style="font-size:17">2,15,0</text>
+ <line x1="537" y1="305" x2="500" y2="290"/>
+ <path class="p2" d="M 500 185 L 429 193 L 446 249 L 500 238 L 500 185"/>
+ <text x="469" y="216" style="font-size:16">2,16,0</text>
+ <path class="p2" d="M 429 193 L 358 200 L 392 261 L 446 249 L 429 193"/>
+ <text x="406" y="226" style="font-size:16">2,17,0</text>
+ <path class="p2" d="M 500 238 L 446 249 L 463 305 L 500 290 L 500 238"/>
+ <text x="477" y="270" style="font-size:17">2,18,0</text>
+ <line x1="500" y1="290" x2="463" y2="305"/>
+ <path class="p2" d="M 446 249 L 392 261 L 426 321 L 463 305 L 446 249"/>
+ <text x="432" y="284" style="font-size:17">2,19,0</text>
+ <line x1="463" y1="305" x2="426" y2="321"/>
+ <path class="p2" d="M 358 200 L 287 208 L 338 272 L 392 261 L 358 200"/>
+ <text x="344" y="235" style="font-size:16">2,20,0</text>
+ <path class="p2" d="M 287 208 L 216 216 L 284 284 L 338 272 L 287 208"/>
+ <text x="281" y="245" style="font-size:16">2,21,0</text>
+ <path class="p2" d="M 392 261 L 338 272 L 389 336 L 426 321 L 392 261"/>
+ <text x="386" y="297" style="font-size:17">2,22,0</text>
+ <line x1="426" y1="321" x2="389" y2="336"/>
+ <path class="p2" d="M 338 272 L 284 284 L 352 352 L 389 336 L 338 272"/>
+ <text x="340" y="311" style="font-size:17">2,23,0</text>
+ <line x1="389" y1="336" x2="352" y2="352"/>
+ <path class="p2" d="M 216 216 L 208 287 L 272 338 L 284 284 L 216 216"/>
+ <text x="245" y="281" style="font-size:16">2,24,0</text>
+ <path class="p2" d="M 208 287 L 200 358 L 261 392 L 272 338 L 208 287"/>
+ <text x="235" y="344" style="font-size:16">2,25,0</text>
+ <path class="p2" d="M 284 284 L 272 338 L 336 389 L 352 352 L 284 284"/>
+ <text x="311" y="340" style="font-size:17">2,26,0</text>
+ <line x1="352" y1="352" x2="336" y2="389"/>
+ <path class="p2" d="M 272 338 L 261 392 L 321 426 L 336 389 L 272 338"/>
+ <text x="297" y="386" style="font-size:17">2,27,0</text>
+ <line x1="336" y1="389" x2="321" y2="426"/>
+ <path class="p2" d="M 200 358 L 193 429 L 249 446 L 261 392 L 200 358"/>
+ <text x="226" y="406" style="font-size:16">2,28,0</text>
+ <path class="p2" d="M 193 429 L 185 500 L 238 500 L 249 446 L 193 429"/>
+ <text x="216" y="469" style="font-size:16">2,29,0</text>
+ <path class="p2" d="M 261 392 L 249 446 L 305 463 L 321 426 L 261 392"/>
+ <text x="284" y="432" style="font-size:17">2,30,0</text>
+ <line x1="321" y1="426" x2="305" y2="463"/>
+ <path class="p2" d="M 249 446 L 238 500 L 290 500 L 305 463 L 249 446"/>
+ <text x="270" y="477" style="font-size:17">2,31,0</text>
+ <line x1="305" y1="463" x2="290" y2="500"/>
+ <path class="p2" d="M 185 500 L 193 571 L 249 554 L 238 500 L 185 500"/>
+ <text x="216" y="531" style="font-size:16">2,32,0</text>
+ <path class="p2" d="M 193 571 L 200 642 L 261 608 L 249 554 L 193 571"/>
+ <text x="226" y="594" style="font-size:16">2,33,0</text>
+ <path class="p2" d="M 238 500 L 249 554 L 305 537 L 290 500 L 238 500"/>
+ <text x="270" y="523" style="font-size:17">2,34,0</text>
+ <line x1="290" y1="500" x2="305" y2="537"/>
+ <path class="p2" d="M 249 554 L 261 608 L 321 574 L 305 537 L 249 554"/>
+ <text x="284" y="568" style="font-size:17">2,35,0</text>
+ <line x1="305" y1="537" x2="321" y2="574"/>
+ <path class="p2" d="M 200 642 L 208 713 L 272 662 L 261 608 L 200 642"/>
+ <text x="235" y="656" style="font-size:16">2,36,0</text>
+ <path class="p2" d="M 208 713 L 216 784 L 284 716 L 272 662 L 208 713"/>
+ <text x="245" y="719" style="font-size:16">2,37,0</text>
+ <path class="p2" d="M 261 608 L 272 662 L 336 611 L 321 574 L 261 608"/>
+ <text x="297" y="614" style="font-size:17">2,38,0</text>
+ <line x1="321" y1="574" x2="336" y2="611"/>
+ <path class="p2" d="M 272 662 L 284 716 L 352 648 L 336 611 L 272 662"/>
+ <text x="311" y="660" style="font-size:17">2,39,0</text>
+ <line x1="336" y1="611" x2="352" y2="648"/>
+ <path class="p2" d="M 216 784 L 287 792 L 338 728 L 284 716 L 216 784"/>
+ <text x="281" y="755" style="font-size:16">2,40,0</text>
+ <path class="p2" d="M 287 792 L 358 800 L 392 739 L 338 728 L 287 792"/>
+ <text x="344" y="765" style="font-size:16">2,41,0</text>
+ <path class="p2" d="M 284 716 L 338 728 L 389 664 L 352 648 L 284 716"/>
+ <text x="340" y="689" style="font-size:17">2,42,0</text>
+ <line x1="352" y1="648" x2="389" y2="664"/>
+ <path class="p2" d="M 338 728 L 392 739 L 426 679 L 389 664 L 338 728"/>
+ <text x="386" y="703" style="font-size:17">2,43,0</text>
+ <line x1="389" y1="664" x2="426" y2="679"/>
+ <path class="p2" d="M 358 800 L 429 807 L 446 751 L 392 739 L 358 800"/>
+ <text x="406" y="774" style="font-size:16">2,44,0</text>
+ <path class="p2" d="M 429 807 L 500 815 L 500 763 L 446 751 L 429 807"/>
+ <text x="469" y="784" style="font-size:16">2,45,0</text>
+ <path class="p2" d="M 392 739 L 446 751 L 463 695 L 426 679 L 392 739"/>
+ <text x="432" y="716" style="font-size:17">2,46,0</text>
+ <line x1="426" y1="679" x2="463" y2="695"/>
+ <path class="p2" d="M 446 751 L 500 763 L 500 710 L 463 695 L 446 751"/>
+ <text x="477" y="730" style="font-size:17">2,47,0</text>
+ <line x1="463" y1="695" x2="500" y2="710"/>
+ <path class="p2" d="M 500 815 L 571 807 L 554 751 L 500 763 L 500 815"/>
+ <text x="531" y="784" style="font-size:16">2,48,0</text>
+ <path class="p2" d="M 571 807 L 642 800 L 608 739 L 554 751 L 571 807"/>
+ <text x="594" y="774" style="font-size:16">2,49,0</text>
+ <path class="p2" d="M 500 763 L 554 751 L 537 695 L 500 710 L 500 763"/>
+ <text x="523" y="730" style="font-size:17">2,50,0</text>
+ <line x1="500" y1="710" x2="537" y2="695"/>
+ <path class="p2" d="M 554 751 L 608 739 L 574 679 L 537 695 L 554 751"/>
+ <text x="568" y="716" style="font-size:17">2,51,0</text>
+ <line x1="537" y1="695" x2="574" y2="679"/>
+ <path class="p2" d="M 642 800 L 713 792 L 662 728 L 608 739 L 642 800"/>
+ <text x="656" y="765" style="font-size:16">2,52,0</text>
+ <path class="p2" d="M 713 792 L 784 784 L 716 716 L 662 728 L 713 792"/>
+ <text x="719" y="755" style="font-size:16">2,53,0</text>
+ <path class="p2" d="M 608 739 L 662 728 L 611 664 L 574 679 L 608 739"/>
+ <text x="614" y="703" style="font-size:17">2,54,0</text>
+ <line x1="574" y1="679" x2="611" y2="664"/>
+ <path class="p2" d="M 662 728 L 716 716 L 648 648 L 611 664 L 662 728"/>
+ <text x="660" y="689" style="font-size:17">2,55,0</text>
+ <line x1="611" y1="664" x2="648" y2="648"/>
+ <path class="p2" d="M 784 784 L 792 713 L 728 662 L 716 716 L 784 784"/>
+ <text x="755" y="719" style="font-size:16">2,56,0</text>
+ <path class="p2" d="M 792 713 L 800 642 L 739 608 L 728 662 L 792 713"/>
+ <text x="765" y="656" style="font-size:16">2,57,0</text>
+ <path class="p2" d="M 716 716 L 728 662 L 664 611 L 648 648 L 716 716"/>
+ <text x="689" y="660" style="font-size:17">2,58,0</text>
+ <line x1="648" y1="648" x2="664" y2="611"/>
+ <path class="p2" d="M 728 662 L 739 608 L 679 574 L 664 611 L 728 662"/>
+ <text x="703" y="614" style="font-size:17">2,59,0</text>
+ <line x1="664" y1="611" x2="679" y2="574"/>
+ <path class="p2" d="M 800 642 L 807 571 L 751 554 L 739 608 L 800 642"/>
+ <text x="774" y="594" style="font-size:16">2,60,0</text>
+ <path class="p2" d="M 807 571 L 815 500 L 763 500 L 751 554 L 807 571"/>
+ <text x="784" y="531" style="font-size:16">2,61,0</text>
+ <path class="p2" d="M 739 608 L 751 554 L 695 537 L 679 574 L 739 608"/>
+ <text x="716" y="568" style="font-size:17">2,62,0</text>
+ <line x1="679" y1="574" x2="695" y2="537"/>
+ <path class="p2" d="M 751 554 L 763 500 L 710 500 L 695 537 L 751 554"/>
+ <text x="730" y="523" style="font-size:17">2,63,0</text>
+ <line x1="695" y1="537" x2="710" y2="500"/>
<!-- legend -->
- <rect x="4000" y="320" width="1280" height="660"/>
- <text x="4050" y="425" style="text-anchor:start; font-weight:bold; font-size:70">cell label</text>
- <text x="4080" y="530" style="text-anchor:start; font-style:oblique; font-size:70">level_number,</text>
- <text x="4080" y="635" style="text-anchor:start; font-style:oblique; font-size:70">cell_index,</text>
- <text x="4080" y="740" style="text-anchor:start; font-style:oblique; font-size:70">material_id</text>
- <text x="4000" y="1073" style="text-anchor:start; font-size:70">azimuth: 0°, polar: 0°</text>
+ <rect x="1000" y="80" width="320" height="165"/>
+ <text x="1013" y="107" style="text-anchor:start; font-weight:bold; font-size:18">cell label</text>
+ <text x="1020" y="134" style="text-anchor:start; font-style:oblique; font-size:18">level_number,</text>
+ <text x="1020" y="161" style="text-anchor:start; font-style:oblique; font-size:18">cell_index,</text>
+ <text x="1020" y="188" style="text-anchor:start; font-style:oblique; font-size:18">material_id</text>
+ <text x="1000" y="274" style="text-anchor:start; font-size:18">azimuth: 0°, polar: 0°</text>
<!-- colorbar -->
- <text x="4000" y="1424" style="text-anchor:start; font-weight:bold; font-size:70">level_number</text>
- <rect class="r0" x="4000" y="2946" width="100" height="733"/>
- <text x="4150.00" y="3337.50" style="text-anchor:start; font-size:70; font-weight:bold">0 min</text>
- <rect class="r1" x="4000" y="2213" width="100" height="733"/>
- <text x="4150.00" y="2604.50" style="text-anchor:start; font-size:70">1</text>
- <rect class="r2" x="4000" y="1480" width="100" height="733"/>
- <text x="4150.00" y="1871.50" style="text-anchor:start; font-size:70; font-weight:bold">2 max</text>
+ <text x="1000" y="356" style="text-anchor:start; font-weight:bold; font-size:18">level_number</text>
+ <rect class="r0" x="1000" y="736" width="25" height="183"/>
+ <text x="1037.50" y="833.500" style="text-anchor:start; font-size:18; font-weight:bold">0 min</text>
+ <rect class="r1" x="1000" y="553" width="25" height="183"/>
+ <text x="1037.50" y="650.500" style="text-anchor:start; font-size:18">1</text>
+ <rect class="r2" x="1000" y="370" width="25" height="183"/>
+ <text x="1037.50" y="467.500" style="text-anchor:start; font-size:18; font-weight:bold">2 max</text>
</svg>
\ No newline at end of file
GridGenerator::hyper_cube_with_cylindrical_hole(triangulation, inner_radius, outer_radius);
triangulation.refine_global(1);
- Triangulation<2>::active_cell_iterator
-
- cell = triangulation.begin_active(),
- endc = triangulation.end();
-
- for (; cell!=endc; ++cell)
+ for (unsigned int l=0;l<3;++l)
{
- for (unsigned int v=0; v < GeometryInfo<2>::vertices_per_cell; ++v)
- {
- const double distance_from_center = center.distance(cell->vertex(v));
-
- if (std::fabs(distance_from_center - inner_radius) < .25)
- {
- cell->set_refine_flag();
- break;
- }
- }
+ Triangulation<2>::active_cell_iterator
+ cell = triangulation.begin_active(),
+ endc = triangulation.end();
+
+ for (; cell!=endc; ++cell)
+ {
+ for (unsigned int v=0; v < GeometryInfo<2>::vertices_per_cell; ++v)
+ {
+ const double distance_from_center = center.distance(cell->vertex(v));
+
+ if (std::fabs(distance_from_center - inner_radius) < .25)
+ {
+ cell->set_refine_flag();
+ break;
+ }
+ }
+ }
+
+ triangulation.execute_coarsening_and_refinement();
}
-
- triangulation.execute_coarsening_and_refinement();
-
+
return triangulation;
}
svg_flags.label_subdomain_id = true;
svg_flags.label_level_subdomain_id = true;
svg_flags.background = GridOutFlags::Svg::transparent;
- svg_flags.polar_angle = 45;
+ svg_flags.polar_angle = 60;
svg_flags.convert_level_number_to_height = true;
-
+ svg_flags.level_height_factor = .5;
+ svg_flags.height = 0;
+ svg_flags.width = 2000;
grid_out.set_flags(svg_flags);
grid_out.write_svg(create_grid(), deallog.get_file_stream());
-<svg width="7850" height="4000" xmlns="http://www.w3.org/2000/svg" version="1.1">
+<svg width="2482" height="1205" xmlns="http://www.w3.org/2000/svg" version="1.1">
<!-- internal style sheet -->
path.p0{fill:rgb(0,102,255); stroke:rgb(25,25,25); stroke-width:2}
path.ps0{fill:rgb(0,77,191); stroke:rgb(20,20,20); stroke-width:2}
rect.r0{fill:rgb(0,102,255); stroke:rgb(25,25,25); stroke-width:2}
- path.p1{fill:rgb(51,255,0); stroke:rgb(25,25,25); stroke-width:2}
- path.ps1{fill:rgb(38,191,0); stroke:rgb(20,20,20); stroke-width:2}
- rect.r1{fill:rgb(51,255,0); stroke:rgb(25,25,25); stroke-width:2}
- path.p2{fill:rgb(255,0,0); stroke:rgb(25,25,25); stroke-width:2}
- path.ps2{fill:rgb(191,0,0); stroke:rgb(20,20,20); stroke-width:2}
- rect.r2{fill:rgb(255,0,0); stroke:rgb(25,25,25); stroke-width:2}
+ path.p1{fill:rgb(0,255,178); stroke:rgb(25,25,25); stroke-width:2}
+ path.ps1{fill:rgb(0,191,134); stroke:rgb(20,20,20); stroke-width:2}
+ rect.r1{fill:rgb(0,255,178); stroke:rgb(25,25,25); stroke-width:2}
+ path.p2{fill:rgb(51,255,0); stroke:rgb(25,25,25); stroke-width:2}
+ path.ps2{fill:rgb(38,191,0); stroke:rgb(20,20,20); stroke-width:2}
+ rect.r2{fill:rgb(51,255,0); stroke:rgb(25,25,25); stroke-width:2}
+ path.p3{fill:rgb(255,230,0); stroke:rgb(25,25,25); stroke-width:2}
+ path.ps3{fill:rgb(191,173,0); stroke:rgb(20,20,20); stroke-width:2}
+ rect.r3{fill:rgb(255,230,0); stroke:rgb(25,25,25); stroke-width:2}
+ path.p4{fill:rgb(255,0,0); stroke:rgb(25,25,25); stroke-width:2}
+ path.ps4{fill:rgb(191,0,0); stroke:rgb(20,20,20); stroke-width:2}
+ rect.r4{fill:rgb(255,0,0); stroke:rgb(25,25,25); stroke-width:2}
]]></style>
- <rect class="background" width="7850" height="4000"/>
+ <rect class="background" width="2000" height="1205"/>
<!-- cells -->
- <path class="ps0" d="M 5193 1904 L 4882 661 L 3813 1417 L 4159 1904 L 5193 1904"/>
- <text x="4517" y="1437" style="font-size:222">0,0,0,X,0</text>
- <line x1="5193" y1="1904" x2="4882" y2="661"/>
- <line x1="4159" y1="1904" x2="3813" y2="1417"/>
- <path class="ps0" d="M 4882 661 L 3125 661 L 3125 1232 L 3813 1417 L 4882 661"/>
- <text x="3746" y="977" style="font-size:192">0,1,0,X,0</text>
- <line x1="4882" y1="661" x2="3125" y2="661"/>
- <line x1="3813" y1="1417" x2="3125" y2="1232"/>
- <path class="ps0" d="M 3125 661 L 1368 661 L 2437 1417 L 3125 1232 L 3125 661"/>
- <text x="2504" y="977" style="font-size:192">0,2,0,X,0</text>
- <line x1="3125" y1="661" x2="1368" y2="661"/>
- <line x1="3125" y1="1232" x2="2437" y2="1417"/>
- <path class="ps0" d="M 1368 661 L 1057 1904 L 2091 1904 L 2437 1417 L 1368 661"/>
- <text x="1733" y="1437" style="font-size:222">0,3,0,X,0</text>
- <line x1="1368" y1="661" x2="1057" y2="1904"/>
- <line x1="2437" y1="1417" x2="2091" y2="1904"/>
- <path class="ps0" d="M 1057 1904 L 613 3680 L 2345 2455 L 2091 1904 L 1057 1904"/>
- <text x="1556" y="2430" style="font-size:295">0,4,0,X,0</text>
- <line x1="1057" y1="1904" x2="613" y2="3680"/>
- <line x1="2091" y1="1904" x2="2345" y2="2455"/>
- <path class="ps0" d="M 613 3680 L 3125 3680 L 3125 2706 L 2345 2455 L 613 3680"/>
- <text x="2324" y="3097" style="font-size:352">0,5,0,X,0</text>
- <line x1="613" y1="3680" x2="3125" y2="3680"/>
- <line x1="2345" y1="2455" x2="3125" y2="2706"/>
- <path class="ps0" d="M 3125 3680 L 5637 3680 L 3905 2455 L 3125 2706 L 3125 3680"/>
- <text x="3926" y="3097" style="font-size:352">0,6,0,X,0</text>
- <line x1="3125" y1="3680" x2="5637" y2="3680"/>
- <line x1="3125" y1="2706" x2="3905" y2="2455"/>
- <path class="ps0" d="M 5637 3680 L 5193 1904 L 4159 1904 L 3905 2455 L 5637 3680"/>
- <text x="4694" y="2430" style="font-size:295">0,7,0,X,0</text>
- <line x1="5637" y1="3680" x2="5193" y2="1904"/>
- <line x1="3905" y1="2455" x2="4159" y2="1904"/>
- <path class="p1" d="M 5269 1600 L 5089 932 L 4565 1135 L 4733 1600 L 5269 1600"/>
- <text x="4913" y="1306" style="font-size:125">1,0,0,0,0</text>
- <line x1="5269" y1="1600" x2="5089" y2="932"/>
- <path class="p1" d="M 5089 932 L 4937 366 L 4416 721 L 4565 1135 L 5089 932"/>
- <text x="4754" y="777" style="font-size:103">1,1,0,0,0</text>
- <line x1="5089" y1="932" x2="4937" y2="366"/>
- <path class="ps1" d="M 4733 1600 L 4565 1135 L 4011 1350 L 4197 1600 L 4733 1600"/>
- <text x="4377" y="1417" style="font-size:134">1,2,0,X,0</text>
- <line x1="4197" y1="1600" x2="4011" y2="1350"/>
- <path class="ps1" d="M 4565 1135 L 4416 721 L 3837 1116 L 4011 1350 L 4565 1135"/>
- <text x="4211" y="1074" style="font-size:119">1,3,0,X,0</text>
- <line x1="4011" y1="1350" x2="3837" y2="1116"/>
- <path class="p1" d="M 4937 366 L 4031 366 L 3767 679 L 4416 721 L 4937 366"/>
- <text x="4292" y="529" style="font-size:95">1,4,0,0,0</text>
- <line x1="4937" y1="366" x2="4031" y2="366"/>
- <path class="p1" d="M 4031 366 L 3125 366 L 3125 638 L 3767 679 L 4031 366"/>
- <text x="3513" y="509" style="font-size:96">1,5,0,0,0</text>
- <line x1="4031" y1="366" x2="3125" y2="366"/>
- <path class="ps1" d="M 4416 721 L 3767 679 L 3477 1022 L 3837 1116 L 4416 721"/>
- <text x="3878" y="880" style="font-size:112">1,6,0,X,0</text>
- <line x1="3837" y1="1116" x2="3477" y2="1022"/>
- <path class="ps1" d="M 3767 679 L 3125 638 L 3125 932 L 3477 1022 L 3767 679"/>
- <text x="3374" y="814" style="font-size:110">1,7,0,X,0</text>
- <line x1="3477" y1="1022" x2="3125" y2="932"/>
- <path class="p1" d="M 3125 366 L 2219 366 L 2483 679 L 3125 638 L 3125 366"/>
- <text x="2737" y="509" style="font-size:96">1,8,0,0,0</text>
- <line x1="3125" y1="366" x2="2219" y2="366"/>
- <path class="p1" d="M 2219 366 L 1313 366 L 1834 721 L 2483 679 L 2219 366"/>
- <text x="1958" y="529" style="font-size:95">1,9,0,0,0</text>
- <line x1="2219" y1="366" x2="1313" y2="366"/>
- <path class="ps1" d="M 3125 638 L 2483 679 L 2773 1022 L 3125 932 L 3125 638"/>
- <text x="2876" y="814" style="font-size:110">1,10,0,X,0</text>
- <line x1="3125" y1="932" x2="2773" y2="1022"/>
- <path class="ps1" d="M 2483 679 L 1834 721 L 2413 1116 L 2773 1022 L 2483 679"/>
- <text x="2372" y="880" style="font-size:112">1,11,0,X,0</text>
- <line x1="2773" y1="1022" x2="2413" y2="1116"/>
- <path class="p1" d="M 1313 366 L 1161 932 L 1685 1135 L 1834 721 L 1313 366"/>
- <text x="1496" y="777" style="font-size:103">1,12,0,0,0</text>
- <line x1="1313" y1="366" x2="1161" y2="932"/>
- <path class="p1" d="M 1161 932 L 981 1600 L 1517 1600 L 1685 1135 L 1161 932"/>
- <text x="1337" y="1306" style="font-size:125">1,13,0,0,0</text>
- <line x1="1161" y1="932" x2="981" y2="1600"/>
- <path class="ps1" d="M 1834 721 L 1685 1135 L 2239 1350 L 2413 1116 L 1834 721"/>
- <text x="2039" y="1074" style="font-size:119">1,14,0,X,0</text>
- <line x1="2413" y1="1116" x2="2239" y2="1350"/>
- <path class="ps1" d="M 1685 1135 L 1517 1600 L 2053 1600 L 2239 1350 L 1685 1135"/>
- <text x="1873" y="1417" style="font-size:134">1,15,0,X,0</text>
- <line x1="2239" y1="1350" x2="2053" y2="1600"/>
- <path class="p1" d="M 981 1600 L 765 2404 L 1494 2127 L 1517 1600 L 981 1600"/>
- <text x="1195" y="1919" style="font-size:150">1,16,0,0,0</text>
- <line x1="981" y1="1600" x2="765" y2="2404"/>
- <path class="p1" d="M 765 2404 L 500 3389 L 1469 2729 L 1494 2127 L 765 2404"/>
- <text x="1071" y="2638" style="font-size:178">1,17,0,0,0</text>
- <line x1="765" y1="2404" x2="500" y2="3389"/>
- <path class="ps1" d="M 1517 1600 L 1494 2127 L 2179 1867 L 2053 1600 L 1517 1600"/>
- <text x="1813" y="1793" style="font-size:150">1,18,0,X,0</text>
- <line x1="2053" y1="1600" x2="2179" y2="1867"/>
- <path class="ps1" d="M 1494 2127 L 1469 2729 L 2314 2153 L 2179 1867 L 1494 2127"/>
- <text x="1873" y="2208" style="font-size:167">1,19,0,X,0</text>
- <line x1="2179" y1="1867" x2="2314" y2="2153"/>
- <path class="p1" d="M 500 3389 L 1812 3389 L 2290 2799 L 1469 2729 L 500 3389"/>
- <text x="1529" y="3066" style="font-size:198">1,20,0,0,0</text>
- <line x1="500" y1="3389" x2="1812" y2="3389"/>
- <path class="p1" d="M 1812 3389 L 3125 3389 L 3125 2870 L 2290 2799 L 1812 3389"/>
- <text x="2591" y="3103" style="font-size:206">1,21,0,0,0</text>
- <line x1="1812" y1="3389" x2="3125" y2="3389"/>
- <path class="ps1" d="M 1469 2729 L 2290 2799 L 2714 2277 L 2314 2153 L 1469 2729"/>
- <text x="2205" y="2480" style="font-size:180">1,22,0,X,0</text>
- <line x1="2314" y1="2153" x2="2714" y2="2277"/>
- <path class="ps1" d="M 2290 2799 L 3125 2870 L 3125 2404 L 2714 2277 L 2290 2799"/>
- <text x="2815" y="2580" style="font-size:187">1,23,0,X,0</text>
- <line x1="2714" y1="2277" x2="3125" y2="2404"/>
- <path class="p1" d="M 3125 3389 L 4438 3389 L 3960 2799 L 3125 2870 L 3125 3389"/>
- <text x="3659" y="3103" style="font-size:206">1,24,0,0,0</text>
- <line x1="3125" y1="3389" x2="4438" y2="3389"/>
- <path class="p1" d="M 4438 3389 L 5750 3389 L 4781 2729 L 3960 2799 L 4438 3389"/>
- <text x="4721" y="3066" style="font-size:198">1,25,0,0,0</text>
- <line x1="4438" y1="3389" x2="5750" y2="3389"/>
- <path class="ps1" d="M 3125 2870 L 3960 2799 L 3536 2277 L 3125 2404 L 3125 2870"/>
- <text x="3435" y="2580" style="font-size:187">1,26,0,X,0</text>
- <line x1="3125" y1="2404" x2="3536" y2="2277"/>
- <path class="ps1" d="M 3960 2799 L 4781 2729 L 3936 2153 L 3536 2277 L 3960 2799"/>
- <text x="4045" y="2480" style="font-size:180">1,27,0,X,0</text>
- <line x1="3536" y1="2277" x2="3936" y2="2153"/>
- <path class="p1" d="M 5750 3389 L 5485 2404 L 4756 2127 L 4781 2729 L 5750 3389"/>
- <text x="5179" y="2638" style="font-size:178">1,28,0,0,0</text>
- <line x1="5750" y1="3389" x2="5485" y2="2404"/>
- <path class="p1" d="M 5485 2404 L 5269 1600 L 4733 1600 L 4756 2127 L 5485 2404"/>
- <text x="5055" y="1919" style="font-size:150">1,29,0,0,0</text>
- <line x1="5485" y1="2404" x2="5269" y2="1600"/>
- <path class="ps1" d="M 4781 2729 L 4756 2127 L 4071 1867 L 3936 2153 L 4781 2729"/>
- <text x="4377" y="2208" style="font-size:167">1,30,0,X,0</text>
- <line x1="3936" y1="2153" x2="4071" y2="1867"/>
- <path class="ps1" d="M 4756 2127 L 4733 1600 L 4197 1600 L 4071 1867 L 4756 2127"/>
- <text x="4437" y="1793" style="font-size:150">1,31,0,X,0</text>
- <line x1="4071" y1="1867" x2="4197" y2="1600"/>
- <path class="p2" d="M 4794 1274 L 4703 1036 L 4423 1091 L 4516 1274 L 4794 1274"/>
- <text x="4609" y="1167" style="font-size:73">2,0,0,0,0</text>
- <path class="p2" d="M 4703 1036 L 4617 812 L 4334 917 L 4423 1091 L 4703 1036"/>
- <text x="4519" y="963" style="font-size:69">2,1,0,0,0</text>
- <path class="p2" d="M 4516 1274 L 4423 1091 L 4139 1148 L 4238 1274 L 4516 1274"/>
- <text x="4329" y="1196" style="font-size:75">2,2,0,0,0</text>
- <line x1="4238" y1="1274" x2="4139" y2="1148"/>
- <path class="p2" d="M 4423 1091 L 4334 917 L 4044 1026 L 4139 1148 L 4423 1091"/>
- <text x="4236" y="1045" style="font-size:72">2,3,0,0,0</text>
- <line x1="4139" y1="1148" x2="4044" y2="1026"/>
- <path class="p2" d="M 4617 812 L 4536 601 L 4250 751 L 4334 917 L 4617 812"/>
- <text x="4435" y="769" style="font-size:64">2,4,0,0,0</text>
- <path class="p2" d="M 4536 601 L 4459 403 L 4169 592 L 4250 751 L 4536 601"/>
- <text x="4355" y="585" style="font-size:60">2,5,0,0,0</text>
- <path class="p2" d="M 4334 917 L 4250 751 L 3952 907 L 4044 1026 L 4334 917"/>
- <text x="4146" y="899" style="font-size:68">2,6,0,0,0</text>
- <line x1="4044" y1="1026" x2="3952" y2="907"/>
- <path class="p2" d="M 4250 751 L 4169 592 L 3862 793 L 3952 907 L 4250 751"/>
- <text x="4060" y="759" style="font-size:65">2,7,0,0,0</text>
- <line x1="3952" y1="907" x2="3862" y2="793"/>
- <path class="p2" d="M 4459 403 L 4123 382 L 3904 559 L 4169 592 L 4459 403"/>
- <text x="4165" y="483" style="font-size:58">2,8,0,0,0</text>
- <path class="p2" d="M 4123 382 L 3788 361 L 3642 527 L 3904 559 L 4123 382"/>
- <text x="3865" y="456" style="font-size:58">2,9,0,0,0</text>
- <path class="p2" d="M 4169 592 L 3904 559 L 3674 746 L 3862 793 L 4169 592"/>
- <text x="3904" y="671" style="font-size:63">2,10,0,0,0</text>
- <line x1="3862" y1="793" x2="3674" y2="746"/>
- <path class="p2" d="M 3904 559 L 3642 527 L 3489 700 L 3674 746 L 3904 559"/>
- <text x="3678" y="632" style="font-size:62">2,11,0,0,0</text>
- <line x1="3674" y1="746" x2="3489" y2="700"/>
- <path class="p2" d="M 3788 361 L 3456 340 L 3382 494 L 3642 527 L 3788 361"/>
- <text x="3567" y="430" style="font-size:57">2,12,0,0,0</text>
- <path class="p2" d="M 3456 340 L 3125 320 L 3125 462 L 3382 494 L 3456 340"/>
- <text x="3272" y="403" style="font-size:57">2,13,0,0,0</text>
- <path class="p2" d="M 3642 527 L 3382 494 L 3306 655 L 3489 700 L 3642 527"/>
- <text x="3455" y="593" style="font-size:62">2,14,0,0,0</text>
- <line x1="3489" y1="700" x2="3306" y2="655"/>
- <path class="p2" d="M 3382 494 L 3125 462 L 3125 610 L 3306 655 L 3382 494"/>
- <text x="3234" y="555" style="font-size:61">2,15,0,0,0</text>
- <line x1="3306" y1="655" x2="3125" y2="610"/>
- <path class="p2" d="M 3125 320 L 2794 340 L 2868 494 L 3125 462 L 3125 320"/>
- <text x="2978" y="403" style="font-size:57">2,16,0,0,0</text>
- <path class="p2" d="M 2794 340 L 2462 361 L 2608 527 L 2868 494 L 2794 340"/>
- <text x="2683" y="430" style="font-size:57">2,17,0,0,0</text>
- <path class="p2" d="M 3125 462 L 2868 494 L 2944 655 L 3125 610 L 3125 462"/>
- <text x="3016" y="555" style="font-size:61">2,18,0,0,0</text>
- <line x1="3125" y1="610" x2="2944" y2="655"/>
- <path class="p2" d="M 2868 494 L 2608 527 L 2761 700 L 2944 655 L 2868 494"/>
- <text x="2795" y="593" style="font-size:62">2,19,0,0,0</text>
- <line x1="2944" y1="655" x2="2761" y2="700"/>
- <path class="p2" d="M 2462 361 L 2127 382 L 2346 559 L 2608 527 L 2462 361"/>
- <text x="2385" y="456" style="font-size:58">2,20,0,0,0</text>
- <path class="p2" d="M 2127 382 L 1791 403 L 2081 592 L 2346 559 L 2127 382"/>
- <text x="2085" y="483" style="font-size:58">2,21,0,0,0</text>
- <path class="p2" d="M 2608 527 L 2346 559 L 2576 746 L 2761 700 L 2608 527"/>
- <text x="2572" y="632" style="font-size:62">2,22,0,0,0</text>
- <line x1="2761" y1="700" x2="2576" y2="746"/>
- <path class="p2" d="M 2346 559 L 2081 592 L 2388 793 L 2576 746 L 2346 559"/>
- <text x="2346" y="671" style="font-size:63">2,23,0,0,0</text>
- <line x1="2576" y1="746" x2="2388" y2="793"/>
- <path class="p2" d="M 1791 403 L 1714 601 L 2000 751 L 2081 592 L 1791 403"/>
- <text x="1895" y="585" style="font-size:60">2,24,0,0,0</text>
- <path class="p2" d="M 1714 601 L 1633 812 L 1916 917 L 2000 751 L 1714 601"/>
- <text x="1815" y="769" style="font-size:64">2,25,0,0,0</text>
- <path class="p2" d="M 2081 592 L 2000 751 L 2298 907 L 2388 793 L 2081 592"/>
- <text x="2190" y="759" style="font-size:65">2,26,0,0,0</text>
- <line x1="2388" y1="793" x2="2298" y2="907"/>
- <path class="p2" d="M 2000 751 L 1916 917 L 2206 1026 L 2298 907 L 2000 751"/>
- <text x="2104" y="899" style="font-size:68">2,27,0,0,0</text>
- <line x1="2298" y1="907" x2="2206" y2="1026"/>
- <path class="p2" d="M 1633 812 L 1547 1036 L 1827 1091 L 1916 917 L 1633 812"/>
- <text x="1731" y="963" style="font-size:69">2,28,0,0,0</text>
- <path class="p2" d="M 1547 1036 L 1456 1274 L 1734 1274 L 1827 1091 L 1547 1036"/>
- <text x="1641" y="1167" style="font-size:73">2,29,0,0,0</text>
- <path class="p2" d="M 1916 917 L 1827 1091 L 2111 1148 L 2206 1026 L 1916 917"/>
- <text x="2014" y="1045" style="font-size:72">2,30,0,0,0</text>
- <line x1="2206" y1="1026" x2="2111" y2="1148"/>
- <path class="p2" d="M 1827 1091 L 1734 1274 L 2012 1274 L 2111 1148 L 1827 1091"/>
- <text x="1921" y="1196" style="font-size:75">2,31,0,0,0</text>
- <line x1="2111" y1="1148" x2="2012" y2="1274"/>
- <path class="p2" d="M 1456 1274 L 1442 1528 L 1762 1466 L 1734 1274 L 1456 1274"/>
- <text x="1599" y="1384" style="font-size:79">2,32,0,0,0</text>
- <path class="p2" d="M 1442 1528 L 1428 1800 L 1791 1668 L 1762 1466 L 1442 1528"/>
- <text x="1607" y="1614" style="font-size:84">2,33,0,0,0</text>
- <path class="p2" d="M 1734 1274 L 1762 1466 L 2076 1405 L 2012 1274 L 1734 1274"/>
- <text x="1896" y="1354" style="font-size:79">2,34,0,0,0</text>
- <line x1="2012" y1="1274" x2="2076" y2="1405"/>
- <path class="p2" d="M 1762 1466 L 1791 1668 L 2142 1540 L 2076 1405 L 1762 1466"/>
- <text x="1943" y="1519" style="font-size:83">2,35,0,0,0</text>
- <line x1="2076" y1="1405" x2="2142" y2="1540"/>
- <path class="p2" d="M 1428 1800 L 1413 2091 L 1822 1881 L 1791 1668 L 1428 1800"/>
- <text x="1615" y="1857" style="font-size:90">2,36,0,0,0</text>
- <path class="p2" d="M 1413 2091 L 1396 2404 L 1854 2105 L 1822 1881 L 1413 2091"/>
- <text x="1624" y="2116" style="font-size:96">2,37,0,0,0</text>
- <path class="p2" d="M 1791 1668 L 1822 1881 L 2211 1680 L 2142 1540 L 1791 1668"/>
- <text x="1993" y="1690" style="font-size:87">2,38,0,0,0</text>
- <line x1="2142" y1="1540" x2="2211" y2="1680"/>
- <path class="p2" d="M 1822 1881 L 1854 2105 L 2281 1825 L 2211 1680 L 1822 1881"/>
- <text x="2045" y="1870" style="font-size:92">2,39,0,0,0</text>
- <line x1="2211" y1="1680" x2="2281" y2="1825"/>
- <path class="p2" d="M 1396 2404 L 1823 2439 L 2166 2154 L 1854 2105 L 1396 2404"/>
- <text x="1813" y="2273" style="font-size:100">2,40,0,0,0</text>
- <path class="p2" d="M 1823 2439 L 2254 2474 L 2482 2204 L 2166 2154 L 1823 2439"/>
- <text x="2183" y="2315" style="font-size:102">2,41,0,0,0</text>
- <path class="p2" d="M 1854 2105 L 2166 2154 L 2488 1887 L 2281 1825 L 1854 2105"/>
- <text x="2200" y="1990" style="font-size:95">2,42,0,0,0</text>
- <line x1="2281" y1="1825" x2="2488" y2="1887"/>
- <path class="p2" d="M 2166 2154 L 2482 2204 L 2697 1950 L 2488 1887 L 2166 2154"/>
- <text x="2460" y="2046" style="font-size:97">2,43,0,0,0</text>
- <line x1="2488" y1="1887" x2="2697" y2="1950"/>
- <path class="p2" d="M 2254 2474 L 2688 2510 L 2802 2254 L 2482 2204 L 2254 2474"/>
- <text x="2557" y="2359" style="font-size:104">2,44,0,0,0</text>
- <path class="p2" d="M 2688 2510 L 3125 2546 L 3125 2306 L 2802 2254 L 2688 2510"/>
- <text x="2935" y="2402" style="font-size:106">2,45,0,0,0</text>
- <path class="p2" d="M 2482 2204 L 2802 2254 L 2909 2013 L 2697 1950 L 2482 2204"/>
- <text x="2723" y="2103" style="font-size:99">2,46,0,0,0</text>
- <line x1="2697" y1="1950" x2="2909" y2="2013"/>
- <path class="p2" d="M 2802 2254 L 3125 2306 L 3125 2078 L 2909 2013 L 2802 2254"/>
- <text x="2990" y="2161" style="font-size:100">2,47,0,0,0</text>
- <line x1="2909" y1="2013" x2="3125" y2="2078"/>
- <path class="p2" d="M 3125 2546 L 3562 2510 L 3448 2254 L 3125 2306 L 3125 2546"/>
- <text x="3315" y="2402" style="font-size:106">2,48,0,0,0</text>
- <path class="p2" d="M 3562 2510 L 3996 2474 L 3768 2204 L 3448 2254 L 3562 2510"/>
- <text x="3693" y="2359" style="font-size:104">2,49,0,0,0</text>
- <path class="p2" d="M 3125 2306 L 3448 2254 L 3341 2013 L 3125 2078 L 3125 2306"/>
- <text x="3260" y="2161" style="font-size:100">2,50,0,0,0</text>
- <line x1="3125" y1="2078" x2="3341" y2="2013"/>
- <path class="p2" d="M 3448 2254 L 3768 2204 L 3553 1950 L 3341 2013 L 3448 2254"/>
- <text x="3527" y="2103" style="font-size:99">2,51,0,0,0</text>
- <line x1="3341" y1="2013" x2="3553" y2="1950"/>
- <path class="p2" d="M 3996 2474 L 4427 2439 L 4084 2154 L 3768 2204 L 3996 2474"/>
- <text x="4067" y="2315" style="font-size:102">2,52,0,0,0</text>
- <path class="p2" d="M 4427 2439 L 4854 2404 L 4396 2105 L 4084 2154 L 4427 2439"/>
- <text x="4437" y="2273" style="font-size:100">2,53,0,0,0</text>
- <path class="p2" d="M 3768 2204 L 4084 2154 L 3762 1887 L 3553 1950 L 3768 2204"/>
- <text x="3790" y="2046" style="font-size:97">2,54,0,0,0</text>
- <line x1="3553" y1="1950" x2="3762" y2="1887"/>
- <path class="p2" d="M 4084 2154 L 4396 2105 L 3969 1825 L 3762 1887 L 4084 2154"/>
- <text x="4050" y="1990" style="font-size:95">2,55,0,0,0</text>
- <line x1="3762" y1="1887" x2="3969" y2="1825"/>
- <path class="p2" d="M 4854 2404 L 4837 2091 L 4428 1881 L 4396 2105 L 4854 2404"/>
- <text x="4626" y="2116" style="font-size:96">2,56,0,0,0</text>
- <path class="p2" d="M 4837 2091 L 4822 1800 L 4459 1668 L 4428 1881 L 4837 2091"/>
- <text x="4635" y="1857" style="font-size:90">2,57,0,0,0</text>
- <path class="p2" d="M 4396 2105 L 4428 1881 L 4039 1680 L 3969 1825 L 4396 2105"/>
- <text x="4205" y="1870" style="font-size:92">2,58,0,0,0</text>
- <line x1="3969" y1="1825" x2="4039" y2="1680"/>
- <path class="p2" d="M 4428 1881 L 4459 1668 L 4108 1540 L 4039 1680 L 4428 1881"/>
- <text x="4257" y="1690" style="font-size:87">2,59,0,0,0</text>
- <line x1="4039" y1="1680" x2="4108" y2="1540"/>
- <path class="p2" d="M 4822 1800 L 4808 1528 L 4488 1466 L 4459 1668 L 4822 1800"/>
- <text x="4643" y="1614" style="font-size:84">2,60,0,0,0</text>
- <path class="p2" d="M 4808 1528 L 4794 1274 L 4516 1274 L 4488 1466 L 4808 1528"/>
- <text x="4651" y="1384" style="font-size:79">2,61,0,0,0</text>
- <path class="p2" d="M 4459 1668 L 4488 1466 L 4174 1405 L 4108 1540 L 4459 1668"/>
- <text x="4307" y="1519" style="font-size:83">2,62,0,0,0</text>
- <line x1="4108" y1="1540" x2="4174" y2="1405"/>
- <path class="p2" d="M 4488 1466 L 4516 1274 L 4238 1274 L 4174 1405 L 4488 1466"/>
- <text x="4354" y="1354" style="font-size:79">2,63,0,0,0</text>
- <line x1="4174" y1="1405" x2="4238" y2="1274"/>
+ <path class="ps0" d="M 1616 716 L 1506 462 L 1202 614 L 1308 716 L 1616 716"/>
+ <text x="1410" y="618" style="font-size:64">0,0,0,X,0</text>
+ <line x1="1616" y1="716" x2="1506" y2="462"/>
+ <line x1="1308" y1="716" x2="1202" y2="614"/>
+ <path class="ps0" d="M 1506 462 L 1000 462 L 1000 577 L 1202 614 L 1506 462"/>
+ <text x="1181" y="525" style="font-size:54">0,1,0,X,0</text>
+ <line x1="1506" y1="462" x2="1000" y2="462"/>
+ <line x1="1202" y1="614" x2="1000" y2="577"/>
+ <path class="ps0" d="M 1000 462 L 494 462 L 798 614 L 1000 577 L 1000 462"/>
+ <text x="819" y="525" style="font-size:54">0,2,0,X,0</text>
+ <line x1="1000" y1="462" x2="494" y2="462"/>
+ <line x1="1000" y1="577" x2="798" y2="614"/>
+ <path class="ps0" d="M 494 462 L 384 716 L 692 716 L 798 614 L 494 462"/>
+ <text x="590" y="618" style="font-size:64">0,3,0,X,0</text>
+ <line x1="494" y1="462" x2="384" y2="716"/>
+ <line x1="798" y1="614" x2="692" y2="716"/>
+ <path class="ps0" d="M 384 716 L 214 1109 L 764 833 L 692 716 L 384 716"/>
+ <text x="526" y="828" style="font-size:91">0,4,0,X,0</text>
+ <line x1="384" y1="716" x2="214" y2="1109"/>
+ <line x1="692" y1="716" x2="764" y2="833"/>
+ <path class="ps0" d="M 214 1109 L 1000 1109 L 1000 888 L 764 833 L 214 1109"/>
+ <text x="753" y="975" style="font-size:113">0,5,0,X,0</text>
+ <line x1="214" y1="1109" x2="1000" y2="1109"/>
+ <line x1="764" y1="833" x2="1000" y2="888"/>
+ <path class="ps0" d="M 1000 1109 L 1786 1109 L 1236 833 L 1000 888 L 1000 1109"/>
+ <text x="1247" y="975" style="font-size:113">0,6,0,X,0</text>
+ <line x1="1000" y1="1109" x2="1786" y2="1109"/>
+ <line x1="1000" y1="888" x2="1236" y2="833"/>
+ <path class="ps0" d="M 1786 1109 L 1616 716 L 1308 716 L 1236 833 L 1786 1109"/>
+ <text x="1474" y="828" style="font-size:91">0,7,0,X,0</text>
+ <line x1="1786" y1="1109" x2="1616" y2="716"/>
+ <line x1="1236" y1="833" x2="1308" y2="716"/>
+ <path class="ps1" d="M 1632 606 L 1569 475 L 1419 514 L 1474 606 L 1632 606"/>
+ <text x="1523" y="548" style="font-size:35">1,0,0,X,0</text>
+ <line x1="1632" y1="606" x2="1569" y2="475"/>
+ <path class="ps1" d="M 1569 475 L 1517 367 L 1372 435 L 1419 514 L 1569 475"/>
+ <text x="1470" y="445" style="font-size:28">1,1,0,X,0</text>
+ <line x1="1569" y1="475" x2="1517" y2="367"/>
+ <path class="ps1" d="M 1474 606 L 1419 514 L 1260 556 L 1316 606 L 1474 606"/>
+ <text x="1367" y="570" style="font-size:38">1,2,0,X,0</text>
+ <line x1="1316" y1="606" x2="1260" y2="556"/>
+ <path class="ps1" d="M 1419 514 L 1372 435 L 1207 511 L 1260 556 L 1419 514"/>
+ <text x="1316" y="502" style="font-size:33">1,3,0,X,0</text>
+ <line x1="1260" y1="556" x2="1207" y2="511"/>
+ <path class="ps1" d="M 1517 367 L 1259 367 L 1185 427 L 1372 435 L 1517 367"/>
+ <text x="1334" y="398" style="font-size:26">1,4,0,X,0</text>
+ <line x1="1517" y1="367" x2="1259" y2="367"/>
+ <path class="ps1" d="M 1259 367 L 1000 367 L 1000 419 L 1185 427 L 1259 367"/>
+ <text x="1111" y="394" style="font-size:26">1,5,0,X,0</text>
+ <line x1="1259" y1="367" x2="1000" y2="367"/>
+ <path class="ps1" d="M 1372 435 L 1185 427 L 1102 492 L 1207 511 L 1372 435"/>
+ <text x="1218" y="465" style="font-size:31">1,6,0,X,0</text>
+ <line x1="1207" y1="511" x2="1102" y2="492"/>
+ <path class="ps1" d="M 1185 427 L 1000 419 L 1000 475 L 1102 492 L 1185 427"/>
+ <text x="1072" y="452" style="font-size:30">1,7,0,X,0</text>
+ <line x1="1102" y1="492" x2="1000" y2="475"/>
+ <path class="ps1" d="M 1000 367 L 741 367 L 815 427 L 1000 419 L 1000 367"/>
+ <text x="889" y="394" style="font-size:26">1,8,0,X,0</text>
+ <line x1="1000" y1="367" x2="741" y2="367"/>
+ <path class="ps1" d="M 741 367 L 483 367 L 628 435 L 815 427 L 741 367"/>
+ <text x="666" y="398" style="font-size:26">1,9,0,X,0</text>
+ <line x1="741" y1="367" x2="483" y2="367"/>
+ <path class="ps1" d="M 1000 419 L 815 427 L 898 492 L 1000 475 L 1000 419"/>
+ <text x="928" y="452" style="font-size:30">1,10,0,X,0</text>
+ <line x1="1000" y1="475" x2="898" y2="492"/>
+ <path class="ps1" d="M 815 427 L 628 435 L 793 511 L 898 492 L 815 427"/>
+ <text x="782" y="465" style="font-size:31">1,11,0,X,0</text>
+ <line x1="898" y1="492" x2="793" y2="511"/>
+ <path class="ps1" d="M 483 367 L 431 475 L 581 514 L 628 435 L 483 367"/>
+ <text x="530" y="445" style="font-size:28">1,12,0,X,0</text>
+ <line x1="483" y1="367" x2="431" y2="475"/>
+ <path class="ps1" d="M 431 475 L 368 606 L 526 606 L 581 514 L 431 475"/>
+ <text x="477" y="548" style="font-size:35">1,13,0,X,0</text>
+ <line x1="431" y1="475" x2="368" y2="606"/>
+ <path class="ps1" d="M 628 435 L 581 514 L 740 556 L 793 511 L 628 435"/>
+ <text x="684" y="502" style="font-size:33">1,14,0,X,0</text>
+ <line x1="793" y1="511" x2="740" y2="556"/>
+ <path class="ps1" d="M 581 514 L 526 606 L 684 606 L 740 556 L 581 514"/>
+ <text x="633" y="570" style="font-size:38">1,15,0,X,0</text>
+ <line x1="740" y1="556" x2="684" y2="606"/>
+ <path class="ps1" d="M 368 606 L 289 770 L 513 713 L 526 606 L 368 606"/>
+ <text x="426" y="670" style="font-size:44">1,16,0,X,0</text>
+ <line x1="368" y1="606" x2="289" y2="770"/>
+ <path class="ps1" d="M 289 770 L 188 981 L 497 838 L 513 713 L 289 770"/>
+ <text x="377" y="819" style="font-size:55">1,17,0,X,0</text>
+ <line x1="289" y1="770" x2="188" y2="981"/>
+ <path class="ps1" d="M 526 606 L 513 713 L 719 660 L 684 606 L 526 606"/>
+ <text x="611" y="645" style="font-size:44">1,18,0,X,0</text>
+ <line x1="684" y1="606" x2="719" y2="660"/>
+ <path class="ps1" d="M 513 713 L 497 838 L 758 718 L 719 660 L 513 713"/>
+ <text x="625" y="729" style="font-size:50">1,19,0,X,0</text>
+ <line x1="719" y1="660" x2="758" y2="718"/>
+ <path class="ps1" d="M 188 981 L 594 981 L 746 853 L 497 838 L 188 981"/>
+ <text x="511" y="911" style="font-size:63">1,20,0,X,0</text>
+ <line x1="188" y1="981" x2="594" y2="981"/>
+ <path class="ps1" d="M 594 981 L 1000 981 L 1000 868 L 746 853 L 594 981"/>
+ <text x="836" y="919" style="font-size:66">1,21,0,X,0</text>
+ <line x1="594" y1="981" x2="1000" y2="981"/>
+ <path class="ps1" d="M 497 838 L 746 853 L 877 744 L 758 718 L 497 838"/>
+ <text x="722" y="786" style="font-size:55">1,22,0,X,0</text>
+ <line x1="758" y1="718" x2="877" y2="744"/>
+ <path class="ps1" d="M 746 853 L 1000 868 L 1000 770 L 877 744 L 746 853"/>
+ <text x="906" y="807" style="font-size:57">1,23,0,X,0</text>
+ <line x1="877" y1="744" x2="1000" y2="770"/>
+ <path class="ps1" d="M 1000 981 L 1406 981 L 1254 853 L 1000 868 L 1000 981"/>
+ <text x="1164" y="919" style="font-size:66">1,24,0,X,0</text>
+ <line x1="1000" y1="981" x2="1406" y2="981"/>
+ <path class="ps1" d="M 1406 981 L 1812 981 L 1503 838 L 1254 853 L 1406 981"/>
+ <text x="1489" y="911" style="font-size:63">1,25,0,X,0</text>
+ <line x1="1406" y1="981" x2="1812" y2="981"/>
+ <path class="ps1" d="M 1000 868 L 1254 853 L 1123 744 L 1000 770 L 1000 868"/>
+ <text x="1094" y="807" style="font-size:57">1,26,0,X,0</text>
+ <line x1="1000" y1="770" x2="1123" y2="744"/>
+ <path class="ps1" d="M 1254 853 L 1503 838 L 1242 718 L 1123 744 L 1254 853"/>
+ <text x="1278" y="786" style="font-size:55">1,27,0,X,0</text>
+ <line x1="1123" y1="744" x2="1242" y2="718"/>
+ <path class="ps1" d="M 1812 981 L 1711 770 L 1487 713 L 1503 838 L 1812 981"/>
+ <text x="1623" y="819" style="font-size:55">1,28,0,X,0</text>
+ <line x1="1812" y1="981" x2="1711" y2="770"/>
+ <path class="ps1" d="M 1711 770 L 1632 606 L 1474 606 L 1487 713 L 1711 770"/>
+ <text x="1574" y="670" style="font-size:44">1,29,0,X,0</text>
+ <line x1="1711" y1="770" x2="1632" y2="606"/>
+ <path class="ps1" d="M 1503 838 L 1487 713 L 1281 660 L 1242 718 L 1503 838"/>
+ <text x="1375" y="729" style="font-size:50">1,30,0,X,0</text>
+ <line x1="1242" y1="718" x2="1281" y2="660"/>
+ <path class="ps1" d="M 1487 713 L 1474 606 L 1316 606 L 1281 660 L 1487 713"/>
+ <text x="1389" y="645" style="font-size:44">1,31,0,X,0</text>
+ <line x1="1281" y1="660" x2="1316" y2="606"/>
+ <path class="ps2" d="M 1486 491 L 1457 446 L 1376 457 L 1405 491 L 1486 491"/>
+ <text x="1431" y="471" style="font-size:21">2,0,0,X,0</text>
+ <path class="ps2" d="M 1457 446 L 1430 405 L 1349 424 L 1376 457 L 1457 446"/>
+ <text x="1403" y="433" style="font-size:19">2,1,0,X,0</text>
+ <path class="ps2" d="M 1405 491 L 1376 457 L 1295 467 L 1324 491 L 1405 491"/>
+ <text x="1350" y="476" style="font-size:21">2,2,0,X,0</text>
+ <line x1="1324" y1="491" x2="1295" y2="467"/>
+ <path class="ps2" d="M 1376 457 L 1349 424 L 1266 445 L 1295 467 L 1376 457"/>
+ <text x="1322" y="448" style="font-size:20">2,3,0,X,0</text>
+ <line x1="1295" y1="467" x2="1266" y2="445"/>
+ <path class="ps2" d="M 1430 405 L 1404 367 L 1323 394 L 1349 424 L 1430 405"/>
+ <text x="1377" y="397" style="font-size:17">2,4,0,X,0</text>
+ <path class="ps2" d="M 1404 367 L 1380 331 L 1299 365 L 1323 394 L 1404 367"/>
+ <text x="1352" y="364" style="font-size:16">2,5,0,X,0</text>
+ <path class="ps2" d="M 1349 424 L 1323 394 L 1239 423 L 1266 445 L 1349 424"/>
+ <text x="1295" y="421" style="font-size:19">2,6,0,X,0</text>
+ <line x1="1266" y1="445" x2="1239" y2="423"/>
+ <path class="ps2" d="M 1323 394 L 1299 365 L 1212 402 L 1239 423 L 1323 394"/>
+ <text x="1269" y="395" style="font-size:18">2,7,0,X,0</text>
+ <line x1="1239" y1="423" x2="1212" y2="402"/>
+ <path class="ps2" d="M 1380 331 L 1284 327 L 1223 359 L 1299 365 L 1380 331"/>
+ <text x="1297" y="345" style="font-size:15">2,8,0,X,0</text>
+ <path class="ps2" d="M 1284 327 L 1189 323 L 1148 353 L 1223 359 L 1284 327"/>
+ <text x="1211" y="340" style="font-size:15">2,9,0,X,0</text>
+ <path class="ps2" d="M 1299 365 L 1223 359 L 1158 393 L 1212 402 L 1299 365"/>
+ <text x="1224" y="379" style="font-size:17">2,10,0,X,0</text>
+ <line x1="1212" y1="402" x2="1158" y2="393"/>
+ <path class="ps2" d="M 1223 359 L 1148 353 L 1104 385 L 1158 393 L 1223 359"/>
+ <text x="1159" y="372" style="font-size:17">2,11,0,X,0</text>
+ <line x1="1158" y1="393" x2="1104" y2="385"/>
+ <path class="ps2" d="M 1189 323 L 1094 320 L 1074 347 L 1148 353 L 1189 323"/>
+ <text x="1126" y="336" style="font-size:15">2,12,0,X,0</text>
+ <path class="ps2" d="M 1094 320 L 1000 316 L 1000 342 L 1074 347 L 1094 320"/>
+ <text x="1042" y="331" style="font-size:15">2,13,0,X,0</text>
+ <path class="ps2" d="M 1148 353 L 1074 347 L 1052 376 L 1104 385 L 1148 353"/>
+ <text x="1095" y="365" style="font-size:17">2,14,0,X,0</text>
+ <line x1="1104" y1="385" x2="1052" y2="376"/>
+ <path class="ps2" d="M 1074 347 L 1000 342 L 1000 368 L 1052 376 L 1074 347"/>
+ <text x="1031" y="358" style="font-size:16">2,15,0,X,0</text>
+ <line x1="1052" y1="376" x2="1000" y2="368"/>
+ <path class="ps2" d="M 1000 316 L 906 320 L 926 347 L 1000 342 L 1000 316"/>
+ <text x="958" y="331" style="font-size:15">2,16,0,X,0</text>
+ <path class="ps2" d="M 906 320 L 811 323 L 852 353 L 926 347 L 906 320"/>
+ <text x="874" y="336" style="font-size:15">2,17,0,X,0</text>
+ <path class="ps2" d="M 1000 342 L 926 347 L 948 376 L 1000 368 L 1000 342"/>
+ <text x="969" y="358" style="font-size:16">2,18,0,X,0</text>
+ <line x1="1000" y1="368" x2="948" y2="376"/>
+ <path class="ps2" d="M 926 347 L 852 353 L 896 385 L 948 376 L 926 347"/>
+ <text x="905" y="365" style="font-size:17">2,19,0,X,0</text>
+ <line x1="948" y1="376" x2="896" y2="385"/>
+ <path class="ps2" d="M 811 323 L 716 327 L 777 359 L 852 353 L 811 323"/>
+ <text x="789" y="340" style="font-size:15">2,20,0,X,0</text>
+ <path class="ps2" d="M 716 327 L 620 331 L 701 365 L 777 359 L 716 327"/>
+ <text x="703" y="345" style="font-size:15">2,21,0,X,0</text>
+ <path class="ps2" d="M 852 353 L 777 359 L 842 393 L 896 385 L 852 353"/>
+ <text x="841" y="372" style="font-size:17">2,22,0,X,0</text>
+ <line x1="896" y1="385" x2="842" y2="393"/>
+ <path class="ps2" d="M 777 359 L 701 365 L 788 402 L 842 393 L 777 359"/>
+ <text x="776" y="379" style="font-size:17">2,23,0,X,0</text>
+ <line x1="842" y1="393" x2="788" y2="402"/>
+ <path class="ps2" d="M 620 331 L 596 367 L 677 394 L 701 365 L 620 331"/>
+ <text x="648" y="364" style="font-size:16">2,24,0,X,0</text>
+ <path class="ps2" d="M 596 367 L 570 405 L 651 424 L 677 394 L 596 367"/>
+ <text x="623" y="397" style="font-size:17">2,25,0,X,0</text>
+ <path class="ps2" d="M 701 365 L 677 394 L 761 423 L 788 402 L 701 365"/>
+ <text x="731" y="395" style="font-size:18">2,26,0,X,0</text>
+ <line x1="788" y1="402" x2="761" y2="423"/>
+ <path class="ps2" d="M 677 394 L 651 424 L 734 445 L 761 423 L 677 394"/>
+ <text x="705" y="421" style="font-size:19">2,27,0,X,0</text>
+ <line x1="761" y1="423" x2="734" y2="445"/>
+ <path class="ps2" d="M 570 405 L 543 446 L 624 457 L 651 424 L 570 405"/>
+ <text x="597" y="433" style="font-size:19">2,28,0,X,0</text>
+ <path class="ps2" d="M 543 446 L 514 491 L 595 491 L 624 457 L 543 446"/>
+ <text x="569" y="471" style="font-size:21">2,29,0,X,0</text>
+ <path class="ps2" d="M 651 424 L 624 457 L 705 467 L 734 445 L 651 424"/>
+ <text x="678" y="448" style="font-size:20">2,30,0,X,0</text>
+ <line x1="734" y1="445" x2="705" y2="467"/>
+ <path class="ps2" d="M 624 457 L 595 491 L 676 491 L 705 467 L 624 457"/>
+ <text x="650" y="476" style="font-size:21">2,31,0,X,0</text>
+ <line x1="705" y1="467" x2="676" y2="491"/>
+ <path class="ps2" d="M 514 491 L 506 539 L 601 527 L 595 491 L 514 491"/>
+ <text x="554" y="512" style="font-size:22">2,32,0,X,0</text>
+ <path class="ps2" d="M 506 539 L 499 591 L 607 566 L 601 527 L 506 539"/>
+ <text x="554" y="555" style="font-size:24">2,33,0,X,0</text>
+ <path class="ps2" d="M 595 491 L 601 527 L 693 516 L 676 491 L 595 491"/>
+ <text x="641" y="506" style="font-size:22">2,34,0,X,0</text>
+ <line x1="676" y1="491" x2="693" y2="516"/>
+ <path class="ps2" d="M 601 527 L 607 566 L 712 541 L 693 516 L 601 527"/>
+ <text x="653" y="537" style="font-size:24">2,35,0,X,0</text>
+ <line x1="693" y1="516" x2="712" y2="541"/>
+ <path class="ps2" d="M 499 591 L 490 648 L 614 607 L 607 566 L 499 591"/>
+ <text x="553" y="602" style="font-size:26">2,36,0,X,0</text>
+ <path class="ps2" d="M 490 648 L 481 709 L 621 650 L 614 607 L 490 648"/>
+ <text x="553" y="652" style="font-size:28">2,37,0,X,0</text>
+ <path class="ps2" d="M 607 566 L 614 607 L 731 568 L 712 541 L 607 566"/>
+ <text x="666" y="570" style="font-size:25">2,38,0,X,0</text>
+ <line x1="712" y1="541" x2="731" y2="568"/>
+ <path class="ps2" d="M 614 607 L 621 650 L 751 596 L 731 568 L 614 607"/>
+ <text x="680" y="605" style="font-size:27">2,39,0,X,0</text>
+ <line x1="731" y1="568" x2="751" y2="596"/>
+ <path class="ps2" d="M 481 709 L 609 716 L 714 660 L 621 650 L 481 709"/>
+ <text x="607" y="683" style="font-size:30">2,40,0,X,0</text>
+ <path class="ps2" d="M 609 716 L 738 723 L 808 670 L 714 660 L 609 716"/>
+ <text x="718" y="692" style="font-size:31">2,41,0,X,0</text>
+ <path class="ps2" d="M 621 650 L 714 660 L 811 608 L 751 596 L 621 650"/>
+ <text x="725" y="628" style="font-size:28">2,42,0,X,0</text>
+ <line x1="751" y1="596" x2="811" y2="608"/>
+ <path class="ps2" d="M 714 660 L 808 670 L 873 620 L 811 608 L 714 660"/>
+ <text x="802" y="639" style="font-size:29">2,43,0,X,0</text>
+ <line x1="811" y1="608" x2="873" y2="620"/>
+ <path class="ps2" d="M 738 723 L 868 731 L 903 680 L 808 670 L 738 723"/>
+ <text x="830" y="700" style="font-size:31">2,44,0,X,0</text>
+ <path class="ps2" d="M 868 731 L 1000 738 L 1000 690 L 903 680 L 868 731"/>
+ <text x="943" y="709" style="font-size:32">2,45,0,X,0</text>
+ <path class="ps2" d="M 808 670 L 903 680 L 936 632 L 873 620 L 808 670"/>
+ <text x="880" y="650" style="font-size:29">2,46,0,X,0</text>
+ <line x1="873" y1="620" x2="936" y2="632"/>
+ <path class="ps2" d="M 903 680 L 1000 690 L 1000 645 L 936 632 L 903 680"/>
+ <text x="960" y="661" style="font-size:30">2,47,0,X,0</text>
+ <line x1="936" y1="632" x2="1000" y2="645"/>
+ <path class="ps2" d="M 1000 738 L 1132 731 L 1097 680 L 1000 690 L 1000 738"/>
+ <text x="1057" y="709" style="font-size:32">2,48,0,X,0</text>
+ <path class="ps2" d="M 1132 731 L 1262 723 L 1192 670 L 1097 680 L 1132 731"/>
+ <text x="1170" y="700" style="font-size:31">2,49,0,X,0</text>
+ <path class="ps2" d="M 1000 690 L 1097 680 L 1064 632 L 1000 645 L 1000 690"/>
+ <text x="1040" y="661" style="font-size:30">2,50,0,X,0</text>
+ <line x1="1000" y1="645" x2="1064" y2="632"/>
+ <path class="ps2" d="M 1097 680 L 1192 670 L 1127 620 L 1064 632 L 1097 680"/>
+ <text x="1120" y="650" style="font-size:29">2,51,0,X,0</text>
+ <line x1="1064" y1="632" x2="1127" y2="620"/>
+ <path class="ps2" d="M 1262 723 L 1391 716 L 1286 660 L 1192 670 L 1262 723"/>
+ <text x="1282" y="692" style="font-size:31">2,52,0,X,0</text>
+ <path class="ps2" d="M 1391 716 L 1519 709 L 1379 650 L 1286 660 L 1391 716"/>
+ <text x="1393" y="683" style="font-size:30">2,53,0,X,0</text>
+ <path class="ps2" d="M 1192 670 L 1286 660 L 1189 608 L 1127 620 L 1192 670"/>
+ <text x="1198" y="639" style="font-size:29">2,54,0,X,0</text>
+ <line x1="1127" y1="620" x2="1189" y2="608"/>
+ <path class="ps2" d="M 1286 660 L 1379 650 L 1249 596 L 1189 608 L 1286 660"/>
+ <text x="1275" y="628" style="font-size:28">2,55,0,X,0</text>
+ <line x1="1189" y1="608" x2="1249" y2="596"/>
+ <path class="ps2" d="M 1519 709 L 1510 648 L 1386 607 L 1379 650 L 1519 709"/>
+ <text x="1447" y="652" style="font-size:28">2,56,0,X,0</text>
+ <path class="ps2" d="M 1510 648 L 1501 591 L 1393 566 L 1386 607 L 1510 648"/>
+ <text x="1447" y="602" style="font-size:26">2,57,0,X,0</text>
+ <path class="ps2" d="M 1379 650 L 1386 607 L 1269 568 L 1249 596 L 1379 650"/>
+ <text x="1320" y="605" style="font-size:27">2,58,0,X,0</text>
+ <line x1="1249" y1="596" x2="1269" y2="568"/>
+ <path class="ps2" d="M 1386 607 L 1393 566 L 1288 541 L 1269 568 L 1386 607"/>
+ <text x="1334" y="570" style="font-size:25">2,59,0,X,0</text>
+ <line x1="1269" y1="568" x2="1288" y2="541"/>
+ <path class="ps2" d="M 1501 591 L 1494 539 L 1399 527 L 1393 566 L 1501 591"/>
+ <text x="1446" y="555" style="font-size:24">2,60,0,X,0</text>
+ <path class="ps2" d="M 1494 539 L 1486 491 L 1405 491 L 1399 527 L 1494 539"/>
+ <text x="1446" y="512" style="font-size:22">2,61,0,X,0</text>
+ <path class="ps2" d="M 1393 566 L 1399 527 L 1307 516 L 1288 541 L 1393 566"/>
+ <text x="1347" y="537" style="font-size:24">2,62,0,X,0</text>
+ <line x1="1288" y1="541" x2="1307" y2="516"/>
+ <path class="ps2" d="M 1399 527 L 1405 491 L 1324 491 L 1307 516 L 1399 527"/>
+ <text x="1359" y="506" style="font-size:22">2,63,0,X,0</text>
+ <line x1="1307" y1="516" x2="1324" y2="491"/>
+ <path class="p2" d="M 1649 491 L 1614 426 L 1536 436 L 1567 491 L 1649 491"/>
+ <text x="1591" y="460" style="font-size:19">2,64,0,0,0</text>
+ <line x1="1649" y1="491" x2="1614" y2="426"/>
+ <path class="p2" d="M 1614 426 L 1582 368 L 1507 386 L 1536 436 L 1614 426"/>
+ <text x="1560" y="404" style="font-size:17">2,65,0,0,0</text>
+ <line x1="1614" y1="426" x2="1582" y2="368"/>
+ <path class="ps2" d="M 1567 491 L 1536 436 L 1457 446 L 1486 491 L 1567 491"/>
+ <text x="1511" y="466" style="font-size:20">2,66,0,X,0</text>
+ <path class="ps2" d="M 1536 436 L 1507 386 L 1430 405 L 1457 446 L 1536 436"/>
+ <text x="1482" y="418" style="font-size:18">2,67,0,X,0</text>
+ <path class="p2" d="M 1582 368 L 1554 316 L 1481 341 L 1507 386 L 1582 368"/>
+ <text x="1531" y="352" style="font-size:15">2,68,0,0,0</text>
+ <line x1="1582" y1="368" x2="1554" y2="316"/>
+ <path class="p2" d="M 1554 316 L 1528 269 L 1457 299 L 1481 341 L 1554 316"/>
+ <text x="1505" y="305" style="font-size:13">2,69,0,0,0</text>
+ <line x1="1554" y1="316" x2="1528" y2="269"/>
+ <path class="ps2" d="M 1507 386 L 1481 341 L 1404 367 L 1430 405 L 1507 386"/>
+ <text x="1456" y="374" style="font-size:16">2,70,0,X,0</text>
+ <path class="p2" d="M 1481 341 L 1457 299 L 1380 331 L 1404 367 L 1481 341"/>
+ <text x="1431" y="334" style="font-size:15">2,71,0,0,0</text>
+ <path class="p2" d="M 1528 269 L 1396 269 L 1342 297 L 1457 299 L 1528 269"/>
+ <text x="1431" y="283" style="font-size:13">2,72,0,0,0</text>
+ <line x1="1528" y1="269" x2="1396" y2="269"/>
+ <path class="p2" d="M 1396 269 L 1264 269 L 1227 295 L 1342 297 L 1396 269"/>
+ <text x="1308" y="282" style="font-size:13">2,73,0,0,0</text>
+ <line x1="1396" y1="269" x2="1264" y2="269"/>
+ <path class="p2" d="M 1457 299 L 1342 297 L 1284 327 L 1380 331 L 1457 299"/>
+ <text x="1366" y="313" style="font-size:14">2,74,0,0,0</text>
+ <path class="ps2" d="M 1342 297 L 1227 295 L 1189 323 L 1284 327 L 1342 297"/>
+ <text x="1261" y="310" style="font-size:14">2,75,0,X,0</text>
+ <path class="p2" d="M 1264 269 L 1132 269 L 1114 293 L 1227 295 L 1264 269"/>
+ <text x="1184" y="281" style="font-size:13">2,76,0,0,0</text>
+ <line x1="1264" y1="269" x2="1132" y2="269"/>
+ <path class="p2" d="M 1132 269 L 1000 269 L 1000 292 L 1114 293 L 1132 269"/>
+ <text x="1061" y="280" style="font-size:13">2,77,0,0,0</text>
+ <line x1="1132" y1="269" x2="1000" y2="269"/>
+ <path class="ps2" d="M 1227 295 L 1114 293 L 1094 320 L 1189 323 L 1227 295"/>
+ <text x="1156" y="308" style="font-size:14">2,78,0,X,0</text>
+ <path class="ps2" d="M 1114 293 L 1000 292 L 1000 316 L 1094 320 L 1114 293"/>
+ <text x="1052" y="305" style="font-size:14">2,79,0,X,0</text>
+ <path class="p2" d="M 1000 269 L 868 269 L 886 293 L 1000 292 L 1000 269"/>
+ <text x="939" y="280" style="font-size:13">2,80,0,0,0</text>
+ <line x1="1000" y1="269" x2="868" y2="269"/>
+ <path class="p2" d="M 868 269 L 736 269 L 773 295 L 886 293 L 868 269"/>
+ <text x="816" y="281" style="font-size:13">2,81,0,0,0</text>
+ <line x1="868" y1="269" x2="736" y2="269"/>
+ <path class="ps2" d="M 1000 292 L 886 293 L 906 320 L 1000 316 L 1000 292"/>
+ <text x="948" y="305" style="font-size:14">2,82,0,X,0</text>
+ <path class="ps2" d="M 886 293 L 773 295 L 811 323 L 906 320 L 886 293"/>
+ <text x="844" y="308" style="font-size:14">2,83,0,X,0</text>
+ <path class="p2" d="M 736 269 L 604 269 L 658 297 L 773 295 L 736 269"/>
+ <text x="692" y="282" style="font-size:13">2,84,0,0,0</text>
+ <line x1="736" y1="269" x2="604" y2="269"/>
+ <path class="p2" d="M 604 269 L 472 269 L 543 299 L 658 297 L 604 269"/>
+ <text x="569" y="283" style="font-size:13">2,85,0,0,0</text>
+ <line x1="604" y1="269" x2="472" y2="269"/>
+ <path class="ps2" d="M 773 295 L 658 297 L 716 327 L 811 323 L 773 295"/>
+ <text x="739" y="310" style="font-size:14">2,86,0,X,0</text>
+ <path class="p2" d="M 658 297 L 543 299 L 620 331 L 716 327 L 658 297"/>
+ <text x="634" y="313" style="font-size:14">2,87,0,0,0</text>
+ <path class="p2" d="M 472 269 L 446 316 L 519 341 L 543 299 L 472 269"/>
+ <text x="495" y="305" style="font-size:13">2,88,0,0,0</text>
+ <line x1="472" y1="269" x2="446" y2="316"/>
+ <path class="p2" d="M 446 316 L 418 368 L 493 386 L 519 341 L 446 316"/>
+ <text x="469" y="352" style="font-size:15">2,89,0,0,0</text>
+ <line x1="446" y1="316" x2="418" y2="368"/>
+ <path class="p2" d="M 543 299 L 519 341 L 596 367 L 620 331 L 543 299"/>
+ <text x="569" y="334" style="font-size:15">2,90,0,0,0</text>
+ <path class="ps2" d="M 519 341 L 493 386 L 570 405 L 596 367 L 519 341"/>
+ <text x="544" y="374" style="font-size:16">2,91,0,X,0</text>
+ <path class="p2" d="M 418 368 L 386 426 L 464 436 L 493 386 L 418 368"/>
+ <text x="440" y="404" style="font-size:17">2,92,0,0,0</text>
+ <line x1="418" y1="368" x2="386" y2="426"/>
+ <path class="p2" d="M 386 426 L 351 491 L 433 491 L 464 436 L 386 426"/>
+ <text x="409" y="460" style="font-size:19">2,93,0,0,0</text>
+ <line x1="386" y1="426" x2="351" y2="491"/>
+ <path class="ps2" d="M 493 386 L 464 436 L 543 446 L 570 405 L 493 386"/>
+ <text x="518" y="418" style="font-size:18">2,94,0,X,0</text>
+ <path class="ps2" d="M 464 436 L 433 491 L 514 491 L 543 446 L 464 436"/>
+ <text x="489" y="466" style="font-size:20">2,95,0,X,0</text>
+ <path class="p2" d="M 351 491 L 312 563 L 410 551 L 433 491 L 351 491"/>
+ <text x="377" y="523" style="font-size:22">2,96,0,0,0</text>
+ <line x1="351" y1="491" x2="312" y2="563"/>
+ <path class="p2" d="M 312 563 L 268 645 L 386 617 L 410 551 L 312 563"/>
+ <text x="345" y="593" style="font-size:25">2,97,0,0,0</text>
+ <line x1="312" y1="563" x2="268" y2="645"/>
+ <path class="ps2" d="M 433 491 L 410 551 L 506 539 L 514 491 L 433 491"/>
+ <text x="466" y="517" style="font-size:22">2,98,0,X,0</text>
+ <path class="ps2" d="M 410 551 L 386 617 L 499 591 L 506 539 L 410 551"/>
+ <text x="451" y="574" style="font-size:25">2,99,0,X,0</text>
+ <path class="p2" d="M 268 645 L 218 738 L 358 691 L 386 617 L 268 645"/>
+ <text x="309" y="671" style="font-size:28">2,100,0,0,0</text>
+ <line x1="268" y1="645" x2="218" y2="738"/>
+ <path class="p2" d="M 218 738 L 160 844 L 328 774 L 358 691 L 218 738"/>
+ <text x="268" y="760" style="font-size:31">2,101,0,0,0</text>
+ <line x1="218" y1="738" x2="160" y2="844"/>
+ <path class="ps2" d="M 386 617 L 358 691 L 490 648 L 499 591 L 386 617"/>
+ <text x="434" y="636" style="font-size:27">2,102,0,X,0</text>
+ <path class="p2" d="M 358 691 L 328 774 L 481 709 L 490 648 L 358 691"/>
+ <text x="416" y="704" style="font-size:30">2,103,0,0,0</text>
+ <path class="p2" d="M 160 844 L 370 844 L 495 778 L 328 774 L 160 844"/>
+ <text x="340" y="809" style="font-size:34">2,104,0,0,0</text>
+ <line x1="160" y1="844" x2="370" y2="844"/>
+ <path class="p2" d="M 370 844 L 580 844 L 662 782 L 495 778 L 370 844"/>
+ <text x="528" y="811" style="font-size:35">2,105,0,0,0</text>
+ <line x1="370" y1="844" x2="580" y2="844"/>
+ <path class="p2" d="M 328 774 L 495 778 L 609 716 L 481 709 L 328 774"/>
+ <text x="479" y="744" style="font-size:32">2,106,0,0,0</text>
+ <path class="ps2" d="M 495 778 L 662 782 L 738 723 L 609 716 L 495 778"/>
+ <text x="627" y="749" style="font-size:33">2,107,0,X,0</text>
+ <path class="p2" d="M 580 844 L 790 844 L 831 785 L 662 782 L 580 844"/>
+ <text x="716" y="813" style="font-size:36">2,108,0,0,0</text>
+ <line x1="580" y1="844" x2="790" y2="844"/>
+ <path class="p2" d="M 790 844 L 1000 844 L 1000 789 L 831 785 L 790 844"/>
+ <text x="905" y="815" style="font-size:36">2,109,0,0,0</text>
+ <line x1="790" y1="844" x2="1000" y2="844"/>
+ <path class="ps2" d="M 662 782 L 831 785 L 868 731 L 738 723 L 662 782"/>
+ <text x="775" y="755" style="font-size:34">2,110,0,X,0</text>
+ <path class="ps2" d="M 831 785 L 1000 789 L 1000 738 L 868 731 L 831 785"/>
+ <text x="925" y="760" style="font-size:34">2,111,0,X,0</text>
+ <path class="p2" d="M 1000 844 L 1210 844 L 1169 785 L 1000 789 L 1000 844"/>
+ <text x="1095" y="815" style="font-size:36">2,112,0,0,0</text>
+ <line x1="1000" y1="844" x2="1210" y2="844"/>
+ <path class="p2" d="M 1210 844 L 1420 844 L 1338 782 L 1169 785 L 1210 844"/>
+ <text x="1284" y="813" style="font-size:36">2,113,0,0,0</text>
+ <line x1="1210" y1="844" x2="1420" y2="844"/>
+ <path class="ps2" d="M 1000 789 L 1169 785 L 1132 731 L 1000 738 L 1000 789"/>
+ <text x="1075" y="760" style="font-size:34">2,114,0,X,0</text>
+ <path class="ps2" d="M 1169 785 L 1338 782 L 1262 723 L 1132 731 L 1169 785"/>
+ <text x="1225" y="755" style="font-size:34">2,115,0,X,0</text>
+ <path class="p2" d="M 1420 844 L 1630 844 L 1505 778 L 1338 782 L 1420 844"/>
+ <text x="1472" y="811" style="font-size:35">2,116,0,0,0</text>
+ <line x1="1420" y1="844" x2="1630" y2="844"/>
+ <path class="p2" d="M 1630 844 L 1840 844 L 1672 774 L 1505 778 L 1630 844"/>
+ <text x="1660" y="809" style="font-size:34">2,117,0,0,0</text>
+ <line x1="1630" y1="844" x2="1840" y2="844"/>
+ <path class="ps2" d="M 1338 782 L 1505 778 L 1391 716 L 1262 723 L 1338 782"/>
+ <text x="1373" y="749" style="font-size:33">2,118,0,X,0</text>
+ <path class="p2" d="M 1505 778 L 1672 774 L 1519 709 L 1391 716 L 1505 778"/>
+ <text x="1521" y="744" style="font-size:32">2,119,0,0,0</text>
+ <path class="p2" d="M 1840 844 L 1782 738 L 1642 691 L 1672 774 L 1840 844"/>
+ <text x="1732" y="760" style="font-size:31">2,120,0,0,0</text>
+ <line x1="1840" y1="844" x2="1782" y2="738"/>
+ <path class="p2" d="M 1782 738 L 1732 645 L 1614 617 L 1642 691 L 1782 738"/>
+ <text x="1691" y="671" style="font-size:28">2,121,0,0,0</text>
+ <line x1="1782" y1="738" x2="1732" y2="645"/>
+ <path class="p2" d="M 1672 774 L 1642 691 L 1510 648 L 1519 709 L 1672 774"/>
+ <text x="1584" y="704" style="font-size:30">2,122,0,0,0</text>
+ <path class="ps2" d="M 1642 691 L 1614 617 L 1501 591 L 1510 648 L 1642 691"/>
+ <text x="1566" y="636" style="font-size:27">2,123,0,X,0</text>
+ <path class="p2" d="M 1732 645 L 1688 563 L 1590 551 L 1614 617 L 1732 645"/>
+ <text x="1655" y="593" style="font-size:25">2,124,0,0,0</text>
+ <line x1="1732" y1="645" x2="1688" y2="563"/>
+ <path class="p2" d="M 1688 563 L 1649 491 L 1567 491 L 1590 551 L 1688 563"/>
+ <text x="1623" y="523" style="font-size:22">2,125,0,0,0</text>
+ <line x1="1688" y1="563" x2="1649" y2="491"/>
+ <path class="ps2" d="M 1614 617 L 1590 551 L 1494 539 L 1501 591 L 1614 617"/>
+ <text x="1549" y="574" style="font-size:25">2,126,0,X,0</text>
+ <path class="ps2" d="M 1590 551 L 1567 491 L 1486 491 L 1494 539 L 1590 551"/>
+ <text x="1534" y="517" style="font-size:22">2,127,0,X,0</text>
+ <path class="ps3" d="M 1500 370 L 1484 349 L 1443 351 L 1458 370 L 1500 370"/>
+ <text x="1471" y="360" style="font-size:11">3,0,0,X,0</text>
+ <path class="ps3" d="M 1484 349 L 1469 328 L 1428 333 L 1443 351 L 1484 349"/>
+ <text x="1456" y="340" style="font-size:10">3,1,0,X,0</text>
+ <path class="ps3" d="M 1458 370 L 1443 351 L 1401 354 L 1416 370 L 1458 370"/>
+ <text x="1429" y="361" style="font-size:11">3,2,0,X,0</text>
+ <path class="ps3" d="M 1443 351 L 1428 333 L 1386 338 L 1401 354 L 1443 351"/>
+ <text x="1414" y="344" style="font-size:11">3,3,0,X,0</text>
+ <path class="ps3" d="M 1469 328 L 1454 309 L 1413 316 L 1428 333 L 1469 328"/>
+ <text x="1441" y="322" style="font-size:10">3,4,0,X,0</text>
+ <path class="ps3" d="M 1454 309 L 1440 290 L 1400 299 L 1413 316 L 1454 309"/>
+ <text x="1427" y="304" style="font-size:10">3,5,0,X,0</text>
+ <path class="ps3" d="M 1428 333 L 1413 316 L 1372 323 L 1386 338 L 1428 333"/>
+ <text x="1400" y="327" style="font-size:10">3,6,0,X,0</text>
+ <path class="ps3" d="M 1413 316 L 1400 299 L 1358 308 L 1372 323 L 1413 316"/>
+ <text x="1386" y="312" style="font-size:10">3,7,0,X,0</text>
+ <path class="ps3" d="M 1416 370 L 1401 354 L 1359 356 L 1375 370 L 1416 370"/>
+ <text x="1388" y="362" style="font-size:11">3,8,0,X,0</text>
+ <path class="ps3" d="M 1401 354 L 1386 338 L 1345 343 L 1359 356 L 1401 354"/>
+ <text x="1373" y="348" style="font-size:11">3,9,0,X,0</text>
+ <path class="ps3" d="M 1375 370 L 1359 356 L 1318 358 L 1333 370 L 1375 370"/>
+ <text x="1346" y="363" style="font-size:11">3,10,0,X,0</text>
+ <line x1="1333" y1="370" x2="1318" y2="358"/>
+ <path class="ps3" d="M 1359 356 L 1345 343 L 1302 348 L 1318 358 L 1359 356"/>
+ <text x="1331" y="351" style="font-size:11">3,11,0,X,0</text>
+ <line x1="1318" y1="358" x2="1302" y2="348"/>
+ <path class="ps3" d="M 1386 338 L 1372 323 L 1330 330 L 1345 343 L 1386 338"/>
+ <text x="1358" y="333" style="font-size:10">3,12,0,X,0</text>
+ <path class="ps3" d="M 1372 323 L 1358 308 L 1316 317 L 1330 330 L 1372 323"/>
+ <text x="1344" y="320" style="font-size:10">3,13,0,X,0</text>
+ <path class="ps3" d="M 1345 343 L 1330 330 L 1288 337 L 1302 348 L 1345 343"/>
+ <text x="1316" y="339" style="font-size:11">3,14,0,X,0</text>
+ <line x1="1302" y1="348" x2="1288" y2="337"/>
+ <path class="ps3" d="M 1330 330 L 1316 317 L 1273 327 L 1288 337 L 1330 330"/>
+ <text x="1302" y="328" style="font-size:10">3,15,0,X,0</text>
+ <line x1="1288" y1="337" x2="1273" y2="327"/>
+ <path class="ps3" d="M 1440 290 L 1427 273 L 1386 283 L 1400 299 L 1440 290"/>
+ <text x="1413" y="286" style="font-size:9">3,16,0,X,0</text>
+ <path class="ps3" d="M 1427 273 L 1414 255 L 1373 268 L 1386 283 L 1427 273"/>
+ <text x="1400" y="270" style="font-size:9">3,17,0,X,0</text>
+ <path class="ps3" d="M 1400 299 L 1386 283 L 1345 294 L 1358 308 L 1400 299"/>
+ <text x="1372" y="296" style="font-size:9">3,18,0,X,0</text>
+ <path class="ps3" d="M 1386 283 L 1373 268 L 1331 280 L 1345 294 L 1386 283"/>
+ <text x="1359" y="281" style="font-size:9">3,19,0,X,0</text>
+ <path class="p3" d="M 1414 255 L 1401 238 L 1361 252 L 1373 268 L 1414 255"/>
+ <text x="1387" y="253" style="font-size:8">3,20,0,0,0</text>
+ <path class="p3" d="M 1401 238 L 1389 222 L 1348 238 L 1361 252 L 1401 238"/>
+ <text x="1375" y="238" style="font-size:8">3,21,0,0,0</text>
+ <path class="ps3" d="M 1373 268 L 1361 252 L 1319 267 L 1331 280 L 1373 268"/>
+ <text x="1346" y="267" style="font-size:9">3,22,0,X,0</text>
+ <path class="ps3" d="M 1361 252 L 1348 238 L 1306 254 L 1319 267 L 1361 252"/>
+ <text x="1334" y="253" style="font-size:8">3,23,0,X,0</text>
+ <path class="ps3" d="M 1358 308 L 1345 294 L 1302 305 L 1316 317 L 1358 308"/>
+ <text x="1330" y="306" style="font-size:10">3,24,0,X,0</text>
+ <path class="ps3" d="M 1345 294 L 1331 280 L 1289 293 L 1302 305 L 1345 294"/>
+ <text x="1317" y="293" style="font-size:9">3,25,0,X,0</text>
+ <path class="ps3" d="M 1316 317 L 1302 305 L 1259 317 L 1273 327 L 1316 317"/>
+ <text x="1288" y="316" style="font-size:10">3,26,0,X,0</text>
+ <line x1="1273" y1="327" x2="1259" y2="317"/>
+ <path class="ps3" d="M 1302 305 L 1289 293 L 1245 307 L 1259 317 L 1302 305"/>
+ <text x="1274" y="305" style="font-size:10">3,27,0,X,0</text>
+ <line x1="1259" y1="317" x2="1245" y2="307"/>
+ <path class="ps3" d="M 1331 280 L 1319 267 L 1275 282 L 1289 293 L 1331 280"/>
+ <text x="1304" y="280" style="font-size:9">3,28,0,X,0</text>
+ <path class="ps3" d="M 1319 267 L 1306 254 L 1263 270 L 1275 282 L 1319 267"/>
+ <text x="1291" y="268" style="font-size:9">3,29,0,X,0</text>
+ <path class="ps3" d="M 1289 293 L 1275 282 L 1231 297 L 1245 307 L 1289 293"/>
+ <text x="1260" y="294" style="font-size:10">3,30,0,X,0</text>
+ <line x1="1245" y1="307" x2="1231" y2="297"/>
+ <path class="ps3" d="M 1275 282 L 1263 270 L 1218 287 L 1231 297 L 1275 282"/>
+ <text x="1247" y="284" style="font-size:9">3,31,0,X,0</text>
+ <line x1="1231" y1="297" x2="1218" y2="287"/>
+ <path class="p3" d="M 1389 222 L 1340 221 L 1304 236 L 1348 238 L 1389 222"/>
+ <text x="1346" y="229" style="font-size:8">3,32,0,0,0</text>
+ <path class="p3" d="M 1340 221 L 1291 219 L 1260 233 L 1304 236 L 1340 221"/>
+ <text x="1299" y="227" style="font-size:8">3,33,0,0,0</text>
+ <path class="ps3" d="M 1348 238 L 1304 236 L 1267 251 L 1306 254 L 1348 238"/>
+ <text x="1307" y="244" style="font-size:8">3,34,0,X,0</text>
+ <path class="ps3" d="M 1304 236 L 1260 233 L 1228 248 L 1267 251 L 1304 236"/>
+ <text x="1265" y="242" style="font-size:8">3,35,0,X,0</text>
+ <path class="ps3" d="M 1291 219 L 1242 217 L 1216 231 L 1260 233 L 1291 219"/>
+ <text x="1252" y="225" style="font-size:8">3,36,0,X,0</text>
+ <path class="ps3" d="M 1242 217 L 1193 215 L 1173 229 L 1216 231 L 1242 217"/>
+ <text x="1206" y="223" style="font-size:8">3,37,0,X,0</text>
+ <path class="ps3" d="M 1260 233 L 1216 231 L 1190 245 L 1228 248 L 1260 233"/>
+ <text x="1224" y="239" style="font-size:8">3,38,0,X,0</text>
+ <path class="ps3" d="M 1216 231 L 1173 229 L 1151 243 L 1190 245 L 1216 231"/>
+ <text x="1183" y="237" style="font-size:8">3,39,0,X,0</text>
+ <path class="ps3" d="M 1306 254 L 1267 251 L 1229 267 L 1263 270 L 1306 254"/>
+ <text x="1266" y="260" style="font-size:9">3,40,0,X,0</text>
+ <path class="ps3" d="M 1267 251 L 1228 248 L 1196 264 L 1229 267 L 1267 251"/>
+ <text x="1230" y="257" style="font-size:9">3,41,0,X,0</text>
+ <path class="ps3" d="M 1263 270 L 1229 267 L 1190 283 L 1218 287 L 1263 270"/>
+ <text x="1225" y="277" style="font-size:9">3,42,0,X,0</text>
+ <line x1="1218" y1="287" x2="1190" y2="283"/>
+ <path class="ps3" d="M 1229 267 L 1196 264 L 1162 279 L 1190 283 L 1229 267"/>
+ <text x="1194" y="273" style="font-size:9">3,43,0,X,0</text>
+ <line x1="1190" y1="283" x2="1162" y2="279"/>
+ <path class="ps3" d="M 1228 248 L 1190 245 L 1162 260 L 1196 264 L 1228 248"/>
+ <text x="1194" y="254" style="font-size:9">3,44,0,X,0</text>
+ <path class="ps3" d="M 1190 245 L 1151 243 L 1130 257 L 1162 260 L 1190 245"/>
+ <text x="1158" y="251" style="font-size:9">3,45,0,X,0</text>
+ <path class="ps3" d="M 1196 264 L 1162 260 L 1134 276 L 1162 279 L 1196 264"/>
+ <text x="1164" y="270" style="font-size:9">3,46,0,X,0</text>
+ <line x1="1162" y1="279" x2="1134" y2="276"/>
+ <path class="ps3" d="M 1162 260 L 1130 257 L 1107 272 L 1134 276 L 1162 260"/>
+ <text x="1133" y="266" style="font-size:9">3,47,0,X,0</text>
+ <line x1="1134" y1="276" x2="1107" y2="272"/>
+ <path class="ps3" d="M 1193 215 L 1145 214 L 1129 227 L 1173 229 L 1193 215"/>
+ <text x="1160" y="221" style="font-size:8">3,48,0,X,0</text>
+ <path class="ps3" d="M 1145 214 L 1096 212 L 1086 225 L 1129 227 L 1145 214"/>
+ <text x="1114" y="219" style="font-size:8">3,49,0,X,0</text>
+ <path class="ps3" d="M 1173 229 L 1129 227 L 1113 240 L 1151 243 L 1173 229"/>
+ <text x="1142" y="235" style="font-size:8">3,50,0,X,0</text>
+ <path class="ps3" d="M 1129 227 L 1086 225 L 1075 237 L 1113 240 L 1129 227"/>
+ <text x="1101" y="232" style="font-size:8">3,51,0,X,0</text>
+ <path class="ps3" d="M 1096 212 L 1048 210 L 1043 222 L 1086 225 L 1096 212"/>
+ <text x="1068" y="217" style="font-size:8">3,52,0,X,0</text>
+ <path class="ps3" d="M 1048 210 L 1000 209 L 1000 220 L 1043 222 L 1048 210"/>
+ <text x="1023" y="215" style="font-size:8">3,53,0,X,0</text>
+ <path class="ps3" d="M 1086 225 L 1043 222 L 1038 235 L 1075 237 L 1086 225"/>
+ <text x="1060" y="230" style="font-size:8">3,54,0,X,0</text>
+ <path class="ps3" d="M 1043 222 L 1000 220 L 1000 232 L 1038 235 L 1043 222"/>
+ <text x="1020" y="227" style="font-size:8">3,55,0,X,0</text>
+ <path class="ps3" d="M 1151 243 L 1113 240 L 1097 254 L 1130 257 L 1151 243"/>
+ <text x="1123" y="248" style="font-size:9">3,56,0,X,0</text>
+ <path class="ps3" d="M 1113 240 L 1075 237 L 1064 251 L 1097 254 L 1113 240"/>
+ <text x="1087" y="245" style="font-size:8">3,57,0,X,0</text>
+ <path class="ps3" d="M 1130 257 L 1097 254 L 1080 268 L 1107 272 L 1130 257"/>
+ <text x="1103" y="263" style="font-size:9">3,58,0,X,0</text>
+ <line x1="1107" y1="272" x2="1080" y2="268"/>
+ <path class="ps3" d="M 1097 254 L 1064 251 L 1053 264 L 1080 268 L 1097 254"/>
+ <text x="1074" y="259" style="font-size:9">3,59,0,X,0</text>
+ <line x1="1080" y1="268" x2="1053" y2="264"/>
+ <path class="ps3" d="M 1075 237 L 1038 235 L 1032 247 L 1064 251 L 1075 237"/>
+ <text x="1052" y="243" style="font-size:8">3,60,0,X,0</text>
+ <path class="ps3" d="M 1038 235 L 1000 232 L 1000 244 L 1032 247 L 1038 235"/>
+ <text x="1017" y="240" style="font-size:8">3,61,0,X,0</text>
+ <path class="ps3" d="M 1064 251 L 1032 247 L 1026 260 L 1053 264 L 1064 251"/>
+ <text x="1044" y="256" style="font-size:9">3,62,0,X,0</text>
+ <line x1="1053" y1="264" x2="1026" y2="260"/>
+ <path class="ps3" d="M 1032 247 L 1000 244 L 1000 257 L 1026 260 L 1032 247"/>
+ <text x="1015" y="252" style="font-size:9">3,63,0,X,0</text>
+ <line x1="1026" y1="260" x2="1000" y2="257"/>
+ <path class="ps3" d="M 1000 209 L 952 210 L 957 222 L 1000 220 L 1000 209"/>
+ <text x="977" y="215" style="font-size:8">3,64,0,X,0</text>
+ <path class="ps3" d="M 952 210 L 904 212 L 914 225 L 957 222 L 952 210"/>
+ <text x="932" y="217" style="font-size:8">3,65,0,X,0</text>
+ <path class="ps3" d="M 1000 220 L 957 222 L 962 235 L 1000 232 L 1000 220"/>
+ <text x="980" y="227" style="font-size:8">3,66,0,X,0</text>
+ <path class="ps3" d="M 957 222 L 914 225 L 925 237 L 962 235 L 957 222"/>
+ <text x="940" y="230" style="font-size:8">3,67,0,X,0</text>
+ <path class="ps3" d="M 904 212 L 855 214 L 871 227 L 914 225 L 904 212"/>
+ <text x="886" y="219" style="font-size:8">3,68,0,X,0</text>
+ <path class="ps3" d="M 855 214 L 807 215 L 827 229 L 871 227 L 855 214"/>
+ <text x="840" y="221" style="font-size:8">3,69,0,X,0</text>
+ <path class="ps3" d="M 914 225 L 871 227 L 887 240 L 925 237 L 914 225"/>
+ <text x="899" y="232" style="font-size:8">3,70,0,X,0</text>
+ <path class="ps3" d="M 871 227 L 827 229 L 849 243 L 887 240 L 871 227"/>
+ <text x="858" y="235" style="font-size:8">3,71,0,X,0</text>
+ <path class="ps3" d="M 1000 232 L 962 235 L 968 247 L 1000 244 L 1000 232"/>
+ <text x="983" y="240" style="font-size:8">3,72,0,X,0</text>
+ <path class="ps3" d="M 962 235 L 925 237 L 936 251 L 968 247 L 962 235"/>
+ <text x="948" y="243" style="font-size:8">3,73,0,X,0</text>
+ <path class="ps3" d="M 1000 244 L 968 247 L 974 260 L 1000 257 L 1000 244"/>
+ <text x="985" y="252" style="font-size:9">3,74,0,X,0</text>
+ <line x1="1000" y1="257" x2="974" y2="260"/>
+ <path class="ps3" d="M 968 247 L 936 251 L 947 264 L 974 260 L 968 247"/>
+ <text x="956" y="256" style="font-size:9">3,75,0,X,0</text>
+ <line x1="974" y1="260" x2="947" y2="264"/>
+ <path class="ps3" d="M 925 237 L 887 240 L 903 254 L 936 251 L 925 237"/>
+ <text x="913" y="245" style="font-size:8">3,76,0,X,0</text>
+ <path class="ps3" d="M 887 240 L 849 243 L 870 257 L 903 254 L 887 240"/>
+ <text x="877" y="248" style="font-size:9">3,77,0,X,0</text>
+ <path class="ps3" d="M 936 251 L 903 254 L 920 268 L 947 264 L 936 251"/>
+ <text x="926" y="259" style="font-size:9">3,78,0,X,0</text>
+ <line x1="947" y1="264" x2="920" y2="268"/>
+ <path class="ps3" d="M 903 254 L 870 257 L 893 272 L 920 268 L 903 254"/>
+ <text x="897" y="263" style="font-size:9">3,79,0,X,0</text>
+ <line x1="920" y1="268" x2="893" y2="272"/>
+ <path class="ps3" d="M 807 215 L 758 217 L 784 231 L 827 229 L 807 215"/>
+ <text x="794" y="223" style="font-size:8">3,80,0,X,0</text>
+ <path class="ps3" d="M 758 217 L 709 219 L 740 233 L 784 231 L 758 217"/>
+ <text x="748" y="225" style="font-size:8">3,81,0,X,0</text>
+ <path class="ps3" d="M 827 229 L 784 231 L 810 245 L 849 243 L 827 229"/>
+ <text x="817" y="237" style="font-size:8">3,82,0,X,0</text>
+ <path class="ps3" d="M 784 231 L 740 233 L 772 248 L 810 245 L 784 231"/>
+ <text x="776" y="239" style="font-size:8">3,83,0,X,0</text>
+ <path class="p3" d="M 709 219 L 660 221 L 696 236 L 740 233 L 709 219"/>
+ <text x="701" y="227" style="font-size:8">3,84,0,0,0</text>
+ <path class="p3" d="M 660 221 L 611 222 L 652 238 L 696 236 L 660 221"/>
+ <text x="654" y="229" style="font-size:8">3,85,0,0,0</text>
+ <path class="ps3" d="M 740 233 L 696 236 L 733 251 L 772 248 L 740 233"/>
+ <text x="735" y="242" style="font-size:8">3,86,0,X,0</text>
+ <path class="ps3" d="M 696 236 L 652 238 L 694 254 L 733 251 L 696 236"/>
+ <text x="693" y="244" style="font-size:8">3,87,0,X,0</text>
+ <path class="ps3" d="M 849 243 L 810 245 L 838 260 L 870 257 L 849 243"/>
+ <text x="842" y="251" style="font-size:9">3,88,0,X,0</text>
+ <path class="ps3" d="M 810 245 L 772 248 L 804 264 L 838 260 L 810 245"/>
+ <text x="806" y="254" style="font-size:9">3,89,0,X,0</text>
+ <path class="ps3" d="M 870 257 L 838 260 L 866 276 L 893 272 L 870 257"/>
+ <text x="867" y="266" style="font-size:9">3,90,0,X,0</text>
+ <line x1="893" y1="272" x2="866" y2="276"/>
+ <path class="ps3" d="M 838 260 L 804 264 L 838 279 L 866 276 L 838 260"/>
+ <text x="836" y="270" style="font-size:9">3,91,0,X,0</text>
+ <line x1="866" y1="276" x2="838" y2="279"/>
+ <path class="ps3" d="M 772 248 L 733 251 L 771 267 L 804 264 L 772 248"/>
+ <text x="770" y="257" style="font-size:9">3,92,0,X,0</text>
+ <path class="ps3" d="M 733 251 L 694 254 L 737 270 L 771 267 L 733 251"/>
+ <text x="734" y="260" style="font-size:9">3,93,0,X,0</text>
+ <path class="ps3" d="M 804 264 L 771 267 L 810 283 L 838 279 L 804 264"/>
+ <text x="806" y="273" style="font-size:9">3,94,0,X,0</text>
+ <line x1="838" y1="279" x2="810" y2="283"/>
+ <path class="ps3" d="M 771 267 L 737 270 L 782 287 L 810 283 L 771 267"/>
+ <text x="775" y="277" style="font-size:9">3,95,0,X,0</text>
+ <line x1="810" y1="283" x2="782" y2="287"/>
+ <path class="p3" d="M 611 222 L 599 238 L 639 252 L 652 238 L 611 222"/>
+ <text x="625" y="238" style="font-size:8">3,96,0,0,0</text>
+ <path class="p3" d="M 599 238 L 586 255 L 627 268 L 639 252 L 599 238"/>
+ <text x="613" y="253" style="font-size:8">3,97,0,0,0</text>
+ <path class="ps3" d="M 652 238 L 639 252 L 681 267 L 694 254 L 652 238"/>
+ <text x="666" y="253" style="font-size:8">3,98,0,X,0</text>
+ <path class="ps3" d="M 639 252 L 627 268 L 669 280 L 681 267 L 639 252"/>
+ <text x="654" y="267" style="font-size:9">3,99,0,X,0</text>
+ <path class="ps3" d="M 586 255 L 573 273 L 614 283 L 627 268 L 586 255"/>
+ <text x="600" y="270" style="font-size:9">3,100,0,X,0</text>
+ <path class="ps3" d="M 573 273 L 560 290 L 600 299 L 614 283 L 573 273"/>
+ <text x="587" y="286" style="font-size:9">3,101,0,X,0</text>
+ <path class="ps3" d="M 627 268 L 614 283 L 655 294 L 669 280 L 627 268"/>
+ <text x="641" y="281" style="font-size:9">3,102,0,X,0</text>
+ <path class="ps3" d="M 614 283 L 600 299 L 642 308 L 655 294 L 614 283"/>
+ <text x="628" y="296" style="font-size:9">3,103,0,X,0</text>
+ <path class="ps3" d="M 694 254 L 681 267 L 725 282 L 737 270 L 694 254"/>
+ <text x="709" y="268" style="font-size:9">3,104,0,X,0</text>
+ <path class="ps3" d="M 681 267 L 669 280 L 711 293 L 725 282 L 681 267"/>
+ <text x="696" y="280" style="font-size:9">3,105,0,X,0</text>
+ <path class="ps3" d="M 737 270 L 725 282 L 769 297 L 782 287 L 737 270"/>
+ <text x="753" y="284" style="font-size:9">3,106,0,X,0</text>
+ <line x1="782" y1="287" x2="769" y2="297"/>
+ <path class="ps3" d="M 725 282 L 711 293 L 755 307 L 769 297 L 725 282"/>
+ <text x="740" y="294" style="font-size:10">3,107,0,X,0</text>
+ <line x1="769" y1="297" x2="755" y2="307"/>
+ <path class="ps3" d="M 669 280 L 655 294 L 698 305 L 711 293 L 669 280"/>
+ <text x="683" y="293" style="font-size:9">3,108,0,X,0</text>
+ <path class="ps3" d="M 655 294 L 642 308 L 684 317 L 698 305 L 655 294"/>
+ <text x="670" y="306" style="font-size:10">3,109,0,X,0</text>
+ <path class="ps3" d="M 711 293 L 698 305 L 741 317 L 755 307 L 711 293"/>
+ <text x="726" y="305" style="font-size:10">3,110,0,X,0</text>
+ <line x1="755" y1="307" x2="741" y2="317"/>
+ <path class="ps3" d="M 698 305 L 684 317 L 727 327 L 741 317 L 698 305"/>
+ <text x="712" y="316" style="font-size:10">3,111,0,X,0</text>
+ <line x1="741" y1="317" x2="727" y2="327"/>
+ <path class="ps3" d="M 560 290 L 546 309 L 587 316 L 600 299 L 560 290"/>
+ <text x="573" y="304" style="font-size:10">3,112,0,X,0</text>
+ <path class="ps3" d="M 546 309 L 531 328 L 572 333 L 587 316 L 546 309"/>
+ <text x="559" y="322" style="font-size:10">3,113,0,X,0</text>
+ <path class="ps3" d="M 600 299 L 587 316 L 628 323 L 642 308 L 600 299"/>
+ <text x="614" y="312" style="font-size:10">3,114,0,X,0</text>
+ <path class="ps3" d="M 587 316 L 572 333 L 614 338 L 628 323 L 587 316"/>
+ <text x="600" y="327" style="font-size:10">3,115,0,X,0</text>
+ <path class="ps3" d="M 531 328 L 516 349 L 557 351 L 572 333 L 531 328"/>
+ <text x="544" y="340" style="font-size:10">3,116,0,X,0</text>
+ <path class="ps3" d="M 516 349 L 500 370 L 542 370 L 557 351 L 516 349"/>
+ <text x="529" y="360" style="font-size:11">3,117,0,X,0</text>
+ <path class="ps3" d="M 572 333 L 557 351 L 599 354 L 614 338 L 572 333"/>
+ <text x="586" y="344" style="font-size:11">3,118,0,X,0</text>
+ <path class="ps3" d="M 557 351 L 542 370 L 584 370 L 599 354 L 557 351"/>
+ <text x="571" y="361" style="font-size:11">3,119,0,X,0</text>
+ <path class="ps3" d="M 642 308 L 628 323 L 670 330 L 684 317 L 642 308"/>
+ <text x="656" y="320" style="font-size:10">3,120,0,X,0</text>
+ <path class="ps3" d="M 628 323 L 614 338 L 655 343 L 670 330 L 628 323"/>
+ <text x="642" y="333" style="font-size:10">3,121,0,X,0</text>
+ <path class="ps3" d="M 684 317 L 670 330 L 712 337 L 727 327 L 684 317"/>
+ <text x="698" y="328" style="font-size:10">3,122,0,X,0</text>
+ <line x1="727" y1="327" x2="712" y2="337"/>
+ <path class="ps3" d="M 670 330 L 655 343 L 698 348 L 712 337 L 670 330"/>
+ <text x="684" y="339" style="font-size:11">3,123,0,X,0</text>
+ <line x1="712" y1="337" x2="698" y2="348"/>
+ <path class="ps3" d="M 614 338 L 599 354 L 641 356 L 655 343 L 614 338"/>
+ <text x="627" y="348" style="font-size:11">3,124,0,X,0</text>
+ <path class="ps3" d="M 599 354 L 584 370 L 625 370 L 641 356 L 599 354"/>
+ <text x="612" y="362" style="font-size:11">3,125,0,X,0</text>
+ <path class="ps3" d="M 655 343 L 641 356 L 682 358 L 698 348 L 655 343"/>
+ <text x="669" y="351" style="font-size:11">3,126,0,X,0</text>
+ <line x1="698" y1="348" x2="682" y2="358"/>
+ <path class="ps3" d="M 641 356 L 625 370 L 667 370 L 682 358 L 641 356"/>
+ <text x="654" y="363" style="font-size:11">3,127,0,X,0</text>
+ <line x1="682" y1="358" x2="667" y2="370"/>
+ <path class="ps3" d="M 500 370 L 497 391 L 542 389 L 542 370 L 500 370"/>
+ <text x="520" y="380" style="font-size:11">3,128,0,X,0</text>
+ <path class="ps3" d="M 497 391 L 493 414 L 541 408 L 542 389 L 497 391"/>
+ <text x="518" y="400" style="font-size:12">3,129,0,X,0</text>
+ <path class="ps3" d="M 542 370 L 542 389 L 587 386 L 584 370 L 542 370"/>
+ <text x="564" y="378" style="font-size:11">3,130,0,X,0</text>
+ <path class="ps3" d="M 542 389 L 541 408 L 590 403 L 587 386 L 542 389"/>
+ <text x="565" y="396" style="font-size:12">3,131,0,X,0</text>
+ <path class="ps3" d="M 493 414 L 488 437 L 541 429 L 541 408 L 493 414"/>
+ <text x="516" y="422" style="font-size:12">3,132,0,X,0</text>
+ <path class="ps3" d="M 488 437 L 484 462 L 540 450 L 541 429 L 488 437"/>
+ <text x="514" y="445" style="font-size:13">3,133,0,X,0</text>
+ <path class="ps3" d="M 541 408 L 541 429 L 593 420 L 590 403 L 541 408"/>
+ <text x="566" y="415" style="font-size:12">3,134,0,X,0</text>
+ <path class="ps3" d="M 541 429 L 540 450 L 596 439 L 593 420 L 541 429"/>
+ <text x="568" y="434" style="font-size:13">3,135,0,X,0</text>
+ <path class="ps3" d="M 584 370 L 587 386 L 631 383 L 625 370 L 584 370"/>
+ <text x="607" y="377" style="font-size:11">3,136,0,X,0</text>
+ <path class="ps3" d="M 587 386 L 590 403 L 637 398 L 631 383 L 587 386"/>
+ <text x="611" y="392" style="font-size:12">3,137,0,X,0</text>
+ <path class="ps3" d="M 625 370 L 631 383 L 676 381 L 667 370 L 625 370"/>
+ <text x="650" y="376" style="font-size:12">3,138,0,X,0</text>
+ <line x1="667" y1="370" x2="676" y2="381"/>
+ <path class="ps3" d="M 631 383 L 637 398 L 685 392 L 676 381 L 631 383"/>
+ <text x="657" y="388" style="font-size:12">3,139,0,X,0</text>
+ <line x1="676" y1="381" x2="685" y2="392"/>
+ <path class="ps3" d="M 590 403 L 593 420 L 644 412 L 637 398 L 590 403"/>
+ <text x="616" y="408" style="font-size:12">3,140,0,X,0</text>
+ <path class="ps3" d="M 593 420 L 596 439 L 650 427 L 644 412 L 593 420"/>
+ <text x="621" y="425" style="font-size:13">3,141,0,X,0</text>
+ <path class="ps3" d="M 637 398 L 644 412 L 694 404 L 685 392 L 637 398"/>
+ <text x="665" y="401" style="font-size:12">3,142,0,X,0</text>
+ <line x1="685" y1="392" x2="694" y2="404"/>
+ <path class="ps3" d="M 644 412 L 650 427 L 703 416 L 694 404 L 644 412"/>
+ <text x="673" y="415" style="font-size:13">3,143,0,X,0</text>
+ <line x1="694" y1="404" x2="703" y2="416"/>
+ <path class="ps3" d="M 484 462 L 479 488 L 540 472 L 540 450 L 484 462"/>
+ <text x="511" y="468" style="font-size:14">3,144,0,X,0</text>
+ <path class="ps3" d="M 479 488 L 475 515 L 540 495 L 540 472 L 479 488"/>
+ <text x="509" y="492" style="font-size:14">3,145,0,X,0</text>
+ <path class="ps3" d="M 540 450 L 540 472 L 599 457 L 596 439 L 540 450"/>
+ <text x="569" y="454" style="font-size:13">3,146,0,X,0</text>
+ <path class="ps3" d="M 540 472 L 540 495 L 603 477 L 599 457 L 540 472"/>
+ <text x="571" y="475" style="font-size:14">3,147,0,X,0</text>
+ <path class="p3" d="M 475 515 L 470 543 L 539 519 L 540 495 L 475 515"/>
+ <text x="506" y="518" style="font-size:15">3,148,0,0,0</text>
+ <path class="p3" d="M 470 543 L 464 572 L 539 544 L 539 519 L 470 543"/>
+ <text x="503" y="544" style="font-size:16">3,149,0,0,0</text>
+ <path class="ps3" d="M 540 495 L 539 519 L 606 496 L 603 477 L 540 495"/>
+ <text x="572" y="497" style="font-size:14">3,150,0,X,0</text>
+ <path class="ps3" d="M 539 519 L 539 544 L 610 517 L 606 496 L 539 519"/>
+ <text x="574" y="519" style="font-size:15">3,151,0,X,0</text>
+ <path class="ps3" d="M 596 439 L 599 457 L 657 443 L 650 427 L 596 439"/>
+ <text x="626" y="441" style="font-size:13">3,152,0,X,0</text>
+ <path class="ps3" d="M 599 457 L 603 477 L 664 458 L 657 443 L 599 457"/>
+ <text x="631" y="459" style="font-size:14">3,153,0,X,0</text>
+ <path class="ps3" d="M 650 427 L 657 443 L 713 428 L 703 416 L 650 427"/>
+ <text x="681" y="428" style="font-size:13">3,154,0,X,0</text>
+ <line x1="703" y1="416" x2="713" y2="428"/>
+ <path class="ps3" d="M 657 443 L 664 458 L 723 441 L 713 428 L 657 443"/>
+ <text x="689" y="442" style="font-size:13">3,155,0,X,0</text>
+ <line x1="713" y1="428" x2="723" y2="441"/>
+ <path class="ps3" d="M 603 477 L 606 496 L 671 475 L 664 458 L 603 477"/>
+ <text x="636" y="476" style="font-size:14">3,156,0,X,0</text>
+ <path class="ps3" d="M 606 496 L 610 517 L 678 491 L 671 475 L 606 496"/>
+ <text x="641" y="495" style="font-size:15">3,157,0,X,0</text>
+ <path class="ps3" d="M 664 458 L 671 475 L 733 454 L 723 441 L 664 458"/>
+ <text x="698" y="457" style="font-size:14">3,158,0,X,0</text>
+ <line x1="723" y1="441" x2="733" y2="454"/>
+ <path class="ps3" d="M 671 475 L 678 491 L 743 467 L 733 454 L 671 475"/>
+ <text x="707" y="471" style="font-size:14">3,159,0,X,0</text>
+ <line x1="733" y1="454" x2="743" y2="467"/>
+ <path class="p3" d="M 464 572 L 530 575 L 595 548 L 539 544 L 464 572"/>
+ <text x="532" y="560" style="font-size:16">3,160,0,0,0</text>
+ <path class="p3" d="M 530 575 L 596 579 L 652 552 L 595 548 L 530 575"/>
+ <text x="594" y="563" style="font-size:16">3,161,0,0,0</text>
+ <path class="ps3" d="M 539 544 L 595 548 L 657 522 L 610 517 L 539 544"/>
+ <text x="601" y="533" style="font-size:15">3,162,0,X,0</text>
+ <path class="ps3" d="M 595 548 L 652 552 L 705 526 L 657 522 L 595 548"/>
+ <text x="653" y="537" style="font-size:16">3,163,0,X,0</text>
+ <path class="ps3" d="M 596 579 L 663 582 L 709 556 L 652 552 L 596 579"/>
+ <text x="655" y="567" style="font-size:16">3,164,0,X,0</text>
+ <path class="ps3" d="M 663 582 L 729 585 L 766 560 L 709 556 L 663 582"/>
+ <text x="717" y="571" style="font-size:17">3,165,0,X,0</text>
+ <path class="ps3" d="M 652 552 L 709 556 L 753 531 L 705 526 L 652 552"/>
+ <text x="705" y="541" style="font-size:16">3,166,0,X,0</text>
+ <path class="ps3" d="M 709 556 L 766 560 L 802 535 L 753 531 L 709 556"/>
+ <text x="758" y="545" style="font-size:16">3,167,0,X,0</text>
+ <path class="ps3" d="M 610 517 L 657 522 L 717 496 L 678 491 L 610 517"/>
+ <text x="666" y="506" style="font-size:15">3,168,0,X,0</text>
+ <path class="ps3" d="M 657 522 L 705 526 L 756 501 L 717 496 L 657 522"/>
+ <text x="709" y="511" style="font-size:15">3,169,0,X,0</text>
+ <path class="ps3" d="M 678 491 L 717 496 L 774 472 L 743 467 L 678 491"/>
+ <text x="728" y="481" style="font-size:14">3,170,0,X,0</text>
+ <line x1="743" y1="467" x2="774" y2="472"/>
+ <path class="ps3" d="M 717 496 L 756 501 L 806 478 L 774 472 L 717 496"/>
+ <text x="764" y="487" style="font-size:15">3,171,0,X,0</text>
+ <line x1="774" y1="472" x2="806" y2="478"/>
+ <path class="ps3" d="M 705 526 L 753 531 L 796 507 L 756 501 L 705 526"/>
+ <text x="753" y="516" style="font-size:15">3,172,0,X,0</text>
+ <path class="ps3" d="M 753 531 L 802 535 L 836 512 L 796 507 L 753 531"/>
+ <text x="797" y="521" style="font-size:15">3,173,0,X,0</text>
+ <path class="ps3" d="M 756 501 L 796 507 L 837 483 L 806 478 L 756 501"/>
+ <text x="799" y="492" style="font-size:15">3,174,0,X,0</text>
+ <line x1="806" y1="478" x2="837" y2="483"/>
+ <path class="ps3" d="M 796 507 L 836 512 L 869 489 L 837 483 L 796 507"/>
+ <text x="835" y="498" style="font-size:15">3,175,0,X,0</text>
+ <line x1="837" y1="483" x2="869" y2="489"/>
+ <path class="ps3" d="M 729 585 L 797 589 L 824 564 L 766 560 L 729 585"/>
+ <text x="779" y="574" style="font-size:17">3,176,0,X,0</text>
+ <path class="ps3" d="M 797 589 L 864 592 L 882 568 L 824 564 L 797 589"/>
+ <text x="842" y="578" style="font-size:17">3,177,0,X,0</text>
+ <path class="ps3" d="M 766 560 L 824 564 L 851 540 L 802 535 L 766 560"/>
+ <text x="811" y="550" style="font-size:16">3,178,0,X,0</text>
+ <path class="ps3" d="M 824 564 L 882 568 L 900 545 L 851 540 L 824 564"/>
+ <text x="865" y="554" style="font-size:16">3,179,0,X,0</text>
+ <path class="ps3" d="M 864 592 L 932 595 L 941 572 L 882 568 L 864 592"/>
+ <text x="905" y="582" style="font-size:17">3,180,0,X,0</text>
+ <path class="ps3" d="M 932 595 L 1000 599 L 1000 576 L 941 572 L 932 595"/>
+ <text x="968" y="585" style="font-size:17">3,181,0,X,0</text>
+ <path class="ps3" d="M 882 568 L 941 572 L 950 549 L 900 545 L 882 568"/>
+ <text x="918" y="558" style="font-size:17">3,182,0,X,0</text>
+ <path class="ps3" d="M 941 572 L 1000 576 L 1000 554 L 950 549 L 941 572"/>
+ <text x="973" y="563" style="font-size:17">3,183,0,X,0</text>
+ <path class="ps3" d="M 802 535 L 851 540 L 877 517 L 836 512 L 802 535"/>
+ <text x="842" y="526" style="font-size:16">3,184,0,X,0</text>
+ <path class="ps3" d="M 851 540 L 900 545 L 917 522 L 877 517 L 851 540"/>
+ <text x="886" y="531" style="font-size:16">3,185,0,X,0</text>
+ <path class="ps3" d="M 836 512 L 877 517 L 901 495 L 869 489 L 836 512"/>
+ <text x="871" y="503" style="font-size:15">3,186,0,X,0</text>
+ <line x1="869" y1="489" x2="901" y2="495"/>
+ <path class="ps3" d="M 877 517 L 917 522 L 934 500 L 901 495 L 877 517"/>
+ <text x="907" y="508" style="font-size:15">3,187,0,X,0</text>
+ <line x1="901" y1="495" x2="934" y2="500"/>
+ <path class="ps3" d="M 900 545 L 950 549 L 959 527 L 917 522 L 900 545"/>
+ <text x="932" y="536" style="font-size:16">3,188,0,X,0</text>
+ <path class="ps3" d="M 950 549 L 1000 554 L 1000 533 L 959 527 L 950 549"/>
+ <text x="977" y="541" style="font-size:16">3,189,0,X,0</text>
+ <path class="ps3" d="M 917 522 L 959 527 L 967 506 L 934 500 L 917 522"/>
+ <text x="944" y="514" style="font-size:15">3,190,0,X,0</text>
+ <line x1="934" y1="500" x2="967" y2="506"/>
+ <path class="ps3" d="M 959 527 L 1000 533 L 1000 512 L 967 506 L 959 527"/>
+ <text x="981" y="520" style="font-size:16">3,191,0,X,0</text>
+ <line x1="967" y1="506" x2="1000" y2="512"/>
+ <path class="ps3" d="M 1000 599 L 1068 595 L 1059 572 L 1000 576 L 1000 599"/>
+ <text x="1032" y="585" style="font-size:17">3,192,0,X,0</text>
+ <path class="ps3" d="M 1068 595 L 1136 592 L 1118 568 L 1059 572 L 1068 595"/>
+ <text x="1095" y="582" style="font-size:17">3,193,0,X,0</text>
+ <path class="ps3" d="M 1000 576 L 1059 572 L 1050 549 L 1000 554 L 1000 576"/>
+ <text x="1027" y="563" style="font-size:17">3,194,0,X,0</text>
+ <path class="ps3" d="M 1059 572 L 1118 568 L 1100 545 L 1050 549 L 1059 572"/>
+ <text x="1082" y="558" style="font-size:17">3,195,0,X,0</text>
+ <path class="ps3" d="M 1136 592 L 1203 589 L 1176 564 L 1118 568 L 1136 592"/>
+ <text x="1158" y="578" style="font-size:17">3,196,0,X,0</text>
+ <path class="ps3" d="M 1203 589 L 1271 585 L 1234 560 L 1176 564 L 1203 589"/>
+ <text x="1221" y="574" style="font-size:17">3,197,0,X,0</text>
+ <path class="ps3" d="M 1118 568 L 1176 564 L 1149 540 L 1100 545 L 1118 568"/>
+ <text x="1135" y="554" style="font-size:16">3,198,0,X,0</text>
+ <path class="ps3" d="M 1176 564 L 1234 560 L 1198 535 L 1149 540 L 1176 564"/>
+ <text x="1189" y="550" style="font-size:16">3,199,0,X,0</text>
+ <path class="ps3" d="M 1000 554 L 1050 549 L 1041 527 L 1000 533 L 1000 554"/>
+ <text x="1023" y="541" style="font-size:16">3,200,0,X,0</text>
+ <path class="ps3" d="M 1050 549 L 1100 545 L 1083 522 L 1041 527 L 1050 549"/>
+ <text x="1068" y="536" style="font-size:16">3,201,0,X,0</text>
+ <path class="ps3" d="M 1000 533 L 1041 527 L 1033 506 L 1000 512 L 1000 533"/>
+ <text x="1019" y="520" style="font-size:16">3,202,0,X,0</text>
+ <line x1="1000" y1="512" x2="1033" y2="506"/>
+ <path class="ps3" d="M 1041 527 L 1083 522 L 1066 500 L 1033 506 L 1041 527"/>
+ <text x="1056" y="514" style="font-size:15">3,203,0,X,0</text>
+ <line x1="1033" y1="506" x2="1066" y2="500"/>
+ <path class="ps3" d="M 1100 545 L 1149 540 L 1123 517 L 1083 522 L 1100 545"/>
+ <text x="1114" y="531" style="font-size:16">3,204,0,X,0</text>
+ <path class="ps3" d="M 1149 540 L 1198 535 L 1164 512 L 1123 517 L 1149 540"/>
+ <text x="1158" y="526" style="font-size:16">3,205,0,X,0</text>
+ <path class="ps3" d="M 1083 522 L 1123 517 L 1099 495 L 1066 500 L 1083 522"/>
+ <text x="1093" y="508" style="font-size:15">3,206,0,X,0</text>
+ <line x1="1066" y1="500" x2="1099" y2="495"/>
+ <path class="ps3" d="M 1123 517 L 1164 512 L 1131 489 L 1099 495 L 1123 517"/>
+ <text x="1129" y="503" style="font-size:15">3,207,0,X,0</text>
+ <line x1="1099" y1="495" x2="1131" y2="489"/>
+ <path class="ps3" d="M 1271 585 L 1337 582 L 1291 556 L 1234 560 L 1271 585"/>
+ <text x="1283" y="571" style="font-size:17">3,208,0,X,0</text>
+ <path class="ps3" d="M 1337 582 L 1404 579 L 1348 552 L 1291 556 L 1337 582"/>
+ <text x="1345" y="567" style="font-size:16">3,209,0,X,0</text>
+ <path class="ps3" d="M 1234 560 L 1291 556 L 1247 531 L 1198 535 L 1234 560"/>
+ <text x="1242" y="545" style="font-size:16">3,210,0,X,0</text>
+ <path class="ps3" d="M 1291 556 L 1348 552 L 1295 526 L 1247 531 L 1291 556"/>
+ <text x="1295" y="541" style="font-size:16">3,211,0,X,0</text>
+ <path class="p3" d="M 1404 579 L 1470 575 L 1405 548 L 1348 552 L 1404 579"/>
+ <text x="1406" y="563" style="font-size:16">3,212,0,0,0</text>
+ <path class="p3" d="M 1470 575 L 1536 572 L 1461 544 L 1405 548 L 1470 575"/>
+ <text x="1468" y="560" style="font-size:16">3,213,0,0,0</text>
+ <path class="ps3" d="M 1348 552 L 1405 548 L 1343 522 L 1295 526 L 1348 552"/>
+ <text x="1347" y="537" style="font-size:16">3,214,0,X,0</text>
+ <path class="ps3" d="M 1405 548 L 1461 544 L 1390 517 L 1343 522 L 1405 548"/>
+ <text x="1399" y="533" style="font-size:15">3,215,0,X,0</text>
+ <path class="ps3" d="M 1198 535 L 1247 531 L 1204 507 L 1164 512 L 1198 535"/>
+ <text x="1203" y="521" style="font-size:15">3,216,0,X,0</text>
+ <path class="ps3" d="M 1247 531 L 1295 526 L 1244 501 L 1204 507 L 1247 531"/>
+ <text x="1247" y="516" style="font-size:15">3,217,0,X,0</text>
+ <path class="ps3" d="M 1164 512 L 1204 507 L 1163 483 L 1131 489 L 1164 512"/>
+ <text x="1165" y="498" style="font-size:15">3,218,0,X,0</text>
+ <line x1="1131" y1="489" x2="1163" y2="483"/>
+ <path class="ps3" d="M 1204 507 L 1244 501 L 1194 478 L 1163 483 L 1204 507"/>
+ <text x="1201" y="492" style="font-size:15">3,219,0,X,0</text>
+ <line x1="1163" y1="483" x2="1194" y2="478"/>
+ <path class="ps3" d="M 1295 526 L 1343 522 L 1283 496 L 1244 501 L 1295 526"/>
+ <text x="1291" y="511" style="font-size:15">3,220,0,X,0</text>
+ <path class="ps3" d="M 1343 522 L 1390 517 L 1322 491 L 1283 496 L 1343 522"/>
+ <text x="1334" y="506" style="font-size:15">3,221,0,X,0</text>
+ <path class="ps3" d="M 1244 501 L 1283 496 L 1226 472 L 1194 478 L 1244 501"/>
+ <text x="1236" y="487" style="font-size:15">3,222,0,X,0</text>
+ <line x1="1194" y1="478" x2="1226" y2="472"/>
+ <path class="ps3" d="M 1283 496 L 1322 491 L 1257 467 L 1226 472 L 1283 496"/>
+ <text x="1272" y="481" style="font-size:14">3,223,0,X,0</text>
+ <line x1="1226" y1="472" x2="1257" y2="467"/>
+ <path class="p3" d="M 1536 572 L 1530 543 L 1461 519 L 1461 544 L 1536 572"/>
+ <text x="1497" y="544" style="font-size:16">3,224,0,0,0</text>
+ <path class="p3" d="M 1530 543 L 1525 515 L 1460 495 L 1461 519 L 1530 543"/>
+ <text x="1494" y="518" style="font-size:15">3,225,0,0,0</text>
+ <path class="ps3" d="M 1461 544 L 1461 519 L 1394 496 L 1390 517 L 1461 544"/>
+ <text x="1426" y="519" style="font-size:15">3,226,0,X,0</text>
+ <path class="ps3" d="M 1461 519 L 1460 495 L 1397 477 L 1394 496 L 1461 519"/>
+ <text x="1428" y="497" style="font-size:14">3,227,0,X,0</text>
+ <path class="ps3" d="M 1525 515 L 1521 488 L 1460 472 L 1460 495 L 1525 515"/>
+ <text x="1491" y="492" style="font-size:14">3,228,0,X,0</text>
+ <path class="ps3" d="M 1521 488 L 1516 462 L 1460 450 L 1460 472 L 1521 488"/>
+ <text x="1489" y="468" style="font-size:14">3,229,0,X,0</text>
+ <path class="ps3" d="M 1460 495 L 1460 472 L 1401 457 L 1397 477 L 1460 495"/>
+ <text x="1429" y="475" style="font-size:14">3,230,0,X,0</text>
+ <path class="ps3" d="M 1460 472 L 1460 450 L 1404 439 L 1401 457 L 1460 472"/>
+ <text x="1431" y="454" style="font-size:13">3,231,0,X,0</text>
+ <path class="ps3" d="M 1390 517 L 1394 496 L 1329 475 L 1322 491 L 1390 517"/>
+ <text x="1359" y="495" style="font-size:15">3,232,0,X,0</text>
+ <path class="ps3" d="M 1394 496 L 1397 477 L 1336 458 L 1329 475 L 1394 496"/>
+ <text x="1364" y="476" style="font-size:14">3,233,0,X,0</text>
+ <path class="ps3" d="M 1322 491 L 1329 475 L 1267 454 L 1257 467 L 1322 491"/>
+ <text x="1293" y="471" style="font-size:14">3,234,0,X,0</text>
+ <line x1="1257" y1="467" x2="1267" y2="454"/>
+ <path class="ps3" d="M 1329 475 L 1336 458 L 1277 441 L 1267 454 L 1329 475"/>
+ <text x="1302" y="457" style="font-size:14">3,235,0,X,0</text>
+ <line x1="1267" y1="454" x2="1277" y2="441"/>
+ <path class="ps3" d="M 1397 477 L 1401 457 L 1343 443 L 1336 458 L 1397 477"/>
+ <text x="1369" y="459" style="font-size:14">3,236,0,X,0</text>
+ <path class="ps3" d="M 1401 457 L 1404 439 L 1350 427 L 1343 443 L 1401 457"/>
+ <text x="1374" y="441" style="font-size:13">3,237,0,X,0</text>
+ <path class="ps3" d="M 1336 458 L 1343 443 L 1287 428 L 1277 441 L 1336 458"/>
+ <text x="1311" y="442" style="font-size:13">3,238,0,X,0</text>
+ <line x1="1277" y1="441" x2="1287" y2="428"/>
+ <path class="ps3" d="M 1343 443 L 1350 427 L 1297 416 L 1287 428 L 1343 443"/>
+ <text x="1319" y="428" style="font-size:13">3,239,0,X,0</text>
+ <line x1="1287" y1="428" x2="1297" y2="416"/>
+ <path class="ps3" d="M 1516 462 L 1512 437 L 1459 429 L 1460 450 L 1516 462"/>
+ <text x="1486" y="445" style="font-size:13">3,240,0,X,0</text>
+ <path class="ps3" d="M 1512 437 L 1507 414 L 1459 408 L 1459 429 L 1512 437"/>
+ <text x="1484" y="422" style="font-size:12">3,241,0,X,0</text>
+ <path class="ps3" d="M 1460 450 L 1459 429 L 1407 420 L 1404 439 L 1460 450"/>
+ <text x="1432" y="434" style="font-size:13">3,242,0,X,0</text>
+ <path class="ps3" d="M 1459 429 L 1459 408 L 1410 403 L 1407 420 L 1459 429"/>
+ <text x="1434" y="415" style="font-size:12">3,243,0,X,0</text>
+ <path class="ps3" d="M 1507 414 L 1503 391 L 1458 389 L 1459 408 L 1507 414"/>
+ <text x="1482" y="400" style="font-size:12">3,244,0,X,0</text>
+ <path class="ps3" d="M 1503 391 L 1500 370 L 1458 370 L 1458 389 L 1503 391"/>
+ <text x="1480" y="380" style="font-size:11">3,245,0,X,0</text>
+ <path class="ps3" d="M 1459 408 L 1458 389 L 1413 386 L 1410 403 L 1459 408"/>
+ <text x="1435" y="396" style="font-size:12">3,246,0,X,0</text>
+ <path class="ps3" d="M 1458 389 L 1458 370 L 1416 370 L 1413 386 L 1458 389"/>
+ <text x="1436" y="378" style="font-size:11">3,247,0,X,0</text>
+ <path class="ps3" d="M 1404 439 L 1407 420 L 1356 412 L 1350 427 L 1404 439"/>
+ <text x="1379" y="425" style="font-size:13">3,248,0,X,0</text>
+ <path class="ps3" d="M 1407 420 L 1410 403 L 1363 398 L 1356 412 L 1407 420"/>
+ <text x="1384" y="408" style="font-size:12">3,249,0,X,0</text>
+ <path class="ps3" d="M 1350 427 L 1356 412 L 1306 404 L 1297 416 L 1350 427"/>
+ <text x="1327" y="415" style="font-size:13">3,250,0,X,0</text>
+ <line x1="1297" y1="416" x2="1306" y2="404"/>
+ <path class="ps3" d="M 1356 412 L 1363 398 L 1315 392 L 1306 404 L 1356 412"/>
+ <text x="1335" y="401" style="font-size:12">3,251,0,X,0</text>
+ <line x1="1306" y1="404" x2="1315" y2="392"/>
+ <path class="ps3" d="M 1410 403 L 1413 386 L 1369 383 L 1363 398 L 1410 403"/>
+ <text x="1389" y="392" style="font-size:12">3,252,0,X,0</text>
+ <path class="ps3" d="M 1413 386 L 1416 370 L 1375 370 L 1369 383 L 1413 386"/>
+ <text x="1393" y="377" style="font-size:11">3,253,0,X,0</text>
+ <path class="ps3" d="M 1363 398 L 1369 383 L 1324 381 L 1315 392 L 1363 398"/>
+ <text x="1343" y="388" style="font-size:12">3,254,0,X,0</text>
+ <line x1="1315" y1="392" x2="1324" y2="381"/>
+ <path class="ps3" d="M 1369 383 L 1375 370 L 1333 370 L 1324 381 L 1369 383"/>
+ <text x="1350" y="376" style="font-size:12">3,255,0,X,0</text>
+ <line x1="1324" y1="381" x2="1333" y2="370"/>
+ <path class="p3" d="M 1583 370 L 1566 344 L 1525 346 L 1541 370 L 1583 370"/>
+ <text x="1554" y="357" style="font-size:11">3,256,0,0,0</text>
+ <path class="p3" d="M 1566 344 L 1550 319 L 1509 324 L 1525 346 L 1566 344"/>
+ <text x="1537" y="333" style="font-size:10">3,257,0,0,0</text>
+ <path class="p3" d="M 1541 370 L 1525 346 L 1484 349 L 1500 370 L 1541 370"/>
+ <text x="1512" y="358" style="font-size:11">3,258,0,0,0</text>
+ <path class="p3" d="M 1525 346 L 1509 324 L 1469 328 L 1484 349 L 1525 346"/>
+ <text x="1497" y="337" style="font-size:10">3,259,0,0,0</text>
+ <path class="p3" d="M 1550 319 L 1534 296 L 1495 302 L 1509 324 L 1550 319"/>
+ <text x="1522" y="310" style="font-size:10">3,260,0,0,0</text>
+ <path class="p3" d="M 1534 296 L 1520 273 L 1480 282 L 1495 302 L 1534 296"/>
+ <text x="1507" y="288" style="font-size:9">3,261,0,0,0</text>
+ <path class="p3" d="M 1509 324 L 1495 302 L 1454 309 L 1469 328 L 1509 324"/>
+ <text x="1482" y="316" style="font-size:10">3,262,0,0,0</text>
+ <path class="p3" d="M 1495 302 L 1480 282 L 1440 290 L 1454 309 L 1495 302"/>
+ <text x="1467" y="296" style="font-size:9">3,263,0,0,0</text>
+ <path class="p3" d="M 1520 273 L 1506 252 L 1467 262 L 1480 282 L 1520 273"/>
+ <text x="1493" y="267" style="font-size:9">3,264,0,0,0</text>
+ <path class="p3" d="M 1506 252 L 1492 231 L 1453 243 L 1467 262 L 1506 252"/>
+ <text x="1479" y="247" style="font-size:8">3,265,0,0,0</text>
+ <path class="p3" d="M 1480 282 L 1467 262 L 1427 273 L 1440 290 L 1480 282"/>
+ <text x="1454" y="277" style="font-size:9">3,266,0,0,0</text>
+ <path class="p3" d="M 1467 262 L 1453 243 L 1414 255 L 1427 273 L 1467 262"/>
+ <text x="1440" y="258" style="font-size:8">3,267,0,0,0</text>
+ <path class="p3" d="M 1350 191 L 1291 191 L 1267 204 L 1321 205 L 1350 191"/>
+ <text x="1307" y="198" style="font-size:7">3,268,0,0,0</text>
+ <path class="p3" d="M 1291 191 L 1233 190 L 1213 202 L 1267 204 L 1291 191"/>
+ <text x="1251" y="197" style="font-size:7">3,269,0,0,0</text>
+ <path class="p3" d="M 1321 205 L 1267 204 L 1242 217 L 1291 219 L 1321 205"/>
+ <text x="1280" y="211" style="font-size:8">3,270,0,0,0</text>
+ <path class="p3" d="M 1267 204 L 1213 202 L 1193 215 L 1242 217 L 1267 204"/>
+ <text x="1229" y="210" style="font-size:8">3,271,0,0,0</text>
+ <path class="p3" d="M 1233 190 L 1174 189 L 1160 201 L 1213 202 L 1233 190"/>
+ <text x="1195" y="195" style="font-size:7">3,272,0,0,0</text>
+ <path class="p3" d="M 1174 189 L 1116 188 L 1106 200 L 1160 201 L 1174 189"/>
+ <text x="1139" y="194" style="font-size:7">3,273,0,0,0</text>
+ <path class="p3" d="M 1213 202 L 1160 201 L 1145 214 L 1193 215 L 1213 202"/>
+ <text x="1178" y="208" style="font-size:8">3,274,0,0,0</text>
+ <path class="p3" d="M 1160 201 L 1106 200 L 1096 212 L 1145 214 L 1160 201"/>
+ <text x="1127" y="207" style="font-size:8">3,275,0,0,0</text>
+ <path class="p3" d="M 1116 188 L 1058 187 L 1053 199 L 1106 200 L 1116 188"/>
+ <text x="1083" y="193" style="font-size:7">3,276,0,0,0</text>
+ <path class="p3" d="M 1058 187 L 1000 187 L 1000 197 L 1053 199 L 1058 187"/>
+ <text x="1028" y="192" style="font-size:7">3,277,0,0,0</text>
+ <path class="p3" d="M 1106 200 L 1053 199 L 1048 210 L 1096 212 L 1106 200"/>
+ <text x="1076" y="205" style="font-size:7">3,278,0,0,0</text>
+ <path class="p3" d="M 1053 199 L 1000 197 L 1000 209 L 1048 210 L 1053 199"/>
+ <text x="1025" y="204" style="font-size:7">3,279,0,0,0</text>
+ <path class="p3" d="M 1000 187 L 942 187 L 947 199 L 1000 197 L 1000 187"/>
+ <text x="972" y="192" style="font-size:7">3,280,0,0,0</text>
+ <path class="p3" d="M 942 187 L 884 188 L 894 200 L 947 199 L 942 187"/>
+ <text x="917" y="193" style="font-size:7">3,281,0,0,0</text>
+ <path class="p3" d="M 1000 197 L 947 199 L 952 210 L 1000 209 L 1000 197"/>
+ <text x="975" y="204" style="font-size:7">3,282,0,0,0</text>
+ <path class="p3" d="M 947 199 L 894 200 L 904 212 L 952 210 L 947 199"/>
+ <text x="924" y="205" style="font-size:7">3,283,0,0,0</text>
+ <path class="p3" d="M 884 188 L 826 189 L 840 201 L 894 200 L 884 188"/>
+ <text x="861" y="194" style="font-size:7">3,284,0,0,0</text>
+ <path class="p3" d="M 826 189 L 767 190 L 787 202 L 840 201 L 826 189"/>
+ <text x="805" y="195" style="font-size:7">3,285,0,0,0</text>
+ <path class="p3" d="M 894 200 L 840 201 L 855 214 L 904 212 L 894 200"/>
+ <text x="873" y="207" style="font-size:8">3,286,0,0,0</text>
+ <path class="p3" d="M 840 201 L 787 202 L 807 215 L 855 214 L 840 201"/>
+ <text x="822" y="208" style="font-size:8">3,287,0,0,0</text>
+ <path class="p3" d="M 767 190 L 709 191 L 733 204 L 787 202 L 767 190"/>
+ <text x="749" y="197" style="font-size:7">3,288,0,0,0</text>
+ <path class="p3" d="M 709 191 L 650 191 L 679 205 L 733 204 L 709 191"/>
+ <text x="693" y="198" style="font-size:7">3,289,0,0,0</text>
+ <path class="p3" d="M 787 202 L 733 204 L 758 217 L 807 215 L 787 202"/>
+ <text x="771" y="210" style="font-size:8">3,290,0,0,0</text>
+ <path class="p3" d="M 733 204 L 679 205 L 709 219 L 758 217 L 733 204"/>
+ <text x="720" y="211" style="font-size:8">3,291,0,0,0</text>
+ <path class="p3" d="M 508 231 L 494 252 L 533 262 L 547 243 L 508 231"/>
+ <text x="521" y="247" style="font-size:8">3,292,0,0,0</text>
+ <path class="p3" d="M 494 252 L 480 273 L 520 282 L 533 262 L 494 252"/>
+ <text x="507" y="267" style="font-size:9">3,293,0,0,0</text>
+ <path class="p3" d="M 547 243 L 533 262 L 573 273 L 586 255 L 547 243"/>
+ <text x="560" y="258" style="font-size:8">3,294,0,0,0</text>
+ <path class="p3" d="M 533 262 L 520 282 L 560 290 L 573 273 L 533 262"/>
+ <text x="546" y="277" style="font-size:9">3,295,0,0,0</text>
+ <path class="p3" d="M 480 273 L 466 296 L 505 302 L 520 282 L 480 273"/>
+ <text x="493" y="288" style="font-size:9">3,296,0,0,0</text>
+ <path class="p3" d="M 466 296 L 450 319 L 491 324 L 505 302 L 466 296"/>
+ <text x="478" y="310" style="font-size:10">3,297,0,0,0</text>
+ <path class="p3" d="M 520 282 L 505 302 L 546 309 L 560 290 L 520 282"/>
+ <text x="533" y="296" style="font-size:9">3,298,0,0,0</text>
+ <path class="p3" d="M 505 302 L 491 324 L 531 328 L 546 309 L 505 302"/>
+ <text x="518" y="316" style="font-size:10">3,299,0,0,0</text>
+ <path class="p3" d="M 450 319 L 434 344 L 475 346 L 491 324 L 450 319"/>
+ <text x="463" y="333" style="font-size:10">3,300,0,0,0</text>
+ <path class="p3" d="M 434 344 L 417 370 L 459 370 L 475 346 L 434 344"/>
+ <text x="446" y="357" style="font-size:11">3,301,0,0,0</text>
+ <path class="p3" d="M 491 324 L 475 346 L 516 349 L 531 328 L 491 324"/>
+ <text x="503" y="337" style="font-size:10">3,302,0,0,0</text>
+ <path class="p3" d="M 475 346 L 459 370 L 500 370 L 516 349 L 475 346"/>
+ <text x="488" y="358" style="font-size:11">3,303,0,0,0</text>
+ <path class="p3" d="M 417 370 L 406 397 L 451 394 L 459 370 L 417 370"/>
+ <text x="433" y="382" style="font-size:11">3,304,0,0,0</text>
+ <path class="p3" d="M 406 397 L 394 425 L 443 419 L 451 394 L 406 397"/>
+ <text x="424" y="409" style="font-size:12">3,305,0,0,0</text>
+ <path class="p3" d="M 459 370 L 451 394 L 497 391 L 500 370 L 459 370"/>
+ <text x="477" y="381" style="font-size:11">3,306,0,0,0</text>
+ <path class="p3" d="M 451 394 L 443 419 L 493 414 L 497 391 L 451 394"/>
+ <text x="471" y="404" style="font-size:12">3,307,0,0,0</text>
+ <path class="p3" d="M 394 425 L 381 455 L 435 446 L 443 419 L 394 425"/>
+ <text x="413" y="436" style="font-size:13">3,308,0,0,0</text>
+ <path class="p3" d="M 381 455 L 367 487 L 426 474 L 435 446 L 381 455"/>
+ <text x="402" y="465" style="font-size:13">3,309,0,0,0</text>
+ <path class="p3" d="M 443 419 L 435 446 L 488 437 L 493 414 L 443 419"/>
+ <text x="465" y="429" style="font-size:13">3,310,0,0,0</text>
+ <path class="p3" d="M 435 446 L 426 474 L 484 462 L 488 437 L 435 446"/>
+ <text x="459" y="455" style="font-size:13">3,311,0,0,0</text>
+ <path class="p3" d="M 367 487 L 353 520 L 417 504 L 426 474 L 367 487"/>
+ <text x="391" y="496" style="font-size:14">3,312,0,0,0</text>
+ <path class="p3" d="M 353 520 L 338 555 L 407 535 L 417 504 L 353 520"/>
+ <text x="379" y="528" style="font-size:15">3,313,0,0,0</text>
+ <path class="p3" d="M 426 474 L 417 504 L 479 488 L 484 462 L 426 474"/>
+ <text x="452" y="482" style="font-size:14">3,314,0,0,0</text>
+ <path class="p3" d="M 417 504 L 407 535 L 475 515 L 479 488 L 417 504"/>
+ <text x="445" y="510" style="font-size:15">3,315,0,0,0</text>
+ <path class="p3" d="M 478 636 L 564 638 L 614 609 L 538 607 L 478 636"/>
+ <text x="549" y="622" style="font-size:18">3,316,0,0,0</text>
+ <path class="p3" d="M 564 638 L 651 639 L 691 612 L 614 609 L 564 638"/>
+ <text x="630" y="624" style="font-size:18">3,317,0,0,0</text>
+ <path class="p3" d="M 538 607 L 614 609 L 663 582 L 596 579 L 538 607"/>
+ <text x="603" y="594" style="font-size:17">3,318,0,0,0</text>
+ <path class="p3" d="M 614 609 L 691 612 L 729 585 L 663 582 L 614 609"/>
+ <text x="675" y="597" style="font-size:17">3,319,0,0,0</text>
+ <path class="p3" d="M 651 639 L 738 641 L 768 614 L 691 612 L 651 639"/>
+ <text x="712" y="627" style="font-size:18">3,320,0,0,0</text>
+ <path class="p3" d="M 738 641 L 825 643 L 845 617 L 768 614 L 738 641"/>
+ <text x="794" y="629" style="font-size:18">3,321,0,0,0</text>
+ <path class="p3" d="M 691 612 L 768 614 L 797 589 L 729 585 L 691 612"/>
+ <text x="746" y="600" style="font-size:17">3,322,0,0,0</text>
+ <path class="p3" d="M 768 614 L 845 617 L 864 592 L 797 589 L 768 614"/>
+ <text x="818" y="603" style="font-size:18">3,323,0,0,0</text>
+ <path class="p3" d="M 825 643 L 912 645 L 922 620 L 845 617 L 825 643"/>
+ <text x="876" y="631" style="font-size:18">3,324,0,0,0</text>
+ <path class="p3" d="M 912 645 L 1000 647 L 1000 622 L 922 620 L 912 645"/>
+ <text x="959" y="633" style="font-size:18">3,325,0,0,0</text>
+ <path class="p3" d="M 845 617 L 922 620 L 932 595 L 864 592 L 845 617"/>
+ <text x="891" y="606" style="font-size:18">3,326,0,0,0</text>
+ <path class="p3" d="M 922 620 L 1000 622 L 1000 599 L 932 595 L 922 620"/>
+ <text x="964" y="609" style="font-size:18">3,327,0,0,0</text>
+ <path class="p3" d="M 1000 647 L 1088 645 L 1078 620 L 1000 622 L 1000 647"/>
+ <text x="1041" y="633" style="font-size:18">3,328,0,0,0</text>
+ <path class="p3" d="M 1088 645 L 1175 643 L 1155 617 L 1078 620 L 1088 645"/>
+ <text x="1124" y="631" style="font-size:18">3,329,0,0,0</text>
+ <path class="p3" d="M 1000 622 L 1078 620 L 1068 595 L 1000 599 L 1000 622"/>
+ <text x="1036" y="609" style="font-size:18">3,330,0,0,0</text>
+ <path class="p3" d="M 1078 620 L 1155 617 L 1136 592 L 1068 595 L 1078 620"/>
+ <text x="1109" y="606" style="font-size:18">3,331,0,0,0</text>
+ <path class="p3" d="M 1175 643 L 1262 641 L 1232 614 L 1155 617 L 1175 643"/>
+ <text x="1206" y="629" style="font-size:18">3,332,0,0,0</text>
+ <path class="p3" d="M 1262 641 L 1349 639 L 1309 612 L 1232 614 L 1262 641"/>
+ <text x="1288" y="627" style="font-size:18">3,333,0,0,0</text>
+ <path class="p3" d="M 1155 617 L 1232 614 L 1203 589 L 1136 592 L 1155 617"/>
+ <text x="1182" y="603" style="font-size:18">3,334,0,0,0</text>
+ <path class="p3" d="M 1232 614 L 1309 612 L 1271 585 L 1203 589 L 1232 614"/>
+ <text x="1254" y="600" style="font-size:17">3,335,0,0,0</text>
+ <path class="p3" d="M 1349 639 L 1436 638 L 1386 609 L 1309 612 L 1349 639"/>
+ <text x="1370" y="624" style="font-size:18">3,336,0,0,0</text>
+ <path class="p3" d="M 1436 638 L 1522 636 L 1462 607 L 1386 609 L 1436 638"/>
+ <text x="1451" y="622" style="font-size:18">3,337,0,0,0</text>
+ <path class="p3" d="M 1309 612 L 1386 609 L 1337 582 L 1271 585 L 1309 612"/>
+ <text x="1325" y="597" style="font-size:17">3,338,0,0,0</text>
+ <path class="p3" d="M 1386 609 L 1462 607 L 1404 579 L 1337 582 L 1386 609"/>
+ <text x="1397" y="594" style="font-size:17">3,339,0,0,0</text>
+ <path class="p3" d="M 1662 555 L 1647 520 L 1583 504 L 1593 535 L 1662 555"/>
+ <text x="1621" y="528" style="font-size:15">3,340,0,0,0</text>
+ <path class="p3" d="M 1647 520 L 1633 487 L 1574 474 L 1583 504 L 1647 520"/>
+ <text x="1609" y="496" style="font-size:14">3,341,0,0,0</text>
+ <path class="p3" d="M 1593 535 L 1583 504 L 1521 488 L 1525 515 L 1593 535"/>
+ <text x="1555" y="510" style="font-size:15">3,342,0,0,0</text>
+ <path class="p3" d="M 1583 504 L 1574 474 L 1516 462 L 1521 488 L 1583 504"/>
+ <text x="1548" y="482" style="font-size:14">3,343,0,0,0</text>
+ <path class="p3" d="M 1633 487 L 1619 455 L 1565 446 L 1574 474 L 1633 487"/>
+ <text x="1598" y="465" style="font-size:13">3,344,0,0,0</text>
+ <path class="p3" d="M 1619 455 L 1606 425 L 1557 419 L 1565 446 L 1619 455"/>
+ <text x="1587" y="436" style="font-size:13">3,345,0,0,0</text>
+ <path class="p3" d="M 1574 474 L 1565 446 L 1512 437 L 1516 462 L 1574 474"/>
+ <text x="1541" y="455" style="font-size:13">3,346,0,0,0</text>
+ <path class="p3" d="M 1565 446 L 1557 419 L 1507 414 L 1512 437 L 1565 446"/>
+ <text x="1535" y="429" style="font-size:13">3,347,0,0,0</text>
+ <path class="p3" d="M 1606 425 L 1594 397 L 1549 394 L 1557 419 L 1606 425"/>
+ <text x="1576" y="409" style="font-size:12">3,348,0,0,0</text>
+ <path class="p3" d="M 1594 397 L 1583 370 L 1541 370 L 1549 394 L 1594 397"/>
+ <text x="1567" y="382" style="font-size:11">3,349,0,0,0</text>
+ <path class="p3" d="M 1557 419 L 1549 394 L 1503 391 L 1507 414 L 1557 419"/>
+ <text x="1529" y="404" style="font-size:12">3,350,0,0,0</text>
+ <path class="p3" d="M 1549 394 L 1541 370 L 1500 370 L 1503 391 L 1549 394"/>
+ <text x="1523" y="381" style="font-size:11">3,351,0,0,0</text>
+ <path class="p4" d="M 1513 241 L 1505 232 L 1484 232 L 1492 241 L 1513 241"/>
+ <text x="1499" y="237" style="font-size:6">4,0,0,0,0</text>
+ <path class="p4" d="M 1505 232 L 1497 222 L 1476 224 L 1484 232 L 1505 232"/>
+ <text x="1490" y="228" style="font-size:6">4,1,0,0,0</text>
+ <path class="p4" d="M 1492 241 L 1484 232 L 1463 233 L 1471 241 L 1492 241"/>
+ <text x="1477" y="237" style="font-size:6">4,2,0,0,0</text>
+ <path class="p4" d="M 1484 232 L 1476 224 L 1455 225 L 1463 233 L 1484 232"/>
+ <text x="1469" y="228" style="font-size:6">4,3,0,0,0</text>
+ <path class="p4" d="M 1497 222 L 1489 213 L 1468 215 L 1476 224 L 1497 222"/>
+ <text x="1483" y="219" style="font-size:5">4,4,0,0,0</text>
+ <path class="p4" d="M 1489 213 L 1481 204 L 1460 206 L 1468 215 L 1489 213"/>
+ <text x="1475" y="210" style="font-size:5">4,5,0,0,0</text>
+ <path class="p4" d="M 1476 224 L 1468 215 L 1447 217 L 1455 225 L 1476 224"/>
+ <text x="1461" y="220" style="font-size:6">4,6,0,0,0</text>
+ <path class="p4" d="M 1468 215 L 1460 206 L 1439 209 L 1447 217 L 1468 215"/>
+ <text x="1454" y="212" style="font-size:5">4,7,0,0,0</text>
+ <path class="p4" d="M 1471 241 L 1463 233 L 1441 233 L 1449 241 L 1471 241"/>
+ <text x="1456" y="237" style="font-size:6">4,8,0,0,0</text>
+ <path class="p4" d="M 1463 233 L 1455 225 L 1433 226 L 1441 233 L 1463 233"/>
+ <text x="1448" y="229" style="font-size:6">4,9,0,0,0</text>
+ <path class="p4" d="M 1449 241 L 1441 233 L 1420 234 L 1428 241 L 1449 241"/>
+ <text x="1435" y="238" style="font-size:6">4,10,0,0,0</text>
+ <path class="p4" d="M 1441 233 L 1433 226 L 1412 227 L 1420 234 L 1441 233"/>
+ <text x="1427" y="230" style="font-size:6">4,11,0,0,0</text>
+ <path class="p4" d="M 1455 225 L 1447 217 L 1426 218 L 1433 226 L 1455 225"/>
+ <text x="1440" y="221" style="font-size:6">4,12,0,0,0</text>
+ <path class="p4" d="M 1447 217 L 1439 209 L 1418 211 L 1426 218 L 1447 217"/>
+ <text x="1432" y="213" style="font-size:5">4,13,0,0,0</text>
+ <path class="p4" d="M 1433 226 L 1426 218 L 1404 220 L 1412 227 L 1433 226"/>
+ <text x="1419" y="223" style="font-size:6">4,14,0,0,0</text>
+ <path class="p4" d="M 1426 218 L 1418 211 L 1397 213 L 1404 220 L 1426 218"/>
+ <text x="1411" y="215" style="font-size:5">4,15,0,0,0</text>
+ <path class="p4" d="M 1481 204 L 1474 195 L 1453 198 L 1460 206 L 1481 204"/>
+ <text x="1467" y="201" style="font-size:5">4,16,0,0,0</text>
+ <path class="p4" d="M 1474 195 L 1466 187 L 1445 190 L 1453 198 L 1474 195"/>
+ <text x="1459" y="193" style="font-size:5">4,17,0,0,0</text>
+ <path class="p4" d="M 1460 206 L 1453 198 L 1432 201 L 1439 209 L 1460 206"/>
+ <text x="1446" y="203" style="font-size:5">4,18,0,0,0</text>
+ <path class="p4" d="M 1453 198 L 1445 190 L 1424 193 L 1432 201 L 1453 198"/>
+ <text x="1439" y="195" style="font-size:5">4,19,0,0,0</text>
+ <path class="p4" d="M 1466 187 L 1459 178 L 1438 182 L 1445 190 L 1466 187"/>
+ <text x="1452" y="184" style="font-size:5">4,20,0,0,0</text>
+ <path class="p4" d="M 1459 178 L 1452 170 L 1431 174 L 1438 182 L 1459 178"/>
+ <text x="1445" y="176" style="font-size:5">4,21,0,0,0</text>
+ <path class="p4" d="M 1445 190 L 1438 182 L 1417 185 L 1424 193 L 1445 190"/>
+ <text x="1431" y="187" style="font-size:5">4,22,0,0,0</text>
+ <path class="p4" d="M 1438 182 L 1431 174 L 1410 178 L 1417 185 L 1438 182"/>
+ <text x="1424" y="180" style="font-size:5">4,23,0,0,0</text>
+ <path class="p4" d="M 1439 209 L 1432 201 L 1411 203 L 1418 211 L 1439 209"/>
+ <text x="1425" y="206" style="font-size:5">4,24,0,0,0</text>
+ <path class="p4" d="M 1432 201 L 1424 193 L 1403 196 L 1411 203 L 1432 201"/>
+ <text x="1417" y="198" style="font-size:5">4,25,0,0,0</text>
+ <path class="p4" d="M 1418 211 L 1411 203 L 1389 206 L 1397 213 L 1418 211"/>
+ <text x="1404" y="208" style="font-size:5">4,26,0,0,0</text>
+ <path class="p4" d="M 1411 203 L 1403 196 L 1382 199 L 1389 206 L 1411 203"/>
+ <text x="1396" y="201" style="font-size:5">4,27,0,0,0</text>
+ <path class="p4" d="M 1424 193 L 1417 185 L 1396 189 L 1403 196 L 1424 193"/>
+ <text x="1410" y="191" style="font-size:5">4,28,0,0,0</text>
+ <path class="p4" d="M 1417 185 L 1410 178 L 1389 182 L 1396 189 L 1417 185"/>
+ <text x="1403" y="184" style="font-size:5">4,29,0,0,0</text>
+ <path class="p4" d="M 1403 196 L 1396 189 L 1375 193 L 1382 199 L 1403 196"/>
+ <text x="1389" y="194" style="font-size:5">4,30,0,0,0</text>
+ <path class="p4" d="M 1396 189 L 1389 182 L 1368 186 L 1375 193 L 1396 189"/>
+ <text x="1382" y="187" style="font-size:5">4,31,0,0,0</text>
+ <path class="p4" d="M 1428 241 L 1420 234 L 1399 235 L 1406 241 L 1428 241"/>
+ <text x="1413" y="238" style="font-size:6">4,32,0,0,0</text>
+ <path class="p4" d="M 1420 234 L 1412 227 L 1391 228 L 1399 235 L 1420 234"/>
+ <text x="1405" y="231" style="font-size:6">4,33,0,0,0</text>
+ <path class="p4" d="M 1406 241 L 1399 235 L 1377 235 L 1385 241 L 1406 241"/>
+ <text x="1392" y="238" style="font-size:6">4,34,0,0,0</text>
+ <path class="p4" d="M 1399 235 L 1391 228 L 1369 229 L 1377 235 L 1399 235"/>
+ <text x="1384" y="232" style="font-size:6">4,35,0,0,0</text>
+ <path class="p4" d="M 1412 227 L 1404 220 L 1383 221 L 1391 228 L 1412 227"/>
+ <text x="1398" y="224" style="font-size:6">4,36,0,0,0</text>
+ <path class="p4" d="M 1404 220 L 1397 213 L 1375 215 L 1383 221 L 1404 220"/>
+ <text x="1390" y="217" style="font-size:6">4,37,0,0,0</text>
+ <path class="p4" d="M 1391 228 L 1383 221 L 1362 223 L 1369 229 L 1391 228"/>
+ <text x="1376" y="225" style="font-size:6">4,38,0,0,0</text>
+ <path class="p4" d="M 1383 221 L 1375 215 L 1354 217 L 1362 223 L 1383 221"/>
+ <text x="1368" y="219" style="font-size:6">4,39,0,0,0</text>
+ <path class="p4" d="M 1385 241 L 1377 235 L 1356 236 L 1364 241 L 1385 241"/>
+ <text x="1370" y="238" style="font-size:6">4,40,0,0,0</text>
+ <path class="p4" d="M 1377 235 L 1369 229 L 1348 230 L 1356 236 L 1377 235"/>
+ <text x="1362" y="233" style="font-size:6">4,41,0,0,0</text>
+ <path class="p4" d="M 1364 241 L 1356 236 L 1334 236 L 1342 241 L 1364 241"/>
+ <text x="1349" y="239" style="font-size:6">4,42,0,0,0</text>
+ <line x1="1342" y1="241" x2="1334" y2="236"/>
+ <path class="p4" d="M 1356 236 L 1348 230 L 1326 231 L 1334 236 L 1356 236"/>
+ <text x="1341" y="233" style="font-size:6">4,43,0,0,0</text>
+ <line x1="1334" y1="236" x2="1326" y2="231"/>
+ <path class="p4" d="M 1369 229 L 1362 223 L 1340 225 L 1348 230 L 1369 229"/>
+ <text x="1355" y="227" style="font-size:6">4,44,0,0,0</text>
+ <path class="p4" d="M 1362 223 L 1354 217 L 1332 219 L 1340 225 L 1362 223"/>
+ <text x="1347" y="221" style="font-size:6">4,45,0,0,0</text>
+ <path class="p4" d="M 1348 230 L 1340 225 L 1318 226 L 1326 231 L 1348 230"/>
+ <text x="1333" y="228" style="font-size:6">4,46,0,0,0</text>
+ <line x1="1326" y1="231" x2="1318" y2="226"/>
+ <path class="p4" d="M 1340 225 L 1332 219 L 1311 222 L 1318 226 L 1340 225"/>
+ <text x="1325" y="223" style="font-size:6">4,47,0,0,0</text>
+ <line x1="1318" y1="226" x2="1311" y2="222"/>
+ <path class="p4" d="M 1397 213 L 1389 206 L 1368 209 L 1375 215 L 1397 213"/>
+ <text x="1382" y="211" style="font-size:5">4,48,0,0,0</text>
+ <path class="p4" d="M 1389 206 L 1382 199 L 1360 202 L 1368 209 L 1389 206"/>
+ <text x="1375" y="204" style="font-size:5">4,49,0,0,0</text>
+ <path class="p4" d="M 1375 215 L 1368 209 L 1346 211 L 1354 217 L 1375 215"/>
+ <text x="1361" y="213" style="font-size:6">4,50,0,0,0</text>
+ <path class="p4" d="M 1368 209 L 1360 202 L 1339 206 L 1346 211 L 1368 209"/>
+ <text x="1353" y="207" style="font-size:5">4,51,0,0,0</text>
+ <path class="p4" d="M 1382 199 L 1375 193 L 1353 196 L 1360 202 L 1382 199"/>
+ <text x="1368" y="198" style="font-size:5">4,52,0,0,0</text>
+ <path class="p4" d="M 1375 193 L 1368 186 L 1346 190 L 1353 196 L 1375 193"/>
+ <text x="1360" y="191" style="font-size:5">4,53,0,0,0</text>
+ <path class="p4" d="M 1360 202 L 1353 196 L 1332 200 L 1339 206 L 1360 202"/>
+ <text x="1346" y="201" style="font-size:5">4,54,0,0,0</text>
+ <path class="p4" d="M 1353 196 L 1346 190 L 1324 194 L 1332 200 L 1353 196"/>
+ <text x="1339" y="195" style="font-size:5">4,55,0,0,0</text>
+ <path class="p4" d="M 1354 217 L 1346 211 L 1325 214 L 1332 219 L 1354 217"/>
+ <text x="1339" y="215" style="font-size:6">4,56,0,0,0</text>
+ <path class="p4" d="M 1346 211 L 1339 206 L 1317 209 L 1325 214 L 1346 211"/>
+ <text x="1332" y="210" style="font-size:5">4,57,0,0,0</text>
+ <path class="p4" d="M 1332 219 L 1325 214 L 1303 217 L 1311 222 L 1332 219"/>
+ <text x="1318" y="218" style="font-size:6">4,58,0,0,0</text>
+ <line x1="1311" y1="222" x2="1303" y2="217"/>
+ <path class="p4" d="M 1325 214 L 1317 209 L 1295 212 L 1303 217 L 1325 214"/>
+ <text x="1310" y="213" style="font-size:6">4,59,0,0,0</text>
+ <line x1="1303" y1="217" x2="1295" y2="212"/>
+ <path class="p4" d="M 1339 206 L 1332 200 L 1310 204 L 1317 209 L 1339 206"/>
+ <text x="1324" y="204" style="font-size:5">4,60,0,0,0</text>
+ <path class="p4" d="M 1332 200 L 1324 194 L 1302 198 L 1310 204 L 1332 200"/>
+ <text x="1317" y="199" style="font-size:5">4,61,0,0,0</text>
+ <path class="p4" d="M 1317 209 L 1310 204 L 1288 207 L 1295 212 L 1317 209"/>
+ <text x="1302" y="208" style="font-size:5">4,62,0,0,0</text>
+ <line x1="1295" y1="212" x2="1288" y2="207"/>
+ <path class="p4" d="M 1310 204 L 1302 198 L 1280 203 L 1288 207 L 1310 204"/>
+ <text x="1295" y="203" style="font-size:5">4,63,0,0,0</text>
+ <line x1="1288" y1="207" x2="1280" y2="203"/>
+ <path class="p4" d="M 1452 170 L 1445 162 L 1424 166 L 1431 174 L 1452 170"/>
+ <text x="1438" y="168" style="font-size:5">4,64,0,0,0</text>
+ <path class="p4" d="M 1445 162 L 1438 154 L 1417 159 L 1424 166 L 1445 162"/>
+ <text x="1431" y="160" style="font-size:5">4,65,0,0,0</text>
+ <path class="p4" d="M 1431 174 L 1424 166 L 1403 171 L 1410 178 L 1431 174"/>
+ <text x="1417" y="172" style="font-size:5">4,66,0,0,0</text>
+ <path class="p4" d="M 1424 166 L 1417 159 L 1396 163 L 1403 171 L 1424 166"/>
+ <text x="1410" y="165" style="font-size:5">4,67,0,0,0</text>
+ <path class="p4" d="M 1438 154 L 1431 146 L 1410 151 L 1417 159 L 1438 154"/>
+ <text x="1424" y="152" style="font-size:5">4,68,0,0,0</text>
+ <path class="p4" d="M 1431 146 L 1424 138 L 1403 144 L 1410 151 L 1431 146"/>
+ <text x="1417" y="145" style="font-size:4">4,69,0,0,0</text>
+ <path class="p4" d="M 1417 159 L 1410 151 L 1389 156 L 1396 163 L 1417 159"/>
+ <text x="1403" y="157" style="font-size:5">4,70,0,0,0</text>
+ <path class="p4" d="M 1410 151 L 1403 144 L 1383 149 L 1389 156 L 1410 151"/>
+ <text x="1396" y="150" style="font-size:5">4,71,0,0,0</text>
+ <path class="p4" d="M 1410 178 L 1403 171 L 1382 175 L 1389 182 L 1410 178"/>
+ <text x="1396" y="176" style="font-size:5">4,72,0,0,0</text>
+ <path class="p4" d="M 1403 171 L 1396 163 L 1375 168 L 1382 175 L 1403 171"/>
+ <text x="1389" y="169" style="font-size:5">4,73,0,0,0</text>
+ <path class="p4" d="M 1389 182 L 1382 175 L 1360 180 L 1368 186 L 1389 182"/>
+ <text x="1375" y="181" style="font-size:5">4,74,0,0,0</text>
+ <path class="p4" d="M 1382 175 L 1375 168 L 1353 173 L 1360 180 L 1382 175"/>
+ <text x="1368" y="174" style="font-size:5">4,75,0,0,0</text>
+ <path class="p4" d="M 1396 163 L 1389 156 L 1368 162 L 1375 168 L 1396 163"/>
+ <text x="1382" y="162" style="font-size:5">4,76,0,0,0</text>
+ <path class="p4" d="M 1389 156 L 1383 149 L 1361 155 L 1368 162 L 1389 156"/>
+ <text x="1375" y="155" style="font-size:5">4,77,0,0,0</text>
+ <path class="p4" d="M 1375 168 L 1368 162 L 1347 167 L 1353 173 L 1375 168"/>
+ <text x="1361" y="167" style="font-size:5">4,78,0,0,0</text>
+ <path class="p4" d="M 1368 162 L 1361 155 L 1340 161 L 1347 167 L 1368 162"/>
+ <text x="1354" y="161" style="font-size:5">4,79,0,0,0</text>
+ <path class="p4" d="M 1383 149 L 1376 142 L 1355 148 L 1361 155 L 1383 149"/>
+ <text x="1369" y="149" style="font-size:5">4,80,0,0,0</text>
+ <path class="p4" d="M 1376 142 L 1369 136 L 1348 142 L 1355 148 L 1376 142"/>
+ <text x="1362" y="142" style="font-size:4">4,81,0,0,0</text>
+ <path class="p4" d="M 1361 155 L 1355 148 L 1333 155 L 1340 161 L 1361 155"/>
+ <text x="1347" y="155" style="font-size:5">4,82,0,0,0</text>
+ <path class="p4" d="M 1355 148 L 1348 142 L 1327 149 L 1333 155 L 1355 148"/>
+ <text x="1341" y="148" style="font-size:5">4,83,0,0,0</text>
+ <path class="p4" d="M 1369 136 L 1363 129 L 1342 136 L 1348 142 L 1369 136"/>
+ <text x="1356" y="136" style="font-size:4">4,84,0,0,0</text>
+ <path class="p4" d="M 1363 129 L 1357 122 L 1335 130 L 1342 136 L 1363 129"/>
+ <text x="1349" y="129" style="font-size:4">4,85,0,0,0</text>
+ <path class="p4" d="M 1348 142 L 1342 136 L 1320 143 L 1327 149 L 1348 142"/>
+ <text x="1334" y="142" style="font-size:4">4,86,0,0,0</text>
+ <path class="p4" d="M 1342 136 L 1335 130 L 1314 137 L 1320 143 L 1342 136"/>
+ <text x="1328" y="136" style="font-size:4">4,87,0,0,0</text>
+ <path class="p4" d="M 1368 186 L 1360 180 L 1339 184 L 1346 190 L 1368 186"/>
+ <text x="1353" y="185" style="font-size:5">4,88,0,0,0</text>
+ <path class="p4" d="M 1360 180 L 1353 173 L 1332 178 L 1339 184 L 1360 180"/>
+ <text x="1346" y="179" style="font-size:5">4,89,0,0,0</text>
+ <path class="p4" d="M 1346 190 L 1339 184 L 1317 189 L 1324 194 L 1346 190"/>
+ <text x="1332" y="189" style="font-size:5">4,90,0,0,0</text>
+ <path class="p4" d="M 1339 184 L 1332 178 L 1310 183 L 1317 189 L 1339 184"/>
+ <text x="1324" y="184" style="font-size:5">4,91,0,0,0</text>
+ <path class="p4" d="M 1353 173 L 1347 167 L 1325 172 L 1332 178 L 1353 173"/>
+ <text x="1339" y="173" style="font-size:5">4,92,0,0,0</text>
+ <path class="p4" d="M 1347 167 L 1340 161 L 1318 167 L 1325 172 L 1347 167"/>
+ <text x="1332" y="167" style="font-size:5">4,93,0,0,0</text>
+ <path class="p4" d="M 1332 178 L 1325 172 L 1303 178 L 1310 183 L 1332 178"/>
+ <text x="1317" y="178" style="font-size:5">4,94,0,0,0</text>
+ <path class="p4" d="M 1325 172 L 1318 167 L 1296 172 L 1303 178 L 1325 172"/>
+ <text x="1311" y="172" style="font-size:5">4,95,0,0,0</text>
+ <path class="p4" d="M 1324 194 L 1317 189 L 1295 193 L 1302 198 L 1324 194"/>
+ <text x="1310" y="194" style="font-size:5">4,96,0,0,0</text>
+ <path class="p4" d="M 1317 189 L 1310 183 L 1288 188 L 1295 193 L 1317 189"/>
+ <text x="1303" y="188" style="font-size:5">4,97,0,0,0</text>
+ <path class="p4" d="M 1302 198 L 1295 193 L 1273 198 L 1280 203 L 1302 198"/>
+ <text x="1288" y="198" style="font-size:5">4,98,0,0,0</text>
+ <line x1="1280" y1="203" x2="1273" y2="198"/>
+ <path class="p4" d="M 1295 193 L 1288 188 L 1266 193 L 1273 198 L 1295 193"/>
+ <text x="1280" y="193" style="font-size:5">4,99,0,0,0</text>
+ <line x1="1273" y1="198" x2="1266" y2="193"/>
+ <path class="p4" d="M 1310 183 L 1303 178 L 1281 183 L 1288 188 L 1310 183"/>
+ <text x="1295" y="183" style="font-size:5">4,100,0,0,0</text>
+ <path class="p4" d="M 1303 178 L 1296 172 L 1274 178 L 1281 183 L 1303 178"/>
+ <text x="1288" y="178" style="font-size:5">4,101,0,0,0</text>
+ <path class="p4" d="M 1288 188 L 1281 183 L 1258 189 L 1266 193 L 1288 188"/>
+ <text x="1273" y="189" style="font-size:5">4,102,0,0,0</text>
+ <line x1="1266" y1="193" x2="1258" y2="189"/>
+ <path class="p4" d="M 1281 183 L 1274 178 L 1251 184 L 1258 189 L 1281 183"/>
+ <text x="1266" y="184" style="font-size:5">4,103,0,0,0</text>
+ <line x1="1258" y1="189" x2="1251" y2="184"/>
+ <path class="p4" d="M 1340 161 L 1333 155 L 1311 161 L 1318 167 L 1340 161"/>
+ <text x="1326" y="161" style="font-size:5">4,104,0,0,0</text>
+ <path class="p4" d="M 1333 155 L 1327 149 L 1305 155 L 1311 161 L 1333 155"/>
+ <text x="1319" y="155" style="font-size:5">4,105,0,0,0</text>
+ <path class="p4" d="M 1318 167 L 1311 161 L 1289 167 L 1296 172 L 1318 167"/>
+ <text x="1304" y="167" style="font-size:5">4,106,0,0,0</text>
+ <path class="p4" d="M 1311 161 L 1305 155 L 1282 162 L 1289 167 L 1311 161"/>
+ <text x="1297" y="161" style="font-size:5">4,107,0,0,0</text>
+ <path class="p4" d="M 1327 149 L 1320 143 L 1298 150 L 1305 155 L 1327 149"/>
+ <text x="1312" y="149" style="font-size:5">4,108,0,0,0</text>
+ <path class="p4" d="M 1320 143 L 1314 137 L 1292 144 L 1298 150 L 1320 143"/>
+ <text x="1306" y="143" style="font-size:5">4,109,0,0,0</text>
+ <path class="p4" d="M 1305 155 L 1298 150 L 1276 157 L 1282 162 L 1305 155"/>
+ <text x="1290" y="156" style="font-size:5">4,110,0,0,0</text>
+ <path class="p4" d="M 1298 150 L 1292 144 L 1269 152 L 1276 157 L 1298 150"/>
+ <text x="1284" y="151" style="font-size:5">4,111,0,0,0</text>
+ <path class="p4" d="M 1296 172 L 1289 167 L 1267 174 L 1274 178 L 1296 172"/>
+ <text x="1281" y="173" style="font-size:5">4,112,0,0,0</text>
+ <path class="p4" d="M 1289 167 L 1282 162 L 1260 169 L 1267 174 L 1289 167"/>
+ <text x="1275" y="168" style="font-size:5">4,113,0,0,0</text>
+ <path class="p4" d="M 1274 178 L 1267 174 L 1244 180 L 1251 184 L 1274 178"/>
+ <text x="1259" y="179" style="font-size:5">4,114,0,0,0</text>
+ <line x1="1251" y1="184" x2="1244" y2="180"/>
+ <path class="p4" d="M 1267 174 L 1260 169 L 1237 176 L 1244 180 L 1267 174"/>
+ <text x="1252" y="174" style="font-size:5">4,115,0,0,0</text>
+ <line x1="1244" y1="180" x2="1237" y2="176"/>
+ <path class="p4" d="M 1282 162 L 1276 157 L 1253 164 L 1260 169 L 1282 162"/>
+ <text x="1268" y="163" style="font-size:5">4,116,0,0,0</text>
+ <path class="p4" d="M 1276 157 L 1269 152 L 1246 159 L 1253 164 L 1276 157"/>
+ <text x="1261" y="158" style="font-size:5">4,117,0,0,0</text>
+ <path class="p4" d="M 1260 169 L 1253 164 L 1230 171 L 1237 176 L 1260 169"/>
+ <text x="1245" y="170" style="font-size:5">4,118,0,0,0</text>
+ <line x1="1237" y1="176" x2="1230" y2="171"/>
+ <path class="p4" d="M 1253 164 L 1246 159 L 1223 167 L 1230 171 L 1253 164"/>
+ <text x="1238" y="165" style="font-size:5">4,119,0,0,0</text>
+ <line x1="1230" y1="171" x2="1223" y2="167"/>
+ <path class="p4" d="M 1357 122 L 1334 121 L 1314 128 L 1335 130 L 1357 122"/>
+ <text x="1335" y="125" style="font-size:4">4,120,0,0,0</text>
+ <path class="p4" d="M 1334 121 L 1311 120 L 1293 127 L 1314 128 L 1334 121"/>
+ <text x="1313" y="124" style="font-size:4">4,121,0,0,0</text>
+ <path class="p4" d="M 1335 130 L 1314 128 L 1294 136 L 1314 137 L 1335 130"/>
+ <text x="1314" y="133" style="font-size:4">4,122,0,0,0</text>
+ <path class="p4" d="M 1314 128 L 1293 127 L 1274 134 L 1294 136 L 1314 128"/>
+ <text x="1294" y="131" style="font-size:4">4,123,0,0,0</text>
+ <path class="p4" d="M 1311 120 L 1289 119 L 1272 126 L 1293 127 L 1311 120"/>
+ <text x="1291" y="123" style="font-size:4">4,124,0,0,0</text>
+ <path class="p4" d="M 1289 119 L 1266 118 L 1250 125 L 1272 126 L 1289 119"/>
+ <text x="1269" y="122" style="font-size:4">4,125,0,0,0</text>
+ <path class="p4" d="M 1293 127 L 1272 126 L 1254 133 L 1274 134 L 1293 127"/>
+ <text x="1273" y="130" style="font-size:4">4,126,0,0,0</text>
+ <path class="p4" d="M 1272 126 L 1250 125 L 1234 132 L 1254 133 L 1272 126"/>
+ <text x="1252" y="129" style="font-size:4">4,127,0,0,0</text>
+ <path class="p4" d="M 1298 105 L 1273 105 L 1258 111 L 1282 112 L 1298 105"/>
+ <text x="1278" y="108" style="font-size:4">4,128,0,0,0</text>
+ <path class="p4" d="M 1273 105 L 1248 104 L 1235 110 L 1258 111 L 1273 105"/>
+ <text x="1253" y="107" style="font-size:4">4,129,0,0,0</text>
+ <path class="p4" d="M 1282 112 L 1258 111 L 1244 117 L 1266 118 L 1282 112"/>
+ <text x="1263" y="115" style="font-size:4">4,130,0,0,0</text>
+ <path class="p4" d="M 1258 111 L 1235 110 L 1221 116 L 1244 117 L 1258 111"/>
+ <text x="1240" y="114" style="font-size:4">4,131,0,0,0</text>
+ <path class="p4" d="M 1248 104 L 1223 103 L 1211 109 L 1235 110 L 1248 104"/>
+ <text x="1229" y="107" style="font-size:4">4,132,0,0,0</text>
+ <path class="p4" d="M 1223 103 L 1198 102 L 1187 108 L 1211 109 L 1223 103"/>
+ <text x="1205" y="106" style="font-size:4">4,133,0,0,0</text>
+ <path class="p4" d="M 1235 110 L 1211 109 L 1199 116 L 1221 116 L 1235 110"/>
+ <text x="1217" y="113" style="font-size:4">4,134,0,0,0</text>
+ <path class="p4" d="M 1211 109 L 1187 108 L 1177 115 L 1199 116 L 1211 109"/>
+ <text x="1194" y="112" style="font-size:4">4,135,0,0,0</text>
+ <path class="p4" d="M 1266 118 L 1244 117 L 1229 124 L 1250 125 L 1266 118"/>
+ <text x="1247" y="121" style="font-size:4">4,136,0,0,0</text>
+ <path class="p4" d="M 1244 117 L 1221 116 L 1208 123 L 1229 124 L 1244 117"/>
+ <text x="1226" y="120" style="font-size:4">4,137,0,0,0</text>
+ <path class="p4" d="M 1250 125 L 1229 124 L 1214 131 L 1234 132 L 1250 125"/>
+ <text x="1232" y="128" style="font-size:4">4,138,0,0,0</text>
+ <path class="p4" d="M 1229 124 L 1208 123 L 1194 129 L 1214 131 L 1229 124"/>
+ <text x="1211" y="127" style="font-size:4">4,139,0,0,0</text>
+ <path class="p4" d="M 1221 116 L 1199 116 L 1187 122 L 1208 123 L 1221 116"/>
+ <text x="1204" y="119" style="font-size:4">4,140,0,0,0</text>
+ <path class="p4" d="M 1199 116 L 1177 115 L 1166 121 L 1187 122 L 1199 116"/>
+ <text x="1182" y="118" style="font-size:4">4,141,0,0,0</text>
+ <path class="p4" d="M 1208 123 L 1187 122 L 1175 128 L 1194 129 L 1208 123"/>
+ <text x="1191" y="126" style="font-size:4">4,142,0,0,0</text>
+ <path class="p4" d="M 1187 122 L 1166 121 L 1155 127 L 1175 128 L 1187 122"/>
+ <text x="1171" y="124" style="font-size:4">4,143,0,0,0</text>
+ <path class="p4" d="M 1314 137 L 1294 136 L 1273 143 L 1292 144 L 1314 137"/>
+ <text x="1293" y="140" style="font-size:4">4,144,0,0,0</text>
+ <path class="p4" d="M 1294 136 L 1274 134 L 1254 141 L 1273 143 L 1294 136"/>
+ <text x="1274" y="138" style="font-size:4">4,145,0,0,0</text>
+ <path class="p4" d="M 1292 144 L 1273 143 L 1252 150 L 1269 152 L 1292 144"/>
+ <text x="1272" y="147" style="font-size:5">4,146,0,0,0</text>
+ <path class="p4" d="M 1273 143 L 1254 141 L 1235 149 L 1252 150 L 1273 143"/>
+ <text x="1254" y="146" style="font-size:5">4,147,0,0,0</text>
+ <path class="p4" d="M 1274 134 L 1254 133 L 1236 140 L 1254 141 L 1274 134"/>
+ <text x="1255" y="137" style="font-size:4">4,148,0,0,0</text>
+ <path class="p4" d="M 1254 133 L 1234 132 L 1217 139 L 1236 140 L 1254 133"/>
+ <text x="1235" y="136" style="font-size:4">4,149,0,0,0</text>
+ <path class="p4" d="M 1254 141 L 1236 140 L 1218 147 L 1235 149 L 1254 141"/>
+ <text x="1236" y="144" style="font-size:5">4,150,0,0,0</text>
+ <path class="p4" d="M 1236 140 L 1217 139 L 1201 146 L 1218 147 L 1236 140"/>
+ <text x="1218" y="143" style="font-size:5">4,151,0,0,0</text>
+ <path class="p4" d="M 1269 152 L 1252 150 L 1231 158 L 1246 159 L 1269 152"/>
+ <text x="1250" y="155" style="font-size:5">4,152,0,0,0</text>
+ <path class="p4" d="M 1252 150 L 1235 149 L 1215 156 L 1231 158 L 1252 150"/>
+ <text x="1233" y="153" style="font-size:5">4,153,0,0,0</text>
+ <path class="p4" d="M 1246 159 L 1231 158 L 1209 165 L 1223 167 L 1246 159"/>
+ <text x="1227" y="162" style="font-size:5">4,154,0,0,0</text>
+ <line x1="1223" y1="167" x2="1209" y2="165"/>
+ <path class="p4" d="M 1231 158 L 1215 156 L 1194 163 L 1209 165 L 1231 158"/>
+ <text x="1212" y="161" style="font-size:5">4,155,0,0,0</text>
+ <line x1="1209" y1="165" x2="1194" y2="163"/>
+ <path class="p4" d="M 1235 149 L 1218 147 L 1199 154 L 1215 156 L 1235 149"/>
+ <text x="1217" y="152" style="font-size:5">4,156,0,0,0</text>
+ <path class="p4" d="M 1218 147 L 1201 146 L 1183 153 L 1199 154 L 1218 147"/>
+ <text x="1200" y="150" style="font-size:5">4,157,0,0,0</text>
+ <path class="p4" d="M 1215 156 L 1199 154 L 1180 162 L 1194 163 L 1215 156"/>
+ <text x="1197" y="159" style="font-size:5">4,158,0,0,0</text>
+ <line x1="1194" y1="163" x2="1180" y2="162"/>
+ <path class="p4" d="M 1199 154 L 1183 153 L 1166 160 L 1180 162 L 1199 154"/>
+ <text x="1182" y="157" style="font-size:5">4,159,0,0,0</text>
+ <line x1="1180" y1="162" x2="1166" y2="160"/>
+ <path class="p4" d="M 1234 132 L 1214 131 L 1199 137 L 1217 139 L 1234 132"/>
+ <text x="1216" y="135" style="font-size:4">4,160,0,0,0</text>
+ <path class="p4" d="M 1214 131 L 1194 129 L 1181 136 L 1199 137 L 1214 131"/>
+ <text x="1197" y="133" style="font-size:4">4,161,0,0,0</text>
+ <path class="p4" d="M 1217 139 L 1199 137 L 1183 144 L 1201 146 L 1217 139"/>
+ <text x="1200" y="141" style="font-size:5">4,162,0,0,0</text>
+ <path class="p4" d="M 1199 137 L 1181 136 L 1167 143 L 1183 144 L 1199 137"/>
+ <text x="1182" y="140" style="font-size:5">4,163,0,0,0</text>
+ <path class="p4" d="M 1194 129 L 1175 128 L 1162 135 L 1181 136 L 1194 129"/>
+ <text x="1178" y="132" style="font-size:4">4,164,0,0,0</text>
+ <path class="p4" d="M 1175 128 L 1155 127 L 1144 133 L 1162 135 L 1175 128"/>
+ <text x="1159" y="131" style="font-size:4">4,165,0,0,0</text>
+ <path class="p4" d="M 1181 136 L 1162 135 L 1150 141 L 1167 143 L 1181 136"/>
+ <text x="1165" y="139" style="font-size:5">4,166,0,0,0</text>
+ <path class="p4" d="M 1162 135 L 1144 133 L 1133 140 L 1150 141 L 1162 135"/>
+ <text x="1147" y="137" style="font-size:4">4,167,0,0,0</text>
+ <path class="p4" d="M 1201 146 L 1183 144 L 1168 151 L 1183 153 L 1201 146"/>
+ <text x="1184" y="148" style="font-size:5">4,168,0,0,0</text>
+ <path class="p4" d="M 1183 144 L 1167 143 L 1152 150 L 1168 151 L 1183 144"/>
+ <text x="1168" y="147" style="font-size:5">4,169,0,0,0</text>
+ <path class="p4" d="M 1183 153 L 1168 151 L 1152 158 L 1166 160 L 1183 153"/>
+ <text x="1167" y="156" style="font-size:5">4,170,0,0,0</text>
+ <line x1="1166" y1="160" x2="1152" y2="158"/>
+ <path class="p4" d="M 1168 151 L 1152 150 L 1138 156 L 1152 158 L 1168 151"/>
+ <text x="1152" y="154" style="font-size:5">4,171,0,0,0</text>
+ <line x1="1152" y1="158" x2="1138" y2="156"/>
+ <path class="p4" d="M 1167 143 L 1150 141 L 1137 148 L 1152 150 L 1167 143"/>
+ <text x="1151" y="145" style="font-size:5">4,172,0,0,0</text>
+ <path class="p4" d="M 1150 141 L 1133 140 L 1121 146 L 1137 148 L 1150 141"/>
+ <text x="1135" y="144" style="font-size:5">4,173,0,0,0</text>
+ <path class="p4" d="M 1152 150 L 1137 148 L 1124 155 L 1138 156 L 1152 150"/>
+ <text x="1138" y="152" style="font-size:5">4,174,0,0,0</text>
+ <line x1="1138" y1="156" x2="1124" y2="155"/>
+ <path class="p4" d="M 1137 148 L 1121 146 L 1110 153 L 1124 155 L 1137 148"/>
+ <text x="1123" y="151" style="font-size:5">4,175,0,0,0</text>
+ <line x1="1124" y1="155" x2="1110" y2="153"/>
+ <path class="p4" d="M 1198 102 L 1173 102 L 1164 108 L 1187 108 L 1198 102"/>
+ <text x="1180" y="105" style="font-size:4">4,176,0,0,0</text>
+ <path class="p4" d="M 1173 102 L 1148 101 L 1140 107 L 1164 108 L 1173 102"/>
+ <text x="1156" y="104" style="font-size:4">4,177,0,0,0</text>
+ <path class="p4" d="M 1187 108 L 1164 108 L 1154 114 L 1177 115 L 1187 108"/>
+ <text x="1171" y="111" style="font-size:4">4,178,0,0,0</text>
+ <path class="p4" d="M 1164 108 L 1140 107 L 1132 113 L 1154 114 L 1164 108"/>
+ <text x="1148" y="110" style="font-size:4">4,179,0,0,0</text>
+ <path class="p4" d="M 1148 101 L 1123 100 L 1117 106 L 1140 107 L 1148 101"/>
+ <text x="1132" y="103" style="font-size:4">4,180,0,0,0</text>
+ <path class="p4" d="M 1123 100 L 1098 99 L 1093 105 L 1117 106 L 1123 100"/>
+ <text x="1108" y="103" style="font-size:4">4,181,0,0,0</text>
+ <path class="p4" d="M 1140 107 L 1117 106 L 1110 112 L 1132 113 L 1140 107"/>
+ <text x="1125" y="109" style="font-size:4">4,182,0,0,0</text>
+ <path class="p4" d="M 1117 106 L 1093 105 L 1088 111 L 1110 112 L 1117 106"/>
+ <text x="1102" y="108" style="font-size:4">4,183,0,0,0</text>
+ <path class="p4" d="M 1177 115 L 1154 114 L 1145 120 L 1166 121 L 1177 115"/>
+ <text x="1161" y="117" style="font-size:4">4,184,0,0,0</text>
+ <path class="p4" d="M 1154 114 L 1132 113 L 1124 119 L 1145 120 L 1154 114"/>
+ <text x="1139" y="116" style="font-size:4">4,185,0,0,0</text>
+ <path class="p4" d="M 1166 121 L 1145 120 L 1135 126 L 1155 127 L 1166 121"/>
+ <text x="1150" y="123" style="font-size:4">4,186,0,0,0</text>
+ <path class="p4" d="M 1145 120 L 1124 119 L 1116 125 L 1135 126 L 1145 120"/>
+ <text x="1130" y="122" style="font-size:4">4,187,0,0,0</text>
+ <path class="p4" d="M 1132 113 L 1110 112 L 1103 117 L 1124 119 L 1132 113"/>
+ <text x="1117" y="115" style="font-size:4">4,188,0,0,0</text>
+ <path class="p4" d="M 1110 112 L 1088 111 L 1083 116 L 1103 117 L 1110 112"/>
+ <text x="1096" y="114" style="font-size:4">4,189,0,0,0</text>
+ <path class="p4" d="M 1124 119 L 1103 117 L 1097 123 L 1116 125 L 1124 119"/>
+ <text x="1110" y="121" style="font-size:4">4,190,0,0,0</text>
+ <path class="p4" d="M 1103 117 L 1083 116 L 1077 122 L 1097 123 L 1103 117"/>
+ <text x="1090" y="120" style="font-size:4">4,191,0,0,0</text>
+ <path class="p4" d="M 1098 99 L 1074 99 L 1070 104 L 1093 105 L 1098 99"/>
+ <text x="1084" y="102" style="font-size:4">4,192,0,0,0</text>
+ <path class="p4" d="M 1074 99 L 1049 98 L 1047 103 L 1070 104 L 1074 99"/>
+ <text x="1060" y="101" style="font-size:4">4,193,0,0,0</text>
+ <path class="p4" d="M 1093 105 L 1070 104 L 1066 110 L 1088 111 L 1093 105"/>
+ <text x="1079" y="107" style="font-size:4">4,194,0,0,0</text>
+ <path class="p4" d="M 1070 104 L 1047 103 L 1044 109 L 1066 110 L 1070 104"/>
+ <text x="1057" y="106" style="font-size:4">4,195,0,0,0</text>
+ <path class="p4" d="M 1049 98 L 1025 97 L 1023 102 L 1047 103 L 1049 98"/>
+ <text x="1036" y="100" style="font-size:4">4,196,0,0,0</text>
+ <path class="p4" d="M 1025 97 L 1000 96 L 1000 102 L 1023 102 L 1025 97"/>
+ <text x="1012" y="99" style="font-size:4">4,197,0,0,0</text>
+ <path class="p4" d="M 1047 103 L 1023 102 L 1022 108 L 1044 109 L 1047 103"/>
+ <text x="1034" y="106" style="font-size:4">4,198,0,0,0</text>
+ <path class="p4" d="M 1023 102 L 1000 102 L 1000 107 L 1022 108 L 1023 102"/>
+ <text x="1011" y="105" style="font-size:4">4,199,0,0,0</text>
+ <path class="p4" d="M 1088 111 L 1066 110 L 1062 115 L 1083 116 L 1088 111"/>
+ <text x="1075" y="113" style="font-size:4">4,200,0,0,0</text>
+ <path class="p4" d="M 1066 110 L 1044 109 L 1041 114 L 1062 115 L 1066 110"/>
+ <text x="1053" y="112" style="font-size:4">4,201,0,0,0</text>
+ <path class="p4" d="M 1083 116 L 1062 115 L 1058 121 L 1077 122 L 1083 116"/>
+ <text x="1070" y="119" style="font-size:4">4,202,0,0,0</text>
+ <path class="p4" d="M 1062 115 L 1041 114 L 1038 120 L 1058 121 L 1062 115"/>
+ <text x="1050" y="118" style="font-size:4">4,203,0,0,0</text>
+ <path class="p4" d="M 1044 109 L 1022 108 L 1021 113 L 1041 114 L 1044 109"/>
+ <text x="1032" y="111" style="font-size:4">4,204,0,0,0</text>
+ <path class="p4" d="M 1022 108 L 1000 107 L 1000 112 L 1021 113 L 1022 108"/>
+ <text x="1011" y="110" style="font-size:4">4,205,0,0,0</text>
+ <path class="p4" d="M 1041 114 L 1021 113 L 1019 119 L 1038 120 L 1041 114"/>
+ <text x="1030" y="116" style="font-size:4">4,206,0,0,0</text>
+ <path class="p4" d="M 1021 113 L 1000 112 L 1000 117 L 1019 119 L 1021 113"/>
+ <text x="1010" y="115" style="font-size:4">4,207,0,0,0</text>
+ <path class="p4" d="M 1155 127 L 1135 126 L 1126 132 L 1144 133 L 1155 127"/>
+ <text x="1140" y="130" style="font-size:4">4,208,0,0,0</text>
+ <path class="p4" d="M 1135 126 L 1116 125 L 1108 131 L 1126 132 L 1135 126"/>
+ <text x="1121" y="128" style="font-size:4">4,209,0,0,0</text>
+ <path class="p4" d="M 1144 133 L 1126 132 L 1116 138 L 1133 140 L 1144 133"/>
+ <text x="1130" y="136" style="font-size:4">4,210,0,0,0</text>
+ <path class="p4" d="M 1126 132 L 1108 131 L 1099 137 L 1116 138 L 1126 132"/>
+ <text x="1112" y="134" style="font-size:4">4,211,0,0,0</text>
+ <path class="p4" d="M 1116 125 L 1097 123 L 1090 129 L 1108 131 L 1116 125"/>
+ <text x="1102" y="127" style="font-size:4">4,212,0,0,0</text>
+ <path class="p4" d="M 1097 123 L 1077 122 L 1072 128 L 1090 129 L 1097 123"/>
+ <text x="1084" y="126" style="font-size:4">4,213,0,0,0</text>
+ <path class="p4" d="M 1108 131 L 1090 129 L 1083 135 L 1099 137 L 1108 131"/>
+ <text x="1095" y="133" style="font-size:4">4,214,0,0,0</text>
+ <path class="p4" d="M 1090 129 L 1072 128 L 1066 134 L 1083 135 L 1090 129"/>
+ <text x="1077" y="132" style="font-size:4">4,215,0,0,0</text>
+ <path class="p4" d="M 1133 140 L 1116 138 L 1106 145 L 1121 146 L 1133 140"/>
+ <text x="1119" y="142" style="font-size:5">4,216,0,0,0</text>
+ <path class="p4" d="M 1116 138 L 1099 137 L 1091 143 L 1106 145 L 1116 138"/>
+ <text x="1103" y="141" style="font-size:5">4,217,0,0,0</text>
+ <path class="p4" d="M 1121 146 L 1106 145 L 1096 151 L 1110 153 L 1121 146"/>
+ <text x="1108" y="149" style="font-size:5">4,218,0,0,0</text>
+ <line x1="1110" y1="153" x2="1096" y2="151"/>
+ <path class="p4" d="M 1106 145 L 1091 143 L 1082 150 L 1096 151 L 1106 145"/>
+ <text x="1094" y="147" style="font-size:5">4,219,0,0,0</text>
+ <line x1="1096" y1="151" x2="1082" y2="150"/>
+ <path class="p4" d="M 1099 137 L 1083 135 L 1075 142 L 1091 143 L 1099 137"/>
+ <text x="1087" y="139" style="font-size:5">4,220,0,0,0</text>
+ <path class="p4" d="M 1083 135 L 1066 134 L 1060 140 L 1075 142 L 1083 135"/>
+ <text x="1071" y="138" style="font-size:5">4,221,0,0,0</text>
+ <path class="p4" d="M 1091 143 L 1075 142 L 1068 148 L 1082 150 L 1091 143"/>
+ <text x="1079" y="146" style="font-size:5">4,222,0,0,0</text>
+ <line x1="1082" y1="150" x2="1068" y2="148"/>
+ <path class="p4" d="M 1075 142 L 1060 140 L 1054 146 L 1068 148 L 1075 142"/>
+ <text x="1065" y="144" style="font-size:5">4,223,0,0,0</text>
+ <line x1="1068" y1="148" x2="1054" y2="146"/>
+ <path class="p4" d="M 1077 122 L 1058 121 L 1054 127 L 1072 128 L 1077 122"/>
+ <text x="1065" y="124" style="font-size:4">4,224,0,0,0</text>
+ <path class="p4" d="M 1058 121 L 1038 120 L 1036 125 L 1054 127 L 1058 121"/>
+ <text x="1046" y="123" style="font-size:4">4,225,0,0,0</text>
+ <path class="p4" d="M 1072 128 L 1054 127 L 1049 133 L 1066 134 L 1072 128"/>
+ <text x="1060" y="130" style="font-size:4">4,226,0,0,0</text>
+ <path class="p4" d="M 1054 127 L 1036 125 L 1033 131 L 1049 133 L 1054 127"/>
+ <text x="1043" y="129" style="font-size:4">4,227,0,0,0</text>
+ <path class="p4" d="M 1038 120 L 1019 119 L 1018 124 L 1036 125 L 1038 120"/>
+ <text x="1028" y="122" style="font-size:4">4,228,0,0,0</text>
+ <path class="p4" d="M 1019 119 L 1000 117 L 1000 123 L 1018 124 L 1019 119"/>
+ <text x="1009" y="121" style="font-size:4">4,229,0,0,0</text>
+ <path class="p4" d="M 1036 125 L 1018 124 L 1016 130 L 1033 131 L 1036 125"/>
+ <text x="1026" y="128" style="font-size:4">4,230,0,0,0</text>
+ <path class="p4" d="M 1018 124 L 1000 123 L 1000 128 L 1016 130 L 1018 124"/>
+ <text x="1009" y="126" style="font-size:4">4,231,0,0,0</text>
+ <path class="p4" d="M 1066 134 L 1049 133 L 1045 139 L 1060 140 L 1066 134"/>
+ <text x="1055" y="136" style="font-size:4">4,232,0,0,0</text>
+ <path class="p4" d="M 1049 133 L 1033 131 L 1030 137 L 1045 139 L 1049 133"/>
+ <text x="1039" y="135" style="font-size:4">4,233,0,0,0</text>
+ <path class="p4" d="M 1060 140 L 1045 139 L 1041 145 L 1054 146 L 1060 140"/>
+ <text x="1050" y="142" style="font-size:5">4,234,0,0,0</text>
+ <line x1="1054" y1="146" x2="1041" y2="145"/>
+ <path class="p4" d="M 1045 139 L 1030 137 L 1027 143 L 1041 145 L 1045 139"/>
+ <text x="1036" y="141" style="font-size:5">4,235,0,0,0</text>
+ <line x1="1041" y1="145" x2="1027" y2="143"/>
+ <path class="p4" d="M 1033 131 L 1016 130 L 1015 135 L 1030 137 L 1033 131"/>
+ <text x="1024" y="133" style="font-size:4">4,236,0,0,0</text>
+ <path class="p4" d="M 1016 130 L 1000 128 L 1000 134 L 1015 135 L 1016 130"/>
+ <text x="1008" y="132" style="font-size:4">4,237,0,0,0</text>
+ <path class="p4" d="M 1030 137 L 1015 135 L 1014 141 L 1027 143 L 1030 137"/>
+ <text x="1021" y="139" style="font-size:5">4,238,0,0,0</text>
+ <line x1="1027" y1="143" x2="1014" y2="141"/>
+ <path class="p4" d="M 1015 135 L 1000 134 L 1000 140 L 1014 141 L 1015 135"/>
+ <text x="1007" y="137" style="font-size:5">4,239,0,0,0</text>
+ <line x1="1014" y1="141" x2="1000" y2="140"/>
+ <path class="p4" d="M 1000 96 L 975 97 L 977 102 L 1000 102 L 1000 96"/>
+ <text x="988" y="99" style="font-size:4">4,240,0,0,0</text>
+ <path class="p4" d="M 975 97 L 951 98 L 953 103 L 977 102 L 975 97"/>
+ <text x="964" y="100" style="font-size:4">4,241,0,0,0</text>
+ <path class="p4" d="M 1000 102 L 977 102 L 978 108 L 1000 107 L 1000 102"/>
+ <text x="989" y="105" style="font-size:4">4,242,0,0,0</text>
+ <path class="p4" d="M 977 102 L 953 103 L 956 109 L 978 108 L 977 102"/>
+ <text x="966" y="106" style="font-size:4">4,243,0,0,0</text>
+ <path class="p4" d="M 951 98 L 926 99 L 930 104 L 953 103 L 951 98"/>
+ <text x="940" y="101" style="font-size:4">4,244,0,0,0</text>
+ <path class="p4" d="M 926 99 L 902 99 L 907 105 L 930 104 L 926 99"/>
+ <text x="916" y="102" style="font-size:4">4,245,0,0,0</text>
+ <path class="p4" d="M 953 103 L 930 104 L 934 110 L 956 109 L 953 103"/>
+ <text x="943" y="106" style="font-size:4">4,246,0,0,0</text>
+ <path class="p4" d="M 930 104 L 907 105 L 912 111 L 934 110 L 930 104"/>
+ <text x="921" y="107" style="font-size:4">4,247,0,0,0</text>
+ <path class="p4" d="M 1000 107 L 978 108 L 979 113 L 1000 112 L 1000 107"/>
+ <text x="989" y="110" style="font-size:4">4,248,0,0,0</text>
+ <path class="p4" d="M 978 108 L 956 109 L 959 114 L 979 113 L 978 108"/>
+ <text x="968" y="111" style="font-size:4">4,249,0,0,0</text>
+ <path class="p4" d="M 1000 112 L 979 113 L 981 119 L 1000 117 L 1000 112"/>
+ <text x="990" y="115" style="font-size:4">4,250,0,0,0</text>
+ <path class="p4" d="M 979 113 L 959 114 L 962 120 L 981 119 L 979 113"/>
+ <text x="970" y="116" style="font-size:4">4,251,0,0,0</text>
+ <path class="p4" d="M 956 109 L 934 110 L 938 115 L 959 114 L 956 109"/>
+ <text x="947" y="112" style="font-size:4">4,252,0,0,0</text>
+ <path class="p4" d="M 934 110 L 912 111 L 917 116 L 938 115 L 934 110"/>
+ <text x="925" y="113" style="font-size:4">4,253,0,0,0</text>
+ <path class="p4" d="M 959 114 L 938 115 L 942 121 L 962 120 L 959 114"/>
+ <text x="950" y="118" style="font-size:4">4,254,0,0,0</text>
+ <path class="p4" d="M 938 115 L 917 116 L 923 122 L 942 121 L 938 115"/>
+ <text x="930" y="119" style="font-size:4">4,255,0,0,0</text>
+ <path class="p4" d="M 902 99 L 877 100 L 883 106 L 907 105 L 902 99"/>
+ <text x="892" y="103" style="font-size:4">4,256,0,0,0</text>
+ <path class="p4" d="M 877 100 L 852 101 L 860 107 L 883 106 L 877 100"/>
+ <text x="868" y="103" style="font-size:4">4,257,0,0,0</text>
+ <path class="p4" d="M 907 105 L 883 106 L 890 112 L 912 111 L 907 105"/>
+ <text x="898" y="108" style="font-size:4">4,258,0,0,0</text>
+ <path class="p4" d="M 883 106 L 860 107 L 868 113 L 890 112 L 883 106"/>
+ <text x="875" y="109" style="font-size:4">4,259,0,0,0</text>
+ <path class="p4" d="M 852 101 L 827 102 L 836 108 L 860 107 L 852 101"/>
+ <text x="844" y="104" style="font-size:4">4,260,0,0,0</text>
+ <path class="p4" d="M 827 102 L 802 102 L 813 108 L 836 108 L 827 102"/>
+ <text x="820" y="105" style="font-size:4">4,261,0,0,0</text>
+ <path class="p4" d="M 860 107 L 836 108 L 846 114 L 868 113 L 860 107"/>
+ <text x="852" y="110" style="font-size:4">4,262,0,0,0</text>
+ <path class="p4" d="M 836 108 L 813 108 L 823 115 L 846 114 L 836 108"/>
+ <text x="829" y="111" style="font-size:4">4,263,0,0,0</text>
+ <path class="p4" d="M 912 111 L 890 112 L 897 117 L 917 116 L 912 111"/>
+ <text x="904" y="114" style="font-size:4">4,264,0,0,0</text>
+ <path class="p4" d="M 890 112 L 868 113 L 876 119 L 897 117 L 890 112"/>
+ <text x="883" y="115" style="font-size:4">4,265,0,0,0</text>
+ <path class="p4" d="M 917 116 L 897 117 L 903 123 L 923 122 L 917 116"/>
+ <text x="910" y="120" style="font-size:4">4,266,0,0,0</text>
+ <path class="p4" d="M 897 117 L 876 119 L 884 125 L 903 123 L 897 117"/>
+ <text x="890" y="121" style="font-size:4">4,267,0,0,0</text>
+ <path class="p4" d="M 868 113 L 846 114 L 855 120 L 876 119 L 868 113"/>
+ <text x="861" y="116" style="font-size:4">4,268,0,0,0</text>
+ <path class="p4" d="M 846 114 L 823 115 L 834 121 L 855 120 L 846 114"/>
+ <text x="839" y="117" style="font-size:4">4,269,0,0,0</text>
+ <path class="p4" d="M 876 119 L 855 120 L 865 126 L 884 125 L 876 119"/>
+ <text x="870" y="122" style="font-size:4">4,270,0,0,0</text>
+ <path class="p4" d="M 855 120 L 834 121 L 845 127 L 865 126 L 855 120"/>
+ <text x="850" y="123" style="font-size:4">4,271,0,0,0</text>
+ <path class="p4" d="M 1000 117 L 981 119 L 982 124 L 1000 123 L 1000 117"/>
+ <text x="991" y="121" style="font-size:4">4,272,0,0,0</text>
+ <path class="p4" d="M 981 119 L 962 120 L 964 125 L 982 124 L 981 119"/>
+ <text x="972" y="122" style="font-size:4">4,273,0,0,0</text>
+ <path class="p4" d="M 1000 123 L 982 124 L 984 130 L 1000 128 L 1000 123"/>
+ <text x="991" y="126" style="font-size:4">4,274,0,0,0</text>
+ <path class="p4" d="M 982 124 L 964 125 L 967 131 L 984 130 L 982 124"/>
+ <text x="974" y="128" style="font-size:4">4,275,0,0,0</text>
+ <path class="p4" d="M 962 120 L 942 121 L 946 127 L 964 125 L 962 120"/>
+ <text x="954" y="123" style="font-size:4">4,276,0,0,0</text>
+ <path class="p4" d="M 942 121 L 923 122 L 928 128 L 946 127 L 942 121"/>
+ <text x="935" y="124" style="font-size:4">4,277,0,0,0</text>
+ <path class="p4" d="M 964 125 L 946 127 L 951 133 L 967 131 L 964 125"/>
+ <text x="957" y="129" style="font-size:4">4,278,0,0,0</text>
+ <path class="p4" d="M 946 127 L 928 128 L 934 134 L 951 133 L 946 127"/>
+ <text x="940" y="130" style="font-size:4">4,279,0,0,0</text>
+ <path class="p4" d="M 1000 128 L 984 130 L 985 135 L 1000 134 L 1000 128"/>
+ <text x="992" y="132" style="font-size:4">4,280,0,0,0</text>
+ <path class="p4" d="M 984 130 L 967 131 L 970 137 L 985 135 L 984 130"/>
+ <text x="976" y="133" style="font-size:4">4,281,0,0,0</text>
+ <path class="p4" d="M 1000 134 L 985 135 L 986 141 L 1000 140 L 1000 134"/>
+ <text x="993" y="137" style="font-size:5">4,282,0,0,0</text>
+ <line x1="1000" y1="140" x2="986" y2="141"/>
+ <path class="p4" d="M 985 135 L 970 137 L 973 143 L 986 141 L 985 135"/>
+ <text x="979" y="139" style="font-size:5">4,283,0,0,0</text>
+ <line x1="986" y1="141" x2="973" y2="143"/>
+ <path class="p4" d="M 967 131 L 951 133 L 955 139 L 970 137 L 967 131"/>
+ <text x="961" y="135" style="font-size:4">4,284,0,0,0</text>
+ <path class="p4" d="M 951 133 L 934 134 L 940 140 L 955 139 L 951 133"/>
+ <text x="945" y="136" style="font-size:4">4,285,0,0,0</text>
+ <path class="p4" d="M 970 137 L 955 139 L 959 145 L 973 143 L 970 137"/>
+ <text x="964" y="141" style="font-size:5">4,286,0,0,0</text>
+ <line x1="973" y1="143" x2="959" y2="145"/>
+ <path class="p4" d="M 955 139 L 940 140 L 946 146 L 959 145 L 955 139"/>
+ <text x="950" y="142" style="font-size:5">4,287,0,0,0</text>
+ <line x1="959" y1="145" x2="946" y2="146"/>
+ <path class="p4" d="M 923 122 L 903 123 L 910 129 L 928 128 L 923 122"/>
+ <text x="916" y="126" style="font-size:4">4,288,0,0,0</text>
+ <path class="p4" d="M 903 123 L 884 125 L 892 131 L 910 129 L 903 123"/>
+ <text x="898" y="127" style="font-size:4">4,289,0,0,0</text>
+ <path class="p4" d="M 928 128 L 910 129 L 917 135 L 934 134 L 928 128"/>
+ <text x="923" y="132" style="font-size:4">4,290,0,0,0</text>
+ <path class="p4" d="M 910 129 L 892 131 L 901 137 L 917 135 L 910 129"/>
+ <text x="905" y="133" style="font-size:4">4,291,0,0,0</text>
+ <path class="p4" d="M 884 125 L 865 126 L 874 132 L 892 131 L 884 125"/>
+ <text x="879" y="128" style="font-size:4">4,292,0,0,0</text>
+ <path class="p4" d="M 865 126 L 845 127 L 856 133 L 874 132 L 865 126"/>
+ <text x="860" y="130" style="font-size:4">4,293,0,0,0</text>
+ <path class="p4" d="M 892 131 L 874 132 L 884 138 L 901 137 L 892 131"/>
+ <text x="888" y="134" style="font-size:4">4,294,0,0,0</text>
+ <path class="p4" d="M 874 132 L 856 133 L 867 140 L 884 138 L 874 132"/>
+ <text x="870" y="136" style="font-size:4">4,295,0,0,0</text>
+ <path class="p4" d="M 934 134 L 917 135 L 925 142 L 940 140 L 934 134"/>
+ <text x="929" y="138" style="font-size:5">4,296,0,0,0</text>
+ <path class="p4" d="M 917 135 L 901 137 L 909 143 L 925 142 L 917 135"/>
+ <text x="913" y="139" style="font-size:5">4,297,0,0,0</text>
+ <path class="p4" d="M 940 140 L 925 142 L 932 148 L 946 146 L 940 140"/>
+ <text x="935" y="144" style="font-size:5">4,298,0,0,0</text>
+ <line x1="946" y1="146" x2="932" y2="148"/>
+ <path class="p4" d="M 925 142 L 909 143 L 918 150 L 932 148 L 925 142"/>
+ <text x="921" y="146" style="font-size:5">4,299,0,0,0</text>
+ <line x1="932" y1="148" x2="918" y2="150"/>
+ <path class="p4" d="M 901 137 L 884 138 L 894 145 L 909 143 L 901 137"/>
+ <text x="897" y="141" style="font-size:5">4,300,0,0,0</text>
+ <path class="p4" d="M 884 138 L 867 140 L 879 146 L 894 145 L 884 138"/>
+ <text x="881" y="142" style="font-size:5">4,301,0,0,0</text>
+ <path class="p4" d="M 909 143 L 894 145 L 904 151 L 918 150 L 909 143"/>
+ <text x="906" y="147" style="font-size:5">4,302,0,0,0</text>
+ <line x1="918" y1="150" x2="904" y2="151"/>
+ <path class="p4" d="M 894 145 L 879 146 L 890 153 L 904 151 L 894 145"/>
+ <text x="892" y="149" style="font-size:5">4,303,0,0,0</text>
+ <line x1="904" y1="151" x2="890" y2="153"/>
+ <path class="p4" d="M 802 102 L 777 103 L 789 109 L 813 108 L 802 102"/>
+ <text x="795" y="106" style="font-size:4">4,304,0,0,0</text>
+ <path class="p4" d="M 777 103 L 752 104 L 765 110 L 789 109 L 777 103"/>
+ <text x="771" y="107" style="font-size:4">4,305,0,0,0</text>
+ <path class="p4" d="M 813 108 L 789 109 L 801 116 L 823 115 L 813 108"/>
+ <text x="806" y="112" style="font-size:4">4,306,0,0,0</text>
+ <path class="p4" d="M 789 109 L 765 110 L 779 116 L 801 116 L 789 109"/>
+ <text x="783" y="113" style="font-size:4">4,307,0,0,0</text>
+ <path class="p4" d="M 752 104 L 727 105 L 742 111 L 765 110 L 752 104"/>
+ <text x="747" y="107" style="font-size:4">4,308,0,0,0</text>
+ <path class="p4" d="M 727 105 L 702 105 L 718 112 L 742 111 L 727 105"/>
+ <text x="722" y="108" style="font-size:4">4,309,0,0,0</text>
+ <path class="p4" d="M 765 110 L 742 111 L 756 117 L 779 116 L 765 110"/>
+ <text x="760" y="114" style="font-size:4">4,310,0,0,0</text>
+ <path class="p4" d="M 742 111 L 718 112 L 734 118 L 756 117 L 742 111"/>
+ <text x="737" y="115" style="font-size:4">4,311,0,0,0</text>
+ <path class="p4" d="M 823 115 L 801 116 L 813 122 L 834 121 L 823 115"/>
+ <text x="818" y="118" style="font-size:4">4,312,0,0,0</text>
+ <path class="p4" d="M 801 116 L 779 116 L 792 123 L 813 122 L 801 116"/>
+ <text x="796" y="119" style="font-size:4">4,313,0,0,0</text>
+ <path class="p4" d="M 834 121 L 813 122 L 825 128 L 845 127 L 834 121"/>
+ <text x="829" y="124" style="font-size:4">4,314,0,0,0</text>
+ <path class="p4" d="M 813 122 L 792 123 L 806 129 L 825 128 L 813 122"/>
+ <text x="809" y="126" style="font-size:4">4,315,0,0,0</text>
+ <path class="p4" d="M 779 116 L 756 117 L 771 124 L 792 123 L 779 116"/>
+ <text x="774" y="120" style="font-size:4">4,316,0,0,0</text>
+ <path class="p4" d="M 756 117 L 734 118 L 750 125 L 771 124 L 756 117"/>
+ <text x="753" y="121" style="font-size:4">4,317,0,0,0</text>
+ <path class="p4" d="M 792 123 L 771 124 L 786 131 L 806 129 L 792 123"/>
+ <text x="789" y="127" style="font-size:4">4,318,0,0,0</text>
+ <path class="p4" d="M 771 124 L 750 125 L 766 132 L 786 131 L 771 124"/>
+ <text x="768" y="128" style="font-size:4">4,319,0,0,0</text>
+ <path class="p4" d="M 734 118 L 711 119 L 728 126 L 750 125 L 734 118"/>
+ <text x="731" y="122" style="font-size:4">4,320,0,0,0</text>
+ <path class="p4" d="M 711 119 L 689 120 L 707 127 L 728 126 L 711 119"/>
+ <text x="709" y="123" style="font-size:4">4,321,0,0,0</text>
+ <path class="p4" d="M 750 125 L 728 126 L 746 133 L 766 132 L 750 125"/>
+ <text x="748" y="129" style="font-size:4">4,322,0,0,0</text>
+ <path class="p4" d="M 728 126 L 707 127 L 726 134 L 746 133 L 728 126"/>
+ <text x="727" y="130" style="font-size:4">4,323,0,0,0</text>
+ <path class="p4" d="M 689 120 L 666 121 L 686 128 L 707 127 L 689 120"/>
+ <text x="687" y="124" style="font-size:4">4,324,0,0,0</text>
+ <path class="p4" d="M 666 121 L 643 122 L 665 130 L 686 128 L 666 121"/>
+ <text x="665" y="125" style="font-size:4">4,325,0,0,0</text>
+ <path class="p4" d="M 707 127 L 686 128 L 706 136 L 726 134 L 707 127"/>
+ <text x="706" y="131" style="font-size:4">4,326,0,0,0</text>
+ <path class="p4" d="M 686 128 L 665 130 L 686 137 L 706 136 L 686 128"/>
+ <text x="686" y="133" style="font-size:4">4,327,0,0,0</text>
+ <path class="p4" d="M 845 127 L 825 128 L 838 135 L 856 133 L 845 127"/>
+ <text x="841" y="131" style="font-size:4">4,328,0,0,0</text>
+ <path class="p4" d="M 825 128 L 806 129 L 819 136 L 838 135 L 825 128"/>
+ <text x="822" y="132" style="font-size:4">4,329,0,0,0</text>
+ <path class="p4" d="M 856 133 L 838 135 L 850 141 L 867 140 L 856 133"/>
+ <text x="853" y="137" style="font-size:4">4,330,0,0,0</text>
+ <path class="p4" d="M 838 135 L 819 136 L 833 143 L 850 141 L 838 135"/>
+ <text x="835" y="139" style="font-size:5">4,331,0,0,0</text>
+ <path class="p4" d="M 806 129 L 786 131 L 801 137 L 819 136 L 806 129"/>
+ <text x="803" y="133" style="font-size:4">4,332,0,0,0</text>
+ <path class="p4" d="M 786 131 L 766 132 L 783 139 L 801 137 L 786 131"/>
+ <text x="784" y="135" style="font-size:4">4,333,0,0,0</text>
+ <path class="p4" d="M 819 136 L 801 137 L 817 144 L 833 143 L 819 136"/>
+ <text x="818" y="140" style="font-size:5">4,334,0,0,0</text>
+ <path class="p4" d="M 801 137 L 783 139 L 799 146 L 817 144 L 801 137"/>
+ <text x="800" y="141" style="font-size:5">4,335,0,0,0</text>
+ <path class="p4" d="M 867 140 L 850 141 L 863 148 L 879 146 L 867 140"/>
+ <text x="865" y="144" style="font-size:5">4,336,0,0,0</text>
+ <path class="p4" d="M 850 141 L 833 143 L 848 150 L 863 148 L 850 141"/>
+ <text x="849" y="145" style="font-size:5">4,337,0,0,0</text>
+ <path class="p4" d="M 879 146 L 863 148 L 876 155 L 890 153 L 879 146"/>
+ <text x="877" y="151" style="font-size:5">4,338,0,0,0</text>
+ <line x1="890" y1="153" x2="876" y2="155"/>
+ <path class="p4" d="M 863 148 L 848 150 L 862 156 L 876 155 L 863 148"/>
+ <text x="862" y="152" style="font-size:5">4,339,0,0,0</text>
+ <line x1="876" y1="155" x2="862" y2="156"/>
+ <path class="p4" d="M 833 143 L 817 144 L 832 151 L 848 150 L 833 143"/>
+ <text x="832" y="147" style="font-size:5">4,340,0,0,0</text>
+ <path class="p4" d="M 817 144 L 799 146 L 817 153 L 832 151 L 817 144"/>
+ <text x="816" y="148" style="font-size:5">4,341,0,0,0</text>
+ <path class="p4" d="M 848 150 L 832 151 L 848 158 L 862 156 L 848 150"/>
+ <text x="848" y="154" style="font-size:5">4,342,0,0,0</text>
+ <line x1="862" y1="156" x2="848" y2="158"/>
+ <path class="p4" d="M 832 151 L 817 153 L 834 160 L 848 158 L 832 151"/>
+ <text x="833" y="156" style="font-size:5">4,343,0,0,0</text>
+ <line x1="848" y1="158" x2="834" y2="160"/>
+ <path class="p4" d="M 766 132 L 746 133 L 764 140 L 783 139 L 766 132"/>
+ <text x="765" y="136" style="font-size:4">4,344,0,0,0</text>
+ <path class="p4" d="M 746 133 L 726 134 L 746 141 L 764 140 L 746 133"/>
+ <text x="745" y="137" style="font-size:4">4,345,0,0,0</text>
+ <path class="p4" d="M 783 139 L 764 140 L 782 147 L 799 146 L 783 139"/>
+ <text x="782" y="143" style="font-size:5">4,346,0,0,0</text>
+ <path class="p4" d="M 764 140 L 746 141 L 765 149 L 782 147 L 764 140"/>
+ <text x="764" y="144" style="font-size:5">4,347,0,0,0</text>
+ <path class="p4" d="M 726 134 L 706 136 L 727 143 L 746 141 L 726 134"/>
+ <text x="726" y="138" style="font-size:4">4,348,0,0,0</text>
+ <path class="p4" d="M 706 136 L 686 137 L 708 144 L 727 143 L 706 136"/>
+ <text x="707" y="140" style="font-size:4">4,349,0,0,0</text>
+ <path class="p4" d="M 746 141 L 727 143 L 748 150 L 765 149 L 746 141"/>
+ <text x="746" y="146" style="font-size:5">4,350,0,0,0</text>
+ <path class="p4" d="M 727 143 L 708 144 L 731 152 L 748 150 L 727 143"/>
+ <text x="728" y="147" style="font-size:5">4,351,0,0,0</text>
+ <path class="p4" d="M 799 146 L 782 147 L 801 154 L 817 153 L 799 146"/>
+ <text x="800" y="150" style="font-size:5">4,352,0,0,0</text>
+ <path class="p4" d="M 782 147 L 765 149 L 785 156 L 801 154 L 782 147"/>
+ <text x="783" y="152" style="font-size:5">4,353,0,0,0</text>
+ <path class="p4" d="M 817 153 L 801 154 L 820 162 L 834 160 L 817 153"/>
+ <text x="818" y="157" style="font-size:5">4,354,0,0,0</text>
+ <line x1="834" y1="160" x2="820" y2="162"/>
+ <path class="p4" d="M 801 154 L 785 156 L 806 163 L 820 162 L 801 154"/>
+ <text x="803" y="159" style="font-size:5">4,355,0,0,0</text>
+ <line x1="820" y1="162" x2="806" y2="163"/>
+ <path class="p4" d="M 765 149 L 748 150 L 769 158 L 785 156 L 765 149"/>
+ <text x="767" y="153" style="font-size:5">4,356,0,0,0</text>
+ <path class="p4" d="M 748 150 L 731 152 L 754 159 L 769 158 L 748 150"/>
+ <text x="750" y="155" style="font-size:5">4,357,0,0,0</text>
+ <path class="p4" d="M 785 156 L 769 158 L 791 165 L 806 163 L 785 156"/>
+ <text x="788" y="161" style="font-size:5">4,358,0,0,0</text>
+ <line x1="806" y1="163" x2="791" y2="165"/>
+ <path class="p4" d="M 769 158 L 754 159 L 777 167 L 791 165 L 769 158"/>
+ <text x="773" y="162" style="font-size:5">4,359,0,0,0</text>
+ <line x1="791" y1="165" x2="777" y2="167"/>
+ <path class="p4" d="M 643 122 L 637 129 L 658 136 L 665 130 L 643 122"/>
+ <text x="651" y="129" style="font-size:4">4,360,0,0,0</text>
+ <path class="p4" d="M 637 129 L 631 136 L 652 142 L 658 136 L 637 129"/>
+ <text x="644" y="136" style="font-size:4">4,361,0,0,0</text>
+ <path class="p4" d="M 665 130 L 658 136 L 680 143 L 686 137 L 665 130"/>
+ <text x="672" y="136" style="font-size:4">4,362,0,0,0</text>
+ <path class="p4" d="M 658 136 L 652 142 L 673 149 L 680 143 L 658 136"/>
+ <text x="666" y="142" style="font-size:4">4,363,0,0,0</text>
+ <path class="p4" d="M 631 136 L 624 142 L 645 148 L 652 142 L 631 136"/>
+ <text x="638" y="142" style="font-size:4">4,364,0,0,0</text>
+ <path class="p4" d="M 624 142 L 617 149 L 639 155 L 645 148 L 624 142"/>
+ <text x="631" y="149" style="font-size:5">4,365,0,0,0</text>
+ <path class="p4" d="M 652 142 L 645 148 L 667 155 L 673 149 L 652 142"/>
+ <text x="659" y="148" style="font-size:5">4,366,0,0,0</text>
+ <path class="p4" d="M 645 148 L 639 155 L 660 161 L 667 155 L 645 148"/>
+ <text x="653" y="155" style="font-size:5">4,367,0,0,0</text>
+ <path class="p4" d="M 576 138 L 569 146 L 590 151 L 597 144 L 576 138"/>
+ <text x="583" y="145" style="font-size:4">4,368,0,0,0</text>
+ <path class="p4" d="M 569 146 L 562 154 L 583 159 L 590 151 L 569 146"/>
+ <text x="576" y="152" style="font-size:5">4,369,0,0,0</text>
+ <path class="p4" d="M 597 144 L 590 151 L 611 156 L 617 149 L 597 144"/>
+ <text x="604" y="150" style="font-size:5">4,370,0,0,0</text>
+ <path class="p4" d="M 590 151 L 583 159 L 604 163 L 611 156 L 590 151"/>
+ <text x="597" y="157" style="font-size:5">4,371,0,0,0</text>
+ <path class="p4" d="M 562 154 L 555 162 L 576 166 L 583 159 L 562 154"/>
+ <text x="569" y="160" style="font-size:5">4,372,0,0,0</text>
+ <path class="p4" d="M 555 162 L 548 170 L 569 174 L 576 166 L 555 162"/>
+ <text x="562" y="168" style="font-size:5">4,373,0,0,0</text>
+ <path class="p4" d="M 583 159 L 576 166 L 597 171 L 604 163 L 583 159"/>
+ <text x="590" y="165" style="font-size:5">4,374,0,0,0</text>
+ <path class="p4" d="M 576 166 L 569 174 L 590 178 L 597 171 L 576 166"/>
+ <text x="583" y="172" style="font-size:5">4,375,0,0,0</text>
+ <path class="p4" d="M 617 149 L 611 156 L 632 162 L 639 155 L 617 149"/>
+ <text x="625" y="155" style="font-size:5">4,376,0,0,0</text>
+ <path class="p4" d="M 611 156 L 604 163 L 625 168 L 632 162 L 611 156"/>
+ <text x="618" y="162" style="font-size:5">4,377,0,0,0</text>
+ <path class="p4" d="M 639 155 L 632 162 L 653 167 L 660 161 L 639 155"/>
+ <text x="646" y="161" style="font-size:5">4,378,0,0,0</text>
+ <path class="p4" d="M 632 162 L 625 168 L 647 173 L 653 167 L 632 162"/>
+ <text x="639" y="167" style="font-size:5">4,379,0,0,0</text>
+ <path class="p4" d="M 604 163 L 597 171 L 618 175 L 625 168 L 604 163"/>
+ <text x="611" y="169" style="font-size:5">4,380,0,0,0</text>
+ <path class="p4" d="M 597 171 L 590 178 L 611 182 L 618 175 L 597 171"/>
+ <text x="604" y="176" style="font-size:5">4,381,0,0,0</text>
+ <path class="p4" d="M 625 168 L 618 175 L 640 180 L 647 173 L 625 168"/>
+ <text x="632" y="174" style="font-size:5">4,382,0,0,0</text>
+ <path class="p4" d="M 618 175 L 611 182 L 632 186 L 640 180 L 618 175"/>
+ <text x="625" y="181" style="font-size:5">4,383,0,0,0</text>
+ <path class="p4" d="M 686 137 L 680 143 L 702 150 L 708 144 L 686 137"/>
+ <text x="694" y="143" style="font-size:5">4,384,0,0,0</text>
+ <path class="p4" d="M 680 143 L 673 149 L 695 155 L 702 150 L 680 143"/>
+ <text x="688" y="149" style="font-size:5">4,385,0,0,0</text>
+ <path class="p4" d="M 708 144 L 702 150 L 724 157 L 731 152 L 708 144"/>
+ <text x="716" y="151" style="font-size:5">4,386,0,0,0</text>
+ <path class="p4" d="M 702 150 L 695 155 L 718 162 L 724 157 L 702 150"/>
+ <text x="710" y="156" style="font-size:5">4,387,0,0,0</text>
+ <path class="p4" d="M 673 149 L 667 155 L 689 161 L 695 155 L 673 149"/>
+ <text x="681" y="155" style="font-size:5">4,388,0,0,0</text>
+ <path class="p4" d="M 667 155 L 660 161 L 682 167 L 689 161 L 667 155"/>
+ <text x="674" y="161" style="font-size:5">4,389,0,0,0</text>
+ <path class="p4" d="M 695 155 L 689 161 L 711 167 L 718 162 L 695 155"/>
+ <text x="703" y="161" style="font-size:5">4,390,0,0,0</text>
+ <path class="p4" d="M 689 161 L 682 167 L 704 172 L 711 167 L 689 161"/>
+ <text x="696" y="167" style="font-size:5">4,391,0,0,0</text>
+ <path class="p4" d="M 731 152 L 724 157 L 747 164 L 754 159 L 731 152"/>
+ <text x="739" y="158" style="font-size:5">4,392,0,0,0</text>
+ <path class="p4" d="M 724 157 L 718 162 L 740 169 L 747 164 L 724 157"/>
+ <text x="732" y="163" style="font-size:5">4,393,0,0,0</text>
+ <path class="p4" d="M 754 159 L 747 164 L 770 171 L 777 167 L 754 159"/>
+ <text x="762" y="165" style="font-size:5">4,394,0,0,0</text>
+ <line x1="777" y1="167" x2="770" y2="171"/>
+ <path class="p4" d="M 747 164 L 740 169 L 763 176 L 770 171 L 747 164"/>
+ <text x="755" y="170" style="font-size:5">4,395,0,0,0</text>
+ <line x1="770" y1="171" x2="763" y2="176"/>
+ <path class="p4" d="M 718 162 L 711 167 L 733 174 L 740 169 L 718 162"/>
+ <text x="725" y="168" style="font-size:5">4,396,0,0,0</text>
+ <path class="p4" d="M 711 167 L 704 172 L 726 178 L 733 174 L 711 167"/>
+ <text x="719" y="173" style="font-size:5">4,397,0,0,0</text>
+ <path class="p4" d="M 740 169 L 733 174 L 756 180 L 763 176 L 740 169"/>
+ <text x="748" y="174" style="font-size:5">4,398,0,0,0</text>
+ <line x1="763" y1="176" x2="756" y2="180"/>
+ <path class="p4" d="M 733 174 L 726 178 L 749 184 L 756 180 L 733 174"/>
+ <text x="741" y="179" style="font-size:5">4,399,0,0,0</text>
+ <line x1="756" y1="180" x2="749" y2="184"/>
+ <path class="p4" d="M 660 161 L 653 167 L 675 172 L 682 167 L 660 161"/>
+ <text x="668" y="167" style="font-size:5">4,400,0,0,0</text>
+ <path class="p4" d="M 653 167 L 647 173 L 668 178 L 675 172 L 653 167"/>
+ <text x="661" y="173" style="font-size:5">4,401,0,0,0</text>
+ <path class="p4" d="M 682 167 L 675 172 L 697 178 L 704 172 L 682 167"/>
+ <text x="689" y="172" style="font-size:5">4,402,0,0,0</text>
+ <path class="p4" d="M 675 172 L 668 178 L 690 183 L 697 178 L 675 172"/>
+ <text x="683" y="178" style="font-size:5">4,403,0,0,0</text>
+ <path class="p4" d="M 647 173 L 640 180 L 661 184 L 668 178 L 647 173"/>
+ <text x="654" y="179" style="font-size:5">4,404,0,0,0</text>
+ <path class="p4" d="M 640 180 L 632 186 L 654 190 L 661 184 L 640 180"/>
+ <text x="647" y="185" style="font-size:5">4,405,0,0,0</text>
+ <path class="p4" d="M 668 178 L 661 184 L 683 189 L 690 183 L 668 178"/>
+ <text x="676" y="184" style="font-size:5">4,406,0,0,0</text>
+ <path class="p4" d="M 661 184 L 654 190 L 676 194 L 683 189 L 661 184"/>
+ <text x="668" y="189" style="font-size:5">4,407,0,0,0</text>
+ <path class="p4" d="M 704 172 L 697 178 L 719 183 L 726 178 L 704 172"/>
+ <text x="712" y="178" style="font-size:5">4,408,0,0,0</text>
+ <path class="p4" d="M 697 178 L 690 183 L 712 188 L 719 183 L 697 178"/>
+ <text x="705" y="183" style="font-size:5">4,409,0,0,0</text>
+ <path class="p4" d="M 726 178 L 719 183 L 742 189 L 749 184 L 726 178"/>
+ <text x="734" y="184" style="font-size:5">4,410,0,0,0</text>
+ <line x1="749" y1="184" x2="742" y2="189"/>
+ <path class="p4" d="M 719 183 L 712 188 L 734 193 L 742 189 L 719 183"/>
+ <text x="727" y="189" style="font-size:5">4,411,0,0,0</text>
+ <line x1="742" y1="189" x2="734" y2="193"/>
+ <path class="p4" d="M 690 183 L 683 189 L 705 193 L 712 188 L 690 183"/>
+ <text x="697" y="188" style="font-size:5">4,412,0,0,0</text>
+ <path class="p4" d="M 683 189 L 676 194 L 698 198 L 705 193 L 683 189"/>
+ <text x="690" y="194" style="font-size:5">4,413,0,0,0</text>
+ <path class="p4" d="M 712 188 L 705 193 L 727 198 L 734 193 L 712 188"/>
+ <text x="720" y="193" style="font-size:5">4,414,0,0,0</text>
+ <line x1="734" y1="193" x2="727" y2="198"/>
+ <path class="p4" d="M 705 193 L 698 198 L 720 203 L 727 198 L 705 193"/>
+ <text x="712" y="198" style="font-size:5">4,415,0,0,0</text>
+ <line x1="727" y1="198" x2="720" y2="203"/>
+ <path class="p4" d="M 548 170 L 541 178 L 562 182 L 569 174 L 548 170"/>
+ <text x="555" y="176" style="font-size:5">4,416,0,0,0</text>
+ <path class="p4" d="M 541 178 L 534 187 L 555 190 L 562 182 L 541 178"/>
+ <text x="548" y="184" style="font-size:5">4,417,0,0,0</text>
+ <path class="p4" d="M 569 174 L 562 182 L 583 185 L 590 178 L 569 174"/>
+ <text x="576" y="180" style="font-size:5">4,418,0,0,0</text>
+ <path class="p4" d="M 562 182 L 555 190 L 576 193 L 583 185 L 562 182"/>
+ <text x="569" y="187" style="font-size:5">4,419,0,0,0</text>
+ <path class="p4" d="M 534 187 L 526 195 L 547 198 L 555 190 L 534 187"/>
+ <text x="541" y="193" style="font-size:5">4,420,0,0,0</text>
+ <path class="p4" d="M 526 195 L 519 204 L 540 206 L 547 198 L 526 195"/>
+ <text x="533" y="201" style="font-size:5">4,421,0,0,0</text>
+ <path class="p4" d="M 555 190 L 547 198 L 568 201 L 576 193 L 555 190"/>
+ <text x="561" y="195" style="font-size:5">4,422,0,0,0</text>
+ <path class="p4" d="M 547 198 L 540 206 L 561 209 L 568 201 L 547 198"/>
+ <text x="554" y="203" style="font-size:5">4,423,0,0,0</text>
+ <path class="p4" d="M 590 178 L 583 185 L 604 189 L 611 182 L 590 178"/>
+ <text x="597" y="184" style="font-size:5">4,424,0,0,0</text>
+ <path class="p4" d="M 583 185 L 576 193 L 597 196 L 604 189 L 583 185"/>
+ <text x="590" y="191" style="font-size:5">4,425,0,0,0</text>
+ <path class="p4" d="M 611 182 L 604 189 L 625 193 L 632 186 L 611 182"/>
+ <text x="618" y="187" style="font-size:5">4,426,0,0,0</text>
+ <path class="p4" d="M 604 189 L 597 196 L 618 199 L 625 193 L 604 189"/>
+ <text x="611" y="194" style="font-size:5">4,427,0,0,0</text>
+ <path class="p4" d="M 576 193 L 568 201 L 589 203 L 597 196 L 576 193"/>
+ <text x="583" y="198" style="font-size:5">4,428,0,0,0</text>
+ <path class="p4" d="M 568 201 L 561 209 L 582 211 L 589 203 L 568 201"/>
+ <text x="575" y="206" style="font-size:5">4,429,0,0,0</text>
+ <path class="p4" d="M 597 196 L 589 203 L 611 206 L 618 199 L 597 196"/>
+ <text x="604" y="201" style="font-size:5">4,430,0,0,0</text>
+ <path class="p4" d="M 589 203 L 582 211 L 603 213 L 611 206 L 589 203"/>
+ <text x="596" y="208" style="font-size:5">4,431,0,0,0</text>
+ <path class="p4" d="M 519 204 L 511 213 L 532 215 L 540 206 L 519 204"/>
+ <text x="525" y="210" style="font-size:5">4,432,0,0,0</text>
+ <path class="p4" d="M 511 213 L 503 222 L 524 224 L 532 215 L 511 213"/>
+ <text x="517" y="219" style="font-size:5">4,433,0,0,0</text>
+ <path class="p4" d="M 540 206 L 532 215 L 553 217 L 561 209 L 540 206"/>
+ <text x="546" y="212" style="font-size:5">4,434,0,0,0</text>
+ <path class="p4" d="M 532 215 L 524 224 L 545 225 L 553 217 L 532 215"/>
+ <text x="539" y="220" style="font-size:6">4,435,0,0,0</text>
+ <path class="p4" d="M 503 222 L 495 232 L 516 232 L 524 224 L 503 222"/>
+ <text x="510" y="228" style="font-size:6">4,436,0,0,0</text>
+ <path class="p4" d="M 495 232 L 487 241 L 508 241 L 516 232 L 495 232"/>
+ <text x="501" y="237" style="font-size:6">4,437,0,0,0</text>
+ <path class="p4" d="M 524 224 L 516 232 L 537 233 L 545 225 L 524 224"/>
+ <text x="531" y="228" style="font-size:6">4,438,0,0,0</text>
+ <path class="p4" d="M 516 232 L 508 241 L 529 241 L 537 233 L 516 232"/>
+ <text x="523" y="237" style="font-size:6">4,439,0,0,0</text>
+ <path class="p4" d="M 561 209 L 553 217 L 574 218 L 582 211 L 561 209"/>
+ <text x="568" y="213" style="font-size:5">4,440,0,0,0</text>
+ <path class="p4" d="M 553 217 L 545 225 L 567 226 L 574 218 L 553 217"/>
+ <text x="560" y="221" style="font-size:6">4,441,0,0,0</text>
+ <path class="p4" d="M 582 211 L 574 218 L 596 220 L 603 213 L 582 211"/>
+ <text x="589" y="215" style="font-size:5">4,442,0,0,0</text>
+ <path class="p4" d="M 574 218 L 567 226 L 588 227 L 596 220 L 574 218"/>
+ <text x="581" y="223" style="font-size:6">4,443,0,0,0</text>
+ <path class="p4" d="M 545 225 L 537 233 L 559 233 L 567 226 L 545 225"/>
+ <text x="552" y="229" style="font-size:6">4,444,0,0,0</text>
+ <path class="p4" d="M 537 233 L 529 241 L 551 241 L 559 233 L 537 233"/>
+ <text x="544" y="237" style="font-size:6">4,445,0,0,0</text>
+ <path class="p4" d="M 567 226 L 559 233 L 580 234 L 588 227 L 567 226"/>
+ <text x="573" y="230" style="font-size:6">4,446,0,0,0</text>
+ <path class="p4" d="M 559 233 L 551 241 L 572 241 L 580 234 L 559 233"/>
+ <text x="565" y="238" style="font-size:6">4,447,0,0,0</text>
+ <path class="p4" d="M 632 186 L 625 193 L 647 196 L 654 190 L 632 186"/>
+ <text x="640" y="191" style="font-size:5">4,448,0,0,0</text>
+ <path class="p4" d="M 625 193 L 618 199 L 640 202 L 647 196 L 625 193"/>
+ <text x="632" y="198" style="font-size:5">4,449,0,0,0</text>
+ <path class="p4" d="M 654 190 L 647 196 L 668 200 L 676 194 L 654 190"/>
+ <text x="661" y="195" style="font-size:5">4,450,0,0,0</text>
+ <path class="p4" d="M 647 196 L 640 202 L 661 206 L 668 200 L 647 196"/>
+ <text x="654" y="201" style="font-size:5">4,451,0,0,0</text>
+ <path class="p4" d="M 618 199 L 611 206 L 632 209 L 640 202 L 618 199"/>
+ <text x="625" y="204" style="font-size:5">4,452,0,0,0</text>
+ <path class="p4" d="M 611 206 L 603 213 L 625 215 L 632 209 L 611 206"/>
+ <text x="618" y="211" style="font-size:5">4,453,0,0,0</text>
+ <path class="p4" d="M 640 202 L 632 209 L 654 211 L 661 206 L 640 202"/>
+ <text x="647" y="207" style="font-size:5">4,454,0,0,0</text>
+ <path class="p4" d="M 632 209 L 625 215 L 646 217 L 654 211 L 632 209"/>
+ <text x="639" y="213" style="font-size:6">4,455,0,0,0</text>
+ <path class="p4" d="M 676 194 L 668 200 L 690 204 L 698 198 L 676 194"/>
+ <text x="683" y="199" style="font-size:5">4,456,0,0,0</text>
+ <path class="p4" d="M 668 200 L 661 206 L 683 209 L 690 204 L 668 200"/>
+ <text x="676" y="204" style="font-size:5">4,457,0,0,0</text>
+ <path class="p4" d="M 698 198 L 690 204 L 712 207 L 720 203 L 698 198"/>
+ <text x="705" y="203" style="font-size:5">4,458,0,0,0</text>
+ <line x1="720" y1="203" x2="712" y2="207"/>
+ <path class="p4" d="M 690 204 L 683 209 L 705 212 L 712 207 L 690 204"/>
+ <text x="698" y="208" style="font-size:5">4,459,0,0,0</text>
+ <line x1="712" y1="207" x2="705" y2="212"/>
+ <path class="p4" d="M 661 206 L 654 211 L 675 214 L 683 209 L 661 206"/>
+ <text x="668" y="210" style="font-size:5">4,460,0,0,0</text>
+ <path class="p4" d="M 654 211 L 646 217 L 668 219 L 675 214 L 654 211"/>
+ <text x="661" y="215" style="font-size:6">4,461,0,0,0</text>
+ <path class="p4" d="M 683 209 L 675 214 L 697 217 L 705 212 L 683 209"/>
+ <text x="690" y="213" style="font-size:6">4,462,0,0,0</text>
+ <line x1="705" y1="212" x2="697" y2="217"/>
+ <path class="p4" d="M 675 214 L 668 219 L 689 222 L 697 217 L 675 214"/>
+ <text x="682" y="218" style="font-size:6">4,463,0,0,0</text>
+ <line x1="697" y1="217" x2="689" y2="222"/>
+ <path class="p4" d="M 603 213 L 596 220 L 617 221 L 625 215 L 603 213"/>
+ <text x="610" y="217" style="font-size:6">4,464,0,0,0</text>
+ <path class="p4" d="M 596 220 L 588 227 L 609 228 L 617 221 L 596 220"/>
+ <text x="602" y="224" style="font-size:6">4,465,0,0,0</text>
+ <path class="p4" d="M 625 215 L 617 221 L 638 223 L 646 217 L 625 215"/>
+ <text x="632" y="219" style="font-size:6">4,466,0,0,0</text>
+ <path class="p4" d="M 617 221 L 609 228 L 631 229 L 638 223 L 617 221"/>
+ <text x="624" y="225" style="font-size:6">4,467,0,0,0</text>
+ <path class="p4" d="M 588 227 L 580 234 L 601 235 L 609 228 L 588 227"/>
+ <text x="595" y="231" style="font-size:6">4,468,0,0,0</text>
+ <path class="p4" d="M 580 234 L 572 241 L 594 241 L 601 235 L 580 234"/>
+ <text x="587" y="238" style="font-size:6">4,469,0,0,0</text>
+ <path class="p4" d="M 609 228 L 601 235 L 623 235 L 631 229 L 609 228"/>
+ <text x="616" y="232" style="font-size:6">4,470,0,0,0</text>
+ <path class="p4" d="M 601 235 L 594 241 L 615 241 L 623 235 L 601 235"/>
+ <text x="608" y="238" style="font-size:6">4,471,0,0,0</text>
+ <path class="p4" d="M 646 217 L 638 223 L 660 225 L 668 219 L 646 217"/>
+ <text x="653" y="221" style="font-size:6">4,472,0,0,0</text>
+ <path class="p4" d="M 638 223 L 631 229 L 652 230 L 660 225 L 638 223"/>
+ <text x="645" y="227" style="font-size:6">4,473,0,0,0</text>
+ <path class="p4" d="M 668 219 L 660 225 L 682 226 L 689 222 L 668 219"/>
+ <text x="675" y="223" style="font-size:6">4,474,0,0,0</text>
+ <line x1="689" y1="222" x2="682" y2="226"/>
+ <path class="p4" d="M 660 225 L 652 230 L 674 231 L 682 226 L 660 225"/>
+ <text x="667" y="228" style="font-size:6">4,475,0,0,0</text>
+ <line x1="682" y1="226" x2="674" y2="231"/>
+ <path class="p4" d="M 631 229 L 623 235 L 644 236 L 652 230 L 631 229"/>
+ <text x="638" y="233" style="font-size:6">4,476,0,0,0</text>
+ <path class="p4" d="M 623 235 L 615 241 L 636 241 L 644 236 L 623 235"/>
+ <text x="630" y="238" style="font-size:6">4,477,0,0,0</text>
+ <path class="p4" d="M 652 230 L 644 236 L 666 236 L 674 231 L 652 230"/>
+ <text x="659" y="233" style="font-size:6">4,478,0,0,0</text>
+ <line x1="674" y1="231" x2="666" y2="236"/>
+ <path class="p4" d="M 644 236 L 636 241 L 658 241 L 666 236 L 644 236"/>
+ <text x="651" y="239" style="font-size:6">4,479,0,0,0</text>
+ <line x1="666" y1="236" x2="658" y2="241"/>
+ <path class="p4" d="M 487 241 L 484 251 L 507 251 L 508 241 L 487 241"/>
+ <text x="496" y="246" style="font-size:6">4,480,0,0,0</text>
+ <path class="p4" d="M 484 251 L 482 261 L 506 260 L 507 251 L 484 251"/>
+ <text x="495" y="256" style="font-size:6">4,481,0,0,0</text>
+ <path class="p4" d="M 508 241 L 507 251 L 529 250 L 529 241 L 508 241"/>
+ <text x="518" y="246" style="font-size:6">4,482,0,0,0</text>
+ <path class="p4" d="M 507 251 L 506 260 L 529 259 L 529 250 L 507 251"/>
+ <text x="518" y="255" style="font-size:6">4,483,0,0,0</text>
+ <path class="p4" d="M 482 261 L 480 271 L 504 269 L 506 260 L 482 261"/>
+ <text x="493" y="265" style="font-size:6">4,484,0,0,0</text>
+ <path class="p4" d="M 480 271 L 478 282 L 503 279 L 504 269 L 480 271"/>
+ <text x="491" y="275" style="font-size:6">4,485,0,0,0</text>
+ <path class="p4" d="M 506 260 L 504 269 L 528 268 L 529 259 L 506 260"/>
+ <text x="517" y="264" style="font-size:6">4,486,0,0,0</text>
+ <path class="p4" d="M 504 269 L 503 279 L 528 277 L 528 268 L 504 269"/>
+ <text x="516" y="273" style="font-size:6">4,487,0,0,0</text>
+ <path class="p4" d="M 529 241 L 529 250 L 551 249 L 551 241 L 529 241"/>
+ <text x="540" y="245" style="font-size:6">4,488,0,0,0</text>
+ <path class="p4" d="M 529 250 L 529 259 L 552 257 L 551 249 L 529 250"/>
+ <text x="540" y="254" style="font-size:6">4,489,0,0,0</text>
+ <path class="p4" d="M 551 241 L 551 249 L 574 249 L 572 241 L 551 241"/>
+ <text x="562" y="245" style="font-size:6">4,490,0,0,0</text>
+ <path class="p4" d="M 551 249 L 552 257 L 575 256 L 574 249 L 551 249"/>
+ <text x="563" y="253" style="font-size:6">4,491,0,0,0</text>
+ <path class="p4" d="M 529 259 L 528 268 L 552 266 L 552 257 L 529 259"/>
+ <text x="540" y="262" style="font-size:6">4,492,0,0,0</text>
+ <path class="p4" d="M 528 268 L 528 277 L 553 274 L 552 266 L 528 268"/>
+ <text x="541" y="271" style="font-size:6">4,493,0,0,0</text>
+ <path class="p4" d="M 552 257 L 552 266 L 576 264 L 575 256 L 552 257"/>
+ <text x="564" y="261" style="font-size:6">4,494,0,0,0</text>
+ <path class="p4" d="M 552 266 L 553 274 L 578 272 L 576 264 L 552 266"/>
+ <text x="565" y="269" style="font-size:6">4,495,0,0,0</text>
+ <path class="p4" d="M 478 282 L 476 292 L 502 289 L 503 279 L 478 282"/>
+ <text x="490" y="285" style="font-size:6">4,496,0,0,0</text>
+ <path class="p4" d="M 476 292 L 473 303 L 500 299 L 502 289 L 476 292"/>
+ <text x="488" y="296" style="font-size:7">4,497,0,0,0</text>
+ <path class="p4" d="M 503 279 L 502 289 L 528 286 L 528 277 L 503 279"/>
+ <text x="515" y="283" style="font-size:6">4,498,0,0,0</text>
+ <path class="p4" d="M 502 289 L 500 299 L 527 295 L 528 286 L 502 289"/>
+ <text x="514" y="292" style="font-size:7">4,499,0,0,0</text>
+ <path class="p4" d="M 473 303 L 471 314 L 499 309 L 500 299 L 473 303"/>
+ <text x="486" y="306" style="font-size:7">4,500,0,0,0</text>
+ <path class="p4" d="M 471 314 L 468 325 L 498 320 L 499 309 L 471 314"/>
+ <text x="484" y="317" style="font-size:7">4,501,0,0,0</text>
+ <path class="p4" d="M 500 299 L 499 309 L 527 305 L 527 295 L 500 299"/>
+ <text x="514" y="302" style="font-size:7">4,502,0,0,0</text>
+ <path class="p4" d="M 499 309 L 498 320 L 527 315 L 527 305 L 499 309"/>
+ <text x="513" y="312" style="font-size:7">4,503,0,0,0</text>
+ <path class="p4" d="M 528 277 L 528 286 L 554 283 L 553 274 L 528 277"/>
+ <text x="541" y="280" style="font-size:6">4,504,0,0,0</text>
+ <path class="p4" d="M 528 286 L 527 295 L 554 291 L 554 283 L 528 286"/>
+ <text x="541" y="289" style="font-size:7">4,505,0,0,0</text>
+ <path class="p4" d="M 553 274 L 554 283 L 579 280 L 578 272 L 553 274"/>
+ <text x="566" y="277" style="font-size:6">4,506,0,0,0</text>
+ <path class="p4" d="M 554 283 L 554 291 L 581 288 L 579 280 L 554 283"/>
+ <text x="567" y="285" style="font-size:7">4,507,0,0,0</text>
+ <path class="p4" d="M 527 295 L 527 305 L 555 300 L 554 291 L 527 295"/>
+ <text x="541" y="298" style="font-size:7">4,508,0,0,0</text>
+ <path class="p4" d="M 527 305 L 527 315 L 555 309 L 555 300 L 527 305"/>
+ <text x="541" y="307" style="font-size:7">4,509,0,0,0</text>
+ <path class="p4" d="M 554 291 L 555 300 L 582 296 L 581 288 L 554 291"/>
+ <text x="568" y="294" style="font-size:7">4,510,0,0,0</text>
+ <path class="p4" d="M 555 300 L 555 309 L 584 304 L 582 296 L 555 300"/>
+ <text x="569" y="302" style="font-size:7">4,511,0,0,0</text>
+ <path class="p4" d="M 572 241 L 574 249 L 596 248 L 594 241 L 572 241"/>
+ <text x="584" y="245" style="font-size:6">4,512,0,0,0</text>
+ <path class="p4" d="M 574 249 L 575 256 L 598 255 L 596 248 L 574 249"/>
+ <text x="586" y="252" style="font-size:6">4,513,0,0,0</text>
+ <path class="p4" d="M 594 241 L 596 248 L 618 248 L 615 241 L 594 241"/>
+ <text x="606" y="245" style="font-size:6">4,514,0,0,0</text>
+ <path class="p4" d="M 596 248 L 598 255 L 621 254 L 618 248 L 596 248"/>
+ <text x="608" y="251" style="font-size:6">4,515,0,0,0</text>
+ <path class="p4" d="M 575 256 L 576 264 L 600 262 L 598 255 L 575 256"/>
+ <text x="587" y="259" style="font-size:6">4,516,0,0,0</text>
+ <path class="p4" d="M 576 264 L 578 272 L 603 269 L 600 262 L 576 264"/>
+ <text x="589" y="267" style="font-size:6">4,517,0,0,0</text>
+ <path class="p4" d="M 598 255 L 600 262 L 624 260 L 621 254 L 598 255"/>
+ <text x="611" y="258" style="font-size:6">4,518,0,0,0</text>
+ <path class="p4" d="M 600 262 L 603 269 L 627 267 L 624 260 L 600 262"/>
+ <text x="613" y="265" style="font-size:6">4,519,0,0,0</text>
+ <path class="p4" d="M 615 241 L 618 248 L 640 247 L 636 241 L 615 241"/>
+ <text x="627" y="244" style="font-size:6">4,520,0,0,0</text>
+ <path class="p4" d="M 618 248 L 621 254 L 644 253 L 640 247 L 618 248"/>
+ <text x="631" y="250" style="font-size:6">4,521,0,0,0</text>
+ <path class="p4" d="M 636 241 L 640 247 L 662 246 L 658 241 L 636 241"/>
+ <text x="649" y="244" style="font-size:6">4,522,0,0,0</text>
+ <line x1="658" y1="241" x2="662" y2="246"/>
+ <path class="p4" d="M 640 247 L 644 253 L 667 252 L 662 246 L 640 247"/>
+ <text x="653" y="249" style="font-size:6">4,523,0,0,0</text>
+ <line x1="662" y1="246" x2="667" y2="252"/>
+ <path class="p4" d="M 621 254 L 624 260 L 648 259 L 644 253 L 621 254"/>
+ <text x="634" y="256" style="font-size:6">4,524,0,0,0</text>
+ <path class="p4" d="M 624 260 L 627 267 L 652 264 L 648 259 L 624 260"/>
+ <text x="638" y="262" style="font-size:6">4,525,0,0,0</text>
+ <path class="p4" d="M 644 253 L 648 259 L 671 257 L 667 252 L 644 253"/>
+ <text x="657" y="255" style="font-size:6">4,526,0,0,0</text>
+ <line x1="667" y1="252" x2="671" y2="257"/>
+ <path class="p4" d="M 648 259 L 652 264 L 676 262 L 671 257 L 648 259"/>
+ <text x="662" y="260" style="font-size:6">4,527,0,0,0</text>
+ <line x1="671" y1="257" x2="676" y2="262"/>
+ <path class="p4" d="M 578 272 L 579 280 L 605 276 L 603 269 L 578 272"/>
+ <text x="591" y="274" style="font-size:6">4,528,0,0,0</text>
+ <path class="p4" d="M 579 280 L 581 288 L 607 284 L 605 276 L 579 280"/>
+ <text x="593" y="282" style="font-size:6">4,529,0,0,0</text>
+ <path class="p4" d="M 603 269 L 605 276 L 630 273 L 627 267 L 603 269"/>
+ <text x="616" y="271" style="font-size:6">4,530,0,0,0</text>
+ <path class="p4" d="M 605 276 L 607 284 L 633 280 L 630 273 L 605 276"/>
+ <text x="619" y="278" style="font-size:6">4,531,0,0,0</text>
+ <path class="p4" d="M 581 288 L 582 296 L 610 291 L 607 284 L 581 288"/>
+ <text x="595" y="290" style="font-size:7">4,532,0,0,0</text>
+ <path class="p4" d="M 582 296 L 584 304 L 612 299 L 610 291 L 582 296"/>
+ <text x="597" y="297" style="font-size:7">4,533,0,0,0</text>
+ <path class="p4" d="M 607 284 L 610 291 L 637 287 L 633 280 L 607 284"/>
+ <text x="622" y="285" style="font-size:7">4,534,0,0,0</text>
+ <path class="p4" d="M 610 291 L 612 299 L 640 294 L 637 287 L 610 291"/>
+ <text x="625" y="293" style="font-size:7">4,535,0,0,0</text>
+ <path class="p4" d="M 627 267 L 630 273 L 655 270 L 652 264 L 627 267"/>
+ <text x="641" y="269" style="font-size:6">4,536,0,0,0</text>
+ <path class="p4" d="M 630 273 L 633 280 L 659 276 L 655 270 L 630 273"/>
+ <text x="645" y="275" style="font-size:6">4,537,0,0,0</text>
+ <path class="p4" d="M 652 264 L 655 270 L 681 267 L 676 262 L 652 264"/>
+ <text x="666" y="266" style="font-size:6">4,538,0,0,0</text>
+ <line x1="676" y1="262" x2="681" y2="267"/>
+ <path class="p4" d="M 655 270 L 659 276 L 685 273 L 681 267 L 655 270"/>
+ <text x="670" y="272" style="font-size:6">4,539,0,0,0</text>
+ <line x1="681" y1="267" x2="685" y2="273"/>
+ <path class="p4" d="M 633 280 L 637 287 L 663 282 L 659 276 L 633 280"/>
+ <text x="648" y="281" style="font-size:7">4,540,0,0,0</text>
+ <path class="p4" d="M 637 287 L 640 294 L 668 289 L 663 282 L 637 287"/>
+ <text x="652" y="288" style="font-size:7">4,541,0,0,0</text>
+ <path class="p4" d="M 659 276 L 663 282 L 690 278 L 685 273 L 659 276"/>
+ <text x="675" y="277" style="font-size:6">4,542,0,0,0</text>
+ <line x1="685" y1="273" x2="690" y2="278"/>
+ <path class="p4" d="M 663 282 L 668 289 L 695 283 L 690 278 L 663 282"/>
+ <text x="679" y="283" style="font-size:7">4,543,0,0,0</text>
+ <line x1="690" y1="278" x2="695" y2="283"/>
+ <path class="p4" d="M 468 325 L 466 337 L 496 331 L 498 320 L 468 325"/>
+ <text x="482" y="328" style="font-size:7">4,544,0,0,0</text>
+ <path class="p4" d="M 466 337 L 463 349 L 495 342 L 496 331 L 466 337"/>
+ <text x="480" y="339" style="font-size:7">4,545,0,0,0</text>
+ <path class="p4" d="M 498 320 L 496 331 L 526 325 L 527 315 L 498 320"/>
+ <text x="512" y="322" style="font-size:7">4,546,0,0,0</text>
+ <path class="p4" d="M 496 331 L 495 342 L 526 335 L 526 325 L 496 331"/>
+ <text x="511" y="333" style="font-size:7">4,547,0,0,0</text>
+ <path class="p4" d="M 463 349 L 461 361 L 493 353 L 495 342 L 463 349"/>
+ <text x="478" y="351" style="font-size:7">4,548,0,0,0</text>
+ <path class="p4" d="M 461 361 L 458 373 L 492 364 L 493 353 L 461 361"/>
+ <text x="476" y="363" style="font-size:8">4,549,0,0,0</text>
+ <path class="p4" d="M 495 342 L 493 353 L 526 345 L 526 335 L 495 342"/>
+ <text x="510" y="344" style="font-size:7">4,550,0,0,0</text>
+ <path class="p4" d="M 493 353 L 492 364 L 525 356 L 526 345 L 493 353"/>
+ <text x="509" y="354" style="font-size:8">4,551,0,0,0</text>
+ <path class="p4" d="M 527 315 L 526 325 L 556 318 L 555 309 L 527 315"/>
+ <text x="541" y="317" style="font-size:7">4,552,0,0,0</text>
+ <path class="p4" d="M 526 325 L 526 335 L 557 328 L 556 318 L 526 325"/>
+ <text x="541" y="326" style="font-size:7">4,553,0,0,0</text>
+ <path class="p4" d="M 555 309 L 556 318 L 586 312 L 584 304 L 555 309"/>
+ <text x="570" y="311" style="font-size:7">4,554,0,0,0</text>
+ <path class="p4" d="M 556 318 L 557 328 L 587 321 L 586 312 L 556 318"/>
+ <text x="571" y="320" style="font-size:7">4,555,0,0,0</text>
+ <path class="p4" d="M 526 335 L 526 345 L 557 337 L 557 328 L 526 335"/>
+ <text x="542" y="336" style="font-size:7">4,556,0,0,0</text>
+ <path class="p4" d="M 526 345 L 525 356 L 558 347 L 557 337 L 526 345"/>
+ <text x="542" y="346" style="font-size:7">4,557,0,0,0</text>
+ <path class="p4" d="M 557 328 L 557 337 L 589 330 L 587 321 L 557 328"/>
+ <text x="573" y="329" style="font-size:7">4,558,0,0,0</text>
+ <path class="p4" d="M 557 337 L 558 347 L 590 339 L 589 330 L 557 337"/>
+ <text x="574" y="338" style="font-size:7">4,559,0,0,0</text>
+ <path class="p4" d="M 525 356 L 525 366 L 559 357 L 558 347 L 525 356"/>
+ <text x="542" y="356" style="font-size:8">4,560,0,0,0</text>
+ <path class="p4" d="M 525 366 L 525 377 L 560 367 L 559 357 L 525 366"/>
+ <text x="542" y="367" style="font-size:8">4,561,0,0,0</text>
+ <path class="p4" d="M 558 347 L 559 357 L 592 348 L 590 339 L 558 347"/>
+ <text x="575" y="347" style="font-size:7">4,562,0,0,0</text>
+ <path class="p4" d="M 559 357 L 560 367 L 594 357 L 592 348 L 559 357"/>
+ <text x="576" y="357" style="font-size:8">4,563,0,0,0</text>
+ <path class="p4" d="M 525 377 L 524 389 L 560 377 L 560 367 L 525 377"/>
+ <text x="542" y="377" style="font-size:8">4,564,0,0,0</text>
+ <path class="p4" d="M 524 389 L 524 400 L 561 388 L 560 377 L 524 389"/>
+ <text x="542" y="388" style="font-size:8">4,565,0,0,0</text>
+ <path class="p4" d="M 560 367 L 560 377 L 596 366 L 594 357 L 560 367"/>
+ <text x="577" y="367" style="font-size:8">4,566,0,0,0</text>
+ <path class="p4" d="M 560 377 L 561 388 L 597 375 L 596 366 L 560 377"/>
+ <text x="579" y="377" style="font-size:8">4,567,0,0,0</text>
+ <path class="p4" d="M 584 304 L 586 312 L 615 306 L 612 299 L 584 304"/>
+ <text x="599" y="305" style="font-size:7">4,568,0,0,0</text>
+ <path class="p4" d="M 586 312 L 587 321 L 617 314 L 615 306 L 586 312"/>
+ <text x="601" y="313" style="font-size:7">4,569,0,0,0</text>
+ <path class="p4" d="M 612 299 L 615 306 L 643 301 L 640 294 L 612 299"/>
+ <text x="628" y="300" style="font-size:7">4,570,0,0,0</text>
+ <path class="p4" d="M 615 306 L 617 314 L 647 308 L 643 301 L 615 306"/>
+ <text x="630" y="307" style="font-size:7">4,571,0,0,0</text>
+ <path class="p4" d="M 587 321 L 589 330 L 620 322 L 617 314 L 587 321"/>
+ <text x="603" y="322" style="font-size:7">4,572,0,0,0</text>
+ <path class="p4" d="M 589 330 L 590 339 L 622 330 L 620 322 L 589 330"/>
+ <text x="605" y="330" style="font-size:7">4,573,0,0,0</text>
+ <path class="p4" d="M 617 314 L 620 322 L 650 315 L 647 308 L 617 314"/>
+ <text x="633" y="315" style="font-size:7">4,574,0,0,0</text>
+ <path class="p4" d="M 620 322 L 622 330 L 654 322 L 650 315 L 620 322"/>
+ <text x="636" y="322" style="font-size:7">4,575,0,0,0</text>
+ <path class="p4" d="M 640 294 L 643 301 L 672 295 L 668 289 L 640 294"/>
+ <text x="656" y="294" style="font-size:7">4,576,0,0,0</text>
+ <path class="p4" d="M 643 301 L 647 308 L 676 301 L 672 295 L 643 301"/>
+ <text x="659" y="301" style="font-size:7">4,577,0,0,0</text>
+ <path class="p4" d="M 668 289 L 672 295 L 700 289 L 695 283 L 668 289"/>
+ <text x="683" y="289" style="font-size:7">4,578,0,0,0</text>
+ <line x1="695" y1="283" x2="700" y2="289"/>
+ <path class="p4" d="M 672 295 L 676 301 L 705 295 L 700 289 L 672 295"/>
+ <text x="688" y="295" style="font-size:7">4,579,0,0,0</text>
+ <line x1="700" y1="289" x2="705" y2="295"/>
+ <path class="p4" d="M 647 308 L 650 315 L 680 307 L 676 301 L 647 308"/>
+ <text x="663" y="308" style="font-size:7">4,580,0,0,0</text>
+ <path class="p4" d="M 650 315 L 654 322 L 684 314 L 680 307 L 650 315"/>
+ <text x="667" y="314" style="font-size:7">4,581,0,0,0</text>
+ <path class="p4" d="M 676 301 L 680 307 L 710 300 L 705 295 L 676 301"/>
+ <text x="693" y="301" style="font-size:7">4,582,0,0,0</text>
+ <line x1="705" y1="295" x2="710" y2="300"/>
+ <path class="p4" d="M 680 307 L 684 314 L 715 306 L 710 300 L 680 307"/>
+ <text x="697" y="307" style="font-size:7">4,583,0,0,0</text>
+ <line x1="710" y1="300" x2="715" y2="306"/>
+ <path class="p4" d="M 590 339 L 592 348 L 625 338 L 622 330 L 590 339"/>
+ <text x="608" y="339" style="font-size:7">4,584,0,0,0</text>
+ <path class="p4" d="M 592 348 L 594 357 L 628 347 L 625 338 L 592 348"/>
+ <text x="610" y="347" style="font-size:8">4,585,0,0,0</text>
+ <path class="p4" d="M 622 330 L 625 338 L 657 329 L 654 322 L 622 330"/>
+ <text x="640" y="330" style="font-size:7">4,586,0,0,0</text>
+ <path class="p4" d="M 625 338 L 628 347 L 661 337 L 657 329 L 625 338"/>
+ <text x="643" y="338" style="font-size:7">4,587,0,0,0</text>
+ <path class="p4" d="M 594 357 L 596 366 L 630 355 L 628 347 L 594 357"/>
+ <text x="612" y="356" style="font-size:8">4,588,0,0,0</text>
+ <path class="p4" d="M 596 366 L 597 375 L 633 364 L 630 355 L 596 366"/>
+ <text x="614" y="365" style="font-size:8">4,589,0,0,0</text>
+ <path class="p4" d="M 628 347 L 630 355 L 664 344 L 661 337 L 628 347"/>
+ <text x="646" y="346" style="font-size:8">4,590,0,0,0</text>
+ <path class="p4" d="M 630 355 L 633 364 L 668 352 L 664 344 L 630 355"/>
+ <text x="649" y="354" style="font-size:8">4,591,0,0,0</text>
+ <path class="p4" d="M 654 322 L 657 329 L 689 320 L 684 314 L 654 322"/>
+ <text x="671" y="321" style="font-size:7">4,592,0,0,0</text>
+ <path class="p4" d="M 657 329 L 661 337 L 693 327 L 689 320 L 657 329"/>
+ <text x="675" y="328" style="font-size:7">4,593,0,0,0</text>
+ <path class="p4" d="M 684 314 L 689 320 L 720 312 L 715 306 L 684 314"/>
+ <text x="702" y="313" style="font-size:7">4,594,0,0,0</text>
+ <line x1="715" y1="306" x2="720" y2="312"/>
+ <path class="p4" d="M 689 320 L 693 327 L 725 318 L 720 312 L 689 320"/>
+ <text x="707" y="319" style="font-size:7">4,595,0,0,0</text>
+ <line x1="720" y1="312" x2="725" y2="318"/>
+ <path class="p4" d="M 661 337 L 664 344 L 698 334 L 693 327 L 661 337"/>
+ <text x="679" y="335" style="font-size:7">4,596,0,0,0</text>
+ <path class="p4" d="M 664 344 L 668 352 L 702 341 L 698 334 L 664 344"/>
+ <text x="683" y="343" style="font-size:7">4,597,0,0,0</text>
+ <path class="p4" d="M 693 327 L 698 334 L 730 324 L 725 318 L 693 327"/>
+ <text x="712" y="325" style="font-size:7">4,598,0,0,0</text>
+ <line x1="725" y1="318" x2="730" y2="324"/>
+ <path class="p4" d="M 698 334 L 702 341 L 735 330 L 730 324 L 698 334"/>
+ <text x="716" y="332" style="font-size:7">4,599,0,0,0</text>
+ <line x1="730" y1="324" x2="735" y2="330"/>
+ <path class="p4" d="M 524 400 L 553 402 L 588 390 L 561 388 L 524 400"/>
+ <text x="556" y="395" style="font-size:8">4,600,0,0,0</text>
+ <path class="p4" d="M 553 402 L 582 404 L 615 391 L 588 390 L 553 402"/>
+ <text x="584" y="397" style="font-size:8">4,601,0,0,0</text>
+ <path class="p4" d="M 561 388 L 588 390 L 622 378 L 597 375 L 561 388"/>
+ <text x="592" y="383" style="font-size:8">4,602,0,0,0</text>
+ <path class="p4" d="M 588 390 L 615 391 L 646 380 L 622 378 L 588 390"/>
+ <text x="618" y="385" style="font-size:8">4,603,0,0,0</text>
+ <path class="p4" d="M 582 404 L 611 405 L 641 393 L 615 391 L 582 404"/>
+ <text x="612" y="398" style="font-size:8">4,604,0,0,0</text>
+ <path class="p4" d="M 611 405 L 640 407 L 668 395 L 641 393 L 611 405"/>
+ <text x="640" y="400" style="font-size:8">4,605,0,0,0</text>
+ <path class="p4" d="M 615 391 L 641 393 L 671 382 L 646 380 L 615 391"/>
+ <text x="643" y="387" style="font-size:8">4,606,0,0,0</text>
+ <path class="p4" d="M 641 393 L 668 395 L 696 384 L 671 382 L 641 393"/>
+ <text x="669" y="389" style="font-size:8">4,607,0,0,0</text>
+ <path class="p4" d="M 583 432 L 617 433 L 644 421 L 612 419 L 583 432"/>
+ <text x="614" y="426" style="font-size:9">4,608,0,0,0</text>
+ <path class="p4" d="M 617 433 L 651 435 L 676 423 L 644 421 L 617 433"/>
+ <text x="647" y="428" style="font-size:9">4,609,0,0,0</text>
+ <path class="p4" d="M 612 419 L 644 421 L 670 409 L 640 407 L 612 419"/>
+ <text x="642" y="414" style="font-size:9">4,610,0,0,0</text>
+ <path class="p4" d="M 644 421 L 676 423 L 699 411 L 670 409 L 644 421"/>
+ <text x="672" y="416" style="font-size:9">4,611,0,0,0</text>
+ <path class="p4" d="M 651 435 L 686 436 L 708 424 L 676 423 L 651 435"/>
+ <text x="680" y="429" style="font-size:9">4,612,0,0,0</text>
+ <path class="p4" d="M 686 436 L 720 438 L 740 426 L 708 424 L 686 436"/>
+ <text x="713" y="431" style="font-size:9">4,613,0,0,0</text>
+ <path class="p4" d="M 676 423 L 708 424 L 729 413 L 699 411 L 676 423"/>
+ <text x="703" y="418" style="font-size:9">4,614,0,0,0</text>
+ <path class="p4" d="M 708 424 L 740 426 L 759 414 L 729 413 L 708 424"/>
+ <text x="734" y="419" style="font-size:9">4,615,0,0,0</text>
+ <path class="p4" d="M 640 407 L 670 409 L 696 397 L 668 395 L 640 407"/>
+ <text x="669" y="402" style="font-size:8">4,616,0,0,0</text>
+ <path class="p4" d="M 670 409 L 699 411 L 723 399 L 696 397 L 670 409"/>
+ <text x="697" y="404" style="font-size:8">4,617,0,0,0</text>
+ <path class="p4" d="M 668 395 L 696 397 L 721 386 L 696 384 L 668 395"/>
+ <text x="695" y="391" style="font-size:8">4,618,0,0,0</text>
+ <path class="p4" d="M 696 397 L 723 399 L 746 388 L 721 386 L 696 397"/>
+ <text x="721" y="393" style="font-size:8">4,619,0,0,0</text>
+ <path class="p4" d="M 699 411 L 729 413 L 750 401 L 723 399 L 699 411"/>
+ <text x="725" y="406" style="font-size:8">4,620,0,0,0</text>
+ <path class="p4" d="M 729 413 L 759 414 L 777 403 L 750 401 L 729 413"/>
+ <text x="754" y="408" style="font-size:9">4,621,0,0,0</text>
+ <path class="p4" d="M 723 399 L 750 401 L 771 390 L 746 388 L 723 399"/>
+ <text x="747" y="395" style="font-size:8">4,622,0,0,0</text>
+ <path class="p4" d="M 750 401 L 777 403 L 796 392 L 771 390 L 750 401"/>
+ <text x="773" y="397" style="font-size:8">4,623,0,0,0</text>
+ <path class="p4" d="M 597 375 L 622 378 L 655 366 L 633 364 L 597 375"/>
+ <text x="627" y="371" style="font-size:8">4,624,0,0,0</text>
+ <path class="p4" d="M 622 378 L 646 380 L 678 368 L 655 366 L 622 378"/>
+ <text x="650" y="373" style="font-size:8">4,625,0,0,0</text>
+ <path class="p4" d="M 633 364 L 655 366 L 688 354 L 668 352 L 633 364"/>
+ <text x="661" y="359" style="font-size:8">4,626,0,0,0</text>
+ <path class="p4" d="M 655 366 L 678 368 L 708 357 L 688 354 L 655 366"/>
+ <text x="682" y="361" style="font-size:8">4,627,0,0,0</text>
+ <path class="p4" d="M 646 380 L 671 382 L 700 370 L 678 368 L 646 380"/>
+ <text x="674" y="375" style="font-size:8">4,628,0,0,0</text>
+ <path class="p4" d="M 671 382 L 696 384 L 723 372 L 700 370 L 671 382"/>
+ <text x="697" y="377" style="font-size:8">4,629,0,0,0</text>
+ <path class="p4" d="M 678 368 L 700 370 L 728 359 L 708 357 L 678 368"/>
+ <text x="704" y="363" style="font-size:8">4,630,0,0,0</text>
+ <path class="p4" d="M 700 370 L 723 372 L 749 361 L 728 359 L 700 370"/>
+ <text x="725" y="366" style="font-size:8">4,631,0,0,0</text>
+ <path class="p4" d="M 668 352 L 688 354 L 720 343 L 702 341 L 668 352"/>
+ <text x="695" y="347" style="font-size:8">4,632,0,0,0</text>
+ <path class="p4" d="M 688 354 L 708 357 L 738 345 L 720 343 L 688 354"/>
+ <text x="714" y="350" style="font-size:8">4,633,0,0,0</text>
+ <path class="p4" d="M 702 341 L 720 343 L 751 332 L 735 330 L 702 341"/>
+ <text x="727" y="336" style="font-size:7">4,634,0,0,0</text>
+ <line x1="735" y1="330" x2="751" y2="332"/>
+ <path class="p4" d="M 720 343 L 738 345 L 767 335 L 751 332 L 720 343"/>
+ <text x="744" y="339" style="font-size:7">4,635,0,0,0</text>
+ <line x1="751" y1="332" x2="767" y2="335"/>
+ <path class="p4" d="M 708 357 L 728 359 L 756 348 L 738 345 L 708 357"/>
+ <text x="733" y="352" style="font-size:8">4,636,0,0,0</text>
+ <path class="p4" d="M 728 359 L 749 361 L 774 350 L 756 348 L 728 359"/>
+ <text x="752" y="355" style="font-size:8">4,637,0,0,0</text>
+ <path class="p4" d="M 738 345 L 756 348 L 783 337 L 767 335 L 738 345"/>
+ <text x="761" y="341" style="font-size:8">4,638,0,0,0</text>
+ <line x1="767" y1="335" x2="783" y2="337"/>
+ <path class="p4" d="M 756 348 L 774 350 L 800 340 L 783 337 L 756 348"/>
+ <text x="779" y="344" style="font-size:8">4,639,0,0,0</text>
+ <line x1="783" y1="337" x2="800" y2="340"/>
+ <path class="p4" d="M 696 384 L 721 386 L 745 375 L 723 372 L 696 384"/>
+ <text x="721" y="379" style="font-size:8">4,640,0,0,0</text>
+ <path class="p4" d="M 721 386 L 746 388 L 768 377 L 745 375 L 721 386"/>
+ <text x="745" y="381" style="font-size:8">4,641,0,0,0</text>
+ <path class="p4" d="M 723 372 L 745 375 L 769 364 L 749 361 L 723 372"/>
+ <text x="746" y="368" style="font-size:8">4,642,0,0,0</text>
+ <path class="p4" d="M 745 375 L 768 377 L 790 366 L 769 364 L 745 375"/>
+ <text x="768" y="370" style="font-size:8">4,643,0,0,0</text>
+ <path class="p4" d="M 746 388 L 771 390 L 791 379 L 768 377 L 746 388"/>
+ <text x="769" y="383" style="font-size:8">4,644,0,0,0</text>
+ <path class="p4" d="M 771 390 L 796 392 L 814 381 L 791 379 L 771 390"/>
+ <text x="793" y="386" style="font-size:8">4,645,0,0,0</text>
+ <path class="p4" d="M 768 377 L 791 379 L 810 368 L 790 366 L 768 377"/>
+ <text x="790" y="372" style="font-size:8">4,646,0,0,0</text>
+ <path class="p4" d="M 791 379 L 814 381 L 831 371 L 810 368 L 791 379"/>
+ <text x="811" y="375" style="font-size:8">4,647,0,0,0</text>
+ <path class="p4" d="M 749 361 L 769 364 L 793 353 L 774 350 L 749 361"/>
+ <text x="771" y="357" style="font-size:8">4,648,0,0,0</text>
+ <path class="p4" d="M 769 364 L 790 366 L 811 355 L 793 353 L 769 364"/>
+ <text x="791" y="359" style="font-size:8">4,649,0,0,0</text>
+ <path class="p4" d="M 774 350 L 793 353 L 816 342 L 800 340 L 774 350"/>
+ <text x="796" y="346" style="font-size:8">4,650,0,0,0</text>
+ <line x1="800" y1="340" x2="816" y2="342"/>
+ <path class="p4" d="M 793 353 L 811 355 L 832 345 L 816 342 L 793 353"/>
+ <text x="813" y="349" style="font-size:8">4,651,0,0,0</text>
+ <line x1="816" y1="342" x2="832" y2="345"/>
+ <path class="p4" d="M 790 366 L 810 368 L 830 358 L 811 355 L 790 366"/>
+ <text x="810" y="362" style="font-size:8">4,652,0,0,0</text>
+ <path class="p4" d="M 810 368 L 831 371 L 848 360 L 830 358 L 810 368"/>
+ <text x="830" y="364" style="font-size:8">4,653,0,0,0</text>
+ <path class="p4" d="M 811 355 L 830 358 L 849 347 L 832 345 L 811 355"/>
+ <text x="830" y="351" style="font-size:8">4,654,0,0,0</text>
+ <line x1="832" y1="345" x2="849" y2="347"/>
+ <path class="p4" d="M 830 358 L 848 360 L 865 350 L 849 347 L 830 358"/>
+ <text x="848" y="354" style="font-size:8">4,655,0,0,0</text>
+ <line x1="849" y1="347" x2="865" y2="350"/>
+ <path class="p4" d="M 720 438 L 755 439 L 772 428 L 740 426 L 720 438"/>
+ <text x="747" y="433" style="font-size:9">4,656,0,0,0</text>
+ <path class="p4" d="M 755 439 L 790 441 L 804 429 L 772 428 L 755 439"/>
+ <text x="780" y="434" style="font-size:9">4,657,0,0,0</text>
+ <path class="p4" d="M 740 426 L 772 428 L 789 416 L 759 414 L 740 426"/>
+ <text x="765" y="421" style="font-size:9">4,658,0,0,0</text>
+ <path class="p4" d="M 772 428 L 804 429 L 818 418 L 789 416 L 772 428"/>
+ <text x="796" y="423" style="font-size:9">4,659,0,0,0</text>
+ <path class="p4" d="M 790 441 L 825 442 L 837 431 L 804 429 L 790 441"/>
+ <text x="814" y="436" style="font-size:9">4,660,0,0,0</text>
+ <path class="p4" d="M 825 442 L 859 444 L 869 433 L 837 431 L 825 442"/>
+ <text x="847" y="438" style="font-size:9">4,661,0,0,0</text>
+ <path class="p4" d="M 804 429 L 837 431 L 848 420 L 818 418 L 804 429"/>
+ <text x="827" y="425" style="font-size:9">4,662,0,0,0</text>
+ <path class="p4" d="M 837 431 L 869 433 L 879 422 L 848 420 L 837 431"/>
+ <text x="858" y="426" style="font-size:9">4,663,0,0,0</text>
+ <path class="p4" d="M 759 414 L 789 416 L 805 405 L 777 403 L 759 414"/>
+ <text x="782" y="410" style="font-size:9">4,664,0,0,0</text>
+ <path class="p4" d="M 789 416 L 818 418 L 832 407 L 805 405 L 789 416"/>
+ <text x="811" y="412" style="font-size:9">4,665,0,0,0</text>
+ <path class="p4" d="M 777 403 L 805 405 L 821 394 L 796 392 L 777 403"/>
+ <text x="800" y="399" style="font-size:8">4,666,0,0,0</text>
+ <path class="p4" d="M 805 405 L 832 407 L 846 396 L 821 394 L 805 405"/>
+ <text x="826" y="401" style="font-size:8">4,667,0,0,0</text>
+ <path class="p4" d="M 818 418 L 848 420 L 860 409 L 832 407 L 818 418"/>
+ <text x="840" y="414" style="font-size:9">4,668,0,0,0</text>
+ <path class="p4" d="M 848 420 L 879 422 L 888 411 L 860 409 L 848 420"/>
+ <text x="869" y="415" style="font-size:9">4,669,0,0,0</text>
+ <path class="p4" d="M 832 407 L 860 409 L 872 398 L 846 396 L 832 407"/>
+ <text x="853" y="403" style="font-size:9">4,670,0,0,0</text>
+ <path class="p4" d="M 860 409 L 888 411 L 897 401 L 872 398 L 860 409"/>
+ <text x="879" y="405" style="font-size:9">4,671,0,0,0</text>
+ <path class="p4" d="M 859 444 L 894 445 L 902 434 L 869 433 L 859 444"/>
+ <text x="881" y="439" style="font-size:9">4,672,0,0,0</text>
+ <path class="p4" d="M 894 445 L 930 447 L 934 436 L 902 434 L 894 445"/>
+ <text x="915" y="441" style="font-size:9">4,673,0,0,0</text>
+ <path class="p4" d="M 869 433 L 902 434 L 909 424 L 879 422 L 869 433"/>
+ <text x="890" y="428" style="font-size:9">4,674,0,0,0</text>
+ <path class="p4" d="M 902 434 L 934 436 L 939 426 L 909 424 L 902 434"/>
+ <text x="921" y="430" style="font-size:9">4,675,0,0,0</text>
+ <path class="p4" d="M 930 447 L 965 449 L 967 438 L 934 436 L 930 447"/>
+ <text x="949" y="442" style="font-size:9">4,676,0,0,0</text>
+ <path class="p4" d="M 965 449 L 1000 450 L 1000 440 L 967 438 L 965 449"/>
+ <text x="983" y="444" style="font-size:9">4,677,0,0,0</text>
+ <path class="p4" d="M 934 436 L 967 438 L 969 427 L 939 426 L 934 436"/>
+ <text x="953" y="432" style="font-size:9">4,678,0,0,0</text>
+ <path class="p4" d="M 967 438 L 1000 440 L 1000 429 L 969 427 L 967 438"/>
+ <text x="984" y="434" style="font-size:9">4,679,0,0,0</text>
+ <path class="p4" d="M 879 422 L 909 424 L 916 413 L 888 411 L 879 422"/>
+ <text x="898" y="417" style="font-size:9">4,680,0,0,0</text>
+ <path class="p4" d="M 909 424 L 939 426 L 944 415 L 916 413 L 909 424"/>
+ <text x="927" y="419" style="font-size:9">4,681,0,0,0</text>
+ <path class="p4" d="M 888 411 L 916 413 L 923 403 L 897 401 L 888 411"/>
+ <text x="906" y="407" style="font-size:9">4,682,0,0,0</text>
+ <path class="p4" d="M 916 413 L 944 415 L 948 405 L 923 403 L 916 413"/>
+ <text x="933" y="409" style="font-size:9">4,683,0,0,0</text>
+ <path class="p4" d="M 939 426 L 969 427 L 972 417 L 944 415 L 939 426"/>
+ <text x="956" y="421" style="font-size:9">4,684,0,0,0</text>
+ <path class="p4" d="M 969 427 L 1000 429 L 1000 419 L 972 417 L 969 427"/>
+ <text x="985" y="423" style="font-size:9">4,685,0,0,0</text>
+ <path class="p4" d="M 944 415 L 972 417 L 974 407 L 948 405 L 944 415"/>
+ <text x="959" y="411" style="font-size:9">4,686,0,0,0</text>
+ <path class="p4" d="M 972 417 L 1000 419 L 1000 409 L 974 407 L 972 417"/>
+ <text x="986" y="413" style="font-size:9">4,687,0,0,0</text>
+ <path class="p4" d="M 796 392 L 821 394 L 836 383 L 814 381 L 796 392"/>
+ <text x="817" y="388" style="font-size:8">4,688,0,0,0</text>
+ <path class="p4" d="M 821 394 L 846 396 L 860 386 L 836 383 L 821 394"/>
+ <text x="841" y="390" style="font-size:8">4,689,0,0,0</text>
+ <path class="p4" d="M 814 381 L 836 383 L 852 373 L 831 371 L 814 381"/>
+ <text x="833" y="377" style="font-size:8">4,690,0,0,0</text>
+ <path class="p4" d="M 836 383 L 860 386 L 873 375 L 852 373 L 836 383"/>
+ <text x="855" y="379" style="font-size:8">4,691,0,0,0</text>
+ <path class="p4" d="M 846 396 L 872 398 L 883 388 L 860 386 L 846 396"/>
+ <text x="865" y="392" style="font-size:8">4,692,0,0,0</text>
+ <path class="p4" d="M 872 398 L 897 401 L 906 390 L 883 388 L 872 398"/>
+ <text x="889" y="394" style="font-size:8">4,693,0,0,0</text>
+ <path class="p4" d="M 860 386 L 883 388 L 894 378 L 873 375 L 860 386"/>
+ <text x="877" y="382" style="font-size:8">4,694,0,0,0</text>
+ <path class="p4" d="M 883 388 L 906 390 L 915 380 L 894 378 L 883 388"/>
+ <text x="899" y="384" style="font-size:8">4,695,0,0,0</text>
+ <path class="p4" d="M 831 371 L 852 373 L 867 363 L 848 360 L 831 371"/>
+ <text x="850" y="367" style="font-size:8">4,696,0,0,0</text>
+ <path class="p4" d="M 852 373 L 873 375 L 886 365 L 867 363 L 852 373"/>
+ <text x="869" y="369" style="font-size:8">4,697,0,0,0</text>
+ <path class="p4" d="M 848 360 L 867 363 L 882 352 L 865 350 L 848 360"/>
+ <text x="866" y="356" style="font-size:8">4,698,0,0,0</text>
+ <line x1="865" y1="350" x2="882" y2="352"/>
+ <path class="p4" d="M 867 363 L 886 365 L 898 355 L 882 352 L 867 363"/>
+ <text x="883" y="359" style="font-size:8">4,699,0,0,0</text>
+ <line x1="882" y1="352" x2="898" y2="355"/>
+ <path class="p4" d="M 873 375 L 894 378 L 904 368 L 886 365 L 873 375"/>
+ <text x="889" y="371" style="font-size:8">4,700,0,0,0</text>
+ <path class="p4" d="M 894 378 L 915 380 L 923 370 L 904 368 L 894 378"/>
+ <text x="909" y="374" style="font-size:8">4,701,0,0,0</text>
+ <path class="p4" d="M 886 365 L 904 368 L 915 358 L 898 355 L 886 365"/>
+ <text x="901" y="361" style="font-size:8">4,702,0,0,0</text>
+ <line x1="898" y1="355" x2="915" y2="358"/>
+ <path class="p4" d="M 904 368 L 923 370 L 932 360 L 915 358 L 904 368"/>
+ <text x="919" y="364" style="font-size:8">4,703,0,0,0</text>
+ <line x1="915" y1="358" x2="932" y2="360"/>
+ <path class="p4" d="M 897 401 L 923 403 L 929 392 L 906 390 L 897 401"/>
+ <text x="914" y="396" style="font-size:8">4,704,0,0,0</text>
+ <path class="p4" d="M 923 403 L 948 405 L 953 395 L 929 392 L 923 403"/>
+ <text x="938" y="399" style="font-size:8">4,705,0,0,0</text>
+ <path class="p4" d="M 906 390 L 929 392 L 936 382 L 915 380 L 906 390"/>
+ <text x="922" y="386" style="font-size:8">4,706,0,0,0</text>
+ <path class="p4" d="M 929 392 L 953 395 L 957 385 L 936 382 L 929 392"/>
+ <text x="944" y="389" style="font-size:8">4,707,0,0,0</text>
+ <path class="p4" d="M 948 405 L 974 407 L 976 397 L 953 395 L 948 405"/>
+ <text x="963" y="401" style="font-size:9">4,708,0,0,0</text>
+ <path class="p4" d="M 974 407 L 1000 409 L 1000 399 L 976 397 L 974 407"/>
+ <text x="988" y="403" style="font-size:9">4,709,0,0,0</text>
+ <path class="p4" d="M 953 395 L 976 397 L 979 387 L 957 385 L 953 395"/>
+ <text x="966" y="391" style="font-size:8">4,710,0,0,0</text>
+ <path class="p4" d="M 976 397 L 1000 399 L 1000 390 L 979 387 L 976 397"/>
+ <text x="989" y="393" style="font-size:8">4,711,0,0,0</text>
+ <path class="p4" d="M 915 380 L 936 382 L 942 373 L 923 370 L 915 380"/>
+ <text x="929" y="376" style="font-size:8">4,712,0,0,0</text>
+ <path class="p4" d="M 936 382 L 957 385 L 962 375 L 942 373 L 936 382"/>
+ <text x="949" y="379" style="font-size:8">4,713,0,0,0</text>
+ <path class="p4" d="M 923 370 L 942 373 L 949 363 L 932 360 L 923 370"/>
+ <text x="937" y="366" style="font-size:8">4,714,0,0,0</text>
+ <line x1="932" y1="360" x2="949" y2="363"/>
+ <path class="p4" d="M 942 373 L 962 375 L 966 366 L 949 363 L 942 373"/>
+ <text x="955" y="369" style="font-size:8">4,715,0,0,0</text>
+ <line x1="949" y1="363" x2="966" y2="366"/>
+ <path class="p4" d="M 957 385 L 979 387 L 981 378 L 962 375 L 957 385"/>
+ <text x="969" y="381" style="font-size:8">4,716,0,0,0</text>
+ <path class="p4" d="M 979 387 L 1000 390 L 1000 380 L 981 378 L 979 387"/>
+ <text x="990" y="384" style="font-size:8">4,717,0,0,0</text>
+ <path class="p4" d="M 962 375 L 981 378 L 983 368 L 966 366 L 962 375"/>
+ <text x="973" y="372" style="font-size:8">4,718,0,0,0</text>
+ <line x1="966" y1="366" x2="983" y2="368"/>
+ <path class="p4" d="M 981 378 L 1000 380 L 1000 371 L 983 368 L 981 378"/>
+ <text x="991" y="374" style="font-size:8">4,719,0,0,0</text>
+ <line x1="983" y1="368" x2="1000" y2="371"/>
+ <path class="p4" d="M 1000 450 L 1035 449 L 1033 438 L 1000 440 L 1000 450"/>
+ <text x="1017" y="444" style="font-size:9">4,720,0,0,0</text>
+ <path class="p4" d="M 1035 449 L 1070 447 L 1066 436 L 1033 438 L 1035 449"/>
+ <text x="1051" y="442" style="font-size:9">4,721,0,0,0</text>
+ <path class="p4" d="M 1000 440 L 1033 438 L 1031 427 L 1000 429 L 1000 440"/>
+ <text x="1016" y="434" style="font-size:9">4,722,0,0,0</text>
+ <path class="p4" d="M 1033 438 L 1066 436 L 1061 426 L 1031 427 L 1033 438"/>
+ <text x="1047" y="432" style="font-size:9">4,723,0,0,0</text>
+ <path class="p4" d="M 1070 447 L 1106 445 L 1098 434 L 1066 436 L 1070 447"/>
+ <text x="1085" y="441" style="font-size:9">4,724,0,0,0</text>
+ <path class="p4" d="M 1106 445 L 1141 444 L 1131 433 L 1098 434 L 1106 445"/>
+ <text x="1119" y="439" style="font-size:9">4,725,0,0,0</text>
+ <path class="p4" d="M 1066 436 L 1098 434 L 1091 424 L 1061 426 L 1066 436"/>
+ <text x="1079" y="430" style="font-size:9">4,726,0,0,0</text>
+ <path class="p4" d="M 1098 434 L 1131 433 L 1121 422 L 1091 424 L 1098 434"/>
+ <text x="1110" y="428" style="font-size:9">4,727,0,0,0</text>
+ <path class="p4" d="M 1000 429 L 1031 427 L 1028 417 L 1000 419 L 1000 429"/>
+ <text x="1015" y="423" style="font-size:9">4,728,0,0,0</text>
+ <path class="p4" d="M 1031 427 L 1061 426 L 1056 415 L 1028 417 L 1031 427"/>
+ <text x="1044" y="421" style="font-size:9">4,729,0,0,0</text>
+ <path class="p4" d="M 1000 419 L 1028 417 L 1026 407 L 1000 409 L 1000 419"/>
+ <text x="1014" y="413" style="font-size:9">4,730,0,0,0</text>
+ <path class="p4" d="M 1028 417 L 1056 415 L 1052 405 L 1026 407 L 1028 417"/>
+ <text x="1041" y="411" style="font-size:9">4,731,0,0,0</text>
+ <path class="p4" d="M 1061 426 L 1091 424 L 1084 413 L 1056 415 L 1061 426"/>
+ <text x="1073" y="419" style="font-size:9">4,732,0,0,0</text>
+ <path class="p4" d="M 1091 424 L 1121 422 L 1112 411 L 1084 413 L 1091 424"/>
+ <text x="1102" y="417" style="font-size:9">4,733,0,0,0</text>
+ <path class="p4" d="M 1056 415 L 1084 413 L 1077 403 L 1052 405 L 1056 415"/>
+ <text x="1067" y="409" style="font-size:9">4,734,0,0,0</text>
+ <path class="p4" d="M 1084 413 L 1112 411 L 1103 401 L 1077 403 L 1084 413"/>
+ <text x="1094" y="407" style="font-size:9">4,735,0,0,0</text>
+ <path class="p4" d="M 1141 444 L 1175 442 L 1163 431 L 1131 433 L 1141 444"/>
+ <text x="1153" y="438" style="font-size:9">4,736,0,0,0</text>
+ <path class="p4" d="M 1175 442 L 1210 441 L 1196 429 L 1163 431 L 1175 442"/>
+ <text x="1186" y="436" style="font-size:9">4,737,0,0,0</text>
+ <path class="p4" d="M 1131 433 L 1163 431 L 1152 420 L 1121 422 L 1131 433"/>
+ <text x="1142" y="426" style="font-size:9">4,738,0,0,0</text>
+ <path class="p4" d="M 1163 431 L 1196 429 L 1182 418 L 1152 420 L 1163 431"/>
+ <text x="1173" y="425" style="font-size:9">4,739,0,0,0</text>
+ <path class="p4" d="M 1210 441 L 1245 439 L 1228 428 L 1196 429 L 1210 441"/>
+ <text x="1220" y="434" style="font-size:9">4,740,0,0,0</text>
+ <path class="p4" d="M 1245 439 L 1280 438 L 1260 426 L 1228 428 L 1245 439"/>
+ <text x="1253" y="433" style="font-size:9">4,741,0,0,0</text>
+ <path class="p4" d="M 1196 429 L 1228 428 L 1211 416 L 1182 418 L 1196 429"/>
+ <text x="1204" y="423" style="font-size:9">4,742,0,0,0</text>
+ <path class="p4" d="M 1228 428 L 1260 426 L 1241 414 L 1211 416 L 1228 428"/>
+ <text x="1235" y="421" style="font-size:9">4,743,0,0,0</text>
+ <path class="p4" d="M 1121 422 L 1152 420 L 1140 409 L 1112 411 L 1121 422"/>
+ <text x="1131" y="415" style="font-size:9">4,744,0,0,0</text>
+ <path class="p4" d="M 1152 420 L 1182 418 L 1168 407 L 1140 409 L 1152 420"/>
+ <text x="1160" y="414" style="font-size:9">4,745,0,0,0</text>
+ <path class="p4" d="M 1112 411 L 1140 409 L 1128 398 L 1103 401 L 1112 411"/>
+ <text x="1121" y="405" style="font-size:9">4,746,0,0,0</text>
+ <path class="p4" d="M 1140 409 L 1168 407 L 1154 396 L 1128 398 L 1140 409"/>
+ <text x="1147" y="403" style="font-size:9">4,747,0,0,0</text>
+ <path class="p4" d="M 1182 418 L 1211 416 L 1195 405 L 1168 407 L 1182 418"/>
+ <text x="1189" y="412" style="font-size:9">4,748,0,0,0</text>
+ <path class="p4" d="M 1211 416 L 1241 414 L 1223 403 L 1195 405 L 1211 416"/>
+ <text x="1218" y="410" style="font-size:9">4,749,0,0,0</text>
+ <path class="p4" d="M 1168 407 L 1195 405 L 1179 394 L 1154 396 L 1168 407"/>
+ <text x="1174" y="401" style="font-size:8">4,750,0,0,0</text>
+ <path class="p4" d="M 1195 405 L 1223 403 L 1204 392 L 1179 394 L 1195 405"/>
+ <text x="1200" y="399" style="font-size:8">4,751,0,0,0</text>
+ <path class="p4" d="M 1000 409 L 1026 407 L 1024 397 L 1000 399 L 1000 409"/>
+ <text x="1012" y="403" style="font-size:9">4,752,0,0,0</text>
+ <path class="p4" d="M 1026 407 L 1052 405 L 1047 395 L 1024 397 L 1026 407"/>
+ <text x="1037" y="401" style="font-size:9">4,753,0,0,0</text>
+ <path class="p4" d="M 1000 399 L 1024 397 L 1021 387 L 1000 390 L 1000 399"/>
+ <text x="1011" y="393" style="font-size:8">4,754,0,0,0</text>
+ <path class="p4" d="M 1024 397 L 1047 395 L 1043 385 L 1021 387 L 1024 397"/>
+ <text x="1034" y="391" style="font-size:8">4,755,0,0,0</text>
+ <path class="p4" d="M 1052 405 L 1077 403 L 1071 392 L 1047 395 L 1052 405"/>
+ <text x="1062" y="399" style="font-size:8">4,756,0,0,0</text>
+ <path class="p4" d="M 1077 403 L 1103 401 L 1094 390 L 1071 392 L 1077 403"/>
+ <text x="1086" y="396" style="font-size:8">4,757,0,0,0</text>
+ <path class="p4" d="M 1047 395 L 1071 392 L 1064 382 L 1043 385 L 1047 395"/>
+ <text x="1056" y="389" style="font-size:8">4,758,0,0,0</text>
+ <path class="p4" d="M 1071 392 L 1094 390 L 1085 380 L 1064 382 L 1071 392"/>
+ <text x="1078" y="386" style="font-size:8">4,759,0,0,0</text>
+ <path class="p4" d="M 1000 390 L 1021 387 L 1019 378 L 1000 380 L 1000 390"/>
+ <text x="1010" y="384" style="font-size:8">4,760,0,0,0</text>
+ <path class="p4" d="M 1021 387 L 1043 385 L 1038 375 L 1019 378 L 1021 387"/>
+ <text x="1031" y="381" style="font-size:8">4,761,0,0,0</text>
+ <path class="p4" d="M 1000 380 L 1019 378 L 1017 368 L 1000 371 L 1000 380"/>
+ <text x="1009" y="374" style="font-size:8">4,762,0,0,0</text>
+ <line x1="1000" y1="371" x2="1017" y2="368"/>
+ <path class="p4" d="M 1019 378 L 1038 375 L 1034 366 L 1017 368 L 1019 378"/>
+ <text x="1027" y="372" style="font-size:8">4,763,0,0,0</text>
+ <line x1="1017" y1="368" x2="1034" y2="366"/>
+ <path class="p4" d="M 1043 385 L 1064 382 L 1058 373 L 1038 375 L 1043 385"/>
+ <text x="1051" y="379" style="font-size:8">4,764,0,0,0</text>
+ <path class="p4" d="M 1064 382 L 1085 380 L 1077 370 L 1058 373 L 1064 382"/>
+ <text x="1071" y="376" style="font-size:8">4,765,0,0,0</text>
+ <path class="p4" d="M 1038 375 L 1058 373 L 1051 363 L 1034 366 L 1038 375"/>
+ <text x="1045" y="369" style="font-size:8">4,766,0,0,0</text>
+ <line x1="1034" y1="366" x2="1051" y2="363"/>
+ <path class="p4" d="M 1058 373 L 1077 370 L 1068 360 L 1051 363 L 1058 373"/>
+ <text x="1063" y="366" style="font-size:8">4,767,0,0,0</text>
+ <line x1="1051" y1="363" x2="1068" y2="360"/>
+ <path class="p4" d="M 1103 401 L 1128 398 L 1117 388 L 1094 390 L 1103 401"/>
+ <text x="1111" y="394" style="font-size:8">4,768,0,0,0</text>
+ <path class="p4" d="M 1128 398 L 1154 396 L 1140 386 L 1117 388 L 1128 398"/>
+ <text x="1135" y="392" style="font-size:8">4,769,0,0,0</text>
+ <path class="p4" d="M 1094 390 L 1117 388 L 1106 378 L 1085 380 L 1094 390"/>
+ <text x="1101" y="384" style="font-size:8">4,770,0,0,0</text>
+ <path class="p4" d="M 1117 388 L 1140 386 L 1127 375 L 1106 378 L 1117 388"/>
+ <text x="1123" y="382" style="font-size:8">4,771,0,0,0</text>
+ <path class="p4" d="M 1154 396 L 1179 394 L 1164 383 L 1140 386 L 1154 396"/>
+ <text x="1159" y="390" style="font-size:8">4,772,0,0,0</text>
+ <path class="p4" d="M 1179 394 L 1204 392 L 1186 381 L 1164 383 L 1179 394"/>
+ <text x="1183" y="388" style="font-size:8">4,773,0,0,0</text>
+ <path class="p4" d="M 1140 386 L 1164 383 L 1148 373 L 1127 375 L 1140 386"/>
+ <text x="1145" y="379" style="font-size:8">4,774,0,0,0</text>
+ <path class="p4" d="M 1164 383 L 1186 381 L 1169 371 L 1148 373 L 1164 383"/>
+ <text x="1167" y="377" style="font-size:8">4,775,0,0,0</text>
+ <path class="p4" d="M 1085 380 L 1106 378 L 1096 368 L 1077 370 L 1085 380"/>
+ <text x="1091" y="374" style="font-size:8">4,776,0,0,0</text>
+ <path class="p4" d="M 1106 378 L 1127 375 L 1114 365 L 1096 368 L 1106 378"/>
+ <text x="1111" y="371" style="font-size:8">4,777,0,0,0</text>
+ <path class="p4" d="M 1077 370 L 1096 368 L 1085 358 L 1068 360 L 1077 370"/>
+ <text x="1081" y="364" style="font-size:8">4,778,0,0,0</text>
+ <line x1="1068" y1="360" x2="1085" y2="358"/>
+ <path class="p4" d="M 1096 368 L 1114 365 L 1102 355 L 1085 358 L 1096 368"/>
+ <text x="1099" y="361" style="font-size:8">4,779,0,0,0</text>
+ <line x1="1085" y1="358" x2="1102" y2="355"/>
+ <path class="p4" d="M 1127 375 L 1148 373 L 1133 363 L 1114 365 L 1127 375"/>
+ <text x="1131" y="369" style="font-size:8">4,780,0,0,0</text>
+ <path class="p4" d="M 1148 373 L 1169 371 L 1152 360 L 1133 363 L 1148 373"/>
+ <text x="1150" y="367" style="font-size:8">4,781,0,0,0</text>
+ <path class="p4" d="M 1114 365 L 1133 363 L 1118 352 L 1102 355 L 1114 365"/>
+ <text x="1117" y="359" style="font-size:8">4,782,0,0,0</text>
+ <line x1="1102" y1="355" x2="1118" y2="352"/>
+ <path class="p4" d="M 1133 363 L 1152 360 L 1135 350 L 1118 352 L 1133 363"/>
+ <text x="1134" y="356" style="font-size:8">4,783,0,0,0</text>
+ <line x1="1118" y1="352" x2="1135" y2="350"/>
+ <path class="p4" d="M 1280 438 L 1314 436 L 1292 424 L 1260 426 L 1280 438"/>
+ <text x="1287" y="431" style="font-size:9">4,784,0,0,0</text>
+ <path class="p4" d="M 1314 436 L 1349 435 L 1324 423 L 1292 424 L 1314 436"/>
+ <text x="1320" y="429" style="font-size:9">4,785,0,0,0</text>
+ <path class="p4" d="M 1260 426 L 1292 424 L 1271 413 L 1241 414 L 1260 426"/>
+ <text x="1266" y="419" style="font-size:9">4,786,0,0,0</text>
+ <path class="p4" d="M 1292 424 L 1324 423 L 1301 411 L 1271 413 L 1292 424"/>
+ <text x="1297" y="418" style="font-size:9">4,787,0,0,0</text>
+ <path class="p4" d="M 1349 435 L 1383 433 L 1356 421 L 1324 423 L 1349 435"/>
+ <text x="1353" y="428" style="font-size:9">4,788,0,0,0</text>
+ <path class="p4" d="M 1383 433 L 1417 432 L 1388 419 L 1356 421 L 1383 433"/>
+ <text x="1386" y="426" style="font-size:9">4,789,0,0,0</text>
+ <path class="p4" d="M 1324 423 L 1356 421 L 1330 409 L 1301 411 L 1324 423"/>
+ <text x="1328" y="416" style="font-size:9">4,790,0,0,0</text>
+ <path class="p4" d="M 1356 421 L 1388 419 L 1360 407 L 1330 409 L 1356 421"/>
+ <text x="1358" y="414" style="font-size:9">4,791,0,0,0</text>
+ <path class="p4" d="M 1241 414 L 1271 413 L 1250 401 L 1223 403 L 1241 414"/>
+ <text x="1246" y="408" style="font-size:9">4,792,0,0,0</text>
+ <path class="p4" d="M 1271 413 L 1301 411 L 1277 399 L 1250 401 L 1271 413"/>
+ <text x="1275" y="406" style="font-size:8">4,793,0,0,0</text>
+ <path class="p4" d="M 1223 403 L 1250 401 L 1229 390 L 1204 392 L 1223 403"/>
+ <text x="1227" y="397" style="font-size:8">4,794,0,0,0</text>
+ <path class="p4" d="M 1250 401 L 1277 399 L 1254 388 L 1229 390 L 1250 401"/>
+ <text x="1253" y="395" style="font-size:8">4,795,0,0,0</text>
+ <path class="p4" d="M 1301 411 L 1330 409 L 1304 397 L 1277 399 L 1301 411"/>
+ <text x="1303" y="404" style="font-size:8">4,796,0,0,0</text>
+ <path class="p4" d="M 1330 409 L 1360 407 L 1332 395 L 1304 397 L 1330 409"/>
+ <text x="1331" y="402" style="font-size:8">4,797,0,0,0</text>
+ <path class="p4" d="M 1277 399 L 1304 397 L 1279 386 L 1254 388 L 1277 399"/>
+ <text x="1279" y="393" style="font-size:8">4,798,0,0,0</text>
+ <path class="p4" d="M 1304 397 L 1332 395 L 1304 384 L 1279 386 L 1304 397"/>
+ <text x="1305" y="391" style="font-size:8">4,799,0,0,0</text>
+ <path class="p4" d="M 1360 407 L 1389 405 L 1359 393 L 1332 395 L 1360 407"/>
+ <text x="1360" y="400" style="font-size:8">4,800,0,0,0</text>
+ <path class="p4" d="M 1389 405 L 1418 404 L 1385 391 L 1359 393 L 1389 405"/>
+ <text x="1388" y="398" style="font-size:8">4,801,0,0,0</text>
+ <path class="p4" d="M 1332 395 L 1359 393 L 1329 382 L 1304 384 L 1332 395"/>
+ <text x="1331" y="389" style="font-size:8">4,802,0,0,0</text>
+ <path class="p4" d="M 1359 393 L 1385 391 L 1354 380 L 1329 382 L 1359 393"/>
+ <text x="1357" y="387" style="font-size:8">4,803,0,0,0</text>
+ <path class="p4" d="M 1418 404 L 1447 402 L 1412 390 L 1385 391 L 1418 404"/>
+ <text x="1416" y="397" style="font-size:8">4,804,0,0,0</text>
+ <path class="p4" d="M 1447 402 L 1476 400 L 1439 388 L 1412 390 L 1447 402"/>
+ <text x="1444" y="395" style="font-size:8">4,805,0,0,0</text>
+ <path class="p4" d="M 1385 391 L 1412 390 L 1378 378 L 1354 380 L 1385 391"/>
+ <text x="1382" y="385" style="font-size:8">4,806,0,0,0</text>
+ <path class="p4" d="M 1412 390 L 1439 388 L 1403 375 L 1378 378 L 1412 390"/>
+ <text x="1408" y="383" style="font-size:8">4,807,0,0,0</text>
+ <path class="p4" d="M 1204 392 L 1229 390 L 1209 379 L 1186 381 L 1204 392"/>
+ <text x="1207" y="386" style="font-size:8">4,808,0,0,0</text>
+ <path class="p4" d="M 1229 390 L 1254 388 L 1232 377 L 1209 379 L 1229 390"/>
+ <text x="1231" y="383" style="font-size:8">4,809,0,0,0</text>
+ <path class="p4" d="M 1186 381 L 1209 379 L 1190 368 L 1169 371 L 1186 381"/>
+ <text x="1189" y="375" style="font-size:8">4,810,0,0,0</text>
+ <path class="p4" d="M 1209 379 L 1232 377 L 1210 366 L 1190 368 L 1209 379"/>
+ <text x="1210" y="372" style="font-size:8">4,811,0,0,0</text>
+ <path class="p4" d="M 1254 388 L 1279 386 L 1255 375 L 1232 377 L 1254 388"/>
+ <text x="1255" y="381" style="font-size:8">4,812,0,0,0</text>
+ <path class="p4" d="M 1279 386 L 1304 384 L 1277 372 L 1255 375 L 1279 386"/>
+ <text x="1279" y="379" style="font-size:8">4,813,0,0,0</text>
+ <path class="p4" d="M 1232 377 L 1255 375 L 1231 364 L 1210 366 L 1232 377"/>
+ <text x="1232" y="370" style="font-size:8">4,814,0,0,0</text>
+ <path class="p4" d="M 1255 375 L 1277 372 L 1251 361 L 1231 364 L 1255 375"/>
+ <text x="1254" y="368" style="font-size:8">4,815,0,0,0</text>
+ <path class="p4" d="M 1169 371 L 1190 368 L 1170 358 L 1152 360 L 1169 371"/>
+ <text x="1170" y="364" style="font-size:8">4,816,0,0,0</text>
+ <path class="p4" d="M 1190 368 L 1210 366 L 1189 355 L 1170 358 L 1190 368"/>
+ <text x="1190" y="362" style="font-size:8">4,817,0,0,0</text>
+ <path class="p4" d="M 1152 360 L 1170 358 L 1151 347 L 1135 350 L 1152 360"/>
+ <text x="1152" y="354" style="font-size:8">4,818,0,0,0</text>
+ <line x1="1135" y1="350" x2="1151" y2="347"/>
+ <path class="p4" d="M 1170 358 L 1189 355 L 1168 345 L 1151 347 L 1170 358"/>
+ <text x="1170" y="351" style="font-size:8">4,819,0,0,0</text>
+ <line x1="1151" y1="347" x2="1168" y2="345"/>
+ <path class="p4" d="M 1210 366 L 1231 364 L 1207 353 L 1189 355 L 1210 366"/>
+ <text x="1209" y="359" style="font-size:8">4,820,0,0,0</text>
+ <path class="p4" d="M 1231 364 L 1251 361 L 1226 350 L 1207 353 L 1231 364"/>
+ <text x="1229" y="357" style="font-size:8">4,821,0,0,0</text>
+ <path class="p4" d="M 1189 355 L 1207 353 L 1184 342 L 1168 345 L 1189 355"/>
+ <text x="1187" y="349" style="font-size:8">4,822,0,0,0</text>
+ <line x1="1168" y1="345" x2="1184" y2="342"/>
+ <path class="p4" d="M 1207 353 L 1226 350 L 1200 340 L 1184 342 L 1207 353"/>
+ <text x="1204" y="346" style="font-size:8">4,823,0,0,0</text>
+ <line x1="1184" y1="342" x2="1200" y2="340"/>
+ <path class="p4" d="M 1304 384 L 1329 382 L 1300 370 L 1277 372 L 1304 384"/>
+ <text x="1303" y="377" style="font-size:8">4,824,0,0,0</text>
+ <path class="p4" d="M 1329 382 L 1354 380 L 1322 368 L 1300 370 L 1329 382"/>
+ <text x="1326" y="375" style="font-size:8">4,825,0,0,0</text>
+ <path class="p4" d="M 1277 372 L 1300 370 L 1272 359 L 1251 361 L 1277 372"/>
+ <text x="1275" y="366" style="font-size:8">4,826,0,0,0</text>
+ <path class="p4" d="M 1300 370 L 1322 368 L 1292 357 L 1272 359 L 1300 370"/>
+ <text x="1296" y="363" style="font-size:8">4,827,0,0,0</text>
+ <path class="p4" d="M 1354 380 L 1378 378 L 1345 366 L 1322 368 L 1354 380"/>
+ <text x="1350" y="373" style="font-size:8">4,828,0,0,0</text>
+ <path class="p4" d="M 1378 378 L 1403 375 L 1367 364 L 1345 366 L 1378 378"/>
+ <text x="1373" y="371" style="font-size:8">4,829,0,0,0</text>
+ <path class="p4" d="M 1322 368 L 1345 366 L 1312 354 L 1292 357 L 1322 368"/>
+ <text x="1318" y="361" style="font-size:8">4,830,0,0,0</text>
+ <path class="p4" d="M 1345 366 L 1367 364 L 1332 352 L 1312 354 L 1345 366"/>
+ <text x="1339" y="359" style="font-size:8">4,831,0,0,0</text>
+ <path class="p4" d="M 1251 361 L 1272 359 L 1244 348 L 1226 350 L 1251 361"/>
+ <text x="1248" y="355" style="font-size:8">4,832,0,0,0</text>
+ <path class="p4" d="M 1272 359 L 1292 357 L 1262 345 L 1244 348 L 1272 359"/>
+ <text x="1267" y="352" style="font-size:8">4,833,0,0,0</text>
+ <path class="p4" d="M 1226 350 L 1244 348 L 1217 337 L 1200 340 L 1226 350"/>
+ <text x="1221" y="344" style="font-size:8">4,834,0,0,0</text>
+ <line x1="1200" y1="340" x2="1217" y2="337"/>
+ <path class="p4" d="M 1244 348 L 1262 345 L 1233 335 L 1217 337 L 1244 348"/>
+ <text x="1239" y="341" style="font-size:8">4,835,0,0,0</text>
+ <line x1="1217" y1="337" x2="1233" y2="335"/>
+ <path class="p4" d="M 1292 357 L 1312 354 L 1280 343 L 1262 345 L 1292 357"/>
+ <text x="1286" y="350" style="font-size:8">4,836,0,0,0</text>
+ <path class="p4" d="M 1312 354 L 1332 352 L 1298 341 L 1280 343 L 1312 354"/>
+ <text x="1305" y="347" style="font-size:8">4,837,0,0,0</text>
+ <path class="p4" d="M 1262 345 L 1280 343 L 1249 332 L 1233 335 L 1262 345"/>
+ <text x="1256" y="339" style="font-size:7">4,838,0,0,0</text>
+ <line x1="1233" y1="335" x2="1249" y2="332"/>
+ <path class="p4" d="M 1280 343 L 1298 341 L 1265 330 L 1249 332 L 1280 343"/>
+ <text x="1273" y="336" style="font-size:7">4,839,0,0,0</text>
+ <line x1="1249" y1="332" x2="1265" y2="330"/>
+ <path class="p4" d="M 1476 400 L 1476 389 L 1440 377 L 1439 388 L 1476 400"/>
+ <text x="1458" y="388" style="font-size:8">4,840,0,0,0</text>
+ <path class="p4" d="M 1476 389 L 1475 377 L 1440 367 L 1440 377 L 1476 389"/>
+ <text x="1458" y="377" style="font-size:8">4,841,0,0,0</text>
+ <path class="p4" d="M 1439 388 L 1440 377 L 1404 366 L 1403 375 L 1439 388"/>
+ <text x="1421" y="377" style="font-size:8">4,842,0,0,0</text>
+ <path class="p4" d="M 1440 377 L 1440 367 L 1406 357 L 1404 366 L 1440 377"/>
+ <text x="1423" y="367" style="font-size:8">4,843,0,0,0</text>
+ <path class="p4" d="M 1475 377 L 1475 366 L 1441 357 L 1440 367 L 1475 377"/>
+ <text x="1458" y="367" style="font-size:8">4,844,0,0,0</text>
+ <path class="p4" d="M 1475 366 L 1475 356 L 1442 347 L 1441 357 L 1475 366"/>
+ <text x="1458" y="356" style="font-size:8">4,845,0,0,0</text>
+ <path class="p4" d="M 1440 367 L 1441 357 L 1408 348 L 1406 357 L 1440 367"/>
+ <text x="1424" y="357" style="font-size:8">4,846,0,0,0</text>
+ <path class="p4" d="M 1441 357 L 1442 347 L 1410 339 L 1408 348 L 1441 357"/>
+ <text x="1425" y="347" style="font-size:7">4,847,0,0,0</text>
+ <path class="p4" d="M 1542 373 L 1539 361 L 1507 353 L 1508 364 L 1542 373"/>
+ <text x="1524" y="363" style="font-size:8">4,848,0,0,0</text>
+ <path class="p4" d="M 1539 361 L 1537 349 L 1505 342 L 1507 353 L 1539 361"/>
+ <text x="1522" y="351" style="font-size:7">4,849,0,0,0</text>
+ <path class="p4" d="M 1508 364 L 1507 353 L 1474 345 L 1475 356 L 1508 364"/>
+ <text x="1491" y="354" style="font-size:8">4,850,0,0,0</text>
+ <path class="p4" d="M 1507 353 L 1505 342 L 1474 335 L 1474 345 L 1507 353"/>
+ <text x="1490" y="344" style="font-size:7">4,851,0,0,0</text>
+ <path class="p4" d="M 1537 349 L 1534 337 L 1504 331 L 1505 342 L 1537 349"/>
+ <text x="1520" y="339" style="font-size:7">4,852,0,0,0</text>
+ <path class="p4" d="M 1534 337 L 1532 325 L 1502 320 L 1504 331 L 1534 337"/>
+ <text x="1518" y="328" style="font-size:7">4,853,0,0,0</text>
+ <path class="p4" d="M 1505 342 L 1504 331 L 1474 325 L 1474 335 L 1505 342"/>
+ <text x="1489" y="333" style="font-size:7">4,854,0,0,0</text>
+ <path class="p4" d="M 1504 331 L 1502 320 L 1473 315 L 1474 325 L 1504 331"/>
+ <text x="1488" y="322" style="font-size:7">4,855,0,0,0</text>
+ <path class="p4" d="M 1475 356 L 1474 345 L 1443 337 L 1442 347 L 1475 356"/>
+ <text x="1458" y="346" style="font-size:7">4,856,0,0,0</text>
+ <path class="p4" d="M 1474 345 L 1474 335 L 1443 328 L 1443 337 L 1474 345"/>
+ <text x="1458" y="336" style="font-size:7">4,857,0,0,0</text>
+ <path class="p4" d="M 1442 347 L 1443 337 L 1411 330 L 1410 339 L 1442 347"/>
+ <text x="1426" y="338" style="font-size:7">4,858,0,0,0</text>
+ <path class="p4" d="M 1443 337 L 1443 328 L 1413 321 L 1411 330 L 1443 337"/>
+ <text x="1427" y="329" style="font-size:7">4,859,0,0,0</text>
+ <path class="p4" d="M 1474 335 L 1474 325 L 1444 318 L 1443 328 L 1474 335"/>
+ <text x="1459" y="326" style="font-size:7">4,860,0,0,0</text>
+ <path class="p4" d="M 1474 325 L 1473 315 L 1445 309 L 1444 318 L 1474 325"/>
+ <text x="1459" y="317" style="font-size:7">4,861,0,0,0</text>
+ <path class="p4" d="M 1443 328 L 1444 318 L 1414 312 L 1413 321 L 1443 328"/>
+ <text x="1429" y="320" style="font-size:7">4,862,0,0,0</text>
+ <path class="p4" d="M 1444 318 L 1445 309 L 1416 304 L 1414 312 L 1444 318"/>
+ <text x="1430" y="311" style="font-size:7">4,863,0,0,0</text>
+ <path class="p4" d="M 1403 375 L 1404 366 L 1370 355 L 1367 364 L 1403 375"/>
+ <text x="1386" y="365" style="font-size:8">4,864,0,0,0</text>
+ <path class="p4" d="M 1404 366 L 1406 357 L 1372 347 L 1370 355 L 1404 366"/>
+ <text x="1388" y="356" style="font-size:8">4,865,0,0,0</text>
+ <path class="p4" d="M 1367 364 L 1370 355 L 1336 344 L 1332 352 L 1367 364"/>
+ <text x="1351" y="354" style="font-size:8">4,866,0,0,0</text>
+ <path class="p4" d="M 1370 355 L 1372 347 L 1339 337 L 1336 344 L 1370 355"/>
+ <text x="1354" y="346" style="font-size:8">4,867,0,0,0</text>
+ <path class="p4" d="M 1406 357 L 1408 348 L 1375 338 L 1372 347 L 1406 357"/>
+ <text x="1390" y="347" style="font-size:8">4,868,0,0,0</text>
+ <path class="p4" d="M 1408 348 L 1410 339 L 1378 330 L 1375 338 L 1408 348"/>
+ <text x="1392" y="339" style="font-size:7">4,869,0,0,0</text>
+ <path class="p4" d="M 1372 347 L 1375 338 L 1343 329 L 1339 337 L 1372 347"/>
+ <text x="1357" y="338" style="font-size:7">4,870,0,0,0</text>
+ <path class="p4" d="M 1375 338 L 1378 330 L 1346 322 L 1343 329 L 1375 338"/>
+ <text x="1360" y="330" style="font-size:7">4,871,0,0,0</text>
+ <path class="p4" d="M 1332 352 L 1336 344 L 1302 334 L 1298 341 L 1332 352"/>
+ <text x="1317" y="343" style="font-size:7">4,872,0,0,0</text>
+ <path class="p4" d="M 1336 344 L 1339 337 L 1307 327 L 1302 334 L 1336 344"/>
+ <text x="1321" y="335" style="font-size:7">4,873,0,0,0</text>
+ <path class="p4" d="M 1298 341 L 1302 334 L 1270 324 L 1265 330 L 1298 341"/>
+ <text x="1284" y="332" style="font-size:7">4,874,0,0,0</text>
+ <line x1="1265" y1="330" x2="1270" y2="324"/>
+ <path class="p4" d="M 1302 334 L 1307 327 L 1275 318 L 1270 324 L 1302 334"/>
+ <text x="1288" y="325" style="font-size:7">4,875,0,0,0</text>
+ <line x1="1270" y1="324" x2="1275" y2="318"/>
+ <path class="p4" d="M 1339 337 L 1343 329 L 1311 320 L 1307 327 L 1339 337"/>
+ <text x="1325" y="328" style="font-size:7">4,876,0,0,0</text>
+ <path class="p4" d="M 1343 329 L 1346 322 L 1316 314 L 1311 320 L 1343 329"/>
+ <text x="1329" y="321" style="font-size:7">4,877,0,0,0</text>
+ <path class="p4" d="M 1307 327 L 1311 320 L 1280 312 L 1275 318 L 1307 327"/>
+ <text x="1293" y="319" style="font-size:7">4,878,0,0,0</text>
+ <line x1="1275" y1="318" x2="1280" y2="312"/>
+ <path class="p4" d="M 1311 320 L 1316 314 L 1285 306 L 1280 312 L 1311 320"/>
+ <text x="1298" y="313" style="font-size:7">4,879,0,0,0</text>
+ <line x1="1280" y1="312" x2="1285" y2="306"/>
+ <path class="p4" d="M 1410 339 L 1411 330 L 1380 322 L 1378 330 L 1410 339"/>
+ <text x="1395" y="330" style="font-size:7">4,880,0,0,0</text>
+ <path class="p4" d="M 1411 330 L 1413 321 L 1383 314 L 1380 322 L 1411 330"/>
+ <text x="1397" y="322" style="font-size:7">4,881,0,0,0</text>
+ <path class="p4" d="M 1378 330 L 1380 322 L 1350 315 L 1346 322 L 1378 330"/>
+ <text x="1364" y="322" style="font-size:7">4,882,0,0,0</text>
+ <path class="p4" d="M 1380 322 L 1383 314 L 1353 308 L 1350 315 L 1380 322"/>
+ <text x="1367" y="315" style="font-size:7">4,883,0,0,0</text>
+ <path class="p4" d="M 1413 321 L 1414 312 L 1385 306 L 1383 314 L 1413 321"/>
+ <text x="1399" y="313" style="font-size:7">4,884,0,0,0</text>
+ <path class="p4" d="M 1414 312 L 1416 304 L 1388 299 L 1385 306 L 1414 312"/>
+ <text x="1401" y="305" style="font-size:7">4,885,0,0,0</text>
+ <path class="p4" d="M 1383 314 L 1385 306 L 1357 301 L 1353 308 L 1383 314"/>
+ <text x="1370" y="307" style="font-size:7">4,886,0,0,0</text>
+ <path class="p4" d="M 1385 306 L 1388 299 L 1360 294 L 1357 301 L 1385 306"/>
+ <text x="1372" y="300" style="font-size:7">4,887,0,0,0</text>
+ <path class="p4" d="M 1346 322 L 1350 315 L 1320 307 L 1316 314 L 1346 322"/>
+ <text x="1333" y="314" style="font-size:7">4,888,0,0,0</text>
+ <path class="p4" d="M 1350 315 L 1353 308 L 1324 301 L 1320 307 L 1350 315"/>
+ <text x="1337" y="308" style="font-size:7">4,889,0,0,0</text>
+ <path class="p4" d="M 1316 314 L 1320 307 L 1290 300 L 1285 306 L 1316 314"/>
+ <text x="1303" y="307" style="font-size:7">4,890,0,0,0</text>
+ <line x1="1285" y1="306" x2="1290" y2="300"/>
+ <path class="p4" d="M 1320 307 L 1324 301 L 1295 295 L 1290 300 L 1320 307"/>
+ <text x="1307" y="301" style="font-size:7">4,891,0,0,0</text>
+ <line x1="1290" y1="300" x2="1295" y2="295"/>
+ <path class="p4" d="M 1353 308 L 1357 301 L 1328 295 L 1324 301 L 1353 308"/>
+ <text x="1341" y="301" style="font-size:7">4,892,0,0,0</text>
+ <path class="p4" d="M 1357 301 L 1360 294 L 1332 289 L 1328 295 L 1357 301"/>
+ <text x="1344" y="294" style="font-size:7">4,893,0,0,0</text>
+ <path class="p4" d="M 1324 301 L 1328 295 L 1300 289 L 1295 295 L 1324 301"/>
+ <text x="1312" y="295" style="font-size:7">4,894,0,0,0</text>
+ <line x1="1295" y1="295" x2="1300" y2="289"/>
+ <path class="p4" d="M 1328 295 L 1332 289 L 1305 283 L 1300 289 L 1328 295"/>
+ <text x="1317" y="289" style="font-size:7">4,895,0,0,0</text>
+ <line x1="1300" y1="289" x2="1305" y2="283"/>
+ <path class="p4" d="M 1532 325 L 1529 314 L 1501 309 L 1502 320 L 1532 325"/>
+ <text x="1516" y="317" style="font-size:7">4,896,0,0,0</text>
+ <path class="p4" d="M 1529 314 L 1527 303 L 1500 299 L 1501 309 L 1529 314"/>
+ <text x="1514" y="306" style="font-size:7">4,897,0,0,0</text>
+ <path class="p4" d="M 1502 320 L 1501 309 L 1473 305 L 1473 315 L 1502 320"/>
+ <text x="1487" y="312" style="font-size:7">4,898,0,0,0</text>
+ <path class="p4" d="M 1501 309 L 1500 299 L 1473 295 L 1473 305 L 1501 309"/>
+ <text x="1486" y="302" style="font-size:7">4,899,0,0,0</text>
+ <path class="p4" d="M 1527 303 L 1524 292 L 1498 289 L 1500 299 L 1527 303"/>
+ <text x="1512" y="296" style="font-size:7">4,900,0,0,0</text>
+ <path class="p4" d="M 1524 292 L 1522 282 L 1497 279 L 1498 289 L 1524 292"/>
+ <text x="1510" y="285" style="font-size:6">4,901,0,0,0</text>
+ <path class="p4" d="M 1500 299 L 1498 289 L 1472 286 L 1473 295 L 1500 299"/>
+ <text x="1486" y="292" style="font-size:7">4,902,0,0,0</text>
+ <path class="p4" d="M 1498 289 L 1497 279 L 1472 277 L 1472 286 L 1498 289"/>
+ <text x="1485" y="283" style="font-size:6">4,903,0,0,0</text>
+ <path class="p4" d="M 1473 315 L 1473 305 L 1445 300 L 1445 309 L 1473 315"/>
+ <text x="1459" y="307" style="font-size:7">4,904,0,0,0</text>
+ <path class="p4" d="M 1473 305 L 1473 295 L 1446 291 L 1445 300 L 1473 305"/>
+ <text x="1459" y="298" style="font-size:7">4,905,0,0,0</text>
+ <path class="p4" d="M 1445 309 L 1445 300 L 1418 296 L 1416 304 L 1445 309"/>
+ <text x="1431" y="302" style="font-size:7">4,906,0,0,0</text>
+ <path class="p4" d="M 1445 300 L 1446 291 L 1419 288 L 1418 296 L 1445 300"/>
+ <text x="1432" y="294" style="font-size:7">4,907,0,0,0</text>
+ <path class="p4" d="M 1473 295 L 1472 286 L 1446 283 L 1446 291 L 1473 295"/>
+ <text x="1459" y="289" style="font-size:7">4,908,0,0,0</text>
+ <path class="p4" d="M 1472 286 L 1472 277 L 1447 274 L 1446 283 L 1472 286"/>
+ <text x="1459" y="280" style="font-size:6">4,909,0,0,0</text>
+ <path class="p4" d="M 1446 291 L 1446 283 L 1421 280 L 1419 288 L 1446 291"/>
+ <text x="1433" y="285" style="font-size:7">4,910,0,0,0</text>
+ <path class="p4" d="M 1446 283 L 1447 274 L 1422 272 L 1421 280 L 1446 283"/>
+ <text x="1434" y="277" style="font-size:6">4,911,0,0,0</text>
+ <path class="p4" d="M 1522 282 L 1520 271 L 1496 269 L 1497 279 L 1522 282"/>
+ <text x="1509" y="275" style="font-size:6">4,912,0,0,0</text>
+ <path class="p4" d="M 1520 271 L 1518 261 L 1494 260 L 1496 269 L 1520 271"/>
+ <text x="1507" y="265" style="font-size:6">4,913,0,0,0</text>
+ <path class="p4" d="M 1497 279 L 1496 269 L 1472 268 L 1472 277 L 1497 279"/>
+ <text x="1484" y="273" style="font-size:6">4,914,0,0,0</text>
+ <path class="p4" d="M 1496 269 L 1494 260 L 1471 259 L 1472 268 L 1496 269"/>
+ <text x="1483" y="264" style="font-size:6">4,915,0,0,0</text>
+ <path class="p4" d="M 1518 261 L 1516 251 L 1493 251 L 1494 260 L 1518 261"/>
+ <text x="1505" y="256" style="font-size:6">4,916,0,0,0</text>
+ <path class="p4" d="M 1516 251 L 1513 241 L 1492 241 L 1493 251 L 1516 251"/>
+ <text x="1504" y="246" style="font-size:6">4,917,0,0,0</text>
+ <path class="p4" d="M 1494 260 L 1493 251 L 1471 250 L 1471 259 L 1494 260"/>
+ <text x="1482" y="255" style="font-size:6">4,918,0,0,0</text>
+ <path class="p4" d="M 1493 251 L 1492 241 L 1471 241 L 1471 250 L 1493 251"/>
+ <text x="1482" y="246" style="font-size:6">4,919,0,0,0</text>
+ <path class="p4" d="M 1472 277 L 1472 268 L 1448 266 L 1447 274 L 1472 277"/>
+ <text x="1459" y="271" style="font-size:6">4,920,0,0,0</text>
+ <path class="p4" d="M 1472 268 L 1471 259 L 1448 257 L 1448 266 L 1472 268"/>
+ <text x="1460" y="262" style="font-size:6">4,921,0,0,0</text>
+ <path class="p4" d="M 1447 274 L 1448 266 L 1424 264 L 1422 272 L 1447 274"/>
+ <text x="1435" y="269" style="font-size:6">4,922,0,0,0</text>
+ <path class="p4" d="M 1448 266 L 1448 257 L 1425 256 L 1424 264 L 1448 266"/>
+ <text x="1436" y="261" style="font-size:6">4,923,0,0,0</text>
+ <path class="p4" d="M 1471 259 L 1471 250 L 1449 249 L 1448 257 L 1471 259"/>
+ <text x="1460" y="254" style="font-size:6">4,924,0,0,0</text>
+ <path class="p4" d="M 1471 250 L 1471 241 L 1449 241 L 1449 249 L 1471 250"/>
+ <text x="1460" y="245" style="font-size:6">4,925,0,0,0</text>
+ <path class="p4" d="M 1448 257 L 1449 249 L 1426 249 L 1425 256 L 1448 257"/>
+ <text x="1437" y="253" style="font-size:6">4,926,0,0,0</text>
+ <path class="p4" d="M 1449 249 L 1449 241 L 1428 241 L 1426 249 L 1449 249"/>
+ <text x="1438" y="245" style="font-size:6">4,927,0,0,0</text>
+ <path class="p4" d="M 1416 304 L 1418 296 L 1390 291 L 1388 299 L 1416 304"/>
+ <text x="1403" y="297" style="font-size:7">4,928,0,0,0</text>
+ <path class="p4" d="M 1418 296 L 1419 288 L 1393 284 L 1390 291 L 1418 296"/>
+ <text x="1405" y="290" style="font-size:7">4,929,0,0,0</text>
+ <path class="p4" d="M 1388 299 L 1390 291 L 1363 287 L 1360 294 L 1388 299"/>
+ <text x="1375" y="293" style="font-size:7">4,930,0,0,0</text>
+ <path class="p4" d="M 1390 291 L 1393 284 L 1367 280 L 1363 287 L 1390 291"/>
+ <text x="1378" y="285" style="font-size:7">4,931,0,0,0</text>
+ <path class="p4" d="M 1419 288 L 1421 280 L 1395 276 L 1393 284 L 1419 288"/>
+ <text x="1407" y="282" style="font-size:6">4,932,0,0,0</text>
+ <path class="p4" d="M 1421 280 L 1422 272 L 1397 269 L 1395 276 L 1421 280"/>
+ <text x="1409" y="274" style="font-size:6">4,933,0,0,0</text>
+ <path class="p4" d="M 1393 284 L 1395 276 L 1370 273 L 1367 280 L 1393 284"/>
+ <text x="1381" y="278" style="font-size:6">4,934,0,0,0</text>
+ <path class="p4" d="M 1395 276 L 1397 269 L 1373 267 L 1370 273 L 1395 276"/>
+ <text x="1384" y="271" style="font-size:6">4,935,0,0,0</text>
+ <path class="p4" d="M 1360 294 L 1363 287 L 1337 282 L 1332 289 L 1360 294"/>
+ <text x="1348" y="288" style="font-size:7">4,936,0,0,0</text>
+ <path class="p4" d="M 1363 287 L 1367 280 L 1341 276 L 1337 282 L 1363 287"/>
+ <text x="1352" y="281" style="font-size:7">4,937,0,0,0</text>
+ <path class="p4" d="M 1332 289 L 1337 282 L 1310 278 L 1305 283 L 1332 289"/>
+ <text x="1321" y="283" style="font-size:7">4,938,0,0,0</text>
+ <line x1="1305" y1="283" x2="1310" y2="278"/>
+ <path class="p4" d="M 1337 282 L 1341 276 L 1315 273 L 1310 278 L 1337 282"/>
+ <text x="1325" y="277" style="font-size:6">4,939,0,0,0</text>
+ <line x1="1310" y1="278" x2="1315" y2="273"/>
+ <path class="p4" d="M 1367 280 L 1370 273 L 1345 270 L 1341 276 L 1367 280"/>
+ <text x="1355" y="275" style="font-size:6">4,940,0,0,0</text>
+ <path class="p4" d="M 1370 273 L 1373 267 L 1348 264 L 1345 270 L 1370 273"/>
+ <text x="1359" y="269" style="font-size:6">4,941,0,0,0</text>
+ <path class="p4" d="M 1341 276 L 1345 270 L 1319 267 L 1315 273 L 1341 276"/>
+ <text x="1330" y="272" style="font-size:6">4,942,0,0,0</text>
+ <line x1="1315" y1="273" x2="1319" y2="267"/>
+ <path class="p4" d="M 1345 270 L 1348 264 L 1324 262 L 1319 267 L 1345 270"/>
+ <text x="1334" y="266" style="font-size:6">4,943,0,0,0</text>
+ <line x1="1319" y1="267" x2="1324" y2="262"/>
+ <path class="p4" d="M 1422 272 L 1424 264 L 1400 262 L 1397 269 L 1422 272"/>
+ <text x="1411" y="267" style="font-size:6">4,944,0,0,0</text>
+ <path class="p4" d="M 1424 264 L 1425 256 L 1402 255 L 1400 262 L 1424 264"/>
+ <text x="1413" y="259" style="font-size:6">4,945,0,0,0</text>
+ <path class="p4" d="M 1397 269 L 1400 262 L 1376 260 L 1373 267 L 1397 269"/>
+ <text x="1387" y="265" style="font-size:6">4,946,0,0,0</text>
+ <path class="p4" d="M 1400 262 L 1402 255 L 1379 254 L 1376 260 L 1400 262"/>
+ <text x="1389" y="258" style="font-size:6">4,947,0,0,0</text>
+ <path class="p4" d="M 1425 256 L 1426 249 L 1404 248 L 1402 255 L 1425 256"/>
+ <text x="1414" y="252" style="font-size:6">4,948,0,0,0</text>
+ <path class="p4" d="M 1426 249 L 1428 241 L 1406 241 L 1404 248 L 1426 249"/>
+ <text x="1416" y="245" style="font-size:6">4,949,0,0,0</text>
+ <path class="p4" d="M 1402 255 L 1404 248 L 1382 248 L 1379 254 L 1402 255"/>
+ <text x="1392" y="251" style="font-size:6">4,950,0,0,0</text>
+ <path class="p4" d="M 1404 248 L 1406 241 L 1385 241 L 1382 248 L 1404 248"/>
+ <text x="1394" y="245" style="font-size:6">4,951,0,0,0</text>
+ <path class="p4" d="M 1373 267 L 1376 260 L 1352 259 L 1348 264 L 1373 267"/>
+ <text x="1362" y="262" style="font-size:6">4,952,0,0,0</text>
+ <path class="p4" d="M 1376 260 L 1379 254 L 1356 253 L 1352 259 L 1376 260"/>
+ <text x="1366" y="256" style="font-size:6">4,953,0,0,0</text>
+ <path class="p4" d="M 1348 264 L 1352 259 L 1329 257 L 1324 262 L 1348 264"/>
+ <text x="1338" y="260" style="font-size:6">4,954,0,0,0</text>
+ <line x1="1324" y1="262" x2="1329" y2="257"/>
+ <path class="p4" d="M 1352 259 L 1356 253 L 1333 252 L 1329 257 L 1352 259"/>
+ <text x="1343" y="255" style="font-size:6">4,955,0,0,0</text>
+ <line x1="1329" y1="257" x2="1333" y2="252"/>
+ <path class="p4" d="M 1379 254 L 1382 248 L 1360 247 L 1356 253 L 1379 254"/>
+ <text x="1369" y="250" style="font-size:6">4,956,0,0,0</text>
+ <path class="p4" d="M 1382 248 L 1385 241 L 1364 241 L 1360 247 L 1382 248"/>
+ <text x="1373" y="244" style="font-size:6">4,957,0,0,0</text>
+ <path class="p4" d="M 1356 253 L 1360 247 L 1338 246 L 1333 252 L 1356 253"/>
+ <text x="1347" y="249" style="font-size:6">4,958,0,0,0</text>
+ <line x1="1333" y1="252" x2="1338" y2="246"/>
+ <path class="p4" d="M 1360 247 L 1364 241 L 1342 241 L 1338 246 L 1360 247"/>
+ <text x="1351" y="244" style="font-size:6">4,959,0,0,0</text>
+ <line x1="1338" y1="246" x2="1342" y2="241"/>
<!-- legend -->
- <rect x="6250" y="320" width="1280" height="660"/>
- <text x="6300" y="425" style="text-anchor:start; font-weight:bold; font-size:70">cell label</text>
- <text x="6330" y="530" style="text-anchor:start; font-style:oblique; font-size:70">level_number,</text>
- <text x="6330" y="635" style="text-anchor:start; font-style:oblique; font-size:70">cell_index,</text>
- <text x="6330" y="740" style="text-anchor:start; font-style:oblique; font-size:70">material_id,</text>
- <text x= "6330" y="845" style="text-anchor:start; font-style:oblique; font-size:70">subdomain_id,</text>
- <text x= "6330" y="950" style="text-anchor:start; font-style:oblique; font-size:70">level_subdomain_id</text>
- <text x="6250" y="1073" style="text-anchor:start; font-size:70">azimuth: 0°, polar: 45°</text>
+ <rect x="2000" y="96" width="386" height="199"/>
+ <text x="2015" y="128" style="text-anchor:start; font-weight:bold; font-size:21">cell label</text>
+ <text x="2024" y="159" style="text-anchor:start; font-style:oblique; font-size:21">level_number,</text>
+ <text x="2024" y="191" style="text-anchor:start; font-style:oblique; font-size:21">cell_index,</text>
+ <text x="2024" y="222" style="text-anchor:start; font-style:oblique; font-size:21">material_id,</text>
+ <text x= "2024" y="254" style="text-anchor:start; font-style:oblique; font-size:21">subdomain_id,</text>
+ <text x= "2024" y="285" style="text-anchor:start; font-style:oblique; font-size:21">level_subdomain_id</text>
+ <text x="2000" y="322" style="text-anchor:start; font-size:21">azimuth: 0°, polar: 60°</text>
<!-- colorbar -->
- <text x="6250" y="1424" style="text-anchor:start; font-weight:bold; font-size:70">level_number</text>
- <rect class="r0" x="6250" y="2946" width="100" height="733"/>
- <text x="6400.00" y="3337.50" style="text-anchor:start; font-size:70; font-weight:bold">0 min</text>
- <rect class="r1" x="6250" y="2213" width="100" height="733"/>
- <text x="6400.00" y="2604.50" style="text-anchor:start; font-size:70">1</text>
- <rect class="r2" x="6250" y="1480" width="100" height="733"/>
- <text x="6400.00" y="1871.50" style="text-anchor:start; font-size:70; font-weight:bold">2 max</text>
+ <text x="2000" y="429" style="text-anchor:start; font-weight:bold; font-size:21">level_number</text>
+ <rect class="r0" x="2000" y="974" width="30" height="132"/>
+ <text x="2045.00" y="1047.00" style="text-anchor:start; font-size:21; font-weight:bold">0 min</text>
+ <rect class="r1" x="2000" y="842" width="30" height="132"/>
+ <text x="2045.00" y="915.000" style="text-anchor:start; font-size:21">1</text>
+ <rect class="r2" x="2000" y="710" width="30" height="132"/>
+ <text x="2045.00" y="783.000" style="text-anchor:start; font-size:21">2</text>
+ <rect class="r3" x="2000" y="578" width="30" height="132"/>
+ <text x="2045.00" y="651.000" style="text-anchor:start; font-size:21">3</text>
+ <rect class="r4" x="2000" y="446" width="30" height="132"/>
+ <text x="2045.00" y="519.000" style="text-anchor:start; font-size:21; font-weight:bold">4 max</text>
</svg>
\ No newline at end of file
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: fe_nothing_04.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2009 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// interpolate() can not deal with FE_Nothing in an hp setting
+
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/fe/fe_nothing.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/grid_refinement.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/numerics/vector_tools.h>
+#include <deal.II/base/function.h>
+#include <deal.II/hp/fe_collection.h>
+#include <deal.II/hp/dof_handler.h>
+
+
+#include <fstream>
+
+
+template <int dim>
+void test ()
+{
+ Triangulation<dim> triangulation;
+ GridGenerator :: hyper_cube (triangulation, -0.5, 0.5);
+ triangulation.refine_global(4);
+
+ hp::FECollection<dim> fe_collection;
+
+ fe_collection.push_back (FESystem<dim>(FE_Q<dim>(2),dim,
+ FE_Q<dim>(1),1,
+ FE_Nothing<dim>(), dim));
+
+ fe_collection.push_back (FESystem<dim>(FE_Nothing<dim>(dim+1), 1,
+ FE_Q<dim>(2), dim));
+
+ hp::DoFHandler<dim> dof_handler (triangulation);
+
+
+
+ dof_handler.distribute_dofs (fe_collection);
+
+ deallog << " Number of active cells: "
+ << triangulation.n_active_cells()
+ << std::endl
+ << " Number of degrees of freedom: "
+ << dof_handler.n_dofs()
+ << std::endl;
+
+
+ Vector<double> solution(dof_handler.n_dofs());
+
+ VectorTools::interpolate(dof_handler,
+ ZeroFunction<dim>(2*dim+1),
+ solution);
+
+ deallog << "l2_norm = " << solution.l2_norm() << std::endl;
+}
+
+
+
+int main ()
+{
+ initlog();
+
+ //test<1> ();
+ test<2> ();
+ test<3> ();
+
+ deallog << "OK" << std::endl;
+}
--- /dev/null
+
+DEAL:: Number of active cells: 256
+DEAL:: Number of degrees of freedom: 2467
+DEAL::l2_norm = 0.00000
+DEAL:: Number of active cells: 4096
+DEAL:: Number of degrees of freedom: 112724
+DEAL::l2_norm = 0.00000
+DEAL::OK
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: fe_nothing_04.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2009 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// interpolate() can not deal with FE_Nothing, simplified version of fe_nothing_20.cc
+
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/fe/fe_nothing.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/grid_refinement.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/numerics/vector_tools.h>
+#include <deal.II/base/function.h>
+
+
+#include <fstream>
+
+
+template <int dim>
+void test ()
+{
+ Triangulation<dim> triangulation;
+ GridGenerator :: hyper_cube (triangulation, -0.5, 0.5);
+ triangulation.refine_global(4);
+
+ FESystem<dim> fe(FE_Nothing<dim>(),1, FE_Q<dim>(1),1);
+
+ deallog << "n support points: " << fe.get_unit_support_points().size() << std::endl;
+
+
+ DoFHandler<dim> dof_handler (triangulation);
+
+ dof_handler.distribute_dofs (fe);
+ deallog << " Number of active cells: "
+ << triangulation.n_active_cells()
+ << std::endl
+ << " Number of degrees of freedom: "
+ << dof_handler.n_dofs()
+ << std::endl;
+
+
+ Vector<double> solution(dof_handler.n_dofs());
+
+ VectorTools::interpolate(dof_handler,
+ ZeroFunction<dim>(2),
+ solution);
+
+ deallog << "l2_norm = " << solution.l2_norm() << std::endl;
+}
+
+
+
+int main ()
+{
+ initlog();
+
+ //test<1> ();
+ test<2> ();
+ test<3> ();
+
+ deallog << "OK" << std::endl;
+}
--- /dev/null
+
+DEAL::n support points: 4
+DEAL:: Number of active cells: 256
+DEAL:: Number of degrees of freedom: 289
+DEAL::l2_norm = 0.00000
+DEAL::n support points: 8
+DEAL:: Number of active cells: 4096
+DEAL:: Number of degrees of freedom: 4913
+DEAL::l2_norm = 0.00000
+DEAL::OK
data_out.add_data_vector (solution,
solution_names,
- DataOut<dim,DoFHandler<dim> >::type_automatic,
+ DataOut<dim,DoFHandler<dim> >::type_dof_data,
interpretation);
data_out.build_patches (fe.degree);
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::constructor1
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkConstructor1(FullMatrix<number> &A, FullMatrix<number> &B)
+ {
+ deallog << "Init with empty constructor" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P;
+ P.initialize(A, B, mem);
+
+ deallog << "Multiplying with all ones vector" << std::endl;
+ Vector<number> V(B.n());
+ for (unsigned int i = 0; i < V.size(); ++i)
+ V(i) = 1;
+
+ Vector<number> O(A.m());
+
+ P.vmult(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.vmult(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ checkConstructor1<double>(A, B);
+
+}
--- /dev/null
+
+DEAL::Init with empty constructor
+DEAL::Multiplying with all ones vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::17.0000 29.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::constructor2
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkConstructor2(FullMatrix<number> &A, FullMatrix<number> &B)
+ {
+ deallog << "Init with vector memory. Delayed reinit" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(mem);
+ P.reinit(A, B);
+
+ deallog << "Multiplying with all ones vector" << std::endl;
+ Vector<number> V(B.n());
+ for (unsigned int i = 0; i < V.size(); ++i)
+ V(i) = 1;
+ Vector<number> O(A.m());
+
+ P.vmult(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.vmult(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ checkConstructor2<double>(A, B);
+
+}
--- /dev/null
+
+DEAL::Init with vector memory. Delayed reinit
+DEAL::Multiplying with all ones vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::17.0000 29.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::constructor3
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkConstructor3(FullMatrix<number> &A, FullMatrix<number> &B)
+ {
+ deallog << "Init with vector memory, matrix 1 and matrix 2" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(A, B, mem);
+
+ deallog << "Multiplying with all ones vector" << std::endl;
+ Vector<number> V(B.n());
+ for (unsigned int i = 0; i < V.size(); ++i)
+ V(i) = 1;
+ Vector<number> O(A.m());
+
+ P.vmult(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.vmult(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ checkConstructor3<double>(A, B);
+
+}
--- /dev/null
+
+DEAL::Init with vector memory, matrix 1 and matrix 2
+DEAL::Multiplying with all ones vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::17.0000 29.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::vmult
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkVmult(FullMatrix<number> &A, FullMatrix<number> &B, Vector<number> &V)
+ {
+ deallog << "vmult" << std::endl;
+
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(A, B, mem);
+
+ Vector<number> O(A.m());
+
+ P.vmult(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.vmult(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ Vector<double> V(2);
+ V(0) = 1;
+ V(1) = 2;
+
+ checkVmult<double>(A, B, V);
+
+}
--- /dev/null
+
+DEAL::vmult
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::28.0000 48.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::vmult_add
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkVmult_add(FullMatrix<number> &A, FullMatrix<number> &B,
+ Vector<number> &V)
+ {
+ deallog << "vmult_add" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(A, B, mem);
+
+ deallog
+ << "Result vector set to all ones and to be added with product result vector"
+ << std::endl;
+ Vector<number> O(V.size());
+ for (unsigned int i = 0; i < O.size(); ++i)
+ O(i) = 1;
+
+ P.vmult_add(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+ for (unsigned int i = 0; i < O_.size(); ++i)
+ O_(i) = 1;
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.vmult_add(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ Vector<double> V(2);
+ V(0) = 1;
+ V(1) = 2;
+
+ checkVmult_add<double>(A, B, V);
+
+}
--- /dev/null
+
+DEAL::vmult_add
+DEAL::Result vector set to all ones and to be added with product result vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::29.0000 49.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::Tvmult
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkTvmult(FullMatrix<number> &A, FullMatrix<number> &B, Vector<number> &V)
+ {
+ deallog << "Tvmult" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(A, B, mem);
+
+ Vector<number> O(V.size());
+
+ P.Tvmult(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.Tvmult(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ Vector<double> V(2);
+ V(0) = 1;
+ V(1) = 2;
+
+ checkTvmult<double>(A, B, V);
+
+}
--- /dev/null
+
+DEAL::Tvmult
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::26.0000 49.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::Tvmult_add
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkTvmult_add(FullMatrix<number> &A, FullMatrix<number> &B,
+ Vector<number> &V)
+ {
+ deallog << "Tvmult_add" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(A, B, mem);
+
+ deallog
+ << "Result vector set to all ones and to be added with product result vector"
+ << std::endl;
+ Vector<number> O(V.size());
+ for (unsigned int i = 0; i < O.size(); ++i)
+ O(i) = 1;
+
+ P.Tvmult_add(O, V);
+
+ // Check the dimensions of the result matrix
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+ for (unsigned int i = 0; i < O_.size(); ++i)
+ O_(i) = 1;
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.Tvmult_add(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+
+ Vector<double> V(2);
+ V(0) = 1;
+ V(1) = 2;
+
+ checkTvmult_add<double>(A, B, V);
+
+}
--- /dev/null
+
+DEAL::Tvmult_add
+DEAL::Result vector set to all ones and to be added with product result vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::27.0000 50.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: product_matrix_01.cc 32491 2014-02-14 20:52:51Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Check ProductMatrix::clear
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/lac/matrix_lib.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/vector.h>
+
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+template<typename number>
+ void
+ checkClear(FullMatrix<number> &A, FullMatrix<number> &B,
+ FullMatrix<number> &C, FullMatrix<number> &D)
+ {
+ deallog << "clear" << std::endl;
+ deallog << "Init with vector memory, matrix 1 and matrix 2" << std::endl;
+ GrowingVectorMemory < Vector<number> > mem;
+ ProductMatrix < Vector<number> > P(A, B, mem);
+
+ deallog << "Multiplying with all ones vector" << std::endl;
+ Vector<number> V(B.n());
+ for (unsigned int i = 0; i < V.size(); ++i)
+ V(i) = 1;
+
+ Vector<number> O(A.m());
+
+ P.vmult(O, V);
+
+ // Check the dimensions of the result vector
+ Assert(A.m() == O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: O=(A*B)*V
+ FullMatrix<number> AB_Product(A.m(), B.n());
+ Vector<number> O_(A.m());
+
+ A.mmult(AB_Product, B, false);
+ AB_Product.vmult(O_, V);
+
+ Assert(O == O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < O.size(); ++i)
+ deallog << O(i) << '\t';
+ deallog << std::endl;
+
+ deallog << "Clearing product matrix" << std::endl;
+ P.clear();
+
+ deallog << "Reinitializing product matrix with matrix 3 and matrix 4"
+ << std::endl;
+ P.reinit(C, D);
+
+ deallog << "Multiplying with all ones vector" << std::endl;
+ Vector<number> _V(D.n());
+ for (unsigned int i = 0; i < _V.size(); ++i)
+ _V(i) = 1;
+
+ Vector<number> _O(C.m());
+
+ P.vmult(_O, _V);
+
+ // Check the dimensions of the result vector
+ Assert(C.m() == _O.size(), ExcInternalError());
+ deallog << "Dimensions of result vector verified" << std::endl;
+
+ // Verifying results with Method 2: _O=(C*D)*_V
+ FullMatrix<number> CD_Product(C.m(), D.n());
+ Vector<number> _O_(C.m());
+
+ C.mmult(CD_Product, D, false);
+ CD_Product.vmult(_O_, _V);
+
+ Assert(_O == _O_, ExcInternalError());
+ deallog << "Result vector data verified" << std::endl;
+
+ for (unsigned int i = 0; i < _O.size(); ++i)
+ deallog << _O(i) << '\t';
+ deallog << std::endl;
+ }
+
+int
+main()
+{
+ std::ofstream logfile("output");
+ deallog << std::fixed;
+ deallog << std::setprecision(4);
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ const double Adata[] =
+ { 2, 3, 4, 5 };
+
+ const double Bdata[] =
+ { 0, 1, 2, 3 };
+
+ const double Cdata[] =
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ const double Ddata[] =
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18 };
+
+ FullMatrix<double> A(2, 2);
+ FullMatrix<double> B(2, 2);
+ FullMatrix<double> C(3, 3);
+ FullMatrix<double> D(3, 3);
+
+ A.fill(Adata);
+ B.fill(Bdata);
+ C.fill(Cdata);
+ D.fill(Ddata);
+
+ checkClear<double>(A, B, C, D);
+
+}
--- /dev/null
+
+DEAL::clear
+DEAL::Init with vector memory, matrix 1 and matrix 2
+DEAL::Multiplying with all ones vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::17.0000 29.0000
+DEAL::Clearing product matrix
+DEAL::Reinitializing product matrix with matrix 3 and matrix 4
+DEAL::Multiplying with all ones vector
+DEAL::Dimensions of result vector verified
+DEAL::Result vector data verified
+DEAL::270.0000 648.0000 1026.0000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// same test as matrix_vector_stokes_noflux, but allocating FEEvaluation on
+// the heap (using AlignedVector) instead of allocating it on the stack. Tests
+// also copy constructors of FEEvaluation.
+
+#include "../tests.h"
+
+std::ofstream logfile("output");
+
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/base/aligned_vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_renumbering.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/block_sparse_matrix.h>
+#include <deal.II/lac/block_sparsity_pattern.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <fstream>
+#include <iostream>
+#include <complex>
+
+
+
+template <int dim, int degree_p, typename VectorType>
+class MatrixFreeTest
+{
+public:
+ typedef typename DoFHandler<dim>::active_cell_iterator CellIterator;
+ typedef double Number;
+
+ MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
+ data (data_in)
+ {};
+
+ void
+ local_apply (const MatrixFree<dim,Number> &data,
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ typedef VectorizedArray<Number> vector_t;
+ // allocate FEEvaluation. This test will test proper alignment
+ AlignedVector<FEEvaluation<dim,degree_p+1,degree_p+2,dim,Number> > velocity
+ (1, FEEvaluation<dim,degree_p+1,degree_p+2,dim,Number>(data, 0));
+ AlignedVector<FEEvaluation<dim,degree_p, degree_p+2,1, Number> > pressure
+ (1, FEEvaluation<dim,degree_p, degree_p+2,1, Number>(data, 1));
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ velocity[0].reinit (cell);
+ velocity[0].read_dof_values (src.block(0));
+ velocity[0].evaluate (false,true,false);
+ pressure[0].reinit (cell);
+ pressure[0].read_dof_values (src.block(1));
+ pressure[0].evaluate (true,false,false);
+
+ for (unsigned int q=0; q<FEEvaluation<dim,degree_p,degree_p+2,1,Number>::n_q_points; ++q)
+ {
+ SymmetricTensor<2,dim,vector_t> sym_grad_u =
+ velocity[0].get_symmetric_gradient (q);
+ vector_t pres = pressure[0].get_value(q);
+ vector_t div = -velocity[0].get_divergence(q);
+ pressure[0].submit_value (div, q);
+
+ // subtract p * I
+ for (unsigned int d=0; d<dim; ++d)
+ sym_grad_u[d][d] -= pres;
+
+ velocity[0].submit_symmetric_gradient(sym_grad_u, q);
+ }
+
+ velocity[0].integrate (false,true);
+ velocity[0].distribute_local_to_global (dst.block(0));
+ pressure[0].integrate (true,false);
+ pressure[0].distribute_local_to_global (dst.block(1));
+ }
+ }
+
+
+ void vmult (VectorType &dst,
+ const VectorType &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,degree_p,VectorType>::local_apply,
+ this, dst, src);
+ };
+
+private:
+ const MatrixFree<dim,Number> &data;
+};
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> triangulation;
+ GridGenerator::hyper_shell (triangulation, Point<dim>(),
+ 0.5, 1., 96, true);
+ static HyperShellBoundary<dim> boundary;
+ triangulation.set_boundary (0, boundary);
+ triangulation.set_boundary (1, boundary);
+ triangulation.begin_active()->set_refine_flag();
+ triangulation.last()->set_refine_flag();
+ triangulation.execute_coarsening_and_refinement();
+ triangulation.refine_global (3-dim);
+ triangulation.last()->set_refine_flag();
+ triangulation.execute_coarsening_and_refinement();
+
+ MappingQ<dim> mapping (3);
+ FE_Q<dim> fe_u_scal (fe_degree+1);
+ FESystem<dim> fe_u (fe_u_scal,dim);
+ FE_Q<dim> fe_p (fe_degree);
+ FESystem<dim> fe (fe_u_scal, dim, fe_p, 1);
+ DoFHandler<dim> dof_handler_u (triangulation);
+ DoFHandler<dim> dof_handler_p (triangulation);
+ DoFHandler<dim> dof_handler (triangulation);
+
+ MatrixFree<dim,double> mf_data;
+
+ ConstraintMatrix constraints, constraints_u, constraints_p;
+
+ BlockSparsityPattern sparsity_pattern;
+ BlockSparseMatrix<double> system_matrix;
+
+ BlockVector<double> solution;
+ BlockVector<double> system_rhs;
+ BlockVector<double> mf_solution;
+
+ dof_handler.distribute_dofs (fe);
+ dof_handler_u.distribute_dofs (fe_u);
+ dof_handler_p.distribute_dofs (fe_p);
+ std::vector<unsigned int> stokes_sub_blocks (dim+1,0);
+ stokes_sub_blocks[dim] = 1;
+ DoFRenumbering::component_wise (dof_handler, stokes_sub_blocks);
+
+ std::set<unsigned char> no_normal_flux_boundaries;
+ no_normal_flux_boundaries.insert (0);
+ no_normal_flux_boundaries.insert (1);
+ DoFTools::make_hanging_node_constraints (dof_handler,
+ constraints);
+ VectorTools::compute_no_normal_flux_constraints (dof_handler, 0,
+ no_normal_flux_boundaries,
+ constraints, mapping);
+ constraints.close ();
+ DoFTools::make_hanging_node_constraints (dof_handler_u,
+ constraints_u);
+ VectorTools::compute_no_normal_flux_constraints (dof_handler_u, 0,
+ no_normal_flux_boundaries,
+ constraints_u, mapping);
+ constraints_u.close ();
+ DoFTools::make_hanging_node_constraints (dof_handler_p,
+ constraints_p);
+ constraints_p.close ();
+
+ std::vector<types::global_dof_index> dofs_per_block (2);
+ DoFTools::count_dofs_per_block (dof_handler, dofs_per_block,
+ stokes_sub_blocks);
+
+ //std::cout << "Number of active cells: "
+ // << triangulation.n_active_cells()
+ // << std::endl
+ // << "Number of degrees of freedom: "
+ // << dof_handler.n_dofs()
+ // << " (" << n_u << '+' << n_p << ')'
+ // << std::endl;
+
+ {
+ BlockCompressedSimpleSparsityPattern csp (2,2);
+
+ for (unsigned int d=0; d<2; ++d)
+ for (unsigned int e=0; e<2; ++e)
+ csp.block(d,e).reinit (dofs_per_block[d], dofs_per_block[e]);
+
+ csp.collect_sizes();
+
+ DoFTools::make_sparsity_pattern (dof_handler, csp, constraints, false);
+ sparsity_pattern.copy_from (csp);
+ }
+
+ system_matrix.reinit (sparsity_pattern);
+
+ // this is from step-22
+ {
+ QGauss<dim> quadrature_formula(fe_degree+2);
+
+ FEValues<dim> fe_values (mapping, fe, quadrature_formula,
+ update_values |
+ update_JxW_values |
+ update_gradients);
+
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ FullMatrix<double> local_matrix (dofs_per_cell, dofs_per_cell);
+
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ const FEValuesExtractors::Vector velocities (0);
+ const FEValuesExtractors::Scalar pressure (dim);
+
+ std::vector<SymmetricTensor<2,dim> > phi_grads_u (dofs_per_cell);
+ std::vector<double> div_phi_u (dofs_per_cell);
+ std::vector<double> phi_p (dofs_per_cell);
+
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ {
+ fe_values.reinit (cell);
+ local_matrix = 0;
+
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ for (unsigned int k=0; k<dofs_per_cell; ++k)
+ {
+ phi_grads_u[k] = fe_values[velocities].symmetric_gradient (k, q);
+ div_phi_u[k] = fe_values[velocities].divergence (k, q);
+ phi_p[k] = fe_values[pressure].value (k, q);
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<=i; ++j)
+ {
+ local_matrix(i,j) += (phi_grads_u[i] * phi_grads_u[j]
+ - div_phi_u[i] * phi_p[j]
+ - phi_p[i] * div_phi_u[j])
+ * fe_values.JxW(q);
+ }
+ }
+ }
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=i+1; j<dofs_per_cell; ++j)
+ local_matrix(i,j) = local_matrix(j,i);
+
+ cell->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (local_matrix,
+ local_dof_indices,
+ system_matrix);
+ }
+ }
+
+
+ solution.reinit (2);
+ for (unsigned int d=0; d<2; ++d)
+ solution.block(d).reinit (dofs_per_block[d]);
+ solution.collect_sizes ();
+
+ system_rhs.reinit (solution);
+ mf_solution.reinit (solution);
+
+ // fill system_rhs with random numbers
+ for (unsigned int j=0; j<system_rhs.block(0).size(); ++j)
+ if (constraints_u.is_constrained(j) == false)
+ {
+ const double val = -1 + 2.*(double)Testing::rand()/double(RAND_MAX);
+ system_rhs.block(0)(j) = val;
+ }
+ for (unsigned int j=0; j<system_rhs.block(1).size(); ++j)
+ if (constraints_p.is_constrained(j) == false)
+ {
+ const double val = -1 + 2.*(double)Testing::rand()/double(RAND_MAX);
+ system_rhs.block(1)(j) = val;
+ }
+
+ // setup matrix-free structure
+ {
+ std::vector<const DoFHandler<dim>*> dofs;
+ dofs.push_back(&dof_handler_u);
+ dofs.push_back(&dof_handler_p);
+ std::vector<const ConstraintMatrix *> constraints;
+ constraints.push_back (&constraints_u);
+ constraints.push_back (&constraints_p);
+ QGauss<1> quad(fe_degree+2);
+ // no parallelism
+ mf_data.reinit (mapping, dofs, constraints, quad,
+ typename MatrixFree<dim>::AdditionalData
+ (MPI_COMM_WORLD,
+ MatrixFree<dim>::AdditionalData::none));
+ }
+
+ system_matrix.vmult (solution, system_rhs);
+
+ MatrixFreeTest<dim,fe_degree,BlockVector<double> > mf (mf_data);
+ mf.vmult (mf_solution, system_rhs);
+
+ // Verification
+ mf_solution -= solution;
+ const double error = mf_solution.linfty_norm();
+ const double relative = solution.linfty_norm();
+ deallog << "Verification fe degree " << fe_degree << ": "
+ << error/relative << std::endl << std::endl;
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog << std::endl << "Test with doubles" << std::endl << std::endl;
+ deallog.threshold_double(1.e-12);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ test<2,3>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ deallog.pop();
+ }
+}
+
--- /dev/null
+
+DEAL::
+DEAL::Test with doubles
+DEAL::
+DEAL:2d::Verification fe degree 1: 0
+DEAL:2d::
+DEAL:2d::Verification fe degree 2: 0
+DEAL:2d::
+DEAL:2d::Verification fe degree 3: 0
+DEAL:2d::
+DEAL:3d::Verification fe degree 1: 0
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Tests CellwiseInverseMassMatrix on DG elements by comparing its action on a
+// random vector to a CG solver
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/fe/mapping_q.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/precondition.h>
+
+#include <deal.II/matrix_free/operators.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+
+ MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
+ data (data_in)
+ {};
+
+ void
+ local_mass_operator (const MatrixFree<dim,Number> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values (src);
+ fe_eval.evaluate (true, false);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ fe_eval.submit_value (fe_eval.get_value(q),q);
+ fe_eval.integrate (true, false);
+ fe_eval.distribute_local_to_global (dst);
+ }
+ }
+
+ void
+ local_inverse_mass_operator (const MatrixFree<dim,Number> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
+ MatrixFreeOperators::CellwiseInverseMassMatrix<dim,fe_degree,1,Number> mass_inv(fe_eval);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+ AlignedVector<VectorizedArray<Number> > inverse_coefficients(n_q_points);
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ mass_inv.fill_inverse_JxW_values(inverse_coefficients);
+ fe_eval.read_dof_values (src);
+ mass_inv.apply(inverse_coefficients, 1, fe_eval.begin_dof_values(),
+ fe_eval.begin_dof_values());
+ fe_eval.distribute_local_to_global (dst);
+ }
+ }
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number,VECTOR>::local_mass_operator,
+ this, dst, src);
+ };
+
+ void apply_inverse (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number,VECTOR>::local_inverse_mass_operator,
+ this, dst, src);
+ };
+
+private:
+ const MatrixFree<dim,Number> &data;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+ MappingQ<dim> mapping(4);
+
+ MatrixFree<dim,number> mf_data;
+ {
+ const QGauss<1> quad (fe_degree+1);
+ typename MatrixFree<dim,number>::AdditionalData data;
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_color;
+ data.tasks_block_size = 3;
+ ConstraintMatrix constraints;
+
+ mf_data.reinit (mapping, dof, constraints, quad, data);
+ }
+
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
+ Vector<number> in (dof.n_dofs()), inverse (dof.n_dofs()), reference(dof.n_dofs());
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ }
+
+ mf.apply_inverse (inverse, in);
+
+ SolverControl control(1000, 1e-12);
+ // do not output iteration numbers to log file because these are too
+ // sensitive
+ std::ostringstream stream;
+ deallog.attach(stream);
+ SolverCG<Vector<number> > solver(control);
+ solver.solve (mf, reference, in, PreconditionIdentity());
+ deallog.attach(logfile);
+
+ inverse -= reference;
+ const double diff_norm = inverse.linfty_norm() / reference.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_ball (tria);
+ static const HyperBallBoundary<dim> boundary;
+ tria.set_boundary (0, boundary);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ FE_DGQ<dim> fe (fe_degree);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+
+ do_test<dim, fe_degree, double> (dof);
+
+ if (dim == 2)
+ {
+ deallog.push("float");
+ deallog.threshold_double(1.e-6);
+ do_test<dim, fe_degree, float> (dof);
+ deallog.threshold_double(1.e-10);
+ deallog.pop();
+ }
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(1.e-10);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ test<2,4>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d:float::Testing FE_DGQ<2>(1)
+
+DEAL:2d:float::Norm of difference: 0
+DEAL:2d:float::
+DEAL:2d::Testing FE_DGQ<2>(2)
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d:float::Testing FE_DGQ<2>(2)
+
+DEAL:2d:float::Norm of difference: 0
+DEAL:2d:float::
+DEAL:2d::Testing FE_DGQ<2>(4)
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d:float::Testing FE_DGQ<2>(4)
+
+DEAL:2d:float::Norm of difference: 0
+DEAL:2d:float::
+DEAL:3d::Testing FE_DGQ<3>(1)
+
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FE_DGQ<3>(2)
+
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Tests CellwiseInverseMassMatrix on vector DG elements, otherwise the same
+// as inverse_mass_01.cc
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/precondition.h>
+
+#include <deal.II/matrix_free/operators.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+
+ MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
+ data (data_in)
+ {};
+
+ void
+ local_mass_operator (const MatrixFree<dim,Number> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim,fe_degree,fe_degree+1,dim,Number> fe_eval (data);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values (src);
+ fe_eval.evaluate (true, false);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ fe_eval.submit_value (fe_eval.get_value(q),q);
+ fe_eval.integrate (true, false);
+ fe_eval.distribute_local_to_global (dst);
+ }
+ }
+
+ void
+ local_inverse_mass_operator (const MatrixFree<dim,Number> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim,fe_degree,fe_degree+1,dim,Number> fe_eval (data);
+ MatrixFreeOperators::CellwiseInverseMassMatrix<dim,fe_degree,dim,Number> mass_inv(fe_eval);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+ AlignedVector<VectorizedArray<Number> > inverse_coefficients(n_q_points);
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ mass_inv.fill_inverse_JxW_values(inverse_coefficients);
+ fe_eval.read_dof_values (src);
+ mass_inv.apply(inverse_coefficients, dim, fe_eval.begin_dof_values(),
+ fe_eval.begin_dof_values());
+ fe_eval.distribute_local_to_global (dst);
+ }
+ }
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number,VECTOR>::local_mass_operator,
+ this, dst, src);
+ };
+
+ void apply_inverse (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number,VECTOR>::local_inverse_mass_operator,
+ this, dst, src);
+ };
+
+private:
+ const MatrixFree<dim,Number> &data;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+
+ MatrixFree<dim,number> mf_data;
+ {
+ const QGauss<1> quad (fe_degree+1);
+ typename MatrixFree<dim,number>::AdditionalData data;
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_color;
+ data.tasks_block_size = 3;
+ ConstraintMatrix constraints;
+
+ mf_data.reinit (dof, constraints, quad, data);
+ }
+
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
+ Vector<number> in (dof.n_dofs()), inverse (dof.n_dofs()), reference(dof.n_dofs());
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ }
+
+ mf.apply_inverse (inverse, in);
+
+ SolverControl control(1000, 1e-12);
+ std::ostringstream stream;
+ deallog.attach(stream);
+ SolverCG<Vector<number> > solver(control);
+ solver.solve (mf, reference, in, PreconditionIdentity());
+ deallog.attach(logfile);
+
+ inverse -= reference;
+ const double diff_norm = inverse.linfty_norm() / reference.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_cube (tria, -1, 1);
+ tria.refine_global(1);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ const unsigned int degree = fe_degree;
+ FESystem<dim> fe (FE_DGQ<dim>(degree), dim);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+
+ do_test<dim, fe_degree, double> (dof);
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(5.e-11);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ test<2,4>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FESystem<2>[FE_DGQ<2>(1)^2]
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FESystem<2>[FE_DGQ<2>(2)^2]
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FESystem<2>[FE_DGQ<2>(4)^2]
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:3d::Testing FESystem<3>[FE_DGQ<3>(1)^3]
+
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FESystem<3>[FE_DGQ<3>(2)^3]
+
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Tests CellwiseInverseMassMatrix on vector DG elements, similar test as
+// inverse_mass_02 but using different coefficients on different components
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/fe/mapping_q.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/precondition.h>
+
+#include <deal.II/matrix_free/operators.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+
+ MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
+ data (data_in)
+ {};
+
+ void
+ local_mass_operator (const MatrixFree<dim,Number> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim,fe_degree,fe_degree+1,3,Number> fe_eval (data);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values (src);
+ fe_eval.evaluate (true, false);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ Tensor<1,3,VectorizedArray<double> > val = fe_eval.get_value(q);
+ val[0] *= make_vectorized_array(0.8314159);
+ val[1] *= make_vectorized_array(2.3);
+ val[2] *= make_vectorized_array(1.98);
+ fe_eval.submit_value (val, q);
+ }
+ fe_eval.integrate (true, false);
+ fe_eval.distribute_local_to_global (dst);
+ }
+ }
+
+ void
+ local_inverse_mass_operator (const MatrixFree<dim,Number> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim,fe_degree,fe_degree+1,3,Number> fe_eval (data);
+ MatrixFreeOperators::CellwiseInverseMassMatrix<dim,fe_degree,3,Number> mass_inv(fe_eval);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+ AlignedVector<VectorizedArray<Number> > inverse_coefficients(3*n_q_points);
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ mass_inv.fill_inverse_JxW_values(inverse_coefficients);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ inverse_coefficients[q] *= make_vectorized_array(1./0.8314159);
+ inverse_coefficients[n_q_points+q] *= make_vectorized_array(1./2.3);
+ inverse_coefficients[2*n_q_points+q] *= make_vectorized_array(1./1.98);
+ }
+ fe_eval.read_dof_values (src);
+ mass_inv.apply(inverse_coefficients, 3, fe_eval.begin_dof_values(),
+ fe_eval.begin_dof_values());
+ fe_eval.distribute_local_to_global (dst);
+ }
+ }
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number,VECTOR>::local_mass_operator,
+ this, dst, src);
+ };
+
+ void apply_inverse (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number,VECTOR>::local_inverse_mass_operator,
+ this, dst, src);
+ };
+
+private:
+ const MatrixFree<dim,Number> &data;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+
+ MappingQ<dim> mapping(4);
+ MatrixFree<dim,number> mf_data;
+ {
+ const QGauss<1> quad (fe_degree+1);
+ typename MatrixFree<dim,number>::AdditionalData data;
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_color;
+ data.tasks_block_size = 3;
+ ConstraintMatrix constraints;
+
+ mf_data.reinit (mapping, dof, constraints, quad, data);
+ }
+
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
+ Vector<number> in (dof.n_dofs()), inverse (dof.n_dofs()), reference(dof.n_dofs());
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ }
+
+ mf.apply_inverse (inverse, in);
+
+ SolverControl control(10000, 1e-12);
+ std::ostringstream stream;
+ deallog.attach(stream);
+ SolverCG<Vector<number> > solver(control);
+ solver.solve (mf, reference, in, PreconditionIdentity());
+ deallog.attach(logfile);
+
+ inverse -= reference;
+ const double diff_norm = inverse.linfty_norm() / reference.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_ball (tria);
+ static const HyperBallBoundary<dim> boundary;
+ tria.set_boundary (0, boundary);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ const unsigned int degree = fe_degree;
+ FESystem<dim> fe (FE_DGQ<dim>(degree),3);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+
+ do_test<dim, fe_degree, double> (dof);
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(5.e-11);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ test<2,4>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FESystem<2>[FE_DGQ<2>(1)^3]
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FESystem<2>[FE_DGQ<2>(2)^3]
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FESystem<2>[FE_DGQ<2>(4)^3]
+
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:3d::Testing FESystem<3>[FE_DGQ<3>(1)^3]
+
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FESystem<3>[FE_DGQ<3>(2)^3]
+
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2013 by the deal.II authors
+// Copyright (C) 2013-2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
if (cell->center().norm()<0.2)
cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
+#ifndef DEBUG
if (dim < 3 || fe_degree < 2)
tria.refine_global(1);
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.last()->set_refine_flag();
tria.execute_coarsening_and_refinement();
tria.refine_global(4-dim);
+#endif
cell = tria.begin_active ();
for (unsigned int i=0; i<10-3*dim; ++i)
{
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// this test is similar to matrix_vector_07, but implements the operations for
+// FE_DGP instead of FE_DGQ (where there is no complete tensor product and
+// different routines need to be used). The data is still not very useful
+// because the matrix does not include face terms actually present in an
+// approximation of the Laplacian. It only contains cell terms.
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/fe/fe_dgp.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <deal.II/lac/vector.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename VECTOR>
+void
+helmholtz_operator_dgp (const MatrixFree<dim,typename VECTOR::value_type> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range)
+{
+ typedef typename VECTOR::value_type Number;
+ FEEvaluationDGP<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values (src);
+ fe_eval.evaluate (true, true, false);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
+ fe_eval.integrate (true,true);
+ fe_eval.distribute_local_to_global (dst);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+ typedef VectorizedArray<Number> vector_t;
+
+ MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
+ data (data_in)
+ {};
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ const std_cxx1x::function<void(const MatrixFree<dim,typename VECTOR::value_type> &,
+ VECTOR &,
+ const VECTOR &,
+ const std::pair<unsigned int,unsigned int> &)>
+ wrap = helmholtz_operator_dgp<dim,fe_degree,VECTOR>;
+ data.cell_loop (wrap, dst, src);
+ };
+
+private:
+ const MatrixFree<dim,Number> &data;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof,
+ const ConstraintMatrix &constraints)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+
+ MatrixFree<dim,number> mf_data;
+ {
+ const QGauss<1> quad (fe_degree+1);
+ typename MatrixFree<dim,number>::AdditionalData data;
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_color;
+ data.tasks_block_size = 3;
+
+ mf_data.reinit (dof, constraints, quad, data);
+ }
+
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
+ Vector<number> in (dof.n_dofs()), out (dof.n_dofs());
+ Vector<number> in_dist (dof.n_dofs());
+ Vector<number> out_dist (in_dist);
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ if (constraints.is_constrained(i))
+ continue;
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ in_dist(i) = entry;
+ }
+
+ mf.vmult (out_dist, in_dist);
+
+
+ // assemble sparse matrix with (\nabla v, \nabla u) + (v, 10 * u)
+ SparsityPattern sparsity;
+ {
+ CompressedSimpleSparsityPattern csp(dof.n_dofs(), dof.n_dofs());
+ DoFTools::make_sparsity_pattern (dof, csp, constraints, true);
+ sparsity.copy_from(csp);
+ }
+ SparseMatrix<double> sparse_matrix (sparsity);
+ {
+ QGauss<dim> quadrature_formula(fe_degree+1);
+
+ FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
+ update_values | update_gradients |
+ update_JxW_values);
+
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ {
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
+ }
+ }
+
+ sparse_matrix.vmult (out, in);
+ out -= out_dist;
+ const double diff_norm = out.linfty_norm() / out_dist.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_ball (tria);
+ static const HyperBallBoundary<dim> boundary;
+ tria.set_boundary (0, boundary);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ FE_DGP<dim> fe (fe_degree);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+ ConstraintMatrix constraints;
+
+ do_test<dim, fe_degree, double> (dof, constraints);
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(5.e-11);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
+
+
--- /dev/null
+
+DEAL:2d::Testing FE_DGP<2>(1)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FE_DGP<2>(2)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:3d::Testing FE_DGP<3>(1)
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FE_DGP<3>(2)
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Same as matrix_vector_14, but using more quadrature points than the FE
+// degree would suggest
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/fe/fe_dgp.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <deal.II/lac/vector.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename VECTOR>
+void
+helmholtz_operator_dgp (const MatrixFree<dim,typename VECTOR::value_type> &data,
+ VECTOR &dst,
+ const VECTOR &src,
+ const std::pair<unsigned int,unsigned int> &cell_range)
+{
+ typedef typename VECTOR::value_type Number;
+ FEEvaluationDGP<dim,fe_degree,fe_degree+2,1,Number> fe_eval (data);
+ const unsigned int n_q_points = fe_eval.n_q_points;
+
+ for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
+ {
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values (src);
+ fe_eval.evaluate (true, true, false);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
+ fe_eval.integrate (true,true);
+ fe_eval.distribute_local_to_global (dst);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+ typedef VectorizedArray<Number> vector_t;
+
+ MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
+ data (data_in)
+ {};
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ dst = 0;
+ const std_cxx1x::function<void(const MatrixFree<dim,typename VECTOR::value_type> &,
+ VECTOR &,
+ const VECTOR &,
+ const std::pair<unsigned int,unsigned int> &)>
+ wrap = helmholtz_operator_dgp<dim,fe_degree,VECTOR>;
+ data.cell_loop (wrap, dst, src);
+ };
+
+private:
+ const MatrixFree<dim,Number> &data;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof,
+ const ConstraintMatrix &constraints)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+
+ MatrixFree<dim,number> mf_data;
+ {
+ const QGauss<1> quad (fe_degree+2);
+ typename MatrixFree<dim,number>::AdditionalData data;
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_color;
+ data.tasks_block_size = 3;
+
+ mf_data.reinit (dof, constraints, quad, data);
+ }
+
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
+ Vector<number> in (dof.n_dofs()), out (dof.n_dofs());
+ Vector<number> in_dist (dof.n_dofs());
+ Vector<number> out_dist (in_dist);
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ if (constraints.is_constrained(i))
+ continue;
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ in_dist(i) = entry;
+ }
+
+ mf.vmult (out_dist, in_dist);
+
+
+ // assemble sparse matrix with (\nabla v, \nabla u) + (v, 10 * u)
+ SparsityPattern sparsity;
+ {
+ CompressedSimpleSparsityPattern csp(dof.n_dofs(), dof.n_dofs());
+ DoFTools::make_sparsity_pattern (dof, csp, constraints, true);
+ sparsity.copy_from(csp);
+ }
+ SparseMatrix<double> sparse_matrix (sparsity);
+ {
+ QGauss<dim> quadrature_formula(fe_degree+2);
+
+ FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
+ update_values | update_gradients |
+ update_JxW_values);
+
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ {
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
+ }
+ }
+
+ sparse_matrix.vmult (out, in);
+ out -= out_dist;
+ const double diff_norm = out.linfty_norm() / out_dist.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_ball (tria);
+ static const HyperBallBoundary<dim> boundary;
+ tria.set_boundary (0, boundary);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ FE_DGP<dim> fe (fe_degree);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+ ConstraintMatrix constraints;
+
+ do_test<dim, fe_degree, double> (dof, constraints);
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(5.e-11);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
+
+
--- /dev/null
+
+DEAL:2d::Testing FE_DGP<2>(1)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FE_DGP<2>(2)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:3d::Testing FE_DGP<3>(1)
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FE_DGP<3>(2)
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// this test is similar to matrix_vector_06, but implements the operations on
+// the fly from an FEValues implementation instead of data cached in
+// MatrixFree.
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <deal.II/lac/vector.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+ MatrixFreeTest(const DoFHandler<dim> &dof_handler,
+ const ConstraintMatrix &constraints)
+ :
+ dof_handler (dof_handler),
+ constraints (constraints)
+ {}
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ MappingFEEvaluation<dim,Number> mapping(QGauss<1>(fe_degree+1),
+ update_gradients | update_values |
+ update_JxW_values);
+ VECTOR src_cpy = src;
+ constraints.distribute(src_cpy);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval(mapping, dof_handler);
+ dst = 0;
+ typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for ( ; cell != endc; ++cell)
+ {
+ mapping.reinit(cell);
+ fe_eval.read_dof_values (src_cpy);
+ fe_eval.evaluate (true, true, false);
+ for (unsigned int q=0; q<fe_eval.n_q_points; ++q)
+ {
+ fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
+ fe_eval.integrate (true,true);
+ fe_eval.distribute_local_to_global (dst);
+ }
+ constraints.condense(dst);
+ };
+
+private:
+ const DoFHandler<dim> &dof_handler;
+ const ConstraintMatrix &constraints;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof,
+ const ConstraintMatrix &constraints,
+ const unsigned int parallel_option = 0)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+ if (parallel_option > 0)
+ deallog << "Parallel option: " << parallel_option << std::endl;
+ //std::cout << "Number of cells: " << dof.get_tria().n_active_cells() << std::endl;
+ //std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+ //std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
+
+ MatrixFreeTest<dim,fe_degree,number> mf (dof, constraints);
+ Vector<number> in (dof.n_dofs()), out (dof.n_dofs());
+ Vector<number> in_dist (dof.n_dofs());
+ Vector<number> out_dist (in_dist);
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ if (constraints.is_constrained(i))
+ continue;
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ in_dist(i) = entry;
+ }
+
+ mf.vmult (out_dist, in_dist);
+
+
+ // assemble sparse matrix with (\nabla v, \nabla u) + (v, 10 * u)
+ SparsityPattern sparsity;
+ {
+ CompressedSimpleSparsityPattern csp(dof.n_dofs(), dof.n_dofs());
+ DoFTools::make_sparsity_pattern (dof, csp, constraints, true);
+ sparsity.copy_from(csp);
+ }
+ SparseMatrix<double> sparse_matrix (sparsity);
+ {
+ QGauss<dim> quadrature_formula(fe_degree+1);
+
+ FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
+ update_values | update_gradients |
+ update_JxW_values);
+
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ {
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
+ }
+ }
+
+ sparse_matrix.vmult (out, in);
+ out -= out_dist;
+ const double diff_norm = out.linfty_norm() / out_dist.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_ball (tria);
+ static const HyperBallBoundary<dim> boundary;
+ tria.set_boundary (0, boundary);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ FE_Q<dim> fe (fe_degree);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+ ConstraintMatrix constraints;
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
+ constraints);
+ constraints.close();
+
+ do_test<dim, fe_degree, double> (dof, constraints);
+
+ if (dim == 2)
+ {
+ deallog.push("float");
+ deallog.threshold_double(1.e-6);
+ do_test<dim, fe_degree, float> (dof, constraints);
+ deallog.threshold_double(5.e-11);
+ deallog.pop();
+ }
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(5.e-11);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ test<2,4>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d:float::Testing FE_Q<2>(1)
+DEAL:2d:float::Norm of difference: 0
+DEAL:2d:float::
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d:float::Testing FE_Q<2>(2)
+DEAL:2d:float::Norm of difference: 0
+DEAL:2d:float::
+DEAL:2d::Testing FE_Q<2>(4)
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d:float::Testing FE_Q<2>(4)
+DEAL:2d:float::Norm of difference: 0
+DEAL:2d:float::
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// evaluating the geometry on the fly as in matrix_vector_15, but using
+// vector-valued finite elements.
+
+#include "../tests.h"
+#include <deal.II/base/function.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <deal.II/lac/vector.h>
+
+
+std::ofstream logfile("output");
+
+
+
+template <int dim, int fe_degree, typename Number, typename VECTOR=Vector<Number> >
+class MatrixFreeTest
+{
+public:
+ MatrixFreeTest(const DoFHandler<dim> &dof_handler,
+ const ConstraintMatrix &constraints)
+ :
+ dof_handler (dof_handler),
+ constraints (constraints)
+ {}
+
+ void vmult (VECTOR &dst,
+ const VECTOR &src) const
+ {
+ MappingFEEvaluation<dim,Number> mapping(QGauss<1>(fe_degree+1),
+ update_gradients | update_values |
+ update_JxW_values);
+ VECTOR src_cpy = src;
+ constraints.distribute(src_cpy);
+ FEEvaluation<dim,fe_degree,fe_degree+1,dim,Number> fe_eval(mapping, dof_handler);
+ dst = 0;
+ typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for ( ; cell != endc; ++cell)
+ {
+ mapping.reinit(cell);
+ fe_eval.read_dof_values (src_cpy);
+ fe_eval.evaluate (true, true, false);
+ for (unsigned int q=0; q<fe_eval.n_q_points; ++q)
+ {
+ fe_eval.submit_value (make_vectorized_array<Number>(10.) *
+ fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
+ fe_eval.integrate (true,true);
+ fe_eval.distribute_local_to_global (dst);
+ }
+ constraints.condense(dst);
+ };
+
+private:
+ const DoFHandler<dim> &dof_handler;
+ const ConstraintMatrix &constraints;
+};
+
+
+
+template <int dim, int fe_degree, typename number>
+void do_test (const DoFHandler<dim> &dof,
+ const ConstraintMatrix &constraints,
+ const unsigned int parallel_option = 0)
+{
+
+ deallog << "Testing " << dof.get_fe().get_name() << std::endl;
+ if (parallel_option > 0)
+ deallog << "Parallel option: " << parallel_option << std::endl;
+ //std::cout << "Number of cells: " << dof.get_tria().n_active_cells() << std::endl;
+ //std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+ //std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
+
+ MatrixFreeTest<dim,fe_degree,number> mf (dof, constraints);
+ Vector<number> in (dof.n_dofs()), out (dof.n_dofs());
+ Vector<number> in_dist (dof.n_dofs());
+ Vector<number> out_dist (in_dist);
+
+ for (unsigned int i=0; i<dof.n_dofs(); ++i)
+ {
+ if (constraints.is_constrained(i))
+ continue;
+ const double entry = Testing::rand()/(double)RAND_MAX;
+ in(i) = entry;
+ in_dist(i) = entry;
+ }
+
+ mf.vmult (out_dist, in_dist);
+
+
+ // assemble sparse matrix with vector-valued form of (\nabla v, \nabla u) +
+ // (v, 10 * u)
+ SparsityPattern sparsity;
+ {
+ CompressedSimpleSparsityPattern csp(dof.n_dofs(), dof.n_dofs());
+ DoFTools::make_sparsity_pattern (dof, csp, constraints, true);
+ sparsity.copy_from(csp);
+ }
+ SparseMatrix<double> sparse_matrix (sparsity);
+ {
+ QGauss<dim> quadrature_formula(fe_degree+1);
+
+ FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
+ update_values | update_gradients |
+ update_JxW_values);
+
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof.begin_active(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ {
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ if (dof.get_fe().system_to_component_index(i).first ==
+ dof.get_fe().system_to_component_index(j).first)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
+ }
+ }
+
+ sparse_matrix.vmult (out, in);
+ out -= out_dist;
+ const double diff_norm = out.linfty_norm() / out_dist.linfty_norm();
+
+ deallog << "Norm of difference: " << diff_norm << std::endl << std::endl;
+}
+
+
+
+template <int dim, int fe_degree>
+void test ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_ball (tria);
+ static const HyperBallBoundary<dim> boundary;
+ tria.set_boundary (0, boundary);
+ if (dim < 3 || fe_degree < 2)
+ tria.refine_global(1);
+ tria.begin(tria.n_levels()-1)->set_refine_flag();
+ tria.last()->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ typename Triangulation<dim>::active_cell_iterator
+ cell = tria.begin_active (),
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ if (cell->center().norm()<1e-8)
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+
+ const unsigned int degree = fe_degree;
+ FESystem<dim> fe(FE_Q<dim>(degree), dim);
+ DoFHandler<dim> dof (tria);
+ dof.distribute_dofs(fe);
+ ConstraintMatrix constraints;
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(dim),
+ constraints);
+ constraints.close();
+
+ do_test<dim, fe_degree, double> (dof, constraints);
+}
+
+
+
+int main ()
+{
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+
+ deallog << std::setprecision (3);
+
+ {
+ deallog.threshold_double(5.e-11);
+ deallog.push("2d");
+ test<2,1>();
+ test<2,2>();
+ test<2,4>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3,1>();
+ test<3,2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FESystem<2>[FE_Q<2>(1)^2]
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FESystem<2>[FE_Q<2>(2)^2]
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:2d::Testing FESystem<2>[FE_Q<2>(4)^2]
+DEAL:2d::Norm of difference: 0
+DEAL:2d::
+DEAL:3d::Testing FESystem<3>[FE_Q<3>(1)^3]
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
+DEAL:3d::Testing FESystem<3>[FE_Q<3>(2)^3]
+DEAL:3d::Norm of difference: 0
+DEAL:3d::
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2013 by the deal.II authors
+// Copyright (C) 2013-2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
if (cell->center().norm()<0.5)
cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
+#ifndef DEBUG
if (dim < 3 || fe_degree < 2)
tria.refine_global(1);
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.refine_global(2);
else
tria.refine_global(1);
+#endif
FE_Q<dim> fe (fe_degree);
DoFHandler<dim> dof (tria);
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2013 by the deal.II authors
+// Copyright (C) 2013-2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
{
// Ask MatrixFree for cell_range for different
// orders
- std::pair<unsigned int,unsigned int> subrange_deg =
- data.create_cell_subrange_hp (cell_range, 1);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,1,Vector<Number> > (data, dst, src,
- subrange_deg);
- subrange_deg = data.create_cell_subrange_hp (cell_range, 2);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,2,Vector<Number> > (data, dst, src,
- subrange_deg);
- subrange_deg = data.create_cell_subrange_hp (cell_range, 3);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,3,Vector<Number> > (data, dst, src,
- subrange_deg);
- subrange_deg = data.create_cell_subrange_hp (cell_range, 4);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,4,Vector<Number> > (data, dst, src,
- subrange_deg);
- subrange_deg = data.create_cell_subrange_hp (cell_range, 5);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,5,Vector<Number> > (data, dst, src,
- subrange_deg);
- subrange_deg = data.create_cell_subrange_hp (cell_range, 6);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,6,Vector<Number> > (data, dst, src,
- subrange_deg);
- subrange_deg = data.create_cell_subrange_hp (cell_range, 7);
- if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,7,Vector<Number> > (data, dst, src,
- subrange_deg);
+ std::pair<unsigned int,unsigned int> subrange_deg;
+#define CALL_METHOD(degree) \
+ subrange_deg = data.create_cell_subrange_hp(cell_range, degree); \
+ if (subrange_deg.second > subrange_deg.first) \
+ helmholtz_operator<dim,degree,Vector<Number> > (data, dst, src, subrange_deg)
+
+ CALL_METHOD(1);
+ CALL_METHOD(2);
+ CALL_METHOD(3);
+ CALL_METHOD(4);
+ CALL_METHOD(5);
+ CALL_METHOD(6);
+ CALL_METHOD(7);
+
+#undef CALL_METHOD
}
void vmult (Vector<Number> &dst,
{
Triangulation<dim> tria;
create_mesh (tria);
+ // larger mesh in release mode
+#ifndef DEBUG
tria.refine_global(2);
+#endif
// refine a few cells
for (unsigned int i=0; i<11-3*dim; ++i)
MatrixFree<dim,number>::AdditionalData::partition_partition;
deallog << "Parallel option partition/partition" << std::endl;
}
- else
+ else if (parallel_option == 1)
{
data.tasks_parallel_scheme =
MatrixFree<dim,number>::AdditionalData::partition_color;
deallog << "Parallel option partition/color" << std::endl;
}
+ else
+ {
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::color;
+ deallog << "Parallel option partition/color" << std::endl;
+ }
data.tasks_block_size = 1;
mf_data_par.reinit (dof, constraints, quadrature_collection_mf, data);
MatrixFreeTestHP<dim,number> mf_par(mf_data_par);
}
DataOut<dim> data_out;
- data_out.attach_dof_handler (dof_handler);
+ data_out.attach_triangulation (triangulation);
data_out.add_data_vector (partitions, "partitions");
data_out.build_patches ();
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: 2d_refinement_01.cc 31349 2013-10-20 19:07:06Z maier $
+//
+// Copyright (C) 2008 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Test Tria<2,3> and DataOutput.
+
+#include "../tests.h"
+#include "coarse_grid_common.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/tensor.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/distributed/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_out.h>
+#include <deal.II/numerics/data_out.h>
+
+#include <fstream>
+#include <deal.II/fe/fe_q.h>
+
+template <int dim, int spacedim=dim>
+void write_vtk (const parallel::distributed::Triangulation<dim,spacedim> &tria,
+ const char *filename)
+{
+ deallog << "Checksum: "
+ << tria.get_checksum ()
+ << std::endl;
+
+ tria.write_mesh_vtk (filename);
+
+ // copy the .pvtu and .vtu files
+ // into the logstream
+ {
+ std::ifstream in((std::string(filename) + ".pvtu").c_str());
+ while (in)
+ {
+ std::string s;
+ std::getline(in, s);
+ deallog.get_file_stream() << s << "\n";
+ }
+ }
+
+ {
+ std::ifstream in((std::string(filename) + "_0000.vtu").c_str());
+ while (in)
+ {
+ std::string s;
+ std::getline(in, s);
+ deallog.get_file_stream() << s << "\n";
+ }
+ }
+}
+
+template<int dim, int spacedim>
+void test(std::ostream & /*out*/)
+{
+ parallel::distributed::Triangulation<dim,spacedim> tr(MPI_COMM_WORLD);
+
+ GridGenerator::torus(tr, 1, 0.2);
+ tr.refine_global();
+
+ tr.begin_active()->set_refine_flag();
+ (++(tr.begin_active()))->set_refine_flag();
+
+ tr.execute_coarsening_and_refinement ();
+
+ write_vtk(tr, "file");
+
+ FE_Q<dim,spacedim> fe(1);
+ DoFHandler<dim,spacedim> dh(tr);
+ dh.distribute_dofs(fe);
+ deallog << "dofs " << dh.n_dofs() << std::endl;
+
+ DataOut<dim,DoFHandler<dim,spacedim> > data_out;
+ data_out.attach_triangulation (tr);
+ Vector<float> subdomain (tr.n_active_cells());
+ for (unsigned int i=0; i<subdomain.size(); ++i)
+ subdomain(i) = tr.locally_owned_subdomain();
+ data_out.add_data_vector (subdomain, "subdomain");
+
+ std::string name = "f0.vtu";
+ name[1] += tr.locally_owned_subdomain();
+
+ {
+ std::ofstream file(name.c_str());
+ data_out.build_patches ();
+ data_out.write_vtu (file);
+ }
+ cat_file(name.c_str());
+}
+
+
+int main(int argc, char *argv[])
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
+
+ MPILogInitAll init;
+
+ deallog.push("2-3");
+ test<2,3>(deallog.get_file_stream());
+ deallog.pop();
+}
--- /dev/null
+
+DEAL:0:2-3::Checksum: 296355976
+<?xml version="1.0"?>
+<VTKFile type="PUnstructuredGrid" version="0.1" byte_order="LittleEndian">
+ <PUnstructuredGrid GhostLevel="0">
+ <PPoints>
+ <PDataArray type="Float32" Name="Position" NumberOfComponents="3" format="ascii"/>
+ </PPoints>
+ <PCellData Scalars="mpirank,treeid">
+ <PDataArray type="Int32" Name="mpirank" format="ascii"/>
+ <PDataArray type="Int32" Name="treeid" format="ascii"/>
+ </PCellData>
+ <PPointData>
+ </PPointData>
+ <Piece Source="file_0000.vtu"/>
+ <Piece Source="file_0001.vtu"/>
+ <Piece Source="file_0002.vtu"/>
+ </PUnstructuredGrid>
+</VTKFile>
+
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">
+ <UnstructuredGrid>
+ <Piece NumberOfPoints="92" NumberOfCells="23">
+ <Points>
+ <DataArray type="Float32" Name="Position" NumberOfComponents="3" format="ascii">
+ 7.96242177e-01 1.24999997e-03 5.00781229e-03
+ 6.05945289e-01 1.24999997e-03 1.95304692e-01
+ 8.43445301e-01 4.87499982e-02 5.30468766e-03
+ 6.41867161e-01 4.87499982e-02 2.06882820e-01
+ 5.95929682e-01 1.24999997e-03 2.05320314e-01
+ 4.05632824e-01 1.24999997e-03 3.95617187e-01
+ 6.31257832e-01 4.87499982e-02 2.17492193e-01
+ 4.29679692e-01 4.87499982e-02 4.19070303e-01
+ 8.45929682e-01 5.12499996e-02 5.32031246e-03
+ 6.43757820e-01 5.12499996e-02 2.07492188e-01
+ 8.93132806e-01 9.87500027e-02 5.61718736e-03
+ 6.79679692e-01 9.87500027e-02 2.19070315e-01
+ 6.33117199e-01 5.12499996e-02 2.18132809e-01
+ 4.30945307e-01 5.12499996e-02 4.20304686e-01
+ 6.68445289e-01 9.87500027e-02 2.30304688e-01
+ 4.54992175e-01 9.87500027e-02 4.43757802e-01
+ 3.91218752e-01 2.49999994e-03 4.11281258e-01
+ 1.00312503e-02 2.49999994e-03 7.92468727e-01
+ 4.37531263e-01 9.74999964e-02 4.59968746e-01
+ 1.12187499e-02 9.74999964e-02 8.86281252e-01
+ 8.91218722e-01 1.02499999e-01 1.12812500e-02
+ 4.62531239e-01 1.02499999e-01 4.39968765e-01
+ 9.85031247e-01 1.97500005e-01 1.24687497e-02
+ 5.11218727e-01 1.97500005e-01 4.86281246e-01
+ 4.39968765e-01 1.02499999e-01 4.62531239e-01
+ 1.12812500e-02 1.02499999e-01 8.91218722e-01
+ 4.86281246e-01 1.97500005e-01 5.11218727e-01
+ 1.24687497e-02 1.97500005e-01 9.85031247e-01
+ 9.85031247e-01 -1.97500005e-01 1.24687497e-02
+ 5.11218727e-01 -1.97500005e-01 4.86281246e-01
+ 8.91218722e-01 -1.02499999e-01 1.12812500e-02
+ 4.62531239e-01 -1.02499999e-01 4.39968765e-01
+ 4.86281246e-01 -1.97500005e-01 5.11218727e-01
+ 1.24687497e-02 -1.97500005e-01 9.85031247e-01
+ 4.39968765e-01 -1.02499999e-01 4.62531239e-01
+ 1.12812500e-02 -1.02499999e-01 8.91218722e-01
+ 8.86281252e-01 -9.74999964e-02 1.12187499e-02
+ 4.59968746e-01 -9.74999964e-02 4.37531263e-01
+ 7.92468727e-01 -2.49999994e-03 1.00312503e-02
+ 4.11281258e-01 -2.49999994e-03 3.91218752e-01
+ 4.37531263e-01 -9.74999964e-02 4.59968746e-01
+ 1.12187499e-02 -9.74999964e-02 8.86281252e-01
+ 3.91218752e-01 -2.49999994e-03 4.11281258e-01
+ 1.00312503e-02 -2.49999994e-03 7.92468727e-01
+ 9.89968777e-01 1.97500005e-01 1.25312498e-02
+ 5.13781250e-01 1.97500005e-01 4.88718748e-01
+ 1.08378124e+00 1.02499999e-01 1.37187503e-02
+ 5.62468767e-01 1.02499999e-01 5.35031259e-01
+ 4.88718748e-01 1.97500005e-01 5.13781250e-01
+ 1.25312498e-02 1.97500005e-01 9.89968777e-01
+ 5.35031259e-01 1.02499999e-01 5.62468767e-01
+ 1.37187503e-02 1.02499999e-01 1.08378124e+00
+ 1.08871877e+00 9.74999964e-02 1.37812505e-02
+ 5.65031230e-01 9.74999964e-02 5.37468731e-01
+ 1.18253124e+00 2.49999994e-03 1.49687501e-02
+ 6.13718748e-01 2.49999994e-03 5.83781242e-01
+ 5.37468731e-01 9.74999964e-02 5.65031230e-01
+ 1.37812505e-02 9.74999964e-02 1.08871877e+00
+ 5.83781242e-01 2.49999994e-03 6.13718748e-01
+ 1.49687501e-02 2.49999994e-03 1.18253124e+00
+ -1.00312503e-02 2.49999994e-03 7.92468727e-01
+ -3.91218752e-01 2.49999994e-03 4.11281258e-01
+ -1.12187499e-02 9.74999964e-02 8.86281252e-01
+ -4.37531263e-01 9.74999964e-02 4.59968746e-01
+ -4.11281258e-01 2.49999994e-03 3.91218752e-01
+ -7.92468727e-01 2.49999994e-03 1.00312503e-02
+ -4.59968746e-01 9.74999964e-02 4.37531263e-01
+ -8.86281252e-01 9.74999964e-02 1.12187499e-02
+ -1.12812500e-02 1.02499999e-01 8.91218722e-01
+ -4.39968765e-01 1.02499999e-01 4.62531239e-01
+ -1.24687497e-02 1.97500005e-01 9.85031247e-01
+ -4.86281246e-01 1.97500005e-01 5.11218727e-01
+ -4.62531239e-01 1.02499999e-01 4.39968765e-01
+ -8.91218722e-01 1.02499999e-01 1.12812500e-02
+ -5.11218727e-01 1.97500005e-01 4.86281246e-01
+ -9.85031247e-01 1.97500005e-01 1.24687497e-02
+ 1.00312503e-02 2.49999994e-03 -7.92468727e-01
+ 3.91218752e-01 2.49999994e-03 -4.11281258e-01
+ 1.12187499e-02 9.74999964e-02 -8.86281252e-01
+ 4.37531263e-01 9.74999964e-02 -4.59968746e-01
+ 4.11281258e-01 2.49999994e-03 -3.91218752e-01
+ 7.92468727e-01 2.49999994e-03 -1.00312503e-02
+ 4.59968746e-01 9.74999964e-02 -4.37531263e-01
+ 8.86281252e-01 9.74999964e-02 -1.12187499e-02
+ 1.12812500e-02 1.02499999e-01 -8.91218722e-01
+ 4.39968765e-01 1.02499999e-01 -4.62531239e-01
+ 1.24687497e-02 1.97500005e-01 -9.85031247e-01
+ 4.86281246e-01 1.97500005e-01 -5.11218727e-01
+ 4.62531239e-01 1.02499999e-01 -4.39968765e-01
+ 8.91218722e-01 1.02499999e-01 -1.12812500e-02
+ 5.11218727e-01 1.97500005e-01 -4.86281246e-01
+ 9.85031247e-01 1.97500005e-01 -1.24687497e-02
+ </DataArray>
+ </Points>
+ <Cells>
+ <DataArray type="Int32" Name="connectivity" format="ascii">
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 10 11
+ 12 13 14 15
+ 16 17 18 19
+ 20 21 22 23
+ 24 25 26 27
+ 28 29 30 31
+ 32 33 34 35
+ 36 37 38 39
+ 40 41 42 43
+ 44 45 46 47
+ 48 49 50 51
+ 52 53 54 55
+ 56 57 58 59
+ 60 61 62 63
+ 64 65 66 67
+ 68 69 70 71
+ 72 73 74 75
+ 76 77 78 79
+ 80 81 82 83
+ 84 85 86 87
+ 88 89 90 91
+ </DataArray>
+ <DataArray type="Int32" Name="offsets" format="ascii">
+ 4 8 12 16 20 24 28 32
+ 36 40 44 48 52 56 60 64
+ 68 72 76 80 84 88 92
+ </DataArray>
+ <DataArray type="UInt8" Name="types" format="ascii">
+ 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
+ 8 8 8
+ </DataArray>
+ </Cells>
+ <CellData Scalars="mpirank,treeid">
+ <DataArray type="Int32" Name="mpirank" format="ascii">
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0
+ </DataArray>
+ <DataArray type="Int32" Name="treeid" format="ascii">
+ 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4
+ 4 4 4
+ </DataArray>
+ </CellData>
+ <PointData>
+ </PointData>
+ </Piece>
+ </UnstructuredGrid>
+</VTKFile>
+
+DEAL:0:2-3::dofs 69
+<?xml version="1.0" ?>
+<!--
+# vtk DataFile Version 3.0
+#This file was generated
+-->
+<VTKFile type="UnstructuredGrid" version="0.1" compressor="vtkZLibDataCompressor" byte_order="LittleEndian">
+<UnstructuredGrid>
+<Piece NumberOfPoints="92" NumberOfCells="23" >
+ <Points>
+ <DataArray type="Float64" NumberOfComponents="3" format="binary">
+AQAAAKAIAACgCAAAJAEAAA==eNqdlTEOwjAMRbkT7LkNnInegCMw/bmiHAC1QxEwIBhAvQAqSYzi9AdMFuRP+H5xHFOtx3Vws7AqFaf61e2bcXXOx1uJ031Rv8tn1OO+ss8j6LXi6JXem3mYT7q/Fg7FA8KDlEfOC3JepJy5j+JB5Cj7yHlB6v+VJ97z9P3nfWLlqYz9Zu0HHz+zfvPxUfQYW/uh7PPpt5Tjd575ew1ZPbx+cjq28jCf6XwDvZdwbyj3h54DHfQ7ZT4hD3R+5hPyQNfZylOeAz3I/DHy5D4hD6b7PKs/yDsCOS/InKQ+bA4wHzbnrTyk/iDvFP/x5D5szrA6LNS7ib/z+i34bOT71XJcZ9H9vp1jPmxOln1apbdmHlY3H19UnRszD/Nh/+MvbR2P5g==
+ </DataArray>
+ </Points>
+
+ <Cells>
+ <DataArray type="Int32" Name="connectivity" format="binary">
+AQAAAHABAABwAQAAlwAAAA==eNoNw4c2QgEAANBXKoRESCUjq4XsmZQZiczi//+je8+5QRAEIUcMGzHqqDHHHHfCuJNOOW3CpDOmnHXOedMuuGjGnFmXzLvisquuuW7BDTfddsuiJSuWrbrjnrvW3PfQA4889tQTzzz30guvrNvw2hub3tryznsfffDJti8+2/HVN7u+2/PTD7/89tcf+w78988h7c0QWw==
+ </DataArray>
+ <DataArray type="Int32" Name="offsets" format="binary">
+AQAAAFwAAABcAAAAQAAAAA==eNoNw5ESgEAUAMAHB8FBEATBQRAEQRAEQRAcBEHQ/39HuzObIqIx29rZO1gcnZxdXN3cPTy9rN4+vn7+kBwEUQ==
+ </DataArray>
+ <DataArray type="UInt8" Name="types" format="binary">
+AQAAABcAAAAXAAAACwAAAA==eNrj5MQKAAnLANA=
+ </DataArray>
+ </Cells>
+ <PointData Scalars="scalars">
+ <DataArray type="Float64" Name="subdomain" format="binary">
+AQAAAOACAADgAgAADwAAAA==eNpjYBgFo2D4AgAC4AAB </DataArray>
+ </PointData>
+ </Piece>
+ </UnstructuredGrid>
+</VTKFile>
+
+
+DEAL:1:2-3::Checksum: 0
+<?xml version="1.0"?>
+<VTKFile type="PUnstructuredGrid" version="0.1" byte_order="LittleEndian">
+ <PUnstructuredGrid GhostLevel="0">
+ <PPoints>
+ <PDataArray type="Float32" Name="Position" NumberOfComponents="3" format="ascii"/>
+ </PPoints>
+ <PCellData Scalars="mpirank,treeid">
+ <PDataArray type="Int32" Name="mpirank" format="ascii"/>
+ <PDataArray type="Int32" Name="treeid" format="ascii"/>
+ </PCellData>
+ <PPointData>
+ </PPointData>
+ <Piece Source="file_0000.vtu"/>
+ <Piece Source="file_0001.vtu"/>
+ <Piece Source="file_0002.vtu"/>
+ </PUnstructuredGrid>
+</VTKFile>
+
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">
+ <UnstructuredGrid>
+ <Piece NumberOfPoints="92" NumberOfCells="23">
+ <Points>
+ <DataArray type="Float32" Name="Position" NumberOfComponents="3" format="ascii">
+ 7.96242177e-01 1.24999997e-03 5.00781229e-03
+ 6.05945289e-01 1.24999997e-03 1.95304692e-01
+ 8.43445301e-01 4.87499982e-02 5.30468766e-03
+ 6.41867161e-01 4.87499982e-02 2.06882820e-01
+ 5.95929682e-01 1.24999997e-03 2.05320314e-01
+ 4.05632824e-01 1.24999997e-03 3.95617187e-01
+ 6.31257832e-01 4.87499982e-02 2.17492193e-01
+ 4.29679692e-01 4.87499982e-02 4.19070303e-01
+ 8.45929682e-01 5.12499996e-02 5.32031246e-03
+ 6.43757820e-01 5.12499996e-02 2.07492188e-01
+ 8.93132806e-01 9.87500027e-02 5.61718736e-03
+ 6.79679692e-01 9.87500027e-02 2.19070315e-01
+ 6.33117199e-01 5.12499996e-02 2.18132809e-01
+ 4.30945307e-01 5.12499996e-02 4.20304686e-01
+ 6.68445289e-01 9.87500027e-02 2.30304688e-01
+ 4.54992175e-01 9.87500027e-02 4.43757802e-01
+ 3.91218752e-01 2.49999994e-03 4.11281258e-01
+ 1.00312503e-02 2.49999994e-03 7.92468727e-01
+ 4.37531263e-01 9.74999964e-02 4.59968746e-01
+ 1.12187499e-02 9.74999964e-02 8.86281252e-01
+ 8.91218722e-01 1.02499999e-01 1.12812500e-02
+ 4.62531239e-01 1.02499999e-01 4.39968765e-01
+ 9.85031247e-01 1.97500005e-01 1.24687497e-02
+ 5.11218727e-01 1.97500005e-01 4.86281246e-01
+ 4.39968765e-01 1.02499999e-01 4.62531239e-01
+ 1.12812500e-02 1.02499999e-01 8.91218722e-01
+ 4.86281246e-01 1.97500005e-01 5.11218727e-01
+ 1.24687497e-02 1.97500005e-01 9.85031247e-01
+ 9.85031247e-01 -1.97500005e-01 1.24687497e-02
+ 5.11218727e-01 -1.97500005e-01 4.86281246e-01
+ 8.91218722e-01 -1.02499999e-01 1.12812500e-02
+ 4.62531239e-01 -1.02499999e-01 4.39968765e-01
+ 4.86281246e-01 -1.97500005e-01 5.11218727e-01
+ 1.24687497e-02 -1.97500005e-01 9.85031247e-01
+ 4.39968765e-01 -1.02499999e-01 4.62531239e-01
+ 1.12812500e-02 -1.02499999e-01 8.91218722e-01
+ 8.86281252e-01 -9.74999964e-02 1.12187499e-02
+ 4.59968746e-01 -9.74999964e-02 4.37531263e-01
+ 7.92468727e-01 -2.49999994e-03 1.00312503e-02
+ 4.11281258e-01 -2.49999994e-03 3.91218752e-01
+ 4.37531263e-01 -9.74999964e-02 4.59968746e-01
+ 1.12187499e-02 -9.74999964e-02 8.86281252e-01
+ 3.91218752e-01 -2.49999994e-03 4.11281258e-01
+ 1.00312503e-02 -2.49999994e-03 7.92468727e-01
+ 9.89968777e-01 1.97500005e-01 1.25312498e-02
+ 5.13781250e-01 1.97500005e-01 4.88718748e-01
+ 1.08378124e+00 1.02499999e-01 1.37187503e-02
+ 5.62468767e-01 1.02499999e-01 5.35031259e-01
+ 4.88718748e-01 1.97500005e-01 5.13781250e-01
+ 1.25312498e-02 1.97500005e-01 9.89968777e-01
+ 5.35031259e-01 1.02499999e-01 5.62468767e-01
+ 1.37187503e-02 1.02499999e-01 1.08378124e+00
+ 1.08871877e+00 9.74999964e-02 1.37812505e-02
+ 5.65031230e-01 9.74999964e-02 5.37468731e-01
+ 1.18253124e+00 2.49999994e-03 1.49687501e-02
+ 6.13718748e-01 2.49999994e-03 5.83781242e-01
+ 5.37468731e-01 9.74999964e-02 5.65031230e-01
+ 1.37812505e-02 9.74999964e-02 1.08871877e+00
+ 5.83781242e-01 2.49999994e-03 6.13718748e-01
+ 1.49687501e-02 2.49999994e-03 1.18253124e+00
+ -1.00312503e-02 2.49999994e-03 7.92468727e-01
+ -3.91218752e-01 2.49999994e-03 4.11281258e-01
+ -1.12187499e-02 9.74999964e-02 8.86281252e-01
+ -4.37531263e-01 9.74999964e-02 4.59968746e-01
+ -4.11281258e-01 2.49999994e-03 3.91218752e-01
+ -7.92468727e-01 2.49999994e-03 1.00312503e-02
+ -4.59968746e-01 9.74999964e-02 4.37531263e-01
+ -8.86281252e-01 9.74999964e-02 1.12187499e-02
+ -1.12812500e-02 1.02499999e-01 8.91218722e-01
+ -4.39968765e-01 1.02499999e-01 4.62531239e-01
+ -1.24687497e-02 1.97500005e-01 9.85031247e-01
+ -4.86281246e-01 1.97500005e-01 5.11218727e-01
+ -4.62531239e-01 1.02499999e-01 4.39968765e-01
+ -8.91218722e-01 1.02499999e-01 1.12812500e-02
+ -5.11218727e-01 1.97500005e-01 4.86281246e-01
+ -9.85031247e-01 1.97500005e-01 1.24687497e-02
+ 1.00312503e-02 2.49999994e-03 -7.92468727e-01
+ 3.91218752e-01 2.49999994e-03 -4.11281258e-01
+ 1.12187499e-02 9.74999964e-02 -8.86281252e-01
+ 4.37531263e-01 9.74999964e-02 -4.59968746e-01
+ 4.11281258e-01 2.49999994e-03 -3.91218752e-01
+ 7.92468727e-01 2.49999994e-03 -1.00312503e-02
+ 4.59968746e-01 9.74999964e-02 -4.37531263e-01
+ 8.86281252e-01 9.74999964e-02 -1.12187499e-02
+ 1.12812500e-02 1.02499999e-01 -8.91218722e-01
+ 4.39968765e-01 1.02499999e-01 -4.62531239e-01
+ 1.24687497e-02 1.97500005e-01 -9.85031247e-01
+ 4.86281246e-01 1.97500005e-01 -5.11218727e-01
+ 4.62531239e-01 1.02499999e-01 -4.39968765e-01
+ 8.91218722e-01 1.02499999e-01 -1.12812500e-02
+ 5.11218727e-01 1.97500005e-01 -4.86281246e-01
+ 9.85031247e-01 1.97500005e-01 -1.24687497e-02
+ </DataArray>
+ </Points>
+ <Cells>
+ <DataArray type="Int32" Name="connectivity" format="ascii">
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 10 11
+ 12 13 14 15
+ 16 17 18 19
+ 20 21 22 23
+ 24 25 26 27
+ 28 29 30 31
+ 32 33 34 35
+ 36 37 38 39
+ 40 41 42 43
+ 44 45 46 47
+ 48 49 50 51
+ 52 53 54 55
+ 56 57 58 59
+ 60 61 62 63
+ 64 65 66 67
+ 68 69 70 71
+ 72 73 74 75
+ 76 77 78 79
+ 80 81 82 83
+ 84 85 86 87
+ 88 89 90 91
+ </DataArray>
+ <DataArray type="Int32" Name="offsets" format="ascii">
+ 4 8 12 16 20 24 28 32
+ 36 40 44 48 52 56 60 64
+ 68 72 76 80 84 88 92
+ </DataArray>
+ <DataArray type="UInt8" Name="types" format="ascii">
+ 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
+ 8 8 8
+ </DataArray>
+ </Cells>
+ <CellData Scalars="mpirank,treeid">
+ <DataArray type="Int32" Name="mpirank" format="ascii">
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0
+ </DataArray>
+ <DataArray type="Int32" Name="treeid" format="ascii">
+ 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4
+ 4 4 4
+ </DataArray>
+ </CellData>
+ <PointData>
+ </PointData>
+ </Piece>
+ </UnstructuredGrid>
+</VTKFile>
+
+DEAL:1:2-3::dofs 69
+<?xml version="1.0" ?>
+<!--
+# vtk DataFile Version 3.0
+#This file was generated
+-->
+<VTKFile type="UnstructuredGrid" version="0.1" compressor="vtkZLibDataCompressor" byte_order="LittleEndian">
+<UnstructuredGrid>
+<Piece NumberOfPoints="80" NumberOfCells="20" >
+ <Points>
+ <DataArray type="Float64" NumberOfComponents="3" format="binary">
+AQAAAIAHAACABwAABQEAAA==eNqdVMENgzAM7E4M4DnbTXj5XakdAIkHqC+kPoJYoKLYkXLhmqT+RLnA+WSf3XV7bHKB+MLdS/B+u+6x2tmrvx/3OeJ+Zzzn+TZhPGkex9dmPcdrMPyuqYoJ8KlZD+NJv3c8FPBJf/P0+nzs8ZbjHDXFxwJPUKwD47E8inX+Tw/+t1i9BujfIK16GI/lyXRD/YXUX0j9wX+zpvhc4AmAR99mPJYn4qT+lXryubO51PN5r9fDeCwP8c1C8KyPCn0X4lvwzUD9gToYD9bZdbTqYX0nPmnWw3iIz5XsHyV7TMm8x7mEOS3w5HuY8fheqdw/BT15331PnPutXg/j8T2H+T+XphyK
+ </DataArray>
+ </Points>
+
+ <Cells>
+ <DataArray type="Int32" Name="connectivity" format="binary">
+AQAAAEABAABAAQAAhQAAAA==eNoNw4c2QgEAANBHpSHRUAhF00pWQyVNlPj/v+nec24QBMGOIXcNGzHqnjHj7psw6YGHpjwybdaMOY8tmPfEU4ueee6FJS8te2XFa6vWbFi36Y133nrvg4+2bPvki8+++mbXjj37Dnx36MixH346cebUuQu/XPrtj2tX/rrx3z+3NvsMWQ==
+ </DataArray>
+ <DataArray type="Int32" Name="offsets" format="binary">
+AQAAAFAAAABQAAAAOwAAAA==eNpjYWBg4ABiHiAWAGIRIJYAYhkgVgBiFSDWAGIdIDYAYhMgtgBiGyB2AGIXIPYAYh8gDgBiAGCQA0k=
+ </DataArray>
+ <DataArray type="UInt8" Name="types" format="binary">
+AQAAABQAAAAUAAAACwAAAA==eNrj5MQEAAd2ALU=
+ </DataArray>
+ </Cells>
+ <PointData Scalars="scalars">
+ <DataArray type="Float64" Name="subdomain" format="binary">
+AQAAAIACAACAAgAAFAAAAA==eNpjYACBD/YMo/QoPQA0AJRLXrE= </DataArray>
+ </PointData>
+ </Piece>
+ </UnstructuredGrid>
+</VTKFile>
+
+
+
+DEAL:2:2-3::Checksum: 0
+<?xml version="1.0"?>
+<VTKFile type="PUnstructuredGrid" version="0.1" byte_order="LittleEndian">
+ <PUnstructuredGrid GhostLevel="0">
+ <PPoints>
+ <PDataArray type="Float32" Name="Position" NumberOfComponents="3" format="ascii"/>
+ </PPoints>
+ <PCellData Scalars="mpirank,treeid">
+ <PDataArray type="Int32" Name="mpirank" format="ascii"/>
+ <PDataArray type="Int32" Name="treeid" format="ascii"/>
+ </PCellData>
+ <PPointData>
+ </PPointData>
+ <Piece Source="file_0000.vtu"/>
+ <Piece Source="file_0001.vtu"/>
+ <Piece Source="file_0002.vtu"/>
+ </PUnstructuredGrid>
+</VTKFile>
+
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">
+ <UnstructuredGrid>
+ <Piece NumberOfPoints="92" NumberOfCells="23">
+ <Points>
+ <DataArray type="Float32" Name="Position" NumberOfComponents="3" format="ascii">
+ 7.96242177e-01 1.24999997e-03 5.00781229e-03
+ 6.05945289e-01 1.24999997e-03 1.95304692e-01
+ 8.43445301e-01 4.87499982e-02 5.30468766e-03
+ 6.41867161e-01 4.87499982e-02 2.06882820e-01
+ 5.95929682e-01 1.24999997e-03 2.05320314e-01
+ 4.05632824e-01 1.24999997e-03 3.95617187e-01
+ 6.31257832e-01 4.87499982e-02 2.17492193e-01
+ 4.29679692e-01 4.87499982e-02 4.19070303e-01
+ 8.45929682e-01 5.12499996e-02 5.32031246e-03
+ 6.43757820e-01 5.12499996e-02 2.07492188e-01
+ 8.93132806e-01 9.87500027e-02 5.61718736e-03
+ 6.79679692e-01 9.87500027e-02 2.19070315e-01
+ 6.33117199e-01 5.12499996e-02 2.18132809e-01
+ 4.30945307e-01 5.12499996e-02 4.20304686e-01
+ 6.68445289e-01 9.87500027e-02 2.30304688e-01
+ 4.54992175e-01 9.87500027e-02 4.43757802e-01
+ 3.91218752e-01 2.49999994e-03 4.11281258e-01
+ 1.00312503e-02 2.49999994e-03 7.92468727e-01
+ 4.37531263e-01 9.74999964e-02 4.59968746e-01
+ 1.12187499e-02 9.74999964e-02 8.86281252e-01
+ 8.91218722e-01 1.02499999e-01 1.12812500e-02
+ 4.62531239e-01 1.02499999e-01 4.39968765e-01
+ 9.85031247e-01 1.97500005e-01 1.24687497e-02
+ 5.11218727e-01 1.97500005e-01 4.86281246e-01
+ 4.39968765e-01 1.02499999e-01 4.62531239e-01
+ 1.12812500e-02 1.02499999e-01 8.91218722e-01
+ 4.86281246e-01 1.97500005e-01 5.11218727e-01
+ 1.24687497e-02 1.97500005e-01 9.85031247e-01
+ 9.85031247e-01 -1.97500005e-01 1.24687497e-02
+ 5.11218727e-01 -1.97500005e-01 4.86281246e-01
+ 8.91218722e-01 -1.02499999e-01 1.12812500e-02
+ 4.62531239e-01 -1.02499999e-01 4.39968765e-01
+ 4.86281246e-01 -1.97500005e-01 5.11218727e-01
+ 1.24687497e-02 -1.97500005e-01 9.85031247e-01
+ 4.39968765e-01 -1.02499999e-01 4.62531239e-01
+ 1.12812500e-02 -1.02499999e-01 8.91218722e-01
+ 8.86281252e-01 -9.74999964e-02 1.12187499e-02
+ 4.59968746e-01 -9.74999964e-02 4.37531263e-01
+ 7.92468727e-01 -2.49999994e-03 1.00312503e-02
+ 4.11281258e-01 -2.49999994e-03 3.91218752e-01
+ 4.37531263e-01 -9.74999964e-02 4.59968746e-01
+ 1.12187499e-02 -9.74999964e-02 8.86281252e-01
+ 3.91218752e-01 -2.49999994e-03 4.11281258e-01
+ 1.00312503e-02 -2.49999994e-03 7.92468727e-01
+ 9.89968777e-01 1.97500005e-01 1.25312498e-02
+ 5.13781250e-01 1.97500005e-01 4.88718748e-01
+ 1.08378124e+00 1.02499999e-01 1.37187503e-02
+ 5.62468767e-01 1.02499999e-01 5.35031259e-01
+ 4.88718748e-01 1.97500005e-01 5.13781250e-01
+ 1.25312498e-02 1.97500005e-01 9.89968777e-01
+ 5.35031259e-01 1.02499999e-01 5.62468767e-01
+ 1.37187503e-02 1.02499999e-01 1.08378124e+00
+ 1.08871877e+00 9.74999964e-02 1.37812505e-02
+ 5.65031230e-01 9.74999964e-02 5.37468731e-01
+ 1.18253124e+00 2.49999994e-03 1.49687501e-02
+ 6.13718748e-01 2.49999994e-03 5.83781242e-01
+ 5.37468731e-01 9.74999964e-02 5.65031230e-01
+ 1.37812505e-02 9.74999964e-02 1.08871877e+00
+ 5.83781242e-01 2.49999994e-03 6.13718748e-01
+ 1.49687501e-02 2.49999994e-03 1.18253124e+00
+ -1.00312503e-02 2.49999994e-03 7.92468727e-01
+ -3.91218752e-01 2.49999994e-03 4.11281258e-01
+ -1.12187499e-02 9.74999964e-02 8.86281252e-01
+ -4.37531263e-01 9.74999964e-02 4.59968746e-01
+ -4.11281258e-01 2.49999994e-03 3.91218752e-01
+ -7.92468727e-01 2.49999994e-03 1.00312503e-02
+ -4.59968746e-01 9.74999964e-02 4.37531263e-01
+ -8.86281252e-01 9.74999964e-02 1.12187499e-02
+ -1.12812500e-02 1.02499999e-01 8.91218722e-01
+ -4.39968765e-01 1.02499999e-01 4.62531239e-01
+ -1.24687497e-02 1.97500005e-01 9.85031247e-01
+ -4.86281246e-01 1.97500005e-01 5.11218727e-01
+ -4.62531239e-01 1.02499999e-01 4.39968765e-01
+ -8.91218722e-01 1.02499999e-01 1.12812500e-02
+ -5.11218727e-01 1.97500005e-01 4.86281246e-01
+ -9.85031247e-01 1.97500005e-01 1.24687497e-02
+ 1.00312503e-02 2.49999994e-03 -7.92468727e-01
+ 3.91218752e-01 2.49999994e-03 -4.11281258e-01
+ 1.12187499e-02 9.74999964e-02 -8.86281252e-01
+ 4.37531263e-01 9.74999964e-02 -4.59968746e-01
+ 4.11281258e-01 2.49999994e-03 -3.91218752e-01
+ 7.92468727e-01 2.49999994e-03 -1.00312503e-02
+ 4.59968746e-01 9.74999964e-02 -4.37531263e-01
+ 8.86281252e-01 9.74999964e-02 -1.12187499e-02
+ 1.12812500e-02 1.02499999e-01 -8.91218722e-01
+ 4.39968765e-01 1.02499999e-01 -4.62531239e-01
+ 1.24687497e-02 1.97500005e-01 -9.85031247e-01
+ 4.86281246e-01 1.97500005e-01 -5.11218727e-01
+ 4.62531239e-01 1.02499999e-01 -4.39968765e-01
+ 8.91218722e-01 1.02499999e-01 -1.12812500e-02
+ 5.11218727e-01 1.97500005e-01 -4.86281246e-01
+ 9.85031247e-01 1.97500005e-01 -1.24687497e-02
+ </DataArray>
+ </Points>
+ <Cells>
+ <DataArray type="Int32" Name="connectivity" format="ascii">
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 10 11
+ 12 13 14 15
+ 16 17 18 19
+ 20 21 22 23
+ 24 25 26 27
+ 28 29 30 31
+ 32 33 34 35
+ 36 37 38 39
+ 40 41 42 43
+ 44 45 46 47
+ 48 49 50 51
+ 52 53 54 55
+ 56 57 58 59
+ 60 61 62 63
+ 64 65 66 67
+ 68 69 70 71
+ 72 73 74 75
+ 76 77 78 79
+ 80 81 82 83
+ 84 85 86 87
+ 88 89 90 91
+ </DataArray>
+ <DataArray type="Int32" Name="offsets" format="ascii">
+ 4 8 12 16 20 24 28 32
+ 36 40 44 48 52 56 60 64
+ 68 72 76 80 84 88 92
+ </DataArray>
+ <DataArray type="UInt8" Name="types" format="ascii">
+ 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
+ 8 8 8
+ </DataArray>
+ </Cells>
+ <CellData Scalars="mpirank,treeid">
+ <DataArray type="Int32" Name="mpirank" format="ascii">
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0
+ </DataArray>
+ <DataArray type="Int32" Name="treeid" format="ascii">
+ 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4
+ 4 4 4
+ </DataArray>
+ </CellData>
+ <PointData>
+ </PointData>
+ </Piece>
+ </UnstructuredGrid>
+</VTKFile>
+
+DEAL:2:2-3::dofs 69
+<?xml version="1.0" ?>
+<!--
+# vtk DataFile Version 3.0
+#This file was generated
+-->
+<VTKFile type="UnstructuredGrid" version="0.1" compressor="vtkZLibDataCompressor" byte_order="LittleEndian">
+<UnstructuredGrid>
+<Piece NumberOfPoints="96" NumberOfCells="24" >
+ <Points>
+ <DataArray type="Float64" NumberOfComponents="3" format="binary">
+AQAAAAAJAAAACQAAGgEAAA==eNqdlTEOwjAMRXsnDuBzwk2YPCPBAZAYWnWqxFDUC6CSOMh2fhs3S5QveP5Jftyu0+P0GwuleWStjyTry3kdV07zh9I8sNYHyMl12JTvECfXKXr9f/t+9O9vmTNnvWet93TMj+fkOkaXgXTH4cd9HW9XN+mvossaccA58Dbnf87iI+onrSdwf0+266gfxKnXmxjlEOSW0b2DnDDi1OstjDgg52E/0bxF/UTzZvwQ8GPeZ9kvgf2S9uk5xo95n4hT9kvg/Hf9HMtbu59o3pBu+73l1HMofdHl33HkOwP6v+Povr7b/6Gf7RxKv3f5D/rxHPnO1N+dz6HhgNzaHBafNv+AM5N9d4hj9gvurdVPe96ifqJ5+wICvYbI
+ </DataArray>
+ </Points>
+
+ <Cells>
+ <DataArray type="Int32" Name="connectivity" format="binary">
+AQAAAIABAACAAQAAnQAAAA==eNoNw4c2QgEAANCnSJJVRsmmYUV2SLISQigz/v8v3HvODYIg6DFsyF777Ddi1AEHjRl3yBGHHXXMpAnHnXDKSVOmzTjtjLPOO+eCiy675IpZ8+YsuOq6a2646ZZFty2564577nvogUeWPfHYUytWPfPcmpdeeOW1dW+8teG9dz7Y9MlHn2356otvtn2344effvvlj13//PUfAicR0Q==
+ </DataArray>
+ <DataArray type="Int32" Name="offsets" format="binary">
+AQAAAGAAAABgAAAAQgAAAA==eNoNw5ESgEAUAMAHQRAEQRAcBEEQBMFBcBAEQRAE/f9XtDuzVUTUNrZ29g4mRydnF1c3s7vFw9PL28fXzx+i4ASx
+ </DataArray>
+ <DataArray type="UInt8" Name="types" format="binary">
+AQAAABgAAAAYAAAACwAAAA==eNrj5MQOAAqkANk=
+ </DataArray>
+ </Cells>
+ <PointData Scalars="scalars">
+ <DataArray type="Float64" Name="subdomain" format="binary">
+AQAAAAADAAAAAwAAEwAAAA==eNpjYAADB4ZRepQegTQAvQ0YAQ== </DataArray>
+ </PointData>
+ </Piece>
+ </UnstructuredGrid>
+</VTKFile>
+
+
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+// check that handling of ghost elements in parallel distributed vectors works
+// appropriately when assigning from ghosted to non-ghosted vectors
+
+#include "../tests.h"
+#include <deal.II/base/utilities.h>
+#include <deal.II/base/index_set.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+
+void test ()
+{
+ unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
+ unsigned int numproc = Utilities::MPI::n_mpi_processes (MPI_COMM_WORLD);
+
+ if (myid==0) deallog << "numproc=" << numproc << std::endl;
+
+
+ // processor 0 and 1 own 2 indices each, higher processors nothing, all are
+ // ghosting global elements 1 and 3
+ IndexSet local_owned(std::min(numproc*2, 4U));
+ if (myid < 2)
+ local_owned.add_range(myid*2,myid*2+2);
+ IndexSet local_relevant(local_owned.size());
+ local_relevant = local_owned;
+ local_relevant.add_range(1,2);
+ if (numproc > 1)
+ local_relevant.add_range(3,4);
+
+ // run this twice, once where the vectors have called update_ghost_values
+ // and once where they have not
+ for (unsigned int run = 0; run < 2; ++run)
+ {
+ parallel::distributed::Vector<double> v(local_owned, local_relevant, MPI_COMM_WORLD);
+
+ // set local values
+ if (myid < 2)
+ {
+ v(myid*2)=myid*2.0;
+ v(myid*2+1)=myid*2.0+1.0;
+ }
+
+ v.compress(VectorOperation::insert);
+
+ parallel::distributed::Vector<double> w(v), u(v);
+ u = 0;
+
+ v*=2.0;
+ v.add(1.0);
+
+ if (run == 1)
+ {
+ v.update_ghost_values();
+ w.update_ghost_values();
+ u.update_ghost_values();
+ }
+
+ if (myid < 2)
+ {
+ Assert(v(myid*2) == myid*4.0+1, ExcInternalError());
+ Assert(v(myid*2+1) == myid*4.0+3.0, ExcInternalError());
+ }
+
+ // copy vector content to non-ghosted vectors, manually created.
+ parallel::distributed::Vector<double> v_dist(local_owned, MPI_COMM_WORLD),
+ w_dist(v_dist), u_dist(v_dist);
+
+ v_dist = v;
+ w_dist = w;
+ u_dist = u;
+
+ u_dist.add(1.0, v_dist, -1.0, w);
+
+ // copy back to a ghosted vector and update ghost values there
+ u = u_dist;
+ u.update_ghost_values();
+
+ if (myid < 2)
+ {
+ Assert(u_dist(myid*2) == myid*2.0+1, ExcInternalError());
+ Assert(u_dist(myid*2+1) == myid*2.0+2.0, ExcInternalError());
+ Assert(u(myid*2) == myid*2.0+1, ExcInternalError());
+ Assert(u(myid*2+1) == myid*2.0+2.0, ExcInternalError());
+ }
+
+ Assert(u(1) == 2., ExcInternalError());
+ if (numproc > 1)
+ {
+ if (run == 1)
+ Assert(v(3) == 7., ExcInternalError());
+ Assert(u(3) == 4., ExcInternalError());
+ }
+
+ // check l2 norm
+ const double l2_norm = u.l2_norm();
+ if (myid == 0 && run == 1)
+ deallog << "L2 norm: " << l2_norm << std::endl;
+ }
+
+ if (myid == 0)
+ deallog << "OK" << std::endl;
+}
+
+
+
+int main (int argc, char **argv)
+{
+ Utilities::System::MPI_InitFinalize mpi_initialization(argc, argv);
+
+ unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
+ deallog.push(Utilities::int_to_string(myid));
+
+ if (myid == 0)
+ {
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog << std::setprecision(4);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ test();
+ }
+ else
+ test();
+
+}
--- /dev/null
+
+DEAL:0::numproc=1
+DEAL:0::L2 norm: 2.236
+DEAL:0::OK
--- /dev/null
+
+DEAL:0::numproc=3
+DEAL:0::L2 norm: 5.477
+DEAL:0::OK
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2009 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Test that DofRenumbering::Cuthill_McKee works in parallel (by applying
+// Cuthill-McKee individually on each processor's subdomain).
+
+
+#include "../tests.h"
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/mpi.h>
+#include <deal.II/distributed/tria.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_renumbering.h>
+#include <deal.II/fe/fe_q.h>
+
+#include <fstream>
+
+
+template<int dim>
+void test()
+{
+ unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
+ unsigned int nprocs = Utilities::MPI::n_mpi_processes (MPI_COMM_WORLD);
+
+ parallel::distributed::Triangulation<dim> tr (MPI_COMM_WORLD);
+
+ GridGenerator::hyper_cube (tr, -1.0, 1.0);
+ tr.refine_global (8-2*dim);
+
+ for (typename Triangulation<dim>::active_cell_iterator
+ cell = tr.begin_active();
+ cell != tr.end(); ++cell)
+ if (!cell->is_ghost() && !cell->is_artificial())
+ if (cell->center().norm() < 0.3)
+ {
+ cell->set_refine_flag();
+ }
+
+ tr.execute_coarsening_and_refinement ();
+
+ DoFHandler<dim> dofh (tr);
+
+ static const FE_Q<dim> fe (1);
+ dofh.distribute_dofs (fe);
+ std::vector<types::global_dof_index> renumbering(dofh.locally_owned_dofs().n_elements());
+ DoFRenumbering::compute_Cuthill_McKee (renumbering, dofh);
+
+ // send everything to processor 0 for output
+ std::vector<types::global_dof_index> complete_renumbering(dofh.n_dofs());
+ std::copy(renumbering.begin(), renumbering.end(), complete_renumbering.begin());
+ unsigned int offset = renumbering.size();
+ for (unsigned int i=1; i<nprocs; ++i)
+ {
+ if (myid == i)
+ MPI_Send (&renumbering[0], renumbering.size(),
+ Utilities::MPI::internal::mpi_type_id(&complete_renumbering[0]), 0, i,
+ MPI_COMM_WORLD);
+ else if (myid == 0)
+ MPI_Recv (&complete_renumbering[offset],
+ dofh.locally_owned_dofs_per_processor()[i].n_elements(),
+ Utilities::MPI::internal::mpi_type_id(&complete_renumbering[0]), i, i,
+ MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
+ offset += dofh.locally_owned_dofs_per_processor()[i].n_elements();
+ }
+
+ if (myid == 0)
+ {
+ AssertDimension(offset, complete_renumbering.size());
+ for (unsigned int i=0; i<complete_renumbering.size(); ++i)
+ deallog << complete_renumbering[i] << std::endl;
+ }
+}
+
+
+int main (int argc, char *argv[])
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
+
+ unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
+
+
+ deallog.push (Utilities::int_to_string (myid));
+
+ if (myid == 0)
+ {
+ std::ofstream logfile ("output");
+ deallog.attach (logfile);
+ deallog.depth_console (0);
+ deallog.threshold_double (1.e-10);
+
+ deallog.push ("2d");
+ test<2>();
+ deallog.pop();
+ deallog.push ("3d");
+ test<3>();
+ deallog.pop();
+ }
+ else
+ {
+ test<2>();
+ test<3>();
+ }
+}
--- /dev/null
+
+DEAL:0:2d::0
+DEAL:0:2d::1
+DEAL:0:2d::2
+DEAL:0:2d::3
+DEAL:0:2d::4
+DEAL:0:2d::6
+DEAL:0:2d::5
+DEAL:0:2d::7
+DEAL:0:2d::8
+DEAL:0:2d::9
+DEAL:0:2d::11
+DEAL:0:2d::16
+DEAL:0:2d::18
+DEAL:0:2d::12
+DEAL:0:2d::19
+DEAL:0:2d::10
+DEAL:0:2d::13
+DEAL:0:2d::14
+DEAL:0:2d::17
+DEAL:0:2d::20
+DEAL:0:2d::21
+DEAL:0:2d::15
+DEAL:0:2d::22
+DEAL:0:2d::23
+DEAL:0:2d::24
+DEAL:0:2d::25
+DEAL:0:2d::27
+DEAL:0:2d::36
+DEAL:0:2d::38
+DEAL:0:2d::28
+DEAL:0:2d::39
+DEAL:0:2d::49
+DEAL:0:2d::53
+DEAL:0:2d::66
+DEAL:0:2d::70
+DEAL:0:2d::54
+DEAL:0:2d::71
+DEAL:0:2d::29
+DEAL:0:2d::40
+DEAL:0:2d::30
+DEAL:0:2d::41
+DEAL:0:2d::55
+DEAL:0:2d::72
+DEAL:0:2d::56
+DEAL:0:2d::73
+DEAL:0:2d::26
+DEAL:0:2d::31
+DEAL:0:2d::32
+DEAL:0:2d::37
+DEAL:0:2d::42
+DEAL:0:2d::43
+DEAL:0:2d::33
+DEAL:0:2d::34
+DEAL:0:2d::44
+DEAL:0:2d::45
+DEAL:0:2d::50
+DEAL:0:2d::57
+DEAL:0:2d::58
+DEAL:0:2d::67
+DEAL:0:2d::74
+DEAL:0:2d::75
+DEAL:0:2d::59
+DEAL:0:2d::60
+DEAL:0:2d::76
+DEAL:0:2d::77
+DEAL:0:2d::35
+DEAL:0:2d::46
+DEAL:0:2d::47
+DEAL:0:2d::48
+DEAL:0:2d::61
+DEAL:0:2d::78
+DEAL:0:2d::64
+DEAL:0:2d::85
+DEAL:0:2d::62
+DEAL:0:2d::65
+DEAL:0:2d::79
+DEAL:0:2d::86
+DEAL:0:2d::87
+DEAL:0:2d::91
+DEAL:0:2d::112
+DEAL:0:2d::116
+DEAL:0:2d::92
+DEAL:0:2d::117
+DEAL:0:2d::141
+DEAL:0:2d::145
+DEAL:0:2d::172
+DEAL:0:2d::176
+DEAL:0:2d::146
+DEAL:0:2d::177
+DEAL:0:2d::93
+DEAL:0:2d::118
+DEAL:0:2d::94
+DEAL:0:2d::119
+DEAL:0:2d::147
+DEAL:0:2d::178
+DEAL:0:2d::148
+DEAL:0:2d::179
+DEAL:0:2d::203
+DEAL:0:2d::207
+DEAL:0:2d::234
+DEAL:0:2d::238
+DEAL:0:2d::208
+DEAL:0:2d::239
+DEAL:0:2d::265
+DEAL:0:2d::267
+DEAL:0:2d::296
+DEAL:0:2d::298
+DEAL:0:2d::268
+DEAL:0:2d::299
+DEAL:0:2d::209
+DEAL:0:2d::240
+DEAL:0:2d::210
+DEAL:0:2d::241
+DEAL:0:2d::269
+DEAL:0:2d::300
+DEAL:0:2d::270
+DEAL:0:2d::301
+DEAL:0:2d::95
+DEAL:0:2d::120
+DEAL:0:2d::110
+DEAL:0:2d::139
+DEAL:0:2d::149
+DEAL:0:2d::180
+DEAL:0:2d::150
+DEAL:0:2d::181
+DEAL:0:2d::170
+DEAL:0:2d::151
+DEAL:0:2d::182
+DEAL:0:2d::201
+DEAL:0:2d::183
+DEAL:0:2d::184
+DEAL:0:2d::211
+DEAL:0:2d::242
+DEAL:0:2d::212
+DEAL:0:2d::243
+DEAL:0:2d::271
+DEAL:0:2d::302
+DEAL:0:2d::272
+DEAL:0:2d::303
+DEAL:0:2d::213
+DEAL:0:2d::244
+DEAL:0:2d::214
+DEAL:0:2d::245
+DEAL:0:2d::273
+DEAL:0:2d::304
+DEAL:0:2d::274
+DEAL:0:2d::305
+DEAL:0:2d::88
+DEAL:0:2d::96
+DEAL:0:2d::97
+DEAL:0:2d::113
+DEAL:0:2d::121
+DEAL:0:2d::122
+DEAL:0:2d::98
+DEAL:0:2d::99
+DEAL:0:2d::123
+DEAL:0:2d::124
+DEAL:0:2d::142
+DEAL:0:2d::152
+DEAL:0:2d::153
+DEAL:0:2d::173
+DEAL:0:2d::185
+DEAL:0:2d::186
+DEAL:0:2d::154
+DEAL:0:2d::155
+DEAL:0:2d::187
+DEAL:0:2d::188
+DEAL:0:2d::100
+DEAL:0:2d::111
+DEAL:0:2d::125
+DEAL:0:2d::140
+DEAL:0:2d::156
+DEAL:0:2d::157
+DEAL:0:2d::189
+DEAL:0:2d::190
+DEAL:0:2d::171
+DEAL:0:2d::158
+DEAL:0:2d::202
+DEAL:0:2d::191
+DEAL:0:2d::192
+DEAL:0:2d::193
+DEAL:0:2d::204
+DEAL:0:2d::215
+DEAL:0:2d::216
+DEAL:0:2d::235
+DEAL:0:2d::246
+DEAL:0:2d::247
+DEAL:0:2d::217
+DEAL:0:2d::218
+DEAL:0:2d::248
+DEAL:0:2d::249
+DEAL:0:2d::266
+DEAL:0:2d::275
+DEAL:0:2d::276
+DEAL:0:2d::297
+DEAL:0:2d::306
+DEAL:0:2d::307
+DEAL:0:2d::277
+DEAL:0:2d::278
+DEAL:0:2d::308
+DEAL:0:2d::309
+DEAL:0:2d::219
+DEAL:0:2d::220
+DEAL:0:2d::250
+DEAL:0:2d::251
+DEAL:0:2d::221
+DEAL:0:2d::222
+DEAL:0:2d::252
+DEAL:0:2d::253
+DEAL:0:2d::279
+DEAL:0:2d::280
+DEAL:0:2d::310
+DEAL:0:2d::311
+DEAL:0:2d::281
+DEAL:0:2d::282
+DEAL:0:2d::312
+DEAL:0:2d::313
+DEAL:0:2d::232
+DEAL:0:2d::223
+DEAL:0:2d::224
+DEAL:0:2d::264
+DEAL:0:2d::254
+DEAL:0:2d::255
+DEAL:0:2d::233
+DEAL:0:2d::225
+DEAL:0:2d::256
+DEAL:0:2d::226
+DEAL:0:2d::257
+DEAL:0:2d::283
+DEAL:0:2d::284
+DEAL:0:2d::285
+DEAL:0:2d::322
+DEAL:0:2d::227
+DEAL:0:2d::258
+DEAL:0:2d::259
+DEAL:0:2d::260
+DEAL:0:2d::286
+DEAL:0:2d::314
+DEAL:0:2d::287
+DEAL:0:2d::315
+DEAL:0:2d::288
+DEAL:0:2d::289
+DEAL:0:2d::323
+DEAL:0:2d::324
+DEAL:0:2d::290
+DEAL:0:2d::316
+DEAL:0:2d::325
+DEAL:0:2d::317
+DEAL:0:2d::228
+DEAL:0:2d::261
+DEAL:0:2d::262
+DEAL:0:2d::263
+DEAL:0:2d::291
+DEAL:0:2d::326
+DEAL:0:2d::292
+DEAL:0:2d::327
+DEAL:0:2d::293
+DEAL:0:2d::294
+DEAL:0:2d::318
+DEAL:0:2d::319
+DEAL:0:2d::295
+DEAL:0:2d::328
+DEAL:0:2d::320
+DEAL:0:2d::321
+DEAL:0:2d::331
+DEAL:0:2d::332
+DEAL:0:2d::333
+DEAL:0:2d::338
+DEAL:0:2d::334
+DEAL:0:2d::329
+DEAL:0:2d::339
+DEAL:0:2d::336
+DEAL:0:2d::335
+DEAL:0:2d::340
+DEAL:0:2d::330
+DEAL:0:2d::337
+DEAL:0:2d::343
+DEAL:0:2d::341
+DEAL:0:2d::342
+DEAL:0:2d::344
+DEAL:0:2d::51
+DEAL:0:2d::52
+DEAL:0:2d::63
+DEAL:0:2d::80
+DEAL:0:2d::81
+DEAL:0:2d::82
+DEAL:0:2d::68
+DEAL:0:2d::83
+DEAL:0:2d::101
+DEAL:0:2d::102
+DEAL:0:2d::103
+DEAL:0:2d::69
+DEAL:0:2d::84
+DEAL:0:2d::104
+DEAL:0:2d::105
+DEAL:0:2d::106
+DEAL:0:2d::107
+DEAL:0:2d::126
+DEAL:0:2d::127
+DEAL:0:2d::128
+DEAL:0:2d::89
+DEAL:0:2d::108
+DEAL:0:2d::129
+DEAL:0:2d::130
+DEAL:0:2d::131
+DEAL:0:2d::114
+DEAL:0:2d::132
+DEAL:0:2d::143
+DEAL:0:2d::159
+DEAL:0:2d::133
+DEAL:0:2d::160
+DEAL:0:2d::161
+DEAL:0:2d::162
+DEAL:0:2d::163
+DEAL:0:2d::174
+DEAL:0:2d::194
+DEAL:0:2d::90
+DEAL:0:2d::109
+DEAL:0:2d::134
+DEAL:0:2d::135
+DEAL:0:2d::136
+DEAL:0:2d::137
+DEAL:0:2d::164
+DEAL:0:2d::165
+DEAL:0:2d::166
+DEAL:0:2d::115
+DEAL:0:2d::138
+DEAL:0:2d::167
+DEAL:0:2d::144
+DEAL:0:2d::168
+DEAL:0:2d::195
+DEAL:0:2d::175
+DEAL:0:2d::169
+DEAL:0:2d::196
+DEAL:0:2d::197
+DEAL:0:2d::198
+DEAL:0:2d::199
+DEAL:0:2d::205
+DEAL:0:2d::229
+DEAL:0:2d::200
+DEAL:0:2d::230
+DEAL:0:2d::206
+DEAL:0:2d::231
+DEAL:0:2d::236
+DEAL:0:2d::237
+DEAL:0:3d::0
+DEAL:0:3d::1
+DEAL:0:3d::2
+DEAL:0:3d::4
+DEAL:0:3d::3
+DEAL:0:3d::5
+DEAL:0:3d::6
+DEAL:0:3d::7
+DEAL:0:3d::8
+DEAL:0:3d::11
+DEAL:0:3d::12
+DEAL:0:3d::20
+DEAL:0:3d::9
+DEAL:0:3d::13
+DEAL:0:3d::14
+DEAL:0:3d::21
+DEAL:0:3d::15
+DEAL:0:3d::22
+DEAL:0:3d::10
+DEAL:0:3d::16
+DEAL:0:3d::17
+DEAL:0:3d::23
+DEAL:0:3d::18
+DEAL:0:3d::24
+DEAL:0:3d::19
+DEAL:0:3d::25
+DEAL:0:3d::26
+DEAL:0:3d::27
+DEAL:0:3d::30
+DEAL:0:3d::31
+DEAL:0:3d::45
+DEAL:0:3d::64
+DEAL:0:3d::71
+DEAL:0:3d::72
+DEAL:0:3d::98
+DEAL:0:3d::32
+DEAL:0:3d::46
+DEAL:0:3d::73
+DEAL:0:3d::99
+DEAL:0:3d::33
+DEAL:0:3d::47
+DEAL:0:3d::74
+DEAL:0:3d::100
+DEAL:0:3d::48
+DEAL:0:3d::101
+DEAL:0:3d::28
+DEAL:0:3d::34
+DEAL:0:3d::35
+DEAL:0:3d::49
+DEAL:0:3d::36
+DEAL:0:3d::50
+DEAL:0:3d::65
+DEAL:0:3d::75
+DEAL:0:3d::76
+DEAL:0:3d::102
+DEAL:0:3d::77
+DEAL:0:3d::103
+DEAL:0:3d::37
+DEAL:0:3d::51
+DEAL:0:3d::52
+DEAL:0:3d::78
+DEAL:0:3d::104
+DEAL:0:3d::105
+DEAL:0:3d::38
+DEAL:0:3d::53
+DEAL:0:3d::79
+DEAL:0:3d::106
+DEAL:0:3d::80
+DEAL:0:3d::107
+DEAL:0:3d::66
+DEAL:0:3d::81
+DEAL:0:3d::54
+DEAL:0:3d::108
+DEAL:0:3d::109
+DEAL:0:3d::82
+DEAL:0:3d::29
+DEAL:0:3d::39
+DEAL:0:3d::40
+DEAL:0:3d::55
+DEAL:0:3d::41
+DEAL:0:3d::56
+DEAL:0:3d::42
+DEAL:0:3d::57
+DEAL:0:3d::58
+DEAL:0:3d::67
+DEAL:0:3d::83
+DEAL:0:3d::84
+DEAL:0:3d::110
+DEAL:0:3d::85
+DEAL:0:3d::111
+DEAL:0:3d::86
+DEAL:0:3d::112
+DEAL:0:3d::113
+DEAL:0:3d::43
+DEAL:0:3d::59
+DEAL:0:3d::87
+DEAL:0:3d::114
+DEAL:0:3d::60
+DEAL:0:3d::115
+DEAL:0:3d::88
+DEAL:0:3d::116
+DEAL:0:3d::68
+DEAL:0:3d::89
+DEAL:0:3d::117
+DEAL:0:3d::90
+DEAL:0:3d::44
+DEAL:0:3d::61
+DEAL:0:3d::62
+DEAL:0:3d::91
+DEAL:0:3d::118
+DEAL:0:3d::119
+DEAL:0:3d::92
+DEAL:0:3d::120
+DEAL:0:3d::121
+DEAL:0:3d::69
+DEAL:0:3d::93
+DEAL:0:3d::94
+DEAL:0:3d::63
+DEAL:0:3d::122
+DEAL:0:3d::123
+DEAL:0:3d::95
+DEAL:0:3d::124
+DEAL:0:3d::96
+DEAL:0:3d::97
+DEAL:0:3d::70
--- /dev/null
+
+DEAL:0:2d::0
+DEAL:0:2d::1
+DEAL:0:2d::2
+DEAL:0:2d::3
+DEAL:0:2d::4
+DEAL:0:2d::6
+DEAL:0:2d::5
+DEAL:0:2d::7
+DEAL:0:2d::8
+DEAL:0:2d::9
+DEAL:0:2d::11
+DEAL:0:2d::16
+DEAL:0:2d::18
+DEAL:0:2d::12
+DEAL:0:2d::19
+DEAL:0:2d::10
+DEAL:0:2d::13
+DEAL:0:2d::14
+DEAL:0:2d::17
+DEAL:0:2d::20
+DEAL:0:2d::21
+DEAL:0:2d::15
+DEAL:0:2d::22
+DEAL:0:2d::23
+DEAL:0:2d::24
+DEAL:0:2d::25
+DEAL:0:2d::27
+DEAL:0:2d::36
+DEAL:0:2d::38
+DEAL:0:2d::28
+DEAL:0:2d::39
+DEAL:0:2d::49
+DEAL:0:2d::53
+DEAL:0:2d::66
+DEAL:0:2d::68
+DEAL:0:2d::54
+DEAL:0:2d::69
+DEAL:0:2d::29
+DEAL:0:2d::40
+DEAL:0:2d::30
+DEAL:0:2d::41
+DEAL:0:2d::55
+DEAL:0:2d::70
+DEAL:0:2d::56
+DEAL:0:2d::71
+DEAL:0:2d::26
+DEAL:0:2d::31
+DEAL:0:2d::32
+DEAL:0:2d::37
+DEAL:0:2d::42
+DEAL:0:2d::43
+DEAL:0:2d::33
+DEAL:0:2d::34
+DEAL:0:2d::44
+DEAL:0:2d::45
+DEAL:0:2d::50
+DEAL:0:2d::57
+DEAL:0:2d::58
+DEAL:0:2d::67
+DEAL:0:2d::72
+DEAL:0:2d::73
+DEAL:0:2d::59
+DEAL:0:2d::60
+DEAL:0:2d::74
+DEAL:0:2d::75
+DEAL:0:2d::35
+DEAL:0:2d::46
+DEAL:0:2d::47
+DEAL:0:2d::48
+DEAL:0:2d::61
+DEAL:0:2d::76
+DEAL:0:2d::64
+DEAL:0:2d::80
+DEAL:0:2d::62
+DEAL:0:2d::65
+DEAL:0:2d::77
+DEAL:0:2d::81
+DEAL:0:2d::51
+DEAL:0:2d::52
+DEAL:0:2d::63
+DEAL:0:2d::82
+DEAL:0:2d::83
+DEAL:0:2d::84
+DEAL:0:2d::78
+DEAL:0:2d::85
+DEAL:0:2d::87
+DEAL:0:2d::91
+DEAL:0:2d::88
+DEAL:0:2d::79
+DEAL:0:2d::86
+DEAL:0:2d::92
+DEAL:0:2d::89
+DEAL:0:2d::90
+DEAL:0:2d::93
+DEAL:0:2d::95
+DEAL:0:2d::96
+DEAL:0:2d::94
+DEAL:0:2d::97
+DEAL:0:2d::98
+DEAL:0:2d::99
+DEAL:0:2d::100
+DEAL:0:2d::101
+DEAL:0:2d::103
+DEAL:0:2d::102
+DEAL:0:2d::104
+DEAL:0:2d::106
+DEAL:0:2d::108
+DEAL:0:2d::105
+DEAL:0:2d::109
+DEAL:0:2d::107
+DEAL:0:2d::110
+DEAL:0:2d::113
+DEAL:0:2d::115
+DEAL:0:2d::111
+DEAL:0:2d::112
+DEAL:0:2d::116
+DEAL:0:2d::117
+DEAL:0:2d::114
+DEAL:0:2d::118
+DEAL:0:2d::122
+DEAL:0:2d::124
+DEAL:0:2d::119
+DEAL:0:2d::125
+DEAL:0:2d::133
+DEAL:0:2d::134
+DEAL:0:2d::146
+DEAL:0:2d::148
+DEAL:0:2d::135
+DEAL:0:2d::149
+DEAL:0:2d::120
+DEAL:0:2d::126
+DEAL:0:2d::121
+DEAL:0:2d::127
+DEAL:0:2d::136
+DEAL:0:2d::150
+DEAL:0:2d::137
+DEAL:0:2d::151
+DEAL:0:2d::123
+DEAL:0:2d::128
+DEAL:0:2d::138
+DEAL:0:2d::145
+DEAL:0:2d::129
+DEAL:0:2d::130
+DEAL:0:2d::139
+DEAL:0:2d::140
+DEAL:0:2d::165
+DEAL:0:2d::158
+DEAL:0:2d::159
+DEAL:0:2d::174
+DEAL:0:2d::167
+DEAL:0:2d::168
+DEAL:0:2d::131
+DEAL:0:2d::132
+DEAL:0:2d::141
+DEAL:0:2d::142
+DEAL:0:2d::143
+DEAL:0:2d::152
+DEAL:0:2d::144
+DEAL:0:2d::153
+DEAL:0:2d::160
+DEAL:0:2d::161
+DEAL:0:2d::169
+DEAL:0:2d::170
+DEAL:0:2d::162
+DEAL:0:2d::154
+DEAL:0:2d::171
+DEAL:0:2d::166
+DEAL:0:2d::147
+DEAL:0:2d::155
+DEAL:0:2d::163
+DEAL:0:2d::172
+DEAL:0:2d::175
+DEAL:0:2d::156
+DEAL:0:2d::164
+DEAL:0:2d::157
+DEAL:0:2d::176
+DEAL:0:2d::178
+DEAL:0:2d::181
+DEAL:0:2d::182
+DEAL:0:2d::179
+DEAL:0:2d::177
+DEAL:0:2d::173
+DEAL:0:2d::180
+DEAL:0:2d::183
+DEAL:0:2d::184
+DEAL:0:2d::187
+DEAL:0:2d::185
+DEAL:0:2d::186
+DEAL:0:2d::189
+DEAL:0:2d::192
+DEAL:0:2d::199
+DEAL:0:2d::194
+DEAL:0:2d::201
+DEAL:0:2d::188
+DEAL:0:2d::190
+DEAL:0:2d::191
+DEAL:0:2d::193
+DEAL:0:2d::195
+DEAL:0:2d::196
+DEAL:0:2d::197
+DEAL:0:2d::202
+DEAL:0:2d::198
+DEAL:0:2d::203
+DEAL:0:2d::208
+DEAL:0:2d::220
+DEAL:0:2d::210
+DEAL:0:2d::231
+DEAL:0:2d::211
+DEAL:0:2d::221
+DEAL:0:2d::212
+DEAL:0:2d::222
+DEAL:0:2d::251
+DEAL:0:2d::244
+DEAL:0:2d::260
+DEAL:0:2d::253
+DEAL:0:2d::245
+DEAL:0:2d::254
+DEAL:0:2d::200
+DEAL:0:2d::204
+DEAL:0:2d::205
+DEAL:0:2d::209
+DEAL:0:2d::213
+DEAL:0:2d::214
+DEAL:0:2d::206
+DEAL:0:2d::207
+DEAL:0:2d::215
+DEAL:0:2d::216
+DEAL:0:2d::219
+DEAL:0:2d::223
+DEAL:0:2d::224
+DEAL:0:2d::232
+DEAL:0:2d::234
+DEAL:0:2d::235
+DEAL:0:2d::225
+DEAL:0:2d::226
+DEAL:0:2d::236
+DEAL:0:2d::237
+DEAL:0:2d::217
+DEAL:0:2d::227
+DEAL:0:2d::218
+DEAL:0:2d::228
+DEAL:0:2d::246
+DEAL:0:2d::255
+DEAL:0:2d::247
+DEAL:0:2d::256
+DEAL:0:2d::229
+DEAL:0:2d::230
+DEAL:0:2d::238
+DEAL:0:2d::239
+DEAL:0:2d::248
+DEAL:0:2d::257
+DEAL:0:2d::240
+DEAL:0:2d::252
+DEAL:0:2d::233
+DEAL:0:2d::241
+DEAL:0:2d::258
+DEAL:0:2d::249
+DEAL:0:2d::261
+DEAL:0:2d::264
+DEAL:0:2d::268
+DEAL:0:2d::267
+DEAL:0:2d::265
+DEAL:0:2d::242
+DEAL:0:2d::250
+DEAL:0:2d::262
+DEAL:0:2d::243
+DEAL:0:2d::263
+DEAL:0:2d::266
+DEAL:0:2d::259
+DEAL:0:2d::306
+DEAL:0:2d::294
+DEAL:0:2d::285
+DEAL:0:2d::317
+DEAL:0:2d::296
+DEAL:0:2d::287
+DEAL:0:2d::335
+DEAL:0:2d::321
+DEAL:0:2d::307
+DEAL:0:2d::322
+DEAL:0:2d::308
+DEAL:0:2d::297
+DEAL:0:2d::288
+DEAL:0:2d::298
+DEAL:0:2d::289
+DEAL:0:2d::278
+DEAL:0:2d::273
+DEAL:0:2d::280
+DEAL:0:2d::275
+DEAL:0:2d::270
+DEAL:0:2d::269
+DEAL:0:2d::272
+DEAL:0:2d::271
+DEAL:0:2d::281
+DEAL:0:2d::276
+DEAL:0:2d::282
+DEAL:0:2d::283
+DEAL:0:2d::277
+DEAL:0:2d::274
+DEAL:0:2d::284
+DEAL:0:2d::279
+DEAL:0:2d::323
+DEAL:0:2d::309
+DEAL:0:2d::324
+DEAL:0:2d::310
+DEAL:0:2d::299
+DEAL:0:2d::290
+DEAL:0:2d::300
+DEAL:0:2d::301
+DEAL:0:2d::325
+DEAL:0:2d::311
+DEAL:0:2d::318
+DEAL:0:2d::326
+DEAL:0:2d::312
+DEAL:0:2d::313
+DEAL:0:2d::327
+DEAL:0:2d::328
+DEAL:0:2d::291
+DEAL:0:2d::292
+DEAL:0:2d::302
+DEAL:0:2d::303
+DEAL:0:2d::293
+DEAL:0:2d::286
+DEAL:0:2d::304
+DEAL:0:2d::295
+DEAL:0:2d::314
+DEAL:0:2d::315
+DEAL:0:2d::329
+DEAL:0:2d::330
+DEAL:0:2d::316
+DEAL:0:2d::305
+DEAL:0:2d::331
+DEAL:0:2d::319
+DEAL:0:2d::343
+DEAL:0:2d::339
+DEAL:0:2d::344
+DEAL:0:2d::341
+DEAL:0:2d::332
+DEAL:0:2d::320
+DEAL:0:2d::336
+DEAL:0:2d::340
+DEAL:0:2d::342
+DEAL:0:2d::338
+DEAL:0:2d::337
+DEAL:0:2d::333
+DEAL:0:2d::334
+DEAL:0:3d::0
+DEAL:0:3d::1
+DEAL:0:3d::2
+DEAL:0:3d::4
+DEAL:0:3d::3
+DEAL:0:3d::5
+DEAL:0:3d::6
+DEAL:0:3d::7
+DEAL:0:3d::11
+DEAL:0:3d::20
+DEAL:0:3d::21
+DEAL:0:3d::26
+DEAL:0:3d::8
+DEAL:0:3d::12
+DEAL:0:3d::13
+DEAL:0:3d::22
+DEAL:0:3d::14
+DEAL:0:3d::23
+DEAL:0:3d::9
+DEAL:0:3d::15
+DEAL:0:3d::16
+DEAL:0:3d::24
+DEAL:0:3d::17
+DEAL:0:3d::25
+DEAL:0:3d::10
+DEAL:0:3d::18
+DEAL:0:3d::19
+DEAL:0:3d::27
+DEAL:0:3d::31
+DEAL:0:3d::32
+DEAL:0:3d::35
+DEAL:0:3d::36
+DEAL:0:3d::40
+DEAL:0:3d::41
+DEAL:0:3d::44
+DEAL:0:3d::28
+DEAL:0:3d::33
+DEAL:0:3d::37
+DEAL:0:3d::42
+DEAL:0:3d::29
+DEAL:0:3d::34
+DEAL:0:3d::38
+DEAL:0:3d::43
+DEAL:0:3d::30
+DEAL:0:3d::39
+DEAL:0:3d::45
+DEAL:0:3d::47
+DEAL:0:3d::48
+DEAL:0:3d::51
+DEAL:0:3d::55
+DEAL:0:3d::61
+DEAL:0:3d::46
+DEAL:0:3d::49
+DEAL:0:3d::50
+DEAL:0:3d::52
+DEAL:0:3d::56
+DEAL:0:3d::62
+DEAL:0:3d::53
+DEAL:0:3d::57
+DEAL:0:3d::58
+DEAL:0:3d::54
+DEAL:0:3d::59
+DEAL:0:3d::60
+DEAL:0:3d::63
+DEAL:0:3d::67
+DEAL:0:3d::69
+DEAL:0:3d::73
+DEAL:0:3d::64
+DEAL:0:3d::68
+DEAL:0:3d::70
+DEAL:0:3d::74
+DEAL:0:3d::65
+DEAL:0:3d::71
+DEAL:0:3d::66
+DEAL:0:3d::72
+DEAL:0:3d::75
+DEAL:0:3d::77
+DEAL:0:3d::78
+DEAL:0:3d::81
+DEAL:0:3d::85
+DEAL:0:3d::91
+DEAL:0:3d::83
+DEAL:0:3d::86
+DEAL:0:3d::87
+DEAL:0:3d::76
+DEAL:0:3d::79
+DEAL:0:3d::80
+DEAL:0:3d::82
+DEAL:0:3d::88
+DEAL:0:3d::92
+DEAL:0:3d::84
+DEAL:0:3d::89
+DEAL:0:3d::90
+DEAL:0:3d::93
+DEAL:0:3d::97
+DEAL:0:3d::99
+DEAL:0:3d::103
+DEAL:0:3d::94
+DEAL:0:3d::100
+DEAL:0:3d::95
+DEAL:0:3d::98
+DEAL:0:3d::101
+DEAL:0:3d::104
+DEAL:0:3d::96
+DEAL:0:3d::102
+DEAL:0:3d::105
+DEAL:0:3d::109
+DEAL:0:3d::113
+DEAL:0:3d::106
+DEAL:0:3d::110
+DEAL:0:3d::114
+DEAL:0:3d::107
+DEAL:0:3d::111
+DEAL:0:3d::115
+DEAL:0:3d::108
+DEAL:0:3d::112
+DEAL:0:3d::116
+DEAL:0:3d::117
+DEAL:0:3d::121
+DEAL:0:3d::118
+DEAL:0:3d::122
+DEAL:0:3d::119
+DEAL:0:3d::123
+DEAL:0:3d::120
+DEAL:0:3d::124
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// check correct behavior of sadd of Trilinos vectors
+// if they have different Epetra maps
+
+#include "../tests.h"
+#include <deal.II/base/utilities.h>
+#include <deal.II/base/index_set.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+
+void test ()
+{
+ const int n_proc = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD);
+ const int my_id = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
+
+ //All processes should own 10 entries
+ const int entries_per_process = 10;
+
+ IndexSet locally_owned(entries_per_process*n_proc);
+ const int begin_index = my_id*entries_per_process;
+ const int end_index = (my_id+1)*entries_per_process;
+ locally_owned.add_range(begin_index, end_index);
+
+ IndexSet locally_relevant(entries_per_process*n_proc);
+ const int local_begin = std::max(0, begin_index-entries_per_process/2);
+ const int local_end = entries_per_process*n_proc;
+ locally_relevant.add_range (local_begin, local_end);
+
+ TrilinosWrappers::MPI::Vector ghosted, distributed;
+ distributed.reinit(locally_owned, MPI_COMM_WORLD);
+ ghosted.reinit (locally_owned, locally_relevant, MPI_COMM_WORLD);
+
+ // set the 'distributed' vector to all ones and store its results in
+ // 'ghosted'
+ distributed=1.;
+ ghosted=distributed;
+
+ // then multiply 'distributed' by two and add 'ghosted' to it again
+ distributed*=2;
+ distributed.add(ghosted, true);
+
+ // assign the result, which should contain all 3s to 'ghosted'
+ ghosted = distributed;
+
+ if (my_id==0)
+ {
+ deallog << "Distributed:" << std::endl;
+ for (unsigned int i=begin_index; i<end_index; ++i)
+ deallog << i << ": " << distributed(i) << std::endl;
+
+ deallog << "Ghosted:" << std::endl;
+ for (unsigned int i=local_begin; i<local_end; ++i)
+ deallog << i << ": " << ghosted(i) << std::endl;
+ }
+
+ // verify correct value
+ for (unsigned int i=begin_index; i<end_index; ++i)
+ Assert(distributed(i)==3, ExcInternalError());
+
+ for (unsigned int i=local_begin; i<local_end; ++i)
+ Assert(ghosted(i)==3, ExcInternalError());
+}
+
+
+
+int main (int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv);
+
+ unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
+ deallog.push(Utilities::int_to_string(myid));
+
+ if (myid == 0)
+ {
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog << std::setprecision(4);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ test();
+ }
+ else
+ test();
+
+}
--- /dev/null
+
+DEAL:0::Distributed:
+DEAL:0::0: 3.000
+DEAL:0::1: 3.000
+DEAL:0::2: 3.000
+DEAL:0::3: 3.000
+DEAL:0::4: 3.000
+DEAL:0::5: 3.000
+DEAL:0::6: 3.000
+DEAL:0::7: 3.000
+DEAL:0::8: 3.000
+DEAL:0::9: 3.000
+DEAL:0::Ghosted:
+DEAL:0::0: 3.000
+DEAL:0::1: 3.000
+DEAL:0::2: 3.000
+DEAL:0::3: 3.000
+DEAL:0::4: 3.000
+DEAL:0::5: 3.000
+DEAL:0::6: 3.000
+DEAL:0::7: 3.000
+DEAL:0::8: 3.000
+DEAL:0::9: 3.000
+DEAL:0::10: 3.000
+DEAL:0::11: 3.000
+DEAL:0::12: 3.000
+DEAL:0::13: 3.000
+DEAL:0::14: 3.000
+DEAL:0::15: 3.000
+DEAL:0::16: 3.000
+DEAL:0::17: 3.000
+DEAL:0::18: 3.000
+DEAL:0::19: 3.000
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// check correct behaviour of sadd of Trilinos vectors
+// if they have different Epetra maps
+
+#include "../tests.h"
+#include <deal.II/base/utilities.h>
+#include <deal.II/base/index_set.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+
+void test ()
+{
+ TrilinosWrappers::MPI::Vector ghosted, distributed;
+ //All processes should own 10 entries
+ const int entries_per_process = 10;
+ const int n_proc = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD);
+ IndexSet locally_owned(entries_per_process*n_proc);
+ IndexSet locally_relevant(entries_per_process*n_proc);
+ const int my_id = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
+ const int begin_index = my_id*entries_per_process;
+ const int end_index = (my_id+1)*entries_per_process;
+ const int local_begin = std::max(0, begin_index-entries_per_process/2);
+ const int local_end = entries_per_process*n_proc;
+
+ locally_owned.add_range(begin_index, end_index);
+ locally_relevant.add_range
+ (local_begin, local_end);
+
+ distributed.reinit(locally_owned, MPI_COMM_WORLD);
+ ghosted.reinit (locally_owned, locally_relevant, MPI_COMM_WORLD);
+
+ distributed=1.;
+ ghosted=distributed;
+ distributed.sadd (2., ghosted);
+ ghosted = distributed;
+ deallog << "sadd (s, v)" <<std::endl;
+ if (my_id==0)
+ for (unsigned int i=local_begin; i<local_end; ++i)
+ deallog << i << ": " << ghosted(i) << std::endl;
+
+ distributed=1.;
+ ghosted=distributed;
+ distributed.sadd (2., 3., ghosted);
+ ghosted = distributed;
+ deallog << "sadd (s, a, v)" <<std::endl;
+ if (my_id==0)
+ for (unsigned int i=local_begin; i<local_end; ++i)
+ deallog << i << ": " << ghosted(i) << std::endl;
+
+ distributed=1.;
+ ghosted=distributed;
+ distributed.sadd (2., 3., ghosted, 4., ghosted);
+ ghosted = distributed;
+ deallog << "sadd (s, a, v, b, w)" <<std::endl;
+ if (my_id==0)
+ for (unsigned int i=local_begin; i<local_end; ++i)
+ deallog << i << ": " << ghosted(i) << std::endl;
+
+ distributed=1.;
+ ghosted=distributed;
+ distributed.sadd (2., 3., ghosted, 4., ghosted, 5., ghosted);
+ ghosted = distributed;
+ deallog << "sadd (s, a, v, b, w, c, x)" <<std::endl;
+ if (my_id==0)
+ for (unsigned int i=local_begin; i<local_end; ++i)
+ deallog << i << ": " << ghosted(i) << std::endl;
+}
+
+
+
+int main (int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv);
+
+ unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
+ deallog.push(Utilities::int_to_string(myid));
+
+ if (myid == 0)
+ {
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog << std::setprecision(4);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ test();
+ }
+ else
+ test();
+
+}
--- /dev/null
+
+DEAL:0::sadd (s, v)
+DEAL:0::0: 3.000
+DEAL:0::1: 3.000
+DEAL:0::2: 3.000
+DEAL:0::3: 3.000
+DEAL:0::4: 3.000
+DEAL:0::5: 3.000
+DEAL:0::6: 3.000
+DEAL:0::7: 3.000
+DEAL:0::8: 3.000
+DEAL:0::9: 3.000
+DEAL:0::sadd (s, a, v)
+DEAL:0::0: 5.000
+DEAL:0::1: 5.000
+DEAL:0::2: 5.000
+DEAL:0::3: 5.000
+DEAL:0::4: 5.000
+DEAL:0::5: 5.000
+DEAL:0::6: 5.000
+DEAL:0::7: 5.000
+DEAL:0::8: 5.000
+DEAL:0::9: 5.000
+DEAL:0::sadd (s, a, v, b, w)
+DEAL:0::0: 9.000
+DEAL:0::1: 9.000
+DEAL:0::2: 9.000
+DEAL:0::3: 9.000
+DEAL:0::4: 9.000
+DEAL:0::5: 9.000
+DEAL:0::6: 9.000
+DEAL:0::7: 9.000
+DEAL:0::8: 9.000
+DEAL:0::9: 9.000
+DEAL:0::sadd (s, a, v, b, w, c, x)
+DEAL:0::0: 14.00
+DEAL:0::1: 14.00
+DEAL:0::2: 14.00
+DEAL:0::3: 14.00
+DEAL:0::4: 14.00
+DEAL:0::5: 14.00
+DEAL:0::6: 14.00
+DEAL:0::7: 14.00
+DEAL:0::8: 14.00
+DEAL:0::9: 14.00
--- /dev/null
+
+DEAL:0::sadd (s, v)
+DEAL:0::0: 3.000
+DEAL:0::1: 3.000
+DEAL:0::2: 3.000
+DEAL:0::3: 3.000
+DEAL:0::4: 3.000
+DEAL:0::5: 3.000
+DEAL:0::6: 3.000
+DEAL:0::7: 3.000
+DEAL:0::8: 3.000
+DEAL:0::9: 3.000
+DEAL:0::10: 3.000
+DEAL:0::11: 3.000
+DEAL:0::12: 3.000
+DEAL:0::13: 3.000
+DEAL:0::14: 3.000
+DEAL:0::15: 3.000
+DEAL:0::16: 3.000
+DEAL:0::17: 3.000
+DEAL:0::18: 3.000
+DEAL:0::19: 3.000
+DEAL:0::sadd (s, a, v)
+DEAL:0::0: 5.000
+DEAL:0::1: 5.000
+DEAL:0::2: 5.000
+DEAL:0::3: 5.000
+DEAL:0::4: 5.000
+DEAL:0::5: 5.000
+DEAL:0::6: 5.000
+DEAL:0::7: 5.000
+DEAL:0::8: 5.000
+DEAL:0::9: 5.000
+DEAL:0::10: 5.000
+DEAL:0::11: 5.000
+DEAL:0::12: 5.000
+DEAL:0::13: 5.000
+DEAL:0::14: 5.000
+DEAL:0::15: 5.000
+DEAL:0::16: 5.000
+DEAL:0::17: 5.000
+DEAL:0::18: 5.000
+DEAL:0::19: 5.000
+DEAL:0::sadd (s, a, v, b, w)
+DEAL:0::0: 9.000
+DEAL:0::1: 9.000
+DEAL:0::2: 9.000
+DEAL:0::3: 9.000
+DEAL:0::4: 9.000
+DEAL:0::5: 9.000
+DEAL:0::6: 9.000
+DEAL:0::7: 9.000
+DEAL:0::8: 9.000
+DEAL:0::9: 9.000
+DEAL:0::10: 9.000
+DEAL:0::11: 9.000
+DEAL:0::12: 9.000
+DEAL:0::13: 9.000
+DEAL:0::14: 9.000
+DEAL:0::15: 9.000
+DEAL:0::16: 9.000
+DEAL:0::17: 9.000
+DEAL:0::18: 9.000
+DEAL:0::19: 9.000
+DEAL:0::sadd (s, a, v, b, w, c, x)
+DEAL:0::0: 14.00
+DEAL:0::1: 14.00
+DEAL:0::2: 14.00
+DEAL:0::3: 14.00
+DEAL:0::4: 14.00
+DEAL:0::5: 14.00
+DEAL:0::6: 14.00
+DEAL:0::7: 14.00
+DEAL:0::8: 14.00
+DEAL:0::9: 14.00
+DEAL:0::10: 14.00
+DEAL:0::11: 14.00
+DEAL:0::12: 14.00
+DEAL:0::13: 14.00
+DEAL:0::14: 14.00
+DEAL:0::15: 14.00
+DEAL:0::16: 14.00
+DEAL:0::17: 14.00
+DEAL:0::18: 14.00
+DEAL:0::19: 14.00
+++ /dev/null
-# accepts 0,1, or 2 arguments. If a string starting with a number is handed in, it is assumed to be a subdirectory of the current directory to run on. If not specified, the newest build is used. Any other string is taken as the branch name for this test (or treated as mainline). Order of the arguments does not matter.
-# for questions: Timo Heister
-
-import xml.etree.ElementTree as ET
-import glob
-import sys
-from datetime import datetime
-import subprocess
-
-class Group:
- def __init__(self, name):
- self.name = name
- self.n_tests = 0
- self.n_fail = 0
- self.fail = []
- self.fail_text = {}
-
-class Revision:
- def __init__(self):
- self.groups = {}
- self.number = -1
- self.name = ''
- self.n_tests = 0
- self.n_fail = 0
-
-branch=''
-args=sys.argv
-args.pop(0)
-
-dirname=""
-while len(args)>0:
- if args[0].startswith("20"): #I hope this script is not used in the year 2100
- dirname=args[0].replace('/','')
- else:
- branch=args[0].replace('/','')+'/'
- args.pop(0)
-
-if dirname=="":
- n=glob.glob("*/Build.xml")
- n.sort(reverse=True)
- dirname = n[0].replace('/Build.xml','')
-
-if len(glob.glob(dirname+'/Update.xml'))>0:
- #new format
- tree = ET.parse(dirname+'/Update.xml')
- name = tree.getroot().find('BuildName').text
- number = tree.getroot().find('Revision').text
- date = datetime.strptime(dirname,"%Y%m%d-%H%M")
-else:
- #old format
- tree = ET.parse(dirname+'/Notes.xml')
- name = tree.getroot().attrib['BuildName']
- number = name.split('-')[-1]
- number = number[1:]
- date = datetime.strptime(dirname,"%Y%m%d-%H%M")
-
-
-header = "Revision: %s"%number + "\n"
-header += "Date: %s"%(date.strftime("%Y %j %F %U-%w")) + '\n'
-id = subprocess.check_output(["id","-un"])+'@'+subprocess.check_output(["hostname"])
-id=id.replace('\n','')
-header += "Id: %s"%id
-
-#now Test.xml:
-tree = ET.parse(dirname+'/Test.xml')
-root = tree.getroot()
-testing = root.find('Testing')
-
-tests={}
-
-for test in testing.findall("Test"):
- name = test.find('Name').text
- group = name.split('/')[0]
-
- if group=="all-headers":
- name = group + "/" + "-".join(name.split('/')[1:])
-
- text = test.find('Results').find('Measurement').find('Value').text
- if text == None: text=""
- failtext = text.encode('utf-8')
- failtextlines = failtext.replace('"','').split('\n')
- failstatustxt = failtextlines[0].split(' ')[-1]
-
- statuslist=['CONFIGURE','BUILD','RUN','DIFF','PASSED']
- status=-1
- if failstatustxt in statuslist:
- status = statuslist.index(failstatustxt)
- else:
- for meas in test.find('Results').findall('NamedMeasurement'):
- if (meas.attrib["name"]=="Exit Code" and meas.find('Value').text=="Timeout"):
- status=3
- if status == -1:
- print >>sys.stderr, "unknown status '%s' in test %s "% (failstatustxt,name)
- status=0
-
- stati = [" 0 "," 1 "," 2 "," 3 "," + "]
- line = "%s %s %s%s"%(date,stati[status],branch,name)
-
- if group not in tests: tests[group]=[]
- tests[group].append( line )
-
-for g in sorted(tests):
- group = tests[g]
- print header
- for l in group:
- print l
-
-
-