summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Project/ControlEditor.cpp61
-rw-r--r--Project/ControlEditor.h4
-rw-r--r--Project/ControlElementContainer.h3
-rw-r--r--Project/ControlElementSolver.cpp4
-rw-r--r--Project/ElementForm.wxcp1029
-rw-r--r--Project/MathExprParser.cpp26
-rw-r--r--Project/MathExprParser.h30
-rw-r--r--Project/MathExpression.cpp252
-rw-r--r--Project/MathExpression.h68
-rw-r--r--Project/MathExpressionForm.cpp119
-rw-r--r--Project/MathExpressionForm.h48
-rw-r--r--Project/OpenGLText.cpp13
-rw-r--r--Project/OpenGLText.h10
-rw-r--r--Project/Project.mk59
-rw-r--r--Project/Project.project16
-rw-r--r--Project/Project.txt4
-rw-r--r--Project/Workspace.cpp3
-rw-r--r--Project/base/ElementFormBase.cpp157
-rw-r--r--Project/base/ElementFormBase.h37
-rw-r--r--Project/data/lang/pt_BR/pt_BR.mobin47191 -> 48550 bytes
-rw-r--r--Project/data/lang/pt_BR/pt_BR.po2418
-rw-r--r--Project/fparser/docs/fparser.html1841
-rw-r--r--Project/fparser/docs/gpl.txt674
-rw-r--r--Project/fparser/docs/lgpl.txt165
-rw-r--r--Project/fparser/docs/style.css80
-rw-r--r--Project/fparser/examples/example.cc55
-rw-r--r--Project/fparser/examples/example2.cc85
-rw-r--r--Project/fparser/extrasrc/fp_identifier_parser.inc379
-rw-r--r--Project/fparser/extrasrc/fp_opcode_add.inc7696
-rw-r--r--Project/fparser/extrasrc/fpaux.hh1249
-rw-r--r--Project/fparser/extrasrc/fptypes.hh286
-rw-r--r--Project/fparser/fparser.cc3800
-rw-r--r--Project/fparser/fparser.hh223
-rw-r--r--Project/fparser/fparser_gmpint.hh15
-rw-r--r--Project/fparser/fparser_mpfr.hh15
-rw-r--r--Project/fparser/fpconfig.hh88
-rw-r--r--Project/fparser/fpoptimizer.cc11763
-rw-r--r--Project/fparser/mpfr/GmpInt.cc710
-rw-r--r--Project/fparser/mpfr/GmpInt.hh148
-rw-r--r--Project/fparser/mpfr/MpfrFloat.cc976
-rw-r--r--Project/fparser/mpfr/MpfrFloat.hh206
41 files changed, 33602 insertions, 1213 deletions
diff --git a/Project/ControlEditor.cpp b/Project/ControlEditor.cpp
index 45cc10d..becfa43 100644
--- a/Project/ControlEditor.cpp
+++ b/Project/ControlEditor.cpp
@@ -20,23 +20,24 @@
#ifdef USING_WX_3_0_X
#include "DegreesAndRadians.h"
#endif
-#include "FileHanding.h"
#include "Camera.h"
-#include "ControlElement.h"
-#include "TransferFunction.h"
#include "ConnectionLine.h"
-#include "Sum.h"
-#include "Multiplier.h"
-#include "Limiter.h"
-#include "RateLimiter.h"
-#include "Exponential.h"
#include "Constant.h"
+#include "ControlElement.h"
+#include "Divider.h"
+#include "Exponential.h"
+#include "FileHanding.h"
#include "Gain.h"
+#include "Limiter.h"
+#include "MathExpression.h"
#include "MathOperation.h"
-#include "Divider.h"
+#include "Multiplier.h"
+#include "RateLimiter.h"
+#include "Sum.h"
+#include "TransferFunction.h"
-#include "ControlElementSolver.h"
#include "ControlElementContainer.h"
+#include "ControlElementSolver.h"
#include "ChartView.h"
#include "ElementPlotData.h"
@@ -213,6 +214,13 @@ void ControlEditor::BuildControlElementPanel()
wrapSizer->Add(divButton, 0, wxALL, 5);
divButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown, this);
+ ControlElementButton* mathExprButton = new ControlElementButton(
+ m_panelControlElements, _("Math Expression"),
+ wxImage(exePath + wxFileName::DirName("\\..\\data\\images\\control\\sum.png", wxPATH_WIN).GetPath()),
+ ID_MATH_EXPR);
+ wrapSizer->Add(mathExprButton, 0, wxALL, 5);
+ mathExprButton->Bind(wxEVT_LEFT_DOWN, &ControlEditor::LeftClickDown, this);
+
ControlElementButton* satButton = new ControlElementButton(
m_panelControlElements, _("Exponential"),
wxImage(exePath + wxFileName::DirName("\\..\\data\\images\\control\\sat.png", wxPATH_WIN).GetPath()), ID_EXP);
@@ -303,7 +311,12 @@ void ControlEditor::AddElement(ControlElementButtonID id)
m_mode = MODE_INSERT;
Divider* divider = new Divider(GetNextID());
m_elementList.push_back(divider);
- }
+ } break;
+ case ID_MATH_EXPR: {
+ m_mode = MODE_INSERT;
+ MathExpression* mathExpr = new MathExpression(GetNextID());
+ m_elementList.push_back(mathExpr);
+ } break;
}
}
@@ -461,9 +474,7 @@ void ControlEditor::OnLeftClickUp(wxMouseEvent& event)
element->SetSelected(false);
}
} else if(!event.ControlDown()) {
- if(!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
- element->SetSelected(false);
- }
+ if(!element->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { element->SetSelected(false); }
}
}
for(auto it = m_connectionList.begin(), itEnd = m_connectionList.end(); it != itEnd; ++it) {
@@ -485,9 +496,7 @@ void ControlEditor::OnLeftClickUp(wxMouseEvent& event)
cLine->SetSelected(false);
}
} else if(!event.ControlDown()) {
- if(!cLine->Contains(m_camera->ScreenToWorld(event.GetPosition()))) {
- cLine->SetSelected(false);
- }
+ if(!cLine->Contains(m_camera->ScreenToWorld(event.GetPosition()))) { cLine->SetSelected(false); }
}
}
@@ -643,7 +652,7 @@ void ControlEditor::OnIdle(wxIdleEvent& event)
{
if(m_justOpened) {
this->Raise();
-
+
// Update all text elements
m_justOpened = false;
for(auto it = m_elementList.begin(), itEnd = m_elementList.end(); it != itEnd; ++it) {
@@ -715,9 +724,7 @@ void ControlEditor::DeleteSelectedElements()
for(auto it = m_connectionList.begin(); it != m_connectionList.end(); ++it) {
ConnectionLine* line = *it;
- if(line->IsSelected()) {
- it = DeleteLineFromList(it);
- }
+ if(line->IsSelected()) { it = DeleteLineFromList(it); }
}
Redraw();
}
@@ -730,9 +737,7 @@ std::vector<ConnectionLine*>::iterator ControlEditor::DeleteLineFromList(std::ve
ConnectionLine* child = *itC;
for(auto itL = m_connectionList.begin(); itL != m_connectionList.end(); ++itL) {
ConnectionLine* childOnList = *itL;
- if(childOnList == child) {
- itL = DeleteLineFromList(itL);
- }
+ if(childOnList == child) { itL = DeleteLineFromList(itL); }
}
}
// Remove
@@ -758,9 +763,7 @@ void ControlEditor::CheckConnections()
for(auto it = m_connectionList.begin(); it != m_connectionList.end(); ++it) {
ConnectionLine* cLine = *it;
if(cLine->GetType() == ConnectionLine::ELEMENT_ELEMENT) {
- if(cLine->GetParentList().size() < 2) {
- it = DeleteLineFromList(it);
- }
+ if(cLine->GetParentList().size() < 2) { it = DeleteLineFromList(it); }
}
}
}
@@ -891,9 +894,7 @@ void ControlEditor::OnTestClick(wxCommandEvent& event)
void ControlEditor::OnClose(wxCloseEvent& event)
{
- if(m_ctrlContainer) {
- m_ctrlContainer->FillContainer(this);
- }
+ if(m_ctrlContainer) { m_ctrlContainer->FillContainer(this); }
event.Skip();
}
diff --git a/Project/ControlEditor.h b/Project/ControlEditor.h
index 615ecce..f799ca5 100644
--- a/Project/ControlEditor.h
+++ b/Project/ControlEditor.h
@@ -46,6 +46,7 @@ class Constant;
class Gain;
class MathOperation;
class Divider;
+class MathExpression;
class ControlElementSolver;
class ControlElementContainer;
@@ -63,7 +64,8 @@ enum ControlElementButtonID {
ID_MULT,
ID_EXP,
ID_RATELIM,
- ID_MATH_DIV
+ ID_MATH_DIV,
+ ID_MATH_EXPR
};
/**
diff --git a/Project/ControlElementContainer.h b/Project/ControlElementContainer.h
index c8af332..502c775 100644
--- a/Project/ControlElementContainer.h
+++ b/Project/ControlElementContainer.h
@@ -34,6 +34,7 @@ class ControlElement;
#include "Sum.h"
#include "TransferFunction.h"
#include "Divider.h"
+#include "MathExpression.h"
/**
* @class ControlElementContainer
@@ -68,6 +69,7 @@ class ControlElementContainer
std::vector<Sum*> GetSumList() const { return m_sumList; }
std::vector<TransferFunction*> GetTFList() const { return m_tfList; }
std::vector<Divider*> GetDividerList() const { return m_dividerList; }
+ std::vector<MathExpression*> GetMathExprList() const { return m_mathExprList; }
protected:
std::vector<ControlElement*> m_ctrlElementsList;
std::vector<Constant*> m_constantList;
@@ -81,6 +83,7 @@ class ControlElementContainer
std::vector<Sum*> m_sumList;
std::vector<TransferFunction*> m_tfList;
std::vector<Divider*> m_dividerList;
+ std::vector<MathExpression*> m_mathExprList;
};
#endif // CONTROLELEMENTCONTAINER_H
diff --git a/Project/ControlElementSolver.cpp b/Project/ControlElementSolver.cpp
index 4ca4ef4..3534023 100644
--- a/Project/ControlElementSolver.cpp
+++ b/Project/ControlElementSolver.cpp
@@ -204,8 +204,8 @@ void ControlElementSolver::SolveNextStep()
ConnectionLine* child = static_cast<ConnectionLine*>(io->GetChildList()[0]);
if(m_inputControl == io) firstConn = child;
bool inputType = true;
+ io->SetSolved();
switch(io->GetValue()) {
- io->SetSolved();
case IOControl::IN_TERMINAL_VOLTAGE: {
child->SetValue(m_terminalVoltage);
} break;
@@ -235,6 +235,7 @@ void ControlElementSolver::SolveNextStep()
} break;
default: {
inputType = false;
+ io->SetSolved(false);
} break;
}
if(inputType) {
@@ -286,7 +287,6 @@ void ControlElementSolver::SolveNextStep()
io->SetSolved();
ConnectionLine* child = static_cast<ConnectionLine*>(io->GetChildList()[0]);
switch(io->GetValue()) {
- io->SetSolved();
case IOControl::OUT_MEC_POWER: {
m_mecPower = child->GetValue();
m_solutions.push_back(m_mecPower);
diff --git a/Project/ElementForm.wxcp b/Project/ElementForm.wxcp
index b9d19e1..a756e62 100644
--- a/Project/ElementForm.wxcp
+++ b/Project/ElementForm.wxcp
@@ -1,7 +1,7 @@
{
"metadata": {
"m_generatedFilesDir": "base/",
- "m_objCounter": 1932,
+ "m_objCounter": 1975,
"m_includeFiles": [],
"m_bitmapFunction": "wxC9EE9InitBitmapResources",
"m_bitmapsFile": "ElementFormBitmaps.cpp",
@@ -38074,5 +38074,1032 @@
}]
}]
}]
+ }, {
+ "m_type": 4421,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": ["wxDEFAULT_DIALOG_STYLE"],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"],
+ "m_properties": [{
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "MathExpressionFormBase"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Enable Window Persistency:",
+ "m_value": true
+ }, {
+ "type": "string",
+ "m_label": "Title:",
+ "m_value": "Math expression"
+ }, {
+ "type": "virtualFolderPicker",
+ "m_label": "Virtual Folder:",
+ "m_path": "Project:wxcrafter"
+ }, {
+ "type": "choice",
+ "m_label": "Centre:",
+ "m_selection": 1,
+ "m_options": ["", "wxBOTH", "wxVERTICAL", "wxHORIZONTAL"]
+ }, {
+ "type": "string",
+ "m_label": "Inherited Class",
+ "m_value": "MathExpressionForm"
+ }, {
+ "type": "string",
+ "m_label": "File:",
+ "m_value": "MathExpressionForm"
+ }, {
+ "type": "string",
+ "m_label": "Class Decorator",
+ "m_value": ""
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File (16x16) :",
+ "m_path": ""
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File (32x32) :",
+ "m_path": ""
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File (64x64) :",
+ "m_path": ""
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File (128x128):",
+ "m_path": ""
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File (256x256):",
+ "m_path": ""
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4401,
+ "proportion": 1,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxEXPAND"],
+ "m_properties": [{
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "boxSizerLvl1_1"
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "choice",
+ "m_label": "Orientation:",
+ "m_selection": 0,
+ "m_options": ["wxVERTICAL", "wxHORIZONTAL"]
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4442,
+ "proportion": 1,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": ["wxBK_DEFAULT"],
+ "m_sizerFlags": ["wxEXPAND"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_notebook"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4441,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": ["wxTAB_TRAVERSAL"],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_panelGeneral"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Label:",
+ "m_value": "General"
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File:",
+ "m_path": ""
+ }, {
+ "type": "bool",
+ "m_label": "Selected",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Null Page",
+ "m_value": false
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4401,
+ "proportion": 1,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxEXPAND"],
+ "m_properties": [{
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "boxSizerLvl2_1"
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "choice",
+ "m_label": "Orientation:",
+ "m_selection": 0,
+ "m_options": ["wxVERTICAL", "wxHORIZONTAL"]
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4405,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxLEFT", "wxRIGHT", "wxTOP", "wxALIGN_CENTER_VERTICAL"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_staticTextVariables"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Label:",
+ "m_value": "Input variables (space separated)"
+ }, {
+ "type": "string",
+ "m_label": "Wrap:",
+ "m_value": "-1"
+ }],
+ "m_events": [],
+ "m_children": []
+ }, {
+ "m_type": 4406,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxLEFT", "wxRIGHT", "wxBOTTOM", "wxEXPAND", "wxALIGN_CENTER_VERTICAL"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "100,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_textCtrlVariables"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Value:",
+ "m_value": "x y"
+ }, {
+ "type": "string",
+ "m_label": "Text Hint",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Max Length:",
+ "m_value": "0"
+ }, {
+ "type": "bool",
+ "m_label": "Auto Complete Directories:",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Auto Complete Files:",
+ "m_value": false
+ }],
+ "m_events": [{
+ "m_eventName": "wxEVT_COMMAND_TEXT_UPDATED",
+ "m_eventClass": "wxCommandEvent",
+ "m_eventHandler": "wxCommandEventHandler",
+ "m_functionNameAndSignature": "OnTextUpdate(wxCommandEvent& event)",
+ "m_description": "Respond to a wxEVT_COMMAND_TEXT_UPDATED event, generated when the text changes.\nNotice that this event will be sent when the text controls contents changes\n - whether this is due to user input or comes from the program itself\n(for example, if SetValue() is called); see ChangeValue() for a function which does not send this event.",
+ "m_noBody": false
+ }, {
+ "m_eventName": "wxEVT_COMMAND_TEXT_ENTER",
+ "m_eventClass": "wxCommandEvent",
+ "m_eventHandler": "wxCommandEventHandler",
+ "m_functionNameAndSignature": "OnTextEnter(wxCommandEvent& event)",
+ "m_description": "Respond to a wxEVT_COMMAND_TEXT_ENTER event, generated when enter is pressed in a text control\n(which must have wxTE_PROCESS_ENTER style for this event to be generated).",
+ "m_noBody": false
+ }],
+ "m_children": []
+ }, {
+ "m_type": 4466,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "400,200"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_stcMathExpr"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Fold Margin",
+ "m_value": true
+ }, {
+ "type": "bool",
+ "m_label": "Line Number Margin",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Separator Margin",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Symbol Margin",
+ "m_value": false
+ }, {
+ "type": "choice",
+ "m_label": "Wrap Text",
+ "m_selection": 0,
+ "m_options": ["None", "Word", "Char"]
+ }, {
+ "type": "choice",
+ "m_label": "Indentation Guides",
+ "m_selection": 0,
+ "m_options": ["None", "Real", "Look Forward", "Look Both"]
+ }, {
+ "type": "choice",
+ "m_label": "EOL Mode",
+ "m_selection": 3,
+ "m_options": ["CRLF", "CR", "LF", "Default"]
+ }, {
+ "type": "bool",
+ "m_label": "Display EOL Markers",
+ "m_value": false
+ }, {
+ "type": "choice",
+ "m_label": "Lexer",
+ "m_selection": 61,
+ "m_options": ["wxSTC_LEX_ABAQUS", "wxSTC_LEX_ADA", "wxSTC_LEX_APDL", "wxSTC_LEX_ASM", "wxSTC_LEX_ASN1", "wxSTC_LEX_ASYMPTOTE", "wxSTC_LEX_AUTOMATIC", "wxSTC_LEX_AVE", "wxSTC_LEX_BAAN", "wxSTC_LEX_BASH", "wxSTC_LEX_BATCH", "wxSTC_LEX_BLITZBASIC", "wxSTC_LEX_BULLANT", "wxSTC_LEX_CAML", "wxSTC_LEX_CLW", "wxSTC_LEX_CLWNOCASE", "wxSTC_LEX_CMAKE", "wxSTC_LEX_COBOL", "wxSTC_LEX_CONF", "wxSTC_LEX_CONTAINER", "wxSTC_LEX_CPP", "wxSTC_LEX_CPPNOCASE", "wxSTC_LEX_CSOUND", "wxSTC_LEX_CSS", "wxSTC_LEX_D", "wxSTC_LEX_DIFF", "wxSTC_LEX_EIFFEL", "wxSTC_LEX_EIFFELKW", "wxSTC_LEX_ERLANG", "wxSTC_LEX_ERRORLIST", "wxSTC_LEX_ESCRIPT", "wxSTC_LEX_F77", "wxSTC_LEX_FLAGSHIP", "wxSTC_LEX_FORTH", "wxSTC_LEX_FORTRAN", "wxSTC_LEX_FREEBASIC", "wxSTC_LEX_GAP", "wxSTC_LEX_GUI4CLI", "wxSTC_LEX_HASKELL", "wxSTC_LEX_HTML", "wxSTC_LEX_INNOSETUP", "wxSTC_LEX_KIX", "wxSTC_LEX_LATEX", "wxSTC_LEX_LISP", "wxSTC_LEX_LOT", "wxSTC_LEX_LOUT", "wxSTC_LEX_LUA", "wxSTC_LEX_MAGIK", "wxSTC_LEX_MAKEFILE", "wxSTC_LEX_MARKDOWN", "wxSTC_LEX_MATLAB", "wxSTC_LEX_METAPOST", "wxSTC_LEX_MMIXAL", "wxSTC_LEX_MSSQL", "wxSTC_LEX_MYSQL", "wxSTC_LEX_NIMROD", "wxSTC_LEX_NNCRONTAB", "wxSTC_LEX_NSIS", "wxSTC_LEX_NULL", "wxSTC_LEX_OCTAVE", "wxSTC_LEX_OPAL", "wxSTC_LEX_PASCAL", "wxSTC_LEX_PERL", "wxSTC_LEX_PHPSCRIPT", "wxSTC_LEX_PLM", "wxSTC_LEX_PO", "wxSTC_LEX_POV", "wxSTC_LEX_POWERBASIC", "wxSTC_LEX_POWERPRO", "wxSTC_LEX_POWERSHELL", "wxSTC_LEX_PROGRESS", "wxSTC_LEX_PROPERTIES", "wxSTC_LEX_PS", "wxSTC_LEX_PUREBASIC", "wxSTC_LEX_PYTHON", "wxSTC_LEX_R", "wxSTC_LEX_REBOL", "wxSTC_LEX_RUBY", "wxSTC_LEX_SCRIPTOL", "wxSTC_LEX_SMALLTALK", "wxSTC_LEX_SML", "wxSTC_LEX_SORCUS", "wxSTC_LEX_SPECMAN", "wxSTC_LEX_SPICE", "wxSTC_LEX_SQL", "wxSTC_LEX_TACL", "wxSTC_LEX_TADS3", "wxSTC_LEX_TAL", "wxSTC_LEX_TCL", "wxSTC_LEX_TEX", "wxSTC_LEX_VB", "wxSTC_LEX_VBSCRIPT", "wxSTC_LEX_VERILOG", "wxSTC_LEX_VHDL", "wxSTC_LEX_XCODE", "wxSTC_LEX_XML", "wxSTC_LEX_YAML"]
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": "10,normal, normal, modern, 0, Courier New"
+ }, {
+ "type": "multi-string",
+ "m_label": "Keywords Set 1",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Keywords Set 2",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Keywords Set 3",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Keywords Set 4",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Keywords Set 5",
+ "m_value": ""
+ }],
+ "m_events": [{
+ "m_eventName": "wxEVT_LEFT_DOWN",
+ "m_eventClass": "wxMouseEvent",
+ "m_eventHandler": "wxMouseEventHandler",
+ "m_functionNameAndSignature": "OnLeftClickDown(wxMouseEvent& event)",
+ "m_description": "Process a wxEVT_LEFT_DOWN event. The handler of this event should normally call event.Skip() to allow the default processing to take place as otherwise the window under mouse wouldn't get the focus.",
+ "m_noBody": false
+ }],
+ "m_children": []
+ }]
+ }]
+ }]
+ }, {
+ "m_type": 4405,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxLEFT", "wxRIGHT", "wxTOP", "wxALIGN_CENTER_HORIZONTAL", "wxALIGN_CENTER_VERTICAL"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_staticTextCheckStatus"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "multi-string",
+ "m_label": "Label:",
+ "m_value": "No checks performed"
+ }, {
+ "type": "string",
+ "m_label": "Wrap:",
+ "m_value": "-1"
+ }],
+ "m_events": [],
+ "m_children": []
+ }, {
+ "m_type": 4401,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxEXPAND"],
+ "m_properties": [{
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "boxSizerBottomButtons"
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "choice",
+ "m_label": "Orientation:",
+ "m_selection": 1,
+ "m_options": ["wxVERTICAL", "wxHORIZONTAL"]
+ }],
+ "m_events": [],
+ "m_children": [{
+ "m_type": 4400,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxALIGN_LEFT"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_buttonCheck"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Label:",
+ "m_value": "Check expression"
+ }, {
+ "type": "bool",
+ "m_label": "Default Button",
+ "m_value": false
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File:",
+ "m_path": ""
+ }, {
+ "type": "choice",
+ "m_label": "Direction",
+ "m_selection": 0,
+ "m_options": ["wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"]
+ }, {
+ "type": "string",
+ "m_label": "Margins:",
+ "m_value": "2,2"
+ }],
+ "m_events": [{
+ "m_eventName": "wxEVT_COMMAND_BUTTON_CLICKED",
+ "m_eventClass": "wxCommandEvent",
+ "m_eventHandler": "wxCommandEventHandler",
+ "m_functionNameAndSignature": "OnCheckButtonClick(wxCommandEvent& event)",
+ "m_description": "Process a wxEVT_COMMAND_BUTTON_CLICKED event, when the button is clicked.",
+ "m_noBody": false
+ }],
+ "m_children": []
+ }, {
+ "m_type": 4454,
+ "proportion": 1,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"],
+ "m_properties": [{
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "Spacer_1"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "0,0"
+ }],
+ "m_events": [],
+ "m_children": []
+ }, {
+ "m_type": 4400,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxALIGN_RIGHT"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_buttonOK"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Label:",
+ "m_value": "OK"
+ }, {
+ "type": "bool",
+ "m_label": "Default Button",
+ "m_value": false
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File:",
+ "m_path": ""
+ }, {
+ "type": "choice",
+ "m_label": "Direction",
+ "m_selection": 0,
+ "m_options": ["wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"]
+ }, {
+ "type": "string",
+ "m_label": "Margins:",
+ "m_value": "2,2"
+ }],
+ "m_events": [{
+ "m_eventName": "wxEVT_COMMAND_BUTTON_CLICKED",
+ "m_eventClass": "wxCommandEvent",
+ "m_eventHandler": "wxCommandEventHandler",
+ "m_functionNameAndSignature": "OnOKButtonClick(wxCommandEvent& event)",
+ "m_description": "Process a wxEVT_COMMAND_BUTTON_CLICKED event, when the button is clicked.",
+ "m_noBody": false
+ }],
+ "m_children": []
+ }, {
+ "m_type": 4400,
+ "proportion": 0,
+ "border": 5,
+ "gbSpan": "1,1",
+ "gbPosition": "0,0",
+ "m_styles": [],
+ "m_sizerFlags": ["wxALL", "wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM", "wxALIGN_RIGHT"],
+ "m_properties": [{
+ "type": "winid",
+ "m_label": "ID:",
+ "m_winid": "wxID_ANY"
+ }, {
+ "type": "string",
+ "m_label": "Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Minimum Size:",
+ "m_value": "-1,-1"
+ }, {
+ "type": "string",
+ "m_label": "Name:",
+ "m_value": "m_buttonCancel"
+ }, {
+ "type": "multi-string",
+ "m_label": "Tooltip:",
+ "m_value": ""
+ }, {
+ "type": "colour",
+ "m_label": "Bg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "colour",
+ "m_label": "Fg Colour:",
+ "colour": "<Default>"
+ }, {
+ "type": "font",
+ "m_label": "Font:",
+ "m_value": ""
+ }, {
+ "type": "bool",
+ "m_label": "Hidden",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Disabled",
+ "m_value": false
+ }, {
+ "type": "bool",
+ "m_label": "Focused",
+ "m_value": false
+ }, {
+ "type": "string",
+ "m_label": "Class Name:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Include File:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Style:",
+ "m_value": ""
+ }, {
+ "type": "string",
+ "m_label": "Label:",
+ "m_value": "Cancel"
+ }, {
+ "type": "bool",
+ "m_label": "Default Button",
+ "m_value": false
+ }, {
+ "type": "bitmapPicker",
+ "m_label": "Bitmap File:",
+ "m_path": ""
+ }, {
+ "type": "choice",
+ "m_label": "Direction",
+ "m_selection": 0,
+ "m_options": ["wxLEFT", "wxRIGHT", "wxTOP", "wxBOTTOM"]
+ }, {
+ "type": "string",
+ "m_label": "Margins:",
+ "m_value": "2,2"
+ }],
+ "m_events": [{
+ "m_eventName": "wxEVT_COMMAND_BUTTON_CLICKED",
+ "m_eventClass": "wxCommandEvent",
+ "m_eventHandler": "wxCommandEventHandler",
+ "m_functionNameAndSignature": "OnCancelButtonClick(wxCommandEvent& event)",
+ "m_description": "Process a wxEVT_COMMAND_BUTTON_CLICKED event, when the button is clicked.",
+ "m_noBody": false
+ }],
+ "m_children": []
+ }]
+ }]
+ }]
}]
} \ No newline at end of file
diff --git a/Project/MathExprParser.cpp b/Project/MathExprParser.cpp
new file mode 100644
index 0000000..4d6e79a
--- /dev/null
+++ b/Project/MathExprParser.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
+ *
+ * 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 2 of the License, or
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "MathExprParser.h"
+
+MathExprParser::MathExprParser()
+{
+ AddConstant("pi", 3.14159265358979323846);
+ AddConstant("e", 2.71828182845904523536);
+}
+
+MathExprParser::~MathExprParser() {}
diff --git a/Project/MathExprParser.h b/Project/MathExprParser.h
new file mode 100644
index 0000000..b533b19
--- /dev/null
+++ b/Project/MathExprParser.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
+ *
+ * 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 2 of the License, or
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef MATHEXPRPARSER_H
+#define MATHEXPRPARSER_H
+
+#include "fparser/fparser.hh"
+
+class MathExprParser : public FunctionParser
+{
+ public:
+ MathExprParser();
+ ~MathExprParser();
+};
+
+#endif // MATHEXPRPARSER_H
diff --git a/Project/MathExpression.cpp b/Project/MathExpression.cpp
new file mode 100644
index 0000000..1cb6aba
--- /dev/null
+++ b/Project/MathExpression.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
+ *
+ * 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 2 of the License, or
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "MathExpression.h"
+#include "MathExpressionForm.h"
+
+MathExpression::MathExpression(int id) : ControlElement(id)
+{
+ m_variablesVector.push_back("x");
+ // m_variablesVector.push_back("y");
+
+ for(unsigned int i = 0; i < m_variablesVector.size(); ++i) {
+ m_glTextInputVector.push_back(new OpenGLText(m_variablesVector[i]));
+ }
+
+ // Symbol
+ m_symbol.SetFontSize(12);
+ m_symbol.SetFontWeight(wxFONTWEIGHT_BOLD);
+ m_symbol.SetFontStyle(wxFONTSTYLE_ITALIC);
+ m_symbol.SetFontFamily(wxFONTFAMILY_ROMAN);
+ m_symbol.SetText("f(x)");
+ m_symbolSize = wxSize(m_symbol.GetWidth(), m_symbol.GetHeight());
+
+ CalculateBlockSize(static_cast<double>(m_variablesVector.size()));
+
+ for(unsigned int i = 0; i < m_variablesVector.size(); ++i) {
+ wxPoint2DDouble nodePosition(0, 0);
+ if(m_variablesVector.size() == 1) {
+ nodePosition = m_position + wxPoint2DDouble(-m_width / 2, 0);
+ } else {
+ nodePosition = m_position + wxPoint2DDouble(-m_width / 2, 9 + 18 * i - m_height / 2);
+ }
+ Node* nodeIn = new Node(nodePosition, Node::NODE_IN, m_borderSize);
+ nodeIn->StartMove(m_position);
+ m_nodeList.push_back(nodeIn);
+ }
+ Node* nodeOut = new Node(m_position + wxPoint2DDouble(m_width / 2, 0), Node::NODE_OUT, m_borderSize);
+ nodeOut->SetAngle(180.0);
+ nodeOut->StartMove(m_position);
+ m_nodeList.push_back(nodeOut);
+
+ UpdatePoints();
+}
+
+MathExpression::~MathExpression()
+{
+ for(auto it = m_glTextInputVector.begin(), itEnd = m_glTextInputVector.end(); it != itEnd; ++it) { delete *it; }
+ m_glTextInputVector.clear();
+}
+
+void MathExpression::Draw(wxPoint2DDouble translation, double scale) const
+{
+ glLineWidth(1.0);
+ if(m_selected) {
+ glColor4dv(m_selectionColour.GetRGBA());
+ double borderSize = (m_borderSize * 2.0 + 1.0) / scale;
+ DrawRectangle(m_position, m_width + borderSize, m_height + borderSize);
+ }
+ glColor4d(1.0, 1.0, 1.0, 1.0);
+ DrawRectangle(m_position, m_width, m_height);
+ glColor4d(0.0, 0.0, 0.0, 1.0);
+ DrawRectangle(m_position, m_width, m_height, GL_LINE_LOOP);
+
+ // Plot input variables and symbol.
+ glColor4d(0.0, 0.3, 1.0, 1.0);
+ if(m_angle == 0.0) {
+ m_symbol.Draw(m_nodeList[m_nodeList.size() - 1]->GetPosition() -
+ wxPoint2DDouble(m_symbolSize.GetWidth() / 2.0 + 6.0, 0));
+ glColor4d(0.0, 0.0, 0.0, 1.0);
+ for(unsigned int i = 0; i < m_glTextInputVector.size(); ++i) {
+ m_glTextInputVector[i]->Draw(m_nodeList[i]->GetPosition() +
+ wxPoint2DDouble(m_glTextInputVector[i]->GetWidth() / 2.0 + 6, 0));
+ }
+ } else if(m_angle == 90.0) {
+ m_symbol.Draw(m_nodeList[m_nodeList.size() - 1]->GetPosition() -
+ wxPoint2DDouble(0, m_symbolSize.GetHeight() / 2.0 + 6.0));
+ glColor4d(0.0, 0.0, 0.0, 1.0);
+ for(unsigned int i = 0; i < m_glTextInputVector.size(); ++i) {
+ m_glTextInputVector[i]->Draw(
+ m_nodeList[i]->GetPosition() +
+ wxPoint2DDouble(m_glTextInputVector[i]->GetWidth() / 2.0 + m_glTextInputVector[i]->GetHeight() / 2,
+ 15),
+ 90);
+ }
+ } else if(m_angle == 180.0) {
+ m_symbol.Draw(m_nodeList[m_nodeList.size() - 1]->GetPosition() +
+ wxPoint2DDouble(m_symbolSize.GetWidth() / 2.0 + 6.0, 0));
+ glColor4d(0.0, 0.0, 0.0, 1.0);
+ for(unsigned int i = 0; i < m_glTextInputVector.size(); ++i) {
+ m_glTextInputVector[i]->Draw(m_nodeList[i]->GetPosition() -
+ wxPoint2DDouble(m_glTextInputVector[i]->GetWidth() / 2.0 + 6, 0));
+ }
+ } else if(m_angle == 270.0) {
+ m_symbol.Draw(m_nodeList[m_nodeList.size() - 1]->GetPosition() +
+ wxPoint2DDouble(0, m_symbolSize.GetHeight() / 2.0 + 6.0));
+ glColor4d(0.0, 0.0, 0.0, 1.0);
+ for(unsigned int i = 0; i < m_glTextInputVector.size(); ++i) {
+ m_glTextInputVector[i]->Draw(
+ m_nodeList[i]->GetPosition() + wxPoint2DDouble(m_glTextInputVector[i]->GetWidth() / 2.0 +
+ m_glTextInputVector[i]->GetHeight() / 2.0,
+ -m_glTextInputVector[i]->GetWidth()),
+ 90);
+ }
+ }
+
+ glColor4d(0.0, 0.0, 0.0, 1.0);
+ DrawNodes();
+}
+
+bool MathExpression::ShowForm(wxWindowMSW* parent, Element* element)
+{
+ MathExpressionForm* mathExprForm = new MathExpressionForm(parent, this);
+ if(mathExprForm->ShowModal() == wxID_OK) {
+ mathExprForm->Destroy();
+ return true;
+ }
+ mathExprForm->Destroy();
+ return false;
+}
+
+void MathExpression::Rotate(bool clockwise)
+{
+ if(clockwise)
+ m_angle += 90.0;
+ else
+ m_angle -= 90.0;
+ if(m_angle >= 360.0)
+ m_angle = 0.0;
+ else if(m_angle < 0)
+ m_angle = 270.0;
+
+ UpdatePoints();
+
+ for(auto it = m_nodeList.begin(), itEnd = m_nodeList.end(); it != itEnd; ++it) {
+ Node* node = *it;
+ node->Rotate(clockwise);
+ }
+}
+
+bool MathExpression::Solve(double input, double timeStep)
+{
+ // Solve the math expression using fparser
+ return true;
+}
+
+Element* MathExpression::GetCopy()
+{
+ MathExpression* copy = new MathExpression(m_elementID);
+ *copy = *this;
+ copy->m_glTextInputVector.clear();
+ for(auto it = m_glTextInputVector.begin(), itEnd = m_glTextInputVector.end(); it != itEnd; ++it) {
+ copy->m_glTextInputVector.push_back((*it)->GetCopy());
+ }
+ return copy;
+}
+
+void MathExpression::UpdatePoints()
+{
+ CalculateBlockSize(static_cast<double>(m_nodeList.size()) - 1.0);
+
+ if(m_nodeList.size() == 2) // Only one input (and the output).
+ {
+ if(m_angle == 0.0)
+ m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
+ else if(m_angle == 90.0)
+ m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
+ else if(m_angle == 180.0)
+ m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
+ else if(m_angle == 270.0)
+ m_nodeList[0]->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
+ } else {
+ for(unsigned int i = 0; i < m_nodeList.size() - 1; ++i) {
+ if(m_angle == 0.0)
+ m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 9 + 18 * i - m_height / 2));
+ else if(m_angle == 90.0)
+ m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(m_width / 2 - 9 - 18 * i, -m_height / 2));
+ else if(m_angle == 180.0)
+ m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, m_height / 2 - 9 - 18 * i));
+ else if(m_angle == 270.0)
+ m_nodeList[i]->SetPosition(m_position + wxPoint2DDouble(9 + 18 * i - m_width / 2, m_height / 2));
+ }
+ }
+ if(m_angle == 0.0)
+ m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(m_width / 2, 0));
+ else if(m_angle == 90.0)
+ m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(0, m_height / 2));
+ else if(m_angle == 180.0)
+ m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(-m_width / 2, 0));
+ else if(m_angle == 270.0)
+ m_nodeList[m_nodeList.size() - 1]->SetPosition(m_position + wxPoint2DDouble(0, -m_height / 2));
+
+ SetPosition(m_position); // Update rect.
+}
+
+void MathExpression::AddInNode()
+{
+ Node* newNode = new Node(wxPoint2DDouble(0, 0), Node::NODE_IN, m_borderSize);
+ newNode->SetAngle(m_angle);
+ m_nodeList.insert(m_nodeList.end() - 1, newNode);
+}
+
+void MathExpression::RemoveInNode()
+{
+ Node* nodeToRemove = *(m_nodeList.end() - 2);
+ bool foundChild = false;
+ for(auto it = m_childList.begin(), itEnd = m_childList.end(); it != itEnd; ++it) {
+ ControlElement* child = static_cast<ControlElement*>(*it);
+ auto childNodeList = child->GetNodeList();
+ for(auto itN = childNodeList.begin(), itEndN = childNodeList.end(); itN != itEndN; ++itN) {
+ Node* node = *itN;
+ if(node == nodeToRemove) {
+ child->RemoveParent(this);
+ RemoveChild(child);
+ foundChild = true;
+ break;
+ }
+ }
+ if(foundChild) break;
+ }
+ m_nodeList.erase(m_nodeList.end() - 2);
+}
+
+void MathExpression::CalculateBlockSize(double numInNodes)
+{
+ m_maxSringSize = 0;
+ for(auto it = m_glTextInputVector.begin(), itEnd = m_glTextInputVector.end(); it != itEnd; ++it) {
+ if(m_maxSringSize < (*it)->GetWidth()) m_maxSringSize = (*it)->GetWidth();
+ }
+ if(m_angle == 0.0 || m_angle == 180.0) {
+ m_height = 18.0 * numInNodes;
+ if(m_height < m_minimumSize) m_height = m_minimumSize; // minimum height
+ m_width = m_maxSringSize + m_symbolSize.GetWidth() + 18;
+ } else {
+ m_width = 18.0 * numInNodes;
+ if(m_width < m_minimumSize) m_width = m_minimumSize; // minimum width
+ m_height = m_maxSringSize + m_symbolSize.GetHeight() + 18;
+ }
+}
diff --git a/Project/MathExpression.h b/Project/MathExpression.h
new file mode 100644
index 0000000..ce39aca
--- /dev/null
+++ b/Project/MathExpression.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
+ *
+ * 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 2 of the License, or
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef MATHEXPRESSION_H
+#define MATHEXPRESSION_H
+
+#include "ControlElement.h"
+#include "MathExprParser.h"
+#include "OpenGLText.h"
+
+class MathExpressionForm;
+
+/**
+ * @class MathExpression
+ * @author Thales Lima Oliveira <thales@ufu.br>
+ * @date 19/12/2017
+ * @brief A generic math expression block that can perform math and conditional operations with the inputs.
+ * @file MathExpression.h
+ */
+class MathExpression : public ControlElement
+{
+ public:
+ MathExpression(int id);
+ ~MathExpression();
+
+ virtual void Draw(wxPoint2DDouble translation, double scale) const;
+ virtual bool Contains(wxPoint2DDouble position) const { return m_rect.Contains(position); }
+ virtual bool Intersects(wxRect2DDouble rect) const { return m_rect.Intersects(rect); }
+ virtual bool ShowForm(wxWindow* parent, Element* element);
+ virtual void Rotate(bool clockwise = true);
+
+ virtual bool Solve(double input, double timeStep);
+
+ virtual void UpdatePoints();
+ void AddInNode();
+ void RemoveInNode();
+
+ virtual Element* GetCopy();
+
+ protected:
+ void CalculateBlockSize(double numInNodes);
+
+ MathExprParser m_fparser;
+ wxString m_mathExpression = "sqrt(x^2 + y^2)";
+ wxString m_variables = "x,y";
+ std::vector<wxString> m_variablesVector;
+ std::vector<OpenGLText*> m_glTextInputVector;
+ OpenGLText m_symbol;
+ wxSize m_symbolSize;
+ int m_maxSringSize = 0;
+ double m_minimumSize = 36.0;
+};
+
+#endif // MATHEXPRESSION_H
diff --git a/Project/MathExpressionForm.cpp b/Project/MathExpressionForm.cpp
new file mode 100644
index 0000000..f4214c6
--- /dev/null
+++ b/Project/MathExpressionForm.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
+ *
+ * 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 2 of the License, or
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "MathExpressionForm.h"
+
+#define ERROR_INDICATOR 10
+
+MathExpressionForm::MathExpressionForm(wxWindow* parent, MathExpression* mathEpr) : MathExpressionFormBase(parent)
+{
+ m_parent = parent;
+ m_mathEpr = mathEpr;
+
+ m_staticTextCheckStatus->SetLabel(_("No checks performed."));
+ SetSintaxHighlights();
+ m_stcMathExpr->SetTabWidth(3);
+ m_stcMathExpr->IndicatorSetUnder(ERROR_INDICATOR, true);
+ m_stcMathExpr->IndicatorSetStyle(ERROR_INDICATOR, wxSTC_INDIC_ROUNDBOX);
+ m_stcMathExpr->IndicatorSetAlpha(ERROR_INDICATOR, 200);
+ m_stcMathExpr->IndicatorSetUnder(ERROR_INDICATOR, true);
+ m_stcMathExpr->IndicatorSetForeground(ERROR_INDICATOR, wxColor(255, 85, 0));
+ m_stcMathExpr->SetIndicatorCurrent(ERROR_INDICATOR);
+ m_stcMathExpr->SetText("a := 0.98 * x;\nb := int(a) + e^y;\nsqrt(1 - sin(2.2 * a) + cos(pi / b) / 3.3)");
+
+ m_translatedErrorMsg.clear();
+ m_translatedErrorMsg.push_back(_("Syntax error"));
+ m_translatedErrorMsg.push_back(_("Mismatched parenthesis"));
+ m_translatedErrorMsg.push_back(_("Missing ')'"));
+ m_translatedErrorMsg.push_back(_("Empty parentheses"));
+ m_translatedErrorMsg.push_back(_("Syntax error: Operator expected"));
+ m_translatedErrorMsg.push_back(_("Not enough memory"));
+ m_translatedErrorMsg.push_back(_("An unexpected error occurred"));
+ m_translatedErrorMsg.push_back(_("Syntax error in input variables"));
+ m_translatedErrorMsg.push_back(_("Illegal number of parameters to function"));
+ m_translatedErrorMsg.push_back(_("Syntax error: Expecting ( after function"));
+ m_translatedErrorMsg.push_back(_("Syntax error: Unknown identifier"));
+ m_translatedErrorMsg.push_back(_("No function has been parsed yet"));
+}
+
+MathExpressionForm::~MathExpressionForm() {}
+
+void MathExpressionForm::OnCheckButtonClick(wxCommandEvent& event)
+{
+ m_stcMathExpr->IndicatorClearRange(0, m_stcMathExpr->GetValue().length());
+ int currentLang = wxLocale::GetSystemLanguage();
+ wxLocale newLocale(wxLANGUAGE_ENGLISH_US);
+ MathExprParser parser;
+ int parserRes = parser.Parse(static_cast<std::string>(m_stcMathExpr->GetValue()), GetVariablesToParse());
+ if(parserRes != -1) {
+ m_staticTextCheckStatus->SetLabel(m_translatedErrorMsg[parser.GetParseErrorType()]);
+ m_staticTextCheckStatus->SetForegroundColour(wxColor(255, 0, 0));
+ m_stcMathExpr->IndicatorFillRange(parserRes, 1);
+ } else {
+ m_staticTextCheckStatus->SetLabel(_("OK!"));
+ m_staticTextCheckStatus->SetForegroundColour(wxColor(0, 128, 0));
+ }
+ Layout();
+ wxLocale oldLocale(currentLang);
+}
+
+void MathExpressionForm::OnOKButtonClick(wxCommandEvent& event)
+{
+ if(ValidateData()) EndModal(wxID_OK);
+}
+
+bool MathExpressionForm::ValidateData() { return true; }
+
+void MathExpressionForm::SetSintaxHighlights()
+{
+ wxString variables = m_textCtrlVariables->GetValue();
+
+ m_stcMathExpr->StyleClearAll();
+ m_stcMathExpr->SetLexer(wxSTC_LEX_DMAP);
+ m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_OPERATOR, wxColour(180, 0, 255));
+ m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_WORD, wxColour(10, 0, 255));
+ m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_WORD2, wxColour(160, 0, 0));
+ // m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_WORD3, wxColour(0, 150, 0));
+ m_stcMathExpr->StyleSetForeground(wxSTC_DMAP_NUMBER, wxColour(0, 150, 0));
+
+ m_stcMathExpr->StyleSetBold(wxSTC_DMAP_WORD, true);
+ m_stcMathExpr->StyleSetBold(wxSTC_DMAP_WORD2, true);
+ m_stcMathExpr->StyleSetBold(wxSTC_DMAP_WORD3, true);
+
+ m_stcMathExpr->SetKeyWords(
+ 0, wxT("abs acos acosh arg asin asinh atan atan2 atanh cbrt conj ceil cos cosh cot csc eval exp exp2 floor "
+ "hypot if imag int log log2 log10 max min polar pow real sec sin sinh sqrt tan tanh trunc"));
+ m_stcMathExpr->SetKeyWords(1, wxT("time step ") + variables);
+ m_stcMathExpr->SetKeyWords(2, wxT("pi e"));
+}
+
+void MathExpressionForm::OnTextUpdate(wxCommandEvent& event) { SetSintaxHighlights(); }
+
+std::string MathExpressionForm::GetVariablesToParse()
+{
+ wxString variables = wxT("time,step,") + m_textCtrlVariables->GetValue();
+ for(unsigned int i = 0; i < variables.length(); ++i) {
+ if(variables[i] == ' ') variables[i] = ',';
+ }
+ return static_cast<std::string>(variables);
+}
+
+void MathExpressionForm::OnLeftClickDown(wxMouseEvent& event)
+{
+ m_stcMathExpr->IndicatorClearRange(0, m_stcMathExpr->GetValue().length());
+ event.Skip();
+}
diff --git a/Project/MathExpressionForm.h b/Project/MathExpressionForm.h
new file mode 100644
index 0000000..03fb134
--- /dev/null
+++ b/Project/MathExpressionForm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
+ *
+ * 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 2 of the License, or
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef MATHEXPRESSIONFORM_H
+#define MATHEXPRESSIONFORM_H
+
+#include "base/ElementFormBase.h"
+#include "MathExprParser.h"
+#include <wx/msgdlg.h>
+
+class MathExpression;
+
+class MathExpressionForm : public MathExpressionFormBase
+{
+public:
+ MathExpressionForm(wxWindow* parent, MathExpression* mathEpr);
+ virtual ~MathExpressionForm();
+protected:
+ bool ValidateData();
+ void SetSintaxHighlights();
+ std::string GetVariablesToParse();
+ virtual void OnCancelButtonClick(wxCommandEvent& event) { EndModal(wxID_CANCEL); }
+ virtual void OnCheckButtonClick(wxCommandEvent& event);
+ virtual void OnOKButtonClick(wxCommandEvent& event);
+ virtual void OnTextEnter(wxCommandEvent& event) {}
+ virtual void OnTextUpdate(wxCommandEvent& event);
+ virtual void OnLeftClickDown(wxMouseEvent& event);
+
+ std::vector<wxString> m_translatedErrorMsg;
+
+ wxWindow* m_parent;
+ MathExpression* m_mathEpr;
+};
+#endif // MATHEXPRESSIONFORM_H
diff --git a/Project/OpenGLText.cpp b/Project/OpenGLText.cpp
index e71578a..5e1c40b 100644
--- a/Project/OpenGLText.cpp
+++ b/Project/OpenGLText.cpp
@@ -15,8 +15,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include "OpenGLText.h"
#include <wx/log.h>
+#include "OpenGLText.h"
OpenGLText::OpenGLText() { Init(); }
OpenGLText::OpenGLText(wxString text)
@@ -27,9 +27,7 @@ OpenGLText::OpenGLText(wxString text)
OpenGLText::~OpenGLText()
{
- if(m_textureID) {
- glDeleteTextures(1, &m_textureID[0]);
- }
+ if(m_textureID) { glDeleteTextures(1, &m_textureID[0]); }
}
void OpenGLText::Init()
@@ -39,12 +37,13 @@ void OpenGLText::Init()
m_textCoord[1] = wxPoint2DDouble(1, 0);
}
-void OpenGLText::Draw(wxPoint2DDouble position) const
+void OpenGLText::Draw(wxPoint2DDouble position, double angle) const
{
if(m_textureID) {
glPushMatrix();
-
+
glTranslated(position.m_x - m_bitmapSize.GetWidth() / 2, position.m_y - m_bitmapSize.GetHeight() / 2, 0);
+ glRotated(angle, 0, 0, 1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureID[0]);
@@ -87,7 +86,7 @@ int OpenGLText::RoundToPowerOfTwo(int value, int min)
void OpenGLText::TextToBitmap()
{
- wxFont font = wxFont(m_fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+ wxFont font = wxFont(m_fontSize, m_fontFamily, m_fontStyle, m_fontWeight);
wxMemoryDC memDC;
memDC.SetFont(font);
diff --git a/Project/OpenGLText.h b/Project/OpenGLText.h
index 08da8f1..5417ad3 100644
--- a/Project/OpenGLText.h
+++ b/Project/OpenGLText.h
@@ -35,14 +35,19 @@ class OpenGLText
OpenGLText(wxString text);
virtual ~OpenGLText();
- virtual void Draw(wxPoint2DDouble position) const;
+ virtual void Draw(wxPoint2DDouble position, double angle = 0.0) const;
virtual OpenGLText* GetCopy();
virtual void SetText(wxString text);
virtual wxString GetText() const { return m_text; }
virtual int GetWidth() const { return m_bitmapSize.GetWidth(); }
virtual int GetHeight() const { return m_bitmapSize.GetHeight(); }
+ virtual void SetFontSize(int fontSize) { m_fontSize = fontSize; }
+ virtual void SetFontWeight(wxFontWeight fontWeight) { m_fontWeight = fontWeight; }
+ virtual void SetFontStyle(wxFontStyle fontStyle) { m_fontStyle = fontStyle; }
+ virtual void SetFontFamily(wxFontFamily fontFamily) { m_fontFamily = fontFamily; }
virtual bool IsTextureOK();
+
protected:
void Init();
int RoundToPowerOfTwo(int value, int min = 32);
@@ -51,6 +56,9 @@ class OpenGLText
wxString m_text = _("Text");
int m_fontSize = 10;
+ wxFontWeight m_fontWeight = wxFONTWEIGHT_NORMAL;
+ wxFontStyle m_fontStyle = wxFONTSTYLE_NORMAL;
+ wxFontFamily m_fontFamily = wxFONTFAMILY_DEFAULT;
wxBitmap m_bitmap = wxNullBitmap;
wxSize m_bitmapSize = wxSize(0, 0);
diff --git a/Project/Project.mk b/Project/Project.mk
index 41dead0..f1c4b64 100644
--- a/Project/Project.mk
+++ b/Project/Project.mk
@@ -13,7 +13,7 @@ CurrentFileName :=
CurrentFilePath :=
CurrentFileFullPath :=
User :=NDSE-69
-Date :=09/11/2017
+Date :=19/12/2017
CodeLitePath :="C:/Program Files/CodeLite"
LinkerName :=C:/TDM-GCC-64/bin/g++.exe
SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC
@@ -66,15 +66,16 @@ WXWIN:=C:\wxWidgets-3.1.0
WXCFG:=gcc_dll\mswu
Objects0=$(IntermediateDirectory)/main.cpp$(ObjectSuffix) $(IntermediateDirectory)/win_resources.rc$(ObjectSuffix) $(IntermediateDirectory)/PropertiesData.cpp$(ObjectSuffix) $(IntermediateDirectory)/OpenGLText.cpp$(ObjectSuffix) $(IntermediateDirectory)/BusFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_ChartViewBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_ControlEditorBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_DataReportBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_ElementFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_MainFrameBitmaps.cpp$(ObjectSuffix) \
$(IntermediateDirectory)/base_PropertiesFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_WorkspaceBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_ChartViewBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_ControlEditorBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_DataReportBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_ElementFormBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_MainFrameBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_PropertiesFormBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/base_WorkspaceBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElectricCalculation.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/PowerFlow.cpp$(ObjectSuffix) $(IntermediateDirectory)/Fault.cpp$(ObjectSuffix) $(IntermediateDirectory)/Electromechanical.cpp$(ObjectSuffix) $(IntermediateDirectory)/Element.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementDataObject.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementPlotData.cpp$(ObjectSuffix) $(IntermediateDirectory)/wxMathPlot_mathplot.cpp$(ObjectSuffix) $(IntermediateDirectory)/artProvider_ArtMetro.cpp$(ObjectSuffix) $(IntermediateDirectory)/Camera.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrame.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/Workspace.cpp$(ObjectSuffix) $(IntermediateDirectory)/ChartView.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlEditor.cpp$(ObjectSuffix) $(IntermediateDirectory)/DataReport.cpp$(ObjectSuffix) $(IntermediateDirectory)/FileHanding.cpp$(ObjectSuffix) $(IntermediateDirectory)/ConnectionLine.cpp$(ObjectSuffix) $(IntermediateDirectory)/Constant.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlElement.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlElementContainer.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlElementSolver.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/Exponential.cpp$(ObjectSuffix) $(IntermediateDirectory)/Gain.cpp$(ObjectSuffix) $(IntermediateDirectory)/IOControl.cpp$(ObjectSuffix) $(IntermediateDirectory)/Limiter.cpp$(ObjectSuffix) $(IntermediateDirectory)/Multiplier.cpp$(ObjectSuffix) $(IntermediateDirectory)/RateLimiter.cpp$(ObjectSuffix) $(IntermediateDirectory)/Sum.cpp$(ObjectSuffix) $(IntermediateDirectory)/TransferFunction.cpp$(ObjectSuffix) $(IntermediateDirectory)/Divider.cpp$(ObjectSuffix) $(IntermediateDirectory)/MathOperation.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/GraphicalElement.cpp$(ObjectSuffix) $(IntermediateDirectory)/Text.cpp$(ObjectSuffix) $(IntermediateDirectory)/Branch.cpp$(ObjectSuffix) $(IntermediateDirectory)/Bus.cpp$(ObjectSuffix) $(IntermediateDirectory)/Capacitor.cpp$(ObjectSuffix) $(IntermediateDirectory)/IndMotor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Inductor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Line.cpp$(ObjectSuffix) $(IntermediateDirectory)/Load.cpp$(ObjectSuffix) $(IntermediateDirectory)/Machines.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/PowerElement.cpp$(ObjectSuffix) $(IntermediateDirectory)/Shunt.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncGenerator.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMotor.cpp$(ObjectSuffix)
+ $(IntermediateDirectory)/PowerFlow.cpp$(ObjectSuffix) $(IntermediateDirectory)/Fault.cpp$(ObjectSuffix) $(IntermediateDirectory)/Electromechanical.cpp$(ObjectSuffix) $(IntermediateDirectory)/Element.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementDataObject.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementPlotData.cpp$(ObjectSuffix) $(IntermediateDirectory)/MathExprParser.cpp$(ObjectSuffix) $(IntermediateDirectory)/fparser_fparser.cc$(ObjectSuffix) $(IntermediateDirectory)/fparser_fpoptimizer.cc$(ObjectSuffix) $(IntermediateDirectory)/wxMathPlot_mathplot.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/artProvider_ArtMetro.cpp$(ObjectSuffix) $(IntermediateDirectory)/Camera.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrame.cpp$(ObjectSuffix) $(IntermediateDirectory)/Workspace.cpp$(ObjectSuffix) $(IntermediateDirectory)/ChartView.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlEditor.cpp$(ObjectSuffix) $(IntermediateDirectory)/DataReport.cpp$(ObjectSuffix) $(IntermediateDirectory)/FileHanding.cpp$(ObjectSuffix) $(IntermediateDirectory)/ConnectionLine.cpp$(ObjectSuffix) $(IntermediateDirectory)/Constant.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/ControlElement.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlElementContainer.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlElementSolver.cpp$(ObjectSuffix) $(IntermediateDirectory)/Exponential.cpp$(ObjectSuffix) $(IntermediateDirectory)/Gain.cpp$(ObjectSuffix) $(IntermediateDirectory)/IOControl.cpp$(ObjectSuffix) $(IntermediateDirectory)/Limiter.cpp$(ObjectSuffix) $(IntermediateDirectory)/Multiplier.cpp$(ObjectSuffix) $(IntermediateDirectory)/RateLimiter.cpp$(ObjectSuffix) $(IntermediateDirectory)/Sum.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/TransferFunction.cpp$(ObjectSuffix) $(IntermediateDirectory)/Divider.cpp$(ObjectSuffix) $(IntermediateDirectory)/MathOperation.cpp$(ObjectSuffix) $(IntermediateDirectory)/MathExpression.cpp$(ObjectSuffix) $(IntermediateDirectory)/GraphicalElement.cpp$(ObjectSuffix) $(IntermediateDirectory)/Text.cpp$(ObjectSuffix) $(IntermediateDirectory)/Branch.cpp$(ObjectSuffix) $(IntermediateDirectory)/Bus.cpp$(ObjectSuffix) $(IntermediateDirectory)/Capacitor.cpp$(ObjectSuffix) $(IntermediateDirectory)/IndMotor.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/Inductor.cpp$(ObjectSuffix)
-Objects1=$(IntermediateDirectory)/Transformer.cpp$(ObjectSuffix) $(IntermediateDirectory)/GeneralPropertiesForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SimulationsSettingsForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/AboutForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ConstantForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlSystemTest.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/ExponentialForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/GainForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/IOControlForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LimiterForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/RateLimiterForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SumForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TransferFunctionForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TextForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/BusForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/GeneratorStabForm.cpp$(ObjectSuffix) \
- $(IntermediateDirectory)/IndMotorForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LoadForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ReactiveShuntElementForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SwitchingForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMachineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TransformerForm.cpp$(ObjectSuffix)
+Objects1=$(IntermediateDirectory)/Line.cpp$(ObjectSuffix) $(IntermediateDirectory)/Load.cpp$(ObjectSuffix) $(IntermediateDirectory)/Machines.cpp$(ObjectSuffix) $(IntermediateDirectory)/PowerElement.cpp$(ObjectSuffix) $(IntermediateDirectory)/Shunt.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncGenerator.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMotor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Transformer.cpp$(ObjectSuffix) $(IntermediateDirectory)/GeneralPropertiesForm.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/SimulationsSettingsForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/AboutForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ConstantForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ControlSystemTest.cpp$(ObjectSuffix) $(IntermediateDirectory)/ExponentialForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/GainForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/IOControlForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LimiterForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/RateLimiterForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SumForm.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/TransferFunctionForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/MathExpressionForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TextForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/BusForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/GeneratorStabForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/IndMotorForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LoadForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ReactiveShuntElementForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SwitchingForm.cpp$(ObjectSuffix) \
+ $(IntermediateDirectory)/SyncMachineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TransformerForm.cpp$(ObjectSuffix)
@@ -308,6 +309,30 @@ $(IntermediateDirectory)/ElementPlotData.cpp$(DependSuffix): ElementPlotData.cpp
$(IntermediateDirectory)/ElementPlotData.cpp$(PreprocessSuffix): ElementPlotData.cpp
$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/ElementPlotData.cpp$(PreprocessSuffix) ElementPlotData.cpp
+$(IntermediateDirectory)/MathExprParser.cpp$(ObjectSuffix): MathExprParser.cpp $(IntermediateDirectory)/MathExprParser.cpp$(DependSuffix)
+ $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/MathExprParser.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/MathExprParser.cpp$(ObjectSuffix) $(IncludePath)
+$(IntermediateDirectory)/MathExprParser.cpp$(DependSuffix): MathExprParser.cpp
+ @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/MathExprParser.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/MathExprParser.cpp$(DependSuffix) -MM MathExprParser.cpp
+
+$(IntermediateDirectory)/MathExprParser.cpp$(PreprocessSuffix): MathExprParser.cpp
+ $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/MathExprParser.cpp$(PreprocessSuffix) MathExprParser.cpp
+
+$(IntermediateDirectory)/fparser_fparser.cc$(ObjectSuffix): fparser/fparser.cc $(IntermediateDirectory)/fparser_fparser.cc$(DependSuffix)
+ $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/fparser/fparser.cc" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/fparser_fparser.cc$(ObjectSuffix) $(IncludePath)
+$(IntermediateDirectory)/fparser_fparser.cc$(DependSuffix): fparser/fparser.cc
+ @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/fparser_fparser.cc$(ObjectSuffix) -MF$(IntermediateDirectory)/fparser_fparser.cc$(DependSuffix) -MM fparser/fparser.cc
+
+$(IntermediateDirectory)/fparser_fparser.cc$(PreprocessSuffix): fparser/fparser.cc
+ $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/fparser_fparser.cc$(PreprocessSuffix) fparser/fparser.cc
+
+$(IntermediateDirectory)/fparser_fpoptimizer.cc$(ObjectSuffix): fparser/fpoptimizer.cc $(IntermediateDirectory)/fparser_fpoptimizer.cc$(DependSuffix)
+ $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/fparser/fpoptimizer.cc" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/fparser_fpoptimizer.cc$(ObjectSuffix) $(IncludePath)
+$(IntermediateDirectory)/fparser_fpoptimizer.cc$(DependSuffix): fparser/fpoptimizer.cc
+ @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/fparser_fpoptimizer.cc$(ObjectSuffix) -MF$(IntermediateDirectory)/fparser_fpoptimizer.cc$(DependSuffix) -MM fparser/fpoptimizer.cc
+
+$(IntermediateDirectory)/fparser_fpoptimizer.cc$(PreprocessSuffix): fparser/fpoptimizer.cc
+ $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/fparser_fpoptimizer.cc$(PreprocessSuffix) fparser/fpoptimizer.cc
+
$(IntermediateDirectory)/wxMathPlot_mathplot.cpp$(ObjectSuffix): wxMathPlot/mathplot.cpp $(IntermediateDirectory)/wxMathPlot_mathplot.cpp$(DependSuffix)
$(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/wxMathPlot/mathplot.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/wxMathPlot_mathplot.cpp$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/wxMathPlot_mathplot.cpp$(DependSuffix): wxMathPlot/mathplot.cpp
@@ -500,6 +525,14 @@ $(IntermediateDirectory)/MathOperation.cpp$(DependSuffix): MathOperation.cpp
$(IntermediateDirectory)/MathOperation.cpp$(PreprocessSuffix): MathOperation.cpp
$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/MathOperation.cpp$(PreprocessSuffix) MathOperation.cpp
+$(IntermediateDirectory)/MathExpression.cpp$(ObjectSuffix): MathExpression.cpp $(IntermediateDirectory)/MathExpression.cpp$(DependSuffix)
+ $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/MathExpression.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/MathExpression.cpp$(ObjectSuffix) $(IncludePath)
+$(IntermediateDirectory)/MathExpression.cpp$(DependSuffix): MathExpression.cpp
+ @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/MathExpression.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/MathExpression.cpp$(DependSuffix) -MM MathExpression.cpp
+
+$(IntermediateDirectory)/MathExpression.cpp$(PreprocessSuffix): MathExpression.cpp
+ $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/MathExpression.cpp$(PreprocessSuffix) MathExpression.cpp
+
$(IntermediateDirectory)/GraphicalElement.cpp$(ObjectSuffix): GraphicalElement.cpp $(IntermediateDirectory)/GraphicalElement.cpp$(DependSuffix)
$(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/GraphicalElement.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/GraphicalElement.cpp$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/GraphicalElement.cpp$(DependSuffix): GraphicalElement.cpp
@@ -716,6 +749,14 @@ $(IntermediateDirectory)/TransferFunctionForm.cpp$(DependSuffix): TransferFuncti
$(IntermediateDirectory)/TransferFunctionForm.cpp$(PreprocessSuffix): TransferFunctionForm.cpp
$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/TransferFunctionForm.cpp$(PreprocessSuffix) TransferFunctionForm.cpp
+$(IntermediateDirectory)/MathExpressionForm.cpp$(ObjectSuffix): MathExpressionForm.cpp $(IntermediateDirectory)/MathExpressionForm.cpp$(DependSuffix)
+ $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/MathExpressionForm.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/MathExpressionForm.cpp$(ObjectSuffix) $(IncludePath)
+$(IntermediateDirectory)/MathExpressionForm.cpp$(DependSuffix): MathExpressionForm.cpp
+ @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/MathExpressionForm.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/MathExpressionForm.cpp$(DependSuffix) -MM MathExpressionForm.cpp
+
+$(IntermediateDirectory)/MathExpressionForm.cpp$(PreprocessSuffix): MathExpressionForm.cpp
+ $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/MathExpressionForm.cpp$(PreprocessSuffix) MathExpressionForm.cpp
+
$(IntermediateDirectory)/TextForm.cpp$(ObjectSuffix): TextForm.cpp $(IntermediateDirectory)/TextForm.cpp$(DependSuffix)
$(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/NDSE-69/Documents/GitHub/PSP/Project/TextForm.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/TextForm.cpp$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/TextForm.cpp$(DependSuffix): TextForm.cpp
diff --git a/Project/Project.project b/Project/Project.project
index c85466f..bbbcf04 100644
--- a/Project/Project.project
+++ b/Project/Project.project
@@ -36,6 +36,7 @@
<File Name="TransferFunction.cpp"/>
<File Name="Divider.cpp"/>
<File Name="MathOperation.cpp"/>
+ <File Name="MathExpression.cpp"/>
</VirtualDirectory>
<VirtualDirectory Name="graphical">
<File Name="GraphicalElement.cpp"/>
@@ -58,6 +59,11 @@
</VirtualDirectory>
</VirtualDirectory>
<File Name="PropertiesData.cpp"/>
+ <VirtualDirectory Name="fparser">
+ <File Name="MathExprParser.cpp"/>
+ <File Name="fparser/fparser.cc"/>
+ <File Name="fparser/fpoptimizer.cc"/>
+ </VirtualDirectory>
</VirtualDirectory>
<VirtualDirectory Name="view">
<VirtualDirectory Name="wxMathPlot">
@@ -85,6 +91,7 @@
<File Name="RateLimiterForm.cpp"/>
<File Name="SumForm.cpp"/>
<File Name="TransferFunctionForm.cpp"/>
+ <File Name="MathExpressionForm.cpp"/>
</VirtualDirectory>
<VirtualDirectory Name="graphical element">
<File Name="TextForm.cpp"/>
@@ -155,6 +162,7 @@
<File Name="TransferFunction.h"/>
<File Name="Divider.h"/>
<File Name="MathOperation.h"/>
+ <File Name="MathExpression.h"/>
</VirtualDirectory>
<VirtualDirectory Name="power">
<File Name="Branch.h"/>
@@ -172,6 +180,11 @@
<File Name="Transformer.h"/>
</VirtualDirectory>
</VirtualDirectory>
+ <VirtualDirectory Name="farser">
+ <File Name="MathExprParser.h"/>
+ <File Name="fparser/fparser.hh"/>
+ <File Name="fparser/fpconfig.hh"/>
+ </VirtualDirectory>
<File Name="PropertiesData.h"/>
</VirtualDirectory>
<VirtualDirectory Name="view">
@@ -198,6 +211,7 @@
<File Name="RateLimiterForm.h"/>
<File Name="SumForm.h"/>
<File Name="TransferFunctionForm.h"/>
+ <File Name="MathExpressionForm.h"/>
</VirtualDirectory>
<VirtualDirectory Name="graphical">
<File Name="TextForm.h"/>
@@ -446,7 +460,7 @@
<SearchPaths/>
</Completion>
</Configuration>
- <Configuration Name="Release_Windows_x32" CompilerType="MinGW ( TDM-GCC-32 )" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
+ <Configuration Name="Release_Windows_x32" CompilerType="MinGW ( TDM-GCC-481-32 )" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-O2;-Wall;$(shell wx-config --cflags);-std=gnu++11" C_Options="-O2;-Wall" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
<IncludePath Value="."/>
<Preprocessor Value="NDEBUG"/>
diff --git a/Project/Project.txt b/Project/Project.txt
index 0d5647a..5d444a1 100644
--- a/Project/Project.txt
+++ b/Project/Project.txt
@@ -1,2 +1,2 @@
-./Release_Windows_x64/main.cpp.o ./Release_Windows_x64/win_resources.rc.o ./Release_Windows_x64/PropertiesData.cpp.o ./Release_Windows_x64/OpenGLText.cpp.o ./Release_Windows_x64/BusFormBitmaps.cpp.o ./Release_Windows_x64/base_ChartViewBitmaps.cpp.o ./Release_Windows_x64/base_ControlEditorBitmaps.cpp.o ./Release_Windows_x64/base_DataReportBitmaps.cpp.o ./Release_Windows_x64/base_ElementFormBitmaps.cpp.o ./Release_Windows_x64/base_MainFrameBitmaps.cpp.o ./Release_Windows_x64/base_PropertiesFormBitmaps.cpp.o ./Release_Windows_x64/base_WorkspaceBitmaps.cpp.o ./Release_Windows_x64/base_ChartViewBase.cpp.o ./Release_Windows_x64/base_ControlEditorBase.cpp.o ./Release_Windows_x64/base_DataReportBase.cpp.o ./Release_Windows_x64/base_ElementFormBase.cpp.o ./Release_Windows_x64/base_MainFrameBase.cpp.o ./Release_Windows_x64/base_PropertiesFormBase.cpp.o ./Release_Windows_x64/base_WorkspaceBase.cpp.o ./Release_Windows_x64/ElectricCalculation.cpp.o ./Release_Windows_x64/PowerFlow.cpp.o ./Release_Windows_x64/Fault.cpp.o ./Release_Windows_x64/Electromechanical.cpp.o ./Release_Windows_x64/Element.cpp.o ./Release_Windows_x64/ElementDataObject.cpp.o ./Release_Windows_x64/ElementPlotData.cpp.o ./Release_Windows_x64/wxMathPlot_mathplot.cpp.o ./Release_Windows_x64/artProvider_ArtMetro.cpp.o ./Release_Windows_x64/Camera.cpp.o ./Release_Windows_x64/MainFrame.cpp.o ./Release_Windows_x64/Workspace.cpp.o ./Release_Windows_x64/ChartView.cpp.o ./Release_Windows_x64/ControlEditor.cpp.o ./Release_Windows_x64/DataReport.cpp.o ./Release_Windows_x64/FileHanding.cpp.o ./Release_Windows_x64/ConnectionLine.cpp.o ./Release_Windows_x64/Constant.cpp.o ./Release_Windows_x64/ControlElement.cpp.o ./Release_Windows_x64/ControlElementContainer.cpp.o ./Release_Windows_x64/ControlElementSolver.cpp.o ./Release_Windows_x64/Exponential.cpp.o ./Release_Windows_x64/Gain.cpp.o ./Release_Windows_x64/IOControl.cpp.o ./Release_Windows_x64/Limiter.cpp.o ./Release_Windows_x64/Multiplier.cpp.o ./Release_Windows_x64/RateLimiter.cpp.o ./Release_Windows_x64/Sum.cpp.o ./Release_Windows_x64/TransferFunction.cpp.o ./Release_Windows_x64/Divider.cpp.o ./Release_Windows_x64/MathOperation.cpp.o ./Release_Windows_x64/GraphicalElement.cpp.o ./Release_Windows_x64/Text.cpp.o ./Release_Windows_x64/Branch.cpp.o ./Release_Windows_x64/Bus.cpp.o ./Release_Windows_x64/Capacitor.cpp.o ./Release_Windows_x64/IndMotor.cpp.o ./Release_Windows_x64/Inductor.cpp.o ./Release_Windows_x64/Line.cpp.o ./Release_Windows_x64/Load.cpp.o ./Release_Windows_x64/Machines.cpp.o ./Release_Windows_x64/PowerElement.cpp.o ./Release_Windows_x64/Shunt.cpp.o ./Release_Windows_x64/SyncGenerator.cpp.o ./Release_Windows_x64/SyncMotor.cpp.o
-./Release_Windows_x64/Transformer.cpp.o ./Release_Windows_x64/GeneralPropertiesForm.cpp.o ./Release_Windows_x64/SimulationsSettingsForm.cpp.o ./Release_Windows_x64/AboutForm.cpp.o ./Release_Windows_x64/ConstantForm.cpp.o ./Release_Windows_x64/ControlSystemTest.cpp.o ./Release_Windows_x64/ExponentialForm.cpp.o ./Release_Windows_x64/GainForm.cpp.o ./Release_Windows_x64/IOControlForm.cpp.o ./Release_Windows_x64/LimiterForm.cpp.o ./Release_Windows_x64/RateLimiterForm.cpp.o ./Release_Windows_x64/SumForm.cpp.o ./Release_Windows_x64/TransferFunctionForm.cpp.o ./Release_Windows_x64/TextForm.cpp.o ./Release_Windows_x64/BusForm.cpp.o ./Release_Windows_x64/GeneratorStabForm.cpp.o ./Release_Windows_x64/IndMotorForm.cpp.o ./Release_Windows_x64/LineForm.cpp.o ./Release_Windows_x64/LoadForm.cpp.o ./Release_Windows_x64/ReactiveShuntElementForm.cpp.o ./Release_Windows_x64/SwitchingForm.cpp.o ./Release_Windows_x64/SyncMachineForm.cpp.o ./Release_Windows_x64/TransformerForm.cpp.o
+./Release_Windows_x64/main.cpp.o ./Release_Windows_x64/win_resources.rc.o ./Release_Windows_x64/PropertiesData.cpp.o ./Release_Windows_x64/OpenGLText.cpp.o ./Release_Windows_x64/BusFormBitmaps.cpp.o ./Release_Windows_x64/base_ChartViewBitmaps.cpp.o ./Release_Windows_x64/base_ControlEditorBitmaps.cpp.o ./Release_Windows_x64/base_DataReportBitmaps.cpp.o ./Release_Windows_x64/base_ElementFormBitmaps.cpp.o ./Release_Windows_x64/base_MainFrameBitmaps.cpp.o ./Release_Windows_x64/base_PropertiesFormBitmaps.cpp.o ./Release_Windows_x64/base_WorkspaceBitmaps.cpp.o ./Release_Windows_x64/base_ChartViewBase.cpp.o ./Release_Windows_x64/base_ControlEditorBase.cpp.o ./Release_Windows_x64/base_DataReportBase.cpp.o ./Release_Windows_x64/base_ElementFormBase.cpp.o ./Release_Windows_x64/base_MainFrameBase.cpp.o ./Release_Windows_x64/base_PropertiesFormBase.cpp.o ./Release_Windows_x64/base_WorkspaceBase.cpp.o ./Release_Windows_x64/ElectricCalculation.cpp.o ./Release_Windows_x64/PowerFlow.cpp.o ./Release_Windows_x64/Fault.cpp.o ./Release_Windows_x64/Electromechanical.cpp.o ./Release_Windows_x64/Element.cpp.o ./Release_Windows_x64/ElementDataObject.cpp.o ./Release_Windows_x64/ElementPlotData.cpp.o ./Release_Windows_x64/MathExprParser.cpp.o ./Release_Windows_x64/fparser_fparser.cc.o ./Release_Windows_x64/fparser_fpoptimizer.cc.o ./Release_Windows_x64/wxMathPlot_mathplot.cpp.o ./Release_Windows_x64/artProvider_ArtMetro.cpp.o ./Release_Windows_x64/Camera.cpp.o ./Release_Windows_x64/MainFrame.cpp.o ./Release_Windows_x64/Workspace.cpp.o ./Release_Windows_x64/ChartView.cpp.o ./Release_Windows_x64/ControlEditor.cpp.o ./Release_Windows_x64/DataReport.cpp.o ./Release_Windows_x64/FileHanding.cpp.o ./Release_Windows_x64/ConnectionLine.cpp.o ./Release_Windows_x64/Constant.cpp.o ./Release_Windows_x64/ControlElement.cpp.o ./Release_Windows_x64/ControlElementContainer.cpp.o ./Release_Windows_x64/ControlElementSolver.cpp.o ./Release_Windows_x64/Exponential.cpp.o ./Release_Windows_x64/Gain.cpp.o ./Release_Windows_x64/IOControl.cpp.o ./Release_Windows_x64/Limiter.cpp.o ./Release_Windows_x64/Multiplier.cpp.o ./Release_Windows_x64/RateLimiter.cpp.o ./Release_Windows_x64/Sum.cpp.o ./Release_Windows_x64/TransferFunction.cpp.o ./Release_Windows_x64/Divider.cpp.o ./Release_Windows_x64/MathOperation.cpp.o ./Release_Windows_x64/MathExpression.cpp.o ./Release_Windows_x64/GraphicalElement.cpp.o ./Release_Windows_x64/Text.cpp.o ./Release_Windows_x64/Branch.cpp.o ./Release_Windows_x64/Bus.cpp.o ./Release_Windows_x64/Capacitor.cpp.o ./Release_Windows_x64/IndMotor.cpp.o ./Release_Windows_x64/Inductor.cpp.o
+./Release_Windows_x64/Line.cpp.o ./Release_Windows_x64/Load.cpp.o ./Release_Windows_x64/Machines.cpp.o ./Release_Windows_x64/PowerElement.cpp.o ./Release_Windows_x64/Shunt.cpp.o ./Release_Windows_x64/SyncGenerator.cpp.o ./Release_Windows_x64/SyncMotor.cpp.o ./Release_Windows_x64/Transformer.cpp.o ./Release_Windows_x64/GeneralPropertiesForm.cpp.o ./Release_Windows_x64/SimulationsSettingsForm.cpp.o ./Release_Windows_x64/AboutForm.cpp.o ./Release_Windows_x64/ConstantForm.cpp.o ./Release_Windows_x64/ControlSystemTest.cpp.o ./Release_Windows_x64/ExponentialForm.cpp.o ./Release_Windows_x64/GainForm.cpp.o ./Release_Windows_x64/IOControlForm.cpp.o ./Release_Windows_x64/LimiterForm.cpp.o ./Release_Windows_x64/RateLimiterForm.cpp.o ./Release_Windows_x64/SumForm.cpp.o ./Release_Windows_x64/TransferFunctionForm.cpp.o ./Release_Windows_x64/MathExpressionForm.cpp.o ./Release_Windows_x64/TextForm.cpp.o ./Release_Windows_x64/BusForm.cpp.o ./Release_Windows_x64/GeneratorStabForm.cpp.o ./Release_Windows_x64/IndMotorForm.cpp.o ./Release_Windows_x64/LineForm.cpp.o ./Release_Windows_x64/LoadForm.cpp.o ./Release_Windows_x64/ReactiveShuntElementForm.cpp.o ./Release_Windows_x64/SwitchingForm.cpp.o ./Release_Windows_x64/SyncMachineForm.cpp.o ./Release_Windows_x64/TransformerForm.cpp.o
diff --git a/Project/Workspace.cpp b/Project/Workspace.cpp
index 485d350..9bd249b 100644
--- a/Project/Workspace.cpp
+++ b/Project/Workspace.cpp
@@ -743,9 +743,6 @@ void Workspace::OnKeyDown(wxKeyEvent& event)
Redraw();
}
// Tests - Ctrl + Shift + L
- if(event.ControlDown() && event.ShiftDown()) {
- // Nothing...
- }
} break;
case 'T': // Insert a transformer.
{
diff --git a/Project/base/ElementFormBase.cpp b/Project/base/ElementFormBase.cpp
index e1e953e..a42c34d 100644
--- a/Project/base/ElementFormBase.cpp
+++ b/Project/base/ElementFormBase.cpp
@@ -3729,3 +3729,160 @@ IOControlFormBase::~IOControlFormBase()
m_ButtonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(IOControlFormBase::OnCancelButtonClick), NULL, this);
}
+
+MathExpressionFormBase::MathExpressionFormBase(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
+ : wxDialog(parent, id, title, pos, size, style)
+{
+ if ( !bBitmapLoaded ) {
+ // We need to initialise the default bitmap handler
+ wxXmlResource::Get()->AddHandler(new wxBitmapXmlHandler);
+ wxC9EE9InitBitmapResources();
+ bBitmapLoaded = true;
+ }
+
+ wxBoxSizer* boxSizerLvl1_1 = new wxBoxSizer(wxVERTICAL);
+ this->SetSizer(boxSizerLvl1_1);
+
+ m_notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1,-1)), wxBK_DEFAULT);
+ m_notebook->SetName(wxT("m_notebook"));
+
+ boxSizerLvl1_1->Add(m_notebook, 1, wxEXPAND, WXC_FROM_DIP(5));
+
+ m_panelGeneral = new wxPanel(m_notebook, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(m_notebook, wxSize(-1,-1)), wxTAB_TRAVERSAL);
+ m_notebook->AddPage(m_panelGeneral, _("General"), false);
+
+ wxBoxSizer* boxSizerLvl2_1 = new wxBoxSizer(wxVERTICAL);
+ m_panelGeneral->SetSizer(boxSizerLvl2_1);
+
+ m_staticTextVariables = new wxStaticText(m_panelGeneral, wxID_ANY, _("Input variables (space separated)"), wxDefaultPosition, wxDLG_UNIT(m_panelGeneral, wxSize(-1,-1)), 0);
+
+ boxSizerLvl2_1->Add(m_staticTextVariables, 0, wxLEFT|wxRIGHT|wxTOP|wxALIGN_CENTER_VERTICAL, WXC_FROM_DIP(5));
+
+ m_textCtrlVariables = new wxTextCtrl(m_panelGeneral, wxID_ANY, wxT("x y"), wxDefaultPosition, wxDLG_UNIT(m_panelGeneral, wxSize(-1,-1)), 0);
+ #if wxVERSION_NUMBER >= 3000
+ m_textCtrlVariables->SetHint(wxT(""));
+ #endif
+
+ boxSizerLvl2_1->Add(m_textCtrlVariables, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND|wxALIGN_CENTER_VERTICAL, WXC_FROM_DIP(5));
+ m_textCtrlVariables->SetMinSize(wxSize(100,-1));
+
+ m_stcMathExpr = new wxStyledTextCtrl(m_panelGeneral, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(m_panelGeneral, wxSize(-1,-1)), 0);
+ wxFont m_stcMathExprFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Courier New"));
+ m_stcMathExpr->SetFont(m_stcMathExprFont);
+ // Configure the fold margin
+ m_stcMathExpr->SetMarginType (4, wxSTC_MARGIN_SYMBOL);
+ m_stcMathExpr->SetMarginMask (4, wxSTC_MASK_FOLDERS);
+ m_stcMathExpr->SetMarginSensitive(4, true);
+ m_stcMathExpr->SetMarginWidth (4, 16);
+
+ m_stcMathExpr->SetProperty(wxT("fold"),wxT("1"));
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_ARROWDOWN);
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDER, wxSTC_MARK_ARROW);
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_BACKGROUND);
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_BACKGROUND);
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_ARROW);
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_ARROWDOWN);
+ m_stcMathExpr->MarkerDefine(wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_BACKGROUND);
+ // Configure the tracker margin
+ m_stcMathExpr->SetMarginWidth(1, 0);
+
+ // Configure the symbol margin
+ m_stcMathExpr->SetMarginType (2, wxSTC_MARGIN_SYMBOL);
+ m_stcMathExpr->SetMarginMask (2, ~(wxSTC_MASK_FOLDERS));
+ m_stcMathExpr->SetMarginWidth(2, 0);
+ m_stcMathExpr->SetMarginSensitive(2, true);
+
+ // Configure the line numbers margin
+ m_stcMathExpr->SetMarginType(0, wxSTC_MARGIN_NUMBER);
+ m_stcMathExpr->SetMarginWidth(0,0);
+
+ // Configure the line symbol margin
+ m_stcMathExpr->SetMarginType(3, wxSTC_MARGIN_FORE);
+ m_stcMathExpr->SetMarginMask(3, 0);
+ m_stcMathExpr->SetMarginWidth(3,0);
+ // Select the lexer
+ m_stcMathExpr->SetLexer(wxSTC_LEX_PASCAL);
+ // Set default font / styles
+ m_stcMathExpr->StyleClearAll();
+ for(int i=0; i<wxSTC_STYLE_MAX; ++i) {
+ m_stcMathExpr->StyleSetFont(i, m_stcMathExprFont);
+ }
+ m_stcMathExpr->SetWrapMode(0);
+ m_stcMathExpr->SetIndentationGuides(0);
+ m_stcMathExpr->SetKeyWords(0, wxT(""));
+ m_stcMathExpr->SetKeyWords(1, wxT(""));
+ m_stcMathExpr->SetKeyWords(2, wxT(""));
+ m_stcMathExpr->SetKeyWords(3, wxT(""));
+ m_stcMathExpr->SetKeyWords(4, wxT(""));
+
+ boxSizerLvl2_1->Add(m_stcMathExpr, 0, wxALL, WXC_FROM_DIP(5));
+ m_stcMathExpr->SetMinSize(wxSize(400,200));
+
+ m_staticTextCheckStatus = new wxStaticText(this, wxID_ANY, _("No checks performed"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1,-1)), 0);
+
+ boxSizerLvl1_1->Add(m_staticTextCheckStatus, 0, wxLEFT|wxRIGHT|wxTOP|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, WXC_FROM_DIP(5));
+
+ wxBoxSizer* boxSizerBottomButtons = new wxBoxSizer(wxHORIZONTAL);
+
+ boxSizerLvl1_1->Add(boxSizerBottomButtons, 0, wxALL|wxEXPAND, WXC_FROM_DIP(5));
+
+ m_buttonCheck = new wxButton(this, wxID_ANY, _("Check expression"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1,-1)), 0);
+
+ boxSizerBottomButtons->Add(m_buttonCheck, 0, wxALL|wxALIGN_LEFT, WXC_FROM_DIP(5));
+
+ boxSizerBottomButtons->Add(0, 0, 1, wxALL, WXC_FROM_DIP(5));
+
+ m_buttonOK = new wxButton(this, wxID_ANY, _("OK"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1,-1)), 0);
+
+ boxSizerBottomButtons->Add(m_buttonOK, 0, wxALL|wxALIGN_RIGHT, WXC_FROM_DIP(5));
+
+ m_buttonCancel = new wxButton(this, wxID_ANY, _("Cancel"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1,-1)), 0);
+
+ boxSizerBottomButtons->Add(m_buttonCancel, 0, wxALL|wxALIGN_RIGHT, WXC_FROM_DIP(5));
+
+
+ #if wxVERSION_NUMBER >= 2900
+ if(!wxPersistenceManager::Get().Find(m_notebook)){
+ wxPersistenceManager::Get().RegisterAndRestore(m_notebook);
+ } else {
+ wxPersistenceManager::Get().Restore(m_notebook);
+ }
+ #endif
+
+ SetName(wxT("MathExpressionFormBase"));
+ SetSize(-1,-1);
+ if (GetSizer()) {
+ GetSizer()->Fit(this);
+ }
+ if(GetParent()) {
+ CentreOnParent(wxBOTH);
+ } else {
+ CentreOnScreen(wxBOTH);
+ }
+#if wxVERSION_NUMBER >= 2900
+ if(!wxPersistenceManager::Get().Find(this)) {
+ wxPersistenceManager::Get().RegisterAndRestore(this);
+ } else {
+ wxPersistenceManager::Get().Restore(this);
+ }
+#endif
+ // Connect events
+ m_textCtrlVariables->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(MathExpressionFormBase::OnTextUpdate), NULL, this);
+ m_textCtrlVariables->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(MathExpressionFormBase::OnTextEnter), NULL, this);
+ m_stcMathExpr->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(MathExpressionFormBase::OnLeftClickDown), NULL, this);
+ m_buttonCheck->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MathExpressionFormBase::OnCheckButtonClick), NULL, this);
+ m_buttonOK->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MathExpressionFormBase::OnOKButtonClick), NULL, this);
+ m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MathExpressionFormBase::OnCancelButtonClick), NULL, this);
+
+}
+
+MathExpressionFormBase::~MathExpressionFormBase()
+{
+ m_textCtrlVariables->Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(MathExpressionFormBase::OnTextUpdate), NULL, this);
+ m_textCtrlVariables->Disconnect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(MathExpressionFormBase::OnTextEnter), NULL, this);
+ m_stcMathExpr->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(MathExpressionFormBase::OnLeftClickDown), NULL, this);
+ m_buttonCheck->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MathExpressionFormBase::OnCheckButtonClick), NULL, this);
+ m_buttonOK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MathExpressionFormBase::OnOKButtonClick), NULL, this);
+ m_buttonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MathExpressionFormBase::OnCancelButtonClick), NULL, this);
+
+}
diff --git a/Project/base/ElementFormBase.h b/Project/base/ElementFormBase.h
index fc07150..0c1ac13 100644
--- a/Project/base/ElementFormBase.h
+++ b/Project/base/ElementFormBase.h
@@ -29,6 +29,7 @@
#include <wx/propgrid/property.h>
#include <wx/propgrid/advprops.h>
#include <wx/listctrl.h>
+#include <wx/stc/stc.h>
#if wxVERSION_NUMBER >= 2900
#include <wx/persist.h>
#include <wx/persist/toplevel.h>
@@ -1046,4 +1047,40 @@ public:
virtual ~IOControlFormBase();
};
+
+class MathExpressionFormBase : public wxDialog
+{
+protected:
+ wxNotebook* m_notebook;
+ wxPanel* m_panelGeneral;
+ wxStaticText* m_staticTextVariables;
+ wxTextCtrl* m_textCtrlVariables;
+ wxStyledTextCtrl* m_stcMathExpr;
+ wxStaticText* m_staticTextCheckStatus;
+ wxButton* m_buttonCheck;
+ wxButton* m_buttonOK;
+ wxButton* m_buttonCancel;
+
+protected:
+ virtual void OnTextUpdate(wxCommandEvent& event) { event.Skip(); }
+ virtual void OnTextEnter(wxCommandEvent& event) { event.Skip(); }
+ virtual void OnLeftClickDown(wxMouseEvent& event) { event.Skip(); }
+ virtual void OnCheckButtonClick(wxCommandEvent& event) { event.Skip(); }
+ virtual void OnOKButtonClick(wxCommandEvent& event) { event.Skip(); }
+ virtual void OnCancelButtonClick(wxCommandEvent& event) { event.Skip(); }
+
+public:
+ wxStaticText* GetStaticTextVariables() { return m_staticTextVariables; }
+ wxTextCtrl* GetTextCtrlVariables() { return m_textCtrlVariables; }
+ wxStyledTextCtrl* GetStcMathExpr() { return m_stcMathExpr; }
+ wxPanel* GetPanelGeneral() { return m_panelGeneral; }
+ wxNotebook* GetNotebook() { return m_notebook; }
+ wxStaticText* GetStaticTextCheckStatus() { return m_staticTextCheckStatus; }
+ wxButton* GetButtonCheck() { return m_buttonCheck; }
+ wxButton* GetButtonOK() { return m_buttonOK; }
+ wxButton* GetButtonCancel() { return m_buttonCancel; }
+ MathExpressionFormBase(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Math expression"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(-1,-1), long style = wxDEFAULT_DIALOG_STYLE);
+ virtual ~MathExpressionFormBase();
+};
+
#endif
diff --git a/Project/data/lang/pt_BR/pt_BR.mo b/Project/data/lang/pt_BR/pt_BR.mo
index d211a29..6bc34f7 100644
--- a/Project/data/lang/pt_BR/pt_BR.mo
+++ b/Project/data/lang/pt_BR/pt_BR.mo
Binary files differ
diff --git a/Project/data/lang/pt_BR/pt_BR.po b/Project/data/lang/pt_BR/pt_BR.po
index 9d1ea75..937c958 100644
--- a/Project/data/lang/pt_BR/pt_BR.po
+++ b/Project/data/lang/pt_BR/pt_BR.po
@@ -1,15 +1,15 @@
msgid ""
msgstr ""
"Project-Id-Version: PSP-UFU pt_BR 0.0.1\n"
-"POT-Creation-Date: 2017-11-08 19:33-0200\n"
-"PO-Revision-Date: 2017-11-08 19:42-0200\n"
+"POT-Creation-Date: 2017-12-19 10:56-0200\n"
+"PO-Revision-Date: 2017-12-19 10:57-0200\n"
"Last-Translator: \n"
"Language-Team: Thales Lima Oliveira <thaleslima.ufu@gmail.com>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.3\n"
+"X-Generator: Poedit 2.0.4\n"
"X-Poedit-Basepath: ../../..\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Poedit-KeywordsList: _\n"
@@ -285,11 +285,11 @@ msgstr "Cruz"
msgid "Driagonal cross"
msgstr "Cruz diagonal"
-#: ChartView.cpp:100 ChartView.cpp:520 ElementForm.cpp:236
+#: ChartView.cpp:100 ChartView.cpp:520 base/ElementFormBase.cpp:236
msgid "Time"
msgstr "Tempo"
-#: ChartView.cpp:107 ElementForm.h:143
+#: ChartView.cpp:107 base/ElementFormBase.h:144
msgid "Bus"
msgstr "Barra"
@@ -298,11 +298,11 @@ msgid "Induction motor"
msgstr "Motor de indução"
#: ChartView.cpp:109 DataReport.cpp:397 DataReport.cpp:408 DataReport.cpp:549
-#: DataReport.cpp:750 DataReport.cpp:788 ElementForm.h:448
+#: DataReport.cpp:750 DataReport.cpp:788 base/ElementFormBase.h:449
msgid "Line"
msgstr "Linha"
-#: ChartView.cpp:110 ElementForm.h:635
+#: ChartView.cpp:110 base/ElementFormBase.h:636
msgid "Load"
msgstr "Carga"
@@ -319,7 +319,7 @@ msgid "Synchronous generator"
msgstr "Gerador síncrono"
#: ChartView.cpp:115 DataReport.cpp:443 DataReport.cpp:454 DataReport.cpp:600
-#: DataReport.cpp:854 DataReport.cpp:892 ElementForm.h:547
+#: DataReport.cpp:854 DataReport.cpp:892 base/ElementFormBase.h:548
msgid "Transformer"
msgstr "Transformador"
@@ -327,29 +327,29 @@ msgstr "Transformador"
msgid "Test"
msgstr "Teste"
-#: ChartView.cpp:141 ChartViewBase.cpp:123
+#: ChartView.cpp:141 base/ChartViewBase.cpp:123
msgid "Draw"
msgstr "Plotar"
-#: ChartView.cpp:157 ChartViewBase.cpp:127
+#: ChartView.cpp:157 base/ChartViewBase.cpp:127
msgid "Thickness"
msgstr "Espessura"
-#: ChartView.cpp:159 ChartViewBase.cpp:133 DataReport.cpp:229
-#: DataReport.cpp:241 DataReport.cpp:251 DataReport.cpp:296
-#: ElementForm.cpp:2497 SwitchingForm.cpp:23 SwitchingForm.cpp:32
+#: ChartView.cpp:159 DataReport.cpp:229 DataReport.cpp:241 DataReport.cpp:251
+#: DataReport.cpp:296 SwitchingForm.cpp:23 SwitchingForm.cpp:32
+#: base/ChartViewBase.cpp:133 base/ElementFormBase.cpp:2497
msgid "Type"
msgstr "Tipo"
-#: ChartView.cpp:161 ChartViewBase.cpp:141
+#: ChartView.cpp:161 base/ChartViewBase.cpp:141
msgid "Axis"
msgstr "Eixo"
-#: ChartView.cpp:176 ChartViewBase.cpp:160
+#: ChartView.cpp:176 base/ChartViewBase.cpp:160
msgid "Margins"
msgstr "Margens"
-#: ChartView.cpp:181 ChartViewBase.cpp:175
+#: ChartView.cpp:181 base/ChartViewBase.cpp:175
msgid "Axis limit"
msgstr "Limites dos eixos"
@@ -375,9 +375,9 @@ msgstr "Não foi possível enviar para a área de transferência"
#: Element.cpp:297 Element.cpp:311 GeneralPropertiesForm.cpp:74 Line.cpp:168
#: Line.cpp:397 LoadForm.cpp:189 LoadForm.cpp:196 MainFrame.cpp:311
#: SimulationsSettingsForm.cpp:188 SimulationsSettingsForm.cpp:195
-#: SumForm.cpp:58 SumForm.cpp:74 TextForm.cpp:1225 Workspace.cpp:1146
-#: Workspace.cpp:1211 Workspace.cpp:1319 Workspace.cpp:1423 Workspace.cpp:1445
-#: Workspace.cpp:1463
+#: SumForm.cpp:58 SumForm.cpp:74 TextForm.cpp:1225 Workspace.cpp:1147
+#: Workspace.cpp:1212 Workspace.cpp:1320 Workspace.cpp:1424 Workspace.cpp:1446
+#: Workspace.cpp:1464
msgid "Error"
msgstr "Erro"
@@ -389,114 +389,6 @@ msgstr "Salvar arquivo CSV"
msgid "It was not possible to open or create the selected file."
msgstr "Não foi possível criar ou abrir o arquivo selecionado."
-#: ChartViewBase.cpp:64 MainFrameBase.cpp:72 MainFrameBase.cpp:73
-msgid "File"
-msgstr "Arquivo"
-
-#: ChartViewBase.cpp:66
-msgid "Save chart as image"
-msgstr "Salvar gráfico como imagem"
-
-#: ChartViewBase.cpp:69
-msgid "Send to clipboard"
-msgstr "Enviar para a área de transferência"
-
-#: ChartViewBase.cpp:72
-msgid "Export CSV..."
-msgstr "Exportar CSV..."
-
-#: ChartViewBase.cpp:77 MainFrameBase.cpp:88
-msgid "Exit"
-msgstr "Sair"
-
-#: ChartViewBase.cpp:81
-msgid "View"
-msgstr "Vizualização"
-
-#: ChartViewBase.cpp:83 MainFrameBase.cpp:146
-msgid "Fit"
-msgstr "Encaixar"
-
-#: ChartViewBase.cpp:88
-msgid "Show grid"
-msgstr "Exibir linhas de grade"
-
-#: ChartViewBase.cpp:91
-msgid "Show label"
-msgstr "Exibir legendas"
-
-#: ChartViewBase.cpp:94
-msgid "Show coordinates"
-msgstr "Exibir coordenadas"
-
-#: ChartViewBase.cpp:97
-msgid "Dark theme"
-msgstr "Tema escuro"
-
-#: ChartViewBase.cpp:120
-msgid "Line properties"
-msgstr "Propriedades do traço"
-
-#: ChartViewBase.cpp:139
-msgid "Y"
-msgstr "Y"
-
-#: ChartViewBase.cpp:140
-msgid "X"
-msgstr "X"
-
-#: ChartViewBase.cpp:145
-msgid "Chart properties"
-msgstr "Propriedades do gráfico"
-
-#: ChartViewBase.cpp:148
-msgid "Chart title"
-msgstr "Título do gráfico"
-
-#: ChartViewBase.cpp:152
-msgid "X axis label"
-msgstr "Rótulo do eixo X"
-
-#: ChartViewBase.cpp:156
-msgid "Y axis label"
-msgstr "Rótulo do eixo Y"
-
-#: ChartViewBase.cpp:163 ElementForm.cpp:2516
-msgid "Up"
-msgstr "Cima"
-
-#: ChartViewBase.cpp:166
-msgid "Botton"
-msgstr "Baixo"
-
-#: ChartViewBase.cpp:169
-msgid "Left"
-msgstr "Esquerda"
-
-#: ChartViewBase.cpp:172
-msgid "Right"
-msgstr "Direita"
-
-#: ChartViewBase.cpp:178
-msgid "X min"
-msgstr "X min"
-
-#: ChartViewBase.cpp:181
-msgid "X max"
-msgstr "X máx"
-
-#: ChartViewBase.cpp:184
-msgid "Y min"
-msgstr "Y min"
-
-#: ChartViewBase.cpp:187
-msgid "Y max"
-msgstr "Y máx"
-
-#: ChartViewBase.h:96
-msgid "Chart viewer"
-msgstr "Visualizador de gráficos"
-
#: ConstantForm.cpp:41
msgid "Value entered incorrectly in the field \"Constant value\"."
msgstr "Valor inserido incorretamente no campo \"Valor da constante\"."
@@ -509,23 +401,23 @@ msgstr "Entrada/Saída"
msgid "Transfer fcn"
msgstr "Func Transferência"
-#: ControlEditor.cpp:171 ElementForm.h:869
+#: ControlEditor.cpp:171 base/ElementFormBase.h:870
msgid "Sum"
msgstr "Somador"
-#: ControlEditor.cpp:177 ElementForm.h:987
+#: ControlEditor.cpp:177 base/ElementFormBase.h:988
msgid "Constant"
msgstr "Constante"
-#: ControlEditor.cpp:184 ElementForm.h:1013
+#: ControlEditor.cpp:184 base/ElementFormBase.h:1014
msgid "Gain"
msgstr "Ganho"
-#: ControlEditor.cpp:190 ElementForm.h:899
+#: ControlEditor.cpp:190 base/ElementFormBase.h:900
msgid "Limiter"
msgstr "Limitador"
-#: ControlEditor.cpp:197 ElementForm.h:929
+#: ControlEditor.cpp:197 base/ElementFormBase.h:930
msgid "Rate limiter"
msgstr "Limitador de taxa"
@@ -537,7 +429,7 @@ msgstr "Multiplicador"
msgid "Divider"
msgstr "Divisor"
-#: ControlEditor.cpp:217 ElementForm.h:961
+#: ControlEditor.cpp:217 base/ElementFormBase.h:962
msgid "Exponential"
msgstr "Exponencial"
@@ -561,11 +453,11 @@ msgstr "Inicializando..."
msgid "I/O"
msgstr "I/O"
-#: ControlEditor.cpp:870 ElementForm.cpp:3656
+#: ControlEditor.cpp:870 base/ElementFormBase.cpp:3656
msgid "Input"
msgstr "Entrada"
-#: ControlEditor.cpp:871 ElementForm.cpp:3666
+#: ControlEditor.cpp:871 base/ElementFormBase.cpp:3666
msgid "Output"
msgstr "Saída"
@@ -573,124 +465,6 @@ msgstr "Saída"
msgid "It was not possible to solve the control system"
msgstr "Não foi possível resolver o sistema de controle"
-#: ControlEditorBase.cpp:63 MainFrameBase.cpp:82
-msgid "New"
-msgstr "Novo"
-
-#: ControlEditorBase.cpp:65
-msgid "Import"
-msgstr "Importar"
-
-#: ControlEditorBase.cpp:67
-msgid "Export"
-msgstr "Exportar"
-
-#: ControlEditorBase.cpp:71 MainFrameBase.cpp:123
-msgid "Copy"
-msgstr "Copiar"
-
-#: ControlEditorBase.cpp:73 MainFrameBase.cpp:125
-msgid "Paste"
-msgstr "Colar"
-
-#: ControlEditorBase.cpp:75 MainFrameBase.cpp:127
-msgid "Undo"
-msgstr "Desfazer"
-
-#: ControlEditorBase.cpp:77 MainFrameBase.cpp:129
-msgid "Redo"
-msgstr "Refazer"
-
-#: ControlEditorBase.cpp:81 MainFrameBase.cpp:140
-msgid "Drag"
-msgstr "Arrastar"
-
-#: ControlEditorBase.cpp:83 MainFrameBase.cpp:142
-msgid "Move"
-msgstr "Mover"
-
-#: ControlEditorBase.cpp:85 Element.cpp:258 Line.cpp:304 MainFrameBase.cpp:144
-msgid "Delete"
-msgstr "Excluir"
-
-#: ControlEditorBase.cpp:96
-msgid "Control elements"
-msgstr "Elementos de controle"
-
-#: ControlEditorBase.cpp:124
-msgid "Test system..."
-msgstr "Testar sistema..."
-
-#: ControlEditorBase.cpp:130 ElementForm.cpp:328 ElementForm.cpp:731
-#: ElementForm.cpp:1235 ElementForm.cpp:1547 ElementForm.cpp:1947
-#: ElementForm.cpp:2282 ElementForm.cpp:2412 ElementForm.cpp:2540
-#: ElementForm.cpp:2698 ElementForm.cpp:2896 ElementForm.cpp:3011
-#: ElementForm.cpp:3100 ElementForm.cpp:3201 ElementForm.cpp:3302
-#: ElementForm.cpp:3407 ElementForm.cpp:3496 ElementForm.cpp:3585
-#: ElementForm.cpp:3682 PropertiesForm.cpp:78 PropertiesForm.cpp:635
-#: PropertiesForm.cpp:767
-msgid "OK"
-msgstr "OK"
-
-#: ControlEditorBase.cpp:214 ElementForm.cpp:35 ElementForm.cpp:404
-#: ElementForm.cpp:1302 ElementForm.cpp:1615 ElementForm.cpp:2015
-#: ElementForm.cpp:2352 ElementForm.cpp:2609 ElementForm.cpp:2766
-#: ElementForm.cpp:2976 ElementForm.cpp:3077 ElementForm.cpp:3166
-#: ElementForm.cpp:3267 ElementForm.cpp:3368 ElementForm.cpp:3473
-#: ElementForm.cpp:3562 ElementForm.cpp:3651 PropertiesForm.cpp:35
-#: PropertiesForm.cpp:144
-msgid "General"
-msgstr "Geral"
-
-#: ControlEditorBase.cpp:219
-msgid "Input type:"
-msgstr "Tipo de entrada:"
-
-#: ControlEditorBase.cpp:240
-msgid "Start time"
-msgstr "Tempo de início"
-
-#: ControlEditorBase.cpp:255 ControlEditorBase.cpp:308 ElementForm.cpp:251
-#: ElementForm.cpp:274 ElementForm.cpp:829 ElementForm.cpp:1086
-#: ElementForm.cpp:1109 ElementForm.cpp:1186 ElementForm.cpp:1209
-#: PropertiesForm.cpp:291 PropertiesForm.cpp:314 PropertiesForm.cpp:405
-msgid "s"
-msgstr "s"
-
-#: ControlEditorBase.cpp:263
-msgid "Slope"
-msgstr "Inclinação"
-
-#: ControlEditorBase.cpp:278 PropertiesForm.cpp:276
-msgid "Time step"
-msgstr "Passo de integração"
-
-#: ControlEditorBase.cpp:293 PropertiesForm.cpp:299
-msgid "Simulation time"
-msgstr "Tempo de simulação"
-
-#: ControlEditorBase.cpp:316
-msgid "Run"
-msgstr "Executar"
-
-#: ControlEditorBase.cpp:320 ElementForm.cpp:332 ElementForm.cpp:735
-#: ElementForm.cpp:1239 ElementForm.cpp:1551 ElementForm.cpp:1951
-#: ElementForm.cpp:2286 ElementForm.cpp:2416 ElementForm.cpp:2544
-#: ElementForm.cpp:2702 ElementForm.cpp:2900 ElementForm.cpp:3015
-#: ElementForm.cpp:3104 ElementForm.cpp:3205 ElementForm.cpp:3306
-#: ElementForm.cpp:3411 ElementForm.cpp:3500 ElementForm.cpp:3589
-#: ElementForm.cpp:3686 PropertiesForm.cpp:82 PropertiesForm.cpp:639
-msgid "Cancel"
-msgstr "Cancelar"
-
-#: ControlEditorBase.h:90
-msgid "Control editor"
-msgstr "Editor de controle"
-
-#: ControlEditorBase.h:136
-msgid "Control system test"
-msgstr "Teste do sistema de controle"
-
#: ControlElementSolver.cpp:56
msgid "The control system must have at least one input and one output."
msgstr "O sistema de controle deve ter pelo menos uma entrada e uma saída."
@@ -812,11 +586,13 @@ msgid "Current (kA)"
msgstr "Corrente (kA)"
#: DataReport.cpp:230 DataReport.cpp:240 DataReport.cpp:252 DataReport.cpp:281
-#: DataReport.cpp:297 DataReport.cpp:315 ElementForm.cpp:40 ElementForm.cpp:409
-#: ElementForm.cpp:1307 ElementForm.cpp:1620 ElementForm.cpp:2020
-#: ElementForm.cpp:2357 ElementForm.cpp:2614 TextForm.cpp:872 TextForm.cpp:883
+#: DataReport.cpp:297 DataReport.cpp:315 TextForm.cpp:872 TextForm.cpp:883
#: TextForm.cpp:892 TextForm.cpp:903 TextForm.cpp:914 TextForm.cpp:922
#: TextForm.cpp:929 TextForm.cpp:936 TextForm.cpp:944
+#: base/ElementFormBase.cpp:40 base/ElementFormBase.cpp:409
+#: base/ElementFormBase.cpp:1307 base/ElementFormBase.cpp:1620
+#: base/ElementFormBase.cpp:2020 base/ElementFormBase.cpp:2357
+#: base/ElementFormBase.cpp:2614
msgid "Name"
msgstr "Nome"
@@ -878,39 +654,6 @@ msgstr "PV"
msgid "PQ"
msgstr "PQ"
-#: DataReportBase.cpp:73
-msgid "Power flow data"
-msgstr "Dados de fluxo de carga"
-
-#: DataReportBase.cpp:84 PropertiesForm.cpp:192
-msgid "Power flow"
-msgstr "Fluxo de carga"
-
-#: DataReportBase.cpp:101 DataReportBase.cpp:163
-msgid "Buses"
-msgstr "Barras"
-
-#: DataReportBase.cpp:118 DataReportBase.cpp:180
-msgid "Branches"
-msgstr "Ramos"
-
-#: DataReportBase.cpp:135
-msgid "Fault data"
-msgstr "Dados da falta"
-
-#: DataReportBase.cpp:146 ElementForm.cpp:117 ElementForm.cpp:579
-#: ElementForm.cpp:1479 ElementForm.cpp:1826 MainFrameBase.cpp:192
-msgid "Fault"
-msgstr "Falta"
-
-#: DataReportBase.cpp:197
-msgid "Generators"
-msgstr "Geradores"
-
-#: DataReportBase.h:90
-msgid "Data report"
-msgstr "Relatório de dados"
-
#: Electromechanical.cpp:70
msgid "Running simulation"
msgstr "Simulação em andamento"
@@ -957,7 +700,7 @@ msgstr "Não foi possível solucionar a saturação da máquina síncrona \""
msgid "Unknown error"
msgstr "Erro desconhecido"
-#: Element.cpp:250 MainFrameBase.cpp:148
+#: Element.cpp:250 base/MainFrameBase.cpp:148
msgid "Rotate clockwise"
msgstr "Girar no sentido horário"
@@ -965,484 +708,10 @@ msgstr "Girar no sentido horário"
msgid "Rotate counter-clockwise"
msgstr "Girar no sentido anti-horário"
-#: ElementForm.cpp:60 ElementForm.cpp:1327 ElementForm.cpp:1640
-msgid "Rated voltage"
-msgstr "Tensão nominal"
-
-#: ElementForm.cpp:87
-msgid "Controlled voltage"
-msgstr "Tensão controlada"
-
-#: ElementForm.cpp:111
-msgid "Slack Bus"
-msgstr "Barra de referência"
-
-#: ElementForm.cpp:122 ElementForm.cpp:223
-msgid "Insert fault in the bus"
-msgstr "Inserir falta na barra"
-
-#: ElementForm.cpp:135
-msgid "Fault type"
-msgstr "Tipo de falta"
-
-#: ElementForm.cpp:153
-msgid "Fault place"
-msgstr "Local da falta"
-
-#: ElementForm.cpp:170 ElementForm.cpp:282
-msgid "Fault resistance (R)"
-msgstr "Resistência da falta (R)"
-
-#: ElementForm.cpp:185 ElementForm.cpp:208 ElementForm.cpp:297
-#: ElementForm.cpp:320 ElementForm.cpp:852 ElementForm.cpp:909
-#: ElementForm.cpp:932 ElementForm.cpp:955 ElementForm.cpp:986
-#: ElementForm.cpp:1009 ElementForm.cpp:1040 ElementForm.cpp:1063
-#: ElementForm.cpp:1140 ElementForm.cpp:1163 TextForm.cpp:975 TextForm.cpp:985
-#: TextForm.cpp:990 TextForm.cpp:998 TextForm.cpp:1006
-msgid "p.u."
-msgstr "p.u."
-
-#: ElementForm.cpp:193 ElementForm.cpp:305
-msgid "Fault reactance (Xl)"
-msgstr "Reatância da falta (Xl)"
-
-#: ElementForm.cpp:213 ElementForm.cpp:725 ElementForm.cpp:1541
-#: ElementForm.cpp:1941 ElementForm.cpp:2107 ElementForm.cpp:2406
-#: ElementForm.cpp:2692 PropertiesForm.cpp:263
-msgid "Stability"
-msgstr "Estabilidade"
-
-#: ElementForm.cpp:218
-msgid "Plot bus data"
-msgstr "Imprimir dados da barra"
-
-#: ElementForm.cpp:259
-msgid "Fault length"
-msgstr "Duração da falta"
-
-#: ElementForm.cpp:429 ElementForm.cpp:1342 ElementForm.cpp:1671
-msgid "Rated power"
-msgstr "Potência nominal"
-
-#: ElementForm.cpp:459 ElementForm.cpp:2040 ElementForm.cpp:2126
-#: ElementForm.cpp:2634 IOControlForm.cpp:42 Load.cpp:269
-#: PropertiesForm.cpp:429 SyncGenerator.cpp:243 TextForm.cpp:884
-#: TextForm.cpp:915 TextForm.cpp:937 TextForm.cpp:945
-msgid "Active power"
-msgstr "Potência ativa"
-
-#: ElementForm.cpp:488 ElementForm.cpp:2069 ElementForm.cpp:2199
-#: ElementForm.cpp:2377 ElementForm.cpp:2663 IOControlForm.cpp:47 Load.cpp:270
-#: PropertiesForm.cpp:502 SyncGenerator.cpp:244 TextForm.cpp:885
-#: TextForm.cpp:916 TextForm.cpp:923 TextForm.cpp:930 TextForm.cpp:938
-#: TextForm.cpp:946
-msgid "Reactive power"
-msgstr "Potência reativa"
-
-#: ElementForm.cpp:517
-msgid "Max reactive power"
-msgstr "Potência reativa máx"
-
-#: ElementForm.cpp:547
-msgid "Min reactive power"
-msgstr "Potência reativa min"
-
-#: ElementForm.cpp:573
-msgid "Use machine rated power as base"
-msgstr "Utilizar potência nominal da máquina como base"
-
-#: ElementForm.cpp:584
-msgid "Sequence impedances (p.u.)"
-msgstr "Impedâncias de sequência (p.u.)"
-
-#: ElementForm.cpp:596
-msgid "Positive resistance (R1)"
-msgstr "Resistência positiva (R1)"
-
-#: ElementForm.cpp:611
-msgid "Positive reactance (X1)"
-msgstr "Reatância positiva (X1)"
-
-#: ElementForm.cpp:626
-msgid "Negative resistance (R2)"
-msgstr "Resistência negativa (R2)"
-
-#: ElementForm.cpp:641
-msgid "Negative reactance (X2)"
-msgstr "Reatância negativa (X2)"
-
-#: ElementForm.cpp:656
-msgid "Zero resistance (R0)"
-msgstr "Resistência zero (R0)"
-
-#: ElementForm.cpp:671
-msgid "Zero reactance (X0)"
-msgstr "Reatância zero (X0)"
-
-#: ElementForm.cpp:690
-msgid "Ground resistance (p.u.)"
-msgstr "Resistência de aterramento (p.u.)"
-
-#: ElementForm.cpp:705
-msgid "Ground reactance (p.u.)"
-msgstr "Reatância de aterramento (p.u.)"
-
-#: ElementForm.cpp:716
-msgid "Grounded neutral"
-msgstr "Neutro aterrado"
-
-#: ElementForm.cpp:801
-msgid "Plot synchronous machine data"
-msgstr "Imprimir dados da máquina síncrona"
-
-#: ElementForm.cpp:814
-msgid "Inertia (H)"
-msgstr "Inércia (H)"
-
-#: ElementForm.cpp:837
-msgid "Damping factor"
-msgstr "Fator de amortecimento"
-
-#: ElementForm.cpp:860
-msgid "Use AVR"
-msgstr "Utilizar AVR"
-
-#: ElementForm.cpp:865
-msgid "Edit AVR"
-msgstr "Editar AVR"
-
-#: ElementForm.cpp:873
-msgid "Use speed governor"
-msgstr "Utilizar regulador de velocidade"
-
-#: ElementForm.cpp:878
-msgid "Edit speed governor"
-msgstr "Editar regulador de velocidade"
-
-#: ElementForm.cpp:894
-msgid "Armature resistance (Ra)"
-msgstr "Resistência de armadura (Ra)"
-
-#: ElementForm.cpp:917
-msgid "Potier reactance (Xp)"
-msgstr "Reatância de Potier (Xp)"
-
-#: ElementForm.cpp:940
-msgid "Saturation factor"
-msgstr "Fator de saturação"
-
-#: ElementForm.cpp:959
-msgid "Syncronous"
-msgstr "Síncrono"
-
-#: ElementForm.cpp:971
-msgid "Direct-axis reactance (Xd)"
-msgstr "Reatância de eixo direto (Xd)"
-
-#: ElementForm.cpp:994
-msgid "Quadrature-axis reactance (Xq)"
-msgstr "Reatância de eixo em quadratura (Xq)"
-
-#: ElementForm.cpp:1013
-msgid "Transient"
-msgstr "Tansitório"
-
-#: ElementForm.cpp:1025
-msgid "Direct-axis reactance (X'd)"
-msgstr "Reatância de eixo direto (X'd)"
-
-#: ElementForm.cpp:1048
-msgid "Quadrature-axis reactance (X'q)"
-msgstr "Reatância de eixo em quadratura (X'q)"
-
-#: ElementForm.cpp:1071
-msgid "Direct-axis time constant (T'd0)"
-msgstr "Constante de tempo de eixo direto (T'd0)"
-
-#: ElementForm.cpp:1094
-msgid "Quadrature-axis time constant (T'q0)"
-msgstr "Constante de tempo de eixo em quadratura (T'd0)"
-
-#: ElementForm.cpp:1113
-msgid "Sub-transient"
-msgstr "Subtransitório"
-
-#: ElementForm.cpp:1125
-msgid "Direct-axis reactance (X''d)"
-msgstr "Reatância de eixo direto (X''d)"
-
-#: ElementForm.cpp:1148
-msgid "Quadrature-axis reactance (X''q)"
-msgstr "Reatância de eixo em quadratura (X''q)"
-
-#: ElementForm.cpp:1171
-msgid "Direct-axis time constant (T''d0)"
-msgstr "Constante de tempo de eixo direto (T''d0)"
-
-#: ElementForm.cpp:1194
-msgid "Quadrature-axis time constant (T''q0)"
-msgstr "Constante de tempo de eixo em quadratura (T''d0)"
-
-#: ElementForm.cpp:1229 ElementForm.cpp:2276 ElementForm.h:711
-msgid "Switching"
-msgstr "Chaveamento"
-
-#: ElementForm.cpp:1331
-msgid "138 kV"
-msgstr "138 kV"
-
-#: ElementForm.cpp:1370 ElementForm.cpp:1701
-msgid "Resistance (R)"
-msgstr "Resistência (R)"
-
-#: ElementForm.cpp:1398 ElementForm.cpp:1728
-msgid "Indutive reactance (XL)"
-msgstr "Reatância indutiva (Xl)"
-
-#: ElementForm.cpp:1426
-msgid "Capacitive susceptance (B)"
-msgstr "Susceptância capacitiva (B)"
-
-#: ElementForm.cpp:1454
-msgid "Line size"
-msgstr "Comprimento da linha"
-
-#: ElementForm.cpp:1469
-msgid "km"
-msgstr "km"
-
-#: ElementForm.cpp:1473
-msgid "Use line rated power as base"
-msgstr "Utilizar a potência nominal como base"
-
-#: ElementForm.cpp:1484 ElementForm.cpp:1831
-msgid "Zero-sequence impedances (p.u.)"
-msgstr "Impedâncias de sequência zero (p.u.)"
-
-#: ElementForm.cpp:1496 ElementForm.cpp:1843
-msgid "Resistance (R0)"
-msgstr "Resistência (R0)"
-
-#: ElementForm.cpp:1511 ElementForm.cpp:1858
-msgid "Indutive reactance (X0)"
-msgstr "Reatância indutiva (X0)"
-
-#: ElementForm.cpp:1526
-msgid "Capacitive susceptance (B0)"
-msgstr "Susceptância capacitiva (B0)"
-
-#: ElementForm.cpp:1644
-msgid "138 kV / 138 kV"
-msgstr "138 kV / 138 kV"
-
-#: ElementForm.cpp:1655
-msgid "Base voltage"
-msgstr "Tensão base"
-
-#: ElementForm.cpp:1759
-msgid "Connection"
-msgstr "Conexão"
-
-#: ElementForm.cpp:1786
-msgid "Turns ratio"
-msgstr "TAP"
-
-#: ElementForm.cpp:1801
-msgid "Phase shift"
-msgstr "Defasagem"
-
-#: ElementForm.cpp:1816
-msgid "degrees"
-msgstr "graus"
-
-#: ElementForm.cpp:1820
-msgid "Use transformer rated power as base"
-msgstr "Utilizar a potência do transformador como base"
-
-#: ElementForm.cpp:1869
-msgid "Ground impedances (p.u.)"
-msgstr "Impedância de aterramento (p.u.)"
-
-#: ElementForm.cpp:1881
-msgid "Primary resistance"
-msgstr "Resistência do primário"
-
-#: ElementForm.cpp:1896
-msgid "Primary reactance"
-msgstr "Reatância do primário"
-
-#: ElementForm.cpp:1911
-msgid "Secondary resistance"
-msgstr "Resistência do secundário"
-
-#: ElementForm.cpp:1926
-msgid "Secondary reactance"
-msgstr "Reatância do secundário"
-
-#: ElementForm.cpp:2094
-msgid "Load type (power flow)"
-msgstr "Tipo de carga (fluxo de carga)"
-
-#: ElementForm.cpp:2112
-msgid "Plot load data"
-msgstr "Imprimir dados da carga"
-
-#: ElementForm.cpp:2117
-msgid "Use ZIP load composition"
-msgstr "Utilizar composição de carga ZIP"
-
-#: ElementForm.cpp:2134 ElementForm.cpp:2207 PropertiesForm.cpp:437
-#: PropertiesForm.cpp:510
-msgid "Constant impedance"
-msgstr "Impedância constante"
-
-#: ElementForm.cpp:2149 ElementForm.cpp:2172 ElementForm.cpp:2195
-#: ElementForm.cpp:2222 ElementForm.cpp:2245 ElementForm.cpp:2268
-#: PropertiesForm.cpp:452 PropertiesForm.cpp:475 PropertiesForm.cpp:498
-#: PropertiesForm.cpp:525 PropertiesForm.cpp:548 PropertiesForm.cpp:571
-#: PropertiesForm.cpp:602 PropertiesForm.cpp:625
-msgid "%"
-msgstr "%"
-
-#: ElementForm.cpp:2157 ElementForm.cpp:2230 PropertiesForm.cpp:460
-#: PropertiesForm.cpp:533 PropertiesForm.cpp:587
-msgid "Constant current"
-msgstr "Corrente constante"
-
-#: ElementForm.cpp:2180 ElementForm.cpp:2253 PropertiesForm.cpp:483
-#: PropertiesForm.cpp:556 PropertiesForm.cpp:610
-msgid "Constant power"
-msgstr "Potência constante"
-
-#: ElementForm.cpp:2490
-msgid "Switching properties"
-msgstr "Propriedades de chaveamento"
-
-#: ElementForm.cpp:2495 SwitchingForm.cpp:40 SwitchingForm.cpp:53
-#: SwitchingForm.cpp:69
-msgid "Insert"
-msgstr "Inserir"
-
-#: ElementForm.cpp:2496 ElementForm.cpp:2512 SwitchingForm.cpp:40
-#: SwitchingForm.cpp:53
-msgid "Remove"
-msgstr "Remover"
-
-#: ElementForm.cpp:2500 SwitchingForm.cpp:24 SwitchingForm.cpp:33
-msgid "Time (s)"
-msgstr "Tempo (s)"
-
-#: ElementForm.cpp:2508
-msgid "Add"
-msgstr "Adicionar"
-
-#: ElementForm.cpp:2520
-msgid "Down"
-msgstr "Baixo"
-
-#: ElementForm.cpp:2528
-msgid "Switching list"
-msgstr "Lista de chaveamento"
-
-#: ElementForm.cpp:2779
-msgid "Element"
-msgstr "Elemento"
-
-#: ElementForm.cpp:2801
-msgid "Element name"
-msgstr "Nome do elemento"
-
-#: ElementForm.cpp:2814
-msgid "Text type"
-msgstr "Tipo de texto"
-
-#: ElementForm.cpp:2827
-msgid "From bus"
-msgstr "Da barra"
-
-#: ElementForm.cpp:2840
-msgid "To bus"
-msgstr "Para barra"
-
-#: ElementForm.cpp:2853
-msgid "Unit"
-msgstr "Unidade"
-
-#: ElementForm.cpp:2866
-msgid "Decimal places:"
-msgstr "Casas decimais:"
-
-#: ElementForm.cpp:2879
-msgid "Preview:"
-msgstr "Pré-visualização:"
-
-#: ElementForm.cpp:2981
-msgid "Numerator parameters"
-msgstr "Parâmetros do numerador"
-
-#: ElementForm.cpp:2993
-msgid "Denominator parameters"
-msgstr "Parâmetros do denominador"
-
-#: ElementForm.cpp:3082
-msgid "Signs"
-msgstr "Sinais"
-
-#: ElementForm.cpp:3171 ElementForm.cpp:3272
-msgid "Upper limit"
-msgstr "Limite superior"
-
-#: ElementForm.cpp:3183 ElementForm.cpp:3284
-msgid "Lower limit"
-msgstr "Limite inferior"
-
-#: ElementForm.cpp:3373
-msgid "y = A.eB.x"
-msgstr "y = A.eB.x"
-
-#: ElementForm.cpp:3377
-msgid "A value"
-msgstr "Valor A"
-
-#: ElementForm.cpp:3389
-msgid "B value"
-msgstr "Valor B"
-
-#: ElementForm.cpp:3478
-msgid "Constant value"
-msgstr "Valor da constante"
-
-#: ElementForm.cpp:3567
-msgid "Gain value"
-msgstr "Valor do ganho"
-
-#: ElementForm.h:242 SyncGenerator.cpp:66
-msgid "Generator"
-msgstr "Gerador"
-
-#: ElementForm.h:369
-msgid "Generator: Stability"
-msgstr "Gerador: Estabilidade"
-
-#: ElementForm.h:670
-msgid "Reactive shunt element"
-msgstr "Elemento shunt reativo"
-
-#: ElementForm.h:752
-msgid "Motor"
-msgstr "Motor"
-
-#: ElementForm.h:813 OpenGLText.h:52 Text.h:109
-msgid "Text"
-msgstr "Texto"
-
-#: ElementForm.h:843
-msgid "Transfer function"
-msgstr "Função transferência"
-
-#: ElementForm.h:1045
-msgid "Input / Output"
-msgstr "Entrada / Saída"
+#: Element.cpp:258 Line.cpp:304 base/ControlEditorBase.cpp:85
+#: base/MainFrameBase.cpp:144
+msgid "Delete"
+msgstr "Excluir"
#: ExponentialForm.cpp:56
msgid "Value entered incorrectly in the field \"A value\"."
@@ -1633,6 +902,22 @@ msgstr "Tensão terminal"
msgid "Velocity"
msgstr "Velocidade"
+#: IOControlForm.cpp:42 Load.cpp:269 SyncGenerator.cpp:243 TextForm.cpp:884
+#: TextForm.cpp:915 TextForm.cpp:937 TextForm.cpp:945
+#: base/ElementFormBase.cpp:459 base/ElementFormBase.cpp:2040
+#: base/ElementFormBase.cpp:2126 base/ElementFormBase.cpp:2634
+#: base/PropertiesFormBase.cpp:429
+msgid "Active power"
+msgstr "Potência ativa"
+
+#: IOControlForm.cpp:47 Load.cpp:270 SyncGenerator.cpp:244 TextForm.cpp:885
+#: TextForm.cpp:916 TextForm.cpp:923 TextForm.cpp:930 TextForm.cpp:938
+#: TextForm.cpp:946 base/ElementFormBase.cpp:488 base/ElementFormBase.cpp:2069
+#: base/ElementFormBase.cpp:2199 base/ElementFormBase.cpp:2377
+#: base/ElementFormBase.cpp:2663 base/PropertiesFormBase.cpp:502
+msgid "Reactive power"
+msgstr "Potência reativa"
+
#: IOControlForm.cpp:52 SyncGenerator.cpp:247
msgid "Field voltage"
msgstr "Tensão de campo"
@@ -1960,21 +1245,21 @@ msgstr "Linha %d"
msgid "Insert Line: Click on two buses, ESC to cancel."
msgstr "Inserir Linha: Clique em duas barras, ESC para cancelar."
-#: MainFrame.cpp:416 Workspace.cpp:754
+#: MainFrame.cpp:416 Workspace.cpp:755
#, c-format
msgid "Transformer %d"
msgstr "Transformador %d"
-#: MainFrame.cpp:419 Workspace.cpp:758
+#: MainFrame.cpp:419 Workspace.cpp:759
msgid "Insert Transformer: Click on two buses, ESC to cancel."
msgstr "Inserir Transformador: Clique em duas barras, ESC para cancelar."
-#: MainFrame.cpp:424 Workspace.cpp:766
+#: MainFrame.cpp:424 Workspace.cpp:767
#, c-format
msgid "Generator %d"
msgstr "Gerador %d"
-#: MainFrame.cpp:427 Workspace.cpp:770
+#: MainFrame.cpp:427 Workspace.cpp:771
msgid "Insert Generator: Click on a buses, ESC to cancel."
msgstr "Inserir Gerador: Clique em uma barra, ESC para cancelar."
@@ -1987,304 +1272,101 @@ msgstr "Carga %d"
msgid "Insert Load: Click on a buses, ESC to cancel."
msgstr "Inserir Carga: Clique em uma barra, ESC para cancelar."
-#: MainFrame.cpp:439 Workspace.cpp:811
+#: MainFrame.cpp:439 Workspace.cpp:812
#, c-format
msgid "Capacitor %d"
msgstr "Capacitor %d"
-#: MainFrame.cpp:442 Workspace.cpp:815
+#: MainFrame.cpp:442 Workspace.cpp:816
msgid "Insert Capacitor: Click on a buses, ESC to cancel."
msgstr "Inserir Capacitor: Clique em uma barra, ESC para cancelar."
-#: MainFrame.cpp:447 Workspace.cpp:778
+#: MainFrame.cpp:447 Workspace.cpp:779
#, c-format
msgid "Inductor %d"
msgstr "Indutor %d"
-#: MainFrame.cpp:450 Workspace.cpp:782
+#: MainFrame.cpp:450 Workspace.cpp:783
msgid "Insert Inductor: Click on a buses, ESC to cancel."
msgstr "Inserir Indutor: Clique em uma barra, ESC para cancelar."
-#: MainFrame.cpp:455 Workspace.cpp:786
+#: MainFrame.cpp:455 Workspace.cpp:787
#, c-format
msgid "Induction motor %d"
msgstr "Motor de indução %d"
-#: MainFrame.cpp:458 Workspace.cpp:790
+#: MainFrame.cpp:458 Workspace.cpp:791
msgid "Insert Induction Motor: Click on a buses, ESC to cancel."
msgstr "Inserir Motor de indução: Clique em uma barra, ESC para cancelar."
-#: MainFrame.cpp:463 Workspace.cpp:799
+#: MainFrame.cpp:463 Workspace.cpp:800
#, c-format
msgid "Synchronous condenser %d"
msgstr "Compensador síncrono %d"
-#: MainFrame.cpp:466 Workspace.cpp:803
+#: MainFrame.cpp:466 Workspace.cpp:804
msgid "Insert Synchronous Condenser: Click on a buses, ESC to cancel."
msgstr "Inserir Compensador síncrono: Clique em uma barra, ESC para cancelar."
-#: MainFrameBase.cpp:76 MainFrameBase.cpp:77 MainFrameBase.cpp:80
-msgid "Projects"
-msgstr "Projetos"
-
-#: MainFrameBase.cpp:82
-msgid "Create new project"
-msgstr "Criar novo projeto"
-
-#: MainFrameBase.cpp:84
-msgid "Open"
-msgstr "Abrir"
-
-#: MainFrameBase.cpp:84
-msgid "Open saved project"
-msgstr "Abrir projetos salvos"
-
-#: MainFrameBase.cpp:86
-msgid "General Settings"
-msgstr "Configurações gerais"
-
-#: MainFrameBase.cpp:86
-msgid "Opens a dialog to set the main settings of the program"
-msgstr ""
-"Abre um formulário para definir as principais configurações do programa"
-
-#: MainFrameBase.cpp:88
-msgid "Closes the application"
-msgstr "Fecha a aplicação"
-
-#: MainFrameBase.cpp:91 MainFrameBase.cpp:92
-msgid "Current project"
-msgstr "Projeto atual"
-
-#: MainFrameBase.cpp:96
-msgid "Save"
-msgstr "Salvar"
+#: MathExpressionForm.cpp:7
+msgid "No checks performed."
+msgstr "Nenhuma verificação realizada."
-#: MainFrameBase.cpp:96
-msgid "Save the current project"
-msgstr "Salvar o projeto atual"
+#: MathExpressionForm.cpp:19
+msgid "Syntax error"
+msgstr "Erro de sintaxe"
-#: MainFrameBase.cpp:98
-msgid "Save As..."
-msgstr "Salvar como..."
-
-#: MainFrameBase.cpp:98
-msgid "Save as the current project"
-msgstr "Salvar como o projeto atual"
-
-#: MainFrameBase.cpp:100
-msgid "Close"
-msgstr "Fechar"
-
-#: MainFrameBase.cpp:100
-msgid "Close the current project"
-msgstr "Fechar o projeto atual"
-
-#: MainFrameBase.cpp:103 MainFrameBase.cpp:104 MainFrameBase.cpp:107
-msgid "Help"
-msgstr "Ajuda"
-
-#: MainFrameBase.cpp:109
-msgid "PSP-UFU Guide"
-msgstr "Manual do PSP-UFU"
-
-#: MainFrameBase.cpp:109
-msgid "Open PSP-UFU Guide"
-msgstr "Abrir o manual do PSP-UFU"
+#: MathExpressionForm.cpp:20
+msgid "Mismatched parenthesis"
+msgstr "Parênteses sem correspondência"
-#: MainFrameBase.cpp:111
-msgid "About..."
-msgstr "Sobre..."
+#: MathExpressionForm.cpp:21
+msgid "Missing ')'"
+msgstr "Faltando ')'"
-#: MainFrameBase.cpp:111 PropertiesForm.h:256
-msgid "About PSP-UFU"
-msgstr "Sobre o PSP-UFU"
+#: MathExpressionForm.cpp:22
+msgid "Empty parentheses"
+msgstr "Parênteses vazios"
-#: MainFrameBase.cpp:114 MainFrameBase.cpp:115
-msgid "Tools"
-msgstr "Ferramentas"
+#: MathExpressionForm.cpp:23
+msgid "Syntax error: Operator expected"
+msgstr "Erro de sintaxe: Operador esperado"
-#: MainFrameBase.cpp:117 MainFrameBase.cpp:118 MainFrameBase.cpp:121
-msgid "Clipboard"
-msgstr "Ãrea de transferência"
+#: MathExpressionForm.cpp:24
+msgid "Not enough memory"
+msgstr "Não possui memória"
-#: MainFrameBase.cpp:123
-msgid "Copies the selected elements"
-msgstr "Copia os elementos selecionados"
+#: MathExpressionForm.cpp:25
+msgid "An unexpected error occurred"
+msgstr "Um erro inesperado ocorreu"
-#: MainFrameBase.cpp:125
-msgid "Pastes the elements from clipboard"
-msgstr "Cola os elementos da área de transferência"
+#: MathExpressionForm.cpp:26
+msgid "Syntax error in input variables"
+msgstr "Erro de sintaxe nas variáveis de entrada"
-#: MainFrameBase.cpp:127
-msgid "Undoes the last action"
-msgstr "Desfaz a última ação"
+#: MathExpressionForm.cpp:27
+msgid "Illegal number of parameters to function"
+msgstr "Número ilegal de parâmetros para a função"
-#: MainFrameBase.cpp:129
-msgid "Redoes the last undo action"
-msgstr "Refaz a última ação desfeita"
+#: MathExpressionForm.cpp:28
+msgid "Syntax error: Expecting ( after function"
+msgstr "Erro de sintaxe: '(' esperado após a função"
-#: MainFrameBase.cpp:132 MainFrameBase.cpp:133 MainFrameBase.cpp:136
-msgid "Circuit"
-msgstr "Circuito"
+#: MathExpressionForm.cpp:29
+msgid "Syntax error: Unknown identifier"
+msgstr "Erro de sintaxe: identificador desconhecida"
-#: MainFrameBase.cpp:138
-msgid "Add Element"
-msgstr "Inserir elemento"
+#: MathExpressionForm.cpp:30
+msgid "No function has been parsed yet"
+msgstr "Nenhuma função foi analisada ainda"
-#: MainFrameBase.cpp:138
-msgid "Add a new element in the project"
-msgstr "Adicionar um elemento novo no projeto"
+#: MathExpressionForm.cpp:47
+msgid "OK!"
+msgstr "OK!"
-#: MainFrameBase.cpp:140
-msgid "Drag all the elements"
-msgstr "Arrasta todos os elementos"
-
-#: MainFrameBase.cpp:142
-msgid "Move the selected elements"
-msgstr "Move os elementos selecionados"
-
-#: MainFrameBase.cpp:144
-msgid "Removes all selected elements"
-msgstr "Remove todos os elementos selecionados"
-
-#: MainFrameBase.cpp:146
-msgid "Applies the drag and zoom tools to show all elements in workspace"
-msgstr ""
-"Aplica as ferramentas de arrasto e ampliação para exibir todos os elementos "
-"na área de trabalho"
-
-#: MainFrameBase.cpp:148
-msgid "Rotate Clockwise"
-msgstr "Girar Horário"
-
-#: MainFrameBase.cpp:150
-msgid "Rotate Counter-clockwise"
-msgstr "Girar anti-horário"
-
-#: MainFrameBase.cpp:150
-msgid "Rotate the selected elements counter-clockwise"
-msgstr "Gira os elementos selecionados no sentido anti-horário"
-
-#: MainFrameBase.cpp:152
-msgid "Project Settings"
-msgstr "Configurações do projeto"
-
-#: MainFrameBase.cpp:152
-msgid "Opens a dialog to set the main settings of the current project"
-msgstr ""
-"Abre uma janela para definir as principais configurações do projeto atual"
-
-#: MainFrameBase.cpp:155 MainFrameBase.cpp:156
-msgid "Reports"
-msgstr "Relatórios"
-
-#: MainFrameBase.cpp:160
-msgid "Data Report"
-msgstr "Relatório de dados"
-
-#: MainFrameBase.cpp:160
-msgid "Opens a data report"
-msgstr "Abre um relatório de dados"
-
-#: MainFrameBase.cpp:162
-msgid "Charts"
-msgstr "Gráficos"
-
-#: MainFrameBase.cpp:162
-msgid "Open the charts"
-msgstr "Abre os gráficos"
-
-#: MainFrameBase.cpp:164
-msgid "Snapshot"
-msgstr "Instantâneo"
-
-#: MainFrameBase.cpp:164
-msgid "Capture a snapshot of the circuit"
-msgstr "Captura uma imagem instantânea do circuito"
-
-#: MainFrameBase.cpp:167 MainFrameBase.cpp:168
-msgid "Simulation"
-msgstr "Simulação"
-
-#: MainFrameBase.cpp:170 MainFrameBase.cpp:171
-msgid "Continuous"
-msgstr "Contínuo"
-
-#: MainFrameBase.cpp:175
-msgid "Enable Solution"
-msgstr "Habilitar solução"
-
-#: MainFrameBase.cpp:175
-msgid ""
-"Enables the power flow and fault (if exists) calculations after any circuit "
-"change"
-msgstr ""
-"Habilita os cálculos de fluxo de carga e falta (se existir) após qualquer "
-"mudança no circuito"
-
-#: MainFrameBase.cpp:177
-msgid "Disable Solution"
-msgstr "Desabilitar solução"
-
-#: MainFrameBase.cpp:177
-msgid ""
-"Disables the power flow and fault calculations after any circuit changes"
-msgstr ""
-"Desabilita os cálculos de fluxo de carga e falta após qualquer mudança no "
-"circuito"
-
-#: MainFrameBase.cpp:179
-msgid "Reset Voltages"
-msgstr "Reiniciar tensões"
-
-#: MainFrameBase.cpp:179
-msgid "Reset all voltages to initial state"
-msgstr "Reinicia todas as tensões para os valores iniciais"
-
-#: MainFrameBase.cpp:182 MainFrameBase.cpp:183 MainFrameBase.cpp:186
-msgid "Simulations"
-msgstr "Simulações"
-
-#: MainFrameBase.cpp:188
-msgid "Power Flow"
-msgstr "Fluxo de carga"
-
-#: MainFrameBase.cpp:188
-msgid "Calculate the circuit power flow"
-msgstr "Calcula o fluxo de carga do circuito"
-
-#: MainFrameBase.cpp:190
-msgid "Run Stability"
-msgstr "Executar estabilidade"
-
-#: MainFrameBase.cpp:190
-msgid "Run the stability calculations"
-msgstr "Executa os cálculos de estabilidade"
-
-#: MainFrameBase.cpp:192
-msgid "Calculate the circuit fault (if exists)"
-msgstr "Calcula a falta do circuito (se existir)"
-
-#: MainFrameBase.cpp:194
-msgid "Short-Circuit Power"
-msgstr "Nível de curto-circuito"
-
-#: MainFrameBase.cpp:194
-msgid "Calculate the short-circuit power in all buses"
-msgstr "Calcula o nível de curto-circuito em todas as barras"
-
-#: MainFrameBase.cpp:196
-msgid "Simulation Settings"
-msgstr "Configurações de simulação"
-
-#: MainFrameBase.cpp:196
-msgid "Opens a dialog to set the settings of the simulations"
-msgstr "Abre um formulário para definir as configurações de simulação"
-
-#: MainFrameBase.h:141
-msgid "PSP-UFU"
-msgstr "PSP-UFU"
+#: OpenGLText.h:52 Text.h:109 base/ElementFormBase.h:814
+msgid "Text"
+msgstr "Texto"
#: PowerFlow.cpp:31
msgid "No buses found on the system."
@@ -2302,122 +1384,6 @@ msgstr "A barra de referência não tem geração."
msgid "The maximum number of iterations was reached."
msgstr "O número máximo de iterações foi alcançado."
-#: PropertiesForm.cpp:44
-msgid "Language"
-msgstr "Idioma"
-
-#: PropertiesForm.cpp:60
-msgid "Theme"
-msgstr "Tema"
-
-#: PropertiesForm.cpp:153
-msgid "Base power"
-msgstr "Potência base"
-
-#: PropertiesForm.cpp:177
-msgid "Continuous calculation"
-msgstr "Cálculo contínuo"
-
-#: PropertiesForm.cpp:181
-msgid "Calculate fault after power flow"
-msgstr "Calcular falta após o fluxo de carga"
-
-#: PropertiesForm.cpp:186
-msgid "Calculate short-circuit power after power flow"
-msgstr "Calcular o nível de curto-circuito após o fluxo de carga"
-
-#: PropertiesForm.cpp:201
-msgid "Solution method"
-msgstr "Método de solução"
-
-#: PropertiesForm.cpp:221
-msgid "Acceleration factor"
-msgstr "Fator de aceleração"
-
-#: PropertiesForm.cpp:236 PropertiesForm.cpp:345
-msgid "Tolerance"
-msgstr "Tolerância"
-
-#: PropertiesForm.cpp:251
-msgid "Max. iterations"
-msgstr "Iterações máx"
-
-#: PropertiesForm.cpp:322
-msgid "System frequency"
-msgstr "Frequência do sistema"
-
-#: PropertiesForm.cpp:337
-msgid "Hz"
-msgstr "Hz"
-
-#: PropertiesForm.cpp:360
-msgid "Max. Iterations"
-msgstr "Iterações máx"
-
-#: PropertiesForm.cpp:375
-msgid "Controls step ratio"
-msgstr "Razão do passo dos controles"
-
-#: PropertiesForm.cpp:390
-msgid "Plot time"
-msgstr "Tempo de impressão"
-
-#: PropertiesForm.cpp:409
-msgid "Use center of inertia as reference"
-msgstr "Utilizar centro de inércia como referência"
-
-#: PropertiesForm.cpp:415
-msgid "ZIP Load"
-msgstr "Carga ZIP"
-
-#: PropertiesForm.cpp:420
-msgid "Use general composition to all system loads"
-msgstr "Utilizar composição geral para todas as cargas do sistema"
-
-#: PropertiesForm.cpp:575
-msgid ""
-"Undervoltage limit which the loads will be modelled by\n"
-"constant impedance:"
-msgstr ""
-"Subtensão a qual as cargas serão modeladas como\n"
-"impedância constante:"
-
-#: PropertiesForm.cpp:705
-msgid "About"
-msgstr "Sobre"
-
-#: PropertiesForm.cpp:715
-msgid "Credits"
-msgstr "Créditos"
-
-#: PropertiesForm.cpp:732
-msgid "License"
-msgstr "Licença"
-
-#: PropertiesForm.cpp:748
-msgid "Version:"
-msgstr "Versão:"
-
-#: PropertiesForm.cpp:752
-msgid "Alpha 2017w45a"
-msgstr "Alpha 2017w45a"
-
-#: PropertiesForm.cpp:756
-msgid "Home page:"
-msgstr "Página Inicial:"
-
-#: PropertiesForm.cpp:760
-msgid "https://thales1330.github.io/PSP/"
-msgstr "https://thales1330.github.io/PSP/"
-
-#: PropertiesForm.h:73
-msgid "General settings"
-msgstr "Opções gerais"
-
-#: PropertiesForm.h:219
-msgid "Simulation settings"
-msgstr "Opções de simulação"
-
#: ReactiveShuntElementForm.cpp:93
msgid "Capacitor: Switching"
msgstr "Capacitor: Chaveamento"
@@ -2539,10 +1505,28 @@ msgstr "Você deve atribuir pelo menos dois sinais."
msgid "Value entered incorrectly in the field \"Signs\"."
msgstr "Valor inserido incorretamente no campo \"Sinais\"."
+#: SwitchingForm.cpp:24 SwitchingForm.cpp:33 base/ElementFormBase.cpp:2500
+msgid "Time (s)"
+msgstr "Tempo (s)"
+
+#: SwitchingForm.cpp:40 SwitchingForm.cpp:53 SwitchingForm.cpp:69
+#: base/ElementFormBase.cpp:2495
+msgid "Insert"
+msgstr "Inserir"
+
+#: SwitchingForm.cpp:40 SwitchingForm.cpp:53 base/ElementFormBase.cpp:2496
+#: base/ElementFormBase.cpp:2512
+msgid "Remove"
+msgstr "Remover"
+
#: SyncGenerator.cpp:58
msgid "Edit Generator"
msgstr "Editar Gerador"
+#: SyncGenerator.cpp:66 base/ElementFormBase.h:243
+msgid "Generator"
+msgstr "Gerador"
+
#: SyncGenerator.cpp:246
msgid "Frequency"
msgstr "Frequência"
@@ -2623,6 +1607,17 @@ msgstr "Fluxo de potência reativa"
msgid "Losses"
msgstr "Perdas"
+#: TextForm.cpp:975 TextForm.cpp:985 TextForm.cpp:990 TextForm.cpp:998
+#: TextForm.cpp:1006 base/ElementFormBase.cpp:185 base/ElementFormBase.cpp:208
+#: base/ElementFormBase.cpp:297 base/ElementFormBase.cpp:320
+#: base/ElementFormBase.cpp:852 base/ElementFormBase.cpp:909
+#: base/ElementFormBase.cpp:932 base/ElementFormBase.cpp:955
+#: base/ElementFormBase.cpp:986 base/ElementFormBase.cpp:1009
+#: base/ElementFormBase.cpp:1040 base/ElementFormBase.cpp:1063
+#: base/ElementFormBase.cpp:1140 base/ElementFormBase.cpp:1163
+msgid "p.u."
+msgstr "p.u."
+
#: TextForm.cpp:980
msgid "Degrees"
msgstr "Graus"
@@ -2791,43 +1786,1157 @@ msgstr "Atenção"
msgid "Insert Text: Click to insert, ESC to cancel."
msgstr "Inserir Texto: Clique para inserir, ESC para cancelar."
-#: Workspace.cpp:842
+#: Workspace.cpp:843
msgid "MODE: DRAG"
msgstr "MODO: ARRASTAR"
-#: Workspace.cpp:847
+#: Workspace.cpp:848
msgid "MODE: PASTE"
msgstr "MODO: COLAR"
-#: Workspace.cpp:854
+#: Workspace.cpp:855
msgid "MODE: INSERT"
msgstr "MODO: INSERÇÃO"
-#: Workspace.cpp:863
+#: Workspace.cpp:864
msgid "MODE: EDIT"
msgstr "MODO: EDIÇÃO"
-#: Workspace.cpp:867
+#: Workspace.cpp:868
#, c-format
msgid "ZOOM: %d%%"
msgstr "ZOOM: %d%%"
-#: Workspace.cpp:1211 Workspace.cpp:1319
+#: Workspace.cpp:1212 Workspace.cpp:1320
msgid "It was not possible to paste from clipboard."
msgstr "Não foi possível colar da área de transferência."
-#: Workspace.cpp:1327
+#: Workspace.cpp:1328
msgid "Click to paste."
msgstr "Clique para colar."
-#: Workspace.cpp:1472
+#: Workspace.cpp:1473
msgid "Do you wish to open the stability graphics?"
msgstr "Você deseja abrir os gráficos do estudo de estabilidade?"
-#: Workspace.cpp:1472
+#: Workspace.cpp:1473
msgid "Question"
msgstr "Pergunta"
+#: base/ChartViewBase.cpp:64 base/MainFrameBase.cpp:72
+#: base/MainFrameBase.cpp:73
+msgid "File"
+msgstr "Arquivo"
+
+#: base/ChartViewBase.cpp:66
+msgid "Save chart as image"
+msgstr "Salvar gráfico como imagem"
+
+#: base/ChartViewBase.cpp:69
+msgid "Send to clipboard"
+msgstr "Enviar para a área de transferência"
+
+#: base/ChartViewBase.cpp:72
+msgid "Export CSV..."
+msgstr "Exportar CSV..."
+
+#: base/ChartViewBase.cpp:77 base/MainFrameBase.cpp:88
+msgid "Exit"
+msgstr "Sair"
+
+#: base/ChartViewBase.cpp:81
+msgid "View"
+msgstr "Vizualização"
+
+#: base/ChartViewBase.cpp:83 base/MainFrameBase.cpp:146
+msgid "Fit"
+msgstr "Encaixar"
+
+#: base/ChartViewBase.cpp:88
+msgid "Show grid"
+msgstr "Exibir linhas de grade"
+
+#: base/ChartViewBase.cpp:91
+msgid "Show label"
+msgstr "Exibir legendas"
+
+#: base/ChartViewBase.cpp:94
+msgid "Show coordinates"
+msgstr "Exibir coordenadas"
+
+#: base/ChartViewBase.cpp:97
+msgid "Dark theme"
+msgstr "Tema escuro"
+
+#: base/ChartViewBase.cpp:120
+msgid "Line properties"
+msgstr "Propriedades do traço"
+
+#: base/ChartViewBase.cpp:139
+msgid "Y"
+msgstr "Y"
+
+#: base/ChartViewBase.cpp:140
+msgid "X"
+msgstr "X"
+
+#: base/ChartViewBase.cpp:145
+msgid "Chart properties"
+msgstr "Propriedades do gráfico"
+
+#: base/ChartViewBase.cpp:148
+msgid "Chart title"
+msgstr "Título do gráfico"
+
+#: base/ChartViewBase.cpp:152
+msgid "X axis label"
+msgstr "Rótulo do eixo X"
+
+#: base/ChartViewBase.cpp:156
+msgid "Y axis label"
+msgstr "Rótulo do eixo Y"
+
+#: base/ChartViewBase.cpp:163 base/ElementFormBase.cpp:2516
+msgid "Up"
+msgstr "Cima"
+
+#: base/ChartViewBase.cpp:166
+msgid "Botton"
+msgstr "Baixo"
+
+#: base/ChartViewBase.cpp:169
+msgid "Left"
+msgstr "Esquerda"
+
+#: base/ChartViewBase.cpp:172
+msgid "Right"
+msgstr "Direita"
+
+#: base/ChartViewBase.cpp:178
+msgid "X min"
+msgstr "X min"
+
+#: base/ChartViewBase.cpp:181
+msgid "X max"
+msgstr "X máx"
+
+#: base/ChartViewBase.cpp:184
+msgid "Y min"
+msgstr "Y min"
+
+#: base/ChartViewBase.cpp:187
+msgid "Y max"
+msgstr "Y máx"
+
+#: base/ChartViewBase.h:96
+msgid "Chart viewer"
+msgstr "Visualizador de gráficos"
+
+#: base/ControlEditorBase.cpp:63 base/MainFrameBase.cpp:82
+msgid "New"
+msgstr "Novo"
+
+#: base/ControlEditorBase.cpp:65
+msgid "Import"
+msgstr "Importar"
+
+#: base/ControlEditorBase.cpp:67
+msgid "Export"
+msgstr "Exportar"
+
+#: base/ControlEditorBase.cpp:71 base/MainFrameBase.cpp:123
+msgid "Copy"
+msgstr "Copiar"
+
+#: base/ControlEditorBase.cpp:73 base/MainFrameBase.cpp:125
+msgid "Paste"
+msgstr "Colar"
+
+#: base/ControlEditorBase.cpp:75 base/MainFrameBase.cpp:127
+msgid "Undo"
+msgstr "Desfazer"
+
+#: base/ControlEditorBase.cpp:77 base/MainFrameBase.cpp:129
+msgid "Redo"
+msgstr "Refazer"
+
+#: base/ControlEditorBase.cpp:81 base/MainFrameBase.cpp:140
+msgid "Drag"
+msgstr "Arrastar"
+
+#: base/ControlEditorBase.cpp:83 base/MainFrameBase.cpp:142
+msgid "Move"
+msgstr "Mover"
+
+#: base/ControlEditorBase.cpp:96
+msgid "Control elements"
+msgstr "Elementos de controle"
+
+#: base/ControlEditorBase.cpp:124
+msgid "Test system..."
+msgstr "Testar sistema..."
+
+#: base/ControlEditorBase.cpp:130 base/ElementFormBase.cpp:328
+#: base/ElementFormBase.cpp:731 base/ElementFormBase.cpp:1235
+#: base/ElementFormBase.cpp:1547 base/ElementFormBase.cpp:1947
+#: base/ElementFormBase.cpp:2282 base/ElementFormBase.cpp:2412
+#: base/ElementFormBase.cpp:2540 base/ElementFormBase.cpp:2698
+#: base/ElementFormBase.cpp:2896 base/ElementFormBase.cpp:3011
+#: base/ElementFormBase.cpp:3100 base/ElementFormBase.cpp:3201
+#: base/ElementFormBase.cpp:3302 base/ElementFormBase.cpp:3407
+#: base/ElementFormBase.cpp:3496 base/ElementFormBase.cpp:3585
+#: base/ElementFormBase.cpp:3682 base/ElementFormBase.cpp:3835
+#: base/PropertiesFormBase.cpp:78 base/PropertiesFormBase.cpp:635
+#: base/PropertiesFormBase.cpp:767
+msgid "OK"
+msgstr "OK"
+
+#: base/ControlEditorBase.cpp:214 base/ElementFormBase.cpp:35
+#: base/ElementFormBase.cpp:404 base/ElementFormBase.cpp:1302
+#: base/ElementFormBase.cpp:1615 base/ElementFormBase.cpp:2015
+#: base/ElementFormBase.cpp:2352 base/ElementFormBase.cpp:2609
+#: base/ElementFormBase.cpp:2766 base/ElementFormBase.cpp:2976
+#: base/ElementFormBase.cpp:3077 base/ElementFormBase.cpp:3166
+#: base/ElementFormBase.cpp:3267 base/ElementFormBase.cpp:3368
+#: base/ElementFormBase.cpp:3473 base/ElementFormBase.cpp:3562
+#: base/ElementFormBase.cpp:3651 base/ElementFormBase.cpp:3752
+#: base/PropertiesFormBase.cpp:35 base/PropertiesFormBase.cpp:144
+msgid "General"
+msgstr "Geral"
+
+#: base/ControlEditorBase.cpp:219
+msgid "Input type:"
+msgstr "Tipo de entrada:"
+
+#: base/ControlEditorBase.cpp:240
+msgid "Start time"
+msgstr "Tempo de início"
+
+#: base/ControlEditorBase.cpp:255 base/ControlEditorBase.cpp:308
+#: base/ElementFormBase.cpp:251 base/ElementFormBase.cpp:274
+#: base/ElementFormBase.cpp:829 base/ElementFormBase.cpp:1086
+#: base/ElementFormBase.cpp:1109 base/ElementFormBase.cpp:1186
+#: base/ElementFormBase.cpp:1209 base/PropertiesFormBase.cpp:291
+#: base/PropertiesFormBase.cpp:314 base/PropertiesFormBase.cpp:405
+msgid "s"
+msgstr "s"
+
+#: base/ControlEditorBase.cpp:263
+msgid "Slope"
+msgstr "Inclinação"
+
+#: base/ControlEditorBase.cpp:278 base/PropertiesFormBase.cpp:276
+msgid "Time step"
+msgstr "Passo de integração"
+
+#: base/ControlEditorBase.cpp:293 base/PropertiesFormBase.cpp:299
+msgid "Simulation time"
+msgstr "Tempo de simulação"
+
+#: base/ControlEditorBase.cpp:316
+msgid "Run"
+msgstr "Executar"
+
+#: base/ControlEditorBase.cpp:320 base/ElementFormBase.cpp:332
+#: base/ElementFormBase.cpp:735 base/ElementFormBase.cpp:1239
+#: base/ElementFormBase.cpp:1551 base/ElementFormBase.cpp:1951
+#: base/ElementFormBase.cpp:2286 base/ElementFormBase.cpp:2416
+#: base/ElementFormBase.cpp:2544 base/ElementFormBase.cpp:2702
+#: base/ElementFormBase.cpp:2900 base/ElementFormBase.cpp:3015
+#: base/ElementFormBase.cpp:3104 base/ElementFormBase.cpp:3205
+#: base/ElementFormBase.cpp:3306 base/ElementFormBase.cpp:3411
+#: base/ElementFormBase.cpp:3500 base/ElementFormBase.cpp:3589
+#: base/ElementFormBase.cpp:3686 base/ElementFormBase.cpp:3839
+#: base/PropertiesFormBase.cpp:82 base/PropertiesFormBase.cpp:639
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: base/ControlEditorBase.h:90
+msgid "Control editor"
+msgstr "Editor de controle"
+
+#: base/ControlEditorBase.h:136
+msgid "Control system test"
+msgstr "Teste do sistema de controle"
+
+#: base/DataReportBase.cpp:73
+msgid "Power flow data"
+msgstr "Dados de fluxo de carga"
+
+#: base/DataReportBase.cpp:84 base/PropertiesFormBase.cpp:192
+msgid "Power flow"
+msgstr "Fluxo de carga"
+
+#: base/DataReportBase.cpp:101 base/DataReportBase.cpp:163
+msgid "Buses"
+msgstr "Barras"
+
+#: base/DataReportBase.cpp:118 base/DataReportBase.cpp:180
+msgid "Branches"
+msgstr "Ramos"
+
+#: base/DataReportBase.cpp:135
+msgid "Fault data"
+msgstr "Dados da falta"
+
+#: base/DataReportBase.cpp:146 base/ElementFormBase.cpp:117
+#: base/ElementFormBase.cpp:579 base/ElementFormBase.cpp:1479
+#: base/ElementFormBase.cpp:1826 base/MainFrameBase.cpp:192
+msgid "Fault"
+msgstr "Falta"
+
+#: base/DataReportBase.cpp:197
+msgid "Generators"
+msgstr "Geradores"
+
+#: base/DataReportBase.h:90
+msgid "Data report"
+msgstr "Relatório de dados"
+
+#: base/ElementFormBase.cpp:60 base/ElementFormBase.cpp:1327
+#: base/ElementFormBase.cpp:1640
+msgid "Rated voltage"
+msgstr "Tensão nominal"
+
+#: base/ElementFormBase.cpp:87
+msgid "Controlled voltage"
+msgstr "Tensão controlada"
+
+#: base/ElementFormBase.cpp:111
+msgid "Slack Bus"
+msgstr "Barra de referência"
+
+#: base/ElementFormBase.cpp:122 base/ElementFormBase.cpp:223
+msgid "Insert fault in the bus"
+msgstr "Inserir falta na barra"
+
+#: base/ElementFormBase.cpp:135
+msgid "Fault type"
+msgstr "Tipo de falta"
+
+#: base/ElementFormBase.cpp:153
+msgid "Fault place"
+msgstr "Local da falta"
+
+#: base/ElementFormBase.cpp:170 base/ElementFormBase.cpp:282
+msgid "Fault resistance (R)"
+msgstr "Resistência da falta (R)"
+
+#: base/ElementFormBase.cpp:193 base/ElementFormBase.cpp:305
+msgid "Fault reactance (Xl)"
+msgstr "Reatância da falta (Xl)"
+
+#: base/ElementFormBase.cpp:213 base/ElementFormBase.cpp:725
+#: base/ElementFormBase.cpp:1541 base/ElementFormBase.cpp:1941
+#: base/ElementFormBase.cpp:2107 base/ElementFormBase.cpp:2406
+#: base/ElementFormBase.cpp:2692 base/PropertiesFormBase.cpp:263
+msgid "Stability"
+msgstr "Estabilidade"
+
+#: base/ElementFormBase.cpp:218
+msgid "Plot bus data"
+msgstr "Imprimir dados da barra"
+
+#: base/ElementFormBase.cpp:259
+msgid "Fault length"
+msgstr "Duração da falta"
+
+#: base/ElementFormBase.cpp:429 base/ElementFormBase.cpp:1342
+#: base/ElementFormBase.cpp:1671
+msgid "Rated power"
+msgstr "Potência nominal"
+
+#: base/ElementFormBase.cpp:517
+msgid "Max reactive power"
+msgstr "Potência reativa máx"
+
+#: base/ElementFormBase.cpp:547
+msgid "Min reactive power"
+msgstr "Potência reativa min"
+
+#: base/ElementFormBase.cpp:573
+msgid "Use machine rated power as base"
+msgstr "Utilizar potência nominal da máquina como base"
+
+#: base/ElementFormBase.cpp:584
+msgid "Sequence impedances (p.u.)"
+msgstr "Impedâncias de sequência (p.u.)"
+
+#: base/ElementFormBase.cpp:596
+msgid "Positive resistance (R1)"
+msgstr "Resistência positiva (R1)"
+
+#: base/ElementFormBase.cpp:611
+msgid "Positive reactance (X1)"
+msgstr "Reatância positiva (X1)"
+
+#: base/ElementFormBase.cpp:626
+msgid "Negative resistance (R2)"
+msgstr "Resistência negativa (R2)"
+
+#: base/ElementFormBase.cpp:641
+msgid "Negative reactance (X2)"
+msgstr "Reatância negativa (X2)"
+
+#: base/ElementFormBase.cpp:656
+msgid "Zero resistance (R0)"
+msgstr "Resistência zero (R0)"
+
+#: base/ElementFormBase.cpp:671
+msgid "Zero reactance (X0)"
+msgstr "Reatância zero (X0)"
+
+#: base/ElementFormBase.cpp:690
+msgid "Ground resistance (p.u.)"
+msgstr "Resistência de aterramento (p.u.)"
+
+#: base/ElementFormBase.cpp:705
+msgid "Ground reactance (p.u.)"
+msgstr "Reatância de aterramento (p.u.)"
+
+#: base/ElementFormBase.cpp:716
+msgid "Grounded neutral"
+msgstr "Neutro aterrado"
+
+#: base/ElementFormBase.cpp:801
+msgid "Plot synchronous machine data"
+msgstr "Imprimir dados da máquina síncrona"
+
+#: base/ElementFormBase.cpp:814
+msgid "Inertia (H)"
+msgstr "Inércia (H)"
+
+#: base/ElementFormBase.cpp:837
+msgid "Damping factor"
+msgstr "Fator de amortecimento"
+
+#: base/ElementFormBase.cpp:860
+msgid "Use AVR"
+msgstr "Utilizar AVR"
+
+#: base/ElementFormBase.cpp:865
+msgid "Edit AVR"
+msgstr "Editar AVR"
+
+#: base/ElementFormBase.cpp:873
+msgid "Use speed governor"
+msgstr "Utilizar regulador de velocidade"
+
+#: base/ElementFormBase.cpp:878
+msgid "Edit speed governor"
+msgstr "Editar regulador de velocidade"
+
+#: base/ElementFormBase.cpp:894
+msgid "Armature resistance (Ra)"
+msgstr "Resistência de armadura (Ra)"
+
+#: base/ElementFormBase.cpp:917
+msgid "Potier reactance (Xp)"
+msgstr "Reatância de Potier (Xp)"
+
+#: base/ElementFormBase.cpp:940
+msgid "Saturation factor"
+msgstr "Fator de saturação"
+
+#: base/ElementFormBase.cpp:959
+msgid "Syncronous"
+msgstr "Síncrono"
+
+#: base/ElementFormBase.cpp:971
+msgid "Direct-axis reactance (Xd)"
+msgstr "Reatância de eixo direto (Xd)"
+
+#: base/ElementFormBase.cpp:994
+msgid "Quadrature-axis reactance (Xq)"
+msgstr "Reatância de eixo em quadratura (Xq)"
+
+#: base/ElementFormBase.cpp:1013
+msgid "Transient"
+msgstr "Tansitório"
+
+#: base/ElementFormBase.cpp:1025
+msgid "Direct-axis reactance (X'd)"
+msgstr "Reatância de eixo direto (X'd)"
+
+#: base/ElementFormBase.cpp:1048
+msgid "Quadrature-axis reactance (X'q)"
+msgstr "Reatância de eixo em quadratura (X'q)"
+
+#: base/ElementFormBase.cpp:1071
+msgid "Direct-axis time constant (T'd0)"
+msgstr "Constante de tempo de eixo direto (T'd0)"
+
+#: base/ElementFormBase.cpp:1094
+msgid "Quadrature-axis time constant (T'q0)"
+msgstr "Constante de tempo de eixo em quadratura (T'd0)"
+
+#: base/ElementFormBase.cpp:1113
+msgid "Sub-transient"
+msgstr "Subtransitório"
+
+#: base/ElementFormBase.cpp:1125
+msgid "Direct-axis reactance (X''d)"
+msgstr "Reatância de eixo direto (X''d)"
+
+#: base/ElementFormBase.cpp:1148
+msgid "Quadrature-axis reactance (X''q)"
+msgstr "Reatância de eixo em quadratura (X''q)"
+
+#: base/ElementFormBase.cpp:1171
+msgid "Direct-axis time constant (T''d0)"
+msgstr "Constante de tempo de eixo direto (T''d0)"
+
+#: base/ElementFormBase.cpp:1194
+msgid "Quadrature-axis time constant (T''q0)"
+msgstr "Constante de tempo de eixo em quadratura (T''d0)"
+
+#: base/ElementFormBase.cpp:1229 base/ElementFormBase.cpp:2276
+#: base/ElementFormBase.h:712
+msgid "Switching"
+msgstr "Chaveamento"
+
+#: base/ElementFormBase.cpp:1331
+msgid "138 kV"
+msgstr "138 kV"
+
+#: base/ElementFormBase.cpp:1370 base/ElementFormBase.cpp:1701
+msgid "Resistance (R)"
+msgstr "Resistência (R)"
+
+#: base/ElementFormBase.cpp:1398 base/ElementFormBase.cpp:1728
+msgid "Indutive reactance (XL)"
+msgstr "Reatância indutiva (Xl)"
+
+#: base/ElementFormBase.cpp:1426
+msgid "Capacitive susceptance (B)"
+msgstr "Susceptância capacitiva (B)"
+
+#: base/ElementFormBase.cpp:1454
+msgid "Line size"
+msgstr "Comprimento da linha"
+
+#: base/ElementFormBase.cpp:1469
+msgid "km"
+msgstr "km"
+
+#: base/ElementFormBase.cpp:1473
+msgid "Use line rated power as base"
+msgstr "Utilizar a potência nominal como base"
+
+#: base/ElementFormBase.cpp:1484 base/ElementFormBase.cpp:1831
+msgid "Zero-sequence impedances (p.u.)"
+msgstr "Impedâncias de sequência zero (p.u.)"
+
+#: base/ElementFormBase.cpp:1496 base/ElementFormBase.cpp:1843
+msgid "Resistance (R0)"
+msgstr "Resistência (R0)"
+
+#: base/ElementFormBase.cpp:1511 base/ElementFormBase.cpp:1858
+msgid "Indutive reactance (X0)"
+msgstr "Reatância indutiva (X0)"
+
+#: base/ElementFormBase.cpp:1526
+msgid "Capacitive susceptance (B0)"
+msgstr "Susceptância capacitiva (B0)"
+
+#: base/ElementFormBase.cpp:1644
+msgid "138 kV / 138 kV"
+msgstr "138 kV / 138 kV"
+
+#: base/ElementFormBase.cpp:1655
+msgid "Base voltage"
+msgstr "Tensão base"
+
+#: base/ElementFormBase.cpp:1759
+msgid "Connection"
+msgstr "Conexão"
+
+#: base/ElementFormBase.cpp:1786
+msgid "Turns ratio"
+msgstr "TAP"
+
+#: base/ElementFormBase.cpp:1801
+msgid "Phase shift"
+msgstr "Defasagem"
+
+#: base/ElementFormBase.cpp:1816
+msgid "degrees"
+msgstr "graus"
+
+#: base/ElementFormBase.cpp:1820
+msgid "Use transformer rated power as base"
+msgstr "Utilizar a potência do transformador como base"
+
+#: base/ElementFormBase.cpp:1869
+msgid "Ground impedances (p.u.)"
+msgstr "Impedância de aterramento (p.u.)"
+
+#: base/ElementFormBase.cpp:1881
+msgid "Primary resistance"
+msgstr "Resistência do primário"
+
+#: base/ElementFormBase.cpp:1896
+msgid "Primary reactance"
+msgstr "Reatância do primário"
+
+#: base/ElementFormBase.cpp:1911
+msgid "Secondary resistance"
+msgstr "Resistência do secundário"
+
+#: base/ElementFormBase.cpp:1926
+msgid "Secondary reactance"
+msgstr "Reatância do secundário"
+
+#: base/ElementFormBase.cpp:2094
+msgid "Load type (power flow)"
+msgstr "Tipo de carga (fluxo de carga)"
+
+#: base/ElementFormBase.cpp:2112
+msgid "Plot load data"
+msgstr "Imprimir dados da carga"
+
+#: base/ElementFormBase.cpp:2117
+msgid "Use ZIP load composition"
+msgstr "Utilizar composição de carga ZIP"
+
+#: base/ElementFormBase.cpp:2134 base/ElementFormBase.cpp:2207
+#: base/PropertiesFormBase.cpp:437 base/PropertiesFormBase.cpp:510
+msgid "Constant impedance"
+msgstr "Impedância constante"
+
+#: base/ElementFormBase.cpp:2149 base/ElementFormBase.cpp:2172
+#: base/ElementFormBase.cpp:2195 base/ElementFormBase.cpp:2222
+#: base/ElementFormBase.cpp:2245 base/ElementFormBase.cpp:2268
+#: base/PropertiesFormBase.cpp:452 base/PropertiesFormBase.cpp:475
+#: base/PropertiesFormBase.cpp:498 base/PropertiesFormBase.cpp:525
+#: base/PropertiesFormBase.cpp:548 base/PropertiesFormBase.cpp:571
+#: base/PropertiesFormBase.cpp:602 base/PropertiesFormBase.cpp:625
+msgid "%"
+msgstr "%"
+
+#: base/ElementFormBase.cpp:2157 base/ElementFormBase.cpp:2230
+#: base/PropertiesFormBase.cpp:460 base/PropertiesFormBase.cpp:533
+#: base/PropertiesFormBase.cpp:587
+msgid "Constant current"
+msgstr "Corrente constante"
+
+#: base/ElementFormBase.cpp:2180 base/ElementFormBase.cpp:2253
+#: base/PropertiesFormBase.cpp:483 base/PropertiesFormBase.cpp:556
+#: base/PropertiesFormBase.cpp:610
+msgid "Constant power"
+msgstr "Potência constante"
+
+#: base/ElementFormBase.cpp:2490
+msgid "Switching properties"
+msgstr "Propriedades de chaveamento"
+
+#: base/ElementFormBase.cpp:2508
+msgid "Add"
+msgstr "Adicionar"
+
+#: base/ElementFormBase.cpp:2520
+msgid "Down"
+msgstr "Baixo"
+
+#: base/ElementFormBase.cpp:2528
+msgid "Switching list"
+msgstr "Lista de chaveamento"
+
+#: base/ElementFormBase.cpp:2779
+msgid "Element"
+msgstr "Elemento"
+
+#: base/ElementFormBase.cpp:2801
+msgid "Element name"
+msgstr "Nome do elemento"
+
+#: base/ElementFormBase.cpp:2814
+msgid "Text type"
+msgstr "Tipo de texto"
+
+#: base/ElementFormBase.cpp:2827
+msgid "From bus"
+msgstr "Da barra"
+
+#: base/ElementFormBase.cpp:2840
+msgid "To bus"
+msgstr "Para barra"
+
+#: base/ElementFormBase.cpp:2853
+msgid "Unit"
+msgstr "Unidade"
+
+#: base/ElementFormBase.cpp:2866
+msgid "Decimal places:"
+msgstr "Casas decimais:"
+
+#: base/ElementFormBase.cpp:2879
+msgid "Preview:"
+msgstr "Pré-visualização:"
+
+#: base/ElementFormBase.cpp:2981
+msgid "Numerator parameters"
+msgstr "Parâmetros do numerador"
+
+#: base/ElementFormBase.cpp:2993
+msgid "Denominator parameters"
+msgstr "Parâmetros do denominador"
+
+#: base/ElementFormBase.cpp:3082
+msgid "Signs"
+msgstr "Sinais"
+
+#: base/ElementFormBase.cpp:3171 base/ElementFormBase.cpp:3272
+msgid "Upper limit"
+msgstr "Limite superior"
+
+#: base/ElementFormBase.cpp:3183 base/ElementFormBase.cpp:3284
+msgid "Lower limit"
+msgstr "Limite inferior"
+
+#: base/ElementFormBase.cpp:3373
+msgid "y = A.eB.x"
+msgstr "y = A.eB.x"
+
+#: base/ElementFormBase.cpp:3377
+msgid "A value"
+msgstr "Valor A"
+
+#: base/ElementFormBase.cpp:3389
+msgid "B value"
+msgstr "Valor B"
+
+#: base/ElementFormBase.cpp:3478
+msgid "Constant value"
+msgstr "Valor da constante"
+
+#: base/ElementFormBase.cpp:3567
+msgid "Gain value"
+msgstr "Valor do ganho"
+
+#: base/ElementFormBase.cpp:3757
+msgid "Input variables (space separated)"
+msgstr "Variáveis de entrada (separadas por espaço)"
+
+#: base/ElementFormBase.cpp:3821
+msgid "No checks performed"
+msgstr "Nenhuma verificação realizada"
+
+#: base/ElementFormBase.cpp:3829
+msgid "Check expression"
+msgstr "Verificar expressão"
+
+#: base/ElementFormBase.h:370
+msgid "Generator: Stability"
+msgstr "Gerador: Estabilidade"
+
+#: base/ElementFormBase.h:671
+msgid "Reactive shunt element"
+msgstr "Elemento shunt reativo"
+
+#: base/ElementFormBase.h:753
+msgid "Motor"
+msgstr "Motor"
+
+#: base/ElementFormBase.h:844
+msgid "Transfer function"
+msgstr "Função transferência"
+
+#: base/ElementFormBase.h:1046
+msgid "Input / Output"
+msgstr "Entrada / Saída"
+
+#: base/ElementFormBase.h:1082
+msgid "Math expression"
+msgstr "Expressão matemática"
+
+#: base/MainFrameBase.cpp:76 base/MainFrameBase.cpp:77
+#: base/MainFrameBase.cpp:80
+msgid "Projects"
+msgstr "Projetos"
+
+#: base/MainFrameBase.cpp:82
+msgid "Create new project"
+msgstr "Criar novo projeto"
+
+#: base/MainFrameBase.cpp:84
+msgid "Open"
+msgstr "Abrir"
+
+#: base/MainFrameBase.cpp:84
+msgid "Open saved project"
+msgstr "Abrir projetos salvos"
+
+#: base/MainFrameBase.cpp:86
+msgid "General Settings"
+msgstr "Configurações gerais"
+
+#: base/MainFrameBase.cpp:86
+msgid "Opens a dialog to set the main settings of the program"
+msgstr ""
+"Abre um formulário para definir as principais configurações do programa"
+
+#: base/MainFrameBase.cpp:88
+msgid "Closes the application"
+msgstr "Fecha a aplicação"
+
+#: base/MainFrameBase.cpp:91 base/MainFrameBase.cpp:92
+msgid "Current project"
+msgstr "Projeto atual"
+
+#: base/MainFrameBase.cpp:96
+msgid "Save"
+msgstr "Salvar"
+
+#: base/MainFrameBase.cpp:96
+msgid "Save the current project"
+msgstr "Salvar o projeto atual"
+
+#: base/MainFrameBase.cpp:98
+msgid "Save As..."
+msgstr "Salvar como..."
+
+#: base/MainFrameBase.cpp:98
+msgid "Save as the current project"
+msgstr "Salvar como o projeto atual"
+
+#: base/MainFrameBase.cpp:100
+msgid "Close"
+msgstr "Fechar"
+
+#: base/MainFrameBase.cpp:100
+msgid "Close the current project"
+msgstr "Fechar o projeto atual"
+
+#: base/MainFrameBase.cpp:103 base/MainFrameBase.cpp:104
+#: base/MainFrameBase.cpp:107
+msgid "Help"
+msgstr "Ajuda"
+
+#: base/MainFrameBase.cpp:109
+msgid "PSP-UFU Guide"
+msgstr "Manual do PSP-UFU"
+
+#: base/MainFrameBase.cpp:109
+msgid "Open PSP-UFU Guide"
+msgstr "Abrir o manual do PSP-UFU"
+
+#: base/MainFrameBase.cpp:111
+msgid "About..."
+msgstr "Sobre..."
+
+#: base/MainFrameBase.cpp:111 base/PropertiesFormBase.h:256
+msgid "About PSP-UFU"
+msgstr "Sobre o PSP-UFU"
+
+#: base/MainFrameBase.cpp:114 base/MainFrameBase.cpp:115
+msgid "Tools"
+msgstr "Ferramentas"
+
+#: base/MainFrameBase.cpp:117 base/MainFrameBase.cpp:118
+#: base/MainFrameBase.cpp:121
+msgid "Clipboard"
+msgstr "Ãrea de transferência"
+
+#: base/MainFrameBase.cpp:123
+msgid "Copies the selected elements"
+msgstr "Copia os elementos selecionados"
+
+#: base/MainFrameBase.cpp:125
+msgid "Pastes the elements from clipboard"
+msgstr "Cola os elementos da área de transferência"
+
+#: base/MainFrameBase.cpp:127
+msgid "Undoes the last action"
+msgstr "Desfaz a última ação"
+
+#: base/MainFrameBase.cpp:129
+msgid "Redoes the last undo action"
+msgstr "Refaz a última ação desfeita"
+
+#: base/MainFrameBase.cpp:132 base/MainFrameBase.cpp:133
+#: base/MainFrameBase.cpp:136
+msgid "Circuit"
+msgstr "Circuito"
+
+#: base/MainFrameBase.cpp:138
+msgid "Add Element"
+msgstr "Inserir elemento"
+
+#: base/MainFrameBase.cpp:138
+msgid "Add a new element in the project"
+msgstr "Adicionar um elemento novo no projeto"
+
+#: base/MainFrameBase.cpp:140
+msgid "Drag all the elements"
+msgstr "Arrasta todos os elementos"
+
+#: base/MainFrameBase.cpp:142
+msgid "Move the selected elements"
+msgstr "Move os elementos selecionados"
+
+#: base/MainFrameBase.cpp:144
+msgid "Removes all selected elements"
+msgstr "Remove todos os elementos selecionados"
+
+#: base/MainFrameBase.cpp:146
+msgid "Applies the drag and zoom tools to show all elements in workspace"
+msgstr ""
+"Aplica as ferramentas de arrasto e ampliação para exibir todos os elementos "
+"na área de trabalho"
+
+#: base/MainFrameBase.cpp:148
+msgid "Rotate Clockwise"
+msgstr "Girar Horário"
+
+#: base/MainFrameBase.cpp:150
+msgid "Rotate Counter-clockwise"
+msgstr "Girar anti-horário"
+
+#: base/MainFrameBase.cpp:150
+msgid "Rotate the selected elements counter-clockwise"
+msgstr "Gira os elementos selecionados no sentido anti-horário"
+
+#: base/MainFrameBase.cpp:152
+msgid "Project Settings"
+msgstr "Configurações do projeto"
+
+#: base/MainFrameBase.cpp:152
+msgid "Opens a dialog to set the main settings of the current project"
+msgstr ""
+"Abre uma janela para definir as principais configurações do projeto atual"
+
+#: base/MainFrameBase.cpp:155 base/MainFrameBase.cpp:156
+msgid "Reports"
+msgstr "Relatórios"
+
+#: base/MainFrameBase.cpp:160
+msgid "Data Report"
+msgstr "Relatório de dados"
+
+#: base/MainFrameBase.cpp:160
+msgid "Opens a data report"
+msgstr "Abre um relatório de dados"
+
+#: base/MainFrameBase.cpp:162
+msgid "Charts"
+msgstr "Gráficos"
+
+#: base/MainFrameBase.cpp:162
+msgid "Open the charts"
+msgstr "Abre os gráficos"
+
+#: base/MainFrameBase.cpp:164
+msgid "Snapshot"
+msgstr "Instantâneo"
+
+#: base/MainFrameBase.cpp:164
+msgid "Capture a snapshot of the circuit"
+msgstr "Captura uma imagem instantânea do circuito"
+
+#: base/MainFrameBase.cpp:167 base/MainFrameBase.cpp:168
+msgid "Simulation"
+msgstr "Simulação"
+
+#: base/MainFrameBase.cpp:170 base/MainFrameBase.cpp:171
+msgid "Continuous"
+msgstr "Contínuo"
+
+#: base/MainFrameBase.cpp:175
+msgid "Enable Solution"
+msgstr "Habilitar solução"
+
+#: base/MainFrameBase.cpp:175
+msgid ""
+"Enables the power flow and fault (if exists) calculations after any circuit "
+"change"
+msgstr ""
+"Habilita os cálculos de fluxo de carga e falta (se existir) após qualquer "
+"mudança no circuito"
+
+#: base/MainFrameBase.cpp:177
+msgid "Disable Solution"
+msgstr "Desabilitar solução"
+
+#: base/MainFrameBase.cpp:177
+msgid ""
+"Disables the power flow and fault calculations after any circuit changes"
+msgstr ""
+"Desabilita os cálculos de fluxo de carga e falta após qualquer mudança no "
+"circuito"
+
+#: base/MainFrameBase.cpp:179
+msgid "Reset Voltages"
+msgstr "Reiniciar tensões"
+
+#: base/MainFrameBase.cpp:179
+msgid "Reset all voltages to initial state"
+msgstr "Reinicia todas as tensões para os valores iniciais"
+
+#: base/MainFrameBase.cpp:182 base/MainFrameBase.cpp:183
+#: base/MainFrameBase.cpp:186
+msgid "Simulations"
+msgstr "Simulações"
+
+#: base/MainFrameBase.cpp:188
+msgid "Power Flow"
+msgstr "Fluxo de carga"
+
+#: base/MainFrameBase.cpp:188
+msgid "Calculate the circuit power flow"
+msgstr "Calcula o fluxo de carga do circuito"
+
+#: base/MainFrameBase.cpp:190
+msgid "Run Stability"
+msgstr "Executar estabilidade"
+
+#: base/MainFrameBase.cpp:190
+msgid "Run the stability calculations"
+msgstr "Executa os cálculos de estabilidade"
+
+#: base/MainFrameBase.cpp:192
+msgid "Calculate the circuit fault (if exists)"
+msgstr "Calcula a falta do circuito (se existir)"
+
+#: base/MainFrameBase.cpp:194
+msgid "Short-Circuit Power"
+msgstr "Nível de curto-circuito"
+
+#: base/MainFrameBase.cpp:194
+msgid "Calculate the short-circuit power in all buses"
+msgstr "Calcula o nível de curto-circuito em todas as barras"
+
+#: base/MainFrameBase.cpp:196
+msgid "Simulation Settings"
+msgstr "Configurações de simulação"
+
+#: base/MainFrameBase.cpp:196
+msgid "Opens a dialog to set the settings of the simulations"
+msgstr "Abre um formulário para definir as configurações de simulação"
+
+#: base/MainFrameBase.h:141
+msgid "PSP-UFU"
+msgstr "PSP-UFU"
+
+#: base/PropertiesFormBase.cpp:44
+msgid "Language"
+msgstr "Idioma"
+
+#: base/PropertiesFormBase.cpp:60
+msgid "Theme"
+msgstr "Tema"
+
+#: base/PropertiesFormBase.cpp:153
+msgid "Base power"
+msgstr "Potência base"
+
+#: base/PropertiesFormBase.cpp:177
+msgid "Continuous calculation"
+msgstr "Cálculo contínuo"
+
+#: base/PropertiesFormBase.cpp:181
+msgid "Calculate fault after power flow"
+msgstr "Calcular falta após o fluxo de carga"
+
+#: base/PropertiesFormBase.cpp:186
+msgid "Calculate short-circuit power after power flow"
+msgstr "Calcular o nível de curto-circuito após o fluxo de carga"
+
+#: base/PropertiesFormBase.cpp:201
+msgid "Solution method"
+msgstr "Método de solução"
+
+#: base/PropertiesFormBase.cpp:221
+msgid "Acceleration factor"
+msgstr "Fator de aceleração"
+
+#: base/PropertiesFormBase.cpp:236 base/PropertiesFormBase.cpp:345
+msgid "Tolerance"
+msgstr "Tolerância"
+
+#: base/PropertiesFormBase.cpp:251
+msgid "Max. iterations"
+msgstr "Iterações máx"
+
+#: base/PropertiesFormBase.cpp:322
+msgid "System frequency"
+msgstr "Frequência do sistema"
+
+#: base/PropertiesFormBase.cpp:337
+msgid "Hz"
+msgstr "Hz"
+
+#: base/PropertiesFormBase.cpp:360
+msgid "Max. Iterations"
+msgstr "Iterações máx"
+
+#: base/PropertiesFormBase.cpp:375
+msgid "Controls step ratio"
+msgstr "Razão do passo dos controles"
+
+#: base/PropertiesFormBase.cpp:390
+msgid "Plot time"
+msgstr "Tempo de impressão"
+
+#: base/PropertiesFormBase.cpp:409
+msgid "Use center of inertia as reference"
+msgstr "Utilizar centro de inércia como referência"
+
+#: base/PropertiesFormBase.cpp:415
+msgid "ZIP Load"
+msgstr "Carga ZIP"
+
+#: base/PropertiesFormBase.cpp:420
+msgid "Use general composition to all system loads"
+msgstr "Utilizar composição geral para todas as cargas do sistema"
+
+#: base/PropertiesFormBase.cpp:575
+msgid ""
+"Undervoltage limit which the loads will be modelled by\n"
+"constant impedance:"
+msgstr ""
+"Subtensão a qual as cargas serão modeladas como\n"
+"impedância constante:"
+
+#: base/PropertiesFormBase.cpp:705
+msgid "About"
+msgstr "Sobre"
+
+#: base/PropertiesFormBase.cpp:715
+msgid "Credits"
+msgstr "Créditos"
+
+#: base/PropertiesFormBase.cpp:732
+msgid "License"
+msgstr "Licença"
+
+#: base/PropertiesFormBase.cpp:748
+msgid "Version:"
+msgstr "Versão:"
+
+#: base/PropertiesFormBase.cpp:752
+msgid "Alpha 2017w45a"
+msgstr "Alpha 2017w45a"
+
+#: base/PropertiesFormBase.cpp:756
+msgid "Home page:"
+msgstr "Página Inicial:"
+
+#: base/PropertiesFormBase.cpp:760
+msgid "https://thales1330.github.io/PSP/"
+msgstr "https://thales1330.github.io/PSP/"
+
+#: base/PropertiesFormBase.h:73
+msgid "General settings"
+msgstr "Opções gerais"
+
+#: base/PropertiesFormBase.h:219
+msgid "Simulation settings"
+msgstr "Opções de simulação"
+
+#~ msgid "Syntax error in parameter 'Vars' given to FunctionParser::Parse()"
+#~ msgstr "Erro de sintaxe no parâmetro 'Vars' dado em FunctionParser::Parse()"
+
#~ msgid "Load type"
#~ msgstr "Tipo de carga"
@@ -2840,9 +2949,6 @@ msgstr "Pergunta"
#~ msgid "http://www.ndse.ufu.br/pspufu"
#~ msgstr "http://www.ndse.ufu.br/pspufu"
-#~ msgid "Speed error"
-#~ msgstr "Erro de velocidade"
-
#~ msgid "Number iterations"
#~ msgstr "Número de iterações"
diff --git a/Project/fparser/docs/fparser.html b/Project/fparser/docs/fparser.html
new file mode 100644
index 0000000..eb94d19
--- /dev/null
+++ b/Project/fparser/docs/fparser.html
@@ -0,0 +1,1841 @@
+<!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.2 : Documentation</title>
+</head>
+
+<body>
+<h1>Function Parser for C++ v4.5.2 </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.2
+ <ul>
+ <li>Fixed several optimizer bugs.
+ <li>Fixed compilation problems with Visual Studio 2013 and gcc.
+ </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&nbsp;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&nbsp;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&lt;double&gt;</code>,
+ <code>std::complex&lt;float&gt;</code> and
+ <code>std::complex&lt;long&nbsp;double&gt;</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&amp; Function, const std::string&amp; Vars,
+ bool useDegrees = false);
+
+int Parse(const char* Function, const std::string&amp; 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>&gt;0</code>.
+
+<hr>
+<pre>
+void Optimize();
+</pre>
+
+<p>Tries to optimize the bytecode for faster evaluation.
+
+<hr>
+<pre>
+bool AddConstant(const std::string&amp; 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&amp; 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&amp; 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&amp; name, FunctionParser&amp;);
+</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&amp; 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&amp; function,
+ int* amountOfVariablesFound = 0,
+ bool useDegrees = false);
+int ParseAndDeduceVariables(const std::string&amp; function,
+ std::string&amp; resultVarString,
+ int* amountOfVariablesFound = 0,
+ bool useDegrees = false);
+int ParseAndDeduceVariables(const std::string&amp; function,
+ std::vector&lt;std::string&gt;&amp; 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&amp; Function, const std::string&amp; Vars,
+ bool useDegrees = false);
+
+int Parse(const char* Function, const std::string&amp; 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>'&quot;'</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&amp; 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&amp; 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&amp; 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>&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;&nbsp;&nbsp;&nbsp;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&amp; name, FunctionParser&amp;);
+</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&lt;typename DerivedWrapper&gt;
+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&amp; 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&nbsp;=&nbsp;FunctionParser();</code>")
+
+<hr>
+<a name="longdesc_ParseAndDeduceVariables"></a>
+<pre>
+int ParseAndDeduceVariables(const std::string&amp; function,
+ int* amountOfVariablesFound = 0,
+ bool useDegrees = false);
+int ParseAndDeduceVariables(const std::string&amp; function,
+ std::string&amp; resultVarString,
+ int* amountOfVariablesFound = 0,
+ bool useDegrees = false);
+int ParseAndDeduceVariables(const std::string&amp; function,
+ std::vector&lt;std::string&gt;&amp; 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>&lt;</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>&lt;</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&lt;MyFunctionWrapper*&gt;
+ (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&lt;typename Value_t&gt;
+void someFunction(FunctionParserBase&lt;Value_t&gt& 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&lt;typename Value_t&gt;
+class SpecializedParser: public FunctionParserBase&lt;Value_t&gt;
+{
+ ...
+};
+</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)&nbsp;*&nbsp;x</code>"
+ is not the same thing as "<code>2+5i&nbsp;*&nbsp;x</code>". The latter
+ would be equivalent to "<code>2 + (5i&nbsp;*&nbsp;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&lt;B A&lt;=B<br>A!=B A&gt;B A&gt;=B</code></td>
+ <td>comparison between A and B (result is either 0 or 1)</td>
+ </tr><tr>
+ <td><code>A&amp;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>&gt;</code>" or
+"<code>&lt;</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&gt;B, the result is A, else B.</td>
+</tr><tr>
+ <td><code>min(A,B)</code></td>
+ <td>If A&lt;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>"&lt;variable name&gt; := &lt;expression&gt;; &lt;function&gt;"</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>&lt;function&gt;</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&nbsp;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&nbsp;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>
diff --git a/Project/fparser/docs/gpl.txt b/Project/fparser/docs/gpl.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/Project/fparser/docs/gpl.txt
@@ -0,0 +1,674 @@
+ 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>.
diff --git a/Project/fparser/docs/lgpl.txt b/Project/fparser/docs/lgpl.txt
new file mode 100644
index 0000000..cca7fc2
--- /dev/null
+++ b/Project/fparser/docs/lgpl.txt
@@ -0,0 +1,165 @@
+ 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.
diff --git a/Project/fparser/docs/style.css b/Project/fparser/docs/style.css
new file mode 100644
index 0000000..d5141d3
--- /dev/null
+++ b/Project/fparser/docs/style.css
@@ -0,0 +1,80 @@
+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;
+}
diff --git a/Project/fparser/examples/example.cc b/Project/fparser/examples/example.cc
new file mode 100644
index 0000000..2d6b771
--- /dev/null
+++ b/Project/fparser/examples/example.cc
@@ -0,0 +1,55 @@
+// Simple example file for the function parser
+// ===========================================
+
+/* When running the program, try for example with these values:
+
+f(x) = x^2
+min x: -5
+max x: 5
+step: 1
+
+*/
+
+#include "../fparser.hh"
+
+#include <iostream>
+#include <string>
+
+int main()
+{
+ std::string function;
+ double minx, maxx, step;
+ FunctionParser fparser;
+
+ fparser.AddConstant("pi", 3.1415926535897932);
+
+ while(true)
+ {
+ std::cout << "f(x) = ";
+ std::getline(std::cin, function);
+ if(std::cin.fail()) return 0;
+
+ 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 0;
+
+ double vals[] = { 0 };
+ for(vals[0] = minx; vals[0] <= maxx; vals[0] += step)
+ {
+ std::cout << "f(" << vals[0] << ") = " << fparser.Eval(vals)
+ << std::endl;
+ }
+
+ return 0;
+}
diff --git a/Project/fparser/examples/example2.cc b/Project/fparser/examples/example2.cc
new file mode 100644
index 0000000..958b9a1
--- /dev/null
+++ b/Project/fparser/examples/example2.cc
@@ -0,0 +1,85 @@
+// 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;
+}
diff --git a/Project/fparser/extrasrc/fp_identifier_parser.inc b/Project/fparser/extrasrc/fp_identifier_parser.inc
new file mode 100644
index 0000000..7489fd0
--- /dev/null
+++ b/Project/fparser/extrasrc/fp_identifier_parser.inc
@@ -0,0 +1,379 @@
+/* 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;
diff --git a/Project/fparser/extrasrc/fp_opcode_add.inc b/Project/fparser/extrasrc/fp_opcode_add.inc
new file mode 100644
index 0000000..331ef49
--- /dev/null
+++ b/Project/fparser/extrasrc/fp_opcode_add.inc
@@ -0,0 +1,7696 @@
+/* Function Parser for C++ v4.5.2
+
+ 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
diff --git a/Project/fparser/extrasrc/fpaux.hh b/Project/fparser/extrasrc/fpaux.hh
new file mode 100644
index 0000000..f035c33
--- /dev/null
+++ b/Project/fparser/extrasrc/fpaux.hh
@@ -0,0 +1,1249 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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); }
+
+ template<typename Value_t>
+ inline std::complex<Value_t> fp_hypot
+ (const std::complex<Value_t>& x, const std::complex<Value_t>& y)
+ { return fp_sqrt(x*x + y*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); }
+
+ template<typename Value_t>
+ inline std::complex<Value_t> fp_log2(const std::complex<Value_t>& x)
+ {
+ return fp_log(x) * fp_const_log2inv<Value_t>();
+ }
+#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_
diff --git a/Project/fparser/extrasrc/fptypes.hh b/Project/fparser/extrasrc/fptypes.hh
new file mode 100644
index 0000000..ea28cbc
--- /dev/null
+++ b/Project/fparser/extrasrc/fptypes.hh
@@ -0,0 +1,286 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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];
+#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
diff --git a/Project/fparser/fparser.cc b/Project/fparser/fparser.cc
new file mode 100644
index 0000000..5e77ba5
--- /dev/null
+++ b/Project/fparser/fparser.cc
@@ -0,0 +1,3800 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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
diff --git a/Project/fparser/fparser.hh b/Project/fparser/fparser.hh
new file mode 100644
index 0000000..7033a8d
--- /dev/null
+++ b/Project/fparser/fparser.hh
@@ -0,0 +1,223 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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
diff --git a/Project/fparser/fparser_gmpint.hh b/Project/fparser/fparser_gmpint.hh
new file mode 100644
index 0000000..d9d3b5f
--- /dev/null
+++ b/Project/fparser/fparser_gmpint.hh
@@ -0,0 +1,15 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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
diff --git a/Project/fparser/fparser_mpfr.hh b/Project/fparser/fparser_mpfr.hh
new file mode 100644
index 0000000..322b05d
--- /dev/null
+++ b/Project/fparser/fparser_mpfr.hh
@@ -0,0 +1,15 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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
diff --git a/Project/fparser/fpconfig.hh b/Project/fparser/fpconfig.hh
new file mode 100644
index 0000000..17e6c7d
--- /dev/null
+++ b/Project/fparser/fpconfig.hh
@@ -0,0 +1,88 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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
diff --git a/Project/fparser/fpoptimizer.cc b/Project/fparser/fpoptimizer.cc
new file mode 100644
index 0000000..26113c7
--- /dev/null
+++ b/Project/fparser/fpoptimizer.cc
@@ -0,0 +1,11763 @@
+/***************************************************************************\
+|* Function Parser for C++ v4.5.2 *|
+|*-------------------------------------------------------------------------*|
+|* 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 "fpconfig.hh"
+#ifdef FP_SUPPORT_OPTIMIZER
+#include "fparser.hh"
+#include "extrasrc/fptypes.hh"
+#include "extrasrc/fpaux.hh"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#define tO3 ;typedef
+#define tN3 (xP1 a)
+#define tM3 :sim i61
+#define tL3 },{{1,
+#define tK3 :if(tO2
+#define tJ3 xP1 a),
+#define tI3 {data->
+#define tH3 nW 0,
+#define tG3 {tree.x6
+#define tF3 "Found "
+#define tE3 ;for lR1
+#define tD3 stackpos
+#define tC3 .GetOpcode
+#define tB3 "dup(%u) "
+#define tA3 "%d, cost "
+#define t93 "PUSH " yR2
+#define t83 ::cout<<eZ3
+#define t73 "immed "<<
+#define t63 mFuncParsers
+#define t53 cV2{assert
+#define t43 stderr
+#define t33 sep2=" "
+#define t23 FPHASH_CONST
+#define t13 cache_needed[
+#define t03 fprintf
+#define eZ3 "Applying "
+#define eY3 FUNCTIONPARSER_INSTANTIATE_OPTIMIZE
+#define eX3 FUNCTIONPARSER_INSTANTIATE_EMPTY_OPTIMIZE
+#define eW3 HANDLE_UNARY_CONST_FUNC
+#define eV3 ,l1 0x7
+#define eU3 within,
+#define eT3 c_count
+#define eS3 s_count
+#define eR3 tI2 xT1
+#define eQ3 2)lT 2*
+#define eP3 );break
+#define eO3 ].swap(
+#define eN3 else{if(
+#define eM3 b.Value)
+#define eL3 b.Opcode
+#define eK3 FP_GetOpcodeName
+#define eJ3 =synth.
+#define eI3 codes[b
+#define eH3 whydump
+#define eG3 nparams
+#define eF3 450998,
+#define eE3 cHypot,
+#define eD3 cExp nW
+#define eC3 cAbs nW
+#define eB3 )&&p nV
+#define eA3 eO;case
+#define e93 :tree
+#define e83 false;}
+#define e73 l41 y6.
+#define e63 cAbsIf)
+#define e53 ){case
+#define e43 tQ nF==
+#define e33 =true;yH1
+#define e23 =false;
+#define e13 params
+#define e03 ].first
+#define cZ3 Ne_Mask
+#define cY3 Gt_Mask
+#define cX3 Lt_Mask
+#define cW3 opcode,
+#define cV3 public:
+#define cU3 *xB lQ1
+#define cT3 pclone
+#define cS3 info.
+#define cR3 --cU1.
+#define cQ3 eK2 2,
+#define cP3 eK2 1,
+#define cO3 cOr,l6
+#define cN3 switch nR1
+#define cM3 xG p2;p2
+#define cL3 if(op1==
+#define cK3 (tree)!=
+#define cJ3 TreeCountItem
+#define cI3 ){if(
+#define cH3 newpow
+#define cG3 tX2 lU1
+#define cF3 &&p e32
+#define cE3 )))eO lI
+#define cD3 if(xW)&&
+#define cC3 xP1 2)
+#define cB3 change
+#define cA3 133,2,
+#define c93 Needs
+#define c83 byteCode
+#define c73 nT2 a eF
+#define c63 lP1 nF==
+#define c53 factor_t
+#define c43 y7 tmp2)
+#define c33 value1
+#define c23 a));if(!
+#define c13 tM nD lD
+#define c03 cAbsNot
+#define yZ3 ::ByteCodeSynth yB
+#define yY3 break;}
+#define yX3 }switch
+#define yW3 stackptr
+#define yV3 cPow);lD
+#define yU3 .empty()
+#define yT3 cMul);xN
+#define yS3 opcodes
+#define yR3 did_muli
+#define yQ3 c4 data.
+#define yP3 &Value){
+#define yO3 yK const
+#define yN3 yY3}
+#define yM3 used[b]
+#define yL3 if(a>0){
+#define yK3 :if((i42
+#define yJ3 :{lW1 r=
+#define yI3 sizeof(
+#define yH3 cLess c9
+#define yG3 ,cExp2 nW
+#define yF3 lK 2},0,
+#define yE3 ::string
+#define yD3 return p
+#define yC3 ;}return
+#define yB3 Others
+#define yA3 param.
+#define y93 .first.
+#define y83 (yA3
+#define y73 break;yX3(
+#define y63 &param=*
+#define y53 );tmp2.n7
+#define y43 nF==cLog2&&
+#define y33 nF==cPow&&tU
+#define y23 if(xW nR
+#define y13 default:
+#define y03 x83 size()
+#define xZ3 ].data);
+#define xY3 tL));x0
+#define xX3 Ge0Lt1
+#define xW3 Gt0Le1
+#define xV3 =fp_pow(
+#define xU3 ==cOr)l9
+#define xT3 cAdd l02
+#define xS3 x62 0;b<
+#define xR3 iterator
+#define xQ3 begin();
+#define xP3 TreeSet
+#define xO3 parent
+#define xN3 insert(i
+#define xM3 newrel
+#define xL3 IsNever
+#define xK3 b_needed
+#define xJ3 cachepos
+#define xI3 half&64)
+#define xH3 half=
+#define xG3 1 y8 lX1
+#define xF3 FindPos(
+#define xE3 src_pos
+#define xD3 reserve(
+#define xC3 tree.GetHash()
+#define xB3 iT1 tree
+#define xA3 ){pow.l41
+#define x93 Params[a]
+#define x83 Params.
+#define x73 yD void
+#define x63 treeptr
+#define x53 .resize(
+#define x43 yL1 xG>&
+#define x33 t81 void
+#define x23 ImmedTag
+#define x13 yD class
+#define x03 ),child);
+#define nZ3 tmp.n7 0))
+#define nY3 ));tmp c4
+#define nX3 a,const
+#define nW3 RefCount
+#define nV3 Birth();
+#define nU3 exponent
+#define nT3 result
+#define nS3 cost_t
+#define nR3 fpdata
+#define nQ3 middle
+#define nP3 ifdata
+#define nO3 };enum
+#define nN3 );eE t71
+#define nM3 cLog2by);
+#define nL3 sqrt_cost
+#define nK3 const int
+#define nJ3 mul_count
+#define nI3 maxValue1
+#define nH3 minValue1
+#define nG3 maxValue0
+#define nF3 minValue0
+#define nE3 ValueType
+#define nD3 );}yD bool
+#define nC3 xC lU 2,
+#define nB3 const std::eQ
+#define nA3 const char*
+#define n93 x31 a-->0;)if(
+#define n83 ContainsOtherCandidates
+#define n73 ;if(half
+#define n63 ;}void
+#define n53 ,l62(1))){
+#define n43 ,const e3&
+#define n33 )n63
+#define n23 1),l62(1));
+#define n13 nT3 t6
+#define n03 nT3 eY
+#define lZ3 nT3 cT1
+#define lY3 n03 e23 if(
+#define lX3 nT3 nV
+#define lW3 nT3 e32
+#define lV3 yB nT3
+#define lU3 yI n2 0),
+#define lT3 abs_mul
+#define lS3 l8 a));
+#define lR3 pos_set
+#define lQ3 e61);}if(
+#define lP3 Rehash(iB
+#define lO3 cM ifp2);
+#define lN3 sim.x3 1,
+#define lM3 [funcno].
+#define lL3 eE1[++IP]
+#define lK3 eE1[IP]==
+#define lJ3 subtree
+#define lI3 invtree
+#define lH3 MakeHash(
+#define lG3 rulenumit
+#define lF3 (cond yY
+#define lE3 ))break;l62
+#define lD3 ;}static yE1
+#define lC3 {std::cout<<
+#define lB3 a<tree.xD
+#define lA3 cAnd,l6
+#define l93 if y83
+#define l83 (tree nF)
+#define l73 MakeEqual
+#define l63 n61,l4::
+#define l53 n61,{l4::
+#define l43 newbase
+#define l33 branch1op
+#define l23 branch2op
+#define l13 overlap
+#define l03 truth_b
+#define iZ2 truth_a
+#define iY2 found_dup
+#define iX2 cY1 xG&
+#define iW2 nQ r;r c4
+#define iV2 rangeutil
+#define iU2 Plan_Has(
+#define iT2 StackMax)
+#define iS2 const nV2
+#define iR2 namespace
+#define iQ2 ::res,b8<
+#define iP2 inverted
+#define iO2 xL3:
+#define iN2 .known&&
+#define iM2 iftree
+#define iL2 depcodes
+#define iK2 explicit
+#define iJ2 cPow,l2 0,2,
+#define iI2 cPow,xK1
+#define iH2 ,{ReplaceParams,
+#define iG2 ,eB2 7168
+#define iF2 cCosh nW
+#define iE2 VarBegin
+#define iD2 .Become(
+#define iC2 begin(),
+#define iB2 cond_add
+#define iA2 cond_mul
+#define i92 cond_and
+#define i82 mulgroup
+#define i72 leaf1
+#define i62 );synth
+#define i52 ,cEqual
+#define i42 cU3.get()){
+#define i32 )lT 3*3*
+#define i22 Optimize()
+#define i12 costree
+#define i02 sintree
+#define tZ2 leaf_count
+#define tY2 sub_params
+#define tX2 nT3.
+#define tW2 printf(
+#define tV2 swap(tmp);
+#define tU2 cbrt_count
+#define tT2 sqrt_count
+#define tS2 PlusInf
+#define tR2 Finite
+#define tQ2 (lW3
+#define tP2 tI2 n2 0),
+#define tO2 xW)){l62 tmp=
+#define tN2 l62(0.0 nR
+#define tM2 p1 cM ifp1
+#define tL2 pcall_tree
+#define tK2 after_powi
+#define tJ2 ))return
+#define tI2 );m.max.
+#define tH2 ;a<t7;++a)
+#define tG2 else{xB=new
+#define tF2 yS e83
+#define tE2 e13)
+#define tD2 grammar
+#define tC2 ,cGreater
+#define tB2 ,lB 0x12 nM
+#define tA2 cLog nW
+#define t92 0x12},{{3,
+#define t82 cNeg,lU 1,
+#define t72 ),0},{
+#define t62 .data.get(
+#define t52 data;data.
+#define t42 MakeNEqual
+#define t32 xP1 1)
+#define t22 Dump(std::
+#define t12 isInteger(
+#define t02 Comparison
+#define eZ2 ,bool abs)
+#define eY2 needs_flip
+#define eX2 (half&63)-1;
+#define eW2 value]
+#define eV2 x71 xR+1);
+#define eU2 Rule&rule,
+#define eT2 cM tree);
+#define eS2 mul_item
+#define eR2 innersub
+#define eQ2 cbrt_cost
+#define eP2 best_cost
+#define eO2 condition
+#define eN2 per_item
+#define eM2 item_type
+#define eL2 first2
+#define eK2 ,l7 0,
+#define eJ2 yI known
+#define eI2 ,o);o<<"\n";
+#define eH2 info=(*xB)[
+#define eG2 cU3=r.specs;if(r.found){
+#define eF2 cU3,info
+#define eE2 *)start_at.get();
+#define eD2 l3 18,1,
+#define eC2 cIf,eV 3,
+#define eB2 l0 2,
+#define eA2 lK 1},0,
+#define e92 .what nL1
+#define e82 tree))cN
+#define e72 ;std::vector<
+#define e62 )x02.second
+#define e52 );range.x22
+#define e42 (lS,tM)nD lD
+#define e32 .min.val
+#define e22 Decision
+#define e12 ;tree y7
+#define e02 not_tree
+#define cZ2 group_by
+#define cY2 nU3=
+#define cX2 (std::move(
+#define cW2 ->second
+#define cV2 xG&tree)
+#define cU2 targetpos
+#define cT2 eO true;}
+#define cS2 ParamSpec
+#define cR2 rhs.hash2;}
+#define cQ2 rhs.hash1
+#define cP2 struct
+#define cO2 Forget()
+#define cN2 &&cond eH))
+#define cM2 source_tree
+#define cL2 <tH,nS3>
+#define cK2 p1_evenness
+#define cJ2 isNegative(
+#define cI2 (yI val
+#define cH2 ,std::cout)
+#define cG2 neg_set
+#define cF2 cNop,cNop}}
+#define cE2 cTanh,cNop,
+#define cD2 >cP2 cG<
+#define cC2 matches
+#define cB2 .match_tree
+#define cA2 (rule,tree,info
+#define c92 cY1 void*)&
+#define c82 cGreater c9
+#define c72 l5 0,1,
+#define c62 ,cTan nW
+#define c52 .xU 2)xX cPow)
+#define c42 cCos nW
+#define c32 {data xE lO
+#define c22 +=1 eO n21;
+#define c12 negated
+#define c02 iC,1,iZ+1);
+#define yZ2 Specializer
+#define yY2 coshtree
+#define yX2 sinhtree
+#define yW2 best_score
+#define yV2 mulvalue
+#define yU2 pow_item
+#define yT2 );t9=!t9;}
+#define yS2 .push_back(
+#define yR2 ;DumpTree(
+#define yQ2 eB[c i1
+#define yP2 .IsImmed(
+#define yO2 1)yP2)
+#define yN2 PowiResult
+#define yM2 maxValue
+#define yL2 minValue
+#define yK2 fp_min(yH,
+#define yJ2 yI set(fp_floor
+#define yI2 fp_max(yH)
+#define yH2 div_tree
+#define yG2 pow_tree
+#define yF2 preserve
+#define yE2 xP1 a).xE1
+#define yD2 cLog);sim.xU
+#define yC2 PullResult()
+#define yB2 dup_or_fetch
+#define yA2 nominator]
+#define y92 test_order
+#define y82 TopLevel)
+#define y72 ].info=info;
+#define y62 ):start_at()
+#define y52 .param_count
+#define y42 minimum_need
+#define y32 shift(index)
+#define y22 ,tree xA
+#define y12 rulenumber
+#define y02 cLessOrEq c9
+#define xZ2 cTan l3 2,1,
+#define xY2 cLog l3 2,1,
+#define xX2 cTanh nW
+#define xW2 ,cSinh nW
+#define xV2 cInv,lU 1,
+#define xU2 constraints=
+#define xT2 GetDepth()
+#define xS2 factor_immed
+#define xR2 changes
+#define xQ2 n11 cM y6 l8
+#define xP2 cM cond l8
+#define xO2 ,cGreaterOrEq
+#define xN2 l8 0));
+#define xM2 y7 mul);
+#define xL2 for(typename
+#define xK2 exp_diff
+#define xJ2 ExponentInfo
+#define xI2 lower_bound(
+#define xH2 factor
+#define xG2 is_logical
+#define xF2 newrel_and
+#define xE2 ;iC.Remember(
+#define xD2 eO Unknown;}
+#define xC2 res_stackpos
+#define xB2 half_pos
+#define xA2 ){half&=127;
+#define x92 {e3 start_at;
+#define x82 i52,eB2
+#define x72 (size_t
+#define x62 for x72 b=
+#define x52 >>1)):(
+#define x42 CodeTreeData
+#define x32 nU3)
+#define x22 multiply(
+#define x12 var_trees
+#define x02 parampair
+#define nZ2 ,cPow,l2 2,2,
+#define nY2 ,nM2 2,1,
+#define nX2 std::vector<xG>
+#define nW2 nE OPCODE
+#define nV2 CodeTree&
+#define nU2 parent_opcode
+#define nT2 =GetParam(
+#define nS2 changed=true;
+#define nR2 log2_exponent
+#define nQ2 tmp y7 tree);
+#define nP2 nQ tmp;tmp c4
+#define nO2 dup_fetch_pos
+#define nN2 xL3 c5 lD
+#define nM2 cPow l3
+#define nL2 cSin nW
+#define nK2 Value_EvenInt
+#define nJ2 MakeFalse,{l4
+#define nI2 if(y2 l8 a)xI
+#define nH2 AddCollection
+#define nG2 ConditionType
+#define nF2 DUP_ONE(apos)
+#define nE2 ,0,0x4 tL3
+#define nD2 (unsigned
+#define nC2 cY|nD2)
+#define nB2 SpecialOpcode
+#define nA2 sim.Eat(1,
+#define n92 ;sim.Push(
+#define n82 c4 tree nF);
+#define n72 for x72 a=
+#define n62 .UseGetNeeded(
+#define n52 ));TriTruthValue
+#define n42 synth.AddOperation(
+#define n32 ,eR,synth);
+#define n22 =i cW2.
+#define n12 IsDefined()
+#define n02 .GetHash().
+#define lZ2 assimilated
+#define lY2 );sim.x3 2,
+#define lX2 denominator
+#define lW2 fraction
+#define lV2 DUP_BOTH();
+#define lU2 template lM
+#define lT2 -1-offset].
+#define lS2 if(synth.Find(
+#define lR2 IsDescendantOf
+#define lQ2 TreeCounts
+#define lP2 ;tree.DelParam(
+#define lO2 IsImmed()cI3
+#define lN2 bool t9 e23
+#define lM2 SetOpcode(
+#define lL2 found_log2
+#define lK2 div_params
+#define lJ2 immed_sum
+#define lI2 OPCODE(opcode)
+#define lH2 break;nT3*=
+#define lG2 FactorStack yB
+#define lF2 Rehash(false);
+#define lE2 IsAlways c5 lD
+#define lD2 282870 x9
+#define lC2 cNotNot nW
+#define lB2 replacing_slot
+#define lA2 RefParams
+#define l92 if_always[
+#define l82 WhatDoWhenCase
+#define l72 exponent_immed
+#define l62 Value_t
+#define l52 );x0 l4::
+#define l42 GetOpcode())
+#define l32 );goto do_return;
+#define l22 {if(GetOpcode()
+#define l12 CollectionSet yB
+#define l02 ||op1==
+#define iZ1 yF DelParams()
+#define iY1 .SetParamsMove(
+#define iX1 data[a].second
+#define iW1 if(newrel_or==
+#define iV1 eA 2,131,
+#define iU1 Immed.size());
+#define iT1 const xG&
+#define iS1 OptimizedUsing
+#define iR1 Var_or_Funcno
+#define iQ1 iR1;
+#define iP1 GetParams(
+#define iO1 crc32_t
+#define iN1 signed_chain
+#define iM1 MinusInf
+#define iL1 n_immeds
+#define iK1 stack.size()
+#define iJ1 std::cout<<"POP "
+#define iI1 FindClone(xN
+#define iH1 needs_rehash
+#define iG1 AnyWhere_Rec
+#define iF1 ~unsigned(0)
+#define iE1 41,42,43,44,
+#define iD1 p1_logical_b
+#define iC1 p0_logical_b
+#define iB1 p1_logical_a
+#define iA1 p0_logical_a
+#define i91 divgroup
+#define i81 else if(
+#define i71 {case IsAlways:
+#define i61 .xU l62(
+#define i51 ,l5 2,1,
+#define i41 ,1,2,1,4,1,2,
+#define i31 }break cT1
+#define i21 tree nF==
+#define i11 func(val);nJ1
+#define i01 *const func)
+#define tZ1 synth.DoDup(
+#define tY1 cache_needed
+#define tX1 eA 2,1,eA 2,
+#define tW1 [nP3.ofs+
+#define tV1 treelist
+#define tU1 has_bad_balance
+#define tT1 c53 xH2
+#define tS1 fp_abs(max.val))
+#define tR1 )eO m cT1
+#define tQ1 fp_abs(min.val)
+#define tP1 cNEqual
+#define tO1 tP 2},0,0x0},{{
+#define tN1 Oneness_NotOne|
+#define tM1 Value_IsInteger
+#define tL1 Constness_Const
+#define tK1 DumpHashesFrom(
+#define tJ1 iS1(
+#define tI1 reltype
+#define tH1 SequenceOpcodes
+#define tG1 sep_list[
+#define tF1 ,l1 0x0},{{3,
+#define tE1 fpExponentIsTooLarge(
+#define tD1 l62(0
+#define tC1 goto fail;}
+#define tB1 ,cNot nW
+#define tA1 l1 0x4 nM
+#define t91 template<
+#define t81 lA2);
+#define t71 subgroup
+#define t61 lQ2.erase(cs_it);
+#define t51 yL1 unsigned>&eE1,size_t&IP,size_t limit,size_t y4
+#define t41 tJ2 true
+#define t31 TreeCountType yB
+#define t21 xG tmp;tmp c4
+#define t11 ;nU3
+#define t01 Value(Value::
+#define eZ1 >(l62(1),
+#define eY1 0.5))xX yV3
+#define eX1 stack[iK1-
+#define eW1 stack yS2
+#define eV1 synth.PushImmed(
+#define eU1 MaxChildDepth
+#define eT1 std::pair<It,It>
+#define eS1 cPow,lB
+#define eR1 Sign_Negative
+#define eQ1 Value_Logical
+#define eP1 new_factor_immed
+#define eO1 base_immed
+#define eN1 public e9,public std::vector<
+#define eM1 .Rehash();
+#define eL1 );y6 eM1 xG
+#define eK1 occurance_pos
+#define eJ1 exponent_hash
+#define eI1 exponent_list
+#define eH1 CollectMulGroup(
+#define eG1 source_set
+#define eF1 nU3,xP3
+#define eE1 ByteCode
+#define eD1 operator
+#define eC1 FindAndDup(tree);
+#define eB1 .yJ l62(2)));
+#define eA1 back().thenbranch
+#define e91 grammar_rules[*r]
+#define e81 ;flipped=!flipped;}
+#define e71 DelParam(a);}
+#define e61 tree.DelParam(a
+#define e51 synth.xH 1
+#define e41 ,iC n32
+#define e31 =comp.AddItem(atree
+#define e21 (long double)
+#define e11 yB())xX cMul);lD
+#define e01 tree yP2)c5
+#define cZ1 ;synth.StackTopIs(
+#define cY1 (const
+#define cX1 cY1 l62&
+#define cW1 >=tD1)
+#define cV1 iR2 FPoptimizer_Optimize
+#define cU1 NeedList
+#define cT1 ;}case
+#define cS1 ,lI2);
+#define cR1 ParamSpec_Extract
+#define cQ1 retry_anyparams_3
+#define cP1 retry_anyparams_2
+#define cO1 needlist_cached_t
+#define cN1 lK 2}nE2
+#define cM1 lK 1}nE2
+#define cL1 CodeTreeImmed yB(
+#define cK1 by_float_exponent
+#define cJ1 fp_equal(nU3
+#define cI1 new_exp
+#define cH1 end()&&i->first==
+#define cG1 return BecomeZero;
+#define cF1 return BecomeOne;
+#define cE1 if(lR.size()<=n0)
+#define cD1 addgroup
+#define cC1 ,PowiCache&iC,
+#define cB1 NewHash.hash1
+#define cA1 ;NewHash.hash2+=
+#define c91 ;eE i82);
+#define c81 found_log2by
+#define c71 nF==c03)
+#define c61 ParsePowiMuli(
+#define c51 iR1)
+#define c41 MakeNotP1,l4::
+#define c31 MakeNotP0,l4::
+#define c21 new_base_immed
+#define c11 branch1_backup
+#define c01 branch2_backup
+#define yZ1 exponent_map
+#define yY1 plain_set
+#define yX1 LightWeight(
+#define yW1 if(value
+#define yV1 goto do_return;}lD
+#define yU1 .GetParamCount()==
+#define yT1 should_regenerate=true;
+#define yS1 should_regenerate,
+#define yR1 Collection
+#define yQ1 RelationshipResult
+#define yP1 Subdivide_Combine(
+#define yO1 long value
+#define yN1 ):e9(),std::vector<
+#define yM1 ByteCodeSynth yB&synth)
+#define yL1 const std::vector<
+#define yK1 )const yS
+#define yJ1 rhs yK1 hash1
+#define yI1 best_sep_factor
+#define yH1 i81!nT3
+#define yG1 &&p nV<l62(
+#define yF1 needlist_cached
+#define yE1 inline unsigned
+#define yD1 cW3 bool pad
+#define yC1 MakesInteger(
+#define yB1 const l62&value
+#define yA1 best_sep_cost
+#define y91 MultiplicationRange
+#define y81 pihalf_limits
+#define y71 n_stacked
+#define y61 AnyParams_Rec
+#define y51 ;tree.SetParam(
+#define y41 continue;
+#define y31 Become(value l8 0))
+#define y21 PositionalParams,0}
+#define y11 always_sincostan
+#define y01 Recheck_RefCount_Div
+#define xZ1 Recheck_RefCount_Mul
+#define xY1 i82.
+#define xX1 i82;i82 c4
+#define xW1 MultiplyAndMakeLong(
+#define xV1 cMul);nZ3;tmp
+#define xU1 covers_plus1
+#define xT1 template set_if<
+#define xS1 if(synth.FindAndDup(
+#define xR1 SynthesizeParam(
+#define xQ1 xP1 a)yP2))
+#define xP1 tree l8
+#define xO1 ;std::cout<<
+#define xN1 grammar_func
+#define xM1 252421 x9 24830,
+#define xL1 cA 529654 x9
+#define xK1 l2 0,2,165888 x9
+#define xJ1 1)?(poly^(
+#define xI1 cCos l3 2,1,
+#define xH1 l1 0x12 nM
+#define xG1 Modulo_Radians},
+#define xF1 c4 cLog);tree c4 cMul);
+#define xE1 GetImmed()
+#define xD1 PositionType
+#define xC1 CollectionResult
+#define xB1 const_offset
+#define xA1 inline TriTruthValue
+#define x91 stacktop_desired
+#define x81 int mStackPtr=0;
+#define x71 SetStackTop(
+#define x61 }inline
+#define x51 FPoptimizer_ByteCode
+#define x41 );n41 0,x32;DelParam(1);
+#define x31 GetParamCount();
+#define x21 xI leaf2 l8
+#define x11 cond_type
+#define x01 fphash_value_t
+#define nZ1 Recheck_RefCount_RDiv
+#define nY1 fpEstimatePrecision(
+#define nX1 SwapLastTwoInStack();
+#define nW1 CollectMulGroup_Item(
+#define nV1 pair<l62,xP3>
+#define nU1 Rehash()e12 r);}
+#define nT1 nN x71 xR-1);
+#define nS1 covers_full_cycle
+#define nR1 (GetLogicalValue(
+#define nQ1 AssembleSequence(
+#define nP1 252180 x9 281854,
+#define nO1 {DataP slot_holder(y3[
+#define nN1 <<std::dec<<")";}
+#define nM1 :yD3 e32
+#define nL1 !=xK)if(TestCase(
+#define nK1 &&IsLogicalValue(
+#define nJ1 else*this=model;}
+#define nI1 std::pair<T1,T2>&
+#define nH1 t91 typename
+#define nG1 has_good_balance_found
+#define nF1 n_occurrences
+#define nE1 found_log2_on_exponent
+#define nD1 covers_minus1
+#define nC1 needs_resynth
+#define nB1 immed_product
+#define nA1 y73 bitmask&
+#define n91 Sign_Positive
+#define n81 {l4::MakeNotNotP1,l4::
+#define n71 {l4::MakeNotNotP0,l4::
+#define n61 ::MakeTrue
+#define n51 matched_params
+#define n41 SetParamMove(
+#define n31 CodeTreeImmed(l62(
+#define n21 Suboptimal
+#define n11 changed_if
+#define n01 n_as_tanh_param
+#define lZ1 opposite=
+#define lY1 x01(
+#define lX1 eE1.size()
+#define lW1 MatchResultType
+#define lV1 needs_sincos
+#define lU1 resulting_exponent
+#define lT1 ;p1 eM1 tree y7 p1);
+#define lS1 Unknown:y13;}
+#define lR1 nD2 a=0;a<c2;++a)
+#define lQ1 )[a].start_at
+#define lP1 GetParam(a)
+#define lO1 inverse_nominator]
+#define lN1 cSin l3 2,1,
+#define lM1 (xP1 yO2&&
+#define lL1 ,typename xG::
+#define lK1 IsImmed()){l62
+#define lJ1 AddFunctionOpcode(
+#define lI1 void FunctionParserBase
+#define lH1 SetParams(iP1));
+#define lG1 o<<"("<<std::hex<<data.
+#define lF1 IfBalanceGood(
+#define lE1 n_as_tan_param
+#define lD1 changed_exponent
+#define lC1 inverse_denominator
+#define lB1 unsigned index
+#define lA1 7168 x9 401798
+#define l91 yB(rule.repl_param_list,
+#define l81 retry_positionalparams_2
+#define l71 situation_flags&
+#define l61 518 x9 400412,
+#define l51 data.subfunc_opcode
+#define l41 CopyOnWrite();
+#define l31 PlanNtimesCache(
+#define l21 FPoptimizer_Grammar
+#define l11 static inline xG
+#define l01 GetPositivityInfo cK3
+#define iZ recursioncount
+#define iY ParamSpec_SubFunctionData
+#define iX ,cPow xZ
+#define iW xO1 std::endl;DumpHashes(
+#define iV ,2,1 i62.xT if(found[data.
+#define iU AddOperation(cInv,1,1 i62.xT}
+#define iT ]);n42
+#define iS ~size_t(0)){synth.yV
+#define iR PositionalParams_Rec
+#define iQ DumpTreeWithIndent(*this);
+#define iP switch(type e53 cond_or:
+#define iO CalculateResultBoundaries(
+#define iN t91 unsigned Compare>
+#define iM yF3 0x0 tL3
+#define iL edited_powgroup
+#define iK has_unknown_max
+#define iJ has_unknown_min
+#define iI static const range yB
+#define iH if(keep_powi
+#define iG synthed_tree
+#define iF SelectedParams,0},0,0x0},{{
+#define iE by_exponent
+#define iD collections
+#define iC cache
+#define iB )e12 p2);tree c4 iM2 nF);cN}
+#define iA goto ReplaceTreeWithOne;case
+#define i9 xB3,std::ostream&o
+#define i8 y7 comp.yY1[a].value);
+#define i7 !=xK)return l92
+#define i6 cK1.data
+#define i5 iK2 x42(
+#define i4 needs_sinhcosh
+#define i3 t72 l62(
+#define i2 MakeFalse,l4::
+#define i1 ].relationship
+#define i0 ,eE1,IP,limit,y4,stack);
+#define tZ 408964 x9 24963,
+#define tY 528504 x9 24713,
+#define tX AnyParams,0}}iH2
+#define tW [n0 e03=true;lR[n0].second
+#define tV l21::Grammar*
+#define tU powgroup l8
+#define tT }},{ProduceNewTree,2,1,
+#define tS ,l7 2,1,
+#define tR ~size_t(0)&&found[data.
+#define tQ xP1 0)
+#define tP xC AnyParams,
+#define tO iO xP1
+#define tN =tO 0));range yB
+#define tM t32.GetImmed(
+#define tL (tM))
+#define tK n31(
+#define tJ has_mulgroups_remaining
+#define tI Rehash();tY2 yS2
+#define tH int_exponent_t
+#define tG best_factor
+#define tF RootPowerTable yB::RootPowers[
+#define tE :goto ReplaceTreeWithZero;case
+#define tD MatchPositionSpec_AnyParams yB
+#define tC iR2 FPoptimizer_CodeTree
+#define tB n_as_sinh_param
+#define tA n_as_cosh_param
+#define t9 is_signed
+#define t8 nS l62(-n23
+#define t7 tree.GetParamCount()
+#define t6 .max.known
+#define t5 eM1 tree c4 i72 nF);tree.
+#define t4 iP1));xY1 Rehash();
+#define t3 result_positivity
+#define t2 biggest_minimum
+#define t1 124024 x9 139399,
+#define t0 142456 x9 141449,
+#define eZ valueType
+#define eY .min.known
+#define eX x72 a=0 tH2 if(remaining[a])
+#define eW ,cIf,l0 3,
+#define eV lB 0x4},{{
+#define eU cond_tree
+#define eT else_tree
+#define eS then_tree
+#define eR sequencing
+#define eQ string eK3(
+#define eP const iY
+#define eO ;return
+#define eN if_stack
+#define eM .max.set(fp_ceil tR1
+#define eL n_as_sin_param
+#define eK n_as_cos_param
+#define eJ PowiResolver::
+#define eI cIf l3 0,1,
+#define eH .BalanceGood
+#define eG {if(needs_cow){l41 goto
+#define eF );bool needs_cow=GetRefCount()>1;
+#define eE AddParamMove(
+#define eD back().endif_location
+#define eC x01 key
+#define eB relationships
+#define eA 130,1,
+#define e9 MatchPositionSpecBase
+#define e8 iK2 CodeTree(
+#define e7 smallest_maximum
+#define e6 }PACKED_GRAMMAR_ATTRIBUTE;
+#define e5 ReplaceTreeWithParam0;
+#define e4 factor_needs_rehashing
+#define e3 MatchPositionSpecBaseP
+#define e2 typename t31::xR3
+#define e1 fp_cosh cI2);m nV=fp_cosh(m nV);
+#define e0 {AdoptChildrenWithSameOpcode(tree);
+#define cZ cR1 yB(nT.param_list,
+#define cY );eE1 yS2 0x80000000u
+#define cX for(lG3 r=range.first;r!=range.second;++r){
+#define cW 243,244,245,246,249,250,251,253,255,256,257,258,259}};}
+#define cV ];};extern"C"{
+#define cU i9=std::cout
+#define cT 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 cS 27,28,29,30,31,32,33,35,36,
+#define cR const ParamSpec_SubFunction
+#define cQ const ParamSpec_ParamHolder
+#define cP }if(list y93 xE1==l62(
+#define cO otherhalf
+#define cN goto redo;
+#define cM .AddParam(
+#define cL StackState
+#define cK min iN2 p0 e32>=l62(0.0))
+#define cJ max.known e23
+#define cI l62(1.5)*fp_const_pi yB()
+#define cH CalculatePowiFactorCost(
+#define cG ImmedHashGenerator
+#define cF ::map<fphash_t,std::set<std yE3> >
+#define cE T1,typename T2>inline bool eD1()(
+#define cD has_nonlogical_values
+#define cC from_logical_context)
+#define cB AnyParams,0}},{ProduceNewTree,
+#define cA ,l2 18,2,
+#define c9 ,l2 16,2,
+#define c8 max iN2 p0 nV<=fp_const_negativezero yB())
+#define c7 x72 a=t7;a-->0;)
+#define c6 x72 a=0 tH2{
+#define c5 )return false;
+#define c4 .lM2
+#define c3 n72 y2.x31 a-->0;)
+#define c2 nT y52
+#define c1 POWI_CACHE_SIZE
+#define c0 ++IP;y41}if(lK3 yS3.
+#define yZ },{l4::xK,l4::Never},{l4::xK,l4::Never}}
+#define yY .FoundChild
+#define yX BalanceResultType
+#define yW n42 GetOpcode(),
+#define yV DoDup(found[data.
+#define yU nW3(0),Opcode(
+#define yT );void lJ1 unsigned cW3 yZ2<
+#define yS {return
+#define yR const yS data->
+#define yQ +=fp_const_twopi yB();
+#define yP n72 0;a<x31++a cI3
+#define yO MatchPositionSpec_AnyWhere
+#define yN l93 data.match_type==
+#define yM void OutFloatHex(std::ostream&o,
+#define yL paramholder_matches
+#define yK {static void lH3 nE fphash_t&NewHash,
+#define yJ AddParam(CodeTreeImmed(
+#define yI m.min.
+#define yH fp_sin(min),fp_sin(max))
+#define yG fp_const_twopi yB());if(
+#define yF ;n11 eM1 tree c4 op1);tree.
+#define yE n72 0;a<xO3.x31++a)if(
+#define yD template lY
+#define yC ComparisonSetBase::
+#define yB <l62>
+#define yA MatchPositionSpec_PositionalParams yB
+#define y9 AssembleSequence_Subdivide(
+#define y8 ]=0x80000000u|unsigned(
+#define y7 .eE
+#define y6 branch2
+#define y5 unsigned c;unsigned short l[
+#define y4 factor_stack_base
+#define y3 data->Params
+#define y2 branch1
+#define y1 MatchInfo yB&
+#define y0 const SequenceOpCode yB
+#define xZ ,lB 0x4 nM
+#define xY yR2 tree)xO1"\n";
+#define xX ;sim.Eat(2,
+#define xW tQ yP2
+#define xV ,l62(-1)))eG
+#define xU AddConst(
+#define xT StackTopIs(*this)eO;}
+#define xS {lQ2.erase(i);y41}
+#define xR StackTop
+#define xQ FPOPT_autoptr
+#define xP +=nT3 eO nT3;}yD inline l62
+#define xO int_exponent
+#define xN newnode
+#define xM eA2 0x0},{{
+#define xL has_highlevel_opcodes
+#define xK Unchanged
+#define xJ best_selected_sep
+#define xI .IsIdenticalTo(
+#define xH GetStackTop()-
+#define xG CodeTree yB
+#define xF cAnd,tX
+#define xE ->Recalculate_Hash_NoRecursion();}
+#define xD x31++a)if(ApplyGrammar(tD2,tJ3
+#define xC ,cAdd,
+#define xB position
+#define xA )){tree.FixIncompleteHashes();}
+#define x9 ,{2,
+#define x8 for c6 range yB
+#define x7 std::vector<CodeTree>
+#define x6 SetParam(0,iM2 xN2 xG p1;p1 c4
+#define x5 TestImmedConstraints y83 constraints,tree)c5
+#define x4 y53 0 nY3 cInv);tmp c43 eO
+#define x3 nX1 sim.Eat(
+#define x2 {nA2 cInv);yY3 sim.xU-1)xX yV3
+#define x1 paramholder_index
+#define x0 return true;case
+#define nZ occurance_counts
+#define nY >p=tO a));if(p.
+#define nX -->0;){iT1 powgroup=lP1;if(powgroup
+#define nW ,l0 1,
+#define nV .max.val
+#define nU const FPoptimizer_CodeTree::xG&tree
+#define nT model_tree
+#define nS return range yB(
+#define nR )){tree.ReplaceWithImmed(
+#define nQ ){xG
+#define nP ),rangehalf yB model=rangehalf yB()cI3 known
+#define nO x42 yB::x42(
+#define nN ){using iR2 FUNCTIONPARSERTYPES;
+#define nM },{{2,
+#define nL AnyParams,1},0,0x0},{{
+#define nK nX2&lA2
+#define nJ ConstantFolding_LogicCommon(tree,yC
+#define nI nH1 Ref>inline void xQ<Ref>::
+#define nH cOr,tX 16,1,
+#define nG ):data(new x42 yB(
+#define nF tC3()
+#define nE FUNCTIONPARSERTYPES::
+#define nD )l32}
+#define nC b;}};t91>cP2 Comp<nE
+#define nB t21 cPow);nZ3;tmp.yJ l62(
+#define nA xG tmp,tmp2;tmp2 c4
+#define n9 iR1(),Params(),Hash(),Depth(1),tJ1 0){}
+#define n8 SynthesizeByteCode(synth);
+#define n7 AddParam(xP1
+#define n6 while(ApplyGrammar(c92
+#define n5 GetIntegerInfo(tQ)==IsAlways)goto e5
+#define n4 e12 n11)cT2
+#define n3 lS);if(fp_nequal(tmp,tD1)nR l62(1)/tmp l32}}lD
+#define n2 xT1 cGreater>(l62(
+#define n1 DumpParams yB y83 data.param_list,yA3 data y52,o);
+#define n0 restholder_index
+#define lZ :if(ParamComparer yB()(Params[1],Params[0])){std::swap(Params[0],Params[1]);Opcode=
+#define lY <typename l62>
+#define lX xG nU3 t11 c4 cMul)t11 cM
+#define lW tL1,0x0},
+#define lV eE pow l8 1));pow.DelParam(1);pow eM1 tree.n41 0,pow);goto NowWeAreMulGroup;}
+#define lU GroupFunction,0},lW{{
+#define lT ,l62(1)/l62(
+#define lS tQ.xE1
+#define lR restholder_matches
+#define lQ cB1|=key;x01 crc=(key>>10)|(key<<(64-10))cA1((~lY1 crc))*3)^1234567;}};
+#define lP n11;n11 n82 n11 y7 tQ);n11 cM y2 l8
+#define lO yD xG::CodeTree(
+#define lN tree.SetParam(0,tQ l8 0))y51 1,CodeTreeImmed(
+#define lM lY void ByteCodeSynth yB::lJ1 unsigned cW3 yZ2<
+#define lL cMul,lU 2,
+#define lK cMul,AnyParams,
+#define lJ (xW)&&t32 yP2 nR
+#define lI iO tmp)cT1
+#define lH :cB3=comp.AddRelationship(atree l8 0),atree l8 1),yC
+#define lG cPow,l0 2
+#define lF typename l62>inline bool eD1()cX1 nX3 l62&b)yS a
+#define lE {range yB m=tO 0));
+#define lD break;case
+#define lC x73 xG::
+#define lB y21,0,
+#define lA l1 0x0 nM
+#define l9 ?0:1));xG n11;n11 n82 n11 iY1 tree.iP1));n11 eM1 tree c4
+#define l8 .GetParam(
+#define l7 cAdd,tX
+#define l6 SelectedParams,0},0,0x0 nM
+#define l5 lK 0}}iH2
+#define l4 RangeComparisonData
+#define l3 ,y21},{ProduceNewTree,
+#define l2 y21}iH2
+#define l1 cMul,SelectedParams,0},0,
+#define l0 lB 0x0},{{
+#ifdef _MSC_VER
+typedef
+unsigned
+int
+iO1;
+#else
+#include <stdint.h>
+typedef
+uint_least32_t
+iO1;
+#endif
+iR2
+crc32{enum{startvalue=0xFFFFFFFFUL,poly=0xEDB88320UL}
+;t91
+iO1
+crc>cP2
+b8{enum{b1=(crc&xJ1
+crc
+x52
+crc>>1),b2=(b1&xJ1
+b1
+x52
+b1>>1),b3=(b2&xJ1
+b2
+x52
+b2>>1),b4=(b3&xJ1
+b3
+x52
+b3>>1),b5=(b4&xJ1
+b4
+x52
+b4>>1),b6=(b5&xJ1
+b5
+x52
+b5>>1),b7=(b6&xJ1
+b6
+x52
+b6>>1),res=(b7&xJ1
+b7
+x52
+b7>>1)}
+;}
+;inline
+iO1
+update(iO1
+crc,unsigned
+b){
+#define B4(n) b8<n>iQ2 n+1>iQ2 n+2>iQ2 n+3>::res
+#define R(n) B4(n),B4(n+4),B4(n+8),B4(n+12)
+static
+const
+iO1
+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];x61
+iO1
+calc_upd(iO1
+c,const
+unsigned
+char*buf,size_t
+size){iO1
+value=c;for
+x72
+p=0;p<size;++p)value=update(value,buf[p])eO
+value;x61
+iO1
+calc
+cY1
+unsigned
+char*buf,size_t
+size)yS
+calc_upd(startvalue,buf,size);}
+}
+#ifndef FPOptimizerAutoPtrHH
+#define FPOptimizerAutoPtrHH
+nH1
+Ref>class
+xQ{cV3
+xQ():p(0){}
+xQ(Ref*b):p(b){nV3}
+xQ
+cY1
+xQ&b):p(b.p){nV3
+x61
+Ref&eD1*(yK1*p;x61
+Ref*eD1->(yK1
+p;}
+bool
+isnull(yK1!p;}
+Ref*get(yK1
+p;}
+xQ&eD1=(Ref*b){Set(b)eO*this;}
+xQ&eD1=cY1
+xQ&b){Set(b.p)eO*this;}
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+xQ(xQ&&b):p(b.p){b.p=0;}
+xQ&eD1=(xQ&&b
+cI3
+p!=b.p){cO2;p=b.p;b.p=0
+yC3*this;}
+#endif
+~xQ(){cO2
+n63
+UnsafeSetP(Ref*newp){p=newp
+n63
+swap(xQ<Ref>&b){Ref*tmp=p;p=b.p;b.p=tmp;}
+private:inline
+static
+void
+Have(Ref*p2);inline
+void
+cO2;inline
+void
+nV3
+inline
+void
+Set(Ref*p2);private:Ref*p;}
+;nI
+cO2{if(!p)return;p->nW3-=1;if(!p->nW3)delete
+p;}
+nI
+Have(Ref*p2
+cI3
+p2)++(p2->nW3);}
+nI
+Birth(){Have(p);}
+nI
+Set(Ref*p2){Have(p2);cO2;p=p2;}
+#endif
+#include <utility>
+cP2
+Compare2ndRev{nH1
+T>inline
+bool
+eD1()cY1
+T&nX3
+T&b
+yK1
+a.second>b.second;}
+}
+;cP2
+Compare1st{nH1
+cE
+const
+nI1
+nX3
+nI1
+b
+yK1
+a.first<b.first;}
+nH1
+cE
+const
+nI1
+a,T1
+b
+yK1
+a.first<b;}
+nH1
+cE
+T1
+nX3
+nI1
+b
+yK1
+a<b.first;}
+}
+;
+#ifndef FPoptimizerHashHH
+#define FPoptimizerHashHH
+#ifdef _MSC_VER
+typedef
+unsigned
+long
+long
+x01;
+#define FPHASH_CONST(x) x##ULL
+#else
+#include <stdint.h>
+typedef
+uint_fast64_t
+x01;
+#define FPHASH_CONST(x) x##ULL
+#endif
+iR2
+FUNCTIONPARSERTYPES{cP2
+fphash_t{x01
+hash1,hash2;fphash_t():hash1(0),hash2(0){}
+fphash_t
+cY1
+x01&nX3
+x01&b):hash1(a),hash2(b){}
+bool
+eD1==cY1
+fphash_t&yJ1==cQ2&&hash2==cR2
+bool
+eD1!=cY1
+fphash_t&yJ1!=cQ2||hash2!=cR2
+bool
+eD1<cY1
+fphash_t&yJ1!=cQ2?hash1<cQ2:hash2<cR2}
+;}
+#endif
+#ifndef FPOptimizer_CodeTreeHH
+#define FPOptimizer_CodeTreeHH
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <vector>
+#include <utility>
+iR2
+l21{cP2
+Grammar;}
+iR2
+x51{x13
+ByteCodeSynth;}
+tC{x13
+CodeTree;yD
+cP2
+x42;x13
+CodeTree{typedef
+xQ<x42
+yB>DataP;DataP
+data;cV3
+CodeTree();~CodeTree();cP2
+OpcodeTag{}
+;e8
+nW2
+o,OpcodeTag);cP2
+FuncOpcodeTag{}
+;e8
+nW2
+o,unsigned
+f,FuncOpcodeTag);cP2
+x23{}
+;e8
+const
+l62&v,x23);
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+e8
+l62&&v,x23);
+#endif
+cP2
+VarTag{}
+;e8
+unsigned
+varno,VarTag);cP2
+CloneTag{}
+;e8
+iS2
+b,CloneTag);void
+GenerateFrom
+cY1
+typename
+FunctionParserBase
+yB::Data&data,bool
+keep_powi=false);void
+GenerateFrom
+cY1
+typename
+FunctionParserBase
+yB::Data&data,const
+x7&x12,bool
+keep_powi=false);void
+SynthesizeByteCode(std::vector<unsigned>&c83,std::vector
+yB&immed,size_t&stacktop_max);void
+SynthesizeByteCode(x51
+yZ3&synth,bool
+MustPopTemps=true)const;size_t
+SynthCommonSubExpressions(x51::yM1
+const;void
+SetParams
+cY1
+x7&x33
+SetParamsMove(x7&t81
+CodeTree
+GetUniqueRef();
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+void
+SetParams(x7&&t81
+#endif
+void
+SetParam
+x72
+which,iS2
+b);void
+n41
+size_t
+which,nV2
+b);void
+AddParam
+cY1
+nV2
+param);void
+eE
+nV2
+param);void
+AddParams
+cY1
+x7&x33
+AddParamsMove(x7&x33
+AddParamsMove(x7&lA2,size_t
+lB2);void
+DelParam
+x72
+index);void
+DelParams();void
+Become
+cY1
+nV2
+b);inline
+size_t
+GetParamCount(yK1
+iP1).size();x61
+nV2
+GetParam
+x72
+n)yS
+iP1)[n];x61
+iS2
+GetParam
+x72
+n
+yK1
+iP1)[n];x61
+void
+lM2
+nW2
+o)tI3
+Opcode=o;x61
+nW2
+GetOpcode()yR
+Opcode;x61
+nE
+fphash_t
+GetHash()yR
+Hash;x61
+const
+x7&iP1
+yK1
+y3;x61
+x7&iP1)yS
+y3;x61
+size_t
+xT2
+yR
+Depth;x61
+const
+l62&xE1
+yR
+Value;x61
+unsigned
+GetVar()yR
+iQ1
+x61
+unsigned
+GetFuncNo()yR
+iQ1
+x61
+bool
+IsDefined(yK1
+GetOpcode()!=nE
+cNop;x61
+bool
+IsImmed(yK1
+GetOpcode()==nE
+cImmed;x61
+bool
+IsVar(yK1
+GetOpcode()==nE
+iE2;x61
+unsigned
+GetRefCount()yR
+nW3
+n63
+ReplaceWithImmed
+cX1
+i);void
+Rehash(bool
+constantfolding=true);void
+Sort();inline
+void
+Mark_Incompletely_Hashed()tI3
+Depth=0;x61
+bool
+Is_Incompletely_Hashed()yR
+Depth==0;x61
+const
+tV
+GetOptimizedUsing()yR
+iS1;x61
+void
+SetOptimizedUsing
+cY1
+tV
+g)tI3
+iS1=g;}
+bool
+RecreateInversionsAndNegations(bool
+prefer_base2=false);void
+FixIncompleteHashes();void
+swap(nV2
+b){data.swap(b.data);}
+bool
+IsIdenticalTo
+cY1
+nV2
+b)const;void
+l41}
+;yD
+cP2
+x42{int
+nW3;nW2
+Opcode;l62
+Value;unsigned
+iQ1
+nX2
+Params;nE
+fphash_t
+Hash;size_t
+Depth;const
+tV
+iS1;x42();x42
+cY1
+x42&b);i5
+nW2
+o);i5
+nW2
+o,unsigned
+f);i5
+const
+l62&i);
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+i5
+l62&&i);x42(x42&&b);
+#endif
+bool
+IsIdenticalTo
+cY1
+x42&b)const;void
+Sort();void
+Recalculate_Hash_NoRecursion();private:void
+eD1=cY1
+x42&b);}
+;yD
+l11
+CodeTreeImmed
+cX1
+i)yS
+xG(i
+lL1
+x23());}
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+yD
+l11
+CodeTreeImmed(l62&&i)yS
+xG
+cX2
+i)lL1
+x23());}
+#endif
+yD
+l11
+CodeTreeOp(nW2
+opcode)yS
+xG(opcode
+lL1
+OpcodeTag());}
+yD
+l11
+CodeTreeFuncOp(nW2
+cW3
+unsigned
+f)yS
+xG(cW3
+f
+lL1
+FuncOpcodeTag());}
+yD
+l11
+CodeTreeVar
+nD2
+varno)yS
+xG(varno
+lL1
+VarTag());}
+#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
+x73
+DumpHashes(cU);x73
+DumpTree(cU);x73
+DumpTreeWithIndent(cU,const
+std
+yE3&indent="\\"
+);
+#endif
+}
+#endif
+#endif
+#ifndef FPOptimizer_GrammarHH
+#define FPOptimizer_GrammarHH
+#include <iostream>
+tC{x13
+CodeTree;}
+iR2
+l21{enum
+ImmedConstraint_Value{ValueMask=0x07,Value_AnyNum=0x0,nK2=0x1,Value_OddInt=0x2,tM1=0x3,Value_NonInteger=0x4,eQ1=0x5
+nO3
+ImmedConstraint_Sign{SignMask=0x18,Sign_AnySign=0x00,n91=0x08,eR1=0x10,Sign_NoIdea=0x18
+nO3
+ImmedConstraint_Oneness{OnenessMask=0x60,Oneness_Any=0x00,Oneness_One=0x20,Oneness_NotOne=0x40
+nO3
+ImmedConstraint_Constness{ConstnessMask=0x180,Constness_Any=0x00,tL1=0x80,Constness_NotConst=0x100
+nO3
+Modulo_Mode{Modulo_None=0,Modulo_Radians=1
+nO3
+Situation_Flags{LogicalContextOnly=0x01,NotForIntegers=0x02,OnlyForIntegers=0x04,OnlyForComplex=0x08,NotForComplex=0x10
+nO3
+nB2{NumConstant,ParamHolder,SubFunction
+nO3
+ParamMatchingType{PositionalParams,SelectedParams,AnyParams,GroupFunction
+nO3
+RuleType{ProduceNewTree,ReplaceParams}
+;
+#ifdef __GNUC__
+# define PACKED_GRAMMAR_ATTRIBUTE __attribute__((packed))
+#else
+# define PACKED_GRAMMAR_ATTRIBUTE
+#endif
+typedef
+std::pair<nB2,const
+void*>cS2;yD
+cS2
+cR1
+nD2
+paramlist,lB1);yD
+bool
+ParamSpec_Compare
+cY1
+void*nX3
+void*b,nB2
+type);unsigned
+ParamSpec_GetDepCode
+cY1
+cS2&b);cP2
+ParamSpec_ParamHolder{lB1:8;unsigned
+constraints:9;unsigned
+depcode:15;e6
+yD
+cP2
+ParamSpec_NumConstant{l62
+constvalue;unsigned
+modulo;}
+;cP2
+iY{unsigned
+param_count:2;unsigned
+param_list:30;nW2
+subfunc_opcode:8;ParamMatchingType
+match_type:3;unsigned
+n0:5;e6
+cP2
+ParamSpec_SubFunction{iY
+data;unsigned
+constraints:9;unsigned
+depcode:7;e6
+cP2
+Rule{RuleType
+ruletype:2;unsigned
+situation_flags:5;unsigned
+repl_param_count:2+9;unsigned
+repl_param_list:30;iY
+match_tree;e6
+cP2
+Grammar{unsigned
+rule_count;unsigned
+short
+rule_list[999
+cV
+extern
+const
+Rule
+grammar_rules[];}
+x73
+DumpParam
+cY1
+cS2&p,std::ostream&o=std::cout);x73
+DumpParams
+nD2
+paramlist,unsigned
+count,std::ostream&o=std::cout);}
+#endif
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795
+#endif
+#define CONSTANT_POS_INF HUGE_VAL
+#define CONSTANT_NEG_INF (-HUGE_VAL)
+iR2
+FUNCTIONPARSERTYPES{yD
+inline
+l62
+fp_const_pihalf()yS
+fp_const_pi
+yB()*l62(0.5);}
+yD
+inline
+l62
+fp_const_twopi(){l62
+nT3(fp_const_pi
+yB());nT3
+xP
+fp_const_twoe(){l62
+nT3(fp_const_e
+yB());nT3
+xP
+fp_const_twoeinv(){l62
+nT3(fp_const_einv
+yB());nT3
+xP
+fp_const_negativezero()yS-Epsilon
+yB::value;}
+}
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <vector>
+#include <utility>
+#include <iostream>
+cV1{using
+iR2
+l21;using
+tC;using
+iR2
+FUNCTIONPARSERTYPES;x13
+MatchInfo{cV3
+std::vector<std::pair<bool,nX2> >lR;nX2
+yL
+e72
+unsigned>n51;cV3
+MatchInfo():lR(),yL(),n51(){}
+cV3
+bool
+SaveOrTestRestHolder
+nD2
+n0,x43
+tV1){cE1{lR
+x53
+n0+1);lR
+tW=tV1
+cT2
+if(lR[n0
+e03==false){lR
+tW=tV1
+cT2
+x43
+found=lR[n0].second;if(tV1.size()!=found.size()c5
+n72
+0;a<tV1.size();++a)if(!tV1[a]xI
+found[a])c5
+return
+true
+n63
+SaveRestHolder
+nD2
+n0,nX2&tV1){cE1
+lR
+x53
+n0+1);lR
+tW.swap(tV1);}
+bool
+SaveOrTestParamHolder
+nD2
+x1,iT1
+x63
+cI3
+yL.size()<=x1){yL.xD3
+x1+1);yL
+x53
+x1);yL
+yS2
+x63)cT2
+if(!yL[x1].n12){yL[x1]=x63
+cT2
+return
+x63
+xI
+yL[x1]n33
+SaveMatchedParamIndex(lB1){n51
+yS2
+index);}
+iT1
+GetParamHolderValueIfFound
+nD2
+x1)const{static
+const
+xG
+dummytree;if(yL.size()<=x1)return
+dummytree
+eO
+yL[x1];}
+iT1
+GetParamHolderValue
+nD2
+x1
+yK1
+yL[x1];}
+bool
+HasRestHolder
+nD2
+n0
+yK1
+lR.size()>n0&&lR[n0
+e03==true;}
+x43
+GetRestHolderValues
+nD2
+n0)const{static
+yL1
+xG>empty_result;cE1
+return
+empty_result
+eO
+lR[n0].second;}
+yL1
+unsigned>&GetMatchedParamIndexes(yK1
+n51
+n63
+swap(y1
+b){lR.swap(b.lR);yL.swap(b.yL);n51.swap(b.n51);}
+y1
+eD1=cY1
+y1
+b){lR=b.lR;yL=b.yL;n51=b.n51
+eO*this;}
+}
+;class
+e9
+tO3
+xQ<e9>e3;class
+e9{cV3
+int
+nW3;cV3
+e9():nW3(0){}
+virtual~e9(){}
+}
+;cP2
+lW1{bool
+found;e3
+specs;lW1(bool
+f):found(f),specs(){}
+lW1(bool
+f
+n43
+s):found(f),specs(s){}
+}
+;x73
+SynthesizeRule
+cY1
+eU2
+xG&tree,y1
+info);yD
+lW1
+TestParam
+cY1
+cS2&x02,xB3
+n43
+start_at,y1
+info);yD
+lW1
+TestParams(eP&nT,xB3
+n43
+start_at,y1
+info,bool
+y82;yD
+bool
+ApplyGrammar
+cY1
+Grammar&tD2,FPoptimizer_CodeTree::xG&tree,bool
+from_logical_context=false);x73
+ApplyGrammars(FPoptimizer_CodeTree::cV2;yD
+bool
+IsLogisticallyPlausibleParamsMatch(eP&e13,xB3);}
+iR2
+l21{x73
+DumpMatch
+cY1
+eU2
+nU,const
+FPoptimizer_Optimize::y1
+info,bool
+DidMatch,std::ostream&o=std::cout);x73
+DumpMatch
+cY1
+eU2
+nU,const
+FPoptimizer_Optimize::y1
+info,nA3
+eH3,std::ostream&o=std::cout);}
+#endif
+#include <string>
+nB3
+l21::nB2
+yD1=false);nB3
+nW2
+yD1=false);
+#include <string>
+#include <sstream>
+#include <assert.h>
+#include <iostream>
+using
+iR2
+l21;using
+iR2
+FUNCTIONPARSERTYPES;nB3
+l21::nB2
+yD1){
+#if 1
+nA3
+p=0;switch(opcode
+e53
+NumConstant:p="NumConstant"
+;lD
+ParamHolder:p="ParamHolder"
+;lD
+SubFunction:p="SubFunction"
+;yY3
+std::ostringstream
+tmp;assert(p);tmp<<p;if(pad)while(tmp.str().size()<12)tmp<<' '
+eO
+tmp.str();
+#else
+std::ostringstream
+tmp;tmp<<opcode;if(pad)while(tmp.str().size()<5)tmp<<' '
+eO
+tmp.str();
+#endif
+}
+nB3
+nW2
+yD1){
+#if 1
+nA3
+p=0;switch(opcode
+e53
+cAbs:p="cAbs"
+;lD
+cAcos:p="cAcos"
+;lD
+cAcosh:p="cAcosh"
+;lD
+cArg:p="cArg"
+;lD
+cAsin:p="cAsin"
+;lD
+cAsinh:p="cAsinh"
+;lD
+cAtan:p="cAtan"
+;lD
+cAtan2:p="cAtan2"
+;lD
+cAtanh:p="cAtanh"
+;lD
+cCbrt:p="cCbrt"
+;lD
+cCeil:p="cCeil"
+;lD
+cConj:p="cConj"
+;lD
+cCos:p="cCos"
+;lD
+cCosh:p="cCosh"
+;lD
+cCot:p="cCot"
+;lD
+cCsc:p="cCsc"
+;lD
+cExp:p="cExp"
+;lD
+cExp2:p="cExp2"
+;lD
+cFloor:p="cFloor"
+;lD
+cHypot:p="cHypot"
+;lD
+cIf:p="cIf"
+;lD
+cImag:p="cImag"
+;lD
+cInt:p="cInt"
+;lD
+cLog:p="cLog"
+;lD
+cLog2:p="cLog2"
+;lD
+cLog10:p="cLog10"
+;lD
+cMax:p="cMax"
+;lD
+cMin:p="cMin"
+;lD
+cPolar:p="cPolar"
+;lD
+cPow:p="cPow"
+;lD
+cReal:p="cReal"
+;lD
+cSec:p="cSec"
+;lD
+cSin:p="cSin"
+;lD
+cSinh:p="cSinh"
+;lD
+cSqrt:p="cSqrt"
+;lD
+cTan:p="cTan"
+;lD
+cTanh:p="cTanh"
+;lD
+cTrunc:p="cTrunc"
+;lD
+cImmed:p="cImmed"
+;lD
+cJump:p="cJump"
+;lD
+cNeg:p="cNeg"
+;lD
+cAdd:p="cAdd"
+;lD
+cSub:p="cSub"
+;lD
+cMul:p="cMul"
+;lD
+cDiv:p="cDiv"
+;lD
+cMod:p="cMod"
+;lD
+cEqual:p="cEqual"
+;lD
+tP1:p="cNEqual"
+;lD
+cLess:p="cLess"
+;lD
+cLessOrEq:p="cLessOrEq"
+;lD
+cGreater:p="cGreater"
+;lD
+cGreaterOrEq:p="cGreaterOrEq"
+;lD
+cNot:p="cNot"
+;lD
+cAnd:p="cAnd"
+;lD
+cOr:p="cOr"
+;lD
+cDeg:p="cDeg"
+;lD
+cRad:p="cRad"
+;lD
+cFCall:p="cFCall"
+;lD
+cPCall:p="cPCall"
+;break;
+#ifdef FP_SUPPORT_OPTIMIZER
+case
+cFetch:p="cFetch"
+;lD
+cPopNMov:p="cPopNMov"
+;lD
+cLog2by:p="cLog2by"
+;lD
+cNop:p="cNop"
+;break;
+#endif
+case
+cSinCos:p="cSinCos"
+;lD
+cSinhCosh:p="cSinhCosh"
+;lD
+c03:p="cAbsNot"
+;lD
+cAbsNotNot:p="cAbsNotNot"
+;lD
+cAbsAnd:p="cAbsAnd"
+;lD
+cAbsOr:p="cAbsOr"
+;lD
+cAbsIf:p="cAbsIf"
+;lD
+cDup:p="cDup"
+;lD
+cInv:p="cInv"
+;lD
+cSqr:p="cSqr"
+;lD
+cRDiv:p="cRDiv"
+;lD
+cRSub:p="cRSub"
+;lD
+cNotNot:p="cNotNot"
+;lD
+cRSqrt:p="cRSqrt"
+;lD
+iE2:p="VarBegin"
+;yY3
+std::ostringstream
+tmp;assert(p);tmp<<p;if(pad)while(tmp.str().size()<12)tmp<<' '
+eO
+tmp.str();
+#else
+std::ostringstream
+tmp;tmp<<opcode;if(pad)while(tmp.str().size()<5)tmp<<' '
+eO
+tmp.str();
+#endif
+}
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <vector>
+#include <utility>
+#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}
+;iR2
+x51{x13
+ByteCodeSynth{cV3
+ByteCodeSynth():eE1(),Immed(),cL(),xR(0),StackMax(0){eE1.xD3
+64);Immed.xD3
+8);cL.xD3
+16
+n33
+Pull(std::vector<unsigned>&bc,std::vector
+yB&imm,size_t&StackTop_max){for
+nD2
+a=0;a<lX1;++a){eE1[a]&=~0x80000000u;}
+eE1.swap(bc);Immed.swap(imm);StackTop_max=StackMax;}
+size_t
+GetByteCodeSize(yK1
+lX1;}
+size_t
+GetStackTop(yK1
+xR
+n63
+PushVar
+nD2
+varno){eE1
+yS2
+varno);eV2}
+void
+PushImmed(l62
+immed
+nN
+eE1
+yS2
+cImmed);Immed
+yS2
+immed);eV2}
+void
+StackTopIs(nU,int
+offset=0
+cI3(int)xR>offset){cL[xR
+lT2
+first=true;cL[xR
+lT2
+second=tree;}
+}
+bool
+IsStackTop(nU,int
+offset=0
+yK1(int)xR>offset&&cL[xR
+lT2
+first&&cL[xR
+lT2
+second
+xI
+tree);x61
+void
+EatNParams
+nD2
+eat_count){xR-=eat_count
+n63
+ProducedNParams
+nD2
+produce_count){x71
+xR+produce_count
+n33
+DoPopNMov
+x72
+cU2,size_t
+srcpos
+nN
+eE1
+yS2
+cPopNMov
+nC2
+cU2
+nC2
+srcpos);x71
+srcpos+1);cL[cU2]=cL[srcpos];x71
+cU2+1
+n33
+DoDup
+x72
+xE3
+nN
+if(xE3==xR-1){eE1
+yS2
+cDup);}
+else{eE1
+yS2
+cFetch
+nC2
+xE3);}
+eV2
+cL[xR-1]=cL[xE3];}
+#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
+t91
+int>void
+Dump(){std::ostream&o=std::cout;o<<"Stack state now("
+<<xR<<"):\n"
+;n72
+0;a<xR;++a){o<<a<<": "
+;if(cL[a
+e03){nU=cL[a].second;o<<'['<<std::hex<<(void*)(&tree.iP1))<<std::dec<<','<<tree.GetRefCount()<<']'
+yR2
+tree,o);}
+else
+o<<"?"
+;o<<"\n"
+;}
+o<<std::flush;}
+#endif
+size_t
+xF3
+nU)const{n72
+xR;a-->0;)if(cL[a
+e03&&cL[a].second
+xI
+tree
+tJ2
+a
+eO~size_t(0);}
+bool
+Find(nU
+yK1
+xF3
+tree)!=~size_t(0);}
+bool
+FindAndDup(nU){size_t
+pos=xF3
+tree);if(pos!=~size_t(0)){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<tF3"duplicate at ["
+<<pos<<"]: "
+yR2
+tree)xO1" -- issuing cDup or cFetch\n"
+;
+#endif
+DoDup(pos)cT2
+return
+e83
+cP2
+IfData{size_t
+ofs;}
+;void
+SynthIfStep1(IfData&nP3,nW2
+op
+nT1
+nP3.ofs=lX1;eE1
+yS2
+op
+cY
+cY
+n33
+SynthIfStep2(IfData&nP3
+nT1
+eE1
+tW1
+xG3+2);eE1
+tW1
+2
+y8
+iU1
+nP3.ofs=lX1;eE1
+yS2
+cJump
+cY
+cY
+n33
+SynthIfStep3(IfData&nP3
+nT1
+eE1.back()|=0x80000000u;eE1
+tW1
+xG3-1);eE1
+tW1
+2
+y8
+iU1
+eV2
+n72
+0;a<nP3.ofs;++a
+cI3
+eE1[a]==cJump&&eE1[a+1]==(0x80000000u|(nP3.ofs-1))){eE1[a+xG3-1);eE1[a+2
+y8
+iU1
+yX3(eE1[a]e53
+cAbsIf:case
+cIf:case
+cJump:case
+cPopNMov:a+=2;lD
+cFCall:case
+cPCall:case
+cFetch:a+=1;break;y13
+yN3}
+protected:void
+x71
+size_t
+value){xR=value;if(xR>iT2{StackMax=xR;cL
+x53
+iT2;}
+}
+protected:std::vector<unsigned>eE1;std::vector
+yB
+Immed
+e72
+std::pair<bool,FPoptimizer_CodeTree::xG> >cL;size_t
+xR;size_t
+StackMax;private:void
+incStackPtr(){if(xR+2>iT2
+cL
+x53
+StackMax=xR+2);}
+t91
+bool
+IsIntType,bool
+IsComplexType>cP2
+yZ2{}
+;cV3
+void
+AddOperation
+nD2
+cW3
+unsigned
+eat_count,unsigned
+produce_count=1){EatNParams(eat_count);lJ1
+opcode);ProducedNParams(produce_count
+n33
+lJ1
+unsigned
+cW3
+yZ2<false,false>yT
+false,true>yT
+true,false>yT
+true,true>);inline
+void
+lJ1
+unsigned
+opcode){lJ1
+cW3
+yZ2<bool(nE
+IsIntType
+yB::nT3),bool(nE
+IsComplexType
+yB::nT3)>());}
+}
+;yD
+cP2
+SequenceOpCode;yD
+cP2
+tH1{static
+y0
+AddSequence;static
+y0
+MulSequence;}
+;x73
+nQ1
+long
+count,y0&eR,yM1;}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;iR2
+x51{yD
+cP2
+SequenceOpCode{l62
+basevalue;unsigned
+op_flip;unsigned
+op_normal,op_normal_flip;unsigned
+op_inverse,op_inverse_flip;}
+;yD
+y0
+tH1
+yB::AddSequence={tD1),cNeg
+xC
+cAdd,cSub,cRSub}
+;yD
+y0
+tH1
+yB::MulSequence={l62(1),cInv,cMul,cMul,cDiv,cRDiv}
+;
+#define findName(a,b,c) "var"
+#define TryCompilePowi(o) false
+#define mData this
+#define mByteCode eE1
+#define mImmed Immed
+lU2
+false,false>){x81
+# define FP_FLOAT_VERSION 1
+# define FP_COMPLEX_VERSION 0
+# include "extrasrc/fp_opcode_add.inc"
+# undef FP_COMPLEX_VERSION
+# undef FP_FLOAT_VERSION
+}
+lU2
+true,false>){x81
+# 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
+lU2
+false,true>){x81
+# define FP_FLOAT_VERSION 1
+# define FP_COMPLEX_VERSION 1
+# include "extrasrc/fp_opcode_add.inc"
+# undef FP_COMPLEX_VERSION
+# undef FP_FLOAT_VERSION
+}
+lU2
+true,true>){x81
+# 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
+iR2
+x51;
+#define POWI_TABLE_SIZE 256
+#define POWI_WINDOW_SIZE 3
+iR2
+x51{
+#ifndef FP_GENERATING_POWI_TABLE
+extern
+const
+unsigned
+char
+powi_table[POWI_TABLE_SIZE];const
+#endif
+unsigned
+char
+powi_table[POWI_TABLE_SIZE]={0,1,1,1,2
+i41
+1,4,1,2,131,8
+i41
+1,8,cA3
+131,4,1,15,1,16
+i41
+131,8,1,2,1,4,cA3
+1,16,1,25,131,4,1,27,5,8,3,2,1,30,1,31,3,32
+i41
+1,8,1,2,131,4,1,39,1,16,137,2,1,4,cA3
+131,8,1,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,tX1
+131,tX1
+139,iV1
+eA
+30,1,130,137,2,31,iV1
+eA
+eA
+130,cA3
+1,eA
+eA
+2,1,130,133,tX1
+61,130,133,62,139,130,137,eA
+iV1
+eA
+eA
+tX1
+131,eA
+eA
+130,131,2,133,iV1
+130,141,eA
+130,cA3
+1,eA
+5,135,eA
+iV1
+eA
+iV1
+130,133,130,141,130,131,eA
+eA
+2,131}
+;}
+static
+nK3
+c1=256;
+#define FPO(x)
+iR2{class
+PowiCache{private:int
+iC[c1];int
+tY1[c1];cV3
+PowiCache():iC(),tY1(){iC[1]=1;}
+bool
+Plan_Add(yO1,int
+count){yW1>=c1
+c5
+tY1[eW2+=count
+eO
+iC[eW2!=0
+n63
+iU2
+yO1){yW1<c1)iC[eW2=1
+n63
+Start
+x72
+value1_pos){for(int
+n=2;n<c1;++n)iC[n]=-1;Remember(1,value1_pos);DumpContents();}
+int
+Find(yO1)const{yW1<c1
+cI3
+iC[eW2>=0){FPO(t03(t43,"* I found %ld from cache (%u,%d)\n",value,(unsigned)cache[value],t13 value]))eO
+iC[eW2;}
+}
+return-1
+n63
+Remember(yO1,size_t
+tD3){yW1>=c1)return;FPO(t03(t43,"* Remembering that %ld can be found at %u (%d uses remain)\n",value,(unsigned)tD3,t13 value]));iC[eW2=(int)tD3
+n63
+DumpContents()const{FPO(for(int a=1;a<POWI_CACHE_SIZE;++a)if(cache[a]>=0||t13 a]>0){t03(t43,"== cache: sp=%d, val=%d, needs=%d\n",cache[a],a,t13 a]);})}
+int
+UseGetNeeded(yO1){yW1>=0&&value<c1)return--tY1[eW2
+eO
+0;}
+}
+;yD
+size_t
+y9
+long
+count
+cC1
+y0&eR,yM1;x73
+yP1
+size_t
+apos,long
+aval,size_t
+bpos,long
+bval
+cC1
+unsigned
+cumulation_opcode,unsigned
+cimulation_opcode_flip,yM1;void
+l31
+yO1
+cC1
+int
+need_count,int
+iZ=0){yW1<1)return;
+#ifdef FP_GENERATING_POWI_TABLE
+if(iZ>32)throw
+false;
+#endif
+if(iC.Plan_Add(value,need_count
+tJ2;long
+xH3
+1;yW1<POWI_TABLE_SIZE){xH3
+powi_table[eW2
+n73&128
+xA2
+if(xI3
+xH3-eX2
+FPO(t03(t43,"value=%ld, half=%ld, otherhalf=%ld\n",value,half,value/half));l31
+half,c02
+iC.iU2
+half)eO;}
+i81
+xI3{xH3-eX2}
+}
+else
+yW1&1)xH3
+value&((1<<POWI_WINDOW_SIZE)-1);else
+xH3
+value/2;long
+cO=value-half
+n73>cO||half<0)std::swap(half,cO);FPO(t03(t43,"value=%ld, half=%ld, otherhalf=%ld\n",value,half,otherhalf))n73==cO){l31
+half,iC,2,iZ+1);}
+else{l31
+half,c02
+l31
+cO>0?cO:-cO,c02}
+iC.iU2
+value);}
+yD
+size_t
+y9
+yO1
+cC1
+y0&eR,yM1{int
+xJ3=iC.Find(value);if(xJ3>=0)yS
+xJ3;}
+long
+xH3
+1;yW1<POWI_TABLE_SIZE){xH3
+powi_table[eW2
+n73&128
+xA2
+if(xI3
+xH3-eX2
+FPO(t03(t43,"* I want %ld, my plan is %ld * %ld\n",value,half,value/half));size_t
+xB2=y9
+half
+e41
+if(iC
+n62
+half)>0||xB2!=e51){tZ1
+xB2)xE2
+half,e51);}
+nQ1
+value/half
+n32
+size_t
+tD3=e51
+xE2
+value,tD3);iC.DumpContents()eO
+tD3;}
+i81
+xI3{xH3-eX2}
+}
+else
+yW1&1)xH3
+value&((1<<POWI_WINDOW_SIZE)-1);else
+xH3
+value/2;long
+cO=value-half
+n73>cO||half<0)std::swap(half,cO);FPO(t03(t43,"* I want %ld, my plan is %ld + %ld\n",value,half,value-half))n73==cO){size_t
+xB2=y9
+half
+e41
+yP1
+xB2,half,xB2,half,iC,eR.op_normal,eR.op_normal_flip,synth);}
+else{long
+part1=half;long
+part2=cO>0?cO:-cO;size_t
+part1_pos=y9
+part1
+e41
+size_t
+part2_pos=y9
+part2
+e41
+FPO(t03(t43,"Subdivide(%ld: %ld, %ld)\n",value,half,otherhalf));yP1
+part1_pos,part1,part2_pos,part2,iC,cO>0?eR.op_normal:eR.op_inverse,cO>0?eR.op_normal_flip:eR.op_inverse_flip,synth);}
+size_t
+tD3=e51
+xE2
+value,tD3);iC.DumpContents()eO
+tD3;}
+x73
+yP1
+size_t
+apos,long
+aval,size_t
+bpos,long
+bval
+cC1
+unsigned
+cumulation_opcode,unsigned
+cumulation_opcode_flip,yM1{int
+a_needed=iC
+n62
+aval);int
+xK3=iC
+n62
+bval);bool
+flipped
+e23
+#define DUP_BOTH() do{if(apos<bpos){size_t tmp=apos;apos=bpos;bpos=tmp e81 FPO(t03(t43,"-> " tB3 tB3"op\n",(unsigned)apos,(unsigned)bpos));tZ1 apos);tZ1 apos==bpos?e51:bpos);}while(0)
+#define DUP_ONE(p) do{FPO(t03(t43,"-> " tB3"op\n",(unsigned)p));tZ1 p);}while(0)
+if(a_needed>0
+cI3
+xK3>0){lV2}
+eN3
+bpos!=e51)lV2
+else{nF2
+e81}
+}
+i81
+xK3>0
+cI3
+apos!=e51)lV2
+else
+DUP_ONE(bpos);}
+eN3
+apos==bpos&&apos==e51)nF2;i81
+apos==e51&&bpos==synth.xH
+2){FPO(t03(t43,"-> op\n"))e81
+i81
+apos==synth.xH
+2&&bpos==e51)FPO(t03(t43,"-> op\n"));i81
+apos==e51)DUP_ONE(bpos);i81
+bpos==e51){nF2
+e81
+else
+lV2}
+n42
+flipped?cumulation_opcode_flip:cumulation_opcode,2);}
+x73
+yX1
+long
+count,y0&eR,yM1{while(count<256){int
+xH3
+x51::powi_table[count]n73&128
+xA2
+yX1
+half
+n32
+count/=half;}
+else
+yY3
+if(count==1)return;if(!(count&1)){n42
+cSqr,1);yX1
+count/2
+n32}
+else{tZ1
+e51);yX1
+count-1
+n32
+n42
+cMul,2);}
+}
+}
+iR2
+x51{x73
+nQ1
+long
+count,y0&eR,yM1{if(count==0)eV1
+eR.basevalue);else{bool
+eY2
+e23
+if(count<0){eY2=true;count=-count;}
+if(false)yX1
+count
+n32
+i81
+count>1){PowiCache
+iC;l31
+count,iC,1);size_t
+x91
+eJ3
+GetStackTop();iC.Start(e51);FPO(t03(t43,"Calculating result for %ld...\n",count));size_t
+xC2=y9
+count
+e41
+size_t
+n_excess
+eJ3
+xH
+x91;if(n_excess>0||xC2!=x91-1){synth.DoPopNMov(x91-1,xC2);}
+}
+if(eY2)n42
+eR.op_flip,1);}
+}
+}
+#endif
+#ifndef FPOptimizer_ValueRangeHH
+#define FPOptimizer_ValueRangeHH
+tC{iR2
+iV2{iN
+cP2
+Comp{}
+;t91>cP2
+Comp<nE
+cLess>{t91
+lF<nC
+cLessOrEq>{t91
+lF<=nC
+cGreater>{t91
+lF>nC
+cGreaterOrEq>{t91
+lF>=nC
+cEqual>{t91
+lF==nC
+tP1>{t91
+lF!=b;}
+}
+;}
+yD
+cP2
+rangehalf{l62
+val;bool
+known;rangehalf():val(),known(false){}
+rangehalf
+cX1
+v):val(v),known(true){x61
+void
+set
+cX1
+v){known=true;val=v
+n63
+set(l62(i01(l62
+nP)val=i11
+void
+set(l62(i01
+cX1
+nP)val=i11
+iN
+void
+set_if(l62
+v,l62(i01(l62
+nP&&iV2::Comp<Compare>()(val,v))val=i11
+iN
+void
+set_if
+cX1
+v,l62(i01
+cX1
+nP&&iV2::Comp<Compare>()(val,v))val=i11}
+;yD
+cP2
+range{rangehalf
+yB
+min,max;range():min(),max(){}
+range(l62
+mi,l62
+ma):min(mi),max(ma){}
+range(bool,l62
+ma):min(),max(ma){}
+range(l62
+mi,bool):min(mi),max(){}
+void
+set_abs();void
+set_neg();}
+;yD
+bool
+IsLogicalTrueValue
+cY1
+range
+yB&p
+eZ2;yD
+bool
+IsLogicalFalseValue
+cY1
+range
+yB&p
+eZ2;}
+#endif
+#ifndef FPOptimizer_RangeEstimationHH
+#define FPOptimizer_RangeEstimationHH
+tC{enum
+TriTruthValue{IsAlways,xL3,Unknown}
+;yD
+range
+yB
+iO
+xB3);yD
+bool
+IsLogicalValue
+cY1
+cV2;yD
+TriTruthValue
+GetIntegerInfo
+cY1
+cV2;yD
+xA1
+GetEvennessInfo
+cY1
+cV2{if(!tree
+yP2
+tJ2
+Unknown;yB1=tree.xE1;if(nE
+isEvenInteger(value
+tJ2
+IsAlways;if(nE
+isOddInteger(value
+tJ2
+xL3
+xD2
+yD
+xA1
+GetPositivityInfo
+cY1
+cV2{range
+yB
+p=iO
+tree);if(p
+eY
+cF3>=l62(tJ2
+IsAlways;if(p
+t6
+yG1
+tJ2
+xL3
+xD2
+yD
+xA1
+GetLogicalValue
+iX2
+tree
+eZ2{range
+yB
+p=iO
+tree);if(IsLogicalTrueValue(p,abs
+tJ2
+IsAlways;if(IsLogicalFalseValue(p,abs
+tJ2
+xL3
+xD2}
+#endif
+#ifndef FPOptimizer_ConstantFoldingHH
+#define FPOptimizer_ConstantFoldingHH
+tC{x73
+ConstantFolding(cV2;}
+#endif
+iR2{using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;cP2
+ComparisonSetBase{enum{cX3=0x1,Eq_Mask=0x2,Le_Mask=0x3,cY3=0x4,cZ3=0x5,Ge_Mask=0x6}
+;static
+int
+Swap_Mask(int
+m)yS(m&Eq_Mask)|((m&cX3)?cY3:0)|((m&cY3)?cX3:0);}
+enum
+yQ1{Ok,BecomeZero,BecomeOne,n21
+nO3
+nG2{cond_or,i92,iA2,iB2}
+;}
+;yD
+cP2
+ComparisonSet:public
+ComparisonSetBase{cP2
+t02{xG
+a;xG
+b;int
+relationship;t02():a(),b(),relationship(){}
+}
+e72
+t02>eB;cP2
+Item{xG
+value;bool
+c12;Item():value(),c12(false){}
+}
+e72
+Item>yY1;int
+xB1;ComparisonSet():eB(),yY1(),xB1(0){}
+yQ1
+AddItem
+iX2
+a,bool
+c12,nG2
+type){for
+x72
+c=0;c<yY1.size();++c)if(yY1[c].value
+xI
+a)cI3
+c12!=yY1[c].c12){iP
+cF1
+case
+iB2:yY1.erase(yY1.begin()+c);xB1
+c22
+case
+i92:case
+iA2:cG1}
+}
+return
+n21;}
+Item
+pole;pole.value=a;pole.c12=c12;yY1
+yS2
+pole)eO
+Ok;}
+yQ1
+AddRelationship(xG
+a,xG
+b,int
+tI1,nG2
+type){iP
+if(tI1==7)cF1
+lD
+iB2:if(tI1==7){xB1
+c22}
+lD
+i92:case
+iA2:if(tI1==0)cG1
+yY3
+if(!(a.GetHash()<b.GetHash())){a.swap(b);tI1=Swap_Mask(tI1);}
+for
+x72
+c=0;c<eB.size();++c
+cI3
+eB[c].a
+xI
+a)&&eB[c].b
+xI
+b)){iP{int
+xM3=yQ2|tI1;if(xM3==7)cF1
+yQ2=xM3;break
+cT1
+i92:case
+iA2:{int
+xM3=yQ2&tI1;if(xM3==0)cG1
+yQ2=xM3;break
+cT1
+iB2:{int
+newrel_or=yQ2|tI1;int
+xF2=yQ2&tI1;iW1
+5&&xF2==0){yQ2=cZ3
+eO
+n21;}
+iW1
+7&&xF2==0){xB1+=1;eB.erase(eB.begin()+c)eO
+n21;}
+iW1
+7&&xF2==Eq_Mask){yQ2=Eq_Mask;xB1
+c22}
+y41}
+}
+return
+n21;}
+}
+t02
+comp;comp.a=a;comp.b=b;comp.relationship=tI1;eB
+yS2
+comp)eO
+Ok;}
+}
+;nH1
+l62,typename
+CondType>bool
+ConstantFolding_LogicCommon(xG&tree,CondType
+x11,bool
+xG2){bool
+should_regenerate
+e23
+ComparisonSet
+yB
+comp;for
+c6
+typename
+yC
+yQ1
+cB3=yC
+Ok;iT1
+atree=xP1
+a);switch(atree
+nF
+e53
+cEqual
+lH
+Eq_Mask,x11);lD
+tP1
+lH
+cZ3,x11);lD
+cLess
+lH
+cX3,x11);lD
+cLessOrEq
+lH
+Le_Mask,x11);lD
+cGreater
+lH
+cY3,x11);lD
+cGreaterOrEq
+lH
+Ge_Mask,x11);lD
+cNot:cB3
+e31
+l8
+0),true,x11);lD
+cNotNot:cB3
+e31
+l8
+0),false,x11
+eP3;y13
+if(xG2||IsLogicalValue(atree))cB3
+e31,false,x11);yX3(cB3){ReplaceTreeWithZero
+e93.ReplaceWithImmed(0)eO
+true;ReplaceTreeWithOne
+e93.ReplaceWithImmed(1);x0
+yC
+Ok:lD
+yC
+BecomeZero
+tE
+yC
+BecomeOne:iA
+yC
+n21:yT1
+yN3
+if(should_regenerate){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Before ConstantFolding_LogicCommon: "
+xY
+#endif
+if(xG2){tree.DelParams();}
+else{for
+c7{iT1
+atree=xP1
+a);if(IsLogicalValue(atree))e61);}
+}
+n72
+0;a<comp.yY1.size();++a
+cI3
+comp.yY1[a].c12
+iW2
+cNot);r
+i8
+r.nU1
+i81!xG2
+iW2
+cNotNot);r
+i8
+r.nU1
+else
+tree
+i8}
+n72
+0;a<comp.eB.size();++a
+iW2
+cNop);switch(comp.eB[a
+i1
+e53
+yC
+cX3:r
+c4
+cLess);lD
+yC
+Eq_Mask:r
+c4
+cEqual);lD
+yC
+cY3:r
+c4
+cGreater);lD
+yC
+Le_Mask:r
+c4
+cLessOrEq);lD
+yC
+cZ3:r
+c4
+tP1);lD
+yC
+Ge_Mask:r
+c4
+cGreaterOrEq);yY3
+r
+y7
+comp.eB[a].a);r
+y7
+comp.eB[a].b);r.nU1
+if(comp.xB1!=0)tree.yJ
+l62(comp.xB1)));
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"After ConstantFolding_LogicCommon: "
+xY
+#endif
+return
+true
+yC3
+e83
+yD
+bool
+ConstantFolding_AndLogic(t53(tree
+tC3()==cAnd||tree
+tC3()==cAbsAnd)eO
+nJ
+i92,true
+nD3
+ConstantFolding_OrLogic(t53(tree
+tC3()==cOr||tree
+tC3()==cAbsOr)eO
+nJ
+cond_or,true
+nD3
+ConstantFolding_AddLogicItems(t53(tree
+tC3()==cAdd)eO
+nJ
+iB2,false
+nD3
+ConstantFolding_MulLogicItems(t53(tree
+tC3()==cMul)eO
+nJ
+iA2,false);}
+}
+#include <vector>
+#include <map>
+#include <algorithm>
+iR2{using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;cP2
+CollectionSetBase{enum
+xC1{Ok,n21}
+;}
+;yD
+cP2
+CollectionSet:public
+CollectionSetBase{cP2
+yR1{xG
+value;xG
+xH2;bool
+e4;yR1():value(),xH2(),e4(false){}
+yR1
+iX2
+v,iT1
+f):value(v),xH2(f),e4(false){}
+}
+;std::multimap<fphash_t,yR1>iD
+tO3
+typename
+std::multimap<fphash_t,yR1>::xR3
+xD1;CollectionSet():iD(){}
+xD1
+FindIdenticalValueTo
+iX2
+value){fphash_t
+hash=value.GetHash();for(xD1
+i=iD.xI2
+hash);i!=iD.cH1
+hash;++i){yW1
+xI
+i
+cW2.value
+tJ2
+i
+yC3
+iD.end();}
+bool
+Found
+cY1
+xD1&b)yS
+b!=iD.end();}
+xC1
+AddCollectionTo
+iX2
+xH2,const
+xD1&into_which){yR1&c=into_which
+cW2;if(c.e4)c.xH2
+cM
+xH2);else{xG
+add;add
+c4
+cAdd);add
+y7
+c.xH2);add
+cM
+xH2);c.xH2.swap(add);c.e4=true
+yC3
+n21;}
+xC1
+nH2
+iX2
+value,iT1
+xH2){const
+fphash_t
+hash=value.GetHash();xD1
+i=iD.xI2
+hash);for(;i!=iD.cH1
+hash;++i
+cI3
+i
+cW2.value
+xI
+value
+tJ2
+AddCollectionTo(xH2,i);}
+iD.xN3,std::make_pair(hash,yR1(value,xH2)))eO
+Ok;}
+xC1
+nH2
+iX2
+a)yS
+nH2(a,n31
+1)));}
+}
+;yD
+cP2
+ConstantExponentCollection{typedef
+nX2
+xP3
+tO3
+std::nV1
+xJ2
+e72
+xJ2>data;ConstantExponentCollection():data(){}
+void
+MoveToSet_Unique
+cX1
+eF1&eG1){data
+yS2
+std::nV1(eF1()));data.back().second.swap(eG1
+n33
+MoveToSet_NonUnique
+cX1
+eF1&eG1){typename
+std::vector<xJ2>::xR3
+i=std::xI2
+data.iC2
+data.end(),nU3,Compare1st());if(i!=data.cH1
+x32{i
+cW2.xN3
+cW2.end(),eG1.iC2
+eG1.end());}
+else{data.xN3,std::nV1(nU3,eG1));}
+}
+bool
+i22{bool
+changed
+e23
+std::sort(data.iC2
+data.end(),Compare1st());redo:n72
+0;a<data.size();++a){l62
+exp_a=data[a
+e03;if(fp_equal(exp_a,l62(1)))y41
+x62
+a+1;b<data.size();++b){l62
+exp_b=data[b
+e03;l62
+xK2=exp_b-exp_a;if(xK2>=fp_abs(exp_a
+lE3
+exp_diff_still_probable_integer=xK2*l62(16);if(t12
+exp_diff_still_probable_integer)&&!(t12
+exp_b)&&!t12
+xK2))){xP3&a_set=iX1;xP3&b_set=data[b].second;
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Before ConstantExponentCollection iteration:\n"
+;t22
+cout);
+#endif
+if(isEvenInteger(exp_b)&&!isEvenInteger(xK2+exp_a)nQ
+tmp2;tmp2
+c4
+cMul);tmp2
+iY1
+b_set);tmp2
+eM1
+t21
+cAbs);tmp
+c43;tmp
+eM1
+b_set
+x53
+1);b_set[0].tV2}
+a_set.insert(a_set.end(),b_set.iC2
+b_set.end());xP3
+b_copy=b_set;data.erase(data.begin()+b);MoveToSet_NonUnique(xK2,b_copy);nS2
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"After ConstantExponentCollection iteration:\n"
+;t22
+cout);
+#endif
+cN}
+}
+}
+return
+changed;}
+#ifdef DEBUG_SUBSTITUTIONS
+void
+t22
+ostream&out){n72
+0;a<data.size();++a){out.precision(12);out<<data[a
+e03<<": "
+;xS3
+iX1.size();++b
+cI3
+b>0)out<<'*'
+yR2
+iX1[b],out);}
+out<<std::endl;}
+}
+#endif
+}
+;yD
+static
+xG
+nW1
+xG&value,bool&xL){switch(value
+nF
+e53
+cPow:{xG
+cY2
+value
+l8
+1);value.y31
+eO
+nU3
+cT1
+cRSqrt:value.y31;xL=true
+eO
+n31-0.5));case
+cInv:value.y31;xL=true
+eO
+n31-1));y13
+break
+yC3
+n31
+1));}
+yD
+static
+void
+eH1
+l12&mul,xB3,iT1
+xH2,bool&yS1
+bool&xL){n72
+0;a<t7;++a
+nQ
+value
+tN3);xG
+nU3(nW1
+value,xL));if(!xH2
+yP2)||xH2.xE1!=l62(1.0)nQ
+cI1;cI1
+c4
+cMul);cI1
+cM
+x32;cI1
+cM
+xH2);cI1
+eM1
+nU3.swap(cI1);}
+#if 0 /* FIXME: This does not work */
+yW1
+nF==cMul
+cI3
+1){bool
+exponent_is_even=nU3
+yP2)&&isEvenInteger(nU3.xE1);xS3
+value.x31++b){bool
+tmp
+e23
+xG
+val(value
+l8
+b));xG
+exp(nW1
+val,tmp));if(exponent_is_even||(exp
+yP2)&&isEvenInteger(exp.xE1))nQ
+cI1;cI1
+c4
+cMul);cI1
+cM
+x32;cI1
+y7
+exp);cI1.ConstantFolding();if(!cI1
+yP2)||!isEvenInteger(cI1.xE1)){goto
+cannot_adopt_mul;}
+}
+}
+}
+eH1
+mul,value,nU3,yS1
+xL);}
+else
+cannot_adopt_mul:
+#endif
+{if(mul.nH2(value,x32==CollectionSetBase::n21)yT1}
+}
+}
+yD
+bool
+ConstantFolding_MulGrouping(cV2{bool
+xL
+e23
+bool
+should_regenerate
+e23
+l12
+mul;eH1
+mul,tree,n31
+1)),yS1
+xL)tO3
+std::pair<xG,nX2>eI1
+tO3
+std::multimap<fphash_t,eI1>yZ1;yZ1
+iE;xL2
+l12::xD1
+j=mul.iD.xQ3
+j!=mul.iD.end();++j
+nQ&value=j
+cW2.value;xG&cY2
+j
+cW2.xH2;if(j
+cW2.e4)nU3
+eM1
+const
+fphash_t
+eJ1=nU3.GetHash();typename
+yZ1::xR3
+i=iE.xI2
+eJ1);for(;i!=iE.cH1
+eJ1;++i)if(i
+cW2.first
+xI
+x32
+cI3!nU3
+yP2)||!cJ1.xE1,l62(1)))yT1
+i
+cW2.second
+yS2
+value);goto
+skip_b;}
+iE.xN3,std::make_pair(eJ1,std::make_pair(nU3,nX2
+x72(1),value))));skip_b:;}
+#ifdef FP_MUL_COMBINE_EXPONENTS
+ConstantExponentCollection
+yB
+cK1;xL2
+yZ1::xR3
+j,i=iE.xQ3
+i!=iE.end();i=j){j=i;++j;eI1&list=i
+cW2;if(list
+y93
+lK1
+cY2
+list
+y93
+xE1;if(!(nU3==tD1)))cK1.MoveToSet_Unique(nU3,list.second);iE.erase(i);}
+}
+if(cK1.i22)yT1
+#endif
+if(should_regenerate
+nQ
+before=tree;before.l41
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Before ConstantFolding_MulGrouping: "
+yR2
+before)xO1"\n"
+;
+#endif
+tree.DelParams();xL2
+yZ1::xR3
+i=iE.xQ3
+i!=iE.end();++i){eI1&list=i
+cW2;
+#ifndef FP_MUL_COMBINE_EXPONENTS
+if(list
+y93
+lK1
+cY2
+list
+y93
+xE1;if(nU3==tD1))y41
+if(cJ1
+n53
+tree.AddParamsMove(list.second);y41}
+}
+#endif
+xG
+mul;mul
+c4
+cMul);mul
+iY1
+list.second);mul
+eM1
+if(xL&&list
+y93
+lO2
+list
+y93
+xE1==l62(1)/l62(3)nQ
+cbrt;cbrt
+c4
+cCbrt);cbrt
+xM2
+cbrt
+eM1
+tree
+y7
+cbrt);y41
+cP
+0.5)nQ
+sqrt;sqrt
+c4
+cSqrt);sqrt
+xM2
+sqrt
+eM1
+tree
+y7
+sqrt);y41
+cP-0.5)nQ
+rsqrt;rsqrt
+c4
+cRSqrt);rsqrt
+xM2
+rsqrt
+eM1
+tree
+y7
+rsqrt);y41
+cP-1)nQ
+inv;inv
+c4
+cInv);inv
+xM2
+inv
+eM1
+tree
+y7
+inv);y41}
+}
+xG
+pow;pow
+c4
+cPow);pow
+xM2
+pow
+y7
+list.first);pow
+eM1
+tree
+y7
+pow);}
+#ifdef FP_MUL_COMBINE_EXPONENTS
+iE.clear();n72
+0;a<i6.size();++a){l62
+cY2
+i6[a
+e03;if(cJ1
+n53
+tree.AddParamsMove(i6[a].second);y41}
+xG
+mul;mul
+c4
+cMul);mul
+iY1
+i6[a].second);mul
+eM1
+xG
+pow;pow
+c4
+cPow);pow
+xM2
+pow.yJ
+x32);pow
+eM1
+tree
+y7
+pow);}
+#endif
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"After ConstantFolding_MulGrouping: "
+xY
+#endif
+return!tree
+xI
+before)yC3
+e83
+yD
+bool
+ConstantFolding_AddGrouping(cV2{bool
+should_regenerate
+e23
+l12
+add;for
+c6
+if
+tN3
+nF==cMul)y41
+if(add.nH2
+tN3)==CollectionSetBase::n21)yT1}
+std::vector<bool>remaining(t7);size_t
+tJ=0;for
+c6
+iT1
+i82=xP1
+a);if(i82
+nF==cMul){xS3
+xY1
+x31++b
+cI3
+i82
+l8
+b)yP2))y41
+typename
+l12::xD1
+c=add.FindIdenticalValueTo(i82
+l8
+b));if(add.Found(c)nQ
+tmp(i82
+lL1
+CloneTag());tmp.DelParam(b);tmp
+eM1
+add.AddCollectionTo(tmp,c);yT1
+goto
+done_a;}
+}
+remaining[a]=true;tJ+=1;done_a:;}
+}
+if(tJ>0
+cI3
+tJ>1){std::vector<std::pair<xG,size_t> >nZ;std::multimap<fphash_t,size_t>eK1;bool
+iY2
+e23
+for
+eX{xS3
+xP1
+a).x31++b){iT1
+p=xP1
+a)l8
+b);const
+fphash_t
+p_hash=p.GetHash();for(std::multimap<fphash_t,size_t>::const_iterator
+i=eK1.xI2
+p_hash);i!=eK1.cH1
+p_hash;++i
+cI3
+nZ[i
+cW2
+e03
+xI
+p)){nZ[i
+cW2].second+=1;iY2=true;goto
+found_mulgroup_item_dup;}
+}
+nZ
+yS2
+std::make_pair(p,size_t(1)));eK1.insert(std::make_pair(p_hash,nZ.size()-1));found_mulgroup_item_dup:;}
+}
+if(iY2
+nQ
+cZ2;{size_t
+max=0;for
+x72
+p=0;p<nZ.size();++p)if(nZ[p].second<=1)nZ[p].second=0;else{nZ[p].second*=nZ[p]y93
+xT2;if(nZ[p].second>max){cZ2=nZ[p
+e03;max=nZ[p].second;}
+}
+}
+xG
+group_add;group_add
+c4
+cAdd);
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Duplicate across some trees: "
+yR2
+cZ2)xO1" in "
+xY
+#endif
+for
+eX
+xS3
+xP1
+a).x31++b)if(cZ2
+xI
+xP1
+a)l8
+b))nQ
+tmp
+tN3
+lL1
+CloneTag());tmp.DelParam(b);tmp
+eM1
+group_add
+y7
+tmp);remaining[a]e23
+yY3
+group_add
+eM1
+xG
+group;group
+c4
+cMul);group
+y7
+cZ2);group
+y7
+group_add);group
+eM1
+add.nH2(group);yT1}
+}
+for
+eX{if(add.nH2
+tN3)==CollectionSetBase::n21)yT1}
+}
+if(should_regenerate){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Before ConstantFolding_AddGrouping: "
+xY
+#endif
+tree.DelParams();xL2
+l12::xD1
+j=add.iD.xQ3
+j!=add.iD.end();++j
+nQ&value=j
+cW2.value;xG&coeff=j
+cW2.xH2;if(j
+cW2.e4)coeff
+eM1
+if(coeff.lO2
+fp_equal(coeff.xE1,tD1)))y41
+if(fp_equal(coeff.xE1
+n53
+tree
+y7
+value);y41}
+}
+xG
+mul;mul
+c4
+cMul);mul
+y7
+value);mul
+y7
+coeff);mul
+eM1
+tree
+xM2}
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"After ConstantFolding_AddGrouping: "
+xY
+#endif
+return
+true
+yC3
+e83}
+iR2{using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;yD
+bool
+ConstantFolding_IfOperations(t53(tree
+tC3()==cIf||tree
+tC3()==cAbsIf);for(;;cI3
+e43
+cNot){tree
+c4
+cIf);tQ
+iD2
+tQ
+xN2
+t32.swap(cC3);}
+i81
+tQ
+c71{tree
+c4
+e63;tQ
+iD2
+tQ
+xN2
+t32.swap(cC3);}
+else
+break;yX3
+nR1
+tQ,i21
+e63)i71
+tree
+iD2
+t32);x0
+iO2
+tree
+iD2
+cC3);x0
+lS1
+if(e43
+cIf||e43
+cAbsIf
+nQ
+cond=tQ;xG
+iZ2;iZ2
+c4
+cond
+nF==cIf?cNotNot:cAbsNotNot);iZ2
+xP2
+1));ConstantFolding(iZ2);xG
+l03;l03
+c4
+cond
+nF==cIf?cNotNot:cAbsNotNot);l03
+xP2
+2));ConstantFolding(l03);if(iZ2
+yP2)||l03
+yP2)nQ
+eS;eS
+c4
+cond
+nF);eS
+xP2
+1));eS.n7
+1));eS.n7
+2));eS
+eM1
+xG
+eT;eT
+c4
+cond
+nF);eT
+xP2
+2));eT.n7
+1));eT.n7
+2));eT
+eM1
+tree
+c4
+cond
+nF)y51
+0,cond
+xN2
+tree.n41
+1,eS);tree.n41
+2,eT)cT2}
+if(t32
+nF==cC3
+nF&&(t32
+nF==cIf||t32
+nF==e63
+nQ&i72=t32;xG&leaf2=cC3;if(i72
+l8
+0)x21
+0))&&(i72
+l8
+1)x21
+1))||i72
+l8
+2)x21
+2)))nQ
+eS;eS
+n82
+eS.n7
+0));eS
+cM
+i72
+l8
+1));eS
+cM
+leaf2
+l8
+1));eS
+eM1
+xG
+eT;eT
+n82
+eT.n7
+0));eT
+cM
+i72
+l8
+2));eT
+cM
+leaf2
+l8
+2));eT
+t5
+SetParam(0,i72
+xN2
+tree.n41
+1,eS);tree.n41
+2,eT)cT2
+if(i72
+l8
+1)x21
+1))&&i72
+l8
+2)x21
+2))nQ
+eU;eU
+n82
+eU
+y7
+tQ);eU
+cM
+i72
+xN2
+eU
+cM
+leaf2
+xN2
+eU
+t5
+n41
+0,eU)y51
+2,i72
+l8
+2))y51
+1,i72
+l8
+1))cT2
+if(i72
+l8
+1)x21
+2))&&i72
+l8
+2)x21
+1))nQ
+e02;e02
+c4
+leaf2
+nF==cIf?cNot:c03);e02
+cM
+leaf2
+xN2
+e02
+eM1
+xG
+eU;eU
+n82
+eU
+y7
+tQ);eU
+cM
+i72
+xN2
+eU
+y7
+e02);eU
+t5
+n41
+0,eU)y51
+2,i72
+l8
+2))y51
+1,i72
+l8
+1))cT2}
+xG&y2=t32;xG&y6=cC3;if(y2
+xI
+y6)){tree
+iD2
+t32)cT2
+const
+OPCODE
+op1=y2
+nF;const
+OPCODE
+op2=y6
+nF;cL3
+op2
+cI3
+y2
+yU1
+1
+nQ
+lP
+0));xQ2
+0))iZ1
+n4
+if(y2
+yU1
+2&&y6
+yU1
+2
+cI3
+y2
+l8
+0)xI
+y6
+l8
+0))nQ
+param0=y2
+l8
+0);xG
+lP
+1));xQ2
+1))iZ1
+e12
+param0)n4
+if(y2
+l8
+1)xI
+y6
+l8
+1))nQ
+param1=y2
+l8
+1);xG
+lP
+0));xQ2
+0))iZ1
+e12
+n11)e12
+param1)cT2}
+cL3
+xT3
+cMul
+l02
+cAnd
+l02
+cOr
+l02
+cAbsAnd
+l02
+cAbsOr
+l02
+cMin
+l02
+cMax){nX2
+l13;c3{x62
+y6.x31
+b-->0;){nI2
+y6
+l8
+b))cI3
+l13
+yU3){y2.e73
+l41}
+l13
+yS2
+y2
+lS3
+y6.DelParam(b);y2.DelParam(a);yN3}
+if(!l13
+yU3){y2.Rehash(eL1
+n11;n11
+n82
+n11
+iY1
+tree.iP1))yF
+SetParamsMove(l13)n4}
+}
+cL3
+xT3
+cMul||(op1==cAnd
+nK1
+y6))||(op1==cOr
+nK1
+y6))){c3
+nI2
+y6)){y2.l41
+y2.DelParam(a);y2
+eM1
+xG
+c01=y6;y6=tK
+op1==xT3
+cOr)l9
+op1)e12
+c01)n4}
+if((op1==cAnd
+l02
+cOr)&&op2==cNotNot
+nQ&l23=y6
+l8
+0);c3
+nI2
+l23)){y2.l41
+y2.DelParam(a);y2
+eM1
+xG
+c01=l23;y6=tK
+op1
+xU3
+op1)e12
+c01)n4}
+if(op2==cAdd||op2==cMul||(op2==cAnd
+nK1
+y2))||(op2==cOr
+nK1
+y2))){n72
+y6.n93
+y6
+l8
+a)xI
+y2)){y6.e73
+DelParam(a
+eL1
+c11=y2;y2=tK
+op2==cAdd||op2
+xU3
+op2)e12
+c11)n4}
+if((op2==cAnd||op2==cOr)&&op1==cNotNot
+nQ&l33=y2
+l8
+0);n72
+y6.n93
+y6
+l8
+a)xI
+l33)){y6.e73
+DelParam(a
+eL1
+c11=l33;y2=tK
+op2
+xU3
+op2)e12
+c11)n4}
+return
+e83}
+#include <limits>
+iR2{using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;yD
+int
+maxFPExponent()yS
+std::numeric_limits
+yB::max_exponent;}
+yD
+bool
+tE1
+l62
+base,l62
+x32{if(base<tD1
+t41;if(fp_equal(base,tD1))||fp_equal(base,l62(1))c5
+return
+nU3>=l62(maxFPExponent
+yB())/fp_log2(base);}
+yD
+int
+nY1
+l62
+val){int
+ex=0;l62
+t=std::frexp(val,&ex);unsigned
+yO1=fp_abs(t)*(1u<<30),v0=value;unsigned
+int
+nT3=0;while(!(value&1))value>>=1;for(;value!=0;value>>=1)++nT3
+eO
+nT3;}
+yD
+bool
+ConstantFolding_PowOperations(t53(tree
+tC3()==cPow);cD3
+t32.lK1
+const_value
+xV3
+lS,tM));tree.ReplaceWithImmed(const_value)eO
+e83
+if
+lM1
+fp_equal(tM)n53
+tree
+iD2
+tQ)cT2
+cD3
+fp_equal(lS,l62(1)nR
+1)eO
+e83
+cD3
+t32
+nF==cMul){bool
+xR2
+e23
+l62
+eO1=lS;xG
+i82=t32;n72
+xY1
+n93
+i82
+l8
+a).lK1
+imm=i82
+l8
+a).xE1;{if(tE1
+eO1,imm
+lE3
+c21
+xV3
+eO1,imm);if(fp_equal(c21,tD1)))break;if(nY1
+c21)<(nY1
+eO1)+nY1
+imm))/4){yY3
+if(!xR2){xR2=true;xY1
+l41}
+eO1=c21;xY1
+DelParam(a);yN3
+if(xR2){xY1
+Rehash();
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Before pow-mul change: "
+xY
+#endif
+tQ
+iD2
+cL1
+eO1));t32
+iD2
+i82);
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"After pow-mul change: "
+xY
+#endif
+}
+}
+if
+lM1
+e43
+cMul){l62
+l72=tM);l62
+xS2=1.0;bool
+xR2
+e23
+xG&i82=tQ;n72
+xY1
+n93
+i82
+l8
+a).lK1
+imm=i82
+l8
+a).xE1;{if(tE1
+imm,l72
+lE3
+eP1
+xV3
+imm,l72);if(fp_equal(eP1,tD1)))break;if(!xR2){xR2=true;xY1
+l41}
+xS2*=eP1;xY1
+DelParam(a);yN3
+if(xR2){xY1
+Rehash();xG
+cH3;cH3
+c4
+cPow);cH3
+iY1
+tree.iP1));cH3.lF2
+tree
+c4
+cMul)e12
+cH3);tree
+cM
+cL1
+xS2))cT2}
+if(e43
+cPow&&xP1
+yO2&&tQ
+l8
+1).lK1
+a=tQ
+l8
+1).xE1;l62
+b=tM);l62
+c=a*b;if(isEvenInteger(a)&&!isEvenInteger(c)nQ
+l43;l43
+c4
+cAbs);l43.n7
+0)xN2
+l43
+eM1
+tree.n41
+0,l43);}
+else
+tree.SetParam(0,tQ
+l8
+0))y51
+1,cL1
+c))yC3
+e83}
+iR2{using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;cP2
+l4{enum
+e22{MakeFalse=0,MakeTrue=1,t42=2,l73=3,MakeNotNotP0=4,MakeNotNotP1=5,MakeNotP0=6,MakeNotP1=7,xK=8
+nO3
+l82{Never=0,Eq0=1,Eq1=2,xW3=3,xX3=4}
+;e22
+if_identical;e22
+l92
+4];cP2{e22
+what:4;l82
+when:4;}
+iA1,iB1,iC1,iD1;yD
+e22
+Analyze
+iX2
+a,iT1
+b)const{if(a
+xI
+b
+tJ2
+if_identical;range
+yB
+p0=iO
+a);range
+yB
+p1=iO
+b);if(p0
+t6&&p1
+eY
+cI3
+p0
+nV<p1
+e32&&l92
+0]i7
+0];if(p0
+nV<=p1
+e32&&l92
+1]i7
+1];}
+if(p0
+eY&&p1
+t6
+cI3
+p0
+e32>p1
+nV&&l92
+2]i7
+2];if(p0
+e32>=p1
+nV&&l92
+3]i7
+3];}
+if(IsLogicalValue(a)cI3
+iA1
+e92
+iA1.when,p1
+tJ2
+iA1.what;if(iC1
+e92
+iC1.when,p1
+tJ2
+iC1.what;}
+if(IsLogicalValue(b)cI3
+iB1
+e92
+iB1.when,p0
+tJ2
+iB1.what;if(iD1
+e92
+iD1.when,p0
+tJ2
+iD1.what
+yC3
+xK;}
+yD
+static
+bool
+TestCase(l82
+when,const
+range
+yB&p
+cI3!p
+eY||!p
+t6
+c5
+switch(when
+e53
+Eq0
+nM1==l62(0.0
+eB3==p
+e32;case
+Eq1
+nM1==l62(1.0
+eB3==p
+nV;case
+xW3
+nM1>tD1
+eB3<=l62(1);case
+xX3
+nM1
+cW1
+yG1
+1);y13
+yC3
+e83}
+;iR2
+RangeComparisonsData{static
+const
+l4
+Data[6]={{l4
+l53
+i2
+xK,l4::i2
+xK}
+,n71
+Eq1}
+,n81
+Eq1}
+,{l4::c31
+Eq0}
+,{l4::c41
+Eq0}
+}
+,{l4::nJ2
+l63
+xK,l4
+l63
+xK}
+,n71
+Eq0}
+,n81
+Eq0}
+,{l4::c31
+Eq1}
+,{l4::c41
+Eq1}
+}
+,{l4::nJ2
+l63
+t42,l4::i2
+MakeFalse}
+,{l4::c31
+xW3}
+,n81
+xX3
+yZ,{l4
+l53
+xK,l4
+l63
+i2
+l73}
+,{l4::c31
+xX3}
+,n81
+xW3
+yZ,{l4::nJ2::i2
+i2
+MakeTrue,l4::t42}
+,n71
+xX3}
+,{l4::c41
+xW3
+yZ,{l4
+l53
+i2
+l73,l4::xK,l4
+n61}
+,n71
+xW3}
+,{l4::c41
+xX3
+yZ}
+;}
+yD
+bool
+ConstantFolding_Comparison(cV2{using
+iR2
+RangeComparisonsData;assert(tree tC3()>=cEqual&&tree tC3()<=cGreaterOrEq);switch(Data[tree
+nF-cEqual].Analyze(tQ,t32)e53
+l4::MakeFalse
+e93.ReplaceWithImmed(0);x0
+l4
+n61
+e93.ReplaceWithImmed(1
+l52
+l73
+e93
+c4
+cEqual
+l52
+t42
+e93
+c4
+tP1
+l52
+MakeNotNotP0
+e93
+c4
+cNotNot)lP2
+1
+l52
+MakeNotNotP1
+e93
+c4
+cNotNot)lP2
+0
+l52
+MakeNotP0
+e93
+c4
+cNot)lP2
+1
+l52
+MakeNotP1
+e93
+c4
+cNot)lP2
+0
+l52
+xK:;}
+if(xP1
+yO2)switch(tQ
+nF
+e53
+cAsin:lN
+fp_sin
+xY3
+cAcos:lN
+fp_cos
+tL));tree
+c4
+i21
+cLess?cGreater:i21
+cLessOrEq?cGreaterOrEq:i21
+cGreater?cLess:i21
+cGreaterOrEq?cLessOrEq
+e93
+nF);x0
+cAtan:lN
+fp_tan
+xY3
+cLog:lN
+fp_exp
+xY3
+cSinh:lN
+fp_asinh
+xY3
+cTanh:if(fp_less(fp_abs
+tL
+n53
+lN
+fp_atanh
+tL))cT2
+break;y13
+break
+yC3
+e83}
+#include <list>
+#include <algorithm>
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;iR2{
+#ifdef DEBUG_SUBSTITUTIONS
+yM
+double
+d){union{double
+d;uint_least64_t
+h;}
+t52
+d=d;lG1
+h
+nN1
+#ifdef FP_SUPPORT_FLOAT_TYPE
+yM
+float
+f){union{float
+f;uint_least32_t
+h;}
+t52
+f=f;lG1
+h
+nN1
+#endif
+#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
+yM
+long
+double
+ld){union{long
+double
+ld;cP2{uint_least64_t
+a;unsigned
+short
+b;}
+s;}
+t52
+ld=ld;lG1
+s.b<<data.s.a
+nN1
+#endif
+#ifdef FP_SUPPORT_LONG_INT_TYPE
+yM
+long
+ld){o<<"("
+<<std::hex<<ld
+nN1
+#endif
+#endif
+}
+tC{lO
+nG)){}
+lO
+const
+l62&i
+lL1
+x23
+nG
+i)){data
+xE
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+lO
+l62&&i
+lL1
+x23
+nG
+std::move(i))){data
+xE
+#endif
+lO
+unsigned
+v
+lL1
+VarTag
+nG
+iE2,v))c32
+nW2
+o
+lL1
+OpcodeTag
+nG
+o))c32
+nW2
+o,unsigned
+f
+lL1
+FuncOpcodeTag
+nG
+o,f))c32
+iT1
+b
+lL1
+CloneTag
+nG*b.data)){}
+yD
+xG::~CodeTree(){}
+lC
+ReplaceWithImmed
+cX1
+i){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Replacing "
+yR2*this);if(IsImmed())OutFloatHex(std::cout,xE1)xO1" with const value "
+<<i;OutFloatHex(std::cout,i)xO1"\n"
+;
+#endif
+data=new
+x42
+yB(i);}
+yD
+cP2
+ParamComparer{bool
+eD1()iX2
+a,iT1
+b)const{if(a.xT2!=b.xT2)return
+a.xT2<b.xT2
+eO
+a.GetHash()<b.GetHash();}
+}
+;x73
+x42
+yB::Sort(){switch(Opcode
+e53
+cAdd:case
+cMul:case
+cMin:case
+cMax:case
+cAnd:case
+cAbsAnd:case
+cOr:case
+cAbsOr:case
+cHypot:case
+cEqual:case
+tP1:std::sort(x83
+iC2
+x83
+end(),ParamComparer
+yB());lD
+cLess
+lZ
+cGreater;}
+lD
+cLessOrEq
+lZ
+cGreaterOrEq;}
+lD
+cGreater
+lZ
+cLess;}
+lD
+cGreaterOrEq
+lZ
+cLessOrEq;}
+break;y13
+yN3
+lC
+AddParam
+iX2
+param){y3
+yS2
+param);}
+lC
+eE
+xG&param){y3
+yS2
+xG());y3.back().swap(param);}
+lC
+SetParam
+x72
+which,iT1
+b)nO1
+which
+xZ3
+y3[which]=b;}
+lC
+n41
+size_t
+which,xG&b)nO1
+which
+xZ3
+y3[which
+eO3
+b);}
+lC
+AddParams
+cY1
+nK){y3.insert(y3.end(),lA2.iC2
+lA2.end());}
+lC
+AddParamsMove(nK){size_t
+endpos=y3.size(),added=lA2.size();y3
+x53
+endpos+added,xG());for
+x72
+p=0;p<added;++p)y3[endpos+p
+eO3
+lA2[p]);}
+lC
+AddParamsMove(nK,size_t
+lB2)nO1
+lB2
+xZ3
+DelParam(lB2);AddParamsMove(t81}
+lC
+SetParams
+cY1
+nK){nX2
+tmp(t81
+y3.tV2}
+lC
+SetParamsMove(nK){y3.swap(t81
+lA2.clear();}
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+lC
+SetParams(nX2&&lA2){SetParamsMove(t81}
+#endif
+lC
+DelParam
+x72
+index){nX2&Params=y3;
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+x83
+erase(x83
+begin()+index);
+#else
+Params[index].data=0;for
+x72
+p=index;p+1<y03;++p)Params[p].data.UnsafeSetP(Params[p+1]t62));Params[y03-1].data.UnsafeSetP(0);Params
+x53
+y03-1);
+#endif
+}
+lC
+DelParams(){y3.clear(nD3
+xG::IsIdenticalTo
+iX2
+b)const{if(data.get()==b
+t62
+t41
+eO
+data->IsIdenticalTo(*b.data
+nD3
+x42
+yB::IsIdenticalTo
+cY1
+x42
+yB&b)const{if(Hash!=b.Hash
+c5
+if(Opcode!=eL3
+c5
+switch(Opcode
+e53
+cImmed:return
+fp_equal(Value,eM3;case
+iE2:return
+iR1==b.iQ1
+case
+cFCall:case
+cPCall:if(iR1!=b.iR1
+c5
+break;y13
+yY3
+if(y03!=b.y03
+c5
+n72
+0;a<y03;++a
+cI3!x93
+xI
+b.x93)c5}
+return
+true;}
+lC
+Become
+iX2
+b
+cI3&b!=this&&data.get()!=b
+t62)){DataP
+tmp=b.data;l41
+data.tV2}
+}
+lC
+CopyOnWrite(cI3
+GetRefCount()>1)data=new
+x42
+yB(*data);}
+yD
+xG
+xG::GetUniqueRef(cI3
+GetRefCount()>1)return
+xG(*this,CloneTag())eO*this;}
+yD
+nO):yU
+cNop),Value(),n9
+yD
+nO
+const
+x42&b):yU
+eL3),Value(eM3,iR1(b.c51,Params(b.Params),Hash(b.Hash),Depth(b.Depth),tJ1
+b.iS1){}
+yD
+nO
+const
+l62&i):yU
+cImmed),Value(i),n9
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+yD
+nO
+x42
+yB&&b):yU
+eL3),Value
+cX2
+eM3),iR1(b.c51,Params
+cX2
+b.Params)),Hash(b.Hash),Depth(b.Depth),tJ1
+b.iS1){}
+yD
+nO
+l62&&i):yU
+cImmed),Value
+cX2
+i)),n9
+#endif
+yD
+nO
+nW2
+o):yU
+o),Value(),n9
+yD
+nO
+nW2
+o,unsigned
+f):yU
+o),Value(),iR1(f),Params(),Hash(),Depth(1),tJ1
+0){}
+}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <sstream>
+#include <string>
+#include <map>
+#include <set>
+#include <iostream>
+using
+iR2
+FUNCTIONPARSERTYPES;
+#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
+iR2{x73
+tK1
+nU,std
+cF&done,std::ostream&o){n72
+0
+tH2
+tK1
+tJ3
+done,o);std::ostringstream
+buf
+yR2
+tree,buf);done[xC3].insert(buf.str());}
+}
+#endif
+tC{
+#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
+x73
+DumpHashes(i9){std
+cF
+done;tK1
+tree,done,o);for(std
+cF::const_iterator
+i=done.xQ3
+i!=done.end();++i){const
+std::set<std
+yE3>&flist=i
+cW2;if(flist.size()!=1)o<<"ERROR - HASH COLLISION?\n"
+;for(std::set<std
+yE3>::const_iterator
+j=flist.xQ3
+j!=flist.end();++j){o<<'['<<std::hex<<i->first.hash1<<','<<i->first.hash2<<']'<<std::dec;o<<": "
+<<*j<<"\n"
+;}
+}
+}
+x73
+DumpTree(i9){nA3
+t33;switch
+l83{case
+cImmed:o<<tree.xE1
+eA3
+iE2:o<<"Var"
+<<(tree.GetVar()-iE2)eA3
+cAdd:t33"+"
+;lD
+cMul:t33"*"
+;lD
+cAnd:t33"&"
+;lD
+cOr:t33"|"
+;lD
+cPow:t33"^"
+;break;y13
+t33;o<<eK3
+l83;if(i21
+cFCall||i21
+cPCall)o<<':'<<tree.GetFuncNo();}
+o<<'(';if(t7<=1&&sep2[1])o<<(sep2+1)<<' ';for
+c6
+if(a>0)o<<' '
+yR2
+tJ3
+o);if(a+1<t7)o<<sep2;}
+o<<')';}
+x73
+DumpTreeWithIndent(i9,const
+std
+yE3&indent){o<<'['<<std::hex<<(void*)(&tree.iP1))<<std::dec<<','<<tree.GetRefCount()<<']';o<<indent<<'_';switch
+l83{case
+cImmed:o<<"cImmed "
+<<tree.xE1;o<<'\n'
+eA3
+iE2:o<<"VarBegin "
+<<(tree.GetVar()-iE2);o<<'\n'
+eO;y13
+o<<eK3
+l83;if(i21
+cFCall||i21
+cPCall)o<<':'<<tree.GetFuncNo();o<<'\n';}
+for
+c6
+std
+yE3
+ind=indent;for
+x72
+p=0;p<ind.size();p+=2)if(ind[p]=='\\')ind[p]=' ';ind+=(a+1<t7)?" |"
+:" \\"
+;DumpTreeWithIndent(tJ3
+o,ind);}
+o<<std::flush;}
+#endif
+}
+#endif
+using
+iR2
+l21;using
+iR2
+FUNCTIONPARSERTYPES;
+#include <cctype>
+iR2
+l21{unsigned
+ParamSpec_GetDepCode
+cY1
+cS2&b){switch(b.first
+e53
+ParamHolder:{cQ*s=(cQ*)b.second
+eO
+s->depcode
+cT1
+SubFunction:{cR*s=(cR*)b.second
+eO
+s->depcode;}
+y13
+break
+yC3
+0;}
+x73
+DumpParam
+cY1
+cS2&x02,std::ostream&o){static
+const
+char
+ParamHolderNames[][2]={"%"
+,"&"
+,"x"
+,"y"
+,"z"
+,"a"
+,"b"
+,"c"
+}
+;unsigned
+xU2
+0;switch(x02.first
+e53
+NumConstant:{const
+ParamSpec_NumConstant
+yB
+y63
+cY1
+ParamSpec_NumConstant
+yB*e62;using
+iR2
+FUNCTIONPARSERTYPES;o.precision(12);o<<yA3
+constvalue;break
+cT1
+ParamHolder:{cQ
+y63(cQ*e62;o<<ParamHolderNames[yA3
+index];xU2
+yA3
+constraints;break
+cT1
+SubFunction:{cR
+y63(cR*e62;xU2
+yA3
+constraints;yN
+GroupFunction){l93
+l51==cNeg){o<<"-"
+;n1}
+i81
+yA3
+l51==cInv){o<<"/"
+;n1}
+else{std
+yE3
+opcode=eK3((nW2)yA3
+l51).substr(1);n72
+0;a<opcode.size();++a)opcode[a]=(char)std::toupper(opcode[a]);o<<opcode<<"( "
+;n1
+o<<" )"
+;}
+}
+else{o<<'('<<eK3((nW2)yA3
+l51)<<' ';yN
+PositionalParams)o<<'[';yN
+SelectedParams)o<<'{';n1
+l93
+data.n0!=0)o<<" <"
+<<yA3
+data.n0<<'>';yN
+PositionalParams)o<<"]"
+;yN
+SelectedParams)o<<"}"
+;o<<')';}
+yN3
+switch(ImmedConstraint_Value(constraints&ValueMask)e53
+ValueMask:lD
+Value_AnyNum:lD
+nK2:o<<"@E"
+;lD
+Value_OddInt:o<<"@O"
+;lD
+tM1:o<<"@I"
+;lD
+Value_NonInteger:o<<"@F"
+;lD
+eQ1:o<<"@L"
+;y73
+ImmedConstraint_Sign(constraints&SignMask)e53
+SignMask:lD
+Sign_AnySign:lD
+n91:o<<"@P"
+;lD
+eR1:o<<"@N"
+;y73
+ImmedConstraint_Oneness(constraints&OnenessMask)e53
+OnenessMask:lD
+Oneness_Any:lD
+Oneness_One:o<<"@1"
+;lD
+Oneness_NotOne:o<<"@M"
+;y73
+ImmedConstraint_Constness(constraints&ConstnessMask)e53
+ConstnessMask:lD
+tL1:if(x02.first==ParamHolder){cQ
+y63(cQ*e62;l93
+index<2)yY3
+o<<"@C"
+;lD
+Constness_NotConst:o<<"@V"
+;lD
+Oneness_Any:yN3
+x73
+DumpParams
+nD2
+paramlist,unsigned
+count,std::ostream&o){for
+nD2
+a=0;a<count;++a
+cI3
+a>0)o<<' ';const
+cS2&param=cR1
+yB(paramlist,a);DumpParam
+yB(param,o);unsigned
+depcode=ParamSpec_GetDepCode(param);if(depcode!=0)o<<"@D"
+<<depcode;}
+}
+}
+#include <algorithm>
+using
+iR2
+l21;using
+iR2
+FUNCTIONPARSERTYPES;iR2{cQ
+plist_p[37]={{2,0,0x0}
+x9
+0,0x4}
+x9
+n91,0x0}
+x9
+eR1|Constness_NotConst,0x0}
+x9
+Sign_NoIdea,0x0}
+x9
+eQ1,0x0}
+,{3,Sign_NoIdea,0x0}
+,{3,0,0x0}
+,{3,eQ1,0x0}
+,{3,0,0x8}
+,{3,Value_OddInt,0x0}
+,{3,Value_NonInteger,0x0}
+,{3,nK2,0x0}
+,{3,n91,0x0}
+,{0,eR1|lW{0,lW{0,n91|lW{0,nK2|lW{0,tL1,0x1}
+,{0,tM1|n91|lW{0,tN1
+tL1,0x1}
+,{0,tN1
+lW{0,Oneness_One|lW{0,eQ1|lW{1,lW{1,nK2|lW{1,tN1
+lW{1,tM1|lW{1,n91|lW{1,eR1|lW{6,0,0x0}
+,{4,0,0x0}
+,{4,tM1,0x0}
+,{4,lW{4,0,0x16}
+,{5,0,0x0}
+,{5,lW}
+;yD
+cP2
+plist_n_container{static
+const
+ParamSpec_NumConstant
+yB
+plist_n[20];}
+;yD
+const
+ParamSpec_NumConstant
+yB
+plist_n_container
+yB::plist_n[20]={{l62(-2
+i3-1
+i3-0.5
+i3-0.25
+i3
+0
+t72
+fp_const_deg_to_rad
+yB(t72
+fp_const_einv
+yB(t72
+fp_const_log10inv
+yB(i3
+0.5
+t72
+fp_const_log2
+yB(i3
+1
+t72
+fp_const_log2inv
+yB(i3
+2
+t72
+fp_const_log10
+yB(t72
+fp_const_e
+yB(t72
+fp_const_rad_to_deg
+yB(t72-fp_const_pihalf
+yB(),xG1{tD1),xG1{fp_const_pihalf
+yB(),xG1{fp_const_pi
+yB(),xG1}
+;cR
+plist_s[517]={{{1,15,t82
+398,t82
+477,t82
+15,cNeg,GroupFunction,0}
+,tL1,0x1
+tL3
+15,xV2
+24,xV2
+465,xV2
+466,xV2
+498,cInv,lU
+2,327995
+xC
+eB2
+48276
+xC
+l6
+260151
+xC
+l6
+470171
+xC
+l6
+169126
+xC
+l6
+48418
+xC
+l6
+1328
+xC
+l6
+283962
+xC
+l6
+169275
+xC
+l6
+39202
+xC
+l6
+283964
+xC
+l6
+283973
+xC
+l6
+476619
+xC
+l6
+296998
+xC
+l6
+47
+xC
+SelectedParams,0}
+,0,0x4
+nM
+161839
+xC
+l6
+25036
+xC
+l6
+35847
+xC
+l6
+60440
+xC
+l6
+30751
+xC
+l6
+183474
+xC
+l6
+259318
+xC
+l6
+270599
+xC
+l6
+60431
+xC
+l6
+259119
+xC
+l6
+332066
+xC
+l6
+7168
+xC
+l6
+197632
+xC
+l6
+291840
+xC
+l6
+283648
+xC
+l6
+238866
+xC
+l6
+239902
+xC
+l6
+31751
+xC
+l6
+244743
+xC
+l6
+384022
+xC
+SelectedParams,0}
+,0,0x4
+nM
+385262
+xC
+l6
+386086
+xC
+l6
+393254
+xC
+SelectedParams,0}
+,0,0x5
+nM
+393254
+xC
+l6
+386095
+xC
+l6
+387312
+xC
+l6
+18662
+xC
+l6
+61670
+xC
+l6
+387397
+xC
+l6
+247855
+xC
+SelectedParams,0}
+,0,0x1
+nM
+342063
+xC
+l6
+297007
+xC
+l6
+15820
+xC
+l6
+393263
+xC
+l6
+393263
+xC
+SelectedParams,0}
+,0,0x5
+nM
+161847
+xC
+l6
+258103
+xC
+l6
+249073
+xC
+l6
+249076
+xC
+iF
+0,0
+xC
+nL
+0,0
+tO1
+1,45
+xC
+nL
+1,53
+xC
+nL
+1,54
+xC
+nL
+1,55
+xC
+nL
+1,56
+xC
+nL
+1,26
+xC
+nL
+1,259
+tP
+1}
+,0,0x16
+tL3
+272
+tO1
+1,323
+tP
+1}
+,0,0x16
+tL3
+0
+xC
+nL
+1,21
+xC
+nL
+1,447
+tP
+1}
+nE2
+449
+tP
+1}
+nE2
+0
+tP
+1}
+nE2
+0
+tP
+2}
+nE2
+15
+xC
+nL
+1,24
+tP
+2}
+,0,0x0
+nM
+58392
+tO1
+0,0
+tP
+1}
+,n91,0x0
+nM
+24591
+nC3
+33807
+nC3
+48143
+nC3
+285720
+nC3
+290840
+nC3
+305152,lA
+312400,lA
+39202,lA
+122918,lA
+421926,lA
+429094,lA
+443430,lA
+317834,lA
+329098,lA
+7633,lA
+7706,lA
+7730,lA
+38,lA
+50587,lA
+406528,lA
+24583,lA
+31751,lA
+405511,lA
+321551,xH1
+327713,lA
+322596,lA
+90409,lA
+335174,lA
+327050,lA
+493606,lA
+496678,lA
+503846,lA
+516134,lA
+7217,lA
+333875,lA
+336896,lA
+524326,lA
+509952,lA
+286727,lA
+89103,lA
+92175,lA
+296976,tA1
+324623,l1
+0x14
+nM
+332815,l1
+0x10}
+,{{3,7340056,tA1
+289092,lA
+93200,xH1
+337935
+tF1
+7340060,l1
+t92
+7340176,lA
+338959
+tF1
+7340061,xH1
+7206,lA
+7168,lA
+357414,lA
+368678,lA
+370745
+eV3}
+,{{3,7340177,lA
+39277,tA1
+426398,l1
+t92
+40272286,xH1
+490910,l1
+t92
+40336798,xH1
+50600,lA
+426462,xH1
+490974,xH1
+370726,l1
+0x6
+nM
+371750,l1
+0x6
+nM
+428070
+tF1
+40336862,xH1
+38378,lA
+50671
+tF1
+47662080,lA
+477184,lA
+568320,lA
+371727
+eV3}
+,{{3,15779306,lA
+370703
+eV3
+nM
+39277,lA
+39279,l1
+0x4}
+,{{3,15779238,lA
+39338,tA1
+436262,lA
+508966,lA
+39409,tA1
+296998,tA1
+35847,lA
+15,tA1
+377894,lA
+386063,l1
+0x1
+nM
+15,lA
+7192,lA
+123928,lA
+122904,lA
+30751,lA
+57,lA
+7456,lA
+15674
+tF1
+67579935,lA
+39237,lA
+58768,lA
+62924,lA
+122880,lA
+15760
+tF1
+64009216,l1
+0x0}
+,{{0,0,xM
+0,0,iM
+2,cM1
+2,cN1
+3,cM1
+3,cN1
+38,xM
+1,38,iM
+14,xM
+1,57,xM
+1,16,eA2
+0x0
+nM
+471103,eA2
+0x1
+tL3
+303,xM
+1,323,yF3
+0x0
+nM
+471363,eA2
+0x16
+tL3
+293,cM1
+294,cN1
+295,xM
+1,296,iM
+400,xM
+1,0,xM
+1,460,xM
+1,465,xM
+1,16,eA2
+0x1
+tL3
+57,yF3
+0x1
+tL3
+0,iM
+21,xM
+1,15,eA2
+0x0
+nM
+24591,xM
+1,24,iM
+517,yF3
+0x0
+nM
+46095,lL
+46104,lL
+15397,lL
+287789,lL
+66584,lL
+404763,lL
+62504,lL
+15409,lL
+39951,lL
+24591,lL
+33807,lL
+50200,lL
+62509,lL
+50176,lG,178176,eS1
+0x12
+nM
+283648,lG,19456,lG,27648,lG,91136,lG,86016,lG,488448,lG,14342,lG,58375,lG,46147
+iX
+46151,lG,284679,lG,7183,lG,46159
+iX
+38993
+iX
+50262,lG,50249,lG,283808,lG,284835,lG,24822,lG,10240,lG,11264,lG,7170,lG,7168,lG,17408,lG,164864,lG,237568,lG,242688,eS1
+0x14
+nM
+476160,lG,25607,lG,122895,lG,50252,lG,39374,lG,50183,lG,7192,lG,122911,lG,252979,lG,46155,lG,38919,lG,50268,lG,50269,lG,50253,lG,46191,lG,50296,lG,7563,eS1
+0x10
+nM
+416811,lG,416819,lG,40047,lG,46192
+iX
+415795,lG,40048
+iX
+415787,lG,39016,eS1
+0x5
+nM
+39326
+iX
+39326,lG,39332,eS1
+0x5
+nM
+39333,eS1
+0x1
+nM
+50590
+iX
+50590,lG,39338
+iX
+39338,lG,39335,eS1
+0x5
+nM
+15786
+iX
+146858,lG,39372,lG,39379,lG,39380,lG,39390
+iX
+50654
+iX
+50654,lG,24,eS1
+0x6
+nM
+62,lG,24,lG,62,eS1
+0x6
+nM
+43,lG,43
+iX
+51,lG,51
+iX
+50270,lG,50176
+iX
+50271,lG,39159,lG,39183
+iX
+7168
+iX
+31744,lG,100352,lG,31746,lG,101400,lG,39409
+iX
+39411
+iX
+39411,lG,39420,lG,39420
+iX
+15,lG,39026,eS1
+0x5
+nM
+39422,lG,16384,lG,62853,lG,15360,lG,15,eS1
+0x1
+nM
+16,lG,7183,eS1
+0x1
+nM
+7172,cPow,y21,n91,0x0
+nM
+24591,cPow,lU
+2,50200,cPow,lU
+2,63521,cPow,lU
+2,62500,cPow,lU
+2,50453,cPow,lU
+2,62488,cPow,lU
+1,0,eC3
+7,eC3
+194,eC3
+0,cAcos
+tH3
+cAcosh
+tH3
+cAsin
+tH3
+cAsinh
+nW
+120,cAsinh
+tH3
+cAtan,eB2
+306176,cAtan2
+iG2,cAtan2
+tH3
+cAtanh
+nW
+246,cCeil
+tH3
+cCeil,eV
+1,0,c42
+0,cCos,eV
+1,7,c42
+92,c42
+93,c42
+120,c42
+236,c42
+255,c42
+214,iF2
+236,iF2
+464,iF2
+0,cCosh,eV
+1,0,iF2
+0,eD3
+7,eD3
+92,eD3
+0
+yG3
+7
+yG3
+92
+yG3
+246,cFloor
+tH3
+cFloor
+xZ
+309540,eE3
+eB2
+316708,eE3
+eB2
+316724,eE3
+l0
+3,32513024,eC2
+34627584
+eW
+31493120,eC2
+89213952
+eW
+149042176
+eW
+246647808
+eW
+301234176
+eW
+494360576
+eW
+498558976
+eW
+62933520
+eW
+62933520,eC2
+62933526
+eW
+62933526,eC2
+24670208
+eW
+579378176
+eW
+573578240
+eW
+32513024
+eW
+566254592
+eW
+7900160
+eW
+588822528,cIf
+nW
+120,cInt
+nW
+246,tA2
+0,tA2
+7,tA2
+31,tA2
+194,tA2
+363,tA2
+15,cLog,lU
+1,24,cLog,lU
+1,0,cLog10
+tH3
+cLog2
+iG2,cMax,eB2
+35847,cMax,eB2
+30751,cMax
+tH3
+cMax,AnyParams,1}
+,0,0x4
+nM
+7168,cMin,eB2
+35847,cMin,eB2
+30751,cMin
+tH3
+cMin,AnyParams,1}
+,0,0x4
+nM
+24591,cMin,lU
+1,0,nL2
+7,nL2
+92,nL2
+93,nL2
+120,nL2
+149,nL2
+231,cSin,lB
+0x5
+tL3
+246,nL2
+255,nL2
+254,nL2
+0,cSin,eV
+1,273,cSin,lB
+0x1
+tL3
+214
+xW2
+231,cSinh,lB
+0x5
+tL3
+246
+xW2
+254
+xW2
+255
+xW2
+464
+xW2
+0,cSinh,eV
+1,0
+xW2
+15,cSqrt,lU
+1,0
+c62
+0,cTan,eV
+1,116,cTan,eV
+1,117
+c62
+231
+c62
+246
+c62
+273
+c62
+254
+c62
+255
+c62
+0,xX2
+0,cTanh,eV
+1,213,xX2
+231,xX2
+246,xX2
+254,xX2
+255,xX2
+0,cTrunc,eB2
+15384,cSub,lU
+2,15384,cDiv,lU
+2,476626,cDiv,lU
+2,122937
+x82
+7168
+i52
+tB2
+7168
+x82
+31744
+i52,lB
+0x20
+nM
+31751
+i52,lB
+0x24
+nM
+31751
+x82
+122937,tP1
+iG2,cLess
+tB2
+41984,cLess
+xZ
+41984,cLess,eB2
+7,cLess
+iG2,cLessOrEq,eB2
+296182,cLessOrEq
+iG2
+tC2
+tB2
+41984
+tC2
+xZ
+41984
+tC2,eB2
+7
+tC2
+iG2
+xO2,eB2
+296182
+xO2
+nW
+0
+tB1
+245
+tB1
+7
+tB1
+550
+tB1
+553
+tB1
+554
+tB1
+556
+tB1
+31
+tB1
+559
+tB1
+15
+tB1
+560,cNot,eB2
+7706,lA3
+7168,lA3
+35847,lA3
+30751,lA3
+463903,lA3
+466975,cAnd,iF
+0,0,cAnd,nL
+2,7168,cO3
+7706,cO3
+35847,cO3
+463903,cO3
+466975,cO3
+30751,cOr,iF
+1,0,lC2
+92,lC2
+131,lC2
+245,lC2
+215,lC2
+246,cDeg
+nW
+246,cRad
+iG2,cAbsAnd,l6
+7168,cAbsOr,iF
+1,0,c03
+tH3
+cAbsNotNot,l0
+3,32513024,cAbsIf,lB
+0x0}
+,}
+;}
+iR2
+l21{const
+Rule
+grammar_rules[262]={{ProduceNewTree,17,1,0,{1,0,cAbs
+eD2
+409,{1,146,cAtan
+eD2
+403
+x9
+1324,cAtan2
+eD2
+405
+x9
+307201,cAtan2
+cA
+253174
+x9
+255224,cAtan2
+cA
+259324
+x9
+257274,cAtan2
+eD2
+152,{1,252,cCeil
+l3
+2,1,486,{1,68,xI1
+482,{1,123,xI1
+483,{1,125,xI1
+151,{1,126,xI1
+419,{1,124,xI1
+0,{1,403,cCos,l2
+2,1,246,{1,252,cCos,l2
+18,1,0,{1,400,xI1
+301,{1,406,cCosh,l2
+2,1,246,{1,252,cCosh,l2
+18,1,0,{1,400,cCosh
+l3
+2,1,458,{1,122,cFloor
+eD2
+150,{1,252,cFloor
+l3
+0,1,156,{3,7382016,eI
+549,{3,8430592,eI
+556,{3,8436736,eI
+157,{3,42998784,eI
+550,{3,42999808,eI
+562,{3,43039744,eI
+557,{3,49291264,eI
+538,{3,49325056,eI
+469,{3,1058318,eI
+473,{3,1058324,eI
+473,{3,9438734,eI
+469,{3,9438740,cIf,l2
+0,3,32542225,{3,36732434,cIf,l2
+0,3,32542231,{3,36732440,cIf
+l3
+16,1,573,{3,32513026,cIf
+l3
+16,1,515,{3,455505423,cIf
+l3
+16,1,515,{3,433506837,cIf
+l3
+2,1,78,{1,256,xY2
+69,{1,258,xY2
+404,{1,72,xY2
+159,{1,147,cLog,l2
+0,1,0
+x9
+487425,cMax,tX
+16,1,445
+x9
+eF3
+cMax,tX
+0,1,0
+x9
+483329,cMin,tX
+16,1,446
+x9
+eF3
+cMin,cB
+0,1,153
+x9
+24832,nM2
+0,1,153
+x9
+25854,nM2
+0,1,154
+x9
+130063,iI2
+32055,iI2
+32056,iI2
+32057,iJ2
+166288
+x9
+32137,iI2
+33082,iJ2
+7168
+x9
+12688,iJ2
+7434
+x9
+12553
+nY2
+435
+x9
+46146
+nY2
+436
+x9
+46154
+nY2
+437
+x9
+46150
+nY2
+169
+x9
+83983
+nY2
+168
+x9
+131106
+nY2
+175
+x9
+133154
+nZ2
+476160
+x9
+471055
+nZ2
+274432
+x9
+273423
+nZ2
+251904
+x9
+266274
+nZ2
+251904
+x9
+263186
+nY2
+171,{1,252,lN1
+421,{1,68,lN1
+151,{1,123,lN1
+419,{1,125,lN1
+170,{1,126,lN1
+482,{1,124,lN1
+0,{1,405,lN1
+172,{1,252,cSinh
+l3
+2,1,328,{1,404,cSinh
+l3
+2,1,173,{1,252,xZ2
+0,{1,408,xZ2
+176,{1,410,xZ2
+177,{1,252,cTanh,l2
+0,1,442
+x9
+449551
+cP3
+441
+x9
+450998
+cP3
+167
+x9
+268549
+cP3
+180
+x9
+276749
+cP3
+181
+x9
+276500
+cQ3
+190770
+x9
+189622
+cQ3
+194748
+x9
+193723
+cQ3
+202943
+x9
+196795
+cQ3
+59699
+x9
+298148
+cQ3
+59714
+x9
+325815
+cQ3
+59724
+x9
+343224
+xC
+cB
+2,1,337,{1,333
+tP
+1
+tT
+336,{1,338
+tP
+1}
+}
+iH2
+2,1,340
+x9
+1363
+tS
+342
+x9
+1365
+tS
+463
+x9
+472524
+tS
+47
+x9
+356711
+tS
+349
+x9
+200751
+tS
+360
+x9
+199727
+tS
+480
+x9
+207053
+tS
+481
+x9
+208077
+tS
+417
+x9
+211144
+tS
+209
+x9
+211145
+tS
+418
+x9
+215240
+tS
+212
+x9
+212329
+tS
+204
+x9
+373097
+tS
+211
+x9
+372944
+tS
+217
+x9
+201944
+tS
+221
+x9
+223448
+tS
+367
+x9
+508329
+tS
+219
+x9
+508126
+tS
+224
+x9
+225705
+tS
+223
+x9
+225776
+tS
+365
+x9
+230825
+tS
+426
+x9
+377057
+tS
+497
+x9
+377054
+tS
+497
+x9
+204201
+tS
+426
+x9
+375280
+tS
+224
+x9
+375006,l7
+2,2,407781
+x9
+233698,l7
+2,2,59763
+x9
+233842
+cP3
+372
+x9
+1397,c72
+96
+x9
+24705,c72
+97
+x9
+24708,c72
+444
+x9
+449551,c72
+443
+x9
+eF3
+c72
+101
+x9
+102774,c72
+109
+x9
+107845,c72
+106
+x9
+104773,l5
+0,2,111631
+x9
+109893,l5
+0,2,108559
+x9
+110917,lK
+0
+tT
+113
+x9
+112658,cMul,SelectedParams,0
+tT
+567,{1,52,lK
+1
+tT
+568,{1,42,lK
+1}
+}
+iH2
+2,1,467
+x9
+45516
+i51
+356
+x9
+51555
+i51
+468
+x9
+49612
+i51
+357
+x9
+47459
+i51
+429
+x9
+438699
+i51
+432
+x9
+441774
+i51
+486
+x9
+498726
+i51
+494
+x9
+504870
+i51
+382
+x9
+435579
+i51
+497
+x9
+435709
+i51
+426
+x9
+508287
+i51
+414
+x9
+500092
+i51
+499
+x9
+352744
+i51
+345
+x9
+367092
+i51
+381
+x9
+425318
+i51
+478
+x9
+425460
+i51
+47
+x9
+512501
+i51
+505
+x9
+355817
+i51
+47
+x9
+516598
+i51
+507
+x9
+518182
+i51
+508
+x9
+358896
+i51
+351
+x9
+388605
+i51
+511
+x9
+360939
+i51
+503
+x9
+354788
+i51
+514
+x9
+525350
+i51
+510
+x9
+394343
+i51
+386
+x9
+351347,l5
+2,2,363004
+x9
+361968,l5
+16,1,118
+x9
+1157,l5
+16,1,119
+x9
+1158,l5
+16,1,402
+x9
+411024,l5
+16,2,58768
+x9
+1472,l5
+16,2,15760
+x9
+1474,l5
+17,1,0,{1,400,l5
+17,1,57,{1,14,lK
+0}
+}
+,{ProduceNewTree,4,1,538
+x9
+41
+i52
+l3
+4,1,0
+x9
+5167
+i52
+c9
+41984
+x9
+409641
+i52
+c9
+tY
+cEqual
+c9
+t0
+cEqual
+c9
+t1
+cEqual
+xL1
+24849
+i52
+cA
+tZ
+cEqual
+cA
+lD2
+281873
+i52
+cA
+lA1
+i52
+cA
+l61
+cEqual
+l3
+4,1,562
+x9
+41,tP1
+l3
+4,1,538
+x9
+5167,tP1
+c9
+41984
+x9
+409641,tP1
+c9
+tY
+tP1
+c9
+t0
+tP1
+c9
+t1
+tP1
+xL1
+24849,tP1
+cA
+tZ
+tP1
+cA
+lD2
+281873,tP1
+cA
+lA1,tP1
+cA
+l61
+tP1
+c9
+tY
+yH3
+t0
+yH3
+t1
+cLess
+eD2
+571
+x9
+46080,cLess
+xL1
+24832,cLess
+cA
+xM1
+cLess
+cA
+tZ
+cLess
+cA
+lD2
+281856,cLess
+cA
+nP1
+cLess
+cA
+lA1,cLess
+cA
+l61
+cLess
+l3
+20,1,562
+x9
+409641,yH3
+tY
+y02
+t0
+y02
+t1
+cLessOrEq
+eD2
+565
+x9
+409615,cLessOrEq
+xL1
+24832,cLessOrEq
+cA
+xM1
+cLessOrEq
+cA
+tZ
+cLessOrEq
+cA
+lD2
+281856,cLessOrEq
+cA
+nP1
+cLessOrEq
+cA
+lA1,cLessOrEq
+cA
+l61
+cLessOrEq
+l3
+20,1,562
+x9
+409647,y02
+tY
+c82
+t0
+c82
+t1
+cGreater
+eD2
+539
+x9
+409615
+tC2
+xL1
+24832
+tC2
+cA
+xM1
+cGreater
+cA
+tZ
+cGreater
+cA
+lD2
+281856
+tC2
+cA
+nP1
+cGreater
+cA
+lA1
+tC2
+cA
+l61
+cGreater
+l3
+20,1,538
+x9
+409647,c82
+tY
+cGreaterOrEq
+c9
+t0
+cGreaterOrEq
+c9
+t1
+cGreaterOrEq
+eD2
+572
+x9
+46080
+xO2
+xL1
+24832
+xO2
+cA
+xM1
+cGreaterOrEq
+cA
+tZ
+cGreaterOrEq
+cA
+lD2
+281856
+xO2
+cA
+nP1
+cGreaterOrEq
+cA
+lA1
+xO2
+cA
+l61
+cGreaterOrEq
+l3
+20,1,538
+x9
+409641
+xO2
+l3
+4,1,519,{1,137,cNot
+l3
+16,1,571,{1,2,cNot,l2
+0,1,452
+x9
+eF3
+xF
+0,2,537097,{3,547892744,cAnd,cB
+16,1,566,{1,5,cAnd,AnyParams,1}
+}
+iH2
+16,1,569
+x9
+13314,xF
+16,1,544
+x9
+553498,xF
+16,1,546
+x9
+462369,xF
+16,1,548
+x9
+466465,xF
+0,1,457
+x9
+eF3
+nH
+570
+x9
+13314,nH
+563
+x9
+8197,nH
+541
+x9
+553498,nH
+542
+x9
+462369,nH
+543
+x9
+466465,nH
+564
+x9
+143365,cOr,cB
+4,1,525,{1,137,cNotNot
+l3
+16,1,572,{1,2,cNotNot
+l3
+17,1,0,{1,0,cNotNot
+eD2
+537,{1,256,cAbsNotNot,cB
+18,1,531,{1,254,cAbsNotNot,cB
+0,1,572,{3,43039744,cAbsIf
+l3
+0,1,571,{3,49325056,cAbsIf
+l3
+16,1,454,{3,32513586,cAbsIf,l2
+16,3,32542225,{3,36732434,cAbsIf,y21}
+,}
+;cP2
+grammar_optimize_abslogical_type{y5
+9
+cV
+grammar_optimize_abslogical_type
+grammar_optimize_abslogical={9,{34,192,228,238,242,247,254,260,261}
+}
+;}
+cP2
+grammar_optimize_ignore_if_sideeffects_type{y5
+59
+cV
+grammar_optimize_ignore_if_sideeffects_type
+grammar_optimize_ignore_if_sideeffects={59,{0,20,21,22,23,24,25,26,cS
+iE1
+78,cT
+cW
+cP2
+grammar_optimize_nonshortcut_logical_evaluation_type{y5
+56
+cV
+grammar_optimize_nonshortcut_logical_evaluation_type
+grammar_optimize_nonshortcut_logical_evaluation={56,{0,25,cS
+iE1
+78,cT
+241,243,244,245,246,248,249,250,251,252,253,255,256,257,258,259}
+}
+;}
+cP2
+grammar_optimize_recreate_type{y5
+22
+cV
+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}
+}
+;}
+cP2
+grammar_optimize_round1_type{y5
+125
+cV
+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,cS
+37,38,iE1
+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,cW
+cP2
+grammar_optimize_round2_type{y5
+103
+cV
+grammar_optimize_round2_type
+grammar_optimize_round2={103,{0,15,16,17,25,cS
+39,40,iE1
+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,cW
+cP2
+grammar_optimize_round3_type{y5
+79
+cV
+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}
+}
+;}
+cP2
+grammar_optimize_round4_type{y5
+12
+cV
+grammar_optimize_round4_type
+grammar_optimize_round4={12,{18,55,56,57,130,131,132,133,134,135,136,137}
+}
+;}
+cP2
+grammar_optimize_shortcut_logical_evaluation_type{y5
+53
+cV
+grammar_optimize_shortcut_logical_evaluation_type
+grammar_optimize_shortcut_logical_evaluation={53,{0,25,cS
+iE1
+78,cT
+cW}
+iR2
+l21{yD
+cS2
+cR1
+nD2
+paramlist,lB1){index=(paramlist>>(index*10))&1023;if(index>=57)return
+cS2(SubFunction,c92
+plist_s[index-57]);if(index>=37)return
+cS2(NumConstant,c92
+plist_n_container
+yB::plist_n[index-37])eO
+cS2(ParamHolder,c92
+plist_p[index]);}
+}
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <stdio.h>
+#include <algorithm>
+#include <map>
+#include <sstream>
+using
+iR2
+FUNCTIONPARSERTYPES;using
+iR2
+l21;using
+tC;using
+cV1;iR2{nH1
+It,typename
+T,typename
+Comp>eT1
+MyEqualRange(It
+first,It
+last,const
+T&val,Comp
+comp){size_t
+len=last-first;while(len>0){size_t
+xH3
+len/2;It
+nQ3(first);nQ3+=half;if(comp(*nQ3,val)){first=nQ3;++first;len=len-half-1;}
+i81
+comp(val,*nQ3)){len=half;}
+else{It
+left(first);{It&eL2=left;It
+last2(nQ3);size_t
+len2=last2-eL2;while(len2>0){size_t
+half2=len2/2;It
+middle2(eL2);middle2+=half2;if(comp(*middle2,val)){eL2=middle2;++eL2;len2=len2-half2-1;}
+else
+len2=half2;}
+}
+first+=len;It
+right(++nQ3);{It&eL2=right;It&last2=first;size_t
+len2=last2-eL2;while(len2>0){size_t
+half2=len2/2;It
+middle2(eL2);middle2+=half2;if(comp(val,*middle2))len2=half2;else{eL2=middle2;++eL2;len2=len2-half2-1;}
+}
+}
+return
+eT1(left,right);}
+}
+return
+eT1(first,first);}
+yD
+cP2
+OpcodeRuleCompare{bool
+eD1()iX2
+tree,unsigned
+y12)const{const
+Rule&rule=grammar_rules[y12]eO
+tree
+nF<rule
+cB2.subfunc_opcode;}
+bool
+eD1()nD2
+y12,xB3)const{const
+Rule&rule=grammar_rules[y12]eO
+rule
+cB2.subfunc_opcode<tree
+nF;}
+}
+;yD
+bool
+TestRuleAndApplyIfMatch
+cY1
+eU2
+xG&tree,bool
+cC{MatchInfo
+yB
+info;lW1
+found(false,e3());if((rule.l71
+LogicalContextOnly)&&!cC{tC1
+if(nE
+IsIntType
+yB::nT3
+cI3
+rule.l71
+NotForIntegers)tC1
+eN3
+rule.l71
+OnlyForIntegers)tC1
+if(nE
+IsComplexType
+yB::nT3
+cI3
+rule.l71
+NotForComplex)tC1
+eN3
+rule.l71
+OnlyForComplex)tC1
+for(;;){
+#ifdef DEBUG_SUBSTITUTIONS
+#endif
+found=TestParams(rule
+cB2,tree,found.specs,info,true);if(found.found)break;if(found.specs.isnull()){fail:;
+#ifdef DEBUG_SUBSTITUTIONS
+DumpMatch
+cA2,false);
+#endif
+return
+e83}
+#ifdef DEBUG_SUBSTITUTIONS
+DumpMatch
+cA2,true);
+#endif
+SynthesizeRule
+cA2)cT2}
+cV1{yD
+bool
+ApplyGrammar
+cY1
+Grammar&tD2,xG&tree,bool
+cC{if(tree.GetOptimizedUsing()==&tD2){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Already optimized: "
+yR2
+tree)xO1"\n"
+<<std::flush;
+#endif
+return
+e83
+if(true){bool
+changed
+e23
+switch
+l83{case
+cNot:case
+cNotNot:case
+cAnd:case
+cOr:n72
+0;lB3
+true))nS2
+lD
+cIf:case
+cAbsIf:if(ApplyGrammar(tD2,tQ,i21
+cIf))nS2
+n72
+1;lB3
+cC)nS2
+break;y13
+n72
+0;lB3
+false))nS2}
+if(changed){tree.Mark_Incompletely_Hashed()cT2}
+typedef
+const
+unsigned
+short*lG3;std::pair<lG3,lG3>range=MyEqualRange(tD2.rule_list,tD2.rule_list+tD2.rule_count,tree,OpcodeRuleCompare
+yB())e72
+unsigned
+short>rules;rules.xD3
+range.second-range.first);cX
+if(IsLogisticallyPlausibleParamsMatch(e91
+cB2,tree))rules
+yS2*r);}
+range.first=!rules
+yU3?&rules[0]:0;range.second=!rules
+yU3?&rules[rules.size()-1]+1:0;if(range.first!=range.second){
+#ifdef DEBUG_SUBSTITUTIONS
+if(range.first!=range.second)lC3"Input ("
+<<eK3
+l83<<")["
+<<t7<<"]"
+;if(cC
+std::cout<<"(Logical)"
+;unsigned
+first=iF1,prev=iF1;nA3
+sep=", rules "
+;cX
+if(first==iF1)first=prev=*r;i81*r==prev+1)prev=*r;else
+lC3
+sep<<first;sep=","
+;if(prev!=first)std::cout<<'-'<<prev;first=prev=*r;}
+}
+if(first!=iF1)lC3
+sep<<first;if(prev!=first)std::cout<<'-'<<prev;}
+std::cout<<": "
+yR2
+tree)xO1"\n"
+<<std::flush;}
+#endif
+bool
+changed
+e23
+cX
+#ifndef DEBUG_SUBSTITUTIONS
+if(!IsLogisticallyPlausibleParamsMatch(e91
+cB2,tree))y41
+#endif
+if(TestRuleAndApplyIfMatch(e91,tree,cC){nS2
+yN3
+if(changed){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Changed."
+<<std::endl
+xO1"Output: "
+yR2
+tree)xO1"\n"
+<<std::flush;
+#endif
+tree.Mark_Incompletely_Hashed()cT2}
+tree.SetOptimizedUsing(&tD2)eO
+e83
+yD
+bool
+ApplyGrammar
+cY1
+void*p,FPoptimizer_CodeTree::cV2
+yS
+ApplyGrammar(*cY1
+Grammar*)p,tree);}
+x73
+ApplyGrammars(FPoptimizer_CodeTree::cV2{
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_round1\n"
+;
+#endif
+n6
+grammar_optimize_round1
+y22
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_round2\n"
+;
+#endif
+n6
+grammar_optimize_round2
+y22
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_round3\n"
+;
+#endif
+n6
+grammar_optimize_round3
+y22
+#ifndef FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_nonshortcut_logical_evaluation\n"
+;
+#endif
+n6
+grammar_optimize_nonshortcut_logical_evaluation
+y22
+#endif
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_round4\n"
+;
+#endif
+n6
+grammar_optimize_round4
+y22
+#ifdef FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_shortcut_logical_evaluation\n"
+;
+#endif
+n6
+grammar_optimize_shortcut_logical_evaluation
+y22
+#endif
+#ifdef FP_ENABLE_IGNORE_IF_SIDEEFFECTS
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_ignore_if_sideeffects\n"
+;
+#endif
+n6
+grammar_optimize_ignore_if_sideeffects
+y22
+#endif
+#ifdef DEBUG_SUBSTITUTIONS
+std
+t83"grammar_optimize_abslogical\n"
+;
+#endif
+n6
+grammar_optimize_abslogical
+y22
+#undef C
+}
+}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <algorithm>
+#include <assert.h>
+#include <cstring>
+#include <cmath>
+#include <memory> /* for auto_ptr */
+using
+iR2
+FUNCTIONPARSERTYPES;using
+iR2
+l21;using
+tC;using
+cV1;iR2{yD
+bool
+TestImmedConstraints
+nD2
+bitmask,xB3){switch(bitmask&ValueMask
+e53
+Value_AnyNum:case
+ValueMask:lD
+nK2:if(GetEvennessInfo
+cK3
+lE2
+Value_OddInt:if(GetEvennessInfo
+cK3
+nN2
+tM1:if(GetIntegerInfo
+cK3
+lE2
+Value_NonInteger:if(GetIntegerInfo
+cK3
+nN2
+eQ1:if(!IsLogicalValue(tree)c5
+nA1
+SignMask
+e53
+Sign_AnySign:lD
+n91:if(l01
+lE2
+eR1:if(l01
+nN2
+Sign_NoIdea:if(l01
+Unknown
+c5
+nA1
+OnenessMask
+e53
+Oneness_Any:case
+OnenessMask:lD
+Oneness_One:if(!e01
+if(!fp_equal(fp_abs(tree.xE1),l62(1))c5
+lD
+Oneness_NotOne:if(!e01
+if(fp_equal(fp_abs(tree.xE1),l62(1))c5
+nA1
+ConstnessMask
+e53
+Constness_Any:lD
+tL1:if(!e01
+lD
+Constness_NotConst:if(e01
+break
+yC3
+true;}
+t91
+unsigned
+extent,unsigned
+nbits,typename
+eM2=unsigned
+int>cP2
+nbitmap{private:static
+const
+unsigned
+bits_in_char=8;static
+const
+unsigned
+eN2=(yI3
+eM2)*bits_in_char)/nbits;eM2
+data[(extent+eN2-1)/eN2];cV3
+void
+inc(lB1,int
+by=1){data[pos(index)]+=by*eM2(1<<y32);x61
+void
+dec(lB1){inc(index,-1);}
+int
+get(lB1
+yK1(data[pos(index)]>>y32)&mask()lD3
+pos(lB1)yS
+index/eN2
+lD3
+shift(lB1)yS
+nbits*(index%eN2)lD3
+mask()yS(1<<nbits)-1
+lD3
+mask(lB1)yS
+mask()<<y32;}
+}
+;cP2
+c93{int
+SubTrees:8;int
+yB3:8;int
+y42:8;int
+Immeds:8;nbitmap<iE2,2>SubTreesDetail;c93(){std::memset(this,0,yI3*this));}
+c93
+cY1
+c93&b){std::memcpy(this,&b,yI3
+b));}
+c93&eD1=cY1
+c93&b){std::memcpy(this,&b,yI3
+b))eO*this;}
+}
+;yD
+c93
+CreateNeedList_uncached(eP&tE2{c93
+cU1;for
+nD2
+a=0;a<e13
+y52;++a){const
+cS2&x02=cR1
+yB(e13.param_list,a);switch(x02.first
+e53
+SubFunction:{cR
+y63(cR*e62;yN
+GroupFunction)++cU1.Immeds;else{++cU1.SubTrees;assert(param.data.subfunc_opcode<VarBegin);cU1.SubTreesDetail.inc
+y83
+l51);}
+++cU1.y42;break
+cT1
+NumConstant:case
+ParamHolder:++cU1.yB3;++cU1.y42;yN3
+return
+cU1;}
+yD
+c93&CreateNeedList(eP&tE2{typedef
+std::map<eP*,c93>cO1;static
+cO1
+yF1;cO1::xR3
+i=yF1.xI2&tE2;if(i!=yF1.cH1&tE2
+return
+i
+cW2
+eO
+yF1.xN3,std::make_pair(&e13,CreateNeedList_uncached
+yB(tE2))cW2;}
+yD
+xG
+CalculateGroupFunction
+cY1
+cS2&x02,const
+y1
+info){switch(x02.first
+e53
+NumConstant:{const
+ParamSpec_NumConstant
+yB
+y63
+cY1
+ParamSpec_NumConstant
+yB*e62
+eO
+CodeTreeImmed
+y83
+constvalue)cT1
+ParamHolder:{cQ
+y63(cQ*e62
+eO
+cS3
+GetParamHolderValueIfFound
+y83
+index)cT1
+SubFunction:{cR
+y63(cR*e62;xG
+nT3;nT3
+c4
+yA3
+l51);tX2
+iP1).xD3
+yA3
+data
+y52);for
+nD2
+a=0;a<yA3
+data
+y52;++a
+nQ
+tmp(CalculateGroupFunction(cR1
+yB
+y83
+data.param_list,a),info));nT3
+y7
+tmp);}
+tX2
+Rehash()eO
+nT3;}
+}
+return
+xG();}
+}
+cV1{yD
+bool
+IsLogisticallyPlausibleParamsMatch(eP&e13,xB3){c93
+cU1(CreateNeedList
+yB(tE2);size_t
+eG3=t7;if(eG3<size_t(cU1.y42))tF2
+n72
+0;a<eG3;++a){unsigned
+opcode=xP1
+a)nF;switch(opcode
+e53
+cImmed:if(cU1.Immeds>0)cR3
+Immeds;else
+cR3
+yB3;lD
+iE2:case
+cFCall:case
+cPCall:cR3
+yB3;break;y13
+assert(opcode<VarBegin);if(cU1.SubTrees>0&&cU1.SubTreesDetail.get(opcode)>0){cR3
+SubTrees;cU1.SubTreesDetail.dec(opcode);}
+else
+cR3
+yB3;}
+}
+if(cU1.Immeds>0||cU1.SubTrees>0||cU1.yB3>0)tF2
+if(e13.match_type!=AnyParams
+cI3
+0||cU1.SubTrees<0||cU1.yB3<0)tF2}
+return
+true;}
+yD
+lW1
+TestParam
+cY1
+cS2&x02,xB3
+n43
+start_at,y1
+info){switch(x02.first
+e53
+NumConstant:{const
+ParamSpec_NumConstant
+yB
+y63
+cY1
+ParamSpec_NumConstant
+yB*e62;if(!e01
+l62
+imm=tree.xE1;switch
+y83
+modulo
+e53
+Modulo_None:lD
+Modulo_Radians:imm=fp_mod(imm,yG
+imm<tD1))imm
+yQ
+if(imm>fp_const_pi
+yB())imm-=fp_const_twopi
+yB(eP3
+yC3
+fp_equal(imm,yA3
+constvalue)cT1
+ParamHolder:{cQ
+y63(cQ*e62;if(!x5
+return
+cS3
+SaveOrTestParamHolder
+y83
+index,tree)cT1
+SubFunction:{cR
+y63(cR*e62;yN
+GroupFunction
+cI3!x5
+xG
+xN1=CalculateGroupFunction(x02,info);
+#ifdef DEBUG_SUBSTITUTIONS
+DumpHashes(xN1)xO1*cY1
+void**)&xN1.xE1
+xO1"\n"
+xO1*cY1
+void**)&tree.xE1
+xO1"\n"
+;DumpHashes(tree)xO1"Comparing "
+yR2
+xN1)xO1" and "
+yR2
+tree)xO1": "
+xO1(xN1
+xI
+tree)?"true"
+:"false"
+)xO1"\n"
+;
+#endif
+return
+xN1
+xI
+tree);}
+eN3
+start_at.isnull()cI3!x5
+if(tree
+nF!=yA3
+l51
+c5}
+return
+TestParams
+y83
+data,tree,start_at,info,false);}
+}
+}
+return
+e83
+yD
+cP2
+iR
+x92
+MatchInfo
+yB
+info;iR(y62,info(){}
+}
+;x13
+MatchPositionSpec_PositionalParams:eN1
+iR
+yB>{cV3
+iK2
+MatchPositionSpec_PositionalParams
+x72
+n
+yN1
+iR
+yB>(n){}
+}
+;cP2
+iG1
+x92
+iG1(y62{}
+}
+;class
+yO:eN1
+iG1>{cV3
+unsigned
+trypos;iK2
+yO
+x72
+n
+yN1
+iG1>(n),trypos(0){}
+}
+;yD
+lW1
+TestParam_AnyWhere
+cY1
+cS2&x02,xB3
+n43
+start_at,y1
+info,std::vector<bool>&used,bool
+y82{xQ<yO>xB;unsigned
+a;if(!start_at.isnull()){xB=(yO
+eE2
+a=xB->trypos;goto
+retry_anywhere_2;}
+tG2
+yO(t7);a=0;}
+for(tH2{if(used[a])y41
+retry_anywhere
+yJ3
+TestParam(x02,tJ3(eF2);(eG2
+used[a]=true;if(y82
+cS3
+SaveMatchedParamIndex(a);xB->trypos=a
+eO
+lW1(true,xB.get());}
+}
+retry_anywhere_2
+yK3
+goto
+retry_anywhere;}
+}
+return
+e83
+yD
+cP2
+y61
+x92
+MatchInfo
+yB
+info
+e72
+bool>used;iK2
+y61
+x72
+eG3
+y62,info(),used(eG3){}
+}
+;x13
+MatchPositionSpec_AnyParams:eN1
+y61
+yB>{cV3
+iK2
+MatchPositionSpec_AnyParams
+x72
+n,size_t
+m
+yN1
+y61
+yB>(n,y61
+yB(m)){}
+}
+;yD
+lW1
+TestParams(eP&nT,xB3
+n43
+start_at,y1
+info,bool
+y82{if(nT.match_type!=AnyParams
+cI3
+c2!=t7
+c5}
+if(!IsLogisticallyPlausibleParamsMatch(nT,tree))tF2
+switch(nT.match_type
+e53
+PositionalParams:{xQ<yA>xB;unsigned
+a;if(start_at.get()){xB=(yA
+eE2
+a=c2-1;goto
+l81;}
+tG2
+yA(c2);a=0;}
+for(;a<c2;++a){(*xB)[a
+y72
+retry_positionalparams
+yJ3
+TestParam(cZ
+a),tJ3(eF2);(eG2
+y41}
+}
+l81
+yK3
+eH2
+a].info;goto
+retry_positionalparams;}
+yL3--a;goto
+l81;}
+eH2
+0].info
+eO
+e83
+if(y82
+for
+lR1
+cS3
+SaveMatchedParamIndex(a)eO
+lW1(true,xB.get())cT1
+SelectedParams:case
+AnyParams:{xQ<tD>xB
+e72
+bool>used(t7)e72
+unsigned>iL2(c2)e72
+unsigned>y92(c2)tE3{const
+cS2
+x02=cZ
+a);iL2[a]=ParamSpec_GetDepCode(x02);}
+{unsigned
+b=0
+tE3
+if(iL2[a]!=0)y92[b++]=a
+tE3
+if(iL2[a]==0)y92[b++]=a;}
+unsigned
+a;if(start_at.get()){xB=(tD
+eE2
+if(c2==0){a=0;goto
+retry_anyparams_4;}
+a=c2-1;goto
+cP1;}
+tG2
+tD(c2,t7);a=0;if(c2!=0){(*xB)[0
+y72(*xB)[0].used=used;}
+}
+for(;a<c2;++a){yL3(*xB)[a
+y72(*xB)[a].used=used;}
+retry_anyparams
+yJ3
+TestParam_AnyWhere
+yB(cZ
+y92[a]),tree,(eF2,used,y82;(eG2
+y41}
+}
+cP1
+yK3
+eH2
+a].info;used=(*xB)[a].used;goto
+retry_anyparams;}
+cQ1:yL3--a;goto
+cP1;}
+eH2
+0].info
+eO
+e83
+retry_anyparams_4:if(nT.n0!=0
+cI3!TopLevel||!cS3
+HasRestHolder(nT.n0)){nX2
+cC2;cC2.xD3
+t7);for
+nD2
+b=0;b<t7;++b
+cI3
+yM3)y41
+cC2
+yS2
+xP1
+b));yM3=true;if(y82
+cS3
+SaveMatchedParamIndex(b);}
+if(!cS3
+SaveOrTestRestHolder(nT.n0,cC2)){goto
+cQ1;}
+}
+else{x43
+cC2=cS3
+GetRestHolderValues(nT.n0);n72
+0;a<cC2.size();++a){bool
+found
+e23
+for
+nD2
+b=0;b<t7;++b
+cI3
+yM3)y41
+if(cC2[a]xI
+xP1
+b))){yM3=true;if(y82
+cS3
+SaveMatchedParamIndex(b);found=true;yN3
+if(!found){goto
+cQ1;}
+}
+}
+}
+return
+lW1(true,c2?xB.get():0)cT1
+GroupFunction:break
+yC3
+e83}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <algorithm>
+#include <assert.h>
+using
+tC;using
+cV1;iR2{yD
+xG
+xR1
+const
+cS2&x02,y1
+info,bool
+inner=true){switch(x02.first
+e53
+NumConstant:{const
+ParamSpec_NumConstant
+yB
+y63
+cY1
+ParamSpec_NumConstant
+yB*e62
+eO
+CodeTreeImmed
+y83
+constvalue)cT1
+ParamHolder:{cQ
+y63(cQ*e62
+eO
+cS3
+GetParamHolderValue
+y83
+index)cT1
+SubFunction:{cR
+y63(cR*e62;xG
+tree;tree
+c4
+yA3
+l51);for
+nD2
+a=0;a<yA3
+data
+y52;++a
+nQ
+nparam=xR1
+cR1
+yB
+y83
+data.param_list,a),info,true)e12
+nparam);}
+l93
+data.n0!=0){nX2
+trees(cS3
+GetRestHolderValues
+y83
+data.n0));tree.AddParamsMove(trees);if(t7==1){assert(tree tC3()==cAdd||tree tC3()==cMul||tree tC3()==cMin||tree tC3()==cMax||tree tC3()==cAnd||tree tC3()==cOr||tree tC3()==cAbsAnd||tree tC3()==cAbsOr);tree
+iD2
+tQ);}
+i81
+t7==0){switch
+l83{case
+cAdd:case
+cOr
+e93=n31
+0));lD
+cMul:case
+cAnd
+e93=n31
+1));y13
+yN3}
+if(inner)tree.Rehash()eO
+tree;}
+}
+return
+xG();}
+}
+cV1{x73
+SynthesizeRule
+cY1
+eU2
+xG&tree,y1
+info){switch(rule.ruletype
+e53
+ProduceNewTree:{tree
+iD2
+xR1
+cR1
+l91
+0),info,false)eP3
+cT1
+ReplaceParams:y13{std::vector<unsigned>list=cS3
+GetMatchedParamIndexes();std::sort(list.iC2
+list.end());n72
+list.size();a-->0;)tree.DelParam(list[a]);for
+nD2
+a=0;a<rule.repl_param_count;++a
+nQ
+nparam=xR1
+cR1
+l91
+a),info,true)e12
+nparam);}
+yN3}
+}
+#endif
+#ifdef DEBUG_SUBSTITUTIONS
+#include <sstream>
+#include <cstring>
+using
+iR2
+FUNCTIONPARSERTYPES;using
+iR2
+l21;using
+tC;using
+cV1;iR2
+l21{x73
+DumpMatch
+cY1
+eU2
+xB3,const
+y1
+info,bool
+DidMatch,std::ostream&o){DumpMatch
+cA2,DidMatch?tF3"match"
+:tF3"mismatch"
+,o);}
+x73
+DumpMatch
+cY1
+eU2
+xB3,const
+y1
+info,nA3
+eH3,std::ostream&o){static
+const
+char
+ParamHolderNames[][2]={"%"
+,"&"
+,"x"
+,"y"
+,"z"
+,"a"
+,"b"
+,"c"
+}
+;o<<eH3<<" (rule "
+<<(&rule-grammar_rules)<<")"
+<<":\n Pattern : "
+;{cS2
+tmp;tmp.first=SubFunction;ParamSpec_SubFunction
+tmp2;tmp2.data=rule
+cB2;tmp.second=c92
+tmp2;DumpParam
+yB(tmp,o);}
+o<<"\n Replacement: "
+;DumpParams
+l91
+rule.repl_param_count
+eI2
+o<<" Tree : "
+yR2
+tree
+eI2
+if(!std::strcmp(eH3,tF3"match"
+))DumpHashes(tree,o);n72
+0;a<cS3
+yL.size();++a
+cI3!cS3
+yL[a].n12)y41
+o<<" "
+<<ParamHolderNames[a]<<" = "
+yR2
+cS3
+yL[a]eI2}
+xS3
+cS3
+lR.size();++b
+cI3!cS3
+lR[b
+e03)y41
+n72
+0;a<cS3
+lR[b].second.size();++a){o<<" <"
+<<b<<"> = "
+yR2
+cS3
+lR[b].second[a],o);o<<std::endl;}
+}
+o<<std::flush;}
+}
+#endif
+#include <list>
+#include <algorithm>
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;iR2{yD
+bool
+MarkIncompletes(FPoptimizer_CodeTree::cV2{if(tree.Is_Incompletely_Hashed(t41;bool
+iH1
+e23
+n72
+0
+tH2
+iH1|=MarkIncompletes
+tN3);if(iH1)tree.Mark_Incompletely_Hashed()eO
+iH1;}
+x73
+FixIncompletes(FPoptimizer_CodeTree::cV2{if(tree.Is_Incompletely_Hashed()){n72
+0
+tH2
+FixIncompletes
+tN3);tree
+eM1}
+}
+}
+tC{lC
+Sort()tI3
+Sort();}
+lC
+Rehash(bool
+constantfolding
+cI3
+constantfolding)ConstantFolding(*this);else
+Sort();data
+xE
+yD
+cP2
+cG
+yO3
+l62
+yP3
+cB1=0;
+#if 0
+long
+double
+value=Value;eC=crc32::calc(cY1
+unsigned
+char*)&value,yI3
+value));key^=(key<<24);
+#elif 0
+union{cP2{unsigned
+char
+filler1[16];l62
+v;unsigned
+char
+filler2[16];}
+buf2;cP2{unsigned
+char
+filler3[yI3
+l62)+16-yI3
+x01)];eC;}
+buf1;}
+data;memset(&data,0,yI3
+data));data.buf2.v=Value;eC=data.buf1.key;
+#else
+int
+nU3;l62
+lW2=std::frexp(Value,&x32;eC=nD2(nU3+0x8000)&0xFFFF);if(lW2<0){lW2=-lW2;key=key^0xFFFF;}
+else
+key+=0x10000;lW2-=l62(0.5);key<<=39;key|=lY1(lW2+lW2)*l62(1u<<31))<<8;
+#endif
+lQ
+#ifdef FP_SUPPORT_COMPLEX_NUMBERS
+nH1
+T
+cD2
+std::complex<T> >yO3
+std::complex<T>yP3
+cG<T>::lH3
+NewHash,Value.real());nE
+fphash_t
+temp;cG<T>::lH3
+temp,Value.imag());cB1^=temp.hash2;NewHash.hash2^=temp.hash1;}
+}
+;
+#endif
+#ifdef FP_SUPPORT_LONG_INT_TYPE
+t91
+cD2
+long>yK
+long
+Value){eC=Value;lQ
+#endif
+#ifdef FP_SUPPORT_GMP_INT_TYPE
+t91
+cD2
+GmpInt>yO3
+GmpInt
+yP3
+eC=Value.toInt();lQ
+#endif
+x73
+x42
+yB::Recalculate_Hash_NoRecursion(){fphash_t
+NewHash(lY1
+Opcode)<<56,Opcode*t23(0x1131462E270012B));Depth=1;switch(Opcode
+e53
+cImmed:{cG
+yB::lH3
+NewHash,Value
+eP3
+cT1
+iE2:{cB1|=lY1
+c51<<48
+cA1((lY1
+c51)*11)^t23(0x3A83A83A83A83A0);break
+cT1
+cFCall:case
+cPCall:{cB1|=lY1
+c51<<48
+cA1((~lY1
+c51)*7)^3456789;}
+y13{size_t
+eU1=0;n72
+0;a<y03;++a
+cI3
+x93.xT2>eU1)eU1=x93.xT2;cB1+=((x93
+n02
+hash1*(a+1))>>12)cA1
+x93
+n02
+hash1
+cA1(3)*t23(0x9ABCD801357);NewHash.hash2*=t23(0xECADB912345)cA1(~x93
+n02
+hash2)^4567890;}
+Depth+=eU1;}
+}
+if(Hash!=NewHash){Hash=NewHash;iS1=0;}
+}
+lC
+FixIncompleteHashes(){MarkIncompletes(*this);FixIncompletes(*this);}
+}
+#endif
+#include <cmath>
+#include <list>
+#include <cassert>
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;iR2{using
+tC;yD
+bool
+nQ1
+xB3,long
+count,const
+x51::SequenceOpCode
+yB&eR,x51
+yZ3&synth,size_t
+max_bytecode_grow_length);static
+const
+cP2
+SinCosTanDataType{OPCODE
+whichopcode;OPCODE
+inverse_opcode;enum{nominator,lX2,inverse_nominator,lC1}
+;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}
+}
+,{cE2{cSinh,cCosh,cF2,{cSinh,cNop,{cE2
+cNop,cCosh}
+}
+,{cCosh,cNop,{cSinh,cE2
+cNop}
+}
+,{cNop,cTanh,{cCosh,cSinh,cF2,{cNop,cSinh,{cNop,cTanh,cCosh,cNop}
+}
+,{cNop,cCosh,{cTanh,cSinh,cF2}
+;}
+tC{lC
+SynthesizeByteCode(std::vector<unsigned>&eE1,std::vector
+yB&Immed,size_t&stacktop_max){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Making bytecode for:\n"
+;iQ
+#endif
+while(RecreateInversionsAndNegations()){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"One change issued, produced:\n"
+;iQ
+#endif
+FixIncompleteHashes();using
+cV1;using
+iR2
+l21;const
+void*g=c92
+grammar_optimize_recreate;while(ApplyGrammar(*cY1
+Grammar*)g,*this)){FixIncompleteHashes();}
+}
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Actually synthesizing, after recreating inv/neg:\n"
+;iQ
+#endif
+x51
+yZ3
+synth;SynthesizeByteCode(synth,false
+i62.Pull(eE1,Immed,stacktop_max);}
+lC
+SynthesizeByteCode(x51
+yZ3&synth,bool
+MustPopTemps)const{xS1*this))yS;}
+n72
+0;a<12;++a){const
+SinCosTanDataType&data=SinCosTanData[a];if(data.whichopcode!=cNop)l22!=data.whichopcode)y41
+CodeTree
+lI3;lI3.lH1
+lI3
+yQ3
+inverse_opcode);lI3.lF2
+xS1
+lI3)){synth.iU
+else
+l22!=cInv)y41
+if(GetParam(0)nF!=data.inverse_opcode)y41
+xS1
+GetParam(0))){synth.iU
+size_t
+found[4];xS3
+4;++b){CodeTree
+tree;if(data.eI3]==cNop){tree
+c4
+cInv);CodeTree
+lJ3;lJ3.lH1
+lJ3
+yQ3
+eI3^2]);lJ3.lF2
+tree
+y7
+lJ3);}
+else{tree.lH1
+tree
+yQ3
+eI3]);}
+tree.lF2
+found[b]eJ3
+xF3
+tree);}
+if(found[data.yA2!=tR
+lX2]!=iS
+yA2
+i62.yV
+lX2
+iT
+cDiv
+iV
+yA2!=tR
+lC1]!=iS
+yA2
+i62.yV
+lC1
+iT
+cMul
+iV
+lO1!=tR
+lC1]!=iS
+lO1
+i62.yV
+lC1
+iT
+cRDiv
+iV
+lO1!=tR
+lX2]!=iS
+lO1
+i62.yV
+lX2
+iT
+cMul,2,1
+i62.iU
+size_t
+n_subexpressions_synthesized=SynthCommonSubExpressions(synth);switch(l42{case
+iE2:synth.PushVar(GetVar());lD
+cImmed:eV1
+xE1);lD
+cAdd:case
+cMul:case
+cMin:case
+cMax:case
+cAnd:case
+cOr:case
+cAbsAnd:case
+cAbsOr:l22==cMul){bool
+yR3
+e23
+yP
+lP1
+yP2)&&isLongInteger(lP1.xE1)){yO1=makeLongInteger(lP1.xE1);CodeTree
+tmp(*this,typename
+CodeTree::CloneTag());tmp.DelParam(a);tmp
+eM1
+if(nQ1
+tmp,value,x51::tH1
+yB::AddSequence,synth,MAX_MULI_BYTECODE_LENGTH)){yR3=true;yN3}
+if(yR3)yY3
+int
+y71=0
+e72
+bool>done(GetParamCount(),false);CodeTree
+iG;iG
+c4
+l42;for(;;){bool
+found
+e23
+yP
+done[a])y41
+if(synth.IsStackTop(lP1)){found=true;done[a]=true;lP1.n8
+iG
+cM
+lP1);if(++y71>1){yW
+2);iG.Rehash(false)cZ1
+iG);y71=y71-2+1;}
+}
+}
+if(!found)yY3
+yP
+done[a])y41
+lP1.n8
+iG
+cM
+lP1);if(++y71>1){yW
+2);iG.Rehash(false)cZ1
+iG);y71=y71-2+1;}
+}
+if(y71==0){switch(l42{case
+cAdd:case
+cOr:case
+cAbsOr:eV1
+0);lD
+cMul:case
+cAnd:case
+cAbsAnd:eV1
+1);lD
+cMin:case
+cMax:eV1
+0
+eP3;y13
+yY3++y71;}
+assert(n_stacked==1);break
+cT1
+cPow:{iS2
+p0
+nT2
+0);iS2
+p1
+nT2
+1);if(!p1
+yP2)||!isLongInteger(p1.xE1)||!nQ1
+p0,makeLongInteger(p1.xE1),x51::tH1
+yB::MulSequence,synth,MAX_POWI_BYTECODE_LENGTH)){p0.n8
+p1.n8
+yW
+2);i31
+cIf:case
+cAbsIf:{typename
+x51
+yZ3::IfData
+nP3;GetParam(0).n8
+synth.SynthIfStep1(nP3,l42;GetParam(1).n8
+synth.SynthIfStep2(nP3);GetParam(2).n8
+synth.SynthIfStep3(nP3
+eP3
+cT1
+cFCall:case
+cPCall:{n72
+0;a<x31++a)lP1.n8
+yW
+nD2)GetParamCount());n42
+0x80000000u|GetFuncNo(),0,0);yY3
+y13{n72
+0;a<x31++a)lP1.n8
+yW
+nD2)GetParamCount());yN3
+synth.StackTopIs(*this);if(MustPopTemps&&n_subexpressions_synthesized>0){size_t
+top
+eJ3
+GetStackTop(i62.DoPopNMov(top-1-n_subexpressions_synthesized,top-1);}
+}
+}
+iR2{yD
+bool
+nQ1
+xB3,long
+count,const
+x51::SequenceOpCode
+yB&eR,x51
+yZ3&synth,size_t
+max_bytecode_grow_length
+cI3
+count!=0){x51
+yZ3
+backup=synth;tree.n8
+size_t
+bytecodesize_backup
+eJ3
+GetByteCodeSize();x51::nQ1
+count
+n32
+size_t
+bytecode_grow_amount
+eJ3
+GetByteCodeSize()-bytecodesize_backup;if(bytecode_grow_amount>max_bytecode_grow_length){synth=backup
+eO
+false
+yC3
+true;}
+else{x51::nQ1
+count,eR,synth)cT2}
+}
+#endif
+#include <cmath>
+#include <cassert>
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;iR2{using
+tC;
+#define FactorStack std::vector
+const
+cP2
+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={iF1
+xC
+cNeg,iF1,iF1}
+;yD
+l62
+c61
+const
+PowiMuliType&yS3,t51,lG2&stack){l62
+nT3(1);while(IP<limit
+cI3
+lK3
+yS3.opcode_square
+cI3!t12
+nT3))lH2
+2;c0
+opcode_invert){nT3=-nT3;c0
+opcode_half
+cI3
+nT3>tD1)&&isEvenInteger(nT3))lH2
+l62(0.5);c0
+opcode_invhalf
+cI3
+nT3>tD1)&&isEvenInteger(nT3))lH2
+l62(-0.5);++IP;y41}
+size_t
+nO2=IP;l62
+lhs(1);if(lK3
+cFetch){lB1=lL3;if(index<y4||size_t(index-y4)>=iK1){IP=nO2;yY3
+lhs=stack[index-y4];goto
+yB2;}
+if(lK3
+cDup){lhs=nT3;goto
+yB2;yB2:eW1
+nT3);++IP;l62
+subexponent=c61
+yS3
+i0
+if(IP>=limit||eE1[IP]!=yS3.opcode_cumulate){IP=nO2;yY3++IP;stack.pop_back();nT3+=lhs*subexponent;y41}
+break
+yC3
+nT3;}
+yD
+l62
+ParsePowiSequence(t51){lG2
+stack;eW1
+l62(1))eO
+c61
+iseq_powi
+i0}
+yD
+l62
+ParseMuliSequence(t51){lG2
+stack;eW1
+l62(1))eO
+c61
+iseq_muli
+i0}
+x13
+CodeTreeParserData{cV3
+iK2
+CodeTreeParserData(bool
+k_powi):stack(),clones(),keep_powi(k_powi){}
+void
+Eat
+x72
+eG3,OPCODE
+opcode
+nQ
+xN;xN
+c4
+opcode);nX2
+e13=Pop(eG3);xN
+iY1
+tE2;if(!keep_powi)switch(opcode
+e53
+cTanh:{xG
+sinh,cosh;sinh
+c4
+cSinh);sinh
+cM
+xN
+xN2
+sinh
+eM1
+cosh
+c4
+cCosh);cosh
+y7
+xN
+xN2
+cosh
+eM1
+xG
+pow;pow
+c4
+cPow);pow
+y7
+cosh);pow.yJ
+l62(-1)));pow
+eM1
+xN
+c4
+yT3.n41
+0,sinh);xN
+y7
+pow
+eP3
+cT1
+cTan:{xG
+sin,cos;sin
+c4
+cSin);sin
+cM
+xN
+xN2
+sin
+eM1
+cos
+c4
+cCos);cos
+y7
+xN
+xN2
+cos
+eM1
+xG
+pow;pow
+c4
+cPow);pow
+y7
+cos);pow.yJ
+l62(-1)));pow
+eM1
+xN
+c4
+yT3.n41
+0,sin);xN
+y7
+pow
+eP3
+cT1
+cPow:{iT1
+p0=xN
+l8
+0);iT1
+p1=xN
+l8
+1);if(p1
+nF==cAdd){nX2
+i82(p1.GetParamCount());n72
+0;a<p1.x31++a
+nQ
+pow;pow
+c4
+cPow);pow
+cM
+p0);pow
+cM
+p1
+lS3
+pow
+eM1
+i82[a
+eO3
+pow);}
+xN
+c4
+yT3
+iY1
+i82);}
+yY3
+y13
+yY3
+xN.Rehash(!keep_powi);iI1,false);
+#ifdef DEBUG_SUBSTITUTIONS
+iJ1<<eG3<<", "
+<<eK3(opcode)<<"->"
+<<eK3(xN
+nF)<<": "
+t93
+xN)iW
+xN);
+#endif
+eW1
+xN
+n33
+EatFunc
+x72
+eG3,OPCODE
+cW3
+unsigned
+funcno
+nQ
+xN=CodeTreeFuncOp
+yB(cW3
+funcno);nX2
+e13=Pop(eG3);xN
+iY1
+tE2;xN.lF2
+#ifdef DEBUG_SUBSTITUTIONS
+iJ1<<eG3<<", "
+t93
+xN)iW
+xN);
+#endif
+iI1);eW1
+xN
+n33
+xU
+yB1
+nQ
+xN=CodeTreeImmed(value);iI1);Push(xN
+n33
+AddVar
+nD2
+varno
+nQ
+xN=CodeTreeVar
+yB(varno);iI1);Push(xN
+n33
+SwapLastTwoInStack(){eX1
+1
+eO3
+eX1
+2]n33
+Dup(){Fetch(iK1-1
+n33
+Fetch
+x72
+which){Push(stack[which]);}
+nH1
+T>void
+Push(T
+tree){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<t93
+tree)iW
+tree);
+#endif
+eW1
+tree
+n33
+PopNMov
+x72
+target,size_t
+source){stack[target]=stack[source];stack
+x53
+target+1);}
+xG
+yC2{clones.clear();xG
+nT3(stack.back());stack
+x53
+iK1-1)eO
+nT3;}
+nX2
+Pop
+x72
+n_pop){nX2
+nT3(n_pop);for
+nD2
+n=0;n<n_pop;++n)nT3[n
+eO3
+eX1
+n_pop+n]);
+#ifdef DEBUG_SUBSTITUTIONS
+for
+x72
+n=n_pop;n-->0;){iJ1
+yR2
+nT3[n])iW
+nT3[n]);}
+#endif
+stack
+x53
+iK1-n_pop)eO
+nT3;}
+size_t
+GetStackTop(yK1
+iK1;}
+private:void
+FindClone(xG&,bool=true)yS;}
+private:nX2
+stack;std::multimap<fphash_t,xG>clones;bool
+keep_powi;private:CodeTreeParserData
+cY1
+CodeTreeParserData&);CodeTreeParserData&eD1=cY1
+CodeTreeParserData&);}
+;yD
+cP2
+IfInfo{xG
+eO2;xG
+thenbranch;size_t
+endif_location;IfInfo():eO2(),thenbranch(),endif_location(){}
+}
+;}
+tC{lC
+GenerateFrom
+cY1
+typename
+FunctionParserBase
+yB::Data&nR3,bool
+keep_powi){nX2
+x12;x12.xD3
+nR3.mVariablesAmount);for
+nD2
+n=0;n<nR3.mVariablesAmount;++n){x12
+yS2
+CodeTreeVar
+yB(n+iE2));}
+GenerateFrom(nR3,x12,keep_powi);}
+lC
+GenerateFrom
+cY1
+typename
+FunctionParserBase
+yB::Data&nR3,const
+x7&x12,bool
+keep_powi){yL1
+unsigned>&eE1=nR3.mByteCode;const
+std::vector
+yB&Immed=nR3.mImmed;
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"ENTERS GenerateFrom()\n"
+;
+#endif
+CodeTreeParserData
+yB
+sim(keep_powi)e72
+IfInfo
+yB>eN;for
+x72
+IP=0,DP=0;;++IP){tK2:while(!eN
+yU3&&(eN.eD==IP||(IP<lX1&&lK3
+cJump&&eN.eA1.n12))){CodeTree
+elsebranch=sim.yC2
+n92
+eN.back().eO2)n92
+eN.eA1)n92
+elsebranch);sim.Eat(3,cIf);eN.pop_back();}
+if(IP>=lX1)break;unsigned
+opcode=eE1[IP];if((opcode==cSqr||opcode==cDup||(opcode==cInv&&!IsIntType
+yB::nT3)||opcode==cNeg||opcode==cSqrt||opcode==cRSqrt||opcode==cFetch)){size_t
+was_ip=IP;l62
+cY2
+ParsePowiSequence
+yB(eE1,IP,eN
+yU3?lX1:eN.eD,sim.xH
+1);if(nU3!=l62(1.0)){sim.xU
+x32
+xX
+cPow);goto
+tK2;}
+if(opcode==cDup||opcode==cFetch||opcode==cNeg){l62
+xH2=ParseMuliSequence
+yB(eE1,IP,eN
+yU3?lX1:eN.eD,sim.xH
+1);if(xH2!=l62(1.0)){sim.xU
+xH2)xX
+cMul);goto
+tK2;}
+}
+IP=was_ip;}
+if(lI2>=iE2){lB1=opcode-iE2
+n92
+x12[index]);}
+else{switch(lI2
+e53
+cIf:case
+cAbsIf:{eN
+x53
+eN.size()+1);CodeTree
+res(sim.yC2);eN.back().eO2.swap(res);eN.eD=lX1;IP+=2;y41}
+case
+cJump:{CodeTree
+res(sim.yC2);eN.eA1.swap(res);eN.eD=eE1[IP+1]+1;IP+=2;y41}
+case
+cImmed:sim.xU
+Immed[DP++]);lD
+cDup:sim.Dup();lD
+cNop:lD
+cFCall:{unsigned
+funcno=lL3;assert(funcno<fpdata.mFuncPtrs.size());unsigned
+e13=nR3.mFuncPtrs
+lM3
+mParams;sim.EatFunc(e13,lI2,funcno
+eP3
+cT1
+cPCall:{unsigned
+funcno=lL3;assert(funcno<fpdata.t63.size());const
+FunctionParserBase
+yB&p=*nR3.t63
+lM3
+mParserPtr;unsigned
+e13=nR3.t63
+lM3
+mParams;x7
+paramlist=sim.Pop(tE2;CodeTree
+tL2;tL2.GenerateFrom(*p.mData,paramlist)n92
+tL2
+eP3
+cT1
+cInv:sim.xU
+1
+lY2
+cDiv);lD
+cNeg:nA2
+cNeg
+eP3;sim.xU
+0
+lY2
+cSub);lD
+cSqr:sim
+c52;lD
+cSqrt
+tM3
+eY1
+cRSqrt
+tM3-eY1
+cCbrt
+tM3
+1)/l62(3))xX
+yV3
+cDeg:sim.xU
+fp_const_rad_to_deg
+e11
+cRad:sim.xU
+fp_const_deg_to_rad
+e11
+cExp:iH)goto
+default_function_handling;sim.xU
+fp_const_e
+yB()lY2
+yV3
+cExp2:iH)goto
+default_function_handling;sim.xU
+2.0
+lY2
+yV3
+cCot:nA2
+cTan);iH)x2
+cCsc:nA2
+cSin);iH)x2
+cSec:nA2
+cCos);iH)x2
+cInt:
+#ifndef __x86_64
+iH){nA2
+cInt);yY3
+#endif
+sim
+i61
+0.5))xX
+cAdd);nA2
+cFloor);lD
+cLog10:nA2
+yD2
+fp_const_log10inv
+e11
+cLog2:nA2
+yD2
+fp_const_log2inv
+e11
+cLog2by:lN3
+yD2
+fp_const_log2inv
+yB());sim.Eat(3,cMul);lD
+cHypot:sim
+c52;sim.nX1
+sim
+c52
+xX
+cAdd);sim
+i61
+eY1
+cSinCos:sim.Dup();nA2
+cSin);lN3
+cCos);lD
+cSinhCosh:sim.Dup();nA2
+cSinh);lN3
+cCosh);lD
+cRSub:sim.nX1
+case
+cSub:iH){sim.Eat(2,cSub);yY3
+sim.xU-1)xX
+cMul)xX
+cAdd);lD
+cRDiv:sim.nX1
+case
+cDiv:iH||IsIntType
+yB::nT3){sim.Eat(2,cDiv);yY3
+sim.xU-1)xX
+cPow)xX
+cMul);lD
+cAdd:case
+cMul:case
+cMod:case
+cPow:case
+cEqual:case
+cLess:case
+cGreater:case
+tP1:case
+cLessOrEq:case
+cGreaterOrEq:case
+cAnd:case
+cOr:case
+cAbsAnd:case
+cAbsOr:sim.Eat(2
+cS1
+lD
+cNot:case
+cNotNot:case
+c03:case
+cAbsNotNot:sim.Eat(1
+cS1
+lD
+cFetch:sim.Fetch(lL3);lD
+cPopNMov:{unsigned
+stackOffs_target=lL3;unsigned
+stackOffs_source=lL3;sim.PopNMov(stackOffs_target,stackOffs_source);yY3
+y13
+default_function_handling:;unsigned
+funcno=opcode-cAbs;assert(funcno<FUNC_AMOUNT);const
+FuncDefinition&func=Functions[funcno];sim.Eat(func.e13
+cS1
+yN3}
+Become(sim.yC2);
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Produced tree:\n"
+;iQ
+#endif
+}
+}
+#endif
+#include <algorithm>
+#ifdef FP_SUPPORT_OPTIMIZER
+#include <assert.h>
+#define FP_MUL_COMBINE_EXPONENTS
+iR2{using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;yD
+static
+void
+AdoptChildrenWithSameOpcode(cV2{
+#ifdef DEBUG_SUBSTITUTIONS
+bool
+lZ2
+e23
+#endif
+for
+c7
+if
+tN3
+nF==tree
+nF){
+#ifdef DEBUG_SUBSTITUTIONS
+if(!lZ2)lC3"Before assimilation: "
+xY
+lZ2=true;}
+#endif
+tree.AddParamsMove
+tN3.GetUniqueRef().iP1),a);}
+#ifdef DEBUG_SUBSTITUTIONS
+if(lZ2)lC3"After assimilation: "
+xY}
+#endif
+}
+}
+tC{x73
+ConstantFolding(cV2{tree.Sort();
+#ifdef DEBUG_SUBSTITUTIONS
+void*yW3=0
+xO1"["
+<<(&yW3)<<"]Runs ConstantFolding for: "
+xY
+DumpHashes(tree)xO1
+std::flush;
+#endif
+if(false){redo:;tree.Sort();
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"["
+<<(&yW3)<<"]Re-runs ConstantFolding: "
+xY
+DumpHashes(tree);
+#endif
+}
+if(tree
+nF!=cImmed){range
+yB
+p=iO
+tree);if(p
+eY&&p
+t6
+cF3==p
+nV){tree.ReplaceWithImmed(p
+e32
+l32}
+}
+if(false){ReplaceTreeWithOne
+e93.ReplaceWithImmed(l62(1)l32
+ReplaceTreeWithZero
+e93.ReplaceWithImmed(tD1)l32
+ReplaceTreeWithParam0:
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Before replace: "
+xO1
+std::hex<<'['<<tree
+n02
+hash1<<','<<tree
+n02
+hash2<<']'<<std::dec
+xY
+#endif
+tree
+iD2
+tQ);
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"After replace: "
+xO1
+std::hex<<'['<<tree
+n02
+hash1<<','<<tree
+n02
+hash2<<']'<<std::dec
+xY
+#endif
+cN
+yX3
+l83{case
+cImmed:lD
+iE2:lD
+cAnd:case
+cAbsAnd:e0
+bool
+cD
+e23
+for
+c7{if(!IsLogicalValue
+tN3))cD=true;cN3
+tJ3
+i21
+cAbsAnd)e53
+xL3
+tE
+IsAlways:e61);lD
+lS1
+yX3(t7
+e53
+0:iA
+1
+e93
+c4
+i21
+cAnd?cNotNot:cAbsNotNot);cN
+y13
+if(i21
+cAnd||!cD)if(ConstantFolding_AndLogic(e82
+i31
+cOr:case
+cAbsOr:e0
+bool
+cD
+e23
+for
+c7{if(!IsLogicalValue
+tN3))cD=true;cN3
+tJ3
+i21
+cAbsOr))i71
+iA
+iO2
+e61);lD
+lS1
+yX3(t7
+e53
+0
+tE
+1
+e93
+c4
+i21
+cOr?cNotNot:cAbsNotNot);cN
+y13
+if(i21
+cOr||!cD)if(ConstantFolding_OrLogic(e82
+i31
+cNot:case
+c03:{unsigned
+lZ1
+0;switch(tQ
+nF
+e53
+cEqual:lZ1
+tP1;lD
+tP1:lZ1
+cEqual;lD
+cLess:lZ1
+cGreaterOrEq;lD
+cGreater:lZ1
+cLessOrEq;lD
+cLessOrEq:lZ1
+cGreater;lD
+cGreaterOrEq:lZ1
+cLess;lD
+cNotNot:lZ1
+cNot;lD
+cNot:lZ1
+cNotNot;lD
+c03:lZ1
+cAbsNotNot;lD
+cAbsNotNot:lZ1
+c03;break;y13
+yY3
+if(opposite){tree
+c4
+OPCODE(opposite));tree
+iY1
+tQ.GetUniqueRef().iP1));cN
+yX3
+nR1
+tQ,tree
+c71
+e53
+IsAlways
+tE
+iO2
+iA
+lS1
+if(i21
+cNot&&GetPositivityInfo(tQ)==IsAlways)tree
+c4
+c03);if(e43
+cIf||e43
+cAbsIf
+nQ
+iM2=tQ;iT1
+ifp1=iM2
+l8
+1);iT1
+ifp2=iM2
+l8
+2);if(ifp1
+nF==cNot||ifp1
+c71
+tG3
+ifp1
+nF==cNot?cNotNot:cAbsNotNot);tM2
+l8
+0))lT1
+cM3
+n82
+p2
+lO3
+p2.lP3
+if(ifp2
+nF==cNot||ifp2
+c71
+tG3
+tree
+nF);tM2)lT1
+cM3
+c4
+ifp2
+nF==cNot?cNotNot:cAbsNotNot);p2
+cM
+ifp2
+xN2
+p2.lP3
+i31
+cNotNot:case
+cAbsNotNot:{if(IsLogicalValue(tQ))goto
+e5
+cN3
+tQ,i21
+cAbsNotNot)e53
+xL3
+tE
+IsAlways:iA
+lS1
+if(i21
+cNotNot&&GetPositivityInfo(tQ)==IsAlways)tree
+c4
+cAbsNotNot);if(e43
+cIf||e43
+cAbsIf
+nQ
+iM2=tQ;iT1
+ifp1=iM2
+l8
+1);iT1
+ifp2=iM2
+l8
+2);if(ifp1
+nF==cNot||ifp1
+c71{tree.SetParam(0,iM2
+xN2
+tree
+cM
+ifp1);cM3
+n82
+p2
+lO3
+p2.lP3
+if(ifp2
+nF==cNot||ifp2
+c71
+tG3
+tree
+nF);tM2)lT1
+tree
+lO3
+tree
+c4
+iM2
+nF);cN}
+i31
+cIf:case
+cAbsIf:{if(ConstantFolding_IfOperations(e82
+break
+cT1
+cMul:{NowWeAreMulGroup:;AdoptChildrenWithSameOpcode(tree);l62
+nB1=l62(1);size_t
+iL1=0;bool
+nC1
+e23
+for
+c6
+if(!xQ1
+y41
+l62
+immed=yE2;if(immed==tD1))goto
+ReplaceTreeWithZero;nB1*=immed;++iL1;}
+if(iL1>1||(iL1==1&&fp_equal(nB1,l62(1))))nC1=true;if(nC1){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"cMul: Will add new "
+t73
+nB1<<"\n"
+;
+#endif
+for
+c7
+if(xQ1{
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<" - For that, deleting "
+t73
+yE2
+xO1"\n"
+;
+#endif
+lQ3!fp_equal(nB1,l62(1)))tree
+cM
+cL1
+nB1));yX3(t7
+e53
+0:iA
+1:goto
+e5
+y13
+if(ConstantFolding_MulGrouping(e82
+if(ConstantFolding_MulLogicItems(e82
+i31
+cAdd:e0
+l62
+lJ2=0.0;size_t
+iL1=0;bool
+nC1
+e23
+for
+c6
+if(!xQ1
+y41
+l62
+immed=yE2;lJ2+=immed;++iL1;}
+if(iL1>1||(iL1==1&&lJ2==tD1)))nC1=true;if(nC1){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"cAdd: Will add new "
+t73
+lJ2<<"\n"
+xO1"In: "
+xY
+#endif
+for
+c7
+if(xQ1{
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<" - For that, deleting "
+t73
+yE2
+xO1"\n"
+;
+#endif
+lQ3!(lJ2==l62(0.0)))tree
+cM
+cL1
+lJ2));yX3(t7
+e53
+0
+tE
+1:goto
+e5
+y13
+if(ConstantFolding_AddGrouping(e82
+if(ConstantFolding_AddLogicItems(e82
+i31
+cMin:e0
+size_t
+yF2=0;range
+yB
+e7;for
+c6
+while(a+1<t7&&xP1
+a)xI
+xP1
+a+1)))e61+1);range<l62
+nY
+max
+iN2(!e7
+t6||(p
+nV)<e7
+nV)){e7
+nV=p
+nV;e7
+t6=true;yF2=a;}
+}
+if(e7
+t6)for
+c7{range<l62
+nY
+min
+iN2
+a!=yF2
+cF3>=e7
+nV)lQ3
+t7==1){goto
+e5
+i31
+cMax:e0
+size_t
+yF2=0;range
+yB
+t2;for
+c6
+while(a+1<t7&&xP1
+a)xI
+xP1
+a+1)))e61+1);range<l62
+nY
+min
+iN2(!t2
+eY||p
+e32>t2
+e32)){t2
+e32=p
+e32;t2
+eY=true;yF2=a;}
+}
+if(t2
+eY){for
+c7{range<l62
+nY
+max
+iN2
+a!=yF2&&(p
+nV)<t2
+e32){e61);}
+}
+}
+if(t7==1){goto
+e5
+i31
+cEqual:case
+tP1:case
+cLess:case
+cGreater:case
+cLessOrEq:case
+cGreaterOrEq:if(ConstantFolding_Comparison(e82
+lD
+cAbs:{range
+yB
+p0=tO
+0));if(p0.cK
+goto
+e5
+if(p0.c8{tree
+c4
+cMul);tree.yJ
+l62(1)));goto
+NowWeAreMulGroup;}
+if(e43
+cMul){iT1
+p=tQ;nX2
+lR3;nX2
+cG2;n72
+0;a<p.x31++a){p0=iO
+p
+lS3
+if(p0.cK{lR3
+yS2
+p
+lS3}
+if(p0.c8{cG2
+yS2
+p
+lS3}
+}
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"Abs: mul group has "
+<<lR3.size()<<" pos, "
+<<cG2.size()<<"neg\n"
+;
+#endif
+if(!lR3
+yU3||!cG2
+yU3){
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"AbsReplace-Before: "
+yR2
+tree)xO1"\n"
+<<std::flush;DumpHashes(tree
+cH2;
+#endif
+xG
+cT3;cT3
+c4
+cMul);n72
+0;a<p.x31++a){p0=iO
+p
+lS3
+if((p0.cK||(p0.c8){}
+else
+cT3
+cM
+p
+lS3}
+cT3
+eM1
+xG
+lT3;lT3
+c4
+cAbs);lT3
+y7
+cT3);lT3
+eM1
+xG
+xX1
+cMul);i82
+y7
+lT3);xY1
+AddParamsMove(lR3);if(!cG2
+yU3
+cI3
+cG2.size()%2)xY1
+yJ
+l62(-1)));xY1
+AddParamsMove(cG2);}
+tree
+iD2
+i82);
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"AbsReplace-After: "
+yR2
+tree
+cH2
+xO1"\n"
+<<std::flush;DumpHashes(tree
+cH2;
+#endif
+goto
+NowWeAreMulGroup;}
+}
+yY3
+#define HANDLE_UNARY_CONST_FUNC(funcname) y23 funcname(lS nD
+case
+cLog:eW3(fp_log);if(e43
+cPow
+nQ
+pow=tQ;if(GetPositivityInfo(pow
+l8
+0))==IsAlways
+xA3
+pow
+xF1
+tree.lV
+if(GetEvennessInfo(pow
+l8
+1))==IsAlways
+xA3
+xG
+abs;abs
+c4
+cAbs);abs
+y7
+pow
+xN2
+abs
+eM1
+pow
+xF1
+pow.n41
+0,abs);tree.lV}
+i81
+e43
+cAbs
+nQ
+pow=tQ
+l8
+0);if(pow
+nF==cPow
+xA3
+xG
+abs;abs
+c4
+cAbs);abs
+y7
+pow
+xN2
+abs
+eM1
+pow
+xF1
+pow.n41
+0,abs);tree.lV}
+lD
+cAcosh:eW3(fp_acosh);lD
+cAsinh:eW3(fp_asinh);lD
+cAtanh:eW3(fp_atanh);lD
+cAcos:eW3(fp_acos);lD
+cAsin:eW3(fp_asin);lD
+cAtan:eW3(fp_atan);lD
+cCosh:eW3(fp_cosh);lD
+cSinh:eW3(fp_sinh);lD
+cTanh:eW3(fp_tanh);lD
+cSin:eW3(fp_sin);lD
+cCos:eW3(fp_cos);lD
+cTan:eW3(fp_tan);lD
+cCeil:if(n5
+eW3(fp_ceil);lD
+cTrunc:if(n5
+eW3(fp_trunc);lD
+cFloor:if(n5
+eW3(fp_floor);lD
+cInt:if(n5
+eW3(fp_int);lD
+cCbrt:eW3(fp_cbrt);lD
+cSqrt:eW3(fp_sqrt);lD
+cExp:eW3(fp_exp);lD
+cLog2:eW3(fp_log2);lD
+cLog10:eW3(fp_log10);lD
+cLog2by:if
+lJ
+fp_log2(lS)*c13
+cArg:eW3(fp_arg);lD
+cConj:eW3(fp_conj);lD
+cImag:eW3(fp_imag);lD
+cReal:eW3(fp_real);lD
+cPolar:if
+lJ
+fp_polar
+e42
+cMod:if
+lJ
+fp_mod
+e42
+cAtan2:{range
+yB
+p0
+tN
+p1=tO
+1));cD3
+fp_equal(lS,tD1))cI3
+p1
+t6&&(p1
+nV)<tD1
+nR
+fp_const_pi
+yB(nD
+if(p1
+eY&&p1
+e32>=tN2
+tD1
+nD}
+if
+lM1
+fp_equal(tM),tD1))cI3
+p0
+t6&&(p0
+nV)<tD1
+nR-fp_const_pihalf
+yB(nD
+if(p0
+eY&&p0
+e32>tD1
+nR
+fp_const_pihalf
+yB(nD}
+if
+lJ
+fp_atan2(lS,tM)nD
+if((p1
+eY&&p1
+e32>tD1))||(p1
+t6&&(p1
+nV)<fp_const_negativezero
+yB())nQ
+yG2;yG2
+c4
+cPow);yG2
+y7
+t32);yG2.yJ
+l62(-1)));yG2
+eM1
+xG
+yH2;yH2
+c4
+cMul);yH2
+y7
+tQ);yH2
+y7
+yG2);yH2
+eM1
+tree
+c4
+cAtan);tree.n41
+0,yH2)lP2
+1);i31
+cPow:{if(ConstantFolding_PowOperations(e82
+break
+cT1
+cDiv:cD3
+xP1
+yO2&&tM)!=tN2
+lS/c13
+cInv:cD3
+lS!=tN2
+l62(1)/lS);yV1
+cSub:if
+lJ
+lS-c13
+cNeg:y23-lS);yV1
+cRad:y23
+RadiansToDegrees(lS
+nD
+lD
+cDeg:y23
+DegreesToRadians(lS
+nD
+lD
+cSqr:y23
+lS*lS);yV1
+cExp2:eW3(fp_exp2);lD
+cRSqrt:y23
+l62(1)/fp_sqrt(lS
+nD
+lD
+cCot
+tK3
+fp_tan(n3
+cSec
+tK3
+fp_cos(n3
+cCsc
+tK3
+fp_sin(n3
+cHypot:if
+lJ
+fp_hypot
+e42
+cRDiv:case
+cRSub:case
+cDup:case
+cFetch:case
+cPopNMov:case
+cSinCos:case
+cSinhCosh:case
+cNop:case
+cJump:lD
+cPCall:case
+cFCall:yY3
+do_return:;
+#ifdef DEBUG_SUBSTITUTIONS
+std::cout<<"["
+<<(&yW3)<<"]Done ConstantFolding, result: "
+xY
+DumpHashes(tree);
+#endif
+}
+}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+tC{x73
+range
+yB::set_abs(nN
+bool
+has_negative=!min.known||min.val<l62();bool
+has_positive=!max.known||max.val>l62();bool
+crosses_axis=has_negative&&has_positive;rangehalf
+yB
+newmax;if(min
+iN2
+max.known)newmax.set(fp_max(tQ1,tS1);if(crosses_axis)min.set(l62());eN3
+min
+iN2
+max.known)min.set(fp_min(tQ1,tS1);i81
+min.known)min.set(tQ1);else
+min.set(tS1;}
+max=newmax;}
+x73
+range
+yB::set_neg(){std::swap(min,max);min.val=-min.val;max.val=-max.val;}
+yD
+bool
+IsLogicalTrueValue
+cY1
+range
+yB&p
+eZ2{if(nE
+IsIntType
+yB::nT3
+cI3
+p
+eY
+cF3>=l62(1
+t41;if(!abs&&p
+t6&&p
+nV<=l62(-1
+t41;}
+eN3
+p
+eY
+cF3>=l62(0.5
+t41;if(!abs&&p
+t6&&p
+nV<=l62(-0.5
+t41
+yC3
+e83
+yD
+bool
+IsLogicalFalseValue
+cY1
+range
+yB&p
+eZ2{if(nE
+IsIntType
+yB::nT3
+cI3
+abs)yD3
+t6
+yG1
+1);else
+yD3
+eY&&p
+t6
+cF3>l62(-1)yG1
+1);}
+eN3
+abs)yD3
+t6
+yG1
+0.5);else
+yD3
+eY&&p
+t6
+cF3>l62(-0.5)yG1
+0.5);}
+}
+}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;using
+tC;tC{yD
+range
+yB
+iO
+xB3)
+#ifdef DEBUG_SUBSTITUTIONS_extra_verbose
+{using
+iR2
+FUNCTIONPARSERTYPES;range
+yB
+tmp=CalculateResultBoundaries_do(tree)xO1"Estimated boundaries: "
+;if(tmp
+eY)std::cout<<tmp
+e32;else
+std::cout<<"-inf"
+xO1" .. "
+;if(tmp
+t6)std::cout<<tmp
+nV;else
+std::cout<<"+inf"
+xO1": "
+yR2
+tree)xO1
+std::endl
+eO
+tmp;}
+yD
+range
+yB
+xG::CalculateResultBoundaries_do
+cY1
+cV2
+#endif
+{iI
+y81(-fp_const_pihalf
+yB(),fp_const_pihalf
+yB());iI
+pi_limits(-fp_const_pi
+yB(),fp_const_pi
+yB());iI
+abs_pi_limits(tD1),fp_const_pi
+yB());iI
+plusminus1_limits(l62(-n23
+using
+iR2
+std;switch
+l83{case
+cImmed:nS
+tree.xE1,tree.xE1);case
+cAnd:case
+cAbsAnd:case
+cOr:case
+cAbsOr:case
+cNot:case
+c03:case
+cNotNot:case
+cAbsNotNot:case
+cEqual:case
+tP1:case
+cLess:case
+cLessOrEq:case
+cGreater:case
+cGreaterOrEq:{nS
+tD1),l62(1))cT1
+cAbs:lE
+m.set_abs(tR1
+cLog:lE
+lU3
+fp_log
+tP2
+fp_log
+tR1
+cLog2:lE
+lU3
+fp_log2
+tP2
+fp_log2
+tR1
+cLog10:lE
+lU3
+fp_log10
+tP2
+fp_log10
+tR1
+cAcosh:lE
+yI
+xT1
+cGreaterOrEq
+eZ1
+fp_acosh
+eR3
+cGreaterOrEq
+eZ1
+fp_acosh
+tR1
+cAsinh:lE
+yI
+set(fp_asinh
+tI2
+set(fp_asinh
+tR1
+cAtanh:lE
+yI
+n2-1),fp_atanh
+eR3
+cLess
+eZ1
+fp_atanh
+tR1
+cAcos:lE
+nS(m
+t6&&(m
+nV)<l62(1))?fp_acos(m
+nV):tD1),(eJ2&&cI2)>=l62(-1))?fp_acos
+cI2):fp_const_pi
+yB())cT1
+cAsin:lE
+yI
+n2-1),fp_asin,y81
+e32
+eR3
+cLess
+eZ1
+fp_asin,y81
+nV
+tR1
+cAtan:lE
+yI
+set(fp_atan,y81
+e32
+tI2
+set(fp_atan,y81
+nV
+tR1
+cAtan2:{cD3
+fp_equal(lS,tD1)))yS
+abs_pi_limits;}
+if
+lM1
+fp_equal(tM),tD1)))yS
+y81
+yC3
+pi_limits
+cT1
+cSin:lE
+bool
+nS1=!eJ2||!m
+t6||(m
+nV-yI
+val)>=(yG
+nS1)t8
+l62
+min=fp_mod
+cI2,yG
+min<tD1))min
+yQ
+l62
+max=fp_mod(m
+nV,yG
+max<tD1))max
+yQ
+if(max<min)max
+yQ
+bool
+xU1=(min<=fp_const_pihalf
+yB()&&max>=fp_const_pihalf
+yB());bool
+nD1=(min<=cI&&max>=cI);if(xU1&&nD1)t8
+if(nD1)nS
+l62(-1),yI2;if(xU1)nS
+yK2
+l62(1));nS
+yK2
+yI2
+cT1
+cCos:lE
+if(eJ2)yI
+val+=fp_const_pihalf
+yB();if(m
+t6)m
+nV+=fp_const_pihalf
+yB();bool
+nS1=!eJ2||!m
+t6||(m
+nV-yI
+val)>=(yG
+nS1)t8
+l62
+min=fp_mod
+cI2,yG
+min<tD1))min
+yQ
+l62
+max=fp_mod(m
+nV,yG
+max<tD1))max
+yQ
+if(max<min)max
+yQ
+bool
+xU1=(min<=fp_const_pihalf
+yB()&&max>=fp_const_pihalf
+yB());bool
+nD1=(min<=cI&&max>=cI);if(xU1&&nD1)t8
+if(nD1)nS
+l62(-1),yI2;if(xU1)nS
+yK2
+l62(1));nS
+yK2
+yI2
+cT1
+cTan:{nS)cT1
+cCeil:lE
+m
+eM
+cFloor:lE
+yJ2
+tR1
+cTrunc:lE
+yJ2);m
+eM
+cInt:lE
+yJ2);m
+eM
+cSinh:lE
+yI
+set(fp_sinh
+tI2
+set(fp_sinh
+tR1
+cTanh:lE
+yI
+set(fp_tanh,plusminus1_limits.min
+tI2
+set(fp_tanh,plusminus1_limits.max
+tR1
+cCosh:lE
+if(eJ2
+cI3
+m
+t6){if
+cI2
+cW1&&m
+nV
+cW1){yI
+val=e1}
+i81
+cI2)<tD1)&&m
+nV
+cW1){l62
+tmp=e1
+if(tmp>m
+nV)m
+nV=tmp;yI
+val=l62(1);}
+else{yI
+val=e1
+std::swap
+cI2,m
+nV);}
+}
+else{if
+cI2
+cW1){m.cJ
+yI
+val=fp_cosh
+cI2);}
+else{m.cJ
+yI
+val=l62(1);}
+}
+}
+else{eJ2=true;yI
+val=l62(1);if(m
+t6){yI
+val=fp_cosh(m
+nV);m.cJ}
+else
+m.cJ}
+return
+m
+cT1
+cIf:case
+cAbsIf:{range
+yB
+res1=tO
+1));range
+yB
+res2=tO
+2));if(!res2
+eY)res1
+eY
+e23
+i81
+res1
+eY&&(res2
+e32)<res1
+e32)res1
+e32=res2
+e32;if(!res2
+t6)res1.cJ
+i81
+res1
+t6&&(res2
+nV)>res1
+nV)res1
+nV=res2
+nV
+eO
+res1
+cT1
+cMin:{bool
+iJ
+e23
+bool
+iK
+e23
+range
+lV3;x8
+m=tO
+c23
+eJ2)iJ
+e33
+eY||cI2)<lW3)lW3=yI
+val;if(!m
+t6)iK
+e33
+t6||(m
+nV)<lX3)lX3=m
+nV;}
+if(iJ)lY3
+iK)tX2
+cJ
+return
+lZ3
+cMax:{bool
+iJ
+e23
+bool
+iK
+e23
+range
+lV3;x8
+m=tO
+c23
+eJ2)iJ
+e33
+eY||yI
+val>lW3)lW3=yI
+val;if(!m
+t6)iK
+e33
+t6||m
+nV>lX3)lX3=m
+nV;}
+if(iJ)lY3
+iK)tX2
+cJ
+return
+lZ3
+cAdd:{range
+lV3(tD1),tD1));x8
+item=tO
+a));if(item
+eY)lW3+=item
+e32;else
+lY3
+item
+t6)lX3+=item
+nV;else
+tX2
+cJ
+if(!n03&&!n13)yY3
+if(n03&&n13&&lW3>lX3)std::swap
+tQ2,lX3)eO
+lZ3
+cMul:{cP2
+Value{enum
+nE3{tR2,iM1,tS2}
+;nE3
+eZ;l62
+value;Value(nE3
+t):eZ(t),value(0){}
+Value(l62
+v):eZ(tR2),value(v){}
+bool
+cJ2
+yK1
+eZ==iM1||(eZ==tR2&&value<tD1)n33
+eD1*=cY1
+Value&rhs
+cI3
+eZ==tR2&&rhs.eZ==tR2)value*=rhs.value;else
+eZ=(cJ2)!=rhs.cJ2)?iM1:tS2);}
+bool
+eD1<cY1
+Value&rhs
+yK1(eZ==iM1&&rhs.eZ!=iM1)||(eZ==tR2&&(rhs.eZ==tS2||(rhs.eZ==tR2&&value<rhs.value)));}
+}
+;cP2
+y91{Value
+yL2,yM2;y91():yL2(Value::tS2),yM2(Value::iM1){}
+void
+x22
+Value
+c33,const
+Value&value2){c33*=value2;if(c33<yL2)yL2=c33;if(yM2<c33)yM2=c33;}
+}
+;range
+lV3(l62(n23
+x8
+item=tO
+c23
+item
+eY&&!item
+t6)nS);Value
+nF3=n03?Value
+tQ2):t01
+iM1);Value
+nG3=n13?Value(lX3):t01
+tS2);Value
+nH3=item
+eY?Value(item
+e32):t01
+iM1);Value
+nI3=item
+t6?Value(item
+nV):t01
+tS2);y91
+range;range.x22
+nF3,nH3
+e52
+nF3,nI3
+e52
+nG3,nH3
+e52
+nG3,nI3);if(range.yL2.eZ==Value::tR2)lW3=range.yL2.value;else
+lY3
+range.yM2.eZ==Value::tR2)lX3=range.yM2.value;else
+tX2
+cJ
+if(!n03&&!n13)yY3
+if(n03&&n13&&lW3>lX3)std::swap
+tQ2,lX3)eO
+lZ3
+cMod:{range
+yB
+x
+tN
+y=tO
+1));if(y
+t6
+cI3
+y
+nV
+cW1
+cI3!x
+eY||(x
+e32)<tD1))nS-y
+nV,y
+nV);else
+nS
+tD1),y
+nV);}
+eN3!x
+t6||(x
+nV)cW1)nS
+y
+nV,-y
+nV);else
+nS
+y
+nV,fp_const_negativezero
+yB());}
+}
+else
+nS)cT1
+cPow:{if
+lM1
+tM)==tD1)){nS
+l62(n23}
+cD3
+lS==tD1)){nS
+tD1),tD1));}
+cD3
+fp_equal(lS
+n53
+nS
+l62(n23}
+if
+lM1
+tM)>tD1)&&GetEvennessInfo(t32)==IsAlways){l62
+cY2
+tM);range
+yB
+tmp
+tN
+nT3;n03=true;lW3=0;if(tmp
+eY&&tmp
+e32
+cW1)lW3
+xV3
+tmp
+e32,x32;i81
+tmp
+t6&&tmp
+nV<=tD1))lW3
+xV3
+tmp
+nV,x32;tX2
+cJ
+if(tmp
+eY&&tmp
+t6){n13=true;lX3=fp_max(fp_abs(tmp
+e32),fp_abs(tmp
+nV));lX3
+xV3
+lX3,x32
+yC3
+nT3;}
+range
+yB
+p0
+tN
+p1=tO
+1
+n52
+p0_positivity=(p0
+eY&&(p0
+e32)cW1)?IsAlways:(p0
+t6&&(p0
+nV)<tD1)?iO2
+Unknown);TriTruthValue
+cK2=GetEvennessInfo(xP1
+1
+n52
+t3=Unknown;switch(p0_positivity)i71
+t3=IsAlways;lD
+iO2{t3=cK2;yY3
+y13
+switch(cK2)i71
+t3=IsAlways;lD
+iO2
+lD
+Unknown:{if
+lM1!isInteger
+tL&&tM)cW1){t3=IsAlways;}
+yN3
+yX3(t3)i71{if((p1
+t6&&p1
+nV<0)||(p1
+eY&&p1
+e32<0)){nS);}
+l62
+min=tD1);if(p0
+eY&&p1
+eY){min
+xV3
+p0
+e32,p1
+e32);if(p0
+e32<tD1)&&(!p1
+t6||p1
+nV
+cW1)&&min
+cW1)min=tD1);}
+if(p0
+eY&&p0
+e32
+cW1&&p0
+t6&&p1
+t6){l62
+max
+xV3
+p0
+nV,p1
+nV);if(min>max)std::swap(min,max);nS
+min,max);}
+nS
+min,false)cT1
+iO2{nS
+false,fp_const_negativezero
+yB());}
+y13{yY3
+i31
+cNeg:lE
+m.set_neg(tR1
+cSub:{nA
+cNeg
+y53
+1
+nY3
+cAdd);nZ3;tmp
+c43
+eO
+lI
+cInv:{nB-1
+cE3
+cDiv:{nA
+cInv
+y53
+1
+nY3
+xV1
+c43
+eO
+lI
+cRad:{t21
+xV1.yJ
+fp_const_rad_to_deg
+yB(cE3
+cDeg:{t21
+xV1.yJ
+fp_const_deg_to_rad
+yB(cE3
+cSqr:{nB
+2
+cE3
+cExp:{t21
+cPow);tmp.yJ
+fp_const_e
+yB()));nZ3
+eO
+lI
+cExp2:{t21
+cPow);tmp
+eB1
+nZ3
+eO
+lI
+cCbrt:lE
+yI
+set(fp_cbrt
+tI2
+set(fp_cbrt
+tR1
+cSqrt:lE
+if(eJ2)yI
+val=cI2)<tD1)?0:fp_sqrt
+cI2);if(m
+t6)m
+nV=(m
+nV)<tD1)?0:fp_sqrt(m
+nV
+tR1
+cRSqrt:{nB-0.5
+cE3
+cHypot:{xG
+xsqr,ysqr,add,sqrt;xsqr.n7
+0));xsqr
+eB1
+ysqr.n7
+1));ysqr
+eB1
+xsqr
+c4
+cPow);ysqr
+c4
+cPow);add
+y7
+xsqr);add
+y7
+ysqr);add
+c4
+cAdd);sqrt
+y7
+add);sqrt
+c4
+cSqrt)eO
+iO
+sqrt)cT1
+cLog2by:{nA
+cLog2
+y53
+0
+nY3
+cMul);tmp
+c43;tmp.n7
+1))eO
+lI
+cCot:{nA
+cTan
+x4
+lI
+cSec:{nA
+cCos
+x4
+lI
+cCsc:{nA
+cSin
+x4
+iO
+tmp);}
+lD
+cRDiv:case
+cRSub:case
+cDup:case
+cFetch:case
+cPopNMov:case
+cSinCos:case
+cSinhCosh:case
+cNop:case
+cJump:case
+iE2:lD
+cArg:case
+cConj:case
+cImag:case
+cReal:case
+cPolar:lD
+cPCall:lD
+cFCall:yY3
+nS);}
+yD
+TriTruthValue
+GetIntegerInfo
+cY1
+cV2{switch
+l83{case
+cImmed:return
+t12
+tree.xE1)?IsAlways:xL3;case
+cFloor:case
+cCeil:case
+cTrunc:case
+cInt:return
+IsAlways;case
+cAnd:case
+cOr:case
+cNot:case
+cNotNot:case
+cEqual:case
+tP1:case
+cLess:case
+cLessOrEq:case
+cGreater:case
+cGreaterOrEq:return
+IsAlways;case
+cIf:{TriTruthValue
+a=GetIntegerInfo(xP1
+1
+n52
+b=GetIntegerInfo(cC3);if(a==b)return
+a
+eO
+Unknown
+cT1
+cAdd:case
+cMul:{for
+c7
+if(GetIntegerInfo
+tN3)!=IsAlways)return
+Unknown
+eO
+IsAlways;}
+y13
+break
+yC3
+Unknown;}
+yD
+bool
+IsLogicalValue
+cY1
+cV2{switch
+l83{case
+cImmed:return
+fp_equal(tree.xE1,tD1))||fp_equal(tree.xE1,l62(1));case
+cAnd:case
+cOr:case
+cNot:case
+cNotNot:case
+cAbsAnd:case
+cAbsOr:case
+c03:case
+cAbsNotNot:case
+cEqual:case
+tP1:case
+cLess:case
+cLessOrEq:case
+cGreater:case
+cGreaterOrEq:x0
+cMul:{for
+c7
+if(!IsLogicalValue
+tN3)c5
+return
+true
+cT1
+cIf:case
+cAbsIf:yS
+IsLogicalValue(t32)nK1
+cC3);}
+y13
+break
+yC3
+e83}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+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
+iR2
+x51{extern
+const
+unsigned
+char
+powi_table[256];}
+iR2{using
+tC;yD
+bool
+IsOptimizableUsingPowi(long
+immed,long
+penalty=0){x51
+yZ3
+synth;synth.PushVar(iE2);size_t
+bytecodesize_backup
+eJ3
+GetByteCodeSize();x51::nQ1
+immed,x51::tH1
+yB::MulSequence,synth);size_t
+bytecode_grow_amount
+eJ3
+GetByteCodeSize()-bytecodesize_backup
+eO
+bytecode_grow_amount<size_t(MAX_POWI_BYTECODE_LENGTH-penalty);}
+x73
+ChangeIntoRootChain(xG&tree,bool
+iP2,long
+tT2,long
+tU2){while(tU2>0
+nP2
+cCbrt);nQ2
+tmp
+eM1
+tree.tV2--tU2;}
+while(tT2>0
+nP2
+cSqrt);if(iP2){tmp
+c4
+cRSqrt);iP2
+e23}
+nQ2
+tmp
+eM1
+tree.tV2--tT2;}
+if(iP2
+nP2
+cInv);nQ2
+tree.tV2}
+}
+yD
+cP2
+RootPowerTable{static
+const
+l62
+RootPowers[(1+4)*(1+3)];}
+;yD
+const
+l62
+tF(1+4)*(1+3)]={l62(1)lT
+eQ3
+eQ3
+2*eQ3
+2*2*2)lT
+3)lT
+3*2)lT
+3*2*2)lT
+3*2*2*2)lT
+3*2*2*2*2)lT
+3*3
+i32
+2
+i32
+2*2
+i32
+2*2*2
+i32
+2*2*2*2
+i32
+3
+i32
+3*2
+i32
+3*2*2
+i32
+3*2*2*2
+i32
+3*2*2*2*2)}
+;cP2
+PowiResolver{static
+const
+unsigned
+MaxSep=4;static
+nK3
+MaxOp=5
+tO3
+int
+c53
+tO3
+long
+nS3
+tO3
+long
+tH;cP2
+yN2{yN2():n_int_sqrt(0),n_int_cbrt(0),sep_list(),lU1(0){}
+int
+n_int_sqrt;int
+n_int_cbrt;int
+tG1
+MaxSep];tH
+lU1;}
+;yD
+static
+yN2
+CreatePowiResult(l62
+x32{yN2
+nT3;c53
+tG=FindIntegerFactor(x32;if(tG==0){
+#ifdef DEBUG_POWI
+tW2"no factor found for %Lg\n"
+,e21
+x32;
+#endif
+return
+nT3;}
+cG3=xW1
+nU3,tG);nS3
+eP2=EvaluateFactorCost(tG,0,0,0)+cH
+cG3);int
+eS3=0;int
+eT3=0;int
+nJ3=0;
+#ifdef DEBUG_POWI
+tW2"orig = %Lg\n"
+,e21
+x32;tW2"plain factor = "
+tA3"%ld\n"
+,(int)tG,(long)eP2);
+#endif
+for
+nD2
+n_s=0;n_s<MaxSep;++n_s){int
+xJ=0;nS3
+yA1=eP2;c53
+yI1=tG;for(int
+s=1;s<MaxOp*4;++s){
+#ifdef CBRT_IS_SLOW
+if(s>=MaxOp)break;
+#endif
+int
+n_sqrt=s%MaxOp;int
+n_cbrt=s/MaxOp;if(n_sqrt+n_cbrt>4)y41
+l62
+lD1=nU3;lD1-=tF
+s];tT1=FindIntegerFactor(lD1);if(xH2!=0){tH
+xO=xW1
+lD1,xH2);nS3
+cost=EvaluateFactorCost(xH2,eS3+n_sqrt,eT3+n_cbrt,nJ3+1)+cH
+xO);
+#ifdef DEBUG_POWI
+tW2"Candidate sep %u (%d*sqrt %d*cbrt)factor = "
+tA3"%ld (for %Lg to %ld)\n"
+,s,n_sqrt,n_cbrt,xH2,(long)cost,e21
+lD1,(long)xO);
+#endif
+if(cost<yA1){xJ=s;yI1=xH2;yA1=cost;}
+}
+}
+if(!xJ)break;
+#ifdef DEBUG_POWI
+tW2"CHOSEN sep %u (%d*sqrt %d*cbrt)factor = "
+tA3"%ld, exponent %Lg->%Lg\n"
+,xJ,xJ%MaxOp,xJ/MaxOp,yI1,yA1,e21(x32,e21(nU3-tF
+xJ]));
+#endif
+tX2
+tG1
+n_s]=xJ
+t11-=tF
+xJ];eS3+=xJ%MaxOp;eT3+=xJ/MaxOp;eP2=yA1;tG=yI1;nJ3+=1;}
+cG3=xW1
+nU3,tG);
+#ifdef DEBUG_POWI
+tW2"resulting exponent is %ld (from exponent=%Lg, best_factor=%Lg)\n"
+,cG3,e21
+nU3,e21
+tG);
+#endif
+while(tG%2==0){++tX2
+n_int_sqrt;tG/=2;}
+while(tG%3==0){++tX2
+n_int_cbrt;tG/=3
+yC3
+nT3;}
+private:static
+nS3
+cH
+tH
+xO){static
+std::map
+cL2
+iC;if(xO<0){nS3
+cost=22
+eO
+cost+cH-xO);}
+std::map
+cL2::xR3
+i=iC.xI2
+xO);if(i!=iC.cH1
+xO)return
+i
+cW2;std::pair
+cL2
+nT3(xO,0.0);nS3&cost=tX2
+second;while(xO>1){int
+xH2=0;if(xO<256){xH2=x51::powi_table[xO];if(xH2&128)xH2&=127;else
+xH2=0;if(xH2&64)xH2=-(xH2&63)-1;}
+if(xH2){cost+=cH
+xH2);xO/=xH2;y41}
+if(!(xO&1)){xO/=2;cost+=6;}
+else{cost+=7;xO-=1;}
+}
+iC.xN3,nT3)eO
+cost;}
+yD
+static
+tH
+xW1
+yB1,tT1)yS
+makeLongInteger(value*l62(xH2));}
+yD
+static
+bool
+yC1
+yB1,tT1){l62
+v=value*l62(xH2)eO
+isLongInteger(v);}
+yD
+static
+c53
+FindIntegerFactor(yB1){tT1=(2*2*2*2);
+#ifdef CBRT_IS_SLOW
+#else
+xH2*=(3*3*3);
+#endif
+c53
+nT3=0;if(yC1
+value,xH2)){nT3=xH2;while((xH2%2)==0&&yC1
+value,xH2/2))nT3=xH2/=2;while((xH2%3)==0&&yC1
+value,xH2/3))nT3=xH2/=3;}
+#ifdef CBRT_IS_SLOW
+if(nT3==0
+cI3
+yC1
+value,3
+tJ2
+3;}
+#endif
+return
+nT3;}
+static
+int
+EvaluateFactorCost(int
+xH2,int
+s,int
+c,int
+nmuls){nK3
+nL3=6;
+#ifdef CBRT_IS_SLOW
+nK3
+eQ2=25;
+#else
+nK3
+eQ2=8;
+#endif
+int
+nT3=s*nL3+c*eQ2;while(xH2%2==0){xH2/=2;nT3+=nL3;}
+while(xH2%3==0){xH2/=3;nT3+=eQ2;}
+nT3+=nmuls
+eO
+nT3;}
+}
+;}
+tC{yD
+bool
+xG::RecreateInversionsAndNegations(bool
+prefer_base2){bool
+changed
+e23
+n72
+0;a<x31++a)if(lP1.RecreateInversionsAndNegations(prefer_base2))nS2
+if(changed){exit_changed:Mark_Incompletely_Hashed()cT2
+switch(l42{case
+cMul:{nX2
+lK2;xG
+lL2,c81;if(true){bool
+nE1
+e23
+l62
+nR2=0;n72
+x31
+a
+nX
+y33
+0)y43
+tU
+yO2){nE1=true;nR2=tU
+1).xE1;yN3
+if(nE1){l62
+immeds=1.0;n72
+x31
+a
+nX
+yP2)){immeds*=powgroup.xE1;e71}
+n72
+x31
+a-->0;nQ&powgroup=lP1;if(powgroup
+y33
+0)y43
+tU
+yO2
+nQ&log2=tU
+0);log2.l41
+log2
+c4
+nM3
+log2.yJ
+fp_pow(immeds,l62(1)/nR2)));log2
+eM1
+yN3}
+}
+n72
+x31
+a
+nX
+y33
+yO2){iT1
+exp_param=tU
+1);l62
+cY2
+exp_param.xE1;if(cJ1,l62(-1))){l41
+lK2
+yS2
+lP1
+xN2
+e71
+i81
+nU3<tD1)&&t12
+x32
+nQ
+iL;iL
+c4
+cPow);iL
+cM
+tU
+0));iL.yJ-x32);iL
+eM1
+lK2
+yS2
+iL);l41
+e71}
+i81
+powgroup
+y43!lL2.n12){lL2=tU
+0);l41
+e71
+i81
+powgroup
+nF==cLog2by&&!c81.n12){c81=powgroup;l41
+e71}
+if(!lK2
+yU3){nS2
+xG
+i91;i91
+c4
+cMul);i91
+iY1
+lK2);i91
+eM1
+xG
+xX1
+cMul);xY1
+SetParamsMove(t4
+if(xY1
+IsImmed()&&fp_equal(xY1
+xE1
+n53
+lM2
+cInv);eE
+i91);}
+eN3
+xY1
+xT2>=i91.xT2){lM2
+cDiv)c91
+eE
+i91);}
+else{lM2
+cRDiv);eE
+i91)c91}
+}
+}
+if(lL2.n12
+nQ
+xX1
+l42;xY1
+SetParamsMove(t4
+while(xY1
+RecreateInversionsAndNegations(prefer_base2))xY1
+FixIncompleteHashes();lM2
+nM3
+eE
+lL2)c91
+nS2}
+if(c81.n12
+nQ
+xX1
+cMul);i82
+y7
+c81
+l8
+1));xY1
+AddParamsMove(t4
+while(xY1
+RecreateInversionsAndNegations(prefer_base2))xY1
+FixIncompleteHashes();DelParams();lM2
+nM3
+eE
+c81
+l8
+0))c91
+nS2
+i31
+cAdd:{nX2
+tY2;n72
+n93
+c63
+cMul){lN2
+xZ1:;xG&i82
+c73
+x62
+xY1
+x31
+b-->0;cI3
+i82
+l8
+b).lK1
+xH2=i82
+l8
+b).xE1;if(fp_equal(xH2
+xV
+xZ1;}
+xY1
+l41
+xY1
+DelParam(b
+yT2
+i81
+fp_equal(xH2,l62(-2)))eG
+xZ1;}
+xY1
+l41
+xY1
+DelParam(b);xY1
+yJ
+l62(2))yT2}
+}
+if(t9){xY1
+tI
+i82);e71}
+i81
+c63
+cDiv&&!IsIntType
+yB::nT3){lN2
+y01:;xG&i91
+c73
+if(i91
+l8
+0).lO2
+fp_equal(i91
+l8
+0).xE1
+xV
+y01;}
+i91.l41
+i91.DelParam(0);i91
+c4
+cInv
+yT2}
+if(t9)eG
+y01;}
+i91.tI
+i91);e71}
+i81
+c63
+cRDiv&&!IsIntType
+yB::nT3){lN2
+nZ1:;xG&i91
+c73
+if(i91
+l8
+1).lO2
+fp_equal(i91
+l8
+1).xE1
+xV
+nZ1;}
+i91.l41
+i91.DelParam(1);i91
+c4
+cInv
+yT2}
+if(t9)eG
+nZ1;}
+i91.tI
+i91);e71}
+if(!tY2
+yU3){
+#ifdef DEBUG_SUBSTITUTIONS
+tW2"Will make a Sub conversion in:\n"
+);fflush(stdout);iQ
+#endif
+xG
+t71;t71
+c4
+cAdd);t71
+iY1
+tY2);t71
+eM1
+xG
+cD1;cD1
+c4
+cAdd);cD1
+iY1
+iP1));cD1
+eM1
+if(cD1
+yP2)&&fp_equal(cD1.xE1,tD1))){lM2
+cNeg
+nN3);}
+eN3
+cD1.xT2==1){lM2
+cRSub
+nN3);eE
+cD1);}
+i81
+t71
+nF==cAdd){lM2
+cSub);eE
+cD1
+nN3
+xN2
+n72
+1;a<t71.x31++a
+nQ
+eR2;eR2
+c4
+cSub);eR2
+iY1
+iP1));eR2.lF2
+eE
+eR2
+nN3
+lS3}
+}
+else{lM2
+cSub);eE
+cD1
+nN3);}
+}
+#ifdef DEBUG_SUBSTITUTIONS
+tW2"After Sub conversion:\n"
+);fflush(stdout);iQ
+#endif
+i31
+cPow:{iT1
+p0
+nT2
+0);iT1
+p1
+nT2
+1);if(p1.lO2
+p1.xE1!=tD1)&&!t12
+p1.xE1)){eJ
+yN2
+r=eJ
+CreatePowiResult(fp_abs(p1.xE1));if(r.lU1!=0){bool
+iN1
+e23
+if(p1.xE1<tD1)&&r.tG1
+0]==0&&r.n_int_sqrt>0){iN1=true;}
+#ifdef DEBUG_POWI
+tW2"Will resolve powi %Lg as powi(chain(%d,%d),%ld)"
+,e21
+fp_abs(p1.xE1),r.n_int_sqrt,r.n_int_cbrt,r.lU1);for
+nD2
+n=0;n<eJ
+MaxSep;++n
+cI3
+r.tG1
+n]==0)break;int
+n_sqrt=r.tG1
+n]%eJ
+MaxOp;int
+n_cbrt=r.tG1
+n]/eJ
+MaxOp;tW2"*chain(%d,%d)"
+,n_sqrt,n_cbrt);}
+tW2"\n"
+);
+#endif
+xG
+cM2
+nT2
+0);xG
+yU2=cM2;yU2.l41
+ChangeIntoRootChain(yU2,iN1,r.n_int_sqrt,r.n_int_cbrt);yU2
+eM1
+xG
+pow;if(r.lU1!=1){pow
+c4
+cPow);pow
+y7
+yU2);pow.yJ
+l62(r.lU1)));}
+else
+pow.swap(yU2);xG
+mul;mul
+c4
+cMul);mul
+y7
+pow);for
+nD2
+n=0;n<eJ
+MaxSep;++n
+cI3
+r.tG1
+n]==0)break;int
+n_sqrt=r.tG1
+n]%eJ
+MaxOp;int
+n_cbrt=r.tG1
+n]/eJ
+MaxOp;xG
+eS2=cM2;eS2.l41
+ChangeIntoRootChain(eS2,false,n_sqrt,n_cbrt);eS2
+eM1
+mul
+y7
+eS2);}
+if(p1.xE1<tD1)&&!iN1){mul
+eM1
+lM2
+cInv);n41
+0,mul);DelParam(1);}
+else{lM2
+cMul);SetParamsMove(mul.iP1));}
+#ifdef DEBUG_POWI
+iQ
+#endif
+nS2
+yN3}
+if(GetOpcode()==cPow&&(!p1
+yP2)||!isLongInteger(p1.xE1)||!IsOptimizableUsingPowi
+yB(makeLongInteger(p1.xE1)))cI3
+p0
+yP2)&&p0.xE1>l62(0.0)cI3
+prefer_base2){l62
+yV2=fp_log2(p0.xE1);if(fp_equal(yV2
+n53
+DelParam(0);}
+else{lX
+cL1
+yV2))t11
+cM
+p1)t11.Rehash(x41}
+lM2
+cExp2);nS2}
+else{l62
+yV2=fp_log(p0.xE1);if(fp_equal(yV2
+n53
+DelParam(0);}
+else{lX
+cL1
+yV2))t11
+cM
+p1)t11.Rehash(x41}
+lM2
+cExp);nS2}
+}
+i81
+GetPositivityInfo(p0)==IsAlways
+cI3
+prefer_base2
+nQ
+log;log
+c4
+cLog2);log
+cM
+p0);log
+eM1
+lX
+p1)t11
+y7
+log)t11
+eM1
+lM2
+cExp2
+x41
+nS2}
+else{xG
+log;log
+c4
+cLog);log
+cM
+p0);log
+eM1
+lX
+p1)t11
+y7
+log)t11
+eM1
+lM2
+cExp
+x41
+nS2}
+}
+i31
+cDiv:{if(GetParam(0)yP2)&&fp_equal(GetParam(0).xE1
+n53
+lM2
+cInv);DelParam(0);}
+yY3
+y13
+yY3
+if(changed)goto
+exit_changed
+eO
+changed;}
+}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+using
+iR2
+FUNCTIONPARSERTYPES;iR2{using
+tC;class
+cJ3{size_t
+nF1;size_t
+eK;size_t
+eL;size_t
+lE1;size_t
+tA;size_t
+tB;size_t
+n01;cV3
+cJ3():nF1(0),eK(0),eL(0),lE1(0),tA(0),tB(0),n01(0){}
+void
+AddFrom(OPCODE
+op){nF1+=1;if(op==cCos)++eK;if(op==cSin)++eL;if(op==cSec)++eK;if(op==cCsc)++eL;if(op==cTan)++lE1;if(op==cCot)++lE1;if(op==cSinh)++tB;if(op==cCosh)++tA;if(op==cTanh)++n01;}
+size_t
+GetCSEscore()const{size_t
+nT3=nF1
+eO
+nT3;}
+int
+NeedsSinCos()const{bool
+y11=(nF1==(eK+eL+lE1));if((lE1&&(eL||eK))||(eL&&eK)cI3
+y11)return
+1
+eO
+2
+yC3
+0;}
+int
+NeedsSinhCosh()const{bool
+y11=(nF1==(tA+tB+n01));if((n01&&(tB||tA))||(tB&&tA)cI3
+y11)return
+1
+eO
+2
+yC3
+0;}
+size_t
+MinimumDepth()const{size_t
+n_sincos=std::min(eK,eL);size_t
+n_sinhcosh=std::min(tA,tB);if(n_sincos==0&&n_sinhcosh==0)return
+2
+eO
+1;}
+}
+;x13
+TreeCountType:public
+std::multimap<fphash_t,std::pair<cJ3,xG> >{}
+;x73
+FindTreeCounts(t31&lQ2,xB3,OPCODE
+nU2,bool
+skip_root=false){e2
+i=lQ2.xI2
+xC3);if(!skip_root){bool
+found
+e23
+for(;i!=lQ2.cH1
+xC3;++i
+cI3
+tree
+xI
+i
+cW2.second)){i
+cW2
+y93
+AddFrom(nU2);found=true;yN3
+if(!found){cJ3
+count;count.AddFrom(nU2);lQ2.xN3,std::make_pair(xC3,std::make_pair(count,tree)));}
+}
+n72
+0
+tH2
+FindTreeCounts(lQ2,tJ3
+tree
+nF);}
+cP2
+yX{bool
+BalanceGood;bool
+FoundChild;}
+;yD
+yX
+lF1
+iT1
+root,iT1
+child
+cI3
+root
+xI
+child)){yX
+nT3={true,true}
+eO
+nT3;}
+yX
+nT3={true,false}
+;if(root
+nF==cIf||root
+nF==e63{yX
+cond=lF1
+root
+l8
+0
+x03
+yX
+y2=lF1
+root
+l8
+1
+x03
+yX
+y6=lF1
+root
+l8
+2
+x03
+if
+lF3||y2
+yY||y6
+yY){nT3
+yY=true;}
+nT3
+eH=((y2
+yY==y6
+yY)||lF3
+cN2&&(cond
+eH||(y2
+yY&&y6
+yY))&&(y2
+eH||lF3
+cN2&&(y6
+eH||lF3
+cN2;}
+else{bool
+tU1
+e23
+bool
+nG1
+e23
+x62
+root.GetParamCount(),a=0;a<b;++a){yX
+tmp=lF1
+root
+l8
+a
+x03
+if(tmp
+yY)nT3
+yY=true;if(tmp
+eH==false)tU1=true;i81
+tmp
+yY)nG1=true;}
+if(tU1&&!nG1)nT3
+eH=false
+yC3
+nT3;}
+yD
+bool
+n83
+iX2
+eU3
+xB3,const
+x51
+yZ3&synth,const
+t31&lQ2){x62
+t7,a=0;a<b;++a){iT1
+leaf=xP1
+a);e2
+synth_it;xL2
+t31::const_iterator
+i=lQ2.xQ3
+i!=lQ2.end();++i
+cI3
+i->first!=leaf.GetHash())y41
+const
+cJ3&occ
+n22
+first;size_t
+score=occ.GetCSEscore();iT1
+candidate
+n22
+second;lS2
+candidate))y41
+if(leaf.xT2<occ.MinimumDepth())y41
+if(score<2)y41
+if(lF1
+eU3
+leaf)eH==false)continue
+cT2
+if(n83(eU3
+leaf,synth,lQ2
+t41
+yC3
+e83
+yD
+bool
+lR2
+iX2
+xO3,iT1
+expr){yE
+xO3
+l8
+a)xI
+expr
+t41;yE
+lR2(xO3
+l8
+a),expr
+t41
+eO
+e83
+yD
+bool
+GoodMomentForCSE
+iX2
+xO3,iT1
+expr
+cI3
+xO3
+nF==cIf)return
+true;yE
+xO3
+l8
+a)xI
+expr
+t41;size_t
+tZ2=0;yE
+lR2(xO3
+l8
+a),expr))++tZ2
+eO
+tZ2!=1;}
+}
+tC{yD
+size_t
+xG::SynthCommonSubExpressions(x51::yM1
+const{if(GetParamCount()==0)return
+0;size_t
+stacktop_before
+eJ3
+GetStackTop();t31
+lQ2;FindTreeCounts(lQ2,*this,GetOpcode(),true);for(;;){size_t
+yW2=0;
+#ifdef DEBUG_SUBSTITUTIONS_CSE
+std::cout<<"Finding a CSE candidate, root is:"
+<<std::endl;DumpHashes(*this);
+#endif
+e2
+cs_it(lQ2.end());for(e2
+j=lQ2.xQ3
+j!=lQ2.end();){e2
+i(j++);const
+cJ3&occ
+n22
+first;size_t
+score=occ.GetCSEscore();xB3
+n22
+second;
+#ifdef DEBUG_SUBSTITUTIONS_CSE
+std::cout<<"Score "
+<<score<<":\n"
+<<std::flush;DumpTreeWithIndent(tree);
+#endif
+lS2
+tree))xS
+if(tree.xT2<occ.MinimumDepth())xS
+if(score<2)xS
+if(lF1*this,tree)eH==false)xS
+if(n83(*this,tree,synth,lQ2)){y41}
+if(!GoodMomentForCSE(*this,tree))xS
+score*=tree.xT2;if(score>yW2){yW2=score;cs_it=i;}
+}
+if(yW2<=0){
+#ifdef DEBUG_SUBSTITUTIONS_CSE
+std::cout<<"No more CSE candidates.\n"
+<<std::flush;
+#endif
+yY3
+xB3=cs_it
+cW2.second;
+#ifdef DEBUG_SUBSTITUTIONS_CSE
+std::cout<<tF3"Common Subexpression:"
+;DumpTree
+yB(tree)xO1
+std::endl;
+#endif
+#if 0
+int
+lV1=occ.NeedsSinCos();int
+i4=occ.NeedsSinhCosh();xG
+i02,i12,yX2,yY2;if(lV1){i02
+eT2
+i02
+c4
+cSin);i02
+eM1
+i12
+eT2
+i12
+c4
+cCos);i12
+eM1
+lS2
+i02)||synth.Find(i12)cI3
+lV1==2){t61
+y41}
+lV1=0;}
+}
+if(i4){yX2
+eT2
+yX2
+c4
+cSinh);yX2
+eM1
+yY2
+eT2
+yY2
+c4
+cCosh);yY2
+eM1
+lS2
+yX2)||synth.Find(yY2)cI3
+i4==2){t61
+y41}
+i4=0;}
+}
+#endif
+tree.SynthesizeByteCode(synth,false);t61
+#ifdef DEBUG_SUBSTITUTIONS_CSE
+synth.template
+Dump<0>()xO1"Done with Common Subexpression:"
+;DumpTree
+yB(tree)xO1
+std::endl;
+#endif
+#if 0
+if(lV1
+cI3
+lV1==2||i4){synth.eC1}
+n42
+cSinCos,1,2)cZ1
+i02,1)cZ1
+i12,0);}
+if(i4
+cI3
+lV1)synth.eC1
+if(i4==2){synth.eC1}
+n42
+cSinhCosh,1,2)cZ1
+yX2,1)cZ1
+yY2,0);}
+#endif
+}
+return
+synth.xH
+stacktop_before;}
+}
+#endif
+#ifdef FP_SUPPORT_OPTIMIZER
+yD
+lI1
+yB::i22{using
+tC;l41
+xG
+tree;tree.GenerateFrom(*mData);FPoptimizer_Optimize::ApplyGrammars(tree)e72
+unsigned>c83;std::vector
+yB
+immed;size_t
+stacktop_max=0;tree.SynthesizeByteCode(c83,immed,stacktop_max);if(mData->mStackSize!=stacktop_max){mData->mStackSize=unsigned(stacktop_max);
+#if !defined(FP_USE_THREAD_SAFE_EVAL) && \
+ !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
+mData->mStack
+x53
+stacktop_max);
+#endif
+}
+mData->mByteCode.swap(c83);mData->mImmed.swap(immed);}
+#define FUNCTIONPARSER_INSTANTIATE_EMPTY_OPTIMIZE(type) t91>lI1<type>::i22{}
+#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
+eX3(MpfrFloat)
+#endif
+#ifdef FP_SUPPORT_GMP_INT_TYPE
+eX3(GmpInt)
+#endif
+#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
+eX3(std::complex<double>)
+#endif
+#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
+eX3(std::complex<float>)
+#endif
+#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
+eX3(std::complex<long
+double>)
+#endif
+#define FUNCTIONPARSER_INSTANTIATE_OPTIMIZE(type) template lI1<type>::i22;
+#ifndef FP_DISABLE_DOUBLE_TYPE
+eY3(double)
+#endif
+#ifdef FP_SUPPORT_FLOAT_TYPE
+eY3(float)
+#endif
+#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
+eY3(long
+double)
+#endif
+#ifdef FP_SUPPORT_LONG_INT_TYPE
+eY3(long)
+#endif
+#endif // FP_SUPPORT_OPTIMIZER
+
+#endif
diff --git a/Project/fparser/mpfr/GmpInt.cc b/Project/fparser/mpfr/GmpInt.cc
new file mode 100644
index 0000000..490add4
--- /dev/null
+++ b/Project/fparser/mpfr/GmpInt.cc
@@ -0,0 +1,710 @@
+#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;
+}
diff --git a/Project/fparser/mpfr/GmpInt.hh b/Project/fparser/mpfr/GmpInt.hh
new file mode 100644
index 0000000..1c1c171
--- /dev/null
+++ b/Project/fparser/mpfr/GmpInt.hh
@@ -0,0 +1,148 @@
+#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
diff --git a/Project/fparser/mpfr/MpfrFloat.cc b/Project/fparser/mpfr/MpfrFloat.cc
new file mode 100644
index 0000000..112c684
--- /dev/null
+++ b/Project/fparser/mpfr/MpfrFloat.cc
@@ -0,0 +1,976 @@
+#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();
+}
diff --git a/Project/fparser/mpfr/MpfrFloat.hh b/Project/fparser/mpfr/MpfrFloat.hh
new file mode 100644
index 0000000..d455d24
--- /dev/null
+++ b/Project/fparser/mpfr/MpfrFloat.hh
@@ -0,0 +1,206 @@
+#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