C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2014-12-29 05:43:32 +11:00
parent e0bbb336dd
commit c8657e95a2
3 changed files with 475 additions and 198 deletions

View File

@ -2436,7 +2436,7 @@ namespace exprtk
inline std::size_t process(generator& g)
{
if (!g.token_list_.empty())
if (g.token_list_.size() >= stride_)
{
for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
{
@ -2561,6 +2561,8 @@ namespace exprtk
{
if (g.token_list_.empty())
return 0;
else if (g.token_list_.size() < stride_)
return 0;
std::size_t changes = 0;
@ -4383,6 +4385,8 @@ namespace exprtk
virtual std::string str () const = 0;
virtual const char* base() const = 0;
virtual std::size_t size() const = 0;
};
template <typename T>
@ -4428,6 +4432,11 @@ namespace exprtk
return value_.data();
}
std::size_t size() const
{
return value_.size();
}
range_t& range_ref()
{
return rp_;
@ -6247,26 +6256,31 @@ namespace exprtk
return std::numeric_limits<T>::quiet_NaN();
}
inline std::string str() const
std::string str() const
{
return ref();
}
inline virtual std::string& ref()
const char* base() const
{
return (*value_).data();
}
std::size_t size() const
{
return ref().size();
}
std::string& ref()
{
return (*value_);
}
inline virtual const std::string& ref() const
const std::string& ref() const
{
return (*value_);
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_stringvar;
}
range_t& range_ref()
{
return rp_;
@ -6277,9 +6291,9 @@ namespace exprtk
return rp_;
}
const char* base() const
inline typename expression_node<T>::node_type type() const
{
return (*value_).data();
return expression_node<T>::e_stringvar;
}
private:
@ -6327,6 +6341,16 @@ namespace exprtk
return (*value_);
}
const char* base() const
{
return (*value_).data();
}
std::size_t size() const
{
return ref().size();
}
inline range_t range() const
{
return rp_;
@ -6357,11 +6381,6 @@ namespace exprtk
return expression_node<T>::e_stringvarrng;
}
const char* base() const
{
return (*value_).data();
}
private:
std::string* value_;
@ -6395,22 +6414,32 @@ namespace exprtk
return std::numeric_limits<T>::quiet_NaN();
}
inline std::string str() const
std::string str() const
{
return value_;
}
inline range_t range() const
const char* base() const
{
return value_.data();
}
std::size_t size() const
{
return value_.size();
}
range_t range() const
{
return rp_;
}
inline virtual range_t& range_ref()
range_t& range_ref()
{
return rp_;
}
inline virtual const range_t& range_ref() const
const range_t& range_ref() const
{
return rp_;
}
@ -6420,11 +6449,6 @@ namespace exprtk
return expression_node<T>::e_cstringvarrng;
}
const char* base() const
{
return value_.data();
}
private:
const_string_range_node<T>& operator=(const const_string_range_node<T>&);
@ -6500,7 +6524,7 @@ namespace exprtk
range_t& range = str_range_ptr_->range_ref();
const std::size_t base_str_size = str_base_ptr_->str().size();
const std::size_t base_str_size = str_base_ptr_->size();
if (
range (str_r0,str_r1,base_str_size) &&
@ -6529,6 +6553,11 @@ namespace exprtk
return value_.data();
}
std::size_t size() const
{
return value_.size();
}
range_t& range_ref()
{
return range_;
@ -6634,8 +6663,8 @@ namespace exprtk
range_t& range1 = str1_range_ptr_->range_ref();
if (
range0(str0_r0,str0_r1,str0_base_ptr_->str().size()) &&
range1(str1_r0,str1_r1,str1_base_ptr_->str().size())
range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
range1(str1_r0,str1_r1,str1_base_ptr_->size())
)
{
const std::size_t size0 = (str0_r1 - str0_r0) + 1;
@ -6662,6 +6691,11 @@ namespace exprtk
return value_.data();
}
std::size_t size() const
{
return value_.size();
}
range_t& range_ref()
{
return range_;
@ -6745,6 +6779,11 @@ namespace exprtk
return str0_node_ptr_->base();
}
std::size_t size() const
{
return str0_node_ptr_->size();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
@ -6837,7 +6876,7 @@ namespace exprtk
if (str_base_ptr_)
{
branch_->value();
result = T(str_base_ptr_->str().size());
result = T(str_base_ptr_->size());
}
return result;
@ -6854,6 +6893,266 @@ namespace exprtk
bool branch_deletable_;
str_base_ptr str_base_ptr_;
};
struct asn_assignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.assign(data,size); }
};
struct asn_addassignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.append(data,size); }
};
template <typename T, typename AssignmentProcess = asn_assignment>
class assignment_string_node : public binary_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
typedef expression_node <T>* expression_ptr;
typedef stringvar_node <T>* strvar_node_ptr;
typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t;
typedef range_t* range_ptr;
typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr;
typedef typename range_t::cached_range_t cached_range_t;
assignment_string_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
str0_base_ptr_ (0),
str1_base_ptr_ (0),
str0_node_ptr_ (0),
str1_range_ptr_(0)
{
if (is_string_node(binary_node<T>::branch_[0].first))
{
str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
}
if (is_generally_string_node(binary_node<T>::branch_[1].first))
{
str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
if (0 == str1_base_ptr_)
return;
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
if (0 == range_ptr)
return;
str1_range_ptr_ = &(range_ptr->range_ref());
}
}
inline T value() const
{
if (
str0_base_ptr_ &&
str1_base_ptr_ &&
str0_node_ptr_ &&
str1_range_ptr_
)
{
binary_node<T>::branch_[1].first->value();
std::size_t r0 = 0;
std::size_t r1 = 0;
range_t& range = (*str1_range_ptr_);
if (range(r0,r1,str1_base_ptr_->size()))
{
AssignmentProcess::execute(str0_node_ptr_->ref(),
str1_base_ptr_->base() + r0,
(r1 - r0) + 1);
binary_node<T>::branch_[0].first->value();
}
}
return std::numeric_limits<T>::quiet_NaN();
}
std::string str() const
{
return str0_node_ptr_->str();
}
const char* base() const
{
return str0_node_ptr_->base();
}
std::size_t size() const
{
return str0_node_ptr_->size();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
}
const range_t& range_ref() const
{
return str0_node_ptr_->range_ref();
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_strass;
}
private:
str_base_ptr str0_base_ptr_;
str_base_ptr str1_base_ptr_;
strvar_node_ptr str0_node_ptr_;
range_ptr str1_range_ptr_;
};
template <typename T, typename AssignmentProcess = asn_assignment>
class assignment_string_range_node : public binary_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
typedef expression_node <T>* expression_ptr;
typedef stringvar_node <T>* strvar_node_ptr;
typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t;
typedef range_t* range_ptr;
typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr;
typedef typename range_t::cached_range_t cached_range_t;
assignment_string_range_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
str0_base_ptr_ (0),
str1_base_ptr_ (0),
str0_node_ptr_ (0),
str0_range_ptr_(0),
str1_range_ptr_(0)
{
if (is_string_range_node(binary_node<T>::branch_[0].first))
{
str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
if (0 == range_ptr)
return;
str0_range_ptr_ = &(range_ptr->range_ref());
}
if (is_generally_string_node(binary_node<T>::branch_[1].first))
{
str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
if (0 == str1_base_ptr_)
return;
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
if (0 == range_ptr)
return;
str1_range_ptr_ = &(range_ptr->range_ref());
}
}
inline T value() const
{
if (
str0_base_ptr_ &&
str1_base_ptr_ &&
str0_node_ptr_ &&
str0_range_ptr_ &&
str1_range_ptr_
)
{
binary_node<T>::branch_[0].first->value();
binary_node<T>::branch_[1].first->value();
std::size_t s0_r0 = 0;
std::size_t s0_r1 = 0;
std::size_t s1_r0 = 0;
std::size_t s1_r1 = 0;
range_t& range0 = (*str0_range_ptr_);
range_t& range1 = (*str1_range_ptr_);
if (
range0(s0_r0,s0_r1,str0_base_ptr_->size()) &&
range1(s1_r0,s1_r1,str1_base_ptr_->size())
)
{
std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1;
std::copy(str1_base_ptr_->base() + s1_r0,
str1_base_ptr_->base() + s1_r0 + size,
const_cast<char*>(base() + s0_r0));
}
}
return std::numeric_limits<T>::quiet_NaN();
}
std::string str() const
{
return str0_node_ptr_->str();
}
const char* base() const
{
return str0_node_ptr_->base();
}
std::size_t size() const
{
return str0_node_ptr_->size();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
}
const range_t& range_ref() const
{
return str0_node_ptr_->range_ref();
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_strass;
}
private:
str_base_ptr str0_base_ptr_;
str_base_ptr str1_base_ptr_;
strvar_node_ptr str0_node_ptr_;
range_ptr str0_range_ptr_;
range_ptr str1_range_ptr_;
};
#endif
template <typename T, std::size_t N>
@ -7388,128 +7687,6 @@ namespace exprtk
variable_node<T>* var_node_ptr_;
};
struct asn_assignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.assign(data,size); }
};
struct asn_addassignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.append(data,size); }
};
template <typename T, typename AssignmentProcess = asn_assignment>
class assignment_string_node : public binary_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
typedef expression_node <T>* expression_ptr;
typedef stringvar_node <T>* strvar_node_ptr;
typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t;
typedef range_t* range_ptr;
typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr;
typedef typename range_t::cached_range_t cached_range_t;
assignment_string_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
str0_base_ptr_ (0),
str1_base_ptr_ (0),
str0_node_ptr_ (0),
str1_range_ptr_(0)
{
if (is_string_node(binary_node<T>::branch_[0].first))
{
str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
}
if (is_generally_string_node(binary_node<T>::branch_[1].first))
{
str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
if (0 == str1_base_ptr_)
return;
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
if (0 == range_ptr)
return;
str1_range_ptr_ = &(range_ptr->range_ref());
}
}
inline T value() const
{
if (
str0_base_ptr_ &&
str1_base_ptr_ &&
str0_node_ptr_ &&
str1_range_ptr_
)
{
binary_node<T>::branch_[1].first->value();
std::size_t r0 = 0;
std::size_t r1 = 0;
range_t& range = (*str1_range_ptr_);
if (range(r0,r1,str1_base_ptr_->str().size()))
{
AssignmentProcess::execute(str0_node_ptr_->ref(),
str1_base_ptr_->str().data() + r0,
(r1 - r0) + 1);
binary_node<T>::branch_[0].first->value();
}
}
return std::numeric_limits<T>::quiet_NaN();
}
std::string str() const
{
return str0_node_ptr_->str();
}
const char* base() const
{
return str0_node_ptr_->base();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
}
const range_t& range_ref() const
{
return str0_node_ptr_->range_ref();
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_strass;
}
private:
str_base_ptr str0_base_ptr_;
str_base_ptr str1_base_ptr_;
strvar_node_ptr str0_node_ptr_;
range_ptr str1_range_ptr_;
};
template <typename T>
class assignment_vec_elem_node : public binary_node<T>
{
@ -9153,7 +9330,7 @@ namespace exprtk
if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
return false;
ts.size = sbn->str().size();
ts.size = sbn->size();
ts.data = reinterpret_cast<void*>(const_cast<char*>(sbn->base()));
ts.type = type_store_t::e_string;
@ -9328,7 +9505,8 @@ namespace exprtk
{
typedef typename StringFunction::parameter_list_t parameter_list_t;
result = (*gen_function_t::function_)(ret_string_,parameter_list_t(gen_function_t::typestore_list_));
result = (*gen_function_t::function_)(ret_string_,
parameter_list_t(gen_function_t::typestore_list_));
range_.n1_c.second = ret_string_.size() - 1;
range_.cache.second = range_.n1_c.second;
@ -9355,6 +9533,11 @@ namespace exprtk
return ret_string_.data();
}
std::size_t size() const
{
return ret_string_.size();
}
range_t& range_ref()
{
return range_;
@ -9396,7 +9579,8 @@ namespace exprtk
{
typedef typename GenericFunction::parameter_list_t parameter_list_t;
return (*gen_function_t::function_)(param_seq_index_,parameter_list_t(gen_function_t::typestore_list_));
return (*gen_function_t::function_)(param_seq_index_,
parameter_list_t(gen_function_t::typestore_list_));
}
}
@ -10373,6 +10557,7 @@ namespace exprtk
static inline T process(const ivector_ptr v)
{
vector_holder<T>& vec = v->vec()->ref();
T result = T(0);
for (std::size_t i = 0; i < vec.size(); ++i)
@ -10392,6 +10577,7 @@ namespace exprtk
static inline T process(const ivector_ptr v)
{
vector_holder<T>& vec = v->vec()->ref();
T result = (*vec[0]);
for (std::size_t i = 1; i < vec.size(); ++i)
@ -10411,6 +10597,7 @@ namespace exprtk
static inline T process(const ivector_ptr v)
{
vector_holder<T>& vec = v->vec()->ref();
T result = T(0);
for (std::size_t i = 0; i < vec.size(); ++i)
@ -10430,6 +10617,7 @@ namespace exprtk
static inline T process(const ivector_ptr v)
{
vector_holder<T>& vec = v->vec()->ref();
T result = (*vec[0]);
for (std::size_t i = 1; i < vec.size(); ++i)
@ -10452,6 +10640,7 @@ namespace exprtk
static inline T process(const ivector_ptr v)
{
vector_holder<T>& vec = v->vec()->ref();
T result = (*vec[0]);
for (std::size_t i = 1; i < vec.size(); ++i)
@ -12359,8 +12548,8 @@ namespace exprtk
range_t& range1 = (*str1_range_ptr_);
if (
range0(str0_r0,str0_r1,str0_base_ptr_->str().size()) &&
range1(str1_r0,str1_r1,str1_base_ptr_->str().size())
range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
range1(str1_r0,str1_r1,str1_base_ptr_->size())
)
{
return Operation::process(
@ -14883,9 +15072,10 @@ namespace exprtk
typedef details::const_string_range_node<T> const_string_range_node_t;
typedef details::generic_string_range_node<T> generic_string_range_node_t;
typedef details::string_concat_node <T> string_concat_node_t;
typedef details::assignment_string_node<T> assignment_string_node_t;
typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
#endif
typedef details::assignment_node<T> assignment_node_t;
typedef details::assignment_string_node <T> assignment_string_node_t;
typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t;
typedef details::assignment_vec_node <T> assignment_vec_node_t;
typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t;
@ -16780,6 +16970,7 @@ namespace exprtk
make_error(parser_error::e_syntax,
current_token_,
"ERR38 - Expected '?' after condition of ternary if-statement"));
result = false;
}
else if (0 == (consequent = parse_expression()))
@ -16788,6 +16979,7 @@ namespace exprtk
make_error(parser_error::e_syntax,
current_token_,
"ERR39 - Failed to parse consequent for if-statement"));
result = false;
}
else if (!token_is(token_t::e_colon))
@ -16796,6 +16988,7 @@ namespace exprtk
make_error(parser_error::e_syntax,
current_token_,
"ERR40 - Expected ':' between ternary if-statement consequent and alternative"));
result = false;
}
else if (0 == (alternative = parse_expression()))
@ -16804,6 +16997,7 @@ namespace exprtk
make_error(parser_error::e_syntax,
current_token_,
"ERR41 - Failed to parse alternative for if-statement"));
result = false;
}
@ -17944,7 +18138,7 @@ namespace exprtk
{
free_node(node_allocator_,result);
return expression_generator_(T(const_str_node->str().size()));
return expression_generator_(T(const_str_node->size()));
}
else
return node_allocator_.allocate<details::stringvar_size_node<T> >
@ -21760,6 +21954,12 @@ namespace exprtk
return synthesize_expression<assignment_string_node_t,2>(operation,branch);
}
else if (details::is_string_range_node(branch[0]))
{
lodge_assignment(e_st_string,branch[0]);
return synthesize_expression<assignment_string_range_node_t,2>(operation,branch);
}
else if (details::is_vector_node(branch[0]))
{
lodge_assignment(e_st_vector,branch[0]);

View File

@ -2170,7 +2170,74 @@ inline bool run_test02()
test_ab<T>("(a + b)[0:5][] == 6 ","abc","123" ,T(1.0)),
test_ab<T>("(a + b)[0:5][1:4][] == 4 ","abc","123" ,T(1.0)),
test_ab<T>("(a + b)[0:5][1:4][1:2][] == 2 ","abc","123" ,T(1.0)),
test_ab<T>("(a + b)[0:5][1:4][1:2][0:0][] == 1 ","abc","123" ,T(1.0))
test_ab<T>("(a + b)[0:5][1:4][1:2][0:0][] == 1 ","abc","123" ,T(1.0)),
test_ab<T>("(a[ : ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[0: ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[ :9] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[3:7] := b); (a == '012ABCDE89');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[2:8] := b); (a == '01ABCDEFG9');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[1:9] := b); (a == '0ABCDEFGHI');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[0:0] := b); (a == 'A123456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[1:1] := b); (a == '0A23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[2:2] := b); (a == '01A3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[3:3] := b); (a == '012A456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[4:4] := b); (a == '0123A56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[5:5] := b); (a == '01234A6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[6:6] := b); (a == '012345A789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[7:7] := b); (a == '0123456A89');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[8:8] := b); (a == '01234567A9');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[9:9] := b); (a == '012345678A');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[0:1] := b); (a == 'AB23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[1:2] := b); (a == '0AB3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[2:3] := b); (a == '01AB456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[3:4] := b); (a == '012AB56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[4:5] := b); (a == '0123AB6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[5:6] := b); (a == '01234AB789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[6:7] := b); (a == '012345AB89');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[7:8] := b); (a == '0123456AB9');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[8:9] := b); (a == '01234567AB');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[ : ] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0: ] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[ :9] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[3:7] := b[3:b[] - 3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[2:8] := b[3:b[] - 3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[1:9] := b[3:b[] - 3]); (a == '0ABCDEFGHI');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0:0] := b[3:b[] - 3]); (a == 'A123456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[1:1] := b[3:b[] - 3]); (a == '0A23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[2:2] := b[3:b[] - 3]); (a == '01A3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[3:3] := b[3:b[] - 3]); (a == '012A456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[4:4] := b[3:b[] - 3]); (a == '0123A56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[5:5] := b[3:b[] - 3]); (a == '01234A6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[6:6] := b[3:b[] - 3]); (a == '012345A789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[7:7] := b[3:b[] - 3]); (a == '0123456A89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[8:8] := b[3:b[] - 3]); (a == '01234567A9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[9:9] := b[3:b[] - 3]); (a == '012345678A');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0:1] := b[3:b[] - 3]); (a == 'AB23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[1:2] := b[3:b[] - 3]); (a == '0AB3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[2:3] := b[3:b[] - 3]); (a == '01AB456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[3:4] := b[3:b[] - 3]); (a == '012AB56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[4:5] := b[3:b[] - 3]); (a == '0123AB6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[5:6] := b[3:b[] - 3]); (a == '01234AB789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[6:7] := b[3:b[] - 3]); (a == '012345AB89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[7:8] := b[3:b[] - 3]); (a == '0123456AB9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[8:9] := b[3:b[] - 3]); (a == '01234567AB');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'A123456789');", "0123456789","A" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'AB23456789');", "0123456789","AB" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABC3456789');", "0123456789","ABC" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCD456789');", "0123456789","ABCD" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDE56789');", "0123456789","ABCDE" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEF6789');", "0123456789","ABCDEF" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEFG789');", "0123456789","ABCDEFG" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEFGH89');", "0123456789","ABCDEFGH" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEFGHI9');", "0123456789","ABCDEFGHI" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012A456789');", "0123456789","A" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012AB56789');", "0123456789","AB" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABC6789');", "0123456789","ABC" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABCD789');", "0123456789","ABCD" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABCDE89');", "0123456789","ABCDE" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABCDEF9');", "0123456789","ABCDEF" ,T(1.0)),
test_ab<T>("(a[r1 / r0:r2] := b[3:b[] - r3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[r0:r2 + 1] := b[r3:b[] - r3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0))
};
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);

View File

@ -403,13 +403,19 @@ of C++ compilers:
| | will be performed. (eg: 1.67 --> 1) |
+----------+---------------------------------------------------------+
| := | Assign the value of x to y. Where x is a mutable string |
| | and y is either a string or a string range. eg: |
| | or string range and y is either a string or a string |
| | range. eg: |
| | 1. x := y |
| | 2. x := 'abc' |
| | 3. x := y[:i + j] |
| | 4. x := '0123456789'[2:7] |
| | 5. x := '0123456789'[2i + 1:7] |
| | 6. x := (y := '0123456789'[2:7]) |
| | 7. x[i:j] := y |
| | 8. x[i:j] := (y + 'abcdefg'[8 / 4:5])[m:n] |
| | |
| | Note: For options 7 and 8 the shorter of the two ranges |
| | will denote the number characters that are to be copied.|
+----------+---------------------------------------------------------+
| + | Concatenation of x and y. Where x and y are strings or |
| | string ranges. eg |
@ -841,6 +847,7 @@ following are examples of the various transformations that can occur:
(d) (2 / x) / (3 / y) ---> (2 / 3) / (x * y)
(e) (2 * x) * (3 * y) ---> (2 * 3) * (x * y)
Note:
When using strength reduction in conjunction with expressions whose
inputs or sub-expressions may result in values nearing either of the
@ -1919,11 +1926,14 @@ into account when using Exprtk:
be to recompile an expression from its string form every time
it requires evaluating.
(24) Where appropriate the return values of method invocations from
the parser and symbol_table should be taken into account.
Specifically the 'compile' method of the parser and the
'add_xxx' set of methods of the symbol table as they denote
success or failure of the invoked call.
(24) It is strongly recommended that the return value of method
invocations from the parser and symbol_table types be taken
into account. Specifically the 'compile' method of the parser
and the 'add_xxx' set of methods of the symbol_table as they
denote either the success or failure state of the invoked call.
Cointinued processing from a failed state without having first
rectified the underlying issue will in turn result in further
failures and undefined behaviours.
(25) The following are examples of compliant floating point value
representations: