amath/src/main/values.cpp

492 lines
9.8 KiB
C++
Raw Normal View History

2017-02-27 22:31:21 +00:00
/*-
2017-02-27 22:23:06 +00:00
* Copyright (c) 2014-2017 Carsten Sonne Larsen <cs@innolan.net>
2015-04-01 12:43:50 +00:00
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
2017-02-27 22:31:21 +00:00
* Project homepage:
* http://amath.innolan.net
*
2015-04-01 12:43:50 +00:00
*/
#include "math.h"
2017-02-27 22:23:06 +00:00
#include "amath.h"
#include "amathc.h"
#include "nodes.h"
#include "values.h"
2015-04-01 12:43:50 +00:00
#include "lib/numb.h"
#include "lib/real.h"
#include "lib/cplex.h"
#include "lib/charbuf.h"
#include "localize/text.h"
#include "system/program.h"
// -----------------------------------------------------
// --------------------- Variable ----------------------
// -----------------------------------------------------
2017-02-27 22:23:06 +00:00
Variable::Variable(const char* name)
2015-04-01 12:43:50 +00:00
{
AllocAndCopy(&this->name, name);
2017-02-27 22:23:06 +00:00
value = nullptr;
Next = nullptr;
2015-04-01 12:43:50 +00:00
chainDelete = true;
}
Variable::~Variable()
{
delete [] name;
2017-02-27 22:23:06 +00:00
if (value != nullptr)
{
2015-04-01 12:43:50 +00:00
delete value;
}
2017-02-27 22:23:06 +00:00
if (chainDelete && Next != nullptr)
{
2015-04-01 12:43:50 +00:00
delete Next;
}
}
2017-02-27 22:23:06 +00:00
char* Variable::GetName() const
2015-04-01 12:43:50 +00:00
{
return name;
}
2017-02-27 22:23:06 +00:00
Number* Variable::GetValue() const
2015-04-01 12:43:50 +00:00
{
return value->Clone();;
}
2017-02-27 22:23:06 +00:00
void Variable::AssignValue(Number* value)
2015-04-01 12:43:50 +00:00
{
2017-02-27 22:23:06 +00:00
if (this->value != nullptr)
{
2015-04-01 12:43:50 +00:00
delete this->value;
}
this->value = value->Clone();
}
// -----------------------------------------------------
// ------------------- VariableList --------------------
// -----------------------------------------------------
VariableList::VariableList()
{
2017-02-27 22:23:06 +00:00
first = nullptr;
2015-04-01 12:43:50 +00:00
buf = new CharBuffer();
}
VariableList::~VariableList()
{
2017-02-27 22:23:06 +00:00
if (first != nullptr)
{
2015-04-01 12:43:50 +00:00
delete first;
}
delete buf;
}
void VariableList::Clear()
{
2017-02-27 22:23:06 +00:00
if (first != nullptr)
{
2015-04-01 12:43:50 +00:00
delete first;
2017-02-27 22:23:06 +00:00
first = nullptr;
2015-04-01 12:43:50 +00:00
}
buf->ClearBuffer();
}
2017-02-27 22:23:06 +00:00
bool VariableList::Delete(const char* name)
2015-04-01 12:43:50 +00:00
{
Variable* var = GetVariable(name);
2017-02-27 22:23:06 +00:00
if (var == nullptr)
{
2015-04-01 12:43:50 +00:00
return false;
}
2017-02-27 22:23:06 +00:00
if (var == first)
{
2015-04-01 12:43:50 +00:00
first = var->Next;
var->chainDelete = false;
delete var;
return true;
}
2017-02-27 22:23:06 +00:00
Variable* current = first->Next;
Variable* last = first;
2015-04-01 12:43:50 +00:00
2017-02-27 22:23:06 +00:00
while (current != var)
{
2015-04-01 12:43:50 +00:00
current = current->Next;
last = last->Next;
}
last->Next = var->Next;
// Only delete this variable. Not the whole chain.
var->chainDelete = false;
delete var;
return true;
}
2017-02-27 22:23:06 +00:00
Variable* VariableList::GetFirstVariable() const
2015-04-01 12:43:50 +00:00
{
return first;
}
2017-02-27 22:23:06 +00:00
Variable* VariableList::GetVariable(const char* name) const
2015-04-01 12:43:50 +00:00
{
Variable* current = first;
2017-02-27 22:23:06 +00:00
while (current != nullptr && !StrIsEqual(current->GetName(), name))
{
2015-04-01 12:43:50 +00:00
current = current->Next;
}
return current;
}
2017-02-27 22:23:06 +00:00
Variable* VariableList::CreateVariable(const char* name)
2015-04-01 12:43:50 +00:00
{
2017-02-27 22:23:06 +00:00
if (first == nullptr)
{
2015-04-01 12:43:50 +00:00
first = new Variable(name);
return first;
}
Variable* current = first;
2017-02-27 22:23:06 +00:00
Variable* last = nullptr;
2015-04-01 12:43:50 +00:00
2017-02-27 22:23:06 +00:00
while (current != nullptr)
{
if (StrIsEqual(name, current->GetName()))
{
2015-04-01 12:43:50 +00:00
return current;
}
last = current;
current = current->Next;
}
current = new Variable(name);
last->Next = current;
return current;
}
2017-02-27 22:23:06 +00:00
Variable* VariableList::InsertTemporaryVariable(Variable* variable)
2015-04-01 12:43:50 +00:00
{
// Temporary variables are always inserted at the beginning of the list.
Variable* oldFirst = first;
first = variable;
variable->Next = oldFirst;
return variable;
}
void VariableList::RemoveTemporaryVariable()
{
// Temporary variables are not owned by the variable list. Do not free memory.
2017-02-27 22:23:06 +00:00
Variable* newFirst = first->Next;
first->Next = nullptr;
2015-04-01 12:43:50 +00:00
first = newFirst;
}
2017-02-27 22:23:06 +00:00
char* VariableList::List() const
2015-04-01 12:43:50 +00:00
{
return ListContent(false);
}
2017-02-27 22:23:06 +00:00
char* VariableList::ListDefinitions() const
2015-04-01 12:43:50 +00:00
{
return ListContent(true);
}
2017-02-27 22:23:06 +00:00
char* VariableList::ListContent(bool cmdFormat) const
2015-04-01 12:43:50 +00:00
{
buf->Empty();
2017-02-27 22:23:06 +00:00
if (GetFirstVariable() == nullptr)
{
return static_cast<char*>(cmdFormat ? nullptr : HELPVARSNDEF);
2015-04-01 12:43:50 +00:00
}
int len = 0;
Variable* current = GetFirstVariable();
2017-02-27 22:23:06 +00:00
while (current != nullptr)
{
2015-04-01 12:43:50 +00:00
len += StrLen(current->GetName());
len += 3;
len += 32; // Max length of value
len += cmdFormat ? 2 : 1;
current = current->Next;
}
current = GetFirstVariable();
buf->EnsureSize(len);
2017-02-27 22:23:06 +00:00
while (current != nullptr)
{
2015-04-01 12:43:50 +00:00
buf->Append(current->GetName());
buf->Append(" = ");
2017-02-27 22:23:06 +00:00
Number* num = current->GetValue();
const char* val = Program->Output->GetText(num);
2015-04-01 12:43:50 +00:00
buf->Append(val);
delete num;
2017-02-27 22:23:06 +00:00
if (cmdFormat)
{
2015-04-01 12:43:50 +00:00
buf->Append(';');
}
buf->Append(NEWLINE);
current = current->Next;
}
return buf->GetString();
}
// -----------------------------------------------------
// -------------- ListVariablesStatement ---------------
// -----------------------------------------------------
ListVariablesStatement::ListVariablesStatement()
2017-02-27 22:23:06 +00:00
: StatementNode()
{
}
2015-04-01 12:43:50 +00:00
char* ListVariablesStatement::Execute()
{
return Program->Variables->List();
}
// -----------------------------------------------------
// ------------------- VariableNode --------------------
// -----------------------------------------------------
VariableNode::VariableNode(Variable* variable):
2017-02-27 22:23:06 +00:00
ExpressionNode(), variable(variable)
{
}
2015-04-01 12:43:50 +00:00
int VariableNode::GetPrecedence()
{
return 0;
}
Number* VariableNode::Evaluate()
{
result = variable->GetValue();
return result;
}
2017-02-27 22:23:06 +00:00
void VariableNode::AssignValue(Number* value) const
2015-04-01 12:43:50 +00:00
{
variable->AssignValue(value);
}
char* VariableNode::GetText()
{
return variable->GetName();
}
char* VariableNode::GetNodeText()
{
return variable->GetName();
}
SyntaxNode* VariableNode::GetNext()
{
2017-02-27 22:23:06 +00:00
return nullptr;
2015-04-01 12:43:50 +00:00
}
void VariableNode::Attach(SyntaxNode* node)
2017-02-27 22:23:06 +00:00
{
}
2015-04-01 12:43:50 +00:00
void VariableNode::Detach(SyntaxNode* node)
2017-02-27 22:23:06 +00:00
{
}
2015-04-01 12:43:50 +00:00
void VariableNode::Replace(SyntaxNode* n, SyntaxNode* x)
2017-02-27 22:23:06 +00:00
{
}
2015-04-01 12:43:50 +00:00
// -----------------------------------------------------
// ----------------- InsVariableNode -------------------
// -----------------------------------------------------
InsVariableNode::InsVariableNode() :
2017-02-27 22:23:06 +00:00
VariableNode(nullptr)
{
}
2015-04-01 12:43:50 +00:00
Number* InsVariableNode::Evaluate()
{
return Program->GetLastResult();
}
char* InsVariableNode::GetText()
{
2017-02-27 22:23:06 +00:00
static char* ret = (char*)"ins";
return ret;
2015-04-01 12:43:50 +00:00
}
char* InsVariableNode::GetNodeText()
{
2017-02-27 22:23:06 +00:00
static char* ret = (char*)"ins";
return ret;
2015-04-01 12:43:50 +00:00
}
// -----------------------------------------------------
// ----------------- NumericValueNode ------------------
// -----------------------------------------------------
NumericValueNode::NumericValueNode() :
2017-02-27 22:23:06 +00:00
ExpressionNode(new RealNumber())
{
}
2015-04-01 12:43:50 +00:00
2017-02-27 22:23:06 +00:00
NumericValueNode::NumericValueNode(Number* value) :
ExpressionNode(value)
{
}
2015-04-01 12:43:50 +00:00
ReductionType NumericValueNode::GetReductionType()
{
return valuereduc;
}
int NumericValueNode::GetPrecedence()
{
return !leftBottom ?
2017-02-27 22:23:06 +00:00
result->GetPrecedence() :
result->GetDefaultPrecedence();
2015-04-01 12:43:50 +00:00
}
Number* NumericValueNode::Evaluate()
{
return result;
}
char* NumericValueNode::GetText()
{
return GetNodeText();
}
char* NumericValueNode::GetNodeText()
{
2017-02-27 22:23:06 +00:00
const char* val = Program->Input->GetText(result);
2015-04-01 12:43:50 +00:00
output->ClearAndCopy(val);
return output->GetString();
}
SyntaxNode* NumericValueNode::GetNext()
{
2017-02-27 22:23:06 +00:00
return nullptr;
2015-04-01 12:43:50 +00:00
}
void NumericValueNode::Attach(SyntaxNode* node)
2017-02-27 22:23:06 +00:00
{
}
2015-04-01 12:43:50 +00:00
void NumericValueNode::Detach(SyntaxNode* node)
2017-02-27 22:23:06 +00:00
{
}
2015-04-01 12:43:50 +00:00
void NumericValueNode::Replace(SyntaxNode* n, SyntaxNode* x)
2017-02-27 22:23:06 +00:00
{
}
2015-04-01 12:43:50 +00:00
void NumericValueNode::ReplaceWith(Number* value)
{
delete result;
result = value;
}
// -----------------------------------------------------
// ----------------- EulersNumberNode ------------------
// -----------------------------------------------------
EulersNumberNode::EulersNumberNode() :
2017-02-27 22:23:06 +00:00
NumericValueNode(new RealNumber(EULERS))
{
}
2015-04-01 12:43:50 +00:00
ReductionType EulersNumberNode::GetReductionType()
{
return nonereduc;
}
char* EulersNumberNode::GetNodeText()
{
2017-02-27 22:23:06 +00:00
static char* ret = (char*)"e";
return ret;
2015-04-01 12:43:50 +00:00
}
// -----------------------------------------------------
// ---------------------- PiNode -----------------------
// -----------------------------------------------------
PiNode::PiNode() :
2017-02-27 22:23:06 +00:00
NumericValueNode(new RealNumber(PI))
{
}
2015-04-01 12:43:50 +00:00
ReductionType PiNode::GetReductionType()
{
return nonereduc;
}
char* PiNode::GetNodeText()
{
2017-02-27 22:23:06 +00:00
static char* ret = (char*)"pi";
return ret;
2015-04-01 12:43:50 +00:00
}
// -----------------------------------------------------
// ------------------- ComplexiNode --------------------
// -----------------------------------------------------
ComplexiNode::ComplexiNode() :
2017-02-27 22:23:06 +00:00
NumericValueNode(new ComplexNumber(0.0, 1.0))
{
}
2015-04-01 12:43:50 +00:00
ReductionType ComplexiNode::GetReductionType()
{
return nonereduc;
}
char* ComplexiNode::GetNodeText()
{
2017-02-27 22:23:06 +00:00
static char* ret = (char*)"i";
return ret;
2015-04-01 12:43:50 +00:00
}