PIString::toFloat/Double/LDouble own fast implementation (. and , equivalent)
PICout ldouble support PIEthernet small optimization
This commit is contained in:
@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
|||||||
project(PIP)
|
project(PIP)
|
||||||
set(PIP_MAJOR 3)
|
set(PIP_MAJOR 3)
|
||||||
set(PIP_MINOR 1)
|
set(PIP_MINOR 1)
|
||||||
set(PIP_REVISION 1)
|
set(PIP_REVISION 2)
|
||||||
set(PIP_SUFFIX )
|
set(PIP_SUFFIX )
|
||||||
set(PIP_COMPANY SHS)
|
set(PIP_COMPANY SHS)
|
||||||
set(PIP_DOMAIN org.SHS)
|
set(PIP_DOMAIN org.SHS)
|
||||||
|
|||||||
@@ -392,6 +392,8 @@ PICout & PICout::operator <<(float v) {if (!act_) return *this; space(); PIFLOAT
|
|||||||
|
|
||||||
PICout & PICout::operator <<(double v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
|
PICout & PICout::operator <<(double v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
|
||||||
|
|
||||||
|
PICout & PICout::operator <<(ldouble v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
|
||||||
|
|
||||||
PICout & PICout::operator <<(const void * v) {
|
PICout & PICout::operator <<(const void * v) {
|
||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
space();
|
space();
|
||||||
|
|||||||
@@ -230,6 +230,10 @@ public:
|
|||||||
//! \~russian Оператор вывода для <tt>"double"</tt> значений
|
//! \~russian Оператор вывода для <tt>"double"</tt> значений
|
||||||
PICout & operator <<(double v);
|
PICout & operator <<(double v);
|
||||||
|
|
||||||
|
//! \~english Output operator for <tt>"ldouble"</tt> values
|
||||||
|
//! \~russian Оператор вывода для <tt>"ldouble"</tt> значений
|
||||||
|
PICout & operator <<(ldouble v);
|
||||||
|
|
||||||
//! \~english Output operator for pointers
|
//! \~english Output operator for pointers
|
||||||
//! \~russian Оператор вывода для указателей
|
//! \~russian Оператор вывода для указателей
|
||||||
PICout & operator <<(const void * v);
|
PICout & operator <<(const void * v);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "pistring.h"
|
#include "pistring.h"
|
||||||
#include "pistringlist.h"
|
#include "pistringlist.h"
|
||||||
|
#include "pimathbase.h"
|
||||||
#ifdef PIP_ICU
|
#ifdef PIP_ICU
|
||||||
# define U_NOEXCEPT
|
# define U_NOEXCEPT
|
||||||
# include "unicode/ucnv.h"
|
# include "unicode/ucnv.h"
|
||||||
@@ -78,6 +79,97 @@ const float PIString::ElideCenter = .5f;
|
|||||||
const float PIString::ElideRight = 1.f;
|
const float PIString::ElideRight = 1.f;
|
||||||
|
|
||||||
|
|
||||||
|
inline float pow10(const int & e) {return powf(10.f, e);}
|
||||||
|
inline double pow10(const double & e) {return pow(10., e);}
|
||||||
|
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T toDecimal(const PIString & s) {
|
||||||
|
int part = 0, exp = 0;
|
||||||
|
bool negative = false, negative_exp = false, err = false;
|
||||||
|
T ret = 0., frac = 0., frac_delim = 10.;
|
||||||
|
for (const PIChar pc: s) {
|
||||||
|
char c = pc.toAscii();
|
||||||
|
switch (part) {
|
||||||
|
case 0: // sign
|
||||||
|
if (pc.isSpace()) continue;
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
ret = c - '0';
|
||||||
|
part = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '+') {
|
||||||
|
part = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '-') {
|
||||||
|
negative = true;
|
||||||
|
part = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '.' || c == ',') {
|
||||||
|
part = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case 1: // integer
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
ret = ret * 10 + (c - '0');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '.' || c == ',') {
|
||||||
|
part = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == 'e' || c == 'E') {
|
||||||
|
part = 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case 2: // fractional
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
frac += (c - '0') / frac_delim;
|
||||||
|
frac_delim *= 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == 'e' || c == 'E') {
|
||||||
|
part = 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case 3: // exponent with sign
|
||||||
|
if (c == '+') {
|
||||||
|
part = 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '-') {
|
||||||
|
negative_exp = true;
|
||||||
|
part = 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 4: // exponent
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
exp = (exp * 10) + (c - '0');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (err) break;
|
||||||
|
}
|
||||||
|
ret += frac;
|
||||||
|
if (negative) ret = -ret;
|
||||||
|
if (exp > 0) {
|
||||||
|
if (negative_exp) ret /= pow10((T)exp);
|
||||||
|
else ret *= pow10((T)exp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); snprintf(ch, 256, f, v); return PIStringAscii(ch);
|
#define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); snprintf(ch, 256, f, v); return PIStringAscii(ch);
|
||||||
|
|
||||||
PIString PIString::itos(const int num) {pisprintf("%d", num);}
|
PIString PIString::itos(const int num) {pisprintf("%d", num);}
|
||||||
@@ -1023,7 +1115,7 @@ bool PIString::toBool() const {
|
|||||||
PIString s(*this);
|
PIString s(*this);
|
||||||
s = s.trimmed().toLowerCase();
|
s = s.trimmed().toLowerCase();
|
||||||
if (s == s_true || s == s_yes || s == s_on || s == s_ok) return true;
|
if (s == s_true || s == s_yes || s == s_on || s == s_ok) return true;
|
||||||
if (atof(s.toNativeDecimalPoints().data()) > 0.) return true;
|
if (toDouble() > 0.) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1432,37 +1524,25 @@ PIString PIString::toLowerCase() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIString PIString::toNativeDecimalPoints() const {
|
|
||||||
#ifdef HAS_LOCALE
|
|
||||||
PIString s(*this);
|
|
||||||
if (currentLocale == 0) return s;
|
|
||||||
return s.replaceAll('.', currentLocale->decimal_point).replaceAll(',', currentLocale->decimal_point);
|
|
||||||
#else
|
|
||||||
return PIString(*this).replaceAll(',', '.');
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char PIString::toChar() const {
|
char PIString::toChar() const {
|
||||||
PIString s(toNativeDecimalPoints());
|
|
||||||
char v;
|
char v;
|
||||||
sscanf(s.data(), "%c", &v);
|
sscanf(dataAscii(), "%c", &v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float PIString::toFloat() const {
|
float PIString::toFloat() const {
|
||||||
return (float)atof(toNativeDecimalPoints().data());
|
return toDecimal<float>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double PIString::toDouble() const {
|
double PIString::toDouble() const {
|
||||||
return atof(toNativeDecimalPoints().data());
|
return toDecimal<double>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ldouble PIString::toLDouble() const {
|
ldouble PIString::toLDouble() const {
|
||||||
return atof(toNativeDecimalPoints().data());
|
return toDecimal<ldouble>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -870,9 +870,6 @@ public:
|
|||||||
//! \~russian Преобразует каждый символ в скопированной строке в нижний регистр.
|
//! \~russian Преобразует каждый символ в скопированной строке в нижний регистр.
|
||||||
PIString toLowerCase() const;
|
PIString toLowerCase() const;
|
||||||
|
|
||||||
// TODO: doxygen
|
|
||||||
PIString toNativeDecimalPoints() const;
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english Returns if string contains character "c".
|
//! \~english Returns if string contains character "c".
|
||||||
//! \~russian Возвращает содержит ли строка символ "c".
|
//! \~russian Возвращает содержит ли строка символ "c".
|
||||||
|
|||||||
@@ -909,6 +909,17 @@ void PIEthernet::server_func(void * eth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIEthernet::setType(Type t, bool reopen) {
|
||||||
|
eth_type = t;
|
||||||
|
setProperty("type", (int)t);
|
||||||
|
if (reopen && isOpened()) {
|
||||||
|
closeDevice();
|
||||||
|
init();
|
||||||
|
openDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
|
bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
|
||||||
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
|
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
|
||||||
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
|
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public:
|
|||||||
PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(property("parameters").toInt());}
|
PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(property("parameters").toInt());}
|
||||||
|
|
||||||
//! Returns %PIEthernet type
|
//! Returns %PIEthernet type
|
||||||
Type type() const {return (Type)(property("type").toInt());}
|
Type type() const {return eth_type;}
|
||||||
|
|
||||||
//! Returns read timeout
|
//! Returns read timeout
|
||||||
double readTimeout() const {return property("readTimeout").toDouble();}
|
double readTimeout() const {return property("readTimeout").toDouble();}
|
||||||
@@ -489,6 +489,7 @@ protected:
|
|||||||
int sock, sock_s;
|
int sock, sock_s;
|
||||||
bool connected_, connecting_, listen_threaded, server_bounded;
|
bool connected_, connecting_, listen_threaded, server_bounded;
|
||||||
mutable Address addr_r, addr_s, addr_lr;
|
mutable Address addr_r, addr_s, addr_lr;
|
||||||
|
Type eth_type;
|
||||||
PIThread server_thread_;
|
PIThread server_thread_;
|
||||||
PIMutex clients_mutex;
|
PIMutex clients_mutex;
|
||||||
PIVector<PIEthernet * > clients_;
|
PIVector<PIEthernet * > clients_;
|
||||||
@@ -498,7 +499,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
EVENT_HANDLER1(void, clientDeleted, PIObject *, o);
|
EVENT_HANDLER1(void, clientDeleted, PIObject *, o);
|
||||||
static void server_func(void * eth);
|
static void server_func(void * eth);
|
||||||
void setType(Type t, bool reopen = true) {setProperty("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}}
|
void setType(Type t, bool reopen = true);
|
||||||
|
|
||||||
static int ethErrorCore();
|
static int ethErrorCore();
|
||||||
static PIString ethErrorString();
|
static PIString ethErrorString();
|
||||||
|
|||||||
232
main.cpp
232
main.cpp
@@ -1,97 +1,169 @@
|
|||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
#include "piiostream.h"
|
#include "piiostream.h"
|
||||||
#include "pibytearray.h"
|
#include "pibytearray.h"
|
||||||
#include <vector>
|
#include "pimathbase.h"
|
||||||
#include <list>
|
|
||||||
|
|
||||||
using namespace PICoutManipulators;
|
using namespace PICoutManipulators;
|
||||||
|
|
||||||
#define SZ 256
|
inline float pow10(const int & e) {return powf(10.f, e);}
|
||||||
|
inline double pow10(const double & e) {return pow(10., e);}
|
||||||
|
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
|
||||||
|
|
||||||
class A {
|
template <typename T>
|
||||||
public:
|
T toDouble(const PIString & s) {
|
||||||
A() : id_(666) {
|
int part = 0;
|
||||||
arr = new int[SZ];
|
bool negative = false, negative_exp = false, err = false;
|
||||||
piCout << "def A()" << id_ << this << arr;
|
T ret = 0., frac = 0., frac_delim = 10., exp = 0;
|
||||||
}
|
for (const PIChar pc: s) {
|
||||||
A(int id) : id_(id) {
|
char c = pc.toAscii();
|
||||||
arr = new int[SZ];
|
switch (part) {
|
||||||
piCout << "A(int)" << id_ << this << arr;
|
case 0: // sign
|
||||||
}
|
if (pc.isSpace()) continue;
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
A(const A & a) {
|
ret = c - '0';
|
||||||
arr = new int[SZ];
|
part = 1;
|
||||||
id_ = a.id_;
|
continue;
|
||||||
piCout << "A(A)" << id_ << this << arr;
|
}
|
||||||
}
|
if (c == '+') {
|
||||||
|
part = 1;
|
||||||
A(A && a) {
|
continue;
|
||||||
std::swap(id_, a.id_);
|
}
|
||||||
std::swap(arr, a.arr);
|
if (c == '-') {
|
||||||
piCout << "move A(A)" << id_ << this << arr;
|
negative = true;
|
||||||
}
|
part = 1;
|
||||||
|
continue;
|
||||||
~A() {
|
}
|
||||||
if (arr) {
|
if (c == '.' || c == ',') {
|
||||||
memset(arr, 0, SZ * 4);
|
part = 2;
|
||||||
delete arr;
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case 1: // integer
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
ret = ret * 10 + (c - '0');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '.' || c == ',') {
|
||||||
|
part = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == 'e' || c == 'E') {
|
||||||
|
part = 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case 2: // fractional
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
frac += (c - '0') / frac_delim;
|
||||||
|
frac_delim *= 10;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == 'e' || c == 'E') {
|
||||||
|
part = 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
case 3: // exponent with sign
|
||||||
|
if (c == '+') {
|
||||||
|
part = 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '-') {
|
||||||
|
negative_exp = true;
|
||||||
|
part = 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 4: // exponent
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
exp = (exp * 10) + (c - '0');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
piCout << "~A()" << id_ << this << arr;
|
if (err) break;
|
||||||
//id_ = 0;
|
|
||||||
}
|
}
|
||||||
|
ret += frac;
|
||||||
inline A & operator =(const A & a) {
|
if (negative) ret = -ret;
|
||||||
id_ = a.id_;
|
if (exp > 0) {
|
||||||
piCout << "A =" << id_ << this;
|
if (negative_exp) ret /= pow10(exp);
|
||||||
return *this;
|
else ret *= pow10(exp);
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline A & operator =(A && a) {
|
inline void test(const PIString & s) {
|
||||||
std::swap(id_, a.id_);
|
double av = toDouble<double>(s);
|
||||||
std::swap(arr, a.arr);
|
double v = s.toDouble();
|
||||||
piCout << "move A=" << id_ << this;
|
piCout << s << "=" << v << av;
|
||||||
return *this;
|
}
|
||||||
}
|
|
||||||
private:
|
|
||||||
int id_ = -1;
|
|
||||||
int * arr = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//class B {
|
|
||||||
//public:
|
|
||||||
// B() {a_ = nullptr;}
|
|
||||||
// ~B() {if (a_) delete a_;}
|
|
||||||
|
|
||||||
// void setA(A && a) {
|
|
||||||
// a_ = (A *)malloc(sizeof(a));
|
|
||||||
// memcpy(a_, &a, sizeof(a));
|
|
||||||
// operator delete(&a);
|
|
||||||
// }
|
|
||||||
// void setA(const A & a) {a_ = new A(a);}
|
|
||||||
//private:
|
|
||||||
// A * a_;
|
|
||||||
//};
|
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
piCout << "pip 3.1";
|
/*test(" 123 ");
|
||||||
{
|
test("\n123 ");
|
||||||
PIDeque<A> v;
|
test("\t123 ");
|
||||||
//A a;
|
test(" +123 ");
|
||||||
//v.push_back(a);
|
test(" ++123 ");
|
||||||
//v.push_back(std::move(a));
|
test(" + 123 ");
|
||||||
v.push_back(A(1));
|
test(" -123 ");
|
||||||
v.push_back(A(2));
|
test(" --123 ");
|
||||||
v.push_back(A(3));
|
test(" - 123 ");
|
||||||
}
|
test("123.1");
|
||||||
|
test("123 .1");
|
||||||
|
test("123 . 1");
|
||||||
|
test("123.+1");
|
||||||
|
test("123.-1");
|
||||||
|
test("123E2");
|
||||||
|
test("123E+2");
|
||||||
|
test("123E +2");
|
||||||
|
test("123E+ 2");
|
||||||
|
test("123E + 2");
|
||||||
|
test("123 E+2");
|
||||||
|
test("123 E +2");
|
||||||
|
test("123 E+ 2");
|
||||||
|
test("123 E + 2");
|
||||||
|
test("123E+2.5");
|
||||||
|
test("123.4E+2");
|
||||||
|
test("123.4.5E+2");
|
||||||
|
test("123EE+2");
|
||||||
|
test("123e+2");
|
||||||
|
test("123e++2");
|
||||||
|
test("E+2");
|
||||||
|
test("1E+2");
|
||||||
|
test("1.E+2");
|
||||||
|
test(".E+2");
|
||||||
|
test(".1E-2");
|
||||||
|
test("+E2");
|
||||||
|
test("nan");
|
||||||
|
test("inf");*/
|
||||||
|
test("1.23");
|
||||||
|
test("1,23");
|
||||||
|
test(".23");
|
||||||
|
test(",23");
|
||||||
|
PITimeMeasurer tm;
|
||||||
|
PIString s("1E+600");
|
||||||
|
int cnt = 1000000;
|
||||||
|
int el_o = 0, el_n = 0;
|
||||||
|
ldouble v = 0.;
|
||||||
|
NO_UNUSED(v);
|
||||||
|
|
||||||
piCout << "";
|
tm.reset();
|
||||||
piCout << "std";
|
piForTimes (cnt) {
|
||||||
{
|
v = s.toLDouble();
|
||||||
std::vector<A> v;
|
|
||||||
v.push_back(A(1));
|
|
||||||
v.push_back(A(2));
|
|
||||||
v.push_back(A(3));
|
|
||||||
}
|
}
|
||||||
|
el_o = tm.elapsed_u();
|
||||||
|
piCout << v << el_o;
|
||||||
|
|
||||||
|
tm.reset();
|
||||||
|
piForTimes (cnt) {
|
||||||
|
v = toDouble<ldouble>(s);
|
||||||
|
}
|
||||||
|
el_n = tm.elapsed_u();
|
||||||
|
piCout << v << el_n;
|
||||||
|
|
||||||
|
piCout << (double)el_o / el_n;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user