code format

This commit is contained in:
2022-12-14 14:13:52 +03:00
parent 430a41fefc
commit c2b8a8d6da
297 changed files with 27331 additions and 24162 deletions

View File

@@ -5,22 +5,22 @@
* \~russian Вычисление CRC контрольной суммы
*/
/*
PIP - Platform Independent Primitives
CRC checksum calculator
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
CRC checksum calculator
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICRC_H
@@ -28,138 +28,295 @@
#include "pistring.h"
template <int L>
template<int L>
class PIP_EXPORT uint_cl {
public:
uint_cl() {for (int i = 0; i < L / 8; ++i) data_[i] = 0;}
uint_cl(const uint_cl<L> & v) {for (int i = 0; i < L / 8; ++i) data_[i] = v.data_[i];}
uint_cl(uchar v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);}
uint_cl(char v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);}
uint_cl(ushort v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(short v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(uint v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(int v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(ulong v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(long v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(ullong v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl(llong v) {int l = piMin<uint>(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;}
uint_cl() {
for (int i = 0; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(const uint_cl<L> & v) {
for (int i = 0; i < L / 8; ++i)
data_[i] = v.data_[i];
}
uint_cl(uchar v) {
for (int i = 0; i < L / 8; ++i)
data_[i] = (i == 0 ? v : 0);
}
uint_cl(char v) {
for (int i = 0; i < L / 8; ++i)
data_[i] = (i == 0 ? v : 0);
}
uint_cl(ushort v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(short v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(uint v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(int v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(ulong v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(long v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(ullong v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
uint_cl(llong v) {
int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i)
data_[i] = 0;
}
operator bool() {for (int i = 0; i < L / 8; ++i) if (data_[i] > 0) return true; return false;}
operator char() {return (char)data_[0];}
operator short() {short t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator int() {int t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator long() {long t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator llong() {llong t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator uchar() {return data_[0];}
operator ushort() {ushort t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator uint() {uint t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator ulong() {ulong t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator ullong() {ullong t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator bool() {
for (int i = 0; i < L / 8; ++i)
if (data_[i] > 0) return true;
return false;
}
operator char() { return (char)data_[0]; }
operator short() {
short t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator int() {
int t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator long() {
long t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator llong() {
llong t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator uchar() { return data_[0]; }
operator ushort() {
ushort t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator uint() {
uint t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator ulong() {
ulong t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
operator ullong() {
ullong t(0);
int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l);
return t;
}
uint_cl<L> operator +(const uint_cl<L> & v) {
uint_cl<L> operator+(const uint_cl<L> & v) {
uint_cl<L> t;
uint cv;
bool ov = false;
for (int i = 0; i < L / 8; ++i) {
cv = v.data_[i] + data_[i];
if (ov) ++cv;
ov = cv > 255;
ov = cv > 255;
t.data_[i] = ov ? cv - 256 : cv;
}
return t;
}
uint_cl<L> operator &(const uint_cl<L> & v) const {uint_cl<L> t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] & data_[i]; return t;}
uint_cl<L> operator &(const uchar & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const ushort & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const uint & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const ulong & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const ullong & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const char & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const short & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const int & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const long & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const llong & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator&(const uint_cl<L> & v) const {
uint_cl<L> t;
for (int i = 0; i < L / 8; ++i)
t.data_[i] = v.data_[i] & data_[i];
return t;
}
uint_cl<L> operator&(const uchar & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const ushort & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const uint & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const ulong & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const ullong & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const char & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const short & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const int & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const long & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const llong & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator |(const uint_cl<L> & v) const {uint_cl<L> t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] | data_[i]; return t;}
uint_cl<L> operator |(const uchar & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const ushort & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const uint & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const ulong & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const ullong & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const char & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const short & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const int & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const long & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const llong & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator|(const uint_cl<L> & v) const {
uint_cl<L> t;
for (int i = 0; i < L / 8; ++i)
t.data_[i] = v.data_[i] | data_[i];
return t;
}
uint_cl<L> operator|(const uchar & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const ushort & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const uint & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const ulong & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const ullong & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const char & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const short & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const int & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const long & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const llong & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator ^(const uint_cl<L> & v) const {uint_cl<L> t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] ^ data_[i]; return t;}
uint_cl<L> operator ^(const uchar & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const ushort & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const uint & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const ulong & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const ullong & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const char & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const short & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const int & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const long & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const llong & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator^(const uint_cl<L> & v) const {
uint_cl<L> t;
for (int i = 0; i < L / 8; ++i)
t.data_[i] = v.data_[i] ^ data_[i];
return t;
}
uint_cl<L> operator^(const uchar & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const ushort & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const uint & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const ulong & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const ullong & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const char & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const short & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const int & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const long & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const llong & v) const { return *this ^ uint_cl<L>(v); }
bool operator <(const uint_cl<L> & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return false;}
bool operator <=(const uint_cl<L> & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return true;}
bool operator >(const uint_cl<L> & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return false;}
bool operator >=(const uint_cl<L> & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return true;}
bool operator ==(const uint_cl<L> & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return false; return true;}
bool operator !=(const uint_cl<L> & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return true; return false;}
bool operator <=(const uint_cl<8> & v1) {return (*(uchar*)data()) <= (*(uchar*)v1.data());}
bool operator<(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] > data_[i]) return true;
if (v.data_[i] < data_[i]) return false;
}
return false;
}
bool operator<=(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] > data_[i]) return true;
if (v.data_[i] < data_[i]) return false;
}
return true;
}
bool operator>(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] < data_[i]) return true;
if (v.data_[i] > data_[i]) return false;
}
return false;
}
bool operator>=(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] < data_[i]) return true;
if (v.data_[i] > data_[i]) return false;
}
return true;
}
bool operator==(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i)
if (v.data_[i] != data_[i]) return false;
return true;
}
bool operator!=(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i)
if (v.data_[i] != data_[i]) return true;
return false;
}
bool operator<=(const uint_cl<8> & v1) { return (*(uchar *)data()) <= (*(uchar *)v1.data()); }
uint_cl<L> operator >>(const int & c) const {
uint_cl<L> operator>>(const int & c) const {
uint_cl<L> t;
int l = L - c;
bool bit;
if (l <= 0) return t;
for (int i = 0; i < l; ++i) {
bit = 1 & (data_[(i + c) / 8] >> ((i + c) % 8));
if (bit) t.data_[i / 8] |= (1 << (i % 8));
else t.data_[i / 8] &= ~(1 << (i % 8));
if (bit)
t.data_[i / 8] |= (1 << (i % 8));
else
t.data_[i / 8] &= ~(1 << (i % 8));
}
return t;
}
uint_cl<L> operator >>(const uint & c) const {return (*this << (int)c);}
uint_cl<L> operator <<(const int & c) const {
uint_cl<L> operator>>(const uint & c) const { return (*this << (int)c); }
uint_cl<L> operator<<(const int & c) const {
uint_cl<L> t;
int l = L - c;
bool bit;
if (l <= 0) return t;
for (int i = c; i < L; ++i) {
bit = 1 & (data_[(i - c) / 8] >> ((i - c) % 8));
if (bit) t.data_[i / 8] |= (1 << (i % 8));
else t.data_[i / 8] &= ~(1 << (i % 8));
if (bit)
t.data_[i / 8] |= (1 << (i % 8));
else
t.data_[i / 8] &= ~(1 << (i % 8));
}
return t;
}
uint_cl<L> operator <<(const uint & c) const {return (*this >> (int)c);}
uint_cl<L> operator<<(const uint & c) const { return (*this >> (int)c); }
uint_cl<L> & inverse() const {for (int i = 0; i < L / 8; ++i) data_[i] = ~data_[i]; return *this;}
uint_cl<L> inversed() const {uint_cl<L> t(*this); for (int i = 0; i < L / 8; ++i) t.data_[i] = ~t.data_[i]; return t;}
uint_cl<L> & inverse() const {
for (int i = 0; i < L / 8; ++i)
data_[i] = ~data_[i];
return *this;
}
uint_cl<L> inversed() const {
uint_cl<L> t(*this);
for (int i = 0; i < L / 8; ++i)
t.data_[i] = ~t.data_[i];
return t;
}
uint_cl<L> reversed() const {
uint_cl<L> t;
bool bit;
for (int i = 0; i < L; ++i) {
bit = 1 & (data_[(L - i - 1) / 8] >> ((L - i - 1) % 8));
if (bit) t.data_[i / 8] |= (1 << (i % 8));
else t.data_[i / 8] &= ~(1 << (i % 8));
if (bit)
t.data_[i / 8] |= (1 << (i % 8));
else
t.data_[i / 8] &= ~(1 << (i % 8));
}
return t;
}
const uchar * data() const {return data_;}
uchar * data() {return data_;}
uint length() const {return L / 8;}
const uchar * data() const { return data_; }
uchar * data() { return data_; }
uint length() const { return L / 8; }
private:
uchar data_[L / 8];
};
@@ -173,74 +330,117 @@ inline uchar reverseByte(uchar b) {
return ret;
}
template <uint L, typename N = uint_cl<L> >
template<uint L, typename N = uint_cl<L>>
class PIP_EXPORT PICRC {
public:
PICRC(const N & poly = N()) {poly_ = poly; reverse_poly = true; init_ = inversed(N(0)); out_ = inversed(N(0)); reverse_before_xor = reverse_data = false; initTable();}
PICRC(const N & poly, bool reverse_poly_, const N & initial, const N & out_xor) {poly_ = poly; reverse_poly = reverse_poly_; init_ = initial; out_ = out_xor; reverse_before_xor = reverse_data = false; initTable();}
PICRC(const N & poly = N()) {
poly_ = poly;
reverse_poly = true;
init_ = inversed(N(0));
out_ = inversed(N(0));
reverse_before_xor = reverse_data = false;
initTable();
}
PICRC(const N & poly, bool reverse_poly_, const N & initial, const N & out_xor) {
poly_ = poly;
reverse_poly = reverse_poly_;
init_ = initial;
out_ = out_xor;
reverse_before_xor = reverse_data = false;
initTable();
}
void setInitial(const N & v) {init_ = v;}
void setOutXor(const N & v) {out_ = v;}
void setReversePolynome(bool yes) {reverse_poly = yes; initTable();}
void setReverseOutBeforeXOR(bool yes) {reverse_before_xor = yes;}
void setReverseDataBytes(bool yes) {reverse_data = yes;}
void setInitial(const N & v) { init_ = v; }
void setOutXor(const N & v) { out_ = v; }
void setReversePolynome(bool yes) {
reverse_poly = yes;
initTable();
}
void setReverseOutBeforeXOR(bool yes) { reverse_before_xor = yes; }
void setReverseDataBytes(bool yes) { reverse_data = yes; }
void initTable() {
N tmp, pol = reverse_poly ? reversed(poly_) : poly_;
//cout << std::hex << "poly " << (uint)N(poly_) << " -> " << (uint)N(pol) << endl;
// cout << std::hex << "poly " << (uint)N(poly_) << " -> " << (uint)N(pol) << endl;
for (int i = 0; i < 256; ++i) {
tmp = uchar(i);
for (int j = 0; j < 8; ++j)
tmp = ((tmp & 1) ? ((tmp >> 1) ^ pol) : (tmp >> 1));
table[i] = tmp;
}
}
N calculate(const void * data, int size) {
N crc = init_;
uchar * data_ = (uchar * )data, cb;
//cout << "process " << size << endl;
N crc = init_;
uchar *data_ = (uchar *)data, cb;
// cout << "process " << size << endl;
uchar nTemp;
for (int i = 0; i < size; ++i) {
cb = data_[i];
if (reverse_data) cb = reverseByte(cb);
nTemp = cb ^ uchar(crc);
crc = crc >> 8;
crc = crc ^ table[nTemp];
crc = crc >> 8;
crc = crc ^ table[nTemp];
}
if (reverse_before_xor) crc = reversed(crc);
return crc ^ out_;
}
N calculate(const PIByteArray & d) {return calculate(d.data(), d.size());}
N calculate(const char * str) {PIByteArray s(PIString(str).toByteArray()); return calculate(s.data(), s.size_s());}
N calculate(const PIByteArray & d) { return calculate(d.data(), d.size()); }
N calculate(const char * str) {
PIByteArray s(PIString(str).toByteArray());
return calculate(s.data(), s.size_s());
}
private:
inline N reversed(const N & v) {return v.reversed();}
inline N inversed(const N & v) {return v.inversed();}
inline N reversed(const N & v) { return v.reversed(); }
inline N inversed(const N & v) { return v.inversed(); }
N table[256];
N poly_, init_, out_;
bool reverse_poly, reverse_before_xor, reverse_data;
};
template <> inline uchar PICRC<8, uchar>::reversed(const uchar & v) {return reverseByte(v);}
template <> inline ushort PICRC<16, ushort>::reversed(const ushort & v) {return uint_cl<16>(v).reversed();}
template <> inline uint PICRC<32, uint>::reversed(const uint & v) {return uint_cl<32>(v).reversed();}
template <> inline uchar PICRC<8, uchar>::inversed(const uchar & v) {return ~v;}
template <> inline ushort PICRC<16, ushort>::inversed(const ushort & v) {return ~v;}
template <> inline uint PICRC<32, uint>::inversed(const uint & v) {return ~v;}
template<>
inline uchar PICRC<8, uchar>::reversed(const uchar & v) {
return reverseByte(v);
}
template<>
inline ushort PICRC<16, ushort>::reversed(const ushort & v) {
return uint_cl<16>(v).reversed();
}
template<>
inline uint PICRC<32, uint>::reversed(const uint & v) {
return uint_cl<32>(v).reversed();
}
template<>
inline uchar PICRC<8, uchar>::inversed(const uchar & v) {
return ~v;
}
template<>
inline ushort PICRC<16, ushort>::inversed(const ushort & v) {
return ~v;
}
template<>
inline uint PICRC<32, uint>::inversed(const uint & v) {
return ~v;
}
typedef PICRC<32, uint> CRC_32;
typedef PICRC<24> CRC_24;
typedef PICRC<32, uint> CRC_32;
typedef PICRC<24> CRC_24;
typedef PICRC<16, ushort> CRC_16;
typedef PICRC<8, uchar> CRC_8;
typedef PICRC<8, uchar> CRC_8;
inline CRC_32 standardCRC_32() {return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF);}
inline CRC_16 standardCRC_16() {return CRC_16(0x8005, true, 0x0, 0x0);}
inline CRC_16 standardCRC_16_Modbus() {return CRC_16(0x8005, 0xFFFF, 0xFFFF, false);}
inline CRC_8 standardCRC_8() {return CRC_8(0xD5, true, 0x0, 0x0);}
inline CRC_32 standardCRC_32() {
return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF);
}
inline CRC_16 standardCRC_16() {
return CRC_16(0x8005, true, 0x0, 0x0);
}
inline CRC_16 standardCRC_16_Modbus() {
return CRC_16(0x8005, 0xFFFF, 0xFFFF, false);
}
inline CRC_8 standardCRC_8() {
return CRC_8(0xD5, true, 0x0, 0x0);
}
#endif // CRC_H

View File

@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Evaluator designed for stream computing
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Evaluator designed for stream computing
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pievaluator.h"
@@ -122,49 +122,49 @@ using namespace PIEvaluatorTypes;
PIEvaluatorContent::PIEvaluatorContent() {
addFunction(PIStringAscii("arcsin" ), 1);
addFunction(PIStringAscii("arccos" ), 1);
addFunction(PIStringAscii("arctg" ), 1);
addFunction(PIStringAscii("arcctg" ), 1);
addFunction(PIStringAscii("random" ), 2);
addFunction(PIStringAscii("arcsin"), 1);
addFunction(PIStringAscii("arccos"), 1);
addFunction(PIStringAscii("arctg"), 1);
addFunction(PIStringAscii("arcctg"), 1);
addFunction(PIStringAscii("random"), 2);
addFunction(PIStringAscii("randomn"), 2);
addFunction(PIStringAscii("sin" ), 1);
addFunction(PIStringAscii("cos" ), 1);
addFunction(PIStringAscii("ctg" ), 1);
addFunction(PIStringAscii("tg" ), 1);
addFunction(PIStringAscii("exp" ), 1);
addFunction(PIStringAscii("cth" ), 1);
addFunction(PIStringAscii("sh" ), 1);
addFunction(PIStringAscii("ch" ), 1);
addFunction(PIStringAscii("th" ), 1);
addFunction(PIStringAscii("sqrt" ), 1);
addFunction(PIStringAscii("sqr" ), 1);
addFunction(PIStringAscii("pow" ), 2);
addFunction(PIStringAscii("abs" ), 1);
addFunction(PIStringAscii("ln" ), 1);
addFunction(PIStringAscii("lg" ), 1);
addFunction(PIStringAscii("log" ), 2);
addFunction(PIStringAscii("im" ), 1);
addFunction(PIStringAscii("re" ), 1);
addFunction(PIStringAscii("arg" ), 1);
addFunction(PIStringAscii("len" ), 1);
addFunction(PIStringAscii("conj" ), 1);
addFunction(PIStringAscii("sign" ), 1);
addFunction(PIStringAscii("rad" ), 1);
addFunction(PIStringAscii("deg" ), 1);
addFunction(PIStringAscii("j0" ), 1);
addFunction(PIStringAscii("j1" ), 1);
addFunction(PIStringAscii("jn" ), 2);
addFunction(PIStringAscii("y0" ), 1);
addFunction(PIStringAscii("y1" ), 1);
addFunction(PIStringAscii("yn" ), 2);
addFunction(PIStringAscii("min" ), -2); // (x0,x1,...)
addFunction(PIStringAscii("max" ), -2); // (x0,x1,...)
addFunction(PIStringAscii("clamp" ), 3); // (x,a,b) = x < a ? a : (x > b ? b : x)
addFunction(PIStringAscii("step" ), 2); // (x,s) = x >= s ? 1. : 0. (1 if 'x' >= 's', else 0)
addFunction(PIStringAscii("mix" ), 3); // (x,a,b) = a*(1.-x) + b*x (interpolate between 'a' and 'b' linear for 'x')
addFunction(PIStringAscii("sin"), 1);
addFunction(PIStringAscii("cos"), 1);
addFunction(PIStringAscii("ctg"), 1);
addFunction(PIStringAscii("tg"), 1);
addFunction(PIStringAscii("exp"), 1);
addFunction(PIStringAscii("cth"), 1);
addFunction(PIStringAscii("sh"), 1);
addFunction(PIStringAscii("ch"), 1);
addFunction(PIStringAscii("th"), 1);
addFunction(PIStringAscii("sqrt"), 1);
addFunction(PIStringAscii("sqr"), 1);
addFunction(PIStringAscii("pow"), 2);
addFunction(PIStringAscii("abs"), 1);
addFunction(PIStringAscii("ln"), 1);
addFunction(PIStringAscii("lg"), 1);
addFunction(PIStringAscii("log"), 2);
addFunction(PIStringAscii("im"), 1);
addFunction(PIStringAscii("re"), 1);
addFunction(PIStringAscii("arg"), 1);
addFunction(PIStringAscii("len"), 1);
addFunction(PIStringAscii("conj"), 1);
addFunction(PIStringAscii("sign"), 1);
addFunction(PIStringAscii("rad"), 1);
addFunction(PIStringAscii("deg"), 1);
addFunction(PIStringAscii("j0"), 1);
addFunction(PIStringAscii("j1"), 1);
addFunction(PIStringAscii("jn"), 2);
addFunction(PIStringAscii("y0"), 1);
addFunction(PIStringAscii("y1"), 1);
addFunction(PIStringAscii("yn"), 2);
addFunction(PIStringAscii("min"), -2); // (x0,x1,...)
addFunction(PIStringAscii("max"), -2); // (x0,x1,...)
addFunction(PIStringAscii("clamp"), 3); // (x,a,b) = x < a ? a : (x > b ? b : x)
addFunction(PIStringAscii("step"), 2); // (x,s) = x >= s ? 1. : 0. (1 if 'x' >= 's', else 0)
addFunction(PIStringAscii("mix"), 3); // (x,a,b) = a*(1.-x) + b*x (interpolate between 'a' and 'b' linear for 'x')
addFunction(PIStringAscii("defined"), 1);
addFunction(PIStringAscii("round" ), 1);
addFunction(PIStringAscii("round"), 1);
clearCustomVariables();
}
@@ -206,94 +206,89 @@ int PIEvaluatorContent::customVariablesCount() const {
int PIEvaluatorContent::findFunction(const PIString & name) const {
for (uint i = 0; i < functions.size(); i++)
if (functions[i].identifier == name)
return i;
if (functions[i].identifier == name) return i;
return -1;
}
int PIEvaluatorContent::findVariable(const PIString & var_name) const {
for (uint i = 0; i < variables.size(); i++)
if (variables[i].name == var_name)
return i;
if (variables[i].name == var_name) return i;
return -1;
}
PIEvaluatorTypes::Function PIEvaluatorContent::function(int index) {
if (index < 0 || index >= functions.size_s())
return PIEvaluatorTypes::Function();
if (index < 0 || index >= functions.size_s()) return PIEvaluatorTypes::Function();
return functions[index];
}
PIEvaluatorTypes::Variable PIEvaluatorContent::variable(int index) {
if (index < 0 || index >= variables.size_s())
return PIEvaluatorTypes::Variable();
if (index < 0 || index >= variables.size_s()) return PIEvaluatorTypes::Variable();
return variables[index];
}
PIEvaluatorTypes::Variable PIEvaluatorContent::customVariable(int index) {
if (index < 0 || index >= variables.size_s() - cv_count)
return PIEvaluatorTypes::Variable();
if (index < 0 || index >= variables.size_s() - cv_count) return PIEvaluatorTypes::Variable();
return variables[index + cv_count];
}
void PIEvaluatorContent::clearCustomVariables() {
variables.clear();
addVariable(PIStringAscii("i" ), complexd_i);
addVariable(PIStringAscii("i"), complexd_i);
addVariable(PIStringAscii("pi"), 3.141592653589793238462643383280);
addVariable(PIStringAscii("e" ), exp(1.));
addVariable(PIStringAscii("e"), exp(1.));
cv_count = variables.size_s();
}
BaseFunctions PIEvaluatorContent::getBaseFunction(const PIString & name) {
if (name == PIStringAscii("sin" )) return bfSin;
if (name == PIStringAscii("cos" )) return bfCos;
if (name == PIStringAscii("tg" )) return bfTg;
if (name == PIStringAscii("ctg" )) return bfCtg;
if (name == PIStringAscii("arcsin" )) return bfArcsin;
if (name == PIStringAscii("arccos" )) return bfArccos;
if (name == PIStringAscii("arctg" )) return bfArctg;
if (name == PIStringAscii("arcctg" )) return bfArcctg;
if (name == PIStringAscii("exp" )) return bfExp;
if (name == PIStringAscii("random" )) return bfRandom;
if (name == PIStringAscii("sin")) return bfSin;
if (name == PIStringAscii("cos")) return bfCos;
if (name == PIStringAscii("tg")) return bfTg;
if (name == PIStringAscii("ctg")) return bfCtg;
if (name == PIStringAscii("arcsin")) return bfArcsin;
if (name == PIStringAscii("arccos")) return bfArccos;
if (name == PIStringAscii("arctg")) return bfArctg;
if (name == PIStringAscii("arcctg")) return bfArcctg;
if (name == PIStringAscii("exp")) return bfExp;
if (name == PIStringAscii("random")) return bfRandom;
if (name == PIStringAscii("randomn")) return bfRandomn;
if (name == PIStringAscii("sh" )) return bfSh;
if (name == PIStringAscii("ch" )) return bfCh;
if (name == PIStringAscii("th" )) return bfTh;
if (name == PIStringAscii("cth" )) return bfCth;
if (name == PIStringAscii("sqrt" )) return bfSqrt;
if (name == PIStringAscii("sqr" )) return bfSqr;
if (name == PIStringAscii("pow" )) return bfPow;
if (name == PIStringAscii("abs" )) return bfAbs;
if (name == PIStringAscii("ln" )) return bfLn;
if (name == PIStringAscii("lg" )) return bfLg;
if (name == PIStringAscii("log" )) return bfLog;
if (name == PIStringAscii("im" )) return bfIm;
if (name == PIStringAscii("re" )) return bfRe;
if (name == PIStringAscii("arg" )) return bfArg;
if (name == PIStringAscii("len" )) return bfLen;
if (name == PIStringAscii("conj" )) return bfConj;
if (name == PIStringAscii("sign" )) return bfSign;
if (name == PIStringAscii("rad" )) return bfRad;
if (name == PIStringAscii("deg" )) return bfDeg;
if (name == PIStringAscii("j0" )) return bfJ0;
if (name == PIStringAscii("j1" )) return bfJ1;
if (name == PIStringAscii("jn" )) return bfJN;
if (name == PIStringAscii("y0" )) return bfY0;
if (name == PIStringAscii("y1" )) return bfY1;
if (name == PIStringAscii("yn" )) return bfYN;
if (name == PIStringAscii("min" )) return bfMin;
if (name == PIStringAscii("max" )) return bfMax;
if (name == PIStringAscii("clamp" )) return bfClamp;
if (name == PIStringAscii("step" )) return bfStep;
if (name == PIStringAscii("mix" )) return bfMix;
if (name == PIStringAscii("sh")) return bfSh;
if (name == PIStringAscii("ch")) return bfCh;
if (name == PIStringAscii("th")) return bfTh;
if (name == PIStringAscii("cth")) return bfCth;
if (name == PIStringAscii("sqrt")) return bfSqrt;
if (name == PIStringAscii("sqr")) return bfSqr;
if (name == PIStringAscii("pow")) return bfPow;
if (name == PIStringAscii("abs")) return bfAbs;
if (name == PIStringAscii("ln")) return bfLn;
if (name == PIStringAscii("lg")) return bfLg;
if (name == PIStringAscii("log")) return bfLog;
if (name == PIStringAscii("im")) return bfIm;
if (name == PIStringAscii("re")) return bfRe;
if (name == PIStringAscii("arg")) return bfArg;
if (name == PIStringAscii("len")) return bfLen;
if (name == PIStringAscii("conj")) return bfConj;
if (name == PIStringAscii("sign")) return bfSign;
if (name == PIStringAscii("rad")) return bfRad;
if (name == PIStringAscii("deg")) return bfDeg;
if (name == PIStringAscii("j0")) return bfJ0;
if (name == PIStringAscii("j1")) return bfJ1;
if (name == PIStringAscii("jn")) return bfJN;
if (name == PIStringAscii("y0")) return bfY0;
if (name == PIStringAscii("y1")) return bfY1;
if (name == PIStringAscii("yn")) return bfYN;
if (name == PIStringAscii("min")) return bfMin;
if (name == PIStringAscii("max")) return bfMax;
if (name == PIStringAscii("clamp")) return bfClamp;
if (name == PIStringAscii("step")) return bfStep;
if (name == PIStringAscii("mix")) return bfMix;
if (name == PIStringAscii("defined")) return bfDefined;
if (name == PIStringAscii("round" )) return bfRound;
if (name == PIStringAscii("round")) return bfRound;
return bfUnknown;
}
@@ -312,8 +307,10 @@ const PIString & PIEvaluator::prepare(const PIString & string) {
replaceOperators();
removeSpaces();
checkBrackets();
while (fillElements()) checkBrackets();
while (setSignes()) fillElements();
while (fillElements())
checkBrackets();
while (setSignes())
fillElements();
removeJunk();
findUnknownVariables();
return currentString;
@@ -352,7 +349,8 @@ void PIEvaluator::removeJunk() {
elements.pop_back();
junk = true;
break;
} else break;
} else
break;
}
}
}
@@ -388,8 +386,10 @@ void PIEvaluator::findUnknownVariables() {
unknownVars.clear();
usedVars.clear();
for (int i = 0; i < currentString.length(); i++) {
if (elements[i].var_num >= 0) usedVars << content.variable(elements[i].var_num).name;
else if (elements[i].var_num == -666) cvar += currentString[i];
if (elements[i].var_num >= 0)
usedVars << content.variable(elements[i].var_num).name;
else if (elements[i].var_num == -666)
cvar += currentString[i];
else {
if (cvar.length() == 0) continue;
unknownVars << cvar;
@@ -412,7 +412,6 @@ bool PIEvaluator::isSign(const PIChar & ch) {
}
void PIEvaluator::checkBrackets() {
PIString tmps = currentString;
PIChar fc, sc;
@@ -427,7 +426,8 @@ void PIEvaluator::checkBrackets() {
if (bcnt == 0) {
currentString.insert(bpos + inserted, '(');
inserted++;
} else bcnt--;
} else
bcnt--;
}
}
if (bcnt > 0) currentString += PIString(bcnt, ')');
@@ -435,9 +435,8 @@ void PIEvaluator::checkBrackets() {
for (int i = 0; i < tmps.length() - 1; i++) {
fc = tmps[i].toLower();
sc = tmps[i + 1].toLower();
if ((fc == ')' && sc == '(') ||
(fc == ')' && sc >= '0' && sc <= '9') ||
(fc == ')' && sc >= 'a' && sc <= 'z') ) tmps.insert(++i, '*');
if ((fc == ')' && sc == '(') || (fc == ')' && sc >= '0' && sc <= '9') || (fc == ')' && sc >= 'a' && sc <= 'z'))
tmps.insert(++i, '*');
}
currentString = tmps;
}
@@ -445,20 +444,20 @@ void PIEvaluator::checkBrackets() {
bool PIEvaluator::fillElements() {
int fstart, flen, cnum = 0, cpart = 0, cfunc;
PIChar cc, nc, pc, fc = '!';
PIChar cc, nc, pc, fc = '!';
bool numFound = false;
PIString curfind, tmps = currentString;
elements.resize(tmps.length());
for (uint i = 0; i < elements.size(); i++) {
elements[i].type = etVariable;
elements[i].type = etVariable;
elements[i].var_num = -666;
}
currentVariables.clear();
for (int i = 0; i < content.functionsCount(); i++) {
curfind = content.function(i).identifier;
cfunc = i;
flen = curfind.length();
fstart = 0;
cfunc = i;
flen = curfind.length();
fstart = 0;
while (fstart >= 0) {
fstart = tmps.find(curfind, fstart);
if (fstart < 0) break;
@@ -479,12 +478,12 @@ bool PIEvaluator::fillElements() {
for (int i = 0; i < content.variables.size_s(); ++i) {
var_index << PairII(i, content.variables[i].name.length());
}
var_index.sort([](const PairII & v1, const PairII & v2){return v1.second > v2.second;});
var_index.sort([](const PairII & v1, const PairII & v2) { return v1.second > v2.second; });
for (int i = 0; i < var_index.size_s(); i++) {
int vind = var_index[i].first;
curfind = content.variables[vind].name;
flen = curfind.length();
fstart = 0;
curfind = content.variables[vind].name;
flen = curfind.length();
fstart = 0;
while (fstart >= 0) {
fstart = tmps.find(curfind, fstart);
if (fstart < 0) break;
@@ -570,7 +569,7 @@ bool PIEvaluator::fillElements() {
}
curfind.clear();
cnum++;
cpart = 0;
cpart = 0;
numFound = false;
}
}
@@ -584,24 +583,28 @@ bool PIEvaluator::fillElements() {
cc = nc = fc;
for (int i = 0; i < tmps.length(); i++) {
cc = tmps[i];
if (i > 0) pc = tmps[i - 1];
else pc = fc;
if (i < tmps.length() - 1) nc = tmps[i + 1];
else nc = fc;
if (i > 0)
pc = tmps[i - 1];
else
pc = fc;
if (i < tmps.length() - 1)
nc = tmps[i + 1];
else
nc = fc;
if (cc == '(' || cc == ')' || cc == ',') {
elements[i].set(etOperator, -1);
continue;
}
if (cc == '-' || cc == '+') {
elements[i].set(etOperator, -1);
if (i < tmps.length() - 1) if (elements[i + 1].type == etVariable ||
elements[i + 1].type == etFunction) continue;
if (i < tmps.length() - 1)
if (elements[i + 1].type == etVariable || elements[i + 1].type == etFunction) continue;
if ((pc == '(' || isSign(pc) || i == 0) && i < tmps.length() - 1) {
if (elements[i + 1].type != etOperator) {
cnum = elements[i + 1].num;
elements[i].set(etNumber, cnum);
tmps.replace(i, 1, fc);
///cout << "found sign " << cc << " :" << cnum - 1 << endl;
/// cout << "found sign " << cc << " :" << cnum - 1 << endl;
if (cc == '-' && currentVariables.size_s() >= cnum)
currentVariables[cnum - 1].value = -currentVariables[cnum - 1].value;
continue;
@@ -615,12 +618,12 @@ bool PIEvaluator::fillElements() {
}
/*cout << " ";
for (int i = 0; i < elements.size(); i++) {
switch (elements[i].type) {
case etFunction: cout << "f"; break;
case etNumber: cout << "n"; break;
case etOperator: cout << "o"; break;
case etVariable: cout << "v"; break;
}
switch (elements[i].type) {
case etFunction: cout << "f"; break;
case etNumber: cout << "n"; break;
case etOperator: cout << "o"; break;
case etVariable: cout << "v"; break;
}
}
cout << endl; */
return false;
@@ -633,22 +636,26 @@ bool PIEvaluator::setSignes() {
PIString tmps = currentString;
for (int i = 0; i < tmps.length() - 1; i++) {
needInsert = 0;
ni = i + 1;
ni = i + 1;
if (i > 0) pi = i - 1;
fc = tmps[i].toLower();
sc = tmps[ni].toLower();
pc = tmps[pi].toLower();
if (fc == ',' || sc == ',') continue;
if (elements[i].type == etOperator && elements[ni].type == etOperator) continue;
if (fc == ')' && (elements[ni].type == etNumber || elements[ni].type == etVariable || elements[ni].type == etFunction)) needInsert = 1;
if (fc == ')' && (elements[ni].type == etNumber || elements[ni].type == etVariable || elements[ni].type == etFunction))
needInsert = 1;
if (sc == '(' && (elements[i].type == etNumber || elements[i].type == etVariable)) needInsert = 1;
if (elements[i].type == etNumber && elements[ni].type == etNumber && elements[i].num != elements[ni].num) needInsert = 1;
if (elements[i].type == etVariable && elements[ni].type == etVariable && elements[i].num != elements[ni].num) needInsert = 1;
if ((elements[i].type == etNumber && elements[ni].type == etVariable) || (elements[i].type == etVariable && elements[ni].type == etNumber)) needInsert = 1;
if ((elements[i].type == etNumber && elements[ni].type == etVariable) ||
(elements[i].type == etVariable && elements[ni].type == etNumber))
needInsert = 1;
if ((elements[i].type == etNumber || elements[i].type == etVariable) && elements[ni].type == etFunction) needInsert = 1;
if (elements[i].type == etFunction && elements[ni].type == etFunction && elements[i].num != elements[ni].num) needInsert = 2;
if (elements[i].type == etFunction && elements[ni].type != etFunction && sc != '(') needInsert = 2;
if (elements[pi].type == etOperator && (elements[ni].type == etFunction || elements[ni].type == etVariable) && fc == '-') needInsert = 3;
if (elements[pi].type == etOperator && (elements[ni].type == etFunction || elements[ni].type == etVariable) && fc == '-')
needInsert = 3;
switch (needInsert) {
case 1:
currentString.insert(ni + inserted, '*');
@@ -677,7 +684,8 @@ void PIEvaluator::convert() {
j++;
}
currentString.replace(i, j - i, ' ');
for (int k = i + 1; k < j; k++) elements.remove(i);
for (int k = i + 1; k < j; k++)
elements.remove(i);
}
for (int i = 0; i < currentString.length(); i++) {
pe = elements[i];
@@ -689,7 +697,8 @@ void PIEvaluator::convert() {
j++;
}
currentString.replace(i, j - i, ' ');
for (int k = i + 1; k < j; k++) elements.remove(i);
for (int k = i + 1; k < j; k++)
elements.remove(i);
}
for (int i = 0; i < currentString.length(); i++) {
pe = elements[i];
@@ -701,22 +710,22 @@ void PIEvaluator::convert() {
j++;
}
currentString.replace(i, j - i, ' ');
for (int k = i + 1; k < j; k++) elements.remove(i);
for (int k = i + 1; k < j; k++)
elements.remove(i);
}
/*cout << " ";
for (int i = 0; i < elements.size(); i++) {
switch (elements[i].type) {
case etFunction: cout << "f"; break;
case etNumber: cout << "n"; break;
case etOperator: cout << "o"; break;
case etVariable: cout << "v"; break;
}
switch (elements[i].type) {
case etFunction: cout << "f"; break;
case etNumber: cout << "n"; break;
case etOperator: cout << "o"; break;
case etVariable: cout << "v"; break;
}
}
cout << endl; */
}
PIString PIEvaluator::preprocess(const PIString & string) {
PIString ret;
int lind;
@@ -724,24 +733,24 @@ PIString PIEvaluator::preprocess(const PIString & string) {
convert();
instructions.clear();
variables = currentVariables;
lind = parse(currentString);
lind = parse(currentString);
if (instructions.size() == 0) {
variables.push_back(Variable());
instructions.push_back(Instruction(oNone, PIVector<short>(1, lind), -variables.size_s()));
}
/*cout << endl << "variables:" << endl;
for (int i = 0; i < variables.size(); i++)
cout << i << " value = " << variables[i].value << endl;
cout << i << " value = " << variables[i].value << endl;
cout << endl << "instructions:" << endl;
for (int i = 0; i < instructions.size(); i++) {
cout << i << endl;
cout << " operation " << instructions[i].operation << endl;
cout << " operators: ";
for (int j = 0; j < instructions[i].operators.size(); j++)
cout << instructions[i].operators[j] << "; ";
cout << endl << " function " << instructions[i].function << endl;
cout << " out " << instructions[i].out << endl;
cout << i << endl;
cout << " operation " << instructions[i].operation << endl;
cout << " operators: ";
for (int j = 0; j < instructions[i].operators.size(); j++)
cout << instructions[i].operators[j] << "; ";
cout << endl << " function " << instructions[i].function << endl;
cout << " out " << instructions[i].out << endl;
} */
makeOutput(ret);
return ret;
@@ -757,17 +766,13 @@ int PIEvaluator::parse(const PIString & string, int offset) {
PIVector<short> args, atmp;
PIVector<Operation> opers;
//cout << " "; for (int i = 0; i < slen; i++) cout << preproc->elements[i + offset].type; cout << endl;
// cout << " "; for (int i = 0; i < slen; i++) cout << preproc->elements[i + offset].type; cout << endl;
for (int i = 0; i < slen; i++) {
ce = elements[i + offset];
cc = string[i];
switch (ce.type) {
case etNumber:
args.push_back(ce.var_num);
continue;
case etVariable:
args.push_back(ce.var_num);
continue;
case etNumber: args.push_back(ce.var_num); continue;
case etVariable: args.push_back(ce.var_num); continue;
case etFunction:
i++;
cfunc = content.function(ce.var_num);
@@ -782,21 +787,23 @@ int PIEvaluator::parse(const PIString & string, int offset) {
case ')':
bcnt--;
if (bcnt == 0) {
///qDebug() << "arument: " << carg;
/// qDebug() << "arument: " << carg;
atmp.push_back(parse(carg, k + offset - carg.length()));
k++;
carg.clear();
if (atmp.size_s() > 0) if (atmp.back() < 0 && farg > 0) farg = atmp.back();
if (atmp.size_s() > 0)
if (atmp.back() < 0 && farg > 0) farg = atmp.back();
continue;
}
break;
case ',':
if (bcnt == 1) {
///qDebug() << "arument: " << carg;
/// qDebug() << "arument: " << carg;
atmp.push_back(parse(carg, k + offset - carg.length()));
k++;
carg.clear();
if (atmp.size_s() > 0) if (atmp.back() < 0 && farg > 0) farg = atmp.back();
if (atmp.size_s() > 0)
if (atmp.back() < 0 && farg > 0) farg = atmp.back();
continue;
}
break;
@@ -811,7 +818,7 @@ int PIEvaluator::parse(const PIString & string, int offset) {
}
instructions.push_back(Instruction(oFunction, atmp, farg, ce.var_num));
args.push_back(farg);
//for (int i = 0; i < args.size_s(); i++) cout << preproc->currentVariables[-args[i]].value << endl;
// for (int i = 0; i < args.size_s(); i++) cout << preproc->currentVariables[-args[i]].value << endl;
continue;
case etOperator:
if (cc == '(') {
@@ -820,20 +827,62 @@ int PIEvaluator::parse(const PIString & string, int offset) {
i += sbrackets.length() + 1;
continue;
}
if (cc == '+') {opers.push_back(oAdd); continue;}
if (cc == '-') {opers.push_back(oSubtract); continue;}
if (cc == '*') {opers.push_back(oMultiply); continue;}
if (cc == '/') {opers.push_back(oDivide); continue;}
if (cc == '%') {opers.push_back(oResidue); continue;}
if (cc == '^') {opers.push_back(oPower); continue;}
if (cc == '=') {opers.push_back(oEqual); continue;}
if (cc == ':') {opers.push_back(oNotEqual); continue;}
if (cc == '}') {opers.push_back(oGreaterEqual); continue;}
if (cc == '{') {opers.push_back(oSmallerEqual); continue;}
if (cc == '>') {opers.push_back(oGreater); continue;}
if (cc == '<') {opers.push_back(oSmaller); continue;}
if (cc == '&') {opers.push_back(oAnd); continue;}
if (cc == '|') {opers.push_back(oOr); continue;}
if (cc == '+') {
opers.push_back(oAdd);
continue;
}
if (cc == '-') {
opers.push_back(oSubtract);
continue;
}
if (cc == '*') {
opers.push_back(oMultiply);
continue;
}
if (cc == '/') {
opers.push_back(oDivide);
continue;
}
if (cc == '%') {
opers.push_back(oResidue);
continue;
}
if (cc == '^') {
opers.push_back(oPower);
continue;
}
if (cc == '=') {
opers.push_back(oEqual);
continue;
}
if (cc == ':') {
opers.push_back(oNotEqual);
continue;
}
if (cc == '}') {
opers.push_back(oGreaterEqual);
continue;
}
if (cc == '{') {
opers.push_back(oSmallerEqual);
continue;
}
if (cc == '>') {
opers.push_back(oGreater);
continue;
}
if (cc == '<') {
opers.push_back(oSmaller);
continue;
}
if (cc == '&') {
opers.push_back(oAnd);
continue;
}
if (cc == '|') {
opers.push_back(oOr);
continue;
}
}
}
/*cout << "stack: " << endl << "args: ";
@@ -841,26 +890,34 @@ int PIEvaluator::parse(const PIString & string, int offset) {
cout << endl << "opers: ";
for (int i = 0; i < opers.size_s(); i++) cout << opers[i] << ", "; */
if (opers.size_s() == 0) {
if (args.size_s() > 0) return args.back();
else return -666;
if (args.size_s() > 0)
return args.back();
else
return -666;
}
int oprior = -1;
PIVector<Operation> opv;
while(1) {
while (1) {
operationsByPriority(++oprior, opv);
if (opv.isEmpty()) break;
for (int j = 0; j < opers.size_s(); j++) {
if (!opv.contains(opers[j])) continue;
atmp.clear();
if (j < args.size_s() && j >= 0) atmp.push_back(args[j]);
else atmp.push_back(-666);
if (j + 1 < args.size_s() && j >= -1) atmp.push_back(args[j + 1]);
else atmp.push_back(-666);
if (j < args.size_s() && j >= 0)
atmp.push_back(args[j]);
else
atmp.push_back(-666);
if (j + 1 < args.size_s() && j >= -1)
atmp.push_back(args[j + 1]);
else
atmp.push_back(-666);
farg = 1;
if (atmp[0] < 0) farg = atmp[0];
if (atmp[0] < 0)
farg = atmp[0];
else {
if (atmp[1] < 0) farg = atmp[1];
if (atmp[1] < 0)
farg = atmp[1];
else {
variables.push_back(Variable());
farg = -variables.size_s();
@@ -876,7 +933,7 @@ int PIEvaluator::parse(const PIString & string, int offset) {
}
}
return instructions.back().out;
//cout << endl;
// cout << endl;
}
@@ -889,13 +946,13 @@ bool PIEvaluator::check() {
}
for (int i = 0; i < instructions.size_s(); i++) {
error = false;
ci = instructions[i];
ci = instructions[i];
Function cf;
int fac, gac;
switch (ci.operation) {
case oNone: break;
case oFunction:
cf = content.function(ci.function);
cf = content.function(ci.function);
fac = cf.arguments;
gac = ci.operators.size_s();
for (int j = 0; j < ci.operators.size_s(); j++) {
@@ -906,9 +963,8 @@ bool PIEvaluator::check() {
}
if (fac > 0) {
if (gac != fac) {
lastError = PIStringAscii("Invalid arguments count for function \"") + cf.identifier +
PIStringAscii("\", expected ") + PIString::fromNumber(fac) + PIStringAscii(" but ") +
PIString::fromNumber(gac) + PIStringAscii(" given");
lastError = PIStringAscii("Invalid arguments count for function \"") + cf.identifier + PIStringAscii("\", expected ") +
PIString::fromNumber(fac) + PIStringAscii(" but ") + PIString::fromNumber(gac) + PIStringAscii(" given");
return false;
}
if (error) {
@@ -919,8 +975,8 @@ bool PIEvaluator::check() {
if (fac < 0) {
if (gac < -fac) {
lastError = PIStringAscii("Invalid arguments count for function \"") + cf.identifier +
PIStringAscii("\", expected at least ") + PIString::fromNumber(-fac) + PIStringAscii(" but ") +
PIString::fromNumber(gac) + PIStringAscii(" given");
PIStringAscii("\", expected at least ") + PIString::fromNumber(-fac) + PIStringAscii(" but ") +
PIString::fromNumber(gac) + PIStringAscii(" given");
return false;
}
if (error) {
@@ -969,20 +1025,20 @@ PIString PIEvaluator::inBrackets(const PIString & string) {
PIString PIEvaluator::operationChar(const Operation & operation) {
switch (operation) {
case oAdd : return PIStringAscii("+");
case oSubtract : return PIStringAscii("-");
case oMultiply : return PIStringAscii("*");
case oDivide : return PIStringAscii("/");
case oPower : return PIStringAscii("^");
case oResidue : return PIStringAscii("%");
case oEqual : return PIStringAscii("=");
case oNotEqual : return PIString::fromUTF8("");
case oAdd: return PIStringAscii("+");
case oSubtract: return PIStringAscii("-");
case oMultiply: return PIStringAscii("*");
case oDivide: return PIStringAscii("/");
case oPower: return PIStringAscii("^");
case oResidue: return PIStringAscii("%");
case oEqual: return PIStringAscii("=");
case oNotEqual: return PIString::fromUTF8("");
case oGreaterEqual: return PIString::fromUTF8("");
case oSmallerEqual: return PIString::fromUTF8("");
case oGreater : return PIStringAscii(">");
case oSmaller : return PIStringAscii("<");
case oAnd : return PIString::fromUTF8("");
case oOr : return PIString::fromUTF8("");
case oGreater: return PIStringAscii(">");
case oSmaller: return PIStringAscii("<");
case oAnd: return PIString::fromUTF8("");
case oOr: return PIString::fromUTF8("");
default: break;
}
return PIStringAscii("???");
@@ -1016,119 +1072,63 @@ inline void PIEvaluator::execFunction(const Instruction & ci) {
int oi = -ci.out - 1;
complexd tmp, stmp, ttmp;
switch (cfunc.type) {
case bfSin:
tmpvars[oi].value = sin(value(ci.operators[0]));
break;
case bfCos:
tmpvars[oi].value = cos(value(ci.operators[0]));
break;
case bfTg:
tmpvars[oi].value = tan(value(ci.operators[0]));
break;
case bfSin: tmpvars[oi].value = sin(value(ci.operators[0])); break;
case bfCos: tmpvars[oi].value = cos(value(ci.operators[0])); break;
case bfTg: tmpvars[oi].value = tan(value(ci.operators[0])); break;
case bfCtg:
tmp = tan(value(ci.operators[0]));
if (tmp == complexd_0) tmpvars[oi].value = 0.;
else tmpvars[oi].value = complexd_1 / tmp;
break;
case bfArcsin:
tmpvars[oi].value = asinc(value(ci.operators[0]));
break;
case bfArccos:
tmpvars[oi].value = acosc(value(ci.operators[0]));
break;
case bfArctg:
tmpvars[oi].value = atanc(value(ci.operators[0]));
break;
case bfArcctg:
tmpvars[oi].value = atanc(-value(ci.operators[0])) + M_PI_2;
break;
case bfSh:
tmpvars[oi].value = sinh(value(ci.operators[0]));
break;
case bfCh:
tmpvars[oi].value = cosh(value(ci.operators[0]));
break;
case bfTh:
tmpvars[oi].value = tanh(value(ci.operators[0]));
if (tmp == complexd_0)
tmpvars[oi].value = 0.;
else
tmpvars[oi].value = complexd_1 / tmp;
break;
case bfArcsin: tmpvars[oi].value = asinc(value(ci.operators[0])); break;
case bfArccos: tmpvars[oi].value = acosc(value(ci.operators[0])); break;
case bfArctg: tmpvars[oi].value = atanc(value(ci.operators[0])); break;
case bfArcctg: tmpvars[oi].value = atanc(-value(ci.operators[0])) + M_PI_2; break;
case bfSh: tmpvars[oi].value = sinh(value(ci.operators[0])); break;
case bfCh: tmpvars[oi].value = cosh(value(ci.operators[0])); break;
case bfTh: tmpvars[oi].value = tanh(value(ci.operators[0])); break;
case bfCth:
tmp = tanh(value(ci.operators[0]));
if (tmp == complexd_0) tmpvars[oi].value = 0.;
else tmpvars[oi].value = complexd_1 / tmp;
break;
case bfAbs:
tmpvars[oi].value = abs(value(ci.operators[0]));
break;
case bfSqrt:
tmpvars[oi].value = sqrt(value(ci.operators[0]));
break;
case bfSqr:
tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[0]);
break;
case bfExp:
tmpvars[oi].value = exp(value(ci.operators[0]));
break;
case bfPow:
tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1]));
break;
case bfLn:
tmpvars[oi].value = log(value(ci.operators[0]));
break;
case bfLg:
tmpvars[oi].value = log10(value(ci.operators[0]));
if (tmp == complexd_0)
tmpvars[oi].value = 0.;
else
tmpvars[oi].value = complexd_1 / tmp;
break;
case bfAbs: tmpvars[oi].value = abs(value(ci.operators[0])); break;
case bfSqrt: tmpvars[oi].value = sqrt(value(ci.operators[0])); break;
case bfSqr: tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[0]); break;
case bfExp: tmpvars[oi].value = exp(value(ci.operators[0])); break;
case bfPow: tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1])); break;
case bfLn: tmpvars[oi].value = log(value(ci.operators[0])); break;
case bfLg: tmpvars[oi].value = log10(value(ci.operators[0])); break;
case bfLog:
tmp = log(value(ci.operators[1]));
if (tmp == complexd_0) tmpvars[oi].value = 0.;
else tmpvars[oi].value = log(value(ci.operators[0])) / tmp;
break;
case bfRe:
tmpvars[oi].value = value(ci.operators[0]).real();
break;
case bfIm:
tmpvars[oi].value = value(ci.operators[0]).imag();
break;
case bfArg:
tmpvars[oi].value = arg(value(ci.operators[0]));
break;
case bfLen:
tmpvars[oi].value = abs(value(ci.operators[0]));
break;
case bfConj:
tmpvars[oi].value = conj(value(ci.operators[0]));
break;
case bfSign:
tmpvars[oi].value = value(ci.operators[0]).real() >= 0. ? complexd_1 : -complexd_1;
break;
case bfRad:
tmpvars[oi].value = value(ci.operators[0]) * complexd(deg2rad, 0.);
break;
case bfDeg:
tmpvars[oi].value = value(ci.operators[0]) * complexd(rad2deg, 0.);
break;
case bfJ0:
tmpvars[oi].value = piJ0(value(ci.operators[0]).real());
break;
case bfJ1:
tmpvars[oi].value = piJ1(value(ci.operators[0]).real());
break;
case bfJN:
tmpvars[oi].value = piJn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real());
break;
case bfY0:
tmpvars[oi].value = piY0(value(ci.operators[0]).real());
break;
case bfY1:
tmpvars[oi].value = piY1(value(ci.operators[0]).real());
break;
case bfYN:
tmpvars[oi].value = piYn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real());
if (tmp == complexd_0)
tmpvars[oi].value = 0.;
else
tmpvars[oi].value = log(value(ci.operators[0])) / tmp;
break;
case bfRe: tmpvars[oi].value = value(ci.operators[0]).real(); break;
case bfIm: tmpvars[oi].value = value(ci.operators[0]).imag(); break;
case bfArg: tmpvars[oi].value = arg(value(ci.operators[0])); break;
case bfLen: tmpvars[oi].value = abs(value(ci.operators[0])); break;
case bfConj: tmpvars[oi].value = conj(value(ci.operators[0])); break;
case bfSign: tmpvars[oi].value = value(ci.operators[0]).real() >= 0. ? complexd_1 : -complexd_1; break;
case bfRad: tmpvars[oi].value = value(ci.operators[0]) * complexd(deg2rad, 0.); break;
case bfDeg: tmpvars[oi].value = value(ci.operators[0]) * complexd(rad2deg, 0.); break;
case bfJ0: tmpvars[oi].value = piJ0(value(ci.operators[0]).real()); break;
case bfJ1: tmpvars[oi].value = piJ1(value(ci.operators[0]).real()); break;
case bfJN: tmpvars[oi].value = piJn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); break;
case bfY0: tmpvars[oi].value = piY0(value(ci.operators[0]).real()); break;
case bfY1: tmpvars[oi].value = piY1(value(ci.operators[0]).real()); break;
case bfYN: tmpvars[oi].value = piYn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); break;
case bfMin:
tmp = value(ci.operators[0]);
for (int i = 1; i < ci.operators.size_s(); ++i) {
stmp = value(ci.operators[i]);
tmp = complexd(piMind(tmp.real(), stmp.real()), piMind(tmp.imag(), stmp.imag()));
tmp = complexd(piMind(tmp.real(), stmp.real()), piMind(tmp.imag(), stmp.imag()));
}
tmpvars[oi].value = tmp;
break;
@@ -1136,37 +1136,29 @@ inline void PIEvaluator::execFunction(const Instruction & ci) {
tmp = value(ci.operators[0]);
for (int i = 1; i < ci.operators.size_s(); ++i) {
stmp = value(ci.operators[i]);
tmp = complexd(piMaxd(tmp.real(), stmp.real()), piMaxd(tmp.imag(), stmp.imag()));
tmp = complexd(piMaxd(tmp.real(), stmp.real()), piMaxd(tmp.imag(), stmp.imag()));
}
tmpvars[oi].value = tmp;
break;
case bfClamp:
tmp = value(ci.operators[0]);
stmp = value(ci.operators[1]);
ttmp = value(ci.operators[2]);
tmp = value(ci.operators[0]);
stmp = value(ci.operators[1]);
ttmp = value(ci.operators[2]);
tmpvars[oi].value = complexd(piClampd(tmp.real(), stmp.real(), ttmp.real()), piClampd(tmp.imag(), stmp.imag(), ttmp.imag()));
break;
case bfStep:
tmpvars[oi].value = complexd(value(ci.operators[0]).real() >= value(ci.operators[1]).real() ? complexld_1 : complexld_0);
break;
case bfMix:
tmp = value(ci.operators[0]);
stmp = value(ci.operators[1]);
ttmp = value(ci.operators[2]);
tmp = value(ci.operators[0]);
stmp = value(ci.operators[1]);
ttmp = value(ci.operators[2]);
tmpvars[oi].value = stmp.real() * (1. - tmp.real()) + ttmp.real() * tmp.real();
break;
case bfDefined:
tmpvars[oi].value = value(ci.operators[0]).real() > 0. ? complexd_1 : complexd_0;
break;
case bfRandom:
tmpvars[oi].value = value(ci.operators[0]) + randomd() * value(ci.operators[1]);
break;
case bfRandomn:
tmpvars[oi].value = randomn(value(ci.operators[0]).real(), value(ci.operators[1]).real());
break;
case bfRound:
tmpvars[oi].value = piRoundd(value(ci.operators[0]).real());
break;
case bfDefined: tmpvars[oi].value = value(ci.operators[0]).real() > 0. ? complexd_1 : complexd_0; break;
case bfRandom: tmpvars[oi].value = value(ci.operators[0]) + randomd() * value(ci.operators[1]); break;
case bfRandomn: tmpvars[oi].value = randomn(value(ci.operators[0]).real(), value(ci.operators[1]).real()); break;
case bfRound: tmpvars[oi].value = piRoundd(value(ci.operators[0]).real()); break;
default: break;
}
}
@@ -1175,74 +1167,45 @@ inline void PIEvaluator::execFunction(const Instruction & ci) {
inline bool PIEvaluator::execInstructions() {
int oi;
tmpvars = variables;
//cout << "var count " << tmpvars.size_s() << endl;
// cout << "var count " << tmpvars.size_s() << endl;
for (int i = 0; i < instructions.size_s(); i++) {
const Instruction & ci(instructions[i]);
oi = -ci.out - 1;
//cout << value(ci.operators[0]) << operationChar(ci.operation) << value(ci.operators[1]) << ", " << oi << endl;
// cout << value(ci.operators[0]) << operationChar(ci.operation) << value(ci.operators[1]) << ", " << oi << endl;
switch (ci.operation) {
case oAdd:
tmpvars[oi].value = value(ci.operators[0]) + value(ci.operators[1]);
break;
case oSubtract:
tmpvars[oi].value = value(ci.operators[0]) - value(ci.operators[1]);
break;
case oMultiply:
tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]);
break;
case oAdd: tmpvars[oi].value = value(ci.operators[0]) + value(ci.operators[1]); break;
case oSubtract: tmpvars[oi].value = value(ci.operators[0]) - value(ci.operators[1]); break;
case oMultiply: tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]); break;
case oDivide: {
complexd tmp = value(ci.operators[1]);
if (tmp == complexd(0., 0.)) tmpvars[oi].value = 0.;
else tmpvars[oi].value = value(ci.operators[0]) / tmp;
} break;
case oResidue:
tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1]));
break;
case oPower:
tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1]));
break;
case oEqual:
tmpvars[oi].value = value(ci.operators[0]) == value(ci.operators[1]);
break;
case oNotEqual:
tmpvars[oi].value = value(ci.operators[0]) != value(ci.operators[1]);
break;
case oGreaterEqual:
tmpvars[oi].value = value(ci.operators[0]).real() >= value(ci.operators[1]).real();
break;
case oSmallerEqual:
tmpvars[oi].value = value(ci.operators[0]).real() <= value(ci.operators[1]).real();
break;
case oGreater:
tmpvars[oi].value = value(ci.operators[0]).real() > value(ci.operators[1]).real();
break;
case oSmaller:
tmpvars[oi].value = value(ci.operators[0]).real() < value(ci.operators[1]).real();
break;
case oAnd:
tmpvars[oi].value = value(ci.operators[0]).real() > 0. && value(ci.operators[1]).real() > 0.;
break;
case oOr:
tmpvars[oi].value = value(ci.operators[0]).real() > 0. || value(ci.operators[1]).real() > 0.;
break;
case oFunction:
execFunction(ci);
break;
case oNone:
tmpvars[oi].value = value(ci.operators[0]);
break;
if (tmp == complexd(0., 0.))
tmpvars[oi].value = 0.;
else
tmpvars[oi].value = value(ci.operators[0]) / tmp;
} break;
case oResidue: tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1])); break;
case oPower: tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1])); break;
case oEqual: tmpvars[oi].value = value(ci.operators[0]) == value(ci.operators[1]); break;
case oNotEqual: tmpvars[oi].value = value(ci.operators[0]) != value(ci.operators[1]); break;
case oGreaterEqual: tmpvars[oi].value = value(ci.operators[0]).real() >= value(ci.operators[1]).real(); break;
case oSmallerEqual: tmpvars[oi].value = value(ci.operators[0]).real() <= value(ci.operators[1]).real(); break;
case oGreater: tmpvars[oi].value = value(ci.operators[0]).real() > value(ci.operators[1]).real(); break;
case oSmaller: tmpvars[oi].value = value(ci.operators[0]).real() < value(ci.operators[1]).real(); break;
case oAnd: tmpvars[oi].value = value(ci.operators[0]).real() > 0. && value(ci.operators[1]).real() > 0.; break;
case oOr: tmpvars[oi].value = value(ci.operators[0]).real() > 0. || value(ci.operators[1]).real() > 0.; break;
case oFunction: execFunction(ci); break;
case oNone: tmpvars[oi].value = value(ci.operators[0]); break;
default: break;
}
}
if (!instructions.isEmpty())
out = value(instructions.back().out);
if (!instructions.isEmpty()) out = value(instructions.back().out);
return true;
}
bool PIEvaluator::check(const PIString & string) {
currentString = preprocess(string);
correct = check();
correct = check();
if (!correct) {
instructions.clear();
return false;

View File

@@ -5,120 +5,208 @@
* \~russian Вычислитель математических выражений
*/
/*
PIP - Platform Independent Primitives
Evaluator designed for stream calculations
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Evaluator designed for stream calculations
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIEVALUATOR_H
#define PIEVALUATOR_H
#include "pistringlist.h"
#include "pimathcomplex.h"
#include "pistringlist.h"
namespace PIEvaluatorTypes {
typedef std::function<complexd(void * , int, complexd * )> FuncHanlder;
typedef std::function<complexd(void *, int, complexd *)> FuncHanlder;
enum eType {etNumber, etOperator, etVariable, etFunction};
enum Operation {oNone, oAdd, oSubtract, oMultiply, oDivide, oResidue, oPower,
oEqual, oNotEqual, oGreater, oSmaller, oGreaterEqual, oSmallerEqual,
oAnd, oOr, oFunction
};
enum BaseFunctions {bfUnknown, bfSin, bfCos, bfTg, bfCtg,
bfArcsin, bfArccos, bfArctg, bfArcctg,
bfExp, bfRandom, bfRandomn,
bfSh, bfCh, bfTh, bfCth,
bfSqrt, bfSqr, bfPow, bfAbs,
bfLn, bfLg, bfLog, bfSign,
bfIm, bfRe, bfArg, bfLen, bfConj,
bfRad, bfDeg, bfJ0, bfJ1, bfJN,
bfY0, bfY1, bfYN, bfMin, bfMax,
bfClamp, bfStep, bfMix, bfDefined,
bfRound,
bfCustom = 0xFFFF
};
enum eType {
etNumber,
etOperator,
etVariable,
etFunction
};
enum Operation {
oNone,
oAdd,
oSubtract,
oMultiply,
oDivide,
oResidue,
oPower,
oEqual,
oNotEqual,
oGreater,
oSmaller,
oGreaterEqual,
oSmallerEqual,
oAnd,
oOr,
oFunction
};
enum BaseFunctions {
bfUnknown,
bfSin,
bfCos,
bfTg,
bfCtg,
bfArcsin,
bfArccos,
bfArctg,
bfArcctg,
bfExp,
bfRandom,
bfRandomn,
bfSh,
bfCh,
bfTh,
bfCth,
bfSqrt,
bfSqr,
bfPow,
bfAbs,
bfLn,
bfLg,
bfLog,
bfSign,
bfIm,
bfRe,
bfArg,
bfLen,
bfConj,
bfRad,
bfDeg,
bfJ0,
bfJ1,
bfJN,
bfY0,
bfY1,
bfYN,
bfMin,
bfMax,
bfClamp,
bfStep,
bfMix,
bfDefined,
bfRound,
bfCustom = 0xFFFF
};
struct PIP_EXPORT Instruction {
Instruction() {out = -1; function = -1; operation = oNone;}
Instruction(Operation oper, PIVector<short> opers, short out_ind, short func = -1) {
operation = oper; operators = opers; out = out_ind; function = func;}
Operation operation;
short out;
short function;
PIVector<short> operators;
};
struct PIP_EXPORT Element {
Element() {num = 0; var_num = -1; type = etNumber;}
Element(eType new_type, short new_num, short new_var_num = -1) {set(new_type, new_num, new_var_num);}
void set(eType new_type, short new_num, short new_var_num = -1) {type = new_type; num = new_num; var_num = new_var_num;}
eType type;
short num;
short var_num;
};
struct PIP_EXPORT Function {
Function() {arguments = 0; type = bfUnknown; handler = nullptr;}
Function(const PIString & name, short args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype; handler = nullptr;}
Function(const PIString & name, short args, FuncHanlder h) {identifier = name; arguments = args; type = bfCustom; handler = h;}
PIString identifier;
BaseFunctions type;
FuncHanlder handler;
short arguments;
};
struct PIP_EXPORT Variable {
Variable() {value = 0.;}
Variable(const PIString & var_name, complexd val) {name = var_name; value = val;}
PIString name;
complexd value;
};
}
struct PIP_EXPORT Instruction {
Instruction() {
out = -1;
function = -1;
operation = oNone;
}
Instruction(Operation oper, PIVector<short> opers, short out_ind, short func = -1) {
operation = oper;
operators = opers;
out = out_ind;
function = func;
}
Operation operation;
short out;
short function;
PIVector<short> operators;
};
struct PIP_EXPORT Element {
Element() {
num = 0;
var_num = -1;
type = etNumber;
}
Element(eType new_type, short new_num, short new_var_num = -1) { set(new_type, new_num, new_var_num); }
void set(eType new_type, short new_num, short new_var_num = -1) {
type = new_type;
num = new_num;
var_num = new_var_num;
}
eType type;
short num;
short var_num;
};
struct PIP_EXPORT Function {
Function() {
arguments = 0;
type = bfUnknown;
handler = nullptr;
}
Function(const PIString & name, short args, BaseFunctions ftype) {
identifier = name;
arguments = args;
type = ftype;
handler = nullptr;
}
Function(const PIString & name, short args, FuncHanlder h) {
identifier = name;
arguments = args;
type = bfCustom;
handler = h;
}
PIString identifier;
BaseFunctions type;
FuncHanlder handler;
short arguments;
};
struct PIP_EXPORT Variable {
Variable() { value = 0.; }
Variable(const PIString & var_name, complexd val) {
name = var_name;
value = val;
}
PIString name;
complexd value;
};
} // namespace PIEvaluatorTypes
/*
≠ :
≥ }
≤ {
⋀ &
|
≠ :
≥ }
≤ {
⋀ &
|
*/
class PIP_EXPORT PIEvaluatorContent
{
class PIP_EXPORT PIEvaluatorContent {
friend class PIEvaluator;
BINARY_STREAM_FRIEND(PIEvaluatorContent);
public:
PIEvaluatorContent();
~PIEvaluatorContent() {;}
~PIEvaluatorContent() { ; }
void addFunction(const PIString & name, int args = 1);
int addVariable(const PIString & name, const complexd & val = 0.);
int addVariable(const PIString & name, const complexd & val = 0.);
void addCustomFunction(const PIString & name, int args_count, PIEvaluatorTypes::FuncHanlder func);
int functionsCount() const {return functions.size();}
int variablesCount() const {return variables.size();}
int functionsCount() const { return functions.size(); }
int variablesCount() const { return variables.size(); }
int customVariablesCount() const;
int findFunction(const PIString & name) const;
int findVariable(const PIString & var_name) const;
PIEvaluatorTypes::Function function(int index);
PIEvaluatorTypes::Variable variable(int index);
PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(name));}
PIEvaluatorTypes::Variable variable(const PIString & name) {return variable(findVariable(name));}
PIEvaluatorTypes::Function function(const PIString & name) { return function(findFunction(name)); }
PIEvaluatorTypes::Variable variable(const PIString & name) { return variable(findVariable(name)); }
PIEvaluatorTypes::Variable customVariable(int index);
bool setVariableValue(int index, complexd new_value);
bool setVariableValue(const PIString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);}
bool setVariableValue(const PIString & var_name, const complexd & new_value) {
return setVariableValue(findVariable(var_name), new_value);
}
bool setVariableName(int index, const PIString & new_name);
bool setVariableName(const PIString & var_name, const PIString & new_name) {return setVariableName(findVariable(var_name), new_name);}
bool setVariableName(const PIString & var_name, const PIString & new_name) { return setVariableName(findVariable(var_name), new_name); }
void clearCustomVariables();
PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name);
@@ -128,32 +216,32 @@ private:
PIVector<PIEvaluatorTypes::Function> functions;
PIVector<PIEvaluatorTypes::Variable> variables;
int cv_count;
};
class PIP_EXPORT PIEvaluator
{
class PIP_EXPORT PIEvaluator {
public:
//! Constructs an empty evaluator
PIEvaluator() {correct = false; data_ = 0;}
PIEvaluator() {
correct = false;
data_ = 0;
}
~PIEvaluator() {;}
~PIEvaluator() { ; }
//! Returns custom data
void * data() {return data_;}
void * data() { return data_; }
//! Set custom data to "_data"
void setData(void * _data) {data_ = _data;}
void setData(void * _data) { data_ = _data; }
//! Check mathematical expression and parse it to list of instructions
bool check(const PIString & string);
//! Returns true if expression was checked succesfully
bool isCorrect() const {return correct;}
bool isCorrect() const { return correct; }
//! Set variable value with name "name" to value "value". Add variable if it doesn`t exists
int setVariable(const PIString & name, complexd value = complexd(0.));
@@ -165,25 +253,25 @@ public:
complexd evaluate();
//! Remove all manually added variables
void clearCustomVariables() {content.clearCustomVariables();}
void clearCustomVariables() { content.clearCustomVariables(); }
//! Returns index of variable with name "name"
int variableIndex(const PIString & name) const {return content.findVariable(name);}
int variableIndex(const PIString & name) const { return content.findVariable(name); }
//! Returns all unknown variables founded in last expression passed to \a check() function
const PIStringList & unknownVariables() const {return unknownVars;}
const PIStringList & unknownVariables() const { return unknownVars; }
//! Returns all used variables founded in last expression passed to \a check() function
const PIStringList & usedVariables() const {return usedVars;}
const PIStringList & usedVariables() const { return usedVars; }
//! Returns processed last expression passed to \a check() function
const PIString & expression() const {return currentString;}
const PIString & expression() const { return currentString; }
//! Returns last error description occured in \a check() function
const PIString & error() const {return lastError;}
const PIString & error() const { return lastError; }
//! Returns last result of \a evaluate()
const complexd & lastResult() const {return out;}
const complexd & lastResult() const { return out; }
//! Save to %PIByteArray evaluator state (expression, variables, errors, compiled instructions)
PIByteArray save() const;
@@ -205,13 +293,24 @@ private:
bool fillElements();
bool setSignes();
bool isSign(const PIChar & ch);
PIString inverse(const PIString & string) {int len = string.length(); PIString s; for (int i = 0; i < len; i++) s += string[len - i - 1]; return s;}
PIString inverse(const PIString & string) {
int len = string.length();
PIString s;
for (int i = 0; i < len; i++)
s += string[len - i - 1];
return s;
}
bool check();
bool execInstructions();
PIString inBrackets(const PIString & string);
PIString operationChar(const PIEvaluatorTypes::Operation & operation);
void operationsByPriority(int p, PIVector<PIEvaluatorTypes::Operation> & ret);
complexd value(const int & index) {if (index < 0) return tmpvars[-index - 1].value; else return content.variables[index].value;}
complexd value(const int & index) {
if (index < 0)
return tmpvars[-index - 1].value;
else
return content.variables[index].value;
}
inline complexd residue(const complexd & f, const complexd & s);
inline void execFunction(const PIEvaluatorTypes::Instruction & ci);
@@ -226,19 +325,47 @@ private:
void * data_;
};
inline bool operator ==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);}
inline bool operator !=(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type != e2.type || e1.num != e2.num);}
inline bool operator==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {
return (e1.type == e2.type && e1.num == e2.num);
}
inline bool operator!=(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {
return (e1.type != e2.type || e1.num != e2.num);
}
BINARY_STREAM_WRITE(PIEvaluatorTypes::Instruction) {s << PIMemoryBlock(&v, sizeof(v) - sizeof(v.operators)) << v.operators; return s;}
BINARY_STREAM_READ (PIEvaluatorTypes::Instruction) {s >> PIMemoryBlock(&v, sizeof(v) - sizeof(v.operators)) >> v.operators; return s;}
BINARY_STREAM_WRITE(PIEvaluatorTypes::Instruction) {
s << PIMemoryBlock(&v, sizeof(v) - sizeof(v.operators)) << v.operators;
return s;
}
BINARY_STREAM_READ(PIEvaluatorTypes::Instruction) {
s >> PIMemoryBlock(&v, sizeof(v) - sizeof(v.operators)) >> v.operators;
return s;
}
BINARY_STREAM_WRITE(PIEvaluatorTypes::Element) {s << createMemoryBlock(&v); return s;}
BINARY_STREAM_READ (PIEvaluatorTypes::Element) {s >> createMemoryBlock(&v); return s;}
BINARY_STREAM_WRITE(PIEvaluatorTypes::Element) {
s << createMemoryBlock(&v);
return s;
}
BINARY_STREAM_READ(PIEvaluatorTypes::Element) {
s >> createMemoryBlock(&v);
return s;
}
BINARY_STREAM_WRITE(PIEvaluatorTypes::Variable) {s << v.name << v.value; return s;}
BINARY_STREAM_READ (PIEvaluatorTypes::Variable) {s >> v.name >> v.value; return s;}
BINARY_STREAM_WRITE(PIEvaluatorTypes::Variable) {
s << v.name << v.value;
return s;
}
BINARY_STREAM_READ(PIEvaluatorTypes::Variable) {
s >> v.name >> v.value;
return s;
}
BINARY_STREAM_WRITE(PIEvaluatorContent) {s << v.variables << v.cv_count; return s;}
BINARY_STREAM_READ (PIEvaluatorContent) {s >> v.variables >> v.cv_count; return s;}
BINARY_STREAM_WRITE(PIEvaluatorContent) {
s << v.variables << v.cv_count;
return s;
}
BINARY_STREAM_READ(PIEvaluatorContent) {
s >> v.variables >> v.cv_count;
return s;
}
#endif // PIEVALUATOR_H

View File

@@ -1,28 +1,27 @@
/*
PIP - Platform Independent Primitives
Class for FFT, IFFT and Hilbert transformations
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Class for FFT, IFFT and Hilbert transformations
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pifft.h"
#ifndef MICRO_PIP
PIFFT_double::PIFFT_double() {
}
PIFFT_double::PIFFT_double() {}
PIVector<complexd> * PIFFT_double::calcFFT(const PIVector<complexd> & val) {
@@ -45,8 +44,10 @@ PIVector<complexd> * PIFFT_double::calcHilbert(const PIVector<double> & val) {
result.clear();
if (val.size_s() < 4) return &result;
fftc1r(val, val.size());
for (uint i = 0; i < result.size() / 2; i++) result[i] = result[i] * 2.;
for (uint i = result.size() / 2; i < result.size(); i++) result[i] = 0;
for (uint i = 0; i < result.size() / 2; i++)
result[i] = result[i] * 2.;
for (uint i = result.size() / 2; i < result.size(); i++)
result[i] = 0;
fftc1dinv(result, result.size());
return &result;
}
@@ -65,7 +66,7 @@ PIVector<double> PIFFT_double::getAmplitude() const {
ret.resize(result.size());
double tmp;
for (uint i = 0; i < result.size(); i++) {
tmp = sqrt(result[i].real() * result[i].real() + result[i].imag() * result[i].imag());
tmp = sqrt(result[i].real() * result[i].real() + result[i].imag() * result[i].imag());
ret[i] = tmp;
}
return ret;
@@ -111,18 +112,18 @@ void PIFFT_double::fftc1r(const PIVector<double> & a, uint n) {
if (n % 2 == 0) {
PIVector<double> buf;
uint n2 = n / 2;
buf = a;
buf = a;
createPlan(n2);
ftbaseexecuteplan(&buf, 0, n2, &curplan);
result.resize(n);
uint idx;
complexd hn, hmnc, v;
for (i = 0; i <= n2; i++) {
idx = 2 * (i % n2);
hn = complexd(buf[idx + 0], buf[idx + 1]);
idx = 2 * ((n2 - i) % n2);
hmnc = complexd(buf[idx + 0], -buf[idx + 1]);
v = complexd(sin(M_PI * i / n2), cos(M_PI * i / n2));
idx = 2 * (i % n2);
hn = complexd(buf[idx + 0], buf[idx + 1]);
idx = 2 * ((n2 - i) % n2);
hmnc = complexd(buf[idx + 0], -buf[idx + 1]);
v = complexd(sin(M_PI * i / n2), cos(M_PI * i / n2));
result[i] = ((hn + hmnc) - (v * (hn - hmnc)));
result[i] *= 0.5;
}
@@ -169,22 +170,31 @@ void PIFFT_double::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) {
int tmpmemsize;
int stackmemsize;
ae_int_t stackptr;
planarraysize = 1;
plansize = 0;
planarraysize = 1;
plansize = 0;
precomputedsize = 0;
stackmemsize = 0;
stackptr = 0;
tmpmemsize = 2 * n;
stackmemsize = 0;
stackptr = 0;
tmpmemsize = 2 * n;
curplan.plan.resize(planarraysize);
int ftbase_ftbasecffttask = 0;
ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr);
assert(stackptr==0);
curplan.stackbuf.resize(piMax<int>(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
curplan.tmpbuf.resize(piMax<int>(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
curplan.precomputed.resize(piMax<int>(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1));
ftbase_ftbasegenerateplanrec(n,
ftbase_ftbasecffttask,
plan,
&plansize,
&precomputedsize,
&planarraysize,
&tmpmemsize,
&stackmemsize,
stackptr);
assert(stackptr == 0);
curplan.stackbuf.resize(piMax<int>(stackmemsize, 1)); // ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
curplan.tmpbuf.resize(piMax<int>(tmpmemsize, 1)); // ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
curplan.precomputed.resize(piMax<int>(precomputedsize, 1)); // ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize,
// 1));
stackptr = 0;
ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr);
assert(stackptr==0);
assert(stackptr == 0);
}
@@ -192,49 +202,49 @@ void PIFFT_double::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) {
Recurrent subroutine for the FFTGeneratePlan:
PARAMETERS:
N plan size
IsReal whether input is real or not.
subroutine MUST NOT ignore this flag because real
inputs comes with non-initialized imaginary parts,
so ignoring this flag will result in corrupted output
HalfOut whether full output or only half of it from 0 to
floor(N/2) is needed. This flag may be ignored if
doing so will simplify calculations
Plan plan array
PlanSize size of used part (in integers)
PrecomputedSize size of precomputed array allocated yet
PlanArraySize plan array size (actual)
TmpMemSize temporary memory required size
BluesteinMemSize temporary memory required size
N plan size
IsReal whether input is real or not.
subroutine MUST NOT ignore this flag because real
inputs comes with non-initialized imaginary parts,
so ignoring this flag will result in corrupted output
HalfOut whether full output or only half of it from 0 to
floor(N/2) is needed. This flag may be ignored if
doing so will simplify calculations
Plan plan array
PlanSize size of used part (in integers)
PrecomputedSize size of precomputed array allocated yet
PlanArraySize plan array size (actual)
TmpMemSize temporary memory required size
BluesteinMemSize temporary memory required size
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_double::ftbase_ftbasegenerateplanrec(
int n,
int tasktype,
ftplan * plan,
int * plansize,
int * precomputedsize,
int * planarraysize,
int * tmpmemsize,
int * stackmemsize,
ae_int_t stackptr, int debugi) {
void PIFFT_double::ftbase_ftbasegenerateplanrec(int n,
int tasktype,
ftplan * plan,
int * plansize,
int * precomputedsize,
int * planarraysize,
int * tmpmemsize,
int * stackmemsize,
ae_int_t stackptr,
int debugi) {
int k, m, n1, n2, esize, entryoffset;
int ftbase_ftbaseplanentrysize = 8;
int ftbase_ftbasecffttask = 0;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_ftbaseplanentrysize = 8;
int ftbase_ftbasecffttask = 0;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fftrealcooleytukeyplan = 5;
int ftbase_fftemptyplan = 6;
int ftbase_fftemptyplan = 6;
if (*plansize + ftbase_ftbaseplanentrysize > (*planarraysize)) {
curplan.plan.resize(8 * (*planarraysize));
*planarraysize = 8 * (*planarraysize);
}
entryoffset = *plansize;
esize = ftbase_ftbaseplanentrysize;
*plansize = *plansize + esize;
esize = ftbase_ftbaseplanentrysize;
*plansize = *plansize + esize;
if (n == 1) {
curplan.plan[entryoffset + 0] = esize;
curplan.plan[entryoffset + 1] = -1;
@@ -248,7 +258,7 @@ ae_int_t stackptr, int debugi) {
}
ftbasefactorize(n, &n1, &n2);
if (n1 != 1) {
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * n1 * n2);
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * n1 * n2);
curplan.plan[entryoffset + 0] = esize;
curplan.plan[entryoffset + 1] = n1;
curplan.plan[entryoffset + 2] = n2;
@@ -259,9 +269,27 @@ ae_int_t stackptr, int debugi) {
curplan.plan[entryoffset + 4] = 0;
curplan.plan[entryoffset + 5] = *plansize;
debugi++;
ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr, debugi);
ftbase_ftbasegenerateplanrec(n1,
ftbase_ftbasecffttask,
plan,
plansize,
precomputedsize,
planarraysize,
tmpmemsize,
stackmemsize,
stackptr,
debugi);
curplan.plan[entryoffset + 6] = *plansize;
ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr, debugi);
ftbase_ftbasegenerateplanrec(n2,
ftbase_ftbasecffttask,
plan,
plansize,
precomputedsize,
planarraysize,
tmpmemsize,
stackmemsize,
stackptr,
debugi);
curplan.plan[entryoffset + 7] = -1;
return;
} else {
@@ -274,28 +302,34 @@ ae_int_t stackptr, int debugi) {
curplan.plan[entryoffset + 5] = -1;
curplan.plan[entryoffset + 6] = -1;
curplan.plan[entryoffset + 7] = *precomputedsize;
if (n == 3)
*precomputedsize = *precomputedsize + 2;
if (n == 5)
*precomputedsize = *precomputedsize + 5;
if (n == 3) *precomputedsize = *precomputedsize + 2;
if (n == 5) *precomputedsize = *precomputedsize + 5;
return;
} else {
k = 2 * n2 - 1;
m = ftbasefindsmooth(k);
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * m);
k = 2 * n2 - 1;
m = ftbasefindsmooth(k);
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * m);
curplan.plan[entryoffset + 0] = esize;
curplan.plan[entryoffset + 1] = n2;
curplan.plan[entryoffset + 2] = -1;
curplan.plan[entryoffset + 3] = ftbase_fftbluesteinplan;
curplan.plan[entryoffset + 4] = m;
curplan.plan[entryoffset + 5] = *plansize;
stackptr = stackptr + 2 * 2 * m;
*stackmemsize = piMax<int>(*stackmemsize, stackptr);
ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr);
stackptr = stackptr - 2 * 2 * m;
stackptr = stackptr + 2 * 2 * m;
*stackmemsize = piMax<int>(*stackmemsize, stackptr);
ftbase_ftbasegenerateplanrec(m,
ftbase_ftbasecffttask,
plan,
plansize,
precomputedsize,
planarraysize,
tmpmemsize,
stackmemsize,
stackptr);
stackptr = stackptr - 2 * 2 * m;
curplan.plan[entryoffset + 6] = -1;
curplan.plan[entryoffset + 7] = *precomputedsize;
*precomputedsize = *precomputedsize + 2 * m + 2 * n;
*precomputedsize = *precomputedsize + 2 * m + 2 * n;
return;
}
}
@@ -306,20 +340,19 @@ ae_int_t stackptr, int debugi) {
Recurrent subroutine for precomputing FFT plans
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_double::ftbase_ftbaseprecomputeplanrec(ftplan * plan,
int entryoffset,
ae_int_t stackptr) {
void PIFFT_double::ftbase_ftbaseprecomputeplanrec(ftplan * plan, int entryoffset, ae_int_t stackptr) {
int n1, n2, n, m, offs;
double v, bx, by;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftrealcooleytukeyplan = 5;
if ((curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan || curplan.plan[entryoffset + 3] == ftbase_fftrealcooleytukeyplan) || curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) {
if ((curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan || curplan.plan[entryoffset + 3] == ftbase_fftrealcooleytukeyplan) ||
curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) {
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 5], stackptr);
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 6], stackptr);
return;
@@ -327,16 +360,16 @@ ae_int_t stackptr) {
if (curplan.plan[entryoffset + 3] == ftbase_fftcodeletplan || curplan.plan[entryoffset + 3] == ftbase_fhtcodeletplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
if (n == 3) {
offs = curplan.plan[entryoffset + 7];
offs = curplan.plan[entryoffset + 7];
curplan.precomputed[offs + 0] = cos(2 * M_PI / 3) - 1;
curplan.precomputed[offs + 1] = sin(2 * M_PI / 3);
return;
}
if (n == 5) {
offs = curplan.plan[entryoffset + 7];
v = 2 * M_PI / 5;
offs = curplan.plan[entryoffset + 7];
v = 2 * M_PI / 5;
curplan.precomputed[offs + 0] = (cos(v) + cos(2 * v)) / 2 - 1;
curplan.precomputed[offs + 1] = (cos(v) - cos(2 * v)) / 2;
curplan.precomputed[offs + 2] = -sin(v);
@@ -347,16 +380,16 @@ ae_int_t stackptr) {
}
if (curplan.plan[entryoffset + 3] == ftbase_fftbluesteinplan) {
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 5], stackptr);
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
offs = curplan.plan[entryoffset + 7];
for (int i = 0; i <= 2 * m - 1; i++)
curplan.precomputed[offs + i] = 0;
for (int i = 0; i < n; i++) {
bx = cos(M_PI * sqr(i) / n);
by = sin(M_PI * sqr(i) / n);
curplan.precomputed[offs + 2 * i + 0] = bx;
curplan.precomputed[offs + 2 * i + 1] = by;
bx = cos(M_PI * sqr(i) / n);
by = sin(M_PI * sqr(i) / n);
curplan.precomputed[offs + 2 * i + 0] = bx;
curplan.precomputed[offs + 2 * i + 1] = by;
curplan.precomputed[offs + 2 * m + 2 * i + 0] = bx;
curplan.precomputed[offs + 2 * m + 2 * i + 1] = by;
if (i > 0) {
@@ -371,7 +404,7 @@ ae_int_t stackptr) {
void PIFFT_double::ftbasefactorize(int n, int * n1, int * n2) {
*n1 = *n2 = 0;
*n1 = *n2 = 0;
int ftbase_ftbasecodeletrecommended = 5;
if ((*n1) * (*n2) != n) {
for (int j = ftbase_ftbasecodeletrecommended; j >= 2; j--) {
@@ -406,19 +439,16 @@ void PIFFT_double::ftbasefactorize(int n, int * n1, int * n2) {
Is number smooth?
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_double::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best) {
if (seed >= n) {
*best = piMini(*best, seed);
return;
}
if (leastfactor <= 2)
ftbase_ftbasefindsmoothrec(n, seed * 2, 2, best);
if (leastfactor <= 3)
ftbase_ftbasefindsmoothrec(n, seed * 3, 3, best);
if (leastfactor <= 5)
ftbase_ftbasefindsmoothrec(n, seed * 5, 5, best);
if (leastfactor <= 2) ftbase_ftbasefindsmoothrec(n, seed * 2, 2, best);
if (leastfactor <= 3) ftbase_ftbasefindsmoothrec(n, seed * 3, 3, best);
if (leastfactor <= 5) ftbase_ftbasefindsmoothrec(n, seed * 5, 5, best);
}
@@ -435,37 +465,42 @@ int PIFFT_double::ftbasefindsmooth(int n) {
void PIFFT_double::ftbase_internalreallintranspose(PIVector<double> * a, int m, int n, int astart, PIVector<double> * buf) {
ftbase_fftirltrec(a, astart, n, buf, 0, m, m, n);
for (int i = 0; i < 2 * m * n; i++) (*a)[astart + i] = (*buf)[i];
for (int i = 0; i < 2 * m * n; i++)
(*a)[astart + i] = (*buf)[i];
}
void PIFFT_double::ftbase_fftirltrec(PIVector<double> * a, int astart, int astride, PIVector<double> * b, int bstart, int bstride, int m, int n) {
void PIFFT_double::ftbase_fftirltrec(PIVector<double> * a,
int astart,
int astride,
PIVector<double> * b,
int bstart,
int bstride,
int m,
int n) {
int idx1, idx2;
int m1, n1;
if (m == 0 || n == 0)
return;
if (m == 0 || n == 0) return;
if (piMaxi(m, n) <= 8) {
for (int i = 0; i <= m - 1; i++) {
idx1 = bstart + i;
idx2 = astart + i * astride;
for (int j = 0; j <= n - 1; j++) {
(*b)[idx1] = a->at(idx2);
idx1 = idx1 + bstride;
idx2 = idx2 + 1;
idx1 = idx1 + bstride;
idx2 = idx2 + 1;
}
}
return;
}
if (n > m) {
n1 = n / 2;
if (n - n1 >= 8 && n1 % 8 != 0)
n1 = n1 + (8 - n1 % 8);
if (n - n1 >= 8 && n1 % 8 != 0) n1 = n1 + (8 - n1 % 8);
ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1);
ftbase_fftirltrec(a, astart + n1, astride, b, bstart + n1 * bstride, bstride, m, n - n1);
} else {
m1 = m / 2;
if (m - m1 >= 8 && m1 % 8 != 0)
m1 = m1 + (8 - m1 % 8);
if (m - m1 >= 8 && m1 % 8 != 0) m1 = m1 + (8 - m1 % 8);
ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n);
ftbase_fftirltrec(a, astart + m1 * astride, astride, b, bstart + m1, bstride, m - m1, n);
}
@@ -479,10 +514,16 @@ void PIFFT_double::ftbase_internalcomplexlintranspose(PIVector<double> * a, int
}
void PIFFT_double::ftbase_ffticltrec(PIVector<double> * a, int astart, int astride, PIVector<double> * b, int bstart, int bstride, int m, int n) {
void PIFFT_double::ftbase_ffticltrec(PIVector<double> * a,
int astart,
int astride,
PIVector<double> * b,
int bstart,
int bstride,
int m,
int n) {
int idx1, idx2, m2, m1, n1;
if (m == 0 || n == 0)
return;
if (m == 0 || n == 0) return;
if (piMax<int>(m, n) <= 8) {
m2 = 2 * bstride;
for (int i = 0; i <= m - 1; i++) {
@@ -491,22 +532,20 @@ void PIFFT_double::ftbase_ffticltrec(PIVector<double> * a, int astart, int astri
for (int j = 0; j <= n - 1; j++) {
(*b)[idx1 + 0] = a->at(idx2 + 0);
(*b)[idx1 + 1] = a->at(idx2 + 1);
idx1 = idx1 + m2;
idx2 = idx2 + 2;
idx1 = idx1 + m2;
idx2 = idx2 + 2;
}
}
return;
}
if (n > m) {
n1 = n / 2;
if (n - n1 >= 8 && n1 % 8 != 0)
n1 = n1 + (8 - n1 % 8);
if (n - n1 >= 8 && n1 % 8 != 0) n1 = n1 + (8 - n1 % 8);
ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1);
ftbase_ffticltrec(a, astart + 2 * n1, astride, b, bstart + 2 * n1 * bstride, bstride, m, n - n1);
} else {
m1 = m / 2;
if (m - m1 >= 8 && m1 % 8 != 0)
m1 = m1 + (8 - m1 % 8);
if (m - m1 >= 8 && m1 % 8 != 0) m1 = m1 + (8 - m1 % 8);
ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n);
ftbase_ffticltrec(a, astart + 2 * m1 * astride, astride, b, bstart + 2 * m1, bstride, m - m1, n);
}
@@ -524,11 +563,11 @@ void PIFFT_double::ftbaseexecuteplan(PIVector<double> * a, int aoffset, int n, f
Recurrent subroutine for the FTBaseExecutePlan
Parameters:
A FFT'ed array
AOffset offset of the FFT'ed part (distance is measured in doubles)
A FFT'ed array
AOffset offset of the FFT'ed part (distance is measured in doubles)
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr) {
int n1, n2, n, m, offs, offs1, offs2, offsa, offsb, offsp;
@@ -538,17 +577,16 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
double m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y, m5x, m5y;
double s1x, s1y, s2x, s2y, s3x, s3y, s4x, s4y, s5x, s5y;
double c1, c2, c3, c4, c5;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftrealcooleytukeyplan = 5;
int ftbase_fftemptyplan = 6;
int ftbase_fftemptyplan = 6;
PIVector<double> & tmpb(curplan.tmpbuf);
if (curplan.plan[entryoffset + 3] == ftbase_fftemptyplan)
return;
if (curplan.plan[entryoffset + 3] == ftbase_fftemptyplan) return;
if (curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
@@ -571,26 +609,26 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
for (int k = 0; k <= n2 - 1; k++)
(*a)[offs + 2 * k + 1] = (*a)[offs + 2 * n2 + 2 * k + 0];
ftbaseexecuteplanrec(a, offs, plan, curplan.plan[entryoffset + 6], stackptr);
tmpb[0] = (*a)[offs + 0];
tmpb[1] = 0;
tmpb[0] = (*a)[offs + 0];
tmpb[1] = 0;
tmpb[2 * n2 + 0] = (*a)[offs + 1];
tmpb[2 * n2 + 1] = 0;
for (int k = 1; k <= n2 - 1; k++) {
offs1 = 2 * k;
offs2 = 2 * n2 + 2 * k;
hk = (*a)[offs + 2 * k + 0];
hnk = (*a)[offs + 2 * (n2 - k) + 0];
offs1 = 2 * k;
offs2 = 2 * n2 + 2 * k;
hk = (*a)[offs + 2 * k + 0];
hnk = (*a)[offs + 2 * (n2 - k) + 0];
tmpb[offs1 + 0] = 0.5 * (hk + hnk);
tmpb[offs2 + 1] = -0.5 * (hk - hnk);
hk = (*a)[offs + 2 * k + 1];
hnk = (*a)[offs + 2 * (n2 - k) + 1];
hk = (*a)[offs + 2 * k + 1];
hnk = (*a)[offs + 2 * (n2 - k) + 1];
tmpb[offs2 + 0] = 0.5 * (hk + hnk);
tmpb[offs1 + 1] = 0.5 * (hk - hnk);
}
for (int k = 0; k < 2 * n2 * 2; k++) (*a)[offs + k] = tmpb[k];
for (int k = 0; k < 2 * n2 * 2; k++)
(*a)[offs + k] = tmpb[k];
}
if (n1 % 2 != 0)
ftbaseexecuteplanrec(a, aoffset + (n1 - 1)*n2 * 2, plan, curplan.plan[entryoffset + 6], stackptr);
if (n1 % 2 != 0) ftbaseexecuteplanrec(a, aoffset + (n1 - 1) * n2 * 2, plan, curplan.plan[entryoffset + 6], stackptr);
ftbase_ffttwcalc(a, aoffset, n2, n1);
ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf));
for (int i = 0; i <= n2 - 1; i++)
@@ -601,16 +639,16 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
if (curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf));
for (int i = 0; i <= n2 - 1; i++)
ftbaseexecuteplanrec(a, aoffset + i * n1, plan, curplan.plan[entryoffset + 5], stackptr);
for (int i = 0; i <= n2 - 1; i++) {
for (int j = 0; j <= n1 - 1; j++) {
offsa = aoffset + i * n1;
hk = (*a)[offsa + j];
hnk = (*a)[offsa + (n1 - j) % n1];
offs = 2 * (i * n1 + j);
offsa = aoffset + i * n1;
hk = (*a)[offsa + j];
hnk = (*a)[offsa + (n1 - j) % n1];
offs = 2 * (i * n1 + j);
tmpb[offs + 0] = -0.5 * (hnk - hk);
tmpb[offs + 1] = 0.5 * (hk + hnk);
}
@@ -619,13 +657,13 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
for (int j = 0; j <= n1 - 1; j++)
(*a)[aoffset + j] = tmpb[2 * j + 0] + tmpb[2 * j + 1];
if (n2 % 2 == 0) {
offs = 2 * (n2 / 2) * n1;
offs = 2 * (n2 / 2) * n1;
offsa = aoffset + n2 / 2 * n1;
for (int j = 0; j <= n1 - 1; j++)
(*a)[offsa + j] = tmpb[offs + 2 * j + 0] + tmpb[offs + 2 * j + 1];
}
for (int i = 1; i <= (n2 + 1) / 2 - 1; i++) {
offs = 2 * i * n1;
offs = 2 * i * n1;
offs2 = 2 * (n2 - i) * n1;
offsa = aoffset + i * n1;
for (int j = 0; j <= n1 - 1; j++)
@@ -643,16 +681,16 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
if (curplan.plan[entryoffset + 3] == ftbase_fftcodeletplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
if (n == 2) {
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
v0 = a0x + a1x;
v1 = a0y + a1y;
v2 = a0x - a1x;
v3 = a0y - a1y;
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
v0 = a0x + a1x;
v1 = a0y + a1y;
v2 = a0x - a1x;
v3 = a0y - a1y;
(*a)[aoffset + 0] = v0;
(*a)[aoffset + 1] = v1;
(*a)[aoffset + 2] = v2;
@@ -660,29 +698,29 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
return;
}
if (n == 3) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
t1x = a1x + a2x;
t1y = a1y + a2y;
a0x = a0x + t1x;
a0y = a0y + t1y;
m1x = c1 * t1x;
m1y = c1 * t1y;
m2x = c2 * (a1y - a2y);
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
s1y = a0y + m1y;
a1x = s1x + m2x;
a1y = s1y + m2y;
a2x = s1x - m2x;
a2y = s1y - m2y;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
t1x = a1x + a2x;
t1y = a1y + a2y;
a0x = a0x + t1x;
a0y = a0y + t1y;
m1x = c1 * t1x;
m1y = c1 * t1y;
m2x = c2 * (a1y - a2y);
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
s1y = a0y + m1y;
a1x = s1x + m2x;
a1y = s1y + m2y;
a2x = s1x - m2x;
a2y = s1y - m2y;
(*a)[aoffset + 0] = a0x;
(*a)[aoffset + 1] = a0y;
(*a)[aoffset + 2] = a1x;
@@ -692,22 +730,22 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
return;
}
if (n == 4) {
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
a3x = (*a)[aoffset + 6];
a3y = (*a)[aoffset + 7];
t1x = a0x + a2x;
t1y = a0y + a2y;
t2x = a1x + a3x;
t2y = a1y + a3y;
m2x = a0x - a2x;
m2y = a0y - a2y;
m3x = a1y - a3y;
m3y = a3x - a1x;
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
a3x = (*a)[aoffset + 6];
a3y = (*a)[aoffset + 7];
t1x = a0x + a2x;
t1y = a0y + a2y;
t2x = a1x + a3x;
t2y = a1y + a3y;
m2x = a0x - a2x;
m2y = a0y - a2y;
m3x = a1y - a3y;
m3y = a3x - a1x;
(*a)[aoffset + 0] = t1x + t2x;
(*a)[aoffset + 1] = t1y + t2y;
(*a)[aoffset + 4] = t1x - t2x;
@@ -719,44 +757,44 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
return;
}
if (n == 5) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 2] + (*a)[aoffset + 8];
t1y = (*a)[aoffset + 3] + (*a)[aoffset + 9];
t2x = (*a)[aoffset + 4] + (*a)[aoffset + 6];
t2y = (*a)[aoffset + 5] + (*a)[aoffset + 7];
t3x = (*a)[aoffset + 2] - (*a)[aoffset + 8];
t3y = (*a)[aoffset + 3] - (*a)[aoffset + 9];
t4x = (*a)[aoffset + 6] - (*a)[aoffset + 4];
t4y = (*a)[aoffset + 7] - (*a)[aoffset + 5];
t5x = t1x + t2x;
t5y = t1y + t2y;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 2] + (*a)[aoffset + 8];
t1y = (*a)[aoffset + 3] + (*a)[aoffset + 9];
t2x = (*a)[aoffset + 4] + (*a)[aoffset + 6];
t2y = (*a)[aoffset + 5] + (*a)[aoffset + 7];
t3x = (*a)[aoffset + 2] - (*a)[aoffset + 8];
t3y = (*a)[aoffset + 3] - (*a)[aoffset + 9];
t4x = (*a)[aoffset + 6] - (*a)[aoffset + 4];
t4y = (*a)[aoffset + 7] - (*a)[aoffset + 5];
t5x = t1x + t2x;
t5y = t1y + t2y;
(*a)[aoffset + 0] = (*a)[aoffset + 0] + t5x;
(*a)[aoffset + 1] = (*a)[aoffset + 1] + t5y;
m1x = c1 * t5x;
m1y = c1 * t5y;
m2x = c2 * (t1x - t2x);
m2y = c2 * (t1y - t2y);
m3x = -c3 * (t3y + t4y);
m3y = c3 * (t3x + t4x);
m4x = -c4 * t4y;
m4y = c4 * t4x;
m5x = -c5 * t3y;
m5y = c5 * t3x;
s3x = m3x - m4x;
s3y = m3y - m4y;
s5x = m3x + m5x;
s5y = m3y + m5y;
s1x = (*a)[aoffset + 0] + m1x;
s1y = (*a)[aoffset + 1] + m1y;
s2x = s1x + m2x;
s2y = s1y + m2y;
s4x = s1x - m2x;
s4y = s1y - m2y;
m1x = c1 * t5x;
m1y = c1 * t5y;
m2x = c2 * (t1x - t2x);
m2y = c2 * (t1y - t2y);
m3x = -c3 * (t3y + t4y);
m3y = c3 * (t3x + t4x);
m4x = -c4 * t4y;
m4y = c4 * t4x;
m5x = -c5 * t3y;
m5y = c5 * t3x;
s3x = m3x - m4x;
s3y = m3y - m4y;
s5x = m3x + m5x;
s5y = m3y + m5y;
s1x = (*a)[aoffset + 0] + m1x;
s1y = (*a)[aoffset + 1] + m1y;
s2x = s1x + m2x;
s2y = s1y + m2y;
s4x = s1x - m2x;
s4y = s1y - m2y;
(*a)[aoffset + 2] = s2x + s3x;
(*a)[aoffset + 3] = s2y + s3y;
(*a)[aoffset + 4] = s4x + s5x;
@@ -771,40 +809,40 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
if (curplan.plan[entryoffset + 3] == ftbase_fhtcodeletplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
if (n == 2) {
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
(*a)[aoffset + 0] = a0x + a1x;
(*a)[aoffset + 1] = a0x - a1x;
return;
}
if (n == 3) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
t1x = a1x + a2x;
a0x = a0x + t1x;
m1x = c1 * t1x;
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
t1x = a1x + a2x;
a0x = a0x + t1x;
m1x = c1 * t1x;
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
(*a)[aoffset + 0] = a0x;
(*a)[aoffset + 1] = s1x - m2y;
(*a)[aoffset + 2] = s1x + m2y;
return;
}
if (n == 4) {
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
a3x = (*a)[aoffset + 3];
t1x = a0x + a2x;
t2x = a1x + a3x;
m2x = a0x - a2x;
m3y = a3x - a1x;
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
a3x = (*a)[aoffset + 3];
t1x = a0x + a2x;
t2x = a1x + a3x;
m2x = a0x - a2x;
m3y = a3x - a1x;
(*a)[aoffset + 0] = t1x + t2x;
(*a)[aoffset + 1] = m2x - m3y;
(*a)[aoffset + 2] = t1x - t2x;
@@ -812,26 +850,26 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
return;
}
if (n == 5) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 1] + (*a)[aoffset + 4];
t2x = (*a)[aoffset + 2] + (*a)[aoffset + 3];
t3x = (*a)[aoffset + 1] - (*a)[aoffset + 4];
t4x = (*a)[aoffset + 3] - (*a)[aoffset + 2];
t5x = t1x + t2x;
v0 = (*a)[aoffset + 0] + t5x;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 1] + (*a)[aoffset + 4];
t2x = (*a)[aoffset + 2] + (*a)[aoffset + 3];
t3x = (*a)[aoffset + 1] - (*a)[aoffset + 4];
t4x = (*a)[aoffset + 3] - (*a)[aoffset + 2];
t5x = t1x + t2x;
v0 = (*a)[aoffset + 0] + t5x;
(*a)[aoffset + 0] = v0;
m2x = c2 * (t1x - t2x);
m3y = c3 * (t3x + t4x);
s3y = m3y - c4 * t4x;
s5y = m3y + c5 * t3x;
s1x = v0 + c1 * t5x;
s2x = s1x + m2x;
s4x = s1x - m2x;
m2x = c2 * (t1x - t2x);
m3y = c3 * (t3x + t4x);
s3y = m3y - c4 * t4x;
s5y = m3y + c5 * t3x;
s1x = v0 + c1 * t5x;
s2x = s1x + m2x;
s4x = s1x - m2x;
(*a)[aoffset + 1] = s2x - s3y;
(*a)[aoffset + 2] = s4x - s5y;
(*a)[aoffset + 3] = s4x + s5y;
@@ -840,8 +878,8 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
}
}
if (curplan.plan[entryoffset + 3] == ftbase_fftbluesteinplan) {
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
offs = curplan.plan[entryoffset + 7];
for (int i = stackptr + 2 * n; i <= stackptr + 2 * m - 1; i++)
curplan.stackbuf[i] = 0;
@@ -849,43 +887,43 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
offsa = aoffset;
offsb = stackptr;
for (int i = 0; i < n; i++) {
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = (*a)[offsa + 0];
y = (*a)[offsa + 1];
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = (*a)[offsa + 0];
y = (*a)[offsa + 1];
curplan.stackbuf[offsb + 0] = x * bx - y * (-by);
curplan.stackbuf[offsb + 1] = x * (-by) + y * bx;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
}
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset + 5], stackptr + 2 * 2 * m);
offsb = stackptr;
offsp = offs;
for (int i = 0; i <= m - 1; i++) {
x = curplan.stackbuf[offsb + 0];
y = curplan.stackbuf[offsb + 1];
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = curplan.stackbuf[offsb + 0];
y = curplan.stackbuf[offsb + 1];
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
curplan.stackbuf[offsb + 0] = x * bx - y * by;
curplan.stackbuf[offsb + 1] = -(x * by + y * bx);
offsb = offsb + 2;
offsp = offsp + 2;
offsb = offsb + 2;
offsp = offsp + 2;
}
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset + 5], stackptr + 2 * 2 * m);
offsb = stackptr;
offsp = offs + 2 * m;
offsa = aoffset;
for (int i = 0; i < n; i++) {
x = curplan.stackbuf[offsb + 0] / m;
y = -curplan.stackbuf[offsb + 1] / m;
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = curplan.stackbuf[offsb + 0] / m;
y = -curplan.stackbuf[offsb + 1] / m;
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
(*a)[offsa + 0] = x * bx - y * (-by);
(*a)[offsa + 1] = x * (-by) + y * bx;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
}
return;
}
@@ -896,54 +934,54 @@ void PIFFT_double::ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftpla
Twiddle factors calculation
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_double::ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2) {
int n, idx, offs;
double x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v;
int ftbase_ftbaseupdatetw = 4;
n = n1 * n2;
v = -2 * M_PI / n;
twbasexm1 = -2 * sqr(sin(0.5 * v));
twbasey = sin(v);
twrowxm1 = 0;
twrowy = 0;
n = n1 * n2;
v = -2 * M_PI / n;
twbasexm1 = -2 * sqr(sin(0.5 * v));
twbasey = sin(v);
twrowxm1 = 0;
twrowy = 0;
for (int i = 0, j = 0; i <= n2 - 1; i++) {
twxm1 = 0;
twy = 0;
twy = 0;
for (j = 0; j <= n1 - 1; j++) {
idx = i * n1 + j;
offs = aoffset + 2 * idx;
x = (*a)[offs + 0];
y = (*a)[offs + 1];
tmpx = x * twxm1 - y * twy;
tmpy = x * twy + y * twxm1;
idx = i * n1 + j;
offs = aoffset + 2 * idx;
x = (*a)[offs + 0];
y = (*a)[offs + 1];
tmpx = x * twxm1 - y * twy;
tmpy = x * twy + y * twxm1;
(*a)[offs + 0] = x + tmpx;
(*a)[offs + 1] = y + tmpy;
if (j < n1 - 1) {
if (j % ftbase_ftbaseupdatetw == 0) {
v = -2 * M_PI * i * (j + 1) / n;
v = -2 * M_PI * i * (j + 1) / n;
twxm1 = -2 * sqr(sin(0.5 * v));
twy = sin(v);
twy = sin(v);
} else {
tmpx = twrowxm1 + twxm1 * twrowxm1 - twy * twrowy;
tmpy = twrowy + twxm1 * twrowy + twy * twrowxm1;
tmpx = twrowxm1 + twxm1 * twrowxm1 - twy * twrowy;
tmpy = twrowy + twxm1 * twrowy + twy * twrowxm1;
twxm1 = twxm1 + tmpx;
twy = twy + tmpy;
twy = twy + tmpy;
}
}
}
if (i < n2 - 1) {
if (j % ftbase_ftbaseupdatetw == 0) {
v = -2 * M_PI * (i + 1) / n;
v = -2 * M_PI * (i + 1) / n;
twrowxm1 = -2 * sqr(sin(0.5 * v));
twrowy = sin(v);
twrowy = sin(v);
} else {
tmpx = twbasexm1 + twrowxm1 * twbasexm1 - twrowy * twbasey;
tmpy = twbasey + twrowxm1 * twbasey + twrowy * twbasexm1;
tmpx = twbasexm1 + twrowxm1 * twbasexm1 - twrowy * twbasey;
tmpy = twbasey + twrowxm1 * twbasey + twrowy * twbasexm1;
twrowxm1 = twrowxm1 + tmpx;
twrowy = twrowy + tmpy;
twrowy = twrowy + tmpy;
}
}
}
@@ -957,8 +995,7 @@ void PIFFT_double::ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, i
//=================================================================================================
PIFFT_float::PIFFT_float() {
}
PIFFT_float::PIFFT_float() {}
PIVector<complexf> * PIFFT_float::calcFFT(const PIVector<complexf> & val) {
@@ -981,8 +1018,10 @@ PIVector<complexf> * PIFFT_float::calcHilbert(const PIVector<float> & val) {
result.clear();
if (val.size_s() < 4) return &result;
fftc1r(val, val.size());
for (uint i = 0; i < result.size() / 2; i++) result[i] = result[i] * 2.f;
for (uint i = result.size() / 2; i < result.size(); i++) result[i] = 0;
for (uint i = 0; i < result.size() / 2; i++)
result[i] = result[i] * 2.f;
for (uint i = result.size() / 2; i < result.size(); i++)
result[i] = 0;
fftc1dinv(result, result.size());
return &result;
}
@@ -1001,7 +1040,7 @@ PIVector<float> PIFFT_float::getAmplitude() const {
ret.resize(result.size());
float tmp;
for (uint i = 0; i < result.size(); i++) {
tmp = sqrt(result[i].real() * result[i].real() + result[i].imag() * result[i].imag());
tmp = sqrt(result[i].real() * result[i].real() + result[i].imag() * result[i].imag());
ret[i] = tmp;
}
return ret;
@@ -1047,18 +1086,18 @@ void PIFFT_float::fftc1r(const PIVector<float> & a, uint n) {
if (n % 2 == 0) {
PIVector<float> buf;
uint n2 = n / 2;
buf = a;
buf = a;
createPlan(n2);
ftbaseexecuteplan(&buf, 0, n2, &curplan);
result.resize(n);
uint idx;
complexf hn, hmnc, v;
for (i = 0; i <= n2; i++) {
idx = 2 * (i % n2);
hn = complexf(buf[idx + 0], buf[idx + 1]);
idx = 2 * ((n2 - i) % n2);
hmnc = complexf(buf[idx + 0], -buf[idx + 1]);
v = complexf(sin(M_PI * i / n2), cos(M_PI * i / n2));
idx = 2 * (i % n2);
hn = complexf(buf[idx + 0], buf[idx + 1]);
idx = 2 * ((n2 - i) % n2);
hmnc = complexf(buf[idx + 0], -buf[idx + 1]);
v = complexf(sin(M_PI * i / n2), cos(M_PI * i / n2));
result[i] = ((hn + hmnc) - (v * (hn - hmnc)));
result[i] *= 0.5;
}
@@ -1105,22 +1144,31 @@ void PIFFT_float::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) {
int tmpmemsize;
int stackmemsize;
ae_int_t stackptr;
planarraysize = 1;
plansize = 0;
planarraysize = 1;
plansize = 0;
precomputedsize = 0;
stackmemsize = 0;
stackptr = 0;
tmpmemsize = 2 * n;
stackmemsize = 0;
stackptr = 0;
tmpmemsize = 2 * n;
curplan.plan.resize(planarraysize);
int ftbase_ftbasecffttask = 0;
ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr);
assertm(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan");
curplan.stackbuf.resize(piMax<int>(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
curplan.tmpbuf.resize(piMax<int>(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
curplan.precomputed.resize(piMax<int>(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1));
ftbase_ftbasegenerateplanrec(n,
ftbase_ftbasecffttask,
plan,
&plansize,
&precomputedsize,
&planarraysize,
&tmpmemsize,
&stackmemsize,
stackptr);
assertm(stackptr == 0, "Internal error in FTBaseGenerateComplexFFTPlan");
curplan.stackbuf.resize(piMax<int>(stackmemsize, 1)); // ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
curplan.tmpbuf.resize(piMax<int>(tmpmemsize, 1)); // ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
curplan.precomputed.resize(piMax<int>(precomputedsize, 1)); // ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize,
// 1));
stackptr = 0;
ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr);
assertm(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan");
assertm(stackptr == 0, "Internal error in FTBaseGenerateComplexFFTPlan");
}
@@ -1128,49 +1176,49 @@ void PIFFT_float::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) {
Recurrent subroutine for the FFTGeneratePlan:
PARAMETERS:
N plan size
IsReal whether input is real or not.
subroutine MUST NOT ignore this flag because real
inputs comes with non-initialized imaginary parts,
so ignoring this flag will result in corrupted output
HalfOut whether full output or only half of it from 0 to
floor(N/2) is needed. This flag may be ignored if
doing so will simplify calculations
Plan plan array
PlanSize size of used part (in integers)
PrecomputedSize size of precomputed array allocated yet
PlanArraySize plan array size (actual)
TmpMemSize temporary memory required size
BluesteinMemSize temporary memory required size
N plan size
IsReal whether input is real or not.
subroutine MUST NOT ignore this flag because real
inputs comes with non-initialized imaginary parts,
so ignoring this flag will result in corrupted output
HalfOut whether full output or only half of it from 0 to
floor(N/2) is needed. This flag may be ignored if
doing so will simplify calculations
Plan plan array
PlanSize size of used part (in integers)
PrecomputedSize size of precomputed array allocated yet
PlanArraySize plan array size (actual)
TmpMemSize temporary memory required size
BluesteinMemSize temporary memory required size
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_float::ftbase_ftbasegenerateplanrec(
int n,
int tasktype,
ftplan * plan,
int * plansize,
int * precomputedsize,
int * planarraysize,
int * tmpmemsize,
int * stackmemsize,
ae_int_t stackptr, int debugi) {
void PIFFT_float::ftbase_ftbasegenerateplanrec(int n,
int tasktype,
ftplan * plan,
int * plansize,
int * precomputedsize,
int * planarraysize,
int * tmpmemsize,
int * stackmemsize,
ae_int_t stackptr,
int debugi) {
int k, m, n1, n2, esize, entryoffset;
int ftbase_ftbaseplanentrysize = 4;
int ftbase_ftbasecffttask = 0;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_ftbaseplanentrysize = 4;
int ftbase_ftbasecffttask = 0;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fftrealcooleytukeyplan = 5;
int ftbase_fftemptyplan = 6;
int ftbase_fftemptyplan = 6;
if (*plansize + ftbase_ftbaseplanentrysize > (*planarraysize)) {
curplan.plan.resize(4 * (*planarraysize));
*planarraysize = 4 * (*planarraysize);
}
entryoffset = *plansize;
esize = ftbase_ftbaseplanentrysize;
*plansize = *plansize + esize;
esize = ftbase_ftbaseplanentrysize;
*plansize = *plansize + esize;
if (n == 1) {
curplan.plan[entryoffset + 0] = esize;
curplan.plan[entryoffset + 1] = -1;
@@ -1184,7 +1232,7 @@ ae_int_t stackptr, int debugi) {
}
ftbasefactorize(n, &n1, &n2);
if (n1 != 1) {
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * n1 * n2);
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * n1 * n2);
curplan.plan[entryoffset + 0] = esize;
curplan.plan[entryoffset + 1] = n1;
curplan.plan[entryoffset + 2] = n2;
@@ -1195,9 +1243,27 @@ ae_int_t stackptr, int debugi) {
curplan.plan[entryoffset + 4] = 0;
curplan.plan[entryoffset + 5] = *plansize;
debugi++;
ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr, debugi);
ftbase_ftbasegenerateplanrec(n1,
ftbase_ftbasecffttask,
plan,
plansize,
precomputedsize,
planarraysize,
tmpmemsize,
stackmemsize,
stackptr,
debugi);
curplan.plan[entryoffset + 6] = *plansize;
ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr, debugi);
ftbase_ftbasegenerateplanrec(n2,
ftbase_ftbasecffttask,
plan,
plansize,
precomputedsize,
planarraysize,
tmpmemsize,
stackmemsize,
stackptr,
debugi);
curplan.plan[entryoffset + 7] = -1;
return;
} else {
@@ -1210,28 +1276,34 @@ ae_int_t stackptr, int debugi) {
curplan.plan[entryoffset + 5] = -1;
curplan.plan[entryoffset + 6] = -1;
curplan.plan[entryoffset + 7] = *precomputedsize;
if (n == 3)
*precomputedsize = *precomputedsize + 2;
if (n == 5)
*precomputedsize = *precomputedsize + 5;
if (n == 3) *precomputedsize = *precomputedsize + 2;
if (n == 5) *precomputedsize = *precomputedsize + 5;
return;
} else {
k = 2 * n2 - 1;
m = ftbasefindsmooth(k);
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * m);
k = 2 * n2 - 1;
m = ftbasefindsmooth(k);
*tmpmemsize = piMax<int>(*tmpmemsize, 2 * m);
curplan.plan[entryoffset + 0] = esize;
curplan.plan[entryoffset + 1] = n2;
curplan.plan[entryoffset + 2] = -1;
curplan.plan[entryoffset + 3] = ftbase_fftbluesteinplan;
curplan.plan[entryoffset + 4] = m;
curplan.plan[entryoffset + 5] = *plansize;
stackptr = stackptr + 2 * 2 * m;
*stackmemsize = piMax<int>(*stackmemsize, stackptr);
ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr);
stackptr = stackptr - 2 * 2 * m;
stackptr = stackptr + 2 * 2 * m;
*stackmemsize = piMax<int>(*stackmemsize, stackptr);
ftbase_ftbasegenerateplanrec(m,
ftbase_ftbasecffttask,
plan,
plansize,
precomputedsize,
planarraysize,
tmpmemsize,
stackmemsize,
stackptr);
stackptr = stackptr - 2 * 2 * m;
curplan.plan[entryoffset + 6] = -1;
curplan.plan[entryoffset + 7] = *precomputedsize;
*precomputedsize = *precomputedsize + 2 * m + 2 * n;
*precomputedsize = *precomputedsize + 2 * m + 2 * n;
return;
}
}
@@ -1242,20 +1314,19 @@ ae_int_t stackptr, int debugi) {
Recurrent subroutine for precomputing FFT plans
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_float::ftbase_ftbaseprecomputeplanrec(ftplan * plan,
int entryoffset,
ae_int_t stackptr) {
void PIFFT_float::ftbase_ftbaseprecomputeplanrec(ftplan * plan, int entryoffset, ae_int_t stackptr) {
int n1, n2, n, m, offs;
float v, bx, by;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftrealcooleytukeyplan = 5;
if ((curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan || curplan.plan[entryoffset + 3] == ftbase_fftrealcooleytukeyplan) || curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) {
if ((curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan || curplan.plan[entryoffset + 3] == ftbase_fftrealcooleytukeyplan) ||
curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) {
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 5], stackptr);
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 6], stackptr);
return;
@@ -1263,16 +1334,16 @@ ae_int_t stackptr) {
if (curplan.plan[entryoffset + 3] == ftbase_fftcodeletplan || curplan.plan[entryoffset + 3] == ftbase_fhtcodeletplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
if (n == 3) {
offs = curplan.plan[entryoffset + 7];
offs = curplan.plan[entryoffset + 7];
curplan.precomputed[offs + 0] = cos(2 * M_PI / 3) - 1;
curplan.precomputed[offs + 1] = sin(2 * M_PI / 3);
return;
}
if (n == 5) {
offs = curplan.plan[entryoffset + 7];
v = 2 * M_PI / 5;
offs = curplan.plan[entryoffset + 7];
v = 2 * M_PI / 5;
curplan.precomputed[offs + 0] = (cos(v) + cos(2 * v)) / 2 - 1;
curplan.precomputed[offs + 1] = (cos(v) - cos(2 * v)) / 2;
curplan.precomputed[offs + 2] = -sin(v);
@@ -1283,16 +1354,16 @@ ae_int_t stackptr) {
}
if (curplan.plan[entryoffset + 3] == ftbase_fftbluesteinplan) {
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 5], stackptr);
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
offs = curplan.plan[entryoffset + 7];
for (int i = 0; i <= 2 * m - 1; i++)
curplan.precomputed[offs + i] = 0;
for (int i = 0; i < n; i++) {
bx = cos(M_PI * sqr(i) / n);
by = sin(M_PI * sqr(i) / n);
curplan.precomputed[offs + 2 * i + 0] = bx;
curplan.precomputed[offs + 2 * i + 1] = by;
bx = cos(M_PI * sqr(i) / n);
by = sin(M_PI * sqr(i) / n);
curplan.precomputed[offs + 2 * i + 0] = bx;
curplan.precomputed[offs + 2 * i + 1] = by;
curplan.precomputed[offs + 2 * m + 2 * i + 0] = bx;
curplan.precomputed[offs + 2 * m + 2 * i + 1] = by;
if (i > 0) {
@@ -1307,7 +1378,7 @@ ae_int_t stackptr) {
void PIFFT_float::ftbasefactorize(int n, int * n1, int * n2) {
*n1 = *n2 = 0;
*n1 = *n2 = 0;
int ftbase_ftbasecodeletrecommended = 5;
if ((*n1) * (*n2) != n) {
for (int j = ftbase_ftbasecodeletrecommended; j >= 2; j--) {
@@ -1342,19 +1413,16 @@ void PIFFT_float::ftbasefactorize(int n, int * n1, int * n2) {
Is number smooth?
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_float::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best) {
if (seed >= n) {
*best = piMini(*best, seed);
return;
}
if (leastfactor <= 2)
ftbase_ftbasefindsmoothrec(n, seed * 2, 2, best);
if (leastfactor <= 3)
ftbase_ftbasefindsmoothrec(n, seed * 3, 3, best);
if (leastfactor <= 5)
ftbase_ftbasefindsmoothrec(n, seed * 5, 5, best);
if (leastfactor <= 2) ftbase_ftbasefindsmoothrec(n, seed * 2, 2, best);
if (leastfactor <= 3) ftbase_ftbasefindsmoothrec(n, seed * 3, 3, best);
if (leastfactor <= 5) ftbase_ftbasefindsmoothrec(n, seed * 5, 5, best);
}
@@ -1371,37 +1439,42 @@ int PIFFT_float::ftbasefindsmooth(int n) {
void PIFFT_float::ftbase_internalreallintranspose(PIVector<float> * a, int m, int n, int astart, PIVector<float> * buf) {
ftbase_fftirltrec(a, astart, n, buf, 0, m, m, n);
for (int i = 0; i < 2 * m * n; i++) (*a)[astart + i] = (*buf)[i];
for (int i = 0; i < 2 * m * n; i++)
(*a)[astart + i] = (*buf)[i];
}
void PIFFT_float::ftbase_fftirltrec(PIVector<float> * a, int astart, int astride, PIVector<float> * b, int bstart, int bstride, int m, int n) {
void PIFFT_float::ftbase_fftirltrec(PIVector<float> * a,
int astart,
int astride,
PIVector<float> * b,
int bstart,
int bstride,
int m,
int n) {
int idx1, idx2;
int m1, n1;
if (m == 0 || n == 0)
return;
if (m == 0 || n == 0) return;
if (piMaxi(m, n) <= 8) {
for (int i = 0; i <= m - 1; i++) {
idx1 = bstart + i;
idx2 = astart + i * astride;
for (int j = 0; j <= n - 1; j++) {
(*b)[idx1] = a->at(idx2);
idx1 = idx1 + bstride;
idx2 = idx2 + 1;
idx1 = idx1 + bstride;
idx2 = idx2 + 1;
}
}
return;
}
if (n > m) {
n1 = n / 2;
if (n - n1 >= 8 && n1 % 8 != 0)
n1 = n1 + (8 - n1 % 8);
if (n - n1 >= 8 && n1 % 8 != 0) n1 = n1 + (8 - n1 % 8);
ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1);
ftbase_fftirltrec(a, astart + n1, astride, b, bstart + n1 * bstride, bstride, m, n - n1);
} else {
m1 = m / 2;
if (m - m1 >= 8 && m1 % 8 != 0)
m1 = m1 + (8 - m1 % 8);
if (m - m1 >= 8 && m1 % 8 != 0) m1 = m1 + (8 - m1 % 8);
ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n);
ftbase_fftirltrec(a, astart + m1 * astride, astride, b, bstart + m1, bstride, m - m1, n);
}
@@ -1415,10 +1488,16 @@ void PIFFT_float::ftbase_internalcomplexlintranspose(PIVector<float> * a, int m,
}
void PIFFT_float::ftbase_ffticltrec(PIVector<float> * a, int astart, int astride, PIVector<float> * b, int bstart, int bstride, int m, int n) {
void PIFFT_float::ftbase_ffticltrec(PIVector<float> * a,
int astart,
int astride,
PIVector<float> * b,
int bstart,
int bstride,
int m,
int n) {
int idx1, idx2, m2, m1, n1;
if (m == 0 || n == 0)
return;
if (m == 0 || n == 0) return;
if (piMax<int>(m, n) <= 8) {
m2 = 2 * bstride;
for (int i = 0; i <= m - 1; i++) {
@@ -1427,22 +1506,20 @@ void PIFFT_float::ftbase_ffticltrec(PIVector<float> * a, int astart, int astride
for (int j = 0; j <= n - 1; j++) {
(*b)[idx1 + 0] = a->at(idx2 + 0);
(*b)[idx1 + 1] = a->at(idx2 + 1);
idx1 = idx1 + m2;
idx2 = idx2 + 2;
idx1 = idx1 + m2;
idx2 = idx2 + 2;
}
}
return;
}
if (n > m) {
n1 = n / 2;
if (n - n1 >= 8 && n1 % 8 != 0)
n1 = n1 + (8 - n1 % 8);
if (n - n1 >= 8 && n1 % 8 != 0) n1 = n1 + (8 - n1 % 8);
ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1);
ftbase_ffticltrec(a, astart + 2 * n1, astride, b, bstart + 2 * n1 * bstride, bstride, m, n - n1);
} else {
m1 = m / 2;
if (m - m1 >= 8 && m1 % 8 != 0)
m1 = m1 + (8 - m1 % 8);
if (m - m1 >= 8 && m1 % 8 != 0) m1 = m1 + (8 - m1 % 8);
ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n);
ftbase_ffticltrec(a, astart + 2 * m1 * astride, astride, b, bstart + 2 * m1, bstride, m - m1, n);
}
@@ -1460,11 +1537,11 @@ void PIFFT_float::ftbaseexecuteplan(PIVector<float> * a, int aoffset, int n, ftp
Recurrent subroutine for the FTBaseExecutePlan
Parameters:
A FFT'ed array
AOffset offset of the FFT'ed part (distance is measured in floats)
A FFT'ed array
AOffset offset of the FFT'ed part (distance is measured in floats)
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr) {
int n1, n2, n, m, offs, offs1, offs2, offsa, offsb, offsp;
@@ -1474,17 +1551,16 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
float m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y, m5x, m5y;
float s1x, s1y, s2x, s2y, s3x, s3y, s4x, s4y, s5x, s5y;
float c1, c2, c3, c4, c5;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftrealcooleytukeyplan = 5;
int ftbase_fftemptyplan = 6;
int ftbase_fftemptyplan = 6;
PIVector<float> & tmpb(curplan.tmpbuf);
if (curplan.plan[entryoffset + 3] == ftbase_fftemptyplan)
return;
if (curplan.plan[entryoffset + 3] == ftbase_fftemptyplan) return;
if (curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
@@ -1507,26 +1583,26 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
for (int k = 0; k <= n2 - 1; k++)
(*a)[offs + 2 * k + 1] = (*a)[offs + 2 * n2 + 2 * k + 0];
ftbaseexecuteplanrec(a, offs, plan, curplan.plan[entryoffset + 6], stackptr);
tmpb[0] = (*a)[offs + 0];
tmpb[1] = 0;
tmpb[0] = (*a)[offs + 0];
tmpb[1] = 0;
tmpb[2 * n2 + 0] = (*a)[offs + 1];
tmpb[2 * n2 + 1] = 0;
for (int k = 1; k <= n2 - 1; k++) {
offs1 = 2 * k;
offs2 = 2 * n2 + 2 * k;
hk = (*a)[offs + 2 * k + 0];
hnk = (*a)[offs + 2 * (n2 - k) + 0];
offs1 = 2 * k;
offs2 = 2 * n2 + 2 * k;
hk = (*a)[offs + 2 * k + 0];
hnk = (*a)[offs + 2 * (n2 - k) + 0];
tmpb[offs1 + 0] = 0.5 * (hk + hnk);
tmpb[offs2 + 1] = -0.5 * (hk - hnk);
hk = (*a)[offs + 2 * k + 1];
hnk = (*a)[offs + 2 * (n2 - k) + 1];
hk = (*a)[offs + 2 * k + 1];
hnk = (*a)[offs + 2 * (n2 - k) + 1];
tmpb[offs2 + 0] = 0.5 * (hk + hnk);
tmpb[offs1 + 1] = 0.5 * (hk - hnk);
}
for (int k = 0; k < 2 * n2 * 2; k++) (*a)[offs + k] = tmpb[k];
for (int k = 0; k < 2 * n2 * 2; k++)
(*a)[offs + k] = tmpb[k];
}
if (n1 % 2 != 0)
ftbaseexecuteplanrec(a, aoffset + (n1 - 1)*n2 * 2, plan, curplan.plan[entryoffset + 6], stackptr);
if (n1 % 2 != 0) ftbaseexecuteplanrec(a, aoffset + (n1 - 1) * n2 * 2, plan, curplan.plan[entryoffset + 6], stackptr);
ftbase_ffttwcalc(a, aoffset, n2, n1);
ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf));
for (int i = 0; i <= n2 - 1; i++)
@@ -1537,16 +1613,16 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
if (curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf));
for (int i = 0; i <= n2 - 1; i++)
ftbaseexecuteplanrec(a, aoffset + i * n1, plan, curplan.plan[entryoffset + 5], stackptr);
for (int i = 0; i <= n2 - 1; i++) {
for (int j = 0; j <= n1 - 1; j++) {
offsa = aoffset + i * n1;
hk = (*a)[offsa + j];
hnk = (*a)[offsa + (n1 - j) % n1];
offs = 2 * (i * n1 + j);
offsa = aoffset + i * n1;
hk = (*a)[offsa + j];
hnk = (*a)[offsa + (n1 - j) % n1];
offs = 2 * (i * n1 + j);
tmpb[offs + 0] = -0.5 * (hnk - hk);
tmpb[offs + 1] = 0.5 * (hk + hnk);
}
@@ -1555,13 +1631,13 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
for (int j = 0; j <= n1 - 1; j++)
(*a)[aoffset + j] = tmpb[2 * j + 0] + tmpb[2 * j + 1];
if (n2 % 2 == 0) {
offs = 2 * (n2 / 2) * n1;
offs = 2 * (n2 / 2) * n1;
offsa = aoffset + n2 / 2 * n1;
for (int j = 0; j <= n1 - 1; j++)
(*a)[offsa + j] = tmpb[offs + 2 * j + 0] + tmpb[offs + 2 * j + 1];
}
for (int i = 1; i <= (n2 + 1) / 2 - 1; i++) {
offs = 2 * i * n1;
offs = 2 * i * n1;
offs2 = 2 * (n2 - i) * n1;
offsa = aoffset + i * n1;
for (int j = 0; j <= n1 - 1; j++)
@@ -1579,16 +1655,16 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
if (curplan.plan[entryoffset + 3] == ftbase_fftcodeletplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
if (n == 2) {
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
v0 = a0x + a1x;
v1 = a0y + a1y;
v2 = a0x - a1x;
v3 = a0y - a1y;
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
v0 = a0x + a1x;
v1 = a0y + a1y;
v2 = a0x - a1x;
v3 = a0y - a1y;
(*a)[aoffset + 0] = v0;
(*a)[aoffset + 1] = v1;
(*a)[aoffset + 2] = v2;
@@ -1596,29 +1672,29 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
return;
}
if (n == 3) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
t1x = a1x + a2x;
t1y = a1y + a2y;
a0x = a0x + t1x;
a0y = a0y + t1y;
m1x = c1 * t1x;
m1y = c1 * t1y;
m2x = c2 * (a1y - a2y);
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
s1y = a0y + m1y;
a1x = s1x + m2x;
a1y = s1y + m2y;
a2x = s1x - m2x;
a2y = s1y - m2y;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
t1x = a1x + a2x;
t1y = a1y + a2y;
a0x = a0x + t1x;
a0y = a0y + t1y;
m1x = c1 * t1x;
m1y = c1 * t1y;
m2x = c2 * (a1y - a2y);
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
s1y = a0y + m1y;
a1x = s1x + m2x;
a1y = s1y + m2y;
a2x = s1x - m2x;
a2y = s1y - m2y;
(*a)[aoffset + 0] = a0x;
(*a)[aoffset + 1] = a0y;
(*a)[aoffset + 2] = a1x;
@@ -1628,22 +1704,22 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
return;
}
if (n == 4) {
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
a3x = (*a)[aoffset + 6];
a3y = (*a)[aoffset + 7];
t1x = a0x + a2x;
t1y = a0y + a2y;
t2x = a1x + a3x;
t2y = a1y + a3y;
m2x = a0x - a2x;
m2y = a0y - a2y;
m3x = a1y - a3y;
m3y = a3x - a1x;
a0x = (*a)[aoffset + 0];
a0y = (*a)[aoffset + 1];
a1x = (*a)[aoffset + 2];
a1y = (*a)[aoffset + 3];
a2x = (*a)[aoffset + 4];
a2y = (*a)[aoffset + 5];
a3x = (*a)[aoffset + 6];
a3y = (*a)[aoffset + 7];
t1x = a0x + a2x;
t1y = a0y + a2y;
t2x = a1x + a3x;
t2y = a1y + a3y;
m2x = a0x - a2x;
m2y = a0y - a2y;
m3x = a1y - a3y;
m3y = a3x - a1x;
(*a)[aoffset + 0] = t1x + t2x;
(*a)[aoffset + 1] = t1y + t2y;
(*a)[aoffset + 4] = t1x - t2x;
@@ -1655,44 +1731,44 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
return;
}
if (n == 5) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 2] + (*a)[aoffset + 8];
t1y = (*a)[aoffset + 3] + (*a)[aoffset + 9];
t2x = (*a)[aoffset + 4] + (*a)[aoffset + 6];
t2y = (*a)[aoffset + 5] + (*a)[aoffset + 7];
t3x = (*a)[aoffset + 2] - (*a)[aoffset + 8];
t3y = (*a)[aoffset + 3] - (*a)[aoffset + 9];
t4x = (*a)[aoffset + 6] - (*a)[aoffset + 4];
t4y = (*a)[aoffset + 7] - (*a)[aoffset + 5];
t5x = t1x + t2x;
t5y = t1y + t2y;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 2] + (*a)[aoffset + 8];
t1y = (*a)[aoffset + 3] + (*a)[aoffset + 9];
t2x = (*a)[aoffset + 4] + (*a)[aoffset + 6];
t2y = (*a)[aoffset + 5] + (*a)[aoffset + 7];
t3x = (*a)[aoffset + 2] - (*a)[aoffset + 8];
t3y = (*a)[aoffset + 3] - (*a)[aoffset + 9];
t4x = (*a)[aoffset + 6] - (*a)[aoffset + 4];
t4y = (*a)[aoffset + 7] - (*a)[aoffset + 5];
t5x = t1x + t2x;
t5y = t1y + t2y;
(*a)[aoffset + 0] = (*a)[aoffset + 0] + t5x;
(*a)[aoffset + 1] = (*a)[aoffset + 1] + t5y;
m1x = c1 * t5x;
m1y = c1 * t5y;
m2x = c2 * (t1x - t2x);
m2y = c2 * (t1y - t2y);
m3x = -c3 * (t3y + t4y);
m3y = c3 * (t3x + t4x);
m4x = -c4 * t4y;
m4y = c4 * t4x;
m5x = -c5 * t3y;
m5y = c5 * t3x;
s3x = m3x - m4x;
s3y = m3y - m4y;
s5x = m3x + m5x;
s5y = m3y + m5y;
s1x = (*a)[aoffset + 0] + m1x;
s1y = (*a)[aoffset + 1] + m1y;
s2x = s1x + m2x;
s2y = s1y + m2y;
s4x = s1x - m2x;
s4y = s1y - m2y;
m1x = c1 * t5x;
m1y = c1 * t5y;
m2x = c2 * (t1x - t2x);
m2y = c2 * (t1y - t2y);
m3x = -c3 * (t3y + t4y);
m3y = c3 * (t3x + t4x);
m4x = -c4 * t4y;
m4y = c4 * t4x;
m5x = -c5 * t3y;
m5y = c5 * t3x;
s3x = m3x - m4x;
s3y = m3y - m4y;
s5x = m3x + m5x;
s5y = m3y + m5y;
s1x = (*a)[aoffset + 0] + m1x;
s1y = (*a)[aoffset + 1] + m1y;
s2x = s1x + m2x;
s2y = s1y + m2y;
s4x = s1x - m2x;
s4y = s1y - m2y;
(*a)[aoffset + 2] = s2x + s3x;
(*a)[aoffset + 3] = s2y + s3y;
(*a)[aoffset + 4] = s4x + s5x;
@@ -1707,40 +1783,40 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
if (curplan.plan[entryoffset + 3] == ftbase_fhtcodeletplan) {
n1 = curplan.plan[entryoffset + 1];
n2 = curplan.plan[entryoffset + 2];
n = n1 * n2;
n = n1 * n2;
if (n == 2) {
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
(*a)[aoffset + 0] = a0x + a1x;
(*a)[aoffset + 1] = a0x - a1x;
return;
}
if (n == 3) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
t1x = a1x + a2x;
a0x = a0x + t1x;
m1x = c1 * t1x;
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
t1x = a1x + a2x;
a0x = a0x + t1x;
m1x = c1 * t1x;
m2y = c2 * (a2x - a1x);
s1x = a0x + m1x;
(*a)[aoffset + 0] = a0x;
(*a)[aoffset + 1] = s1x - m2y;
(*a)[aoffset + 2] = s1x + m2y;
return;
}
if (n == 4) {
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
a3x = (*a)[aoffset + 3];
t1x = a0x + a2x;
t2x = a1x + a3x;
m2x = a0x - a2x;
m3y = a3x - a1x;
a0x = (*a)[aoffset + 0];
a1x = (*a)[aoffset + 1];
a2x = (*a)[aoffset + 2];
a3x = (*a)[aoffset + 3];
t1x = a0x + a2x;
t2x = a1x + a3x;
m2x = a0x - a2x;
m3y = a3x - a1x;
(*a)[aoffset + 0] = t1x + t2x;
(*a)[aoffset + 1] = m2x - m3y;
(*a)[aoffset + 2] = t1x - t2x;
@@ -1748,26 +1824,26 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
return;
}
if (n == 5) {
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 1] + (*a)[aoffset + 4];
t2x = (*a)[aoffset + 2] + (*a)[aoffset + 3];
t3x = (*a)[aoffset + 1] - (*a)[aoffset + 4];
t4x = (*a)[aoffset + 3] - (*a)[aoffset + 2];
t5x = t1x + t2x;
v0 = (*a)[aoffset + 0] + t5x;
offs = curplan.plan[entryoffset + 7];
c1 = curplan.precomputed[offs + 0];
c2 = curplan.precomputed[offs + 1];
c3 = curplan.precomputed[offs + 2];
c4 = curplan.precomputed[offs + 3];
c5 = curplan.precomputed[offs + 4];
t1x = (*a)[aoffset + 1] + (*a)[aoffset + 4];
t2x = (*a)[aoffset + 2] + (*a)[aoffset + 3];
t3x = (*a)[aoffset + 1] - (*a)[aoffset + 4];
t4x = (*a)[aoffset + 3] - (*a)[aoffset + 2];
t5x = t1x + t2x;
v0 = (*a)[aoffset + 0] + t5x;
(*a)[aoffset + 0] = v0;
m2x = c2 * (t1x - t2x);
m3y = c3 * (t3x + t4x);
s3y = m3y - c4 * t4x;
s5y = m3y + c5 * t3x;
s1x = v0 + c1 * t5x;
s2x = s1x + m2x;
s4x = s1x - m2x;
m2x = c2 * (t1x - t2x);
m3y = c3 * (t3x + t4x);
s3y = m3y - c4 * t4x;
s5y = m3y + c5 * t3x;
s1x = v0 + c1 * t5x;
s2x = s1x + m2x;
s4x = s1x - m2x;
(*a)[aoffset + 1] = s2x - s3y;
(*a)[aoffset + 2] = s4x - s5y;
(*a)[aoffset + 3] = s4x + s5y;
@@ -1776,8 +1852,8 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
}
}
if (curplan.plan[entryoffset + 3] == ftbase_fftbluesteinplan) {
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
n = curplan.plan[entryoffset + 1];
m = curplan.plan[entryoffset + 4];
offs = curplan.plan[entryoffset + 7];
for (int i = stackptr + 2 * n; i <= stackptr + 2 * m - 1; i++)
curplan.stackbuf[i] = 0;
@@ -1785,43 +1861,43 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
offsa = aoffset;
offsb = stackptr;
for (int i = 0; i < n; i++) {
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = (*a)[offsa + 0];
y = (*a)[offsa + 1];
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = (*a)[offsa + 0];
y = (*a)[offsa + 1];
curplan.stackbuf[offsb + 0] = x * bx - y * (-by);
curplan.stackbuf[offsb + 1] = x * (-by) + y * bx;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
}
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset + 5], stackptr + 2 * 2 * m);
offsb = stackptr;
offsp = offs;
for (int i = 0; i <= m - 1; i++) {
x = curplan.stackbuf[offsb + 0];
y = curplan.stackbuf[offsb + 1];
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = curplan.stackbuf[offsb + 0];
y = curplan.stackbuf[offsb + 1];
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
curplan.stackbuf[offsb + 0] = x * bx - y * by;
curplan.stackbuf[offsb + 1] = -(x * by + y * bx);
offsb = offsb + 2;
offsp = offsp + 2;
offsb = offsb + 2;
offsp = offsp + 2;
}
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset + 5], stackptr + 2 * 2 * m);
offsb = stackptr;
offsp = offs + 2 * m;
offsa = aoffset;
for (int i = 0; i < n; i++) {
x = curplan.stackbuf[offsb + 0] / m;
y = -curplan.stackbuf[offsb + 1] / m;
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
x = curplan.stackbuf[offsb + 0] / m;
y = -curplan.stackbuf[offsb + 1] / m;
bx = curplan.precomputed[offsp + 0];
by = curplan.precomputed[offsp + 1];
(*a)[offsa + 0] = x * bx - y * (-by);
(*a)[offsa + 1] = x * (-by) + y * bx;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
offsp = offsp + 2;
offsa = offsa + 2;
offsb = offsb + 2;
}
return;
}
@@ -1832,54 +1908,54 @@ void PIFFT_float::ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan
Twiddle factors calculation
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT_float::ftbase_ffttwcalc(PIVector<float> * a, int aoffset, int n1, int n2) {
int n, idx, offs;
float x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v;
int ftbase_ftbaseupdatetw = 4;
n = n1 * n2;
v = -2 * M_PI / n;
twbasexm1 = -2 * sqr(sin(0.5 * v));
twbasey = sin(v);
twrowxm1 = 0;
twrowy = 0;
n = n1 * n2;
v = -2 * M_PI / n;
twbasexm1 = -2 * sqr(sin(0.5 * v));
twbasey = sin(v);
twrowxm1 = 0;
twrowy = 0;
for (int i = 0, j = 0; i <= n2 - 1; i++) {
twxm1 = 0;
twy = 0;
twy = 0;
for (j = 0; j <= n1 - 1; j++) {
idx = i * n1 + j;
offs = aoffset + 2 * idx;
x = (*a)[offs + 0];
y = (*a)[offs + 1];
tmpx = x * twxm1 - y * twy;
tmpy = x * twy + y * twxm1;
idx = i * n1 + j;
offs = aoffset + 2 * idx;
x = (*a)[offs + 0];
y = (*a)[offs + 1];
tmpx = x * twxm1 - y * twy;
tmpy = x * twy + y * twxm1;
(*a)[offs + 0] = x + tmpx;
(*a)[offs + 1] = y + tmpy;
if (j < n1 - 1) {
if (j % ftbase_ftbaseupdatetw == 0) {
v = -2 * M_PI * i * (j + 1) / n;
v = -2 * M_PI * i * (j + 1) / n;
twxm1 = -2 * sqr(sin(0.5 * v));
twy = sin(v);
twy = sin(v);
} else {
tmpx = twrowxm1 + twxm1 * twrowxm1 - twy * twrowy;
tmpy = twrowy + twxm1 * twrowy + twy * twrowxm1;
tmpx = twrowxm1 + twxm1 * twrowxm1 - twy * twrowy;
tmpy = twrowy + twxm1 * twrowy + twy * twrowxm1;
twxm1 = twxm1 + tmpx;
twy = twy + tmpy;
twy = twy + tmpy;
}
}
}
if (i < n2 - 1) {
if (j % ftbase_ftbaseupdatetw == 0) {
v = -2 * M_PI * (i + 1) / n;
v = -2 * M_PI * (i + 1) / n;
twrowxm1 = -2 * sqr(sin(0.5 * v));
twrowy = sin(v);
twrowy = sin(v);
} else {
tmpx = twbasexm1 + twrowxm1 * twbasexm1 - twrowy * twbasey;
tmpy = twbasey + twrowxm1 * twbasey + twrowy * twbasexm1;
tmpx = twbasexm1 + twrowxm1 * twbasexm1 - twrowy * twbasey;
tmpy = twbasey + twrowxm1 * twbasey + twrowy * twbasexm1;
twrowxm1 = twrowxm1 + tmpx;
twrowy = twrowy + tmpy;
twrowy = twrowy + tmpy;
}
}
}

View File

@@ -6,22 +6,22 @@
* \~russian БПФ, ОБПФ и преобразования Гильберта
*/
/*
PIP - Platform Independent Primitives
Class for FFT, IFFT and Hilbert transformations
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Class for FFT, IFFT and Hilbert transformations
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup FFTW FFTW
//! \~\brief
@@ -62,21 +62,20 @@
#ifndef MICRO_PIP
#include "pip_fftw_export.h"
# include "pip_fftw_export.h"
class PIP_EXPORT PIFFT_double
{
class PIP_EXPORT PIFFT_double {
public:
PIFFT_double();
PIVector<complexd> * calcFFT(const PIVector<complexd> &val);
PIVector<complexd> * calcFFT(const PIVector<double> &val);
PIVector<complexd> * calcFFTinverse(const PIVector<complexd> &val);
PIVector<complexd> * calcHilbert(const PIVector<double> &val);
PIVector<complexd> * calcFFT(const PIVector<complexd> & val);
PIVector<complexd> * calcFFT(const PIVector<double> & val);
PIVector<complexd> * calcFFTinverse(const PIVector<complexd> & val);
PIVector<complexd> * calcHilbert(const PIVector<double> & val);
PIVector<double> getAmplitude() const;
PIVector<double> getReal() const;
PIVector<double> getImag() const;
private:
PIVector<complexd> result;
typedef ptrdiff_t ae_int_t;
@@ -90,35 +89,43 @@ private:
ftplan curplan;
void fftc1d(const PIVector<complexd> &a, uint n);
void fftc1r(const PIVector<double> &a, uint n);
void fftc1dinv(const PIVector<complexd> &a, uint n);
void fftc1d(const PIVector<complexd> & a, uint n);
void fftc1r(const PIVector<double> & a, uint n);
void fftc1dinv(const PIVector<complexd> & a, uint n);
void createPlan(uint n);
void ftbasegeneratecomplexfftplan(uint n, ftplan *plan);
void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan *plan, int *plansize, int *precomputedsize, int *planarraysize, int *tmpmemsize, int *stackmemsize, ae_int_t stackptr, int debugi=0);
void ftbase_ftbaseprecomputeplanrec(ftplan *plan, int entryoffset, ae_int_t stackptr);
void ftbasefactorize(int n, int *n1, int *n2);
void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int *best);
void ftbasegeneratecomplexfftplan(uint n, ftplan * plan);
void ftbase_ftbasegenerateplanrec(int n,
int tasktype,
ftplan * plan,
int * plansize,
int * precomputedsize,
int * planarraysize,
int * tmpmemsize,
int * stackmemsize,
ae_int_t stackptr,
int debugi = 0);
void ftbase_ftbaseprecomputeplanrec(ftplan * plan, int entryoffset, ae_int_t stackptr);
void ftbasefactorize(int n, int * n1, int * n2);
void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best);
int ftbasefindsmooth(int n);
void ftbaseexecuteplan(PIVector<double> *a, int aoffset, int n, ftplan *plan);
void ftbaseexecuteplanrec(PIVector<double> *a, int aoffset, ftplan *plan, int entryoffset, ae_int_t stackptr);
void ftbase_internalcomplexlintranspose(PIVector<double> *a, int m, int n, int astart, PIVector<double> *buf);
void ftbase_ffticltrec(PIVector<double> *a, int astart, int astride, PIVector<double> *b, int bstart, int bstride, int m, int n);
void ftbase_internalreallintranspose(PIVector<double> *a, int m, int n, int astart, PIVector<double> *buf);
void ftbase_fftirltrec(PIVector<double> *a, int astart, int astride, PIVector<double> *b, int bstart, int bstride, int m, int n);
void ftbase_ffttwcalc(PIVector<double> *a, int aoffset, int n1, int n2);
void ftbaseexecuteplan(PIVector<double> * a, int aoffset, int n, ftplan * plan);
void ftbaseexecuteplanrec(PIVector<double> * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr);
void ftbase_internalcomplexlintranspose(PIVector<double> * a, int m, int n, int astart, PIVector<double> * buf);
void ftbase_ffticltrec(PIVector<double> * a, int astart, int astride, PIVector<double> * b, int bstart, int bstride, int m, int n);
void ftbase_internalreallintranspose(PIVector<double> * a, int m, int n, int astart, PIVector<double> * buf);
void ftbase_fftirltrec(PIVector<double> * a, int astart, int astride, PIVector<double> * b, int bstart, int bstride, int m, int n);
void ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2);
};
class PIP_EXPORT PIFFT_float
{
class PIP_EXPORT PIFFT_float {
public:
PIFFT_float();
PIVector<complexf> * calcFFT(const PIVector<complexf> &val);
PIVector<complexf> * calcFFT(const PIVector<float> &val);
PIVector<complexf> * calcFFTinverse(const PIVector<complexf> &val);
PIVector<complexf> * calcHilbert(const PIVector<float> &val);
PIVector<complexf> * calcFFT(const PIVector<complexf> & val);
PIVector<complexf> * calcFFT(const PIVector<float> & val);
PIVector<complexf> * calcFFTinverse(const PIVector<complexf> & val);
PIVector<complexf> * calcHilbert(const PIVector<float> & val);
PIVector<float> getAmplitude() const;
PIVector<float> getReal() const;
PIVector<float> getImag() const;
@@ -136,63 +143,79 @@ private:
ftplan curplan;
void fftc1d(const PIVector<complexf> &a, uint n);
void fftc1r(const PIVector<float> &a, uint n);
void fftc1dinv(const PIVector<complexf> &a, uint n);
void fftc1d(const PIVector<complexf> & a, uint n);
void fftc1r(const PIVector<float> & a, uint n);
void fftc1dinv(const PIVector<complexf> & a, uint n);
void createPlan(uint n);
void ftbasegeneratecomplexfftplan(uint n, ftplan *plan);
void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan *plan, int *plansize, int *precomputedsize, int *planarraysize, int *tmpmemsize, int *stackmemsize, ae_int_t stackptr, int debugi=0);
void ftbase_ftbaseprecomputeplanrec(ftplan *plan, int entryoffset, ae_int_t stackptr);
void ftbasefactorize(int n, int *n1, int *n2);
void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int *best);
void ftbasegeneratecomplexfftplan(uint n, ftplan * plan);
void ftbase_ftbasegenerateplanrec(int n,
int tasktype,
ftplan * plan,
int * plansize,
int * precomputedsize,
int * planarraysize,
int * tmpmemsize,
int * stackmemsize,
ae_int_t stackptr,
int debugi = 0);
void ftbase_ftbaseprecomputeplanrec(ftplan * plan, int entryoffset, ae_int_t stackptr);
void ftbasefactorize(int n, int * n1, int * n2);
void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best);
int ftbasefindsmooth(int n);
void ftbaseexecuteplan(PIVector<float> *a, int aoffset, int n, ftplan *plan);
void ftbaseexecuteplanrec(PIVector<float> *a, int aoffset, ftplan *plan, int entryoffset, ae_int_t stackptr);
void ftbase_internalcomplexlintranspose(PIVector<float> *a, int m, int n, int astart, PIVector<float> *buf);
void ftbase_ffticltrec(PIVector<float> *a, int astart, int astride, PIVector<float> *b, int bstart, int bstride, int m, int n);
void ftbase_internalreallintranspose(PIVector<float> *a, int m, int n, int astart, PIVector<float> *buf);
void ftbase_fftirltrec(PIVector<float> *a, int astart, int astride, PIVector<float> *b, int bstart, int bstride, int m, int n);
void ftbase_ffttwcalc(PIVector<float> *a, int aoffset, int n1, int n2);
void ftbaseexecuteplan(PIVector<float> * a, int aoffset, int n, ftplan * plan);
void ftbaseexecuteplanrec(PIVector<float> * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr);
void ftbase_internalcomplexlintranspose(PIVector<float> * a, int m, int n, int astart, PIVector<float> * buf);
void ftbase_ffticltrec(PIVector<float> * a, int astart, int astride, PIVector<float> * b, int bstart, int bstride, int m, int n);
void ftbase_internalreallintranspose(PIVector<float> * a, int m, int n, int astart, PIVector<float> * buf);
void ftbase_fftirltrec(PIVector<float> * a, int astart, int astride, PIVector<float> * b, int bstart, int bstride, int m, int n);
void ftbase_ffttwcalc(PIVector<float> * a, int aoffset, int n1, int n2);
};
typedef PIFFT_double PIFFT;
typedef PIFFT_double PIFFTd;
typedef PIFFT_float PIFFTf;
#ifndef CC_VC
# ifndef CC_VC
#define _PIFFTW_H(type) class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \
public: \
_PIFFTW_P_##type##_(); \
~_PIFFTW_P_##type##_(); \
const PIVector<complex<type> > & calcFFT(const PIVector<complex<type> > & in); \
const PIVector<complex<type> > & calcFFTR(const PIVector<type> & in); \
const PIVector<complex<type> > & calcFFTI(const PIVector<complex<type> > & in); \
void preparePlan(int size, int op); \
void * impl; \
};
# define _PIFFTW_H(type) \
class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \
public: \
_PIFFTW_P_##type##_(); \
~_PIFFTW_P_##type##_(); \
const PIVector<complex<type>> & calcFFT(const PIVector<complex<type>> & in); \
const PIVector<complex<type>> & calcFFTR(const PIVector<type> & in); \
const PIVector<complex<type>> & calcFFTI(const PIVector<complex<type>> & in); \
void preparePlan(int size, int op); \
void * impl; \
};
_PIFFTW_H(float)
_PIFFTW_H(double)
_PIFFTW_H(ldouble)
template <typename T>
class PIFFTW
{
template<typename T>
class PIFFTW {
public:
explicit PIFFTW() {p = 0; newP(p);}
~PIFFTW() {deleteP(p);}
explicit PIFFTW() {
p = 0;
newP(p);
}
~PIFFTW() { deleteP(p); }
inline const PIVector<complex<T> > & calcFFT(const PIVector<complex<T> > & in) {return PIVector<complex<T> >().resize(in.size());}
inline const PIVector<complex<T> > & calcFFT(const PIVector<T> & in) {return PIVector<complex<T> >().resize(in.size());}
inline const PIVector<complex<T> > & calcFFTinverse(const PIVector<complex<T> > & in) {return PIVector<complex<T> >().resize(in.size());}
inline const PIVector<complex<T>> & calcFFT(const PIVector<complex<T>> & in) { return PIVector<complex<T>>().resize(in.size()); }
inline const PIVector<complex<T>> & calcFFT(const PIVector<T> & in) { return PIVector<complex<T>>().resize(in.size()); }
inline const PIVector<complex<T>> & calcFFTinverse(const PIVector<complex<T>> & in) { return PIVector<complex<T>>().resize(in.size()); }
enum FFT_Operation {foReal, foComplex, foInverse};
enum FFT_Operation {
foReal,
foComplex,
foInverse
};
inline void preparePlan(int size, FFT_Operation op) {}
private:
void operator =(const PIFFTW & );
void operator=(const PIFFTW &);
PIFFTW(const PIFFTW &);
inline void newP(void *& _p) {}
inline void deleteP(void *& _p) {}
@@ -201,36 +224,93 @@ private:
};
template<> inline const PIVector<complex<float> > & PIFFTW<float>::calcFFT(const PIVector<complex<float> > & in) {return ((_PIFFTW_P_float_*)p)->calcFFT(in);}
template<> inline const PIVector<complex<float> > & PIFFTW<float>::calcFFT(const PIVector<float> & in) {return ((_PIFFTW_P_float_*)p)->calcFFTR(in);}
template<> inline const PIVector<complex<float> > & PIFFTW<float>::calcFFTinverse(const PIVector<complex<float> > & in) {return ((_PIFFTW_P_float_*)p)->calcFFTI(in);}
template<> inline void PIFFTW<float>::preparePlan(int size, FFT_Operation op) {((_PIFFTW_P_float_*)p)->preparePlan(size, op);}
template<> inline void PIFFTW<float>::newP(void *& _p) {_p = new _PIFFTW_P_float_();}
template<> inline void PIFFTW<float>::deleteP(void *& _p) {if (_p) delete (_PIFFTW_P_float_*)_p; _p = 0;}
template<>
inline const PIVector<complex<float>> & PIFFTW<float>::calcFFT(const PIVector<complex<float>> & in) {
return ((_PIFFTW_P_float_ *)p)->calcFFT(in);
}
template<>
inline const PIVector<complex<float>> & PIFFTW<float>::calcFFT(const PIVector<float> & in) {
return ((_PIFFTW_P_float_ *)p)->calcFFTR(in);
}
template<>
inline const PIVector<complex<float>> & PIFFTW<float>::calcFFTinverse(const PIVector<complex<float>> & in) {
return ((_PIFFTW_P_float_ *)p)->calcFFTI(in);
}
template<>
inline void PIFFTW<float>::preparePlan(int size, FFT_Operation op) {
((_PIFFTW_P_float_ *)p)->preparePlan(size, op);
}
template<>
inline void PIFFTW<float>::newP(void *& _p) {
_p = new _PIFFTW_P_float_();
}
template<>
inline void PIFFTW<float>::deleteP(void *& _p) {
if (_p) delete (_PIFFTW_P_float_ *)_p;
_p = 0;
}
typedef PIFFTW<float> PIFFTWf;
typedef PIFFTW<float> PIFFTWf;
template<> inline const PIVector<complex<double> > & PIFFTW<double>::calcFFT(const PIVector<complex<double> > & in) {return ((_PIFFTW_P_double_*)p)->calcFFT(in);}
template<> inline const PIVector<complex<double> > & PIFFTW<double>::calcFFT(const PIVector<double> & in) {return ((_PIFFTW_P_double_*)p)->calcFFTR(in);}
template<> inline const PIVector<complex<double> > & PIFFTW<double>::calcFFTinverse(const PIVector<complex<double> > & in) {return ((_PIFFTW_P_double_*)p)->calcFFTI(in);}
template<> inline void PIFFTW<double>::preparePlan(int size, FFT_Operation op) {((_PIFFTW_P_double_*)p)->preparePlan(size, op);}
template<> inline void PIFFTW<double>::newP(void *& _p) {_p = new _PIFFTW_P_double_();}
template<> inline void PIFFTW<double>::deleteP(void *& _p) {if (_p) delete (_PIFFTW_P_double_*)_p; _p = 0;}
template<>
inline const PIVector<complex<double>> & PIFFTW<double>::calcFFT(const PIVector<complex<double>> & in) {
return ((_PIFFTW_P_double_ *)p)->calcFFT(in);
}
template<>
inline const PIVector<complex<double>> & PIFFTW<double>::calcFFT(const PIVector<double> & in) {
return ((_PIFFTW_P_double_ *)p)->calcFFTR(in);
}
template<>
inline const PIVector<complex<double>> & PIFFTW<double>::calcFFTinverse(const PIVector<complex<double>> & in) {
return ((_PIFFTW_P_double_ *)p)->calcFFTI(in);
}
template<>
inline void PIFFTW<double>::preparePlan(int size, FFT_Operation op) {
((_PIFFTW_P_double_ *)p)->preparePlan(size, op);
}
template<>
inline void PIFFTW<double>::newP(void *& _p) {
_p = new _PIFFTW_P_double_();
}
template<>
inline void PIFFTW<double>::deleteP(void *& _p) {
if (_p) delete (_PIFFTW_P_double_ *)_p;
_p = 0;
}
typedef PIFFTW<double> PIFFTWd;
typedef PIFFTW<double> PIFFTWd;
template<> inline const PIVector<complex<ldouble> > & PIFFTW<ldouble>::calcFFT(const PIVector<complex<ldouble> > & in) {return ((_PIFFTW_P_ldouble_*)p)->calcFFT(in);}
template<> inline const PIVector<complex<ldouble> > & PIFFTW<ldouble>::calcFFT(const PIVector<ldouble> & in) {return ((_PIFFTW_P_ldouble_*)p)->calcFFTR(in);}
template<> inline const PIVector<complex<ldouble> > & PIFFTW<ldouble>::calcFFTinverse(const PIVector<complex<ldouble> > & in) {return ((_PIFFTW_P_ldouble_*)p)->calcFFTI(in);}
template<> inline void PIFFTW<ldouble>::preparePlan(int size, FFT_Operation op) {((_PIFFTW_P_ldouble_*)p)->preparePlan(size, op);}
template<> inline void PIFFTW<ldouble>::newP(void *& _p) {_p = new _PIFFTW_P_ldouble_();}
template<> inline void PIFFTW<ldouble>::deleteP(void *& _p) {if (_p) delete (_PIFFTW_P_ldouble_*)_p; _p = 0;}
template<>
inline const PIVector<complex<ldouble>> & PIFFTW<ldouble>::calcFFT(const PIVector<complex<ldouble>> & in) {
return ((_PIFFTW_P_ldouble_ *)p)->calcFFT(in);
}
template<>
inline const PIVector<complex<ldouble>> & PIFFTW<ldouble>::calcFFT(const PIVector<ldouble> & in) {
return ((_PIFFTW_P_ldouble_ *)p)->calcFFTR(in);
}
template<>
inline const PIVector<complex<ldouble>> & PIFFTW<ldouble>::calcFFTinverse(const PIVector<complex<ldouble>> & in) {
return ((_PIFFTW_P_ldouble_ *)p)->calcFFTI(in);
}
template<>
inline void PIFFTW<ldouble>::preparePlan(int size, FFT_Operation op) {
((_PIFFTW_P_ldouble_ *)p)->preparePlan(size, op);
}
template<>
inline void PIFFTW<ldouble>::newP(void *& _p) {
_p = new _PIFFTW_P_ldouble_();
}
template<>
inline void PIFFTW<ldouble>::deleteP(void *& _p) {
if (_p) delete (_PIFFTW_P_ldouble_ *)_p;
_p = 0;
}
typedef PIFFTW<ldouble> PIFFTWld;
#endif
# endif
#endif // MICRO_PIP

View File

@@ -15,30 +15,30 @@
* \~russian
* Иван Пелипенко peri4ko@yandex.ru;
* Андрей Бычков work.a.b@yandex.ru;
*/
*/
/*
PIP - Platform Independent Primitives
Geometry base classes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Geometry base classes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIGEOMETRY_H
#define PIGEOMETRY_H
#include "pipoint.h"
#include "piline.h"
#include "pipoint.h"
#include "pirect.h"
#endif // PIGEOMETRY_H

View File

@@ -3,24 +3,24 @@
* \brief
* \~english Two-dimensional line class
* \~russian Класс отрезка двумерной линии
*/
*/
/*
PIP - Platform Independent Primitives
Two-dimensional line class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Two-dimensional line class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PILINE_H
#define PILINE_H
@@ -38,13 +38,14 @@
template<typename Type>
class PIP_EXPORT PILine {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
PIPoint<Type> p0;
PIPoint<Type> p1;
//! \~russian
//! Пустой конструктор.
//! \details
//! \details
//! При выполнении пустого конструктора координаты не изменяются.
//! Начало и конец совпадают.
PILine() {}
@@ -81,17 +82,15 @@ public:
//! \~russian
//! Проверить на совпадение координат начала и конца.
bool isEmpty() const {
return (p0 == p1);
}
bool isEmpty() const { return (p0 == p1); }
//! \~russian
//! Вычислить ширину прямоугольника, диагональю которого является данный отрезок.
Type width() const {return piAbs<Type>(p1.x - p0.x);}
Type width() const { return piAbs<Type>(p1.x - p0.x); }
//! \~russian
//! Вычислить высоту прямоугольника, диагональю которого является данный отрезок.
Type height() const {return piAbs<Type>(p1.y - p0.y);}
Type height() const { return piAbs<Type>(p1.y - p0.y); }
//! \~russian
//! Сдвинуть линию на \a x, \a y.
@@ -127,12 +126,12 @@ public:
//! \~russian
//! Сдвинуть линию на \a x, \a y.
//! \details Является копией метода \a translate().
PILine<Type> & move(Type x, Type y) {return translate(x, y);}
PILine<Type> & move(Type x, Type y) { return translate(x, y); }
//! \~russian
//! Сдвинуть линию на значение координат точки \a PIPoint.
//! \details Является копией метода \a translate().
PILine<Type> & move(const PIPoint<Type> & p) {return translate(p);}
PILine<Type> & move(const PIPoint<Type> & p) { return translate(p); }
//! \~russian
//! Создать копию отрезка и сдвинуть её на \a x, \a y.
@@ -142,7 +141,7 @@ public:
l.translate(x, y);
return l;
}
//! \~russian
//! Создать копию отрезка и сдвинуть её на значение координат точки \a PIPoint.
//! \details Является копией метода \a translated().
@@ -153,33 +152,33 @@ public:
}
//! \~russian Сдвинуть линию по двум координатам на значение \a x.
void operator +=(Type x) {translate(x, x);}
void operator+=(Type x) { translate(x, x); }
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
void operator +=(const PIPoint<Type> & p) {translate(p);}
void operator+=(const PIPoint<Type> & p) { translate(p); }
//! \~russian Сдвинуть линию по двум координатам на значение \a x.
void operator -=(Type x) {translate(-x, -x);}
void operator-=(Type x) { translate(-x, -x); }
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
void operator -=(const PIPoint<Type> & p) {translate(-p);}
void operator-=(const PIPoint<Type> & p) { translate(-p); }
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
PILine<Type> operator +(const PIPoint<Type> & p) {return translated(p);}
PILine<Type> operator+(const PIPoint<Type> & p) { return translated(p); }
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
PILine<Type> operator -(const PIPoint<Type> & p) {return translated(-p);}
PILine<Type> operator-(const PIPoint<Type> & p) { return translated(-p); }
//! \~russian Проверить равенство координат двух отрезков.
bool operator ==(const PILine<Type> & r) const {return (p0 == r.p0 && p1 == r.p1);}
bool operator==(const PILine<Type> & r) const { return (p0 == r.p0 && p1 == r.p1); }
//! \~russian Проверить неравенство координат двух отрезков.
bool operator !=(const PILine<Type> & r) const {return (p1 != r.p1 || p1 != r.p1);}
bool operator!=(const PILine<Type> & r) const { return (p1 != r.p1 || p1 != r.p1); }
};
//! \~russian Перегруженный оператор для вывода координат в \a PICout.
template<typename Type>
PICout operator <<(PICout & s, const PILine<Type> & v) {
PICout operator<<(PICout & s, const PILine<Type> & v) {
s.saveAndSetControls(0);
s << "Line{" << v.p0 << ", " << v.p1 << "}";
s.restoreControls();

View File

@@ -1,24 +1,26 @@
/*
PIP - Platform Independent Primitives
Basic mathematical functions and defines
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Basic mathematical functions and defines
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pimathbase.h"
#include "pitime.h"
#include <stdlib.h>
@@ -39,60 +41,60 @@ double piJ0(const double & v) {
double q2;
double p3;
double q3;
xsq_ = 64. / (x * x);
p2 = 0.0;
p2 = 2485.271928957404011288128951 + xsq_ * p2;
p2 = 153982.6532623911470917825993 + xsq_ * p2;
p2 = 2016135.283049983642487182349 + xsq_ * p2;
p2 = 8413041.456550439208464315611 + xsq_ * p2;
p2 = 12332384.76817638145232406055 + xsq_ * p2;
p2 = 5393485.083869438325262122897 + xsq_ * p2;
q2 = 1.0;
q2 = 2615.700736920839685159081813 + xsq_ * q2;
q2 = 156001.7276940030940592769933 + xsq_ * q2;
q2 = 2025066.801570134013891035236 + xsq_ * q2;
q2 = 8426449.050629797331554404810 + xsq_ * q2;
q2 = 12338310.22786324960844856182 + xsq_ * q2;
q2 = 5393485.083869438325560444960 + xsq_ * q2;
p3 = -0.0;
p3 = -4.887199395841261531199129300 +xsq_ * p3;
p3 = -226.2630641933704113967255053 +xsq_ * p3;
p3 = -2365.956170779108192723612816 +xsq_ * p3;
p3 = -8239.066313485606568803548860 +xsq_ * p3;
p3 = -10381.41698748464093880530341 +xsq_ * p3;
p3 = -3984.617357595222463506790588 +xsq_ * p3;
q3 = 1.0;
q3 = 408.7714673983499223402830260 + xsq_ * q3;
q3 = 15704.89191515395519392882766 + xsq_ * q3;
q3 = 156021.3206679291652539287109 + xsq_ * q3;
q3 = 533291.3634216897168722255057 + xsq_ * q3;
q3 = 666745.4239319826986004038103 + xsq_ * q3;
q3 = 255015.5108860942382983170882 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8. * p3 / q3 / x;
nn = x- M_PI / 4.;
xsq_ = 64. / (x * x);
p2 = 0.0;
p2 = 2485.271928957404011288128951 + xsq_ * p2;
p2 = 153982.6532623911470917825993 + xsq_ * p2;
p2 = 2016135.283049983642487182349 + xsq_ * p2;
p2 = 8413041.456550439208464315611 + xsq_ * p2;
p2 = 12332384.76817638145232406055 + xsq_ * p2;
p2 = 5393485.083869438325262122897 + xsq_ * p2;
q2 = 1.0;
q2 = 2615.700736920839685159081813 + xsq_ * q2;
q2 = 156001.7276940030940592769933 + xsq_ * q2;
q2 = 2025066.801570134013891035236 + xsq_ * q2;
q2 = 8426449.050629797331554404810 + xsq_ * q2;
q2 = 12338310.22786324960844856182 + xsq_ * q2;
q2 = 5393485.083869438325560444960 + xsq_ * q2;
p3 = -0.0;
p3 = -4.887199395841261531199129300 + xsq_ * p3;
p3 = -226.2630641933704113967255053 + xsq_ * p3;
p3 = -2365.956170779108192723612816 + xsq_ * p3;
p3 = -8239.066313485606568803548860 + xsq_ * p3;
p3 = -10381.41698748464093880530341 + xsq_ * p3;
p3 = -3984.617357595222463506790588 + xsq_ * p3;
q3 = 1.0;
q3 = 408.7714673983499223402830260 + xsq_ * q3;
q3 = 15704.89191515395519392882766 + xsq_ * q3;
q3 = 156021.3206679291652539287109 + xsq_ * q3;
q3 = 533291.3634216897168722255057 + xsq_ * q3;
q3 = 666745.4239319826986004038103 + xsq_ * q3;
q3 = 255015.5108860942382983170882 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8. * p3 / q3 / x;
nn = x - M_PI / 4.;
result = sqrt(2. / M_PI / x) * (pzero * cos(nn) - qzero * sin(nn));
return result;
}
xsq = x * x;
p1 = 26857.86856980014981415848441;
p1 = -40504123.71833132706360663322 + xsq * p1;
p1 = 25071582855.36881945555156435 + xsq * p1;
p1 = -8085222034853.793871199468171 + xsq * p1;
p1 = 1434354939140344.111664316553 + xsq * p1;
p1 = -136762035308817138.6865416609 + xsq * p1;
p1 = 6382059341072356562.289432465 + xsq * p1;
p1 = -117915762910761053603.8440800 + xsq * p1;
p1 = 493378725179413356181.6813446 + xsq * p1;
q1 = 1.;
q1 = 1363.063652328970604442810507 + xsq * q1;
q1 = 1114636.098462985378182402543 + xsq * q1;
q1 = 669998767.2982239671814028660 + xsq * q1;
q1 = 312304311494.1213172572469442 + xsq * q1;
q1 = 112775673967979.8507056031594 + xsq * q1;
q1 = 30246356167094626.98627330784 + xsq * q1;
q1 = 5428918384092285160.200195092 + xsq * q1;
q1 = 493378725179413356211.3278438 + xsq * q1;
p1 = 26857.86856980014981415848441;
p1 = -40504123.71833132706360663322 + xsq * p1;
p1 = 25071582855.36881945555156435 + xsq * p1;
p1 = -8085222034853.793871199468171 + xsq * p1;
p1 = 1434354939140344.111664316553 + xsq * p1;
p1 = -136762035308817138.6865416609 + xsq * p1;
p1 = 6382059341072356562.289432465 + xsq * p1;
p1 = -117915762910761053603.8440800 + xsq * p1;
p1 = 493378725179413356181.6813446 + xsq * p1;
q1 = 1.;
q1 = 1363.063652328970604442810507 + xsq * q1;
q1 = 1114636.098462985378182402543 + xsq * q1;
q1 = 669998767.2982239671814028660 + xsq * q1;
q1 = 312304311494.1213172572469442 + xsq * q1;
q1 = 112775673967979.8507056031594 + xsq * q1;
q1 = 30246356167094626.98627330784 + xsq * q1;
q1 = 5428918384092285160.200195092 + xsq * q1;
q1 = 493378725179413356211.3278438 + xsq * q1;
return p1 / q1;
#else
return j0(v);
@@ -112,68 +114,66 @@ double piJ1(const double & v) {
double q1;
double result;
s = sign(x);
if (x < 0)
x = -x;
if (x < 0) x = -x;
if (x > 8.) {
double xsq_;
double p2;
double q2;
double p3;
double q3;
xsq_ = 64.0 / (x * x);
p2 = -1611.616644324610116477412898;
p2 = -109824.0554345934672737413139 + xsq_ * p2;
p2 = -1523529.351181137383255105722 + xsq_ * p2;
p2 = -6603373.248364939109255245434 + xsq_ * p2;
p2 = -9942246.505077641195658377899 + xsq_ * p2;
p2 = -4435757.816794127857114720794 + xsq_ * p2;
q2 = 1.0;
q2 = -1455.009440190496182453565068 + xsq_ * q2;
q2 = -107263.8599110382011903063867 + xsq_ * q2;
q2 = -1511809.506634160881644546358 + xsq_ * q2;
q2 = -6585339.479723087072826915069 + xsq_ * q2;
q2 = -9934124.389934585658967556309 + xsq_ * q2;
q2 = -4435757.816794127856828016962 + xsq_ * q2;
p3 = 35.26513384663603218592175580;
p3 = 1706.375429020768002061283546 + xsq_ * p3;
p3 = 18494.26287322386679652009819 + xsq_ * p3;
p3 = 66178.83658127083517939992166 + xsq_ * p3;
p3 = 85145.16067533570196555001171 + xsq_ * p3;
p3 = 33220.91340985722351859704442 + xsq_ * p3;
q3 = 1.0;
q3 = 863.8367769604990967475517183 + xsq_ * q3;
q3 = 37890.22974577220264142952256 + xsq_ * q3;
q3 = 400294.4358226697511708610813 + xsq_ * q3;
q3 = 1419460.669603720892855755253 + xsq_ * q3;
q3 = 1819458.042243997298924553839 + xsq_ * q3;
q3 = 708712.8194102874357377502472 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8 * p3 / q3 / x;
nn = x - 3 * M_PI / 4;
xsq_ = 64.0 / (x * x);
p2 = -1611.616644324610116477412898;
p2 = -109824.0554345934672737413139 + xsq_ * p2;
p2 = -1523529.351181137383255105722 + xsq_ * p2;
p2 = -6603373.248364939109255245434 + xsq_ * p2;
p2 = -9942246.505077641195658377899 + xsq_ * p2;
p2 = -4435757.816794127857114720794 + xsq_ * p2;
q2 = 1.0;
q2 = -1455.009440190496182453565068 + xsq_ * q2;
q2 = -107263.8599110382011903063867 + xsq_ * q2;
q2 = -1511809.506634160881644546358 + xsq_ * q2;
q2 = -6585339.479723087072826915069 + xsq_ * q2;
q2 = -9934124.389934585658967556309 + xsq_ * q2;
q2 = -4435757.816794127856828016962 + xsq_ * q2;
p3 = 35.26513384663603218592175580;
p3 = 1706.375429020768002061283546 + xsq_ * p3;
p3 = 18494.26287322386679652009819 + xsq_ * p3;
p3 = 66178.83658127083517939992166 + xsq_ * p3;
p3 = 85145.16067533570196555001171 + xsq_ * p3;
p3 = 33220.91340985722351859704442 + xsq_ * p3;
q3 = 1.0;
q3 = 863.8367769604990967475517183 + xsq_ * q3;
q3 = 37890.22974577220264142952256 + xsq_ * q3;
q3 = 400294.4358226697511708610813 + xsq_ * q3;
q3 = 1419460.669603720892855755253 + xsq_ * q3;
q3 = 1819458.042243997298924553839 + xsq_ * q3;
q3 = 708712.8194102874357377502472 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8 * p3 / q3 / x;
nn = x - 3 * M_PI / 4;
result = sqrt(2 / M_PI / x) * (pzero * cos(nn) - qzero * sin(nn));
if (s < 0)
result = -result;
if (s < 0) result = -result;
return result;
}
xsq = sqr(x);
p1 = 2701.122710892323414856790990;
p1 = -4695753.530642995859767162166 + xsq * p1;
p1 = 3413234182.301700539091292655 + xsq * p1;
p1 = -1322983480332.126453125473247 + xsq * p1;
p1 = 290879526383477.5409737601689 + xsq * p1;
p1 = -35888175699101060.50743641413 + xsq * p1;
p1 = 2316433580634002297.931815435 + xsq * p1;
p1 = -66721065689249162980.20941484 + xsq * p1;
p1 = 581199354001606143928.050809 + xsq * p1;
q1 = 1.0;
q1 = 1606.931573481487801970916749 + xsq * q1;
q1 = 1501793.594998585505921097578 + xsq * q1;
q1 = 1013863514.358673989967045588 + xsq * q1;
q1 = 524371026216.7649715406728642 + xsq * q1;
q1 = 208166122130760.7351240184229 + xsq * q1;
q1 = 60920613989175217.46105196863 + xsq * q1;
q1 = 11857707121903209998.37113348 + xsq * q1;
q1 = 1162398708003212287858.529400 + xsq * q1;
xsq = sqr(x);
p1 = 2701.122710892323414856790990;
p1 = -4695753.530642995859767162166 + xsq * p1;
p1 = 3413234182.301700539091292655 + xsq * p1;
p1 = -1322983480332.126453125473247 + xsq * p1;
p1 = 290879526383477.5409737601689 + xsq * p1;
p1 = -35888175699101060.50743641413 + xsq * p1;
p1 = 2316433580634002297.931815435 + xsq * p1;
p1 = -66721065689249162980.20941484 + xsq * p1;
p1 = 581199354001606143928.050809 + xsq * p1;
q1 = 1.0;
q1 = 1606.931573481487801970916749 + xsq * q1;
q1 = 1501793.594998585505921097578 + xsq * q1;
q1 = 1013863514.358673989967045588 + xsq * q1;
q1 = 524371026216.7649715406728642 + xsq * q1;
q1 = 208166122130760.7351240184229 + xsq * q1;
q1 = 60920613989175217.46105196863 + xsq * q1;
q1 = 11857707121903209998.37113348 + xsq * q1;
q1 = 1162398708003212287858.529400 + xsq * q1;
result = s * x * p1 / q1;
return result;
#else
@@ -203,8 +203,7 @@ double piJn(int n, const double & v) {
} else
sg = 1;
if (x < 0) {
if (n % 2 != 0)
sg = -sg;
if (n % 2 != 0) sg = -sg;
x = -x;
}
if (n == 0) {
@@ -226,26 +225,26 @@ double piJn(int n, const double & v) {
result = 0;
return result;
}
k = 53;
pk = 2 * (n + k);
k = 53;
pk = 2 * (n + k);
ans = pk;
xk = x * x;
xk = x * x;
do {
pk = pk - 2.0;
pk = pk - 2.0;
ans = pk - xk / ans;
k = k - 1;
k = k - 1;
} while (k != 0);
ans = x / ans;
pk = 1.0;
ans = x / ans;
pk = 1.0;
pkm1 = 1.0 / ans;
k = n - 1;
r = 2 * k;
k = n - 1;
r = 2 * k;
do {
pkm2 = (pkm1 * r - pk * x) / x;
pk = pkm1;
pk = pkm1;
pkm1 = pkm2;
r = r - 2.0;
k = k - 1;
r = r - 2.0;
k = k - 1;
} while (k != 0);
if (fabs(pk) > fabs(pkm1))
ans = piJ1(x) / pk;
@@ -275,60 +274,60 @@ double piY0(const double & v) {
double q2;
double p3;
double q3;
xsq_ = 64.0 / (x * x);
p2 = 0.0;
p2 = 2485.271928957404011288128951 + xsq_ * p2;
p2 = 153982.6532623911470917825993 + xsq_ * p2;
p2 = 2016135.283049983642487182349 + xsq_ * p2;
p2 = 8413041.456550439208464315611 + xsq_ * p2;
p2 = 12332384.76817638145232406055 + xsq_ * p2;
p2 = 5393485.083869438325262122897 + xsq_ * p2;
q2 = 1.0;
q2 = 2615.700736920839685159081813 + xsq_ * q2;
q2 = 156001.7276940030940592769933 + xsq_ * q2;
q2 = 2025066.801570134013891035236 + xsq_ * q2;
q2 = 8426449.050629797331554404810 + xsq_ * q2;
q2 = 12338310.22786324960844856182 + xsq_ * q2;
q2 = 5393485.083869438325560444960 + xsq_ * q2;
p3 = -0.0;
p3 = -4.887199395841261531199129300 + xsq_ * p3;
p3 = -226.2630641933704113967255053 + xsq_ * p3;
p3 = -2365.956170779108192723612816 + xsq_ * p3;
p3 = -8239.066313485606568803548860 + xsq_ * p3;
p3 = -10381.41698748464093880530341 + xsq_ * p3;
p3 = -3984.617357595222463506790588 + xsq_ * p3;
q3 = 1.0;
q3 = 408.7714673983499223402830260 + xsq_ * q3;
q3 = 15704.89191515395519392882766 + xsq_ * q3;
q3 = 156021.3206679291652539287109 + xsq_ * q3;
q3 = 533291.3634216897168722255057 + xsq_ * q3;
q3 = 666745.4239319826986004038103 + xsq_ * q3;
q3 = 255015.5108860942382983170882 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8 * p3 / q3 / x;
nn = x - M_PI / 4;
xsq_ = 64.0 / (x * x);
p2 = 0.0;
p2 = 2485.271928957404011288128951 + xsq_ * p2;
p2 = 153982.6532623911470917825993 + xsq_ * p2;
p2 = 2016135.283049983642487182349 + xsq_ * p2;
p2 = 8413041.456550439208464315611 + xsq_ * p2;
p2 = 12332384.76817638145232406055 + xsq_ * p2;
p2 = 5393485.083869438325262122897 + xsq_ * p2;
q2 = 1.0;
q2 = 2615.700736920839685159081813 + xsq_ * q2;
q2 = 156001.7276940030940592769933 + xsq_ * q2;
q2 = 2025066.801570134013891035236 + xsq_ * q2;
q2 = 8426449.050629797331554404810 + xsq_ * q2;
q2 = 12338310.22786324960844856182 + xsq_ * q2;
q2 = 5393485.083869438325560444960 + xsq_ * q2;
p3 = -0.0;
p3 = -4.887199395841261531199129300 + xsq_ * p3;
p3 = -226.2630641933704113967255053 + xsq_ * p3;
p3 = -2365.956170779108192723612816 + xsq_ * p3;
p3 = -8239.066313485606568803548860 + xsq_ * p3;
p3 = -10381.41698748464093880530341 + xsq_ * p3;
p3 = -3984.617357595222463506790588 + xsq_ * p3;
q3 = 1.0;
q3 = 408.7714673983499223402830260 + xsq_ * q3;
q3 = 15704.89191515395519392882766 + xsq_ * q3;
q3 = 156021.3206679291652539287109 + xsq_ * q3;
q3 = 533291.3634216897168722255057 + xsq_ * q3;
q3 = 666745.4239319826986004038103 + xsq_ * q3;
q3 = 255015.5108860942382983170882 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8 * p3 / q3 / x;
nn = x - M_PI / 4;
result = sqrt(2 / M_PI / x) * (pzero * sin(nn) + qzero * cos(nn));
return result;
}
xsq = sqr(x);
p4 = -41370.35497933148554125235152;
p4 = 59152134.65686889654273830069 + xsq * p4;
p4 = -34363712229.79040378171030138 + xsq * p4;
p4 = 10255208596863.94284509167421 + xsq * p4;
p4 = -1648605817185729.473122082537 + xsq * p4;
p4 = 137562431639934407.8571335453 + xsq * p4;
p4 = -5247065581112764941.297350814 + xsq * p4;
p4 = 65874732757195549259.99402049 + xsq * p4;
p4 = -27502866786291095837.01933175 + xsq * p4;
q4 = 1.0;
q4 = 1282.452772478993804176329391 + xsq * q4;
q4 = 1001702.641288906265666651753 + xsq * q4;
q4 = 579512264.0700729537480087915 + xsq * q4;
q4 = 261306575504.1081249568482092 + xsq * q4;
q4 = 91620380340751.85262489147968 + xsq * q4;
q4 = 23928830434997818.57439356652 + xsq * q4;
q4 = 4192417043410839973.904769661 + xsq * q4;
q4 = 372645883898616588198.9980 + xsq * q4;
xsq = sqr(x);
p4 = -41370.35497933148554125235152;
p4 = 59152134.65686889654273830069 + xsq * p4;
p4 = -34363712229.79040378171030138 + xsq * p4;
p4 = 10255208596863.94284509167421 + xsq * p4;
p4 = -1648605817185729.473122082537 + xsq * p4;
p4 = 137562431639934407.8571335453 + xsq * p4;
p4 = -5247065581112764941.297350814 + xsq * p4;
p4 = 65874732757195549259.99402049 + xsq * p4;
p4 = -27502866786291095837.01933175 + xsq * p4;
q4 = 1.0;
q4 = 1282.452772478993804176329391 + xsq * q4;
q4 = 1001702.641288906265666651753 + xsq * q4;
q4 = 579512264.0700729537480087915 + xsq * q4;
q4 = 261306575504.1081249568482092 + xsq * q4;
q4 = 91620380340751.85262489147968 + xsq * q4;
q4 = 23928830434997818.57439356652 + xsq * q4;
q4 = 4192417043410839973.904769661 + xsq * q4;
q4 = 372645883898616588198.9980 + xsq * q4;
result = p4 / q4 + 2 / M_PI * piJ0(x) * log(x);
return result;
#else
@@ -353,59 +352,59 @@ double piY1(const double & v) {
double q2;
double p3;
double q3;
xsq_ = 64.0 / (x * x);
p2 = -1611.616644324610116477412898;
p2 = -109824.0554345934672737413139 + xsq_ * p2;
p2 = -1523529.351181137383255105722 + xsq_ * p2;
p2 = -6603373.248364939109255245434 + xsq_ * p2;
p2 = -9942246.505077641195658377899 + xsq_ * p2;
p2 = -4435757.816794127857114720794 + xsq_ * p2;
q2 = 1.0;
q2 = -1455.009440190496182453565068 + xsq_ * q2;
q2 = -107263.8599110382011903063867 + xsq_ * q2;
q2 = -1511809.506634160881644546358 + xsq_ * q2;
q2 = -6585339.479723087072826915069 + xsq_ * q2;
q2 = -9934124.389934585658967556309 + xsq_ * q2;
q2 = -4435757.816794127856828016962 + xsq_ * q2;
p3 = 35.26513384663603218592175580;
p3 = 1706.375429020768002061283546 + xsq_ * p3;
p3 = 18494.26287322386679652009819 + xsq_ * p3;
p3 = 66178.83658127083517939992166 + xsq_ * p3;
p3 = 85145.16067533570196555001171 + xsq_ * p3;
p3 = 33220.91340985722351859704442 + xsq_ * p3;
q3 = 1.0;
q3 = 863.8367769604990967475517183 + xsq_ * q3;
q3 = 37890.22974577220264142952256 + xsq_ * q3;
q3 = 400294.4358226697511708610813 + xsq_ * q3;
q3 = 1419460.669603720892855755253 + xsq_ * q3;
q3 = 1819458.042243997298924553839 + xsq_ * q3;
q3 = 708712.8194102874357377502472 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8 * p3 / q3 / x;
nn = x - 3 * M_PI / 4;
xsq_ = 64.0 / (x * x);
p2 = -1611.616644324610116477412898;
p2 = -109824.0554345934672737413139 + xsq_ * p2;
p2 = -1523529.351181137383255105722 + xsq_ * p2;
p2 = -6603373.248364939109255245434 + xsq_ * p2;
p2 = -9942246.505077641195658377899 + xsq_ * p2;
p2 = -4435757.816794127857114720794 + xsq_ * p2;
q2 = 1.0;
q2 = -1455.009440190496182453565068 + xsq_ * q2;
q2 = -107263.8599110382011903063867 + xsq_ * q2;
q2 = -1511809.506634160881644546358 + xsq_ * q2;
q2 = -6585339.479723087072826915069 + xsq_ * q2;
q2 = -9934124.389934585658967556309 + xsq_ * q2;
q2 = -4435757.816794127856828016962 + xsq_ * q2;
p3 = 35.26513384663603218592175580;
p3 = 1706.375429020768002061283546 + xsq_ * p3;
p3 = 18494.26287322386679652009819 + xsq_ * p3;
p3 = 66178.83658127083517939992166 + xsq_ * p3;
p3 = 85145.16067533570196555001171 + xsq_ * p3;
p3 = 33220.91340985722351859704442 + xsq_ * p3;
q3 = 1.0;
q3 = 863.8367769604990967475517183 + xsq_ * q3;
q3 = 37890.22974577220264142952256 + xsq_ * q3;
q3 = 400294.4358226697511708610813 + xsq_ * q3;
q3 = 1419460.669603720892855755253 + xsq_ * q3;
q3 = 1819458.042243997298924553839 + xsq_ * q3;
q3 = 708712.8194102874357377502472 + xsq_ * q3;
pzero = p2 / q2;
qzero = 8 * p3 / q3 / x;
nn = x - 3 * M_PI / 4;
result = sqrt(2 / M_PI / x) * (pzero * sin(nn) + qzero * cos(nn));
return result;
}
xsq = sqr(x);
p4 = -2108847.540133123652824139923;
p4 = 3639488548.124002058278999428 + xsq * p4;
p4 = -2580681702194.450950541426399 + xsq * p4;
p4 = 956993023992168.3481121552788 + xsq * p4;
p4 = -196588746272214065.8820322248 + xsq * p4;
p4 = 21931073399177975921.11427556 + xsq * p4;
p4 = -1212297555414509577913.561535 + xsq * p4;
p4 = 26554738314348543268942.48968 + xsq * p4;
p4 = -99637534243069222259967.44354 + xsq * p4;
q4 = 1.0;
q4 = 1612.361029677000859332072312 + xsq * q4;
q4 = 1563282.754899580604737366452 + xsq * q4;
q4 = 1128686837.169442121732366891 + xsq * q4;
q4 = 646534088126.5275571961681500 + xsq * q4;
q4 = 297663212564727.6729292742282 + xsq * q4;
q4 = 108225825940881955.2553850180 + xsq * q4;
q4 = 29549879358971486742.90758119 + xsq * q4;
q4 = 5435310377188854170800.653097 + xsq * q4;
q4 = 508206736694124324531442.4152 + xsq * q4;
xsq = sqr(x);
p4 = -2108847.540133123652824139923;
p4 = 3639488548.124002058278999428 + xsq * p4;
p4 = -2580681702194.450950541426399 + xsq * p4;
p4 = 956993023992168.3481121552788 + xsq * p4;
p4 = -196588746272214065.8820322248 + xsq * p4;
p4 = 21931073399177975921.11427556 + xsq * p4;
p4 = -1212297555414509577913.561535 + xsq * p4;
p4 = 26554738314348543268942.48968 + xsq * p4;
p4 = -99637534243069222259967.44354 + xsq * p4;
q4 = 1.0;
q4 = 1612.361029677000859332072312 + xsq * q4;
q4 = 1563282.754899580604737366452 + xsq * q4;
q4 = 1128686837.169442121732366891 + xsq * q4;
q4 = 646534088126.5275571961681500 + xsq * q4;
q4 = 297663212564727.6729292742282 + xsq * q4;
q4 = 108225825940881955.2553850180 + xsq * q4;
q4 = 29549879358971486742.90758119 + xsq * q4;
q4 = 5435310377188854170800.653097 + xsq * q4;
q4 = 508206736694124324531442.4152 + xsq * q4;
result = x * p4 / q4 + 2 / M_PI * (piJ1(x) * log(x) - 1 / x);
return result;
#else
@@ -426,8 +425,7 @@ double piYn(int n, const double & v) {
s = 1;
if (n < 0) {
n = -n;
if (n % 2 != 0)
s = -1;
if (n % 2 != 0) s = -1;
}
if (n == 0) {
result = piY0(x);
@@ -441,8 +439,8 @@ double piYn(int n, const double & v) {
b = piY1(x);
for (i = 1; i <= n - 1; i++) {
tmp = b;
b = 2 * i / x * b - a;
a = tmp;
b = 2 * i / x * b - a;
a = tmp;
}
result = s * b;
return result;
@@ -457,13 +455,13 @@ double randomn(double dv, double sv) {
double s = 2., v0 = 0., v1 = 0.;
if (agen) {
agen = false;
v1 = v1 * sqrt(-2 * log(s) / s);
v1 = v1 * sqrt(-2 * log(s) / s);
return v1 * sv + dv;
}
while (s > 1. || s == 0.) {
v0 = randomd();
v1 = randomd();
s = v0*v0 + v1*v1;
s = v0 * v0 + v1 * v1;
}
v0 = v0 * sqrt(-2 * log(s) / s);
return v0 * sv + dv;
@@ -471,5 +469,5 @@ double randomn(double dv, double sv) {
double randomd() {
return (double) rand() / RAND_MAX * 2. - 1.;
return (double)rand() / RAND_MAX * 2. - 1.;
}

View File

@@ -5,22 +5,22 @@
* \~russian Базовые математические функции и дефайны
*/
/*
PIP - Platform Independent Primitives
Basic mathematical functions and defines
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Basic mathematical functions and defines
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMATHBASE_H

View File

@@ -5,32 +5,33 @@
* \~russian Комплексные числа
*/
/*
PIP - Platform Independent Primitives
PIP math complex
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PIP math complex
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMATHCOMPLEX_H
#define PIMATHCOMPLEX_H
#include <complex>
#include "pimathbase.h"
#include "pibytearray.h"
#include "pimathbase.h"
#include "pivector2d.h"
#include <complex>
#define PIP_MATH_COMPLEX
using std::complex;
@@ -50,11 +51,19 @@ const complexld complexld_i(0., 1.);
const complexld complexld_0(0.);
const complexld complexld_1(1.);
inline complexd sign(const complexd & x) {return complexd(sign(x.real()), sign(x.imag()));}
inline complexd sign(const complexd & x) {
return complexd(sign(x.real()), sign(x.imag()));
}
inline complexd round(const complexd & c) {return complexd(piRound<double>(c.real()), piRound<double>(c.imag()));}
inline complexd floor(const complexd & c) {return complexd(floor(c.real()), floor(c.imag()));}
inline complexd ceil (const complexd & c) {return complexd(ceil(c.real()), ceil(c.imag()));}
inline complexd round(const complexd & c) {
return complexd(piRound<double>(c.real()), piRound<double>(c.imag()));
}
inline complexd floor(const complexd & c) {
return complexd(floor(c.real()), floor(c.imag()));
}
inline complexd ceil(const complexd & c) {
return complexd(ceil(c.real()), ceil(c.imag()));
}
#define acosc acos
#define asinc asin
@@ -62,15 +71,29 @@ inline complexd ceil (const complexd & c) {return complexd(ceil(c.real()), ceil(
#ifdef CC_GCC
# if CC_GCC_VERSION <= 0x025F
inline complexd tan(const complexd & c) {return sin(c) / cos(c);}
inline complexd tanh(const complexd & c) {return sinh(c) / cosh(c);}
inline complexd log2(const complexd & c) {return log(c) / M_LN2;}
inline complexd log10(const complexd & c) {return log(c) / M_LN10;}
inline complexd tan(const complexd & c) {
return sin(c) / cos(c);
}
inline complexd tanh(const complexd & c) {
return sinh(c) / cosh(c);
}
inline complexd log2(const complexd & c) {
return log(c) / M_LN2;
}
inline complexd log10(const complexd & c) {
return log(c) / M_LN10;
}
# endif
#endif
template<typename T>
inline PICout operator <<(PICout s, const complex<T> & v) {s.space(); s.saveAndSetControls(0); s << "(" << v.real() << "; " << v.imag() << ")"; s.restoreControls(); return s;}
inline PICout operator<<(PICout s, const complex<T> & v) {
s.space();
s.saveAndSetControls(0);
s << "(" << v.real() << "; " << v.imag() << ")";
s.restoreControls();
return s;
}
inline PIVector<double> abs(const PIVector<complexd> & v) {
@@ -86,17 +109,17 @@ inline PIVector2D<double> abs(const PIVector2D<complexd> & v) {
PIVector2D<double> result(v.rows(), v.cols());
for (uint i = 0; i < v.rows(); i++)
for (uint j = 0; j < v.cols(); j++)
result[i][j] = abs(v.element(i,j));
result[i][j] = abs(v.element(i, j));
return result;
}
/**
* \brief floating point number specific comparison between value passed as parameter and zero
*
* @param v floating point parameter for comparison
* @return true if v in locality of zero, otherwise false
*/
* \brief floating point number specific comparison between value passed as parameter and zero
*
* @param v floating point parameter for comparison
* @return true if v in locality of zero, otherwise false
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
inline bool PIMathFloatNullCompare(const T v) {
static_assert(std::is_floating_point<T>::value, "Type must be floating point");
@@ -104,15 +127,14 @@ inline bool PIMathFloatNullCompare(const T v) {
}
/**
* \brief floating point number specific comparison between parameter value and zero.
*
* @param v complex with floating point real and imag parts
* @return true if absolute of v in locality of zero, otherwise false
*/
template<typename T,typename std::enable_if<
std::is_floating_point<decltype(T::real)>::value &&
std::is_floating_point<decltype(T::imag)>::value
, int>::type = 0>
* \brief floating point number specific comparison between parameter value and zero.
*
* @param v complex with floating point real and imag parts
* @return true if absolute of v in locality of zero, otherwise false
*/
template<typename T,
typename std::enable_if<std::is_floating_point<decltype(T::real)>::value && std::is_floating_point<decltype(T::imag)>::value,
int>::type = 0>
inline bool PIMathFloatNullCompare(const T v) {
static_assert(std::is_floating_point<decltype(v.real)>::value, "Type must be floating point");
static_assert(std::is_floating_point<decltype(v.imag)>::value, "Type must be floating point");

View File

@@ -5,34 +5,36 @@
//! \~russian Математическая матрица
/*
PIP - Platform Independent Primitives
PIMathMatrix
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PIMathMatrix
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMATHMATRIX_H
#define PIMATHMATRIX_H
#include "pimathvector.h"
#include "pimathcomplex.h"
#include "pimathvector.h"
/// Matrix templated
#define PIMM_FOR for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c)
#define PIMM_FOR \
for (uint r = 0; r < Rows; ++r) \
for (uint c = 0; c < Cols; ++c)
#define PIMM_FOR_C for (uint i = 0; i < Cols; ++i)
#define PIMM_FOR_R for (uint i = 0; i < Rows; ++i)
@@ -42,7 +44,8 @@
//! \brief A class for fixed size and type matrix.
//! \tparam `Rows` rows number of matrix.
//! \tparam `Сols` columns number of matrix.
//! \tparam `Type` is the data type of the matrix. There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
//! \tparam `Type` is the data type of the matrix. There are can be basic C++ language data and different classes where the arithmetic
//! operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
//! of the C++ language are implemented
//! \~russian
//! \brief Класс для работы с матрицами фиксированного размера и типа данных.
@@ -53,7 +56,7 @@
//! \tparam `Rows` количество строк матрицы.
//! \tparam `Сols` количество столбцов матрицы.
//! \tparam `Type`тип данных матрицы. Здесь можеть быть базовый тип данных C++ или различные классы,
//! где реализованы арифметические операторы(=, +=, -=, *=, /=, ==, !=, +, -, *, /) языка C++.
//! где реализованы арифметические операторы(=, +=, -=, *=, /=, ==, !=, +, -, *, /) языка C++.
template<uint Rows, uint Cols = Rows, typename Type = double>
class PIP_EXPORT PIMathMatrixT {
typedef PIMathMatrixT<Rows, Cols, Type> _CMatrix;
@@ -63,30 +66,32 @@ class PIP_EXPORT PIMathMatrixT {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
static_assert(Rows > 0, "Row count must be > 0");
static_assert(Cols > 0, "Column count must be > 0");
public:
//! \~english
//! \brief Constructs \a PIMathMatrixT that is filled by \a new_value.
//! \~russian
//! \brief Создает \a PIMathMatrixT и заполняет её из \a new_value.
PIMathMatrixT(const Type &new_value = Type()) {PIMM_FOR m[r][c] = new_value;}
PIMathMatrixT(const Type & new_value = Type()) { PIMM_FOR m[r][c] = new_value; }
//! \~english
//! \brief Contructs \a PIMathMatrixT from \a PIVector.
//! \~russian
//! \brief Создает \a PIMathMatrixT и заполняет её из \a PIVector.
PIMathMatrixT(const PIVector<Type> &val) {
assert(Rows*Cols == val.size());
int i = 0;
PIMathMatrixT(const PIVector<Type> & val) {
assert(Rows * Cols == val.size());
int i = 0;
PIMM_FOR m[r][c] = val[i++];
}
//! \~english
//! \brief Contructs \a PIMathMatrixT from [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian
//! \brief Создает \a PIMathMatrixT и заполняет её из [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \brief Создает \a PIMathMatrixT и заполняет её из [списка инициализации
//! C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
PIMathMatrixT(std::initializer_list<Type> init_list) {
assert(Rows*Cols == init_list.size());
int i = 0;
assert(Rows * Cols == init_list.size());
int i = 0;
PIMM_FOR m[r][c] = init_list.begin()[i++];
}
@@ -98,7 +103,7 @@ public:
//! \return единичная матрица типа \a PIMathMatrixT.
static PIMathMatrixT<Rows, Cols, Type> identity() {
PIMathMatrixT<Rows, Cols, Type> tm = PIMathMatrixT<Rows, Cols, Type>();
PIMM_FOR tm.m[r][c] = (c == r ? Type(1) : Type(0));
PIMM_FOR tm.m[r][c] = (c == r ? Type(1) : Type(0));
return tm;
}
@@ -108,7 +113,7 @@ public:
//! \~russian
//! \brief Метод возвращающий количество столбцов в матрице.
//! \return \a uint количество столбцов.
constexpr uint cols() const {return Cols;}
constexpr uint cols() const { return Cols; }
//! \~english
//! \brief Method which returns number of rows in matrix.
@@ -116,7 +121,7 @@ public:
//! \~russian
//! \brief Метод возвращающий количество строк в матрице.
//! \return \a uint количество строк.
constexpr uint rows() const {return Rows;}
constexpr uint rows() const { return Rows; }
//! \~english
//! \brief Method which returns the selected column in PIMathVectorT format.
@@ -160,8 +165,8 @@ public:
//! \details Если вы введете индекс вне границ матрицы, то поведение не определено ("undefined behavior").
//! \param index номер выбранного столбца.
//! \param v вектор типа \a PIMathVectorT<Rows, Type>, которым необходимо заполнить столбец.
//! \return матрица типа \a PIMathMatrixT<Rows, Cols, Type>.
PIMathMatrixT<Rows, Cols, Type> &setCol(uint index, const PIMathVectorT<Rows, Type> &v) {
//! \return матрица типа \a PIMathMatrixT<Rows, Cols, Type>.
PIMathMatrixT<Rows, Cols, Type> & setCol(uint index, const PIMathVectorT<Rows, Type> & v) {
PIMM_FOR_R m[i][index] = v[i];
return *this;
}
@@ -178,7 +183,7 @@ public:
//! \param index номер выбранной строки.
//! \param v вектор типа \a PIMathVectorT<Cols, Type>, которым необходимо заполнить строку.
//! \return матрица типа \a PIMathMatrixT<Rows, Cols, Type>.
PIMathMatrixT<Rows, Cols, Type> &setRow(uint index, const PIMathVectorT<Cols, Type> &v) {
PIMathMatrixT<Rows, Cols, Type> & setRow(uint index, const PIMathVectorT<Cols, Type> & v) {
PIMM_FOR_C m[index][i] = v[i];
return *this;
}
@@ -195,7 +200,7 @@ public:
//! \param rf номер первой выбранной строки.
//! \param rs номер второй выбранной строки.
//! \return матрица типа \a PIMathMatrixT<Rows, Cols, Type>.
PIMathMatrixT<Rows, Cols, Type> &swapRows(uint rf, uint rs) {
PIMathMatrixT<Rows, Cols, Type> & swapRows(uint rf, uint rs) {
PIMM_FOR_C piSwap<Type>(m[rf][i], m[rs][i]);
return *this;
}
@@ -212,7 +217,7 @@ public:
//! \param rf номер первого выбранного столбца.
//! \param rs номер второго выбранного столбца.
//! \return матрица типа \a PIMathMatrixT<Rows, Cols, Type>.
PIMathMatrixT<Rows, Cols, Type> &swapCols(uint cf, uint cs) {
PIMathMatrixT<Rows, Cols, Type> & swapCols(uint cf, uint cs) {
PIMM_FOR_R piSwap<Type>(m[i][cf], m[i][cs]);
return *this;
}
@@ -225,7 +230,7 @@ public:
//! \brief Метод, заполняющий матрицу выбранным значением.
//! \param v параметр тип и значения, которого выбираются и заносятся в матрицу.
//! \return заполненная матрица типа \a PIMathMatrixT<Rows, Cols, Type>.
PIMathMatrixT<Rows, Cols, Type> &fill(const Type &v) {
PIMathMatrixT<Rows, Cols, Type> & fill(const Type & v) {
PIMM_FOR m[r][c] = v;
return *this;
}
@@ -287,7 +292,7 @@ public:
//! \param row номер строки матрицы.
//! \param col номер столбца матрицы.
//! \return элемент матрицы.
inline Type & element(uint row, uint col) {return m[row][col];}
inline Type & element(uint row, uint col) { return m[row][col]; }
//! \~english
//! \brief Read-only access to element by `row` number and `col` number.
@@ -301,7 +306,7 @@ public:
//! \param row номер строки матрицы.
//! \param col номер столбца матрицы.
//! \return копия элемента матрицы.
inline const Type & element(uint row, uint col) const {return m[row][col];}
inline const Type & element(uint row, uint col) const { return m[row][col]; }
//! \~english
//! \brief Full access to the matrix row pointer.
@@ -313,7 +318,7 @@ public:
//! \details Если вы введете индекс вне границ матрицы, то поведение не определено ("undefined behavior").
//! \param row номер строки матрицы.
//! \return указатель на строку матрицы.
Type *operator[](uint row) { return m[row]; }
Type * operator[](uint row) { return m[row]; }
//! \~english
//! \brief Read-only access to the matrix row pointer.
@@ -325,7 +330,7 @@ public:
//! \details Если вы введете индекс вне границ матрицы, то поведение не определено ("undefined behavior").
//! \param row номер строки матрицы.
//! \return указатель на строку матрицы.
const Type *operator[](uint row) const {return m[row];}
const Type * operator[](uint row) const { return m[row]; }
//! \~english
//! \brief Matrix compare.
@@ -335,7 +340,7 @@ public:
//! \brief Сравнение матриц.
//! \param sm матрица для сравнения.
//! \return если матрицы равны true, иначе false.
bool operator==(const PIMathMatrixT<Rows, Cols, Type> &sm) const {
bool operator==(const PIMathMatrixT<Rows, Cols, Type> & sm) const {
PIMM_FOR if (m[r][c] != sm.m[r][c]) return false;
return true;
}
@@ -348,7 +353,7 @@ public:
//! \brief Отрицательное сравнение матриц.
//! \param sm матрица для сравнения.
//! \return если матрицы не равны true, иначе false.
bool operator!=(const PIMathMatrixT<Rows, Cols, Type> &sm) const { return !(*this == sm); }
bool operator!=(const PIMathMatrixT<Rows, Cols, Type> & sm) const { return !(*this == sm); }
//! \~english
//! \brief Addition assignment with matrix `sm`.
@@ -356,7 +361,7 @@ public:
//! \~russian
//! \brief Сложение с присваиванием с матрицей `sm`.
//! \param sm матрица для сложения с присваиванием.
void operator+=(const PIMathMatrixT<Rows, Cols, Type> &sm) {PIMM_FOR m[r][c] += sm.m[r][c];}
void operator+=(const PIMathMatrixT<Rows, Cols, Type> & sm) { PIMM_FOR m[r][c] += sm.m[r][c]; }
//! \~english
//! \brief Subtraction assignment with matrix `sm`.
@@ -364,7 +369,7 @@ public:
//! \~russian
//! \brief Вычитание с присваиванием с матрицей `sm`.
//! \param sm матрица для вычитания с присваиванием.
void operator-=(const PIMathMatrixT<Rows, Cols, Type> &sm) {PIMM_FOR m[r][c] -= sm.m[r][c];}
void operator-=(const PIMathMatrixT<Rows, Cols, Type> & sm) { PIMM_FOR m[r][c] -= sm.m[r][c]; }
//! \~english
//! \brief Multiplication assignment with value `v`.
@@ -372,9 +377,7 @@ public:
//! \~russian
//! \brief Умножение с присваиванием с матрицей `v`.
//! \param sm матрица для умножения с присваиванием.
void operator*=(const Type &v) {
PIMM_FOR m[r][c] *= v;
}
void operator*=(const Type & v) { PIMM_FOR m[r][c] *= v; }
//! \~english
//! \brief Division assignment with value `v`.
@@ -382,7 +385,7 @@ public:
//! \~russian
//! \brief Деление с присваиванием с матрицей `v`.
//! \param sm матрица для деления с присваиванием.
void operator/=(const Type &v) {
void operator/=(const Type & v) {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
PIMM_FOR m[r][c] /= v;
}
@@ -407,7 +410,7 @@ public:
//! \brief Матричное сложение.
//! \param sm матричное слагаемое.
//! \return результат матричного сложения.
PIMathMatrixT<Rows, Cols, Type> operator+(const PIMathMatrixT<Rows, Cols, Type> &sm) const {
PIMathMatrixT<Rows, Cols, Type> operator+(const PIMathMatrixT<Rows, Cols, Type> & sm) const {
PIMathMatrixT<Rows, Cols, Type> tm = PIMathMatrixT<Rows, Cols, Type>(*this);
PIMM_FOR tm.m[r][c] += sm.m[r][c];
return tm;
@@ -421,7 +424,7 @@ public:
//! \brief Матричная разность.
//! \param sm матричное вычитаемое.
//! \return результат матричной разности.
PIMathMatrixT<Rows, Cols, Type> operator-(const PIMathMatrixT<Rows, Cols, Type> &sm) const {
PIMathMatrixT<Rows, Cols, Type> operator-(const PIMathMatrixT<Rows, Cols, Type> & sm) const {
PIMathMatrixT<Rows, Cols, Type> tm = PIMathMatrixT<Rows, Cols, Type>(*this);
PIMM_FOR tm.m[r][c] -= sm.m[r][c];
return tm;
@@ -435,7 +438,7 @@ public:
//! \brief Умножение матрицы на константу.
//! \param v множитель.
//! \return результат произведения.
PIMathMatrixT<Rows, Cols, Type> operator*(const Type &v) const {
PIMathMatrixT<Rows, Cols, Type> operator*(const Type & v) const {
PIMathMatrixT<Rows, Cols, Type> tm = PIMathMatrixT<Rows, Cols, Type>(*this);
PIMM_FOR tm.m[r][c] *= v;
return tm;
@@ -449,7 +452,7 @@ public:
//! \brief Деление матрицы на константу.
//! \param v делитель.
//! \return результат деления.
PIMathMatrixT<Rows, Cols, Type> operator/(const Type &v) const {
PIMathMatrixT<Rows, Cols, Type> operator/(const Type & v) const {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
PIMathMatrixT<Rows, Cols, Type> tm = PIMathMatrixT<Rows, Cols, Type>(*this);
PIMM_FOR tm.m[r][c] /= v;
@@ -457,7 +460,7 @@ public:
}
//! \~english
//! \brief Calculate Determinant of the matrix.
//! \brief Calculate Determinant of the matrix.
//! \details Works only with square matrix, nonzero matrices and invertible matrix.
//! \param ok is a parameter with which we can find out if the method worked correctly.
//! \return matrix determinant.
@@ -466,7 +469,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return опеределитель матрицы.
Type determinant(bool *ok = 0) const {
Type determinant(bool * ok = 0) const {
PIMathMatrixT<Rows, Cols, Type> m(*this);
bool k;
Type ret = Type(0);
@@ -505,7 +508,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return преобразованная верхнетреугольная матрицы.
PIMathMatrixT<Rows, Cols, Type> &toUpperTriangular(bool *ok = 0) {
PIMathMatrixT<Rows, Cols, Type> & toUpperTriangular(bool * ok = 0) {
static_assert(Rows == Cols, "Works only with square matrix");
PIMathMatrixT<Rows, Cols, Type> smat(*this);
bool ndet;
@@ -513,7 +516,8 @@ public:
Type mul;
for (uint i = 0; i < Cols; ++i) {
ndet = true;
for (uint j = 0; j < Rows; ++j) if (smat.m[i][j] != 0) ndet = false;
for (uint j = 0; j < Rows; ++j)
if (smat.m[i][j] != 0) ndet = false;
if (ndet) {
if (ok != 0) *ok = false;
return *this;
@@ -525,7 +529,8 @@ public:
smat.swapRows(i, ++crow);
for (uint j = i + 1; j < Rows; ++j) {
mul = smat.m[i][j] / smat.m[i][i];
for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i];
for (uint k = i; k < Cols; ++k)
smat.m[k][j] -= mul * smat.m[k][i];
}
if (i < Cols - 1) {
if (piAbs<Type>(smat.m[i + 1][i + 1]) < Type(1E-200)) {
@@ -540,7 +545,7 @@ public:
}
//! \~english
//! \brief Matrix inversion operation.
//! \brief Matrix inversion operation.
//! \details Works only with square matrix, nonzero matrices and invertible matrix.
//! \param ok is a parameter with which we can find out if the method worked correctly.
//! \return inverted matrix.
@@ -549,7 +554,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return обратная матрица.
PIMathMatrixT<Rows, Cols, Type> &invert(bool *ok = 0) {
PIMathMatrixT<Rows, Cols, Type> & invert(bool * ok = 0) {
static_assert(Rows == Cols, "Works only with square matrix");
PIMathMatrixT<Rows, Cols, Type> mtmp = PIMathMatrixT<Rows, Cols, Type>::identity(), smat(*this);
bool ndet;
@@ -557,7 +562,8 @@ public:
Type mul, iddiv;
for (uint i = 0; i < Cols; ++i) {
ndet = true;
for (uint j = 0; j < Rows; ++j) if (smat.m[i][j] != 0) ndet = false;
for (uint j = 0; j < Rows; ++j)
if (smat.m[i][j] != 0) ndet = false;
if (ndet) {
if (ok != 0) *ok = false;
return *this;
@@ -572,8 +578,10 @@ public:
}
for (uint j = i + 1; j < Rows; ++j) {
mul = smat.m[i][j] / smat.m[i][i];
for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i];
for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i];
for (uint k = i; k < Cols; ++k)
smat.m[k][j] -= mul * smat.m[k][i];
for (uint k = 0; k < Cols; ++k)
mtmp.m[k][j] -= mul * mtmp.m[k][i];
}
if (i < Cols - 1) {
if (piAbs<Type>(smat.m[i + 1][i + 1]) < Type(1E-200)) {
@@ -582,14 +590,17 @@ public:
}
}
iddiv = smat.m[i][i];
for (uint j = i; j < Cols; ++j) smat.m[j][i] /= iddiv;
for (uint j = 0; j < Cols; ++j) mtmp.m[j][i] /= iddiv;
for (uint j = i; j < Cols; ++j)
smat.m[j][i] /= iddiv;
for (uint j = 0; j < Cols; ++j)
mtmp.m[j][i] /= iddiv;
}
for (uint i = Cols - 1; i > 0; --i) {
for (uint j = 0; j < i; ++j) {
mul = smat.m[i][j];
smat.m[i][j] -= mul;
for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mtmp.m[k][i] * mul;
for (uint k = 0; k < Cols; ++k)
mtmp.m[k][j] -= mtmp.m[k][i] * mul;
}
}
if (ok != 0) *ok = true;
@@ -598,7 +609,7 @@ public:
}
//! \~english
//! \brief Matrix inversion operation.
//! \brief Matrix inversion operation.
//! \details Works only with square matrix, nonzero matrices and invertible matrix.
//! \param ok is a parameter with which we can find out if the method worked correctly.
//! \return copy of inverted matrix.
@@ -607,14 +618,14 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return копия обратной матрицы.
PIMathMatrixT<Rows, Cols, Type> inverted(bool *ok = 0) const {
PIMathMatrixT<Rows, Cols, Type> inverted(bool * ok = 0) const {
PIMathMatrixT<Rows, Cols, Type> tm(*this);
tm.invert(ok);
return tm;
}
//! \~english
//! \brief Matrix transposition operation.
//! \brief Matrix transposition operation.
//! \details Works only with square matrix.
//! \return copy of transposed matrix
//! \~russian
@@ -641,9 +652,9 @@ public:
Type s = std::sin(angle);
PIMathMatrixT<2u, 2u> tm;
tm[0][0] = tm[1][1] = c;
tm[0][1] = -s;
tm[1][0] = s;
*this = *this * tm;
tm[0][1] = -s;
tm[1][0] = s;
*this = *this * tm;
return *this;
}
@@ -655,16 +666,16 @@ public:
//! \brief Операция поворота матрицы.
//! \details Работает только с матрицами 2x2.
//! \return копия повернутой матрицы.
PIMathMatrixT<Rows, Cols, Type>& rotated(Type angle) {
PIMathMatrixT<Rows, Cols, Type> & rotated(Type angle) {
static_assert(Rows == 2 && Cols == 2, "Works only with 2x2 matrix");
PIMathMatrixT<Cols, Rows, Type> outm;
Type c = std::cos(angle);
Type s = std::sin(angle);
PIMathMatrixT<2u, 2u> tm;
tm[0][0] = tm[1][1] = c;
tm[0][1] = -s;
tm[1][0] = s;
outm = outm * tm;
tm[0][1] = -s;
tm[1][0] = s;
outm = outm * tm;
return outm;
}
@@ -677,7 +688,7 @@ private:
#ifdef PIP_STD_IOSTREAM
template<uint Rows, uint Cols, typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT<Rows, Cols, Type> & m) {
inline std::ostream & operator<<(std::ostream & s, const PIMathMatrixT<Rows, Cols, Type> & m) {
s << "{";
for (uint r = 0; r < Rows; ++r) {
for (uint c = 0; c < Cols; ++c) {
@@ -702,7 +713,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT<Rows, Co
//! \param m типа \a PIMathMatrixT.
//! \return непечатанная в консоль \a PICout.
template<uint Rows, uint Cols, typename Type>
inline PICout operator<<(PICout s, const PIMathMatrixT<Rows, Cols, Type> &m) {
inline PICout operator<<(PICout s, const PIMathMatrixT<Rows, Cols, Type> & m) {
s << "{";
for (uint r = 0; r < Rows; ++r) {
for (uint c = 0; c < Cols; ++c) {
@@ -716,7 +727,7 @@ inline PICout operator<<(PICout s, const PIMathMatrixT<Rows, Cols, Type> &m) {
}
//! \~english
//! \brief Multiplying matrices by each other.
//! \brief Multiplying matrices by each other.
//! \param fm first matrix multiplier.
//! \param sm second matrix multiplier.
//! \return matrix that is the result of multiplication.
@@ -726,8 +737,7 @@ inline PICout operator<<(PICout s, const PIMathMatrixT<Rows, Cols, Type> &m) {
//! \param sm второй множитель-матрица.
//! \return матрица, являющаяся результатом умножения.
template<uint CR, uint Rows0, uint Cols1, typename Type>
inline PIMathMatrixT<Rows0, Cols1, Type> operator*(const PIMathMatrixT<Rows0, CR, Type> &fm,
const PIMathMatrixT<CR, Cols1, Type> &sm) {
inline PIMathMatrixT<Rows0, Cols1, Type> operator*(const PIMathMatrixT<Rows0, CR, Type> & fm, const PIMathMatrixT<CR, Cols1, Type> & sm) {
PIMathMatrixT<Rows0, Cols1, Type> tm;
Type t;
for (uint j = 0; j < Rows0; ++j) {
@@ -752,8 +762,7 @@ inline PIMathMatrixT<Rows0, Cols1, Type> operator*(const PIMathMatrixT<Rows0, CR
//! \param sv второй множитель-вектор.
//! \return вектор, являющийся результатом умножения.
template<uint Cols, uint Rows, typename Type>
inline PIMathVectorT<Rows, Type> operator*(const PIMathMatrixT<Rows, Cols, Type> &fm,
const PIMathVectorT<Cols, Type> &sv) {
inline PIMathVectorT<Rows, Type> operator*(const PIMathMatrixT<Rows, Cols, Type> & fm, const PIMathVectorT<Cols, Type> & sv) {
PIMathVectorT<Rows, Type> tv;
Type t;
for (uint j = 0; j < Rows; ++j) {
@@ -776,8 +785,7 @@ inline PIMathVectorT<Rows, Type> operator*(const PIMathMatrixT<Rows, Cols, Type>
//! \param fm первый множитель-матрица.
//! \return вектор, являющийся результатом умножения.
template<uint Cols, uint Rows, typename Type>
inline PIMathVectorT<Cols, Type> operator*(const PIMathVectorT<Rows, Type> &sv,
const PIMathMatrixT<Rows, Cols, Type> &fm) {
inline PIMathVectorT<Cols, Type> operator*(const PIMathVectorT<Rows, Type> & sv, const PIMathMatrixT<Rows, Cols, Type> & fm) {
PIMathVectorT<Cols, Type> tv;
Type t;
for (uint j = 0; j < Cols; ++j) {
@@ -800,7 +808,7 @@ inline PIMathVectorT<Cols, Type> operator*(const PIMathVectorT<Rows, Type> &sv,
//! \param v вторая множитель-матрица.
//! \return матрица, являющаяся результатом умножения.
template<uint Cols, uint Rows, typename Type>
inline PIMathMatrixT<Rows, Cols, Type> operator*(const Type &x, const PIMathMatrixT<Rows, Cols, Type> &v) {
inline PIMathMatrixT<Rows, Cols, Type> operator*(const Type & x, const PIMathMatrixT<Rows, Cols, Type> & v) {
return v * x;
}
@@ -821,28 +829,28 @@ class PIMathMatrix;
#undef PIMM_FOR_R
/// Matrix
#define PIMM_FOR for (uint r = 0; r < _V2D::rows_; ++r) for (uint c = 0; c < _V2D::cols_; ++c)
#define PIMM_FOR \
for (uint r = 0; r < _V2D::rows_; ++r) \
for (uint c = 0; c < _V2D::cols_; ++c)
#define PIMM_FOR_A for (uint i = 0; i < _V2D::mat.size(); ++i)
#define PIMM_FOR_C for (uint i = 0; i < _V2D::cols_; ++i)
#define PIMM_FOR_R for (uint i = 0; i < _V2D::rows_; ++i)
//! \~english
//! \brief A class for dynamic size and fixed type matrix.
//! \tparam `Type` There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=, +, -, *, /)
//! of the C++ language are implemented.
//! \tparam `Type` There are can be basic C++ language data and different classes where the arithmetic operators(=, +=, -=, *=, /=, ==, !=,
//! +, -, *, /) of the C++ language are implemented.
//! \~russian
//! \brief Класс для работы с матрицами динамического размера и фиксированного типа.
//! \tparam `Type` Здесь можеть быть базовый тип данных C++ или различные классы,
//! где реализованы арифметические операторы(=, +=, -=, *=, /=, ==, !=, +, -, *, /) языка C++.
//! где реализованы арифметические операторы(=, +=, -=, *=, /=, ==, !=, +, -, *, /) языка C++.
template<typename Type>
class PIP_EXPORT PIMathMatrix : public PIVector2D<Type> {
class PIP_EXPORT PIMathMatrix: public PIVector2D<Type> {
typedef PIVector2D<Type> _V2D;
typedef PIMathMatrix<Type> _CMatrix;
public:
//! \~english
//! \brief Constructor of class \a PIMathMatrix, which creates a matrix.
@@ -854,7 +862,7 @@ public:
//! \param cols количество столбов матрицы типа \a uint.
//! \param rows количество строк матрицы типа \a uint.
//! \param f тип элементов матрицы.
PIMathMatrix(const uint cols = 0, const uint rows = 0, const Type &f = Type()) { _V2D::resize(rows, cols, f); }
PIMathMatrix(const uint cols = 0, const uint rows = 0, const Type & f = Type()) { _V2D::resize(rows, cols, f); }
//! \~english
//! \brief Constructor of class \a PIMathMatrix, which creates a matrix
@@ -866,9 +874,9 @@ public:
//! \param cols количество столбов матрицы типа \a uint.
//! \param rows количество строк матрицы типа \a uint.
//! \param val тип \a PIVector<Type> элементов матрицы.
PIMathMatrix(const uint cols, const uint rows, const PIVector<Type> &val) {
PIMathMatrix(const uint cols, const uint rows, const PIVector<Type> & val) {
_V2D::resize(rows, cols);
int i = 0;
int i = 0;
PIMM_FOR _V2D::element(r, c) = val[i++];
}
@@ -878,7 +886,7 @@ public:
//! \~russian
//! \brief Конструктор класса \a PIMathMatrix, который создает матрицу.
//! \param val тип \a PIVector<Type>, который создает матрицу.
PIMathMatrix(const PIVector<PIVector<Type> > &val) {
PIMathMatrix(const PIVector<PIVector<Type>> & val) {
if (!val.isEmpty()) {
_V2D::resize(val.size(), val[0].size());
for (uint r = 0; r < _V2D::rows_; ++r) {
@@ -895,7 +903,7 @@ public:
//! \~russian
//! \brief Конструктор класса \a PIMathMatrix, который создает матрицу.
//! \param val тип \a PIVector2D<Type>, который создает матрицу.
PIMathMatrix(const PIVector2D<Type> &val) {
PIMathMatrix(const PIVector2D<Type> & val) {
if (!val.isEmpty()) {
_V2D::resize(val.rows(), val.cols());
PIMM_FOR _V2D::element(r, c) = val.element(r, c);
@@ -914,7 +922,9 @@ public:
//! \return единичная матрица matrix(`cols`, `rows`)
static PIMathMatrix<Type> identity(const uint cols, const uint rows) {
PIMathMatrix<Type> tm(cols, rows);
for (uint r = 0; r < rows; ++r) for (uint c = 0; c < cols; ++c) tm.element(r, c) = (c == r ? Type(1) : Type(0));
for (uint r = 0; r < rows; ++r)
for (uint c = 0; c < cols; ++c)
tm.element(r, c) = (c == r ? Type(1) : Type(0));
return tm;
}
@@ -926,7 +936,7 @@ public:
//! \brief Создает матрицу-строку, каждый элемент которой равен каждому элементу вектора
//! \param val вектор типа \a PIMathVector
//! \return матрица-строка, каждый элемент которой равен каждому элементу вектора
static PIMathMatrix<Type> matrixRow(const PIMathVector<Type> &val) {return PIMathMatrix<Type>(val.size(), 1, val.toVector());}
static PIMathMatrix<Type> matrixRow(const PIMathVector<Type> & val) { return PIMathMatrix<Type>(val.size(), 1, val.toVector()); }
//! \~english
//! \brief Creates a column matrix of every element that is equal to every element of the vector
@@ -936,23 +946,23 @@ public:
//! \brief Создает матрицу-столбец, каждый элемент которой равен каждому элементу вектора
//! \param val вектор типа \a PIMathVector
//! \return матрица-столбец, каждый элемент которой равен каждому элементу вектора
static PIMathMatrix<Type> matrixCol(const PIMathVector<Type> &val) {return PIMathMatrix<Type>(1, val.size(), val.toVector());}
static PIMathMatrix<Type> matrixCol(const PIMathVector<Type> & val) { return PIMathMatrix<Type>(1, val.size(), val.toVector()); }
//! \~english
//! \brief Set the selected column in matrix.
//! \brief Set the selected column in matrix.
//! \details If there are more elements of the vector than elements in the column of the matrix
//! or index larger than the number of columns otherwise there will be "undefined behavior".
//! \param index is the number of the selected column.
//! \param v is a vector of the type \a PIMathVector<Type> that needs to fill the column.
//! \return matrix type \a PIMathMatrix<Type>
//! \~russian
//! \brief Определить выбранный столбец матрицы.
//! \details Если элементов в векторе больше, чем элементов в столбце матрицы
//! \brief Определить выбранный столбец матрицы.
//! \details Если элементов в векторе больше, чем элементов в столбце матрицы
//! или индекс больше количества стобцов, то поведение не определено ("undefined behavior").
//! \param index номер выбранного столбца.
//! \param v вектор типа \a PIMathVector<Type>, которым нужно заполнить столбец.
//! \return матрица типа \a PIMathMatrix<Type>.
PIMathMatrix<Type> &setCol(uint index, const PIMathVector<Type> &v) {
PIMathMatrix<Type> & setCol(uint index, const PIMathVector<Type> & v) {
assert(_V2D::rows() == v.size());
PIMM_FOR_R _V2D::element(i, index) = v[i];
return *this;
@@ -966,13 +976,13 @@ public:
//! \param v is a vector of the type \a PIMathVector<Type> that needs to fill the row.
//! \return matrix type \a PIMathMatrix<Type>.
//! \~russian
//! \brief Определить выбранную строку матрицы.
//! \details Если элементов в векторе больше, чем элементов в строке матрицы
//! \brief Определить выбранную строку матрицы.
//! \details Если элементов в векторе больше, чем элементов в строке матрицы
//! или индекс больше количества стобцов, то поведение не определено ("undefined behavior").
//! \param index номер выбранной строки.
//! \param v вектор типа \a PIMathVector<Type>, которым нужно заполнить строку.
//! \return матрица типа \a PIMathMatrix<Type>.
PIMathMatrix<Type> &setRow(uint index, const PIMathVector<Type> &v) {
PIMathMatrix<Type> & setRow(uint index, const PIMathVector<Type> & v) {
assert(_V2D::cols() == v.size());
PIMM_FOR_C _V2D::element(index, i) = v[i];
return *this;
@@ -987,12 +997,12 @@ public:
//! \return matrix type \a PIMathMatrix<Type>.
//! \~russian
//! \brief Метод меняющий местами выбранные строки в матрице.
//! \details Вы не можете использовать индекс, который больше количества столбцов,
//! \details Вы не можете использовать индекс, который больше количества столбцов,
//! иначе будет неопределенное повередение ("undefined behavior").
//! \param r0 номер первой выбранного стобца.
//! \param r1 номер второй выбранного столбца.
//! \return матрица типа \a PIMathMatrix<Type>.
PIMathMatrix<Type> &swapCols(uint r0, uint r1) {
PIMathMatrix<Type> & swapCols(uint r0, uint r1) {
PIMM_FOR_C piSwap<Type>(_V2D::element(i, r0), _V2D::element(i, r1));
return *this;
}
@@ -1006,12 +1016,12 @@ public:
//! \return matrix type \a PIMathMatrix<Type>.
//! \~russian
//! \brief Метод меняющий местами выбранные строки в матрице.
//! \details Вы не можете использовать индекс, который больше количества строк,
//! \details Вы не можете использовать индекс, который больше количества строк,
//! иначе будет неопределенное повередение ("undefined behavior").
//! \param с0 номер первой выбранной строки.
//! \param с1 номер второй выбранной строки.
//! \return матрица типа \a PIMathMatrix<Type>.
PIMathMatrix<Type> &swapRows(uint c0, uint c1) {
PIMathMatrix<Type> & swapRows(uint c0, uint c1) {
PIMM_FOR_R piSwap<Type>(_V2D::element(c0, i), _V2D::element(c1, i));
return *this;
}
@@ -1024,7 +1034,7 @@ public:
//! \brief Метод заполняющий матрицу выбранным значением.
//! \param v параметр выбранного типа и значения, которым будет заполнена матрица.
//! \return заполненная матрица типа \a PIMathMatrix<Type>.
PIMathMatrix<Type> &fill(const Type &v) {
PIMathMatrix<Type> & fill(const Type & v) {
PIMM_FOR_A _V2D::mat[i] = v;
return *this;
}
@@ -1044,7 +1054,7 @@ public:
//! \brief Метод, проверяющий содержит ли главная диагональ единицы и все остальные поля нули.
//! \return true если матрица единичная, иначе false.
bool isIdentity() const {
PIMM_FOR if ((c == r) ? _V2D::element(r, c) != Type(1) : _V2D::element(r, c) != Type(0))return false;
PIMM_FOR if ((c == r) ? _V2D::element(r, c) != Type(1) : _V2D::element(r, c) != Type(0)) return false;
return true;
}
@@ -1073,7 +1083,7 @@ public:
//! \~russian
//! \brief Сложение с присваиванием с матрицей `sm`.
//! \param sm матрица для сложения с присваиванием.
void operator+=(const PIMathMatrix<Type> &sm) {
void operator+=(const PIMathMatrix<Type> & sm) {
assert(_V2D::rows() == sm.rows());
assert(_V2D::cols() == sm.cols());
PIMM_FOR_A _V2D::mat[i] += sm.mat[i];
@@ -1085,7 +1095,7 @@ public:
//! \~russian
//! \brief Вычитание с присваиванием с матрицей `sm`.
//! \param sm матрица для вычитания с присваиванием.
void operator-=(const PIMathMatrix<Type> &sm) {
void operator-=(const PIMathMatrix<Type> & sm) {
assert(_V2D::rows() == sm.rows());
assert(_V2D::cols() == sm.cols());
PIMM_FOR_A _V2D::mat[i] -= sm.mat[i];
@@ -1097,9 +1107,7 @@ public:
//! \~russian
//! \brief Умножение с присваиванием с матрицей `v`.
//! \param sm матрица для умножения с присваиванием.
void operator*=(const Type &v) {
PIMM_FOR_A _V2D::mat[i] *= v;
}
void operator*=(const Type & v) { PIMM_FOR_A _V2D::mat[i] *= v; }
//! \~english
//! \brief Division assignment with value `v`.
@@ -1107,7 +1115,7 @@ public:
//! \~russian
//! \brief Деление с присваиванием с матрицей `v`.
//! \param sm матрица для деления с присваиванием.
void operator/=(const Type &v) {
void operator/=(const Type & v) {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
PIMM_FOR_A _V2D::mat[i] /= v;
}
@@ -1132,7 +1140,7 @@ public:
//! \brief Матричное сложение.
//! \param sm матричное слагаемое.
//! \return результат матричного сложения.
PIMathMatrix<Type> operator+(const PIMathMatrix<Type> &sm) const {
PIMathMatrix<Type> operator+(const PIMathMatrix<Type> & sm) const {
PIMathMatrix<Type> tm(*this);
assert(tm.rows() == sm.rows());
assert(tm.cols() == sm.cols());
@@ -1148,7 +1156,7 @@ public:
//! \brief Матричная разность.
//! \param sm матричное вычитаемое.
//! \return результат матричной разности.
PIMathMatrix<Type> operator-(const PIMathMatrix<Type> &sm) const {
PIMathMatrix<Type> operator-(const PIMathMatrix<Type> & sm) const {
PIMathMatrix<Type> tm(*this);
assert(tm.rows() == sm.rows());
assert(tm.cols() == sm.cols());
@@ -1164,7 +1172,7 @@ public:
//! \brief Матричное произведение.
//! \param v множитель.
//! \return результат произведения.
PIMathMatrix<Type> operator*(const Type &v) const {
PIMathMatrix<Type> operator*(const Type & v) const {
PIMathMatrix<Type> tm(*this);
PIMM_FOR_A tm.mat[i] *= v;
return tm;
@@ -1178,7 +1186,7 @@ public:
//! \brief Матричное деление.
//! \param v делитель.
//! \return результат деления.
PIMathMatrix<Type> operator/(const Type &v) const {
PIMathMatrix<Type> operator/(const Type & v) const {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
PIMathMatrix<Type> tm(*this);
PIMM_FOR_A tm.mat[i] /= v;
@@ -1186,7 +1194,7 @@ public:
}
//! \~english
//! \brief Calculate Determinant of the matrix.
//! \brief Calculate Determinant of the matrix.
//! \details Works only with square matrix, nonzero matrices and invertible matrix.
//! \param ok is a parameter with which we can find out if the method worked correctly.
//! \return matrix determinant.
@@ -1195,7 +1203,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return опеределитель матрицы.
Type determinant(bool *ok = 0) const {
Type determinant(bool * ok = 0) const {
PIMathMatrix<Type> m(*this);
bool k;
m.toUpperTriangular(&k);
@@ -1205,8 +1213,7 @@ public:
ret = Type(1);
for (uint c = 0; c < _V2D::cols_; ++c)
for (uint r = 0; r < _V2D::rows_; ++r)
if (r == c)
ret *= m.element(r, c);
if (r == c) ret *= m.element(r, c);
return ret;
}
@@ -1237,7 +1244,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return копия преобразованной верхнетреугольной матрицы.
PIMathMatrix<Type> &toUpperTriangular(bool *ok = 0) {
PIMathMatrix<Type> & toUpperTriangular(bool * ok = 0) {
assert(isSquare());
PIMathMatrix<Type> smat(*this);
bool ndet;
@@ -1245,7 +1252,8 @@ public:
Type mul;
for (uint i = 0; i < _V2D::cols_; ++i) {
ndet = true;
for (uint j = 0; j < _V2D::rows_; ++j) if (smat.element(i, j) != 0) ndet = false;
for (uint j = 0; j < _V2D::rows_; ++j)
if (smat.element(i, j) != 0) ndet = false;
if (ndet) {
if (ok != 0) *ok = false;
return *this;
@@ -1257,7 +1265,8 @@ public:
smat.swapRows(i, ++crow);
for (uint j = i + 1; j < _V2D::rows_; ++j) {
mul = smat.element(i, j) / smat.element(i, i);
for (uint k = i; k < _V2D::cols_; ++k) smat.element(k, j) -= mul * smat.element(k, i);
for (uint k = i; k < _V2D::cols_; ++k)
smat.element(k, j) -= mul * smat.element(k, i);
}
if (i < _V2D::cols_ - 1) {
if (PIMathFloatNullCompare(smat.element(i + 1, i + 1))) {
@@ -1272,7 +1281,7 @@ public:
}
//! \~english
//! \brief Matrix inversion operation.
//! \brief Matrix inversion operation.
//! \details Works only with square matrix, nonzero matrices and invertible matrix.
//! \param ok is a parameter with which we can find out if the method worked correctly.
//! \return inverted matrix.
@@ -1281,7 +1290,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return обратная матрица.
PIMathMatrix<Type> &invert(bool *ok = 0, PIMathVector<Type> *sv = 0) {
PIMathMatrix<Type> & invert(bool * ok = 0, PIMathVector<Type> * sv = 0) {
assert(isSquare());
PIMathMatrix<Type> mtmp = PIMathMatrix<Type>::identity(_V2D::cols_, _V2D::rows_), smat(*this);
bool ndet;
@@ -1289,7 +1298,8 @@ public:
Type mul, iddiv;
for (uint i = 0; i < _V2D::cols_; ++i) {
ndet = true;
for (uint j = 0; j < _V2D::rows_; ++j) if (smat.element(i, j) != Type(0)) ndet = false;
for (uint j = 0; j < _V2D::rows_; ++j)
if (smat.element(i, j) != Type(0)) ndet = false;
if (ndet) {
if (ok != 0) *ok = false;
return *this;
@@ -1305,8 +1315,10 @@ public:
}
for (uint j = i + 1; j < _V2D::rows_; ++j) {
mul = smat.element(i, j) / smat.element(i, i);
for (uint k = i; k < _V2D::cols_; ++k) smat.element(k, j) -= mul * smat.element(k, i);
for (uint k = 0; k < _V2D::cols_; ++k) mtmp.element(k, j) -= mul * mtmp.element(k, i);
for (uint k = i; k < _V2D::cols_; ++k)
smat.element(k, j) -= mul * smat.element(k, i);
for (uint k = 0; k < _V2D::cols_; ++k)
mtmp.element(k, j) -= mul * mtmp.element(k, i);
if (sv != 0) (*sv)[j] -= mul * (*sv)[i];
}
if (i < _V2D::cols_ - 1) {
@@ -1316,15 +1328,18 @@ public:
}
}
iddiv = smat.element(i, i);
for (uint j = i; j < _V2D::cols_; ++j) smat.element(j, i) /= iddiv;
for (uint j = 0; j < _V2D::cols_; ++j) mtmp.element(j, i) /= iddiv;
for (uint j = i; j < _V2D::cols_; ++j)
smat.element(j, i) /= iddiv;
for (uint j = 0; j < _V2D::cols_; ++j)
mtmp.element(j, i) /= iddiv;
if (sv != 0) (*sv)[i] /= iddiv;
}
for (uint i = _V2D::cols_ - 1; i > 0; --i) {
for (uint j = 0; j < i; ++j) {
mul = smat.element(i, j);
smat.element(i, j) -= mul;
for (uint k = 0; k < _V2D::cols_; ++k) mtmp.element(k, j) -= mul * mtmp.element(k, i);
for (uint k = 0; k < _V2D::cols_; ++k)
mtmp.element(k, j) -= mul * mtmp.element(k, i);
if (sv != 0) (*sv)[j] -= mul * (*sv)[i];
}
}
@@ -1334,7 +1349,7 @@ public:
}
//! \~english
//! \brief Matrix inversion operation.
//! \brief Matrix inversion operation.
//! \details Works only with square matrix, nonzero matrices and invertible matrix.
//! \param ok is a parameter with which we can find out if the method worked correctly.
//! \return copy of inverted matrix.
@@ -1343,7 +1358,7 @@ public:
//! \details Работает только с квадратными, ненулевыми и обратимыми матрицами.
//! \param ok это параметр, с помощью которого мы можем узнать, правильно ли сработал метод.
//! \return копия обратной матрицы.
PIMathMatrix<Type> inverted(bool *ok = 0) const {
PIMathMatrix<Type> inverted(bool * ok = 0) const {
PIMathMatrix<Type> tm(*this);
tm.invert(ok);
return tm;
@@ -1367,7 +1382,18 @@ public:
#ifdef PIP_STD_IOSTREAM
template<typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix<Type> & m) {s << "{"; for (uint r = 0; r < m.rows(); ++r) { for (uint c = 0; c < m.cols(); ++c) { s << m.element(r, c); if (c < m.cols() - 1 || r < m.rows() - 1) s << ", ";} if (r < m.rows() - 1) s << std::endl << " ";} s << "}"; return s;}
inline std::ostream & operator<<(std::ostream & s, const PIMathMatrix<Type> & m) {
s << "{";
for (uint r = 0; r < m.rows(); ++r) {
for (uint c = 0; c < m.cols(); ++c) {
s << m.element(r, c);
if (c < m.cols() - 1 || r < m.rows() - 1) s << ", ";
}
if (r < m.rows() - 1) s << std::endl << " ";
}
s << "}";
return s;
}
#endif
//! \~english
@@ -1381,7 +1407,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix<Type> & m
//! \param m типа \a PIMathMatrixT.
//! \return непечатанная в консоль \a PICout.
template<typename Type>
inline PICout operator<<(PICout s, const PIMathMatrix<Type> &m) {
inline PICout operator<<(PICout s, const PIMathMatrix<Type> & m) {
s << "Matrix{";
for (uint r = 0; r < m.rows(); ++r) {
for (uint c = 0; c < m.cols(); ++c) {
@@ -1402,9 +1428,9 @@ inline PICout operator<<(PICout s, const PIMathMatrix<Type> &m) {
//! \brief Inline-оператор для сериализации матрицы в \a PIBinaryStream.
//! \param s типа \a PIBinaryStream.
//! \param v типа \a PIMathMatrix.
template <typename P, typename T>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMathMatrix<T> & v) {
s << (const PIVector2D<T> &) v;
template<typename P, typename T>
inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMathMatrix<T> & v) {
s << (const PIVector2D<T> &)v;
return s;
}
@@ -1416,15 +1442,15 @@ inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMathMatrix
//! \brief Inline-оператор для сериализации матрицы в \a PIByteArray.
//! \param s типа \a PIBinaryStream.
//! \param v типа \a PIMathMatrix.
template <typename P, typename T>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMathMatrix<T> & v) {
s >> (PIVector2D<T> &) v;
template<typename P, typename T>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathMatrix<T> & v) {
s >> (PIVector2D<T> &)v;
return s;
}
//! \~english
//! \brief Multiplying matrices by each other.
//! \brief Multiplying matrices by each other.
//! \details If you enter an index out of the border of the matrix there will be "undefined behavior".
//! \param fm first matrix multiplier.
//! \param sm second matrix multiplier.
@@ -1436,8 +1462,7 @@ inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMathMatrix<T> &
//! \param sm вторая множитель-матрица.
//! \return матрица, являющаяся результатом умножения.
template<typename Type>
inline PIMathMatrix<Type> operator*(const PIMathMatrix<Type> &fm,
const PIMathMatrix<Type> &sm) {
inline PIMathMatrix<Type> operator*(const PIMathMatrix<Type> & fm, const PIMathMatrix<Type> & sm) {
assert(fm.cols() == sm.rows());
PIMathMatrix<Type> tm(sm.cols(), fm.rows());
Type t;
@@ -1465,8 +1490,7 @@ inline PIMathMatrix<Type> operator*(const PIMathMatrix<Type> &fm,
//! \param sv второй множитель-вектор.
//! \return вектор, являющийся результатом умножения.
template<typename Type>
inline PIMathVector<Type> operator*(const PIMathMatrix<Type> &fm,
const PIMathVector<Type> &sv) {
inline PIMathVector<Type> operator*(const PIMathMatrix<Type> & fm, const PIMathVector<Type> & sv) {
assert(fm.cols() == sv.size());
PIMathVector<Type> tv(fm.rows());
Type t;
@@ -1492,8 +1516,7 @@ inline PIMathVector<Type> operator*(const PIMathMatrix<Type> &fm,
//! \param fm первый множитель-матрица.
//! \return вектор, являющийся результатом умножения.
template<typename Type>
inline PIMathVector<Type> operator*(const PIMathVector<Type> &sv,
const PIMathMatrix<Type> &fm) {
inline PIMathVector<Type> operator*(const PIMathVector<Type> & sv, const PIMathMatrix<Type> & fm) {
PIMathVector<Type> tv(fm.cols());
assert(fm.rows() == sv.size());
Type t;
@@ -1517,7 +1540,7 @@ inline PIMathVector<Type> operator*(const PIMathVector<Type> &sv,
//! \param v второй множитель-матрица.
//! \return матрица, являющаяся результатом умножения.
template<typename Type>
inline PIMathMatrix<Type> operator*(const Type &x, const PIMathMatrix<Type> &v) {
inline PIMathMatrix<Type> operator*(const Type & x, const PIMathMatrix<Type> & v) {
return v * x;
}
@@ -1533,8 +1556,8 @@ typedef PIMathMatrix<double> PIMathMatrixd;
//! \param m сопряженная транспонированная матрица.
//! \return результат преобразования.
template<typename T>
PIMathMatrix<complex<T> > hermitian(const PIMathMatrix<complex<T> > &m) {
PIMathMatrix<complex<T> > ret(m);
PIMathMatrix<complex<T>> hermitian(const PIMathMatrix<complex<T>> & m) {
PIMathMatrix<complex<T>> ret(m);
for (uint r = 0; r < ret.rows(); ++r)
for (uint c = 0; c < ret.cols(); ++c)
ret.element(r, c).imag(-(ret.element(r, c).imag()));

View File

@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Math Math
//! \~\brief
@@ -51,11 +51,11 @@
#ifndef PIMATHMODULE_H
#define PIMATHMODULE_H
#include "pimathsolver.h"
#include "pistatistic.h"
#include "picrc.h"
#include "pievaluator.h"
#include "pifft.h"
#include "picrc.h"
#include "pimathsolver.h"
#include "piquaternion.h"
#include "pistatistic.h"
#endif // PIMATHMODULE_H

View File

@@ -1,25 +1,25 @@
/*
PIP - Platform Independent Primitives
PIMathSolver
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
PIMathSolver
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pimathsolver.h"
const char PIMathSolver::methods_desc[] = "b{Methods:}\
const char PIMathSolver::methods_desc[] = "b{Methods:}\
\n -1 - Global settings\
\n 01 - Eyler 1\
\n 02 - Eyler 2\
@@ -43,7 +43,8 @@ void PIMathSolver::solve(double u, double h) {
case RungeKutta_4: solveRK4(u, h); break;
case AdamsBashfortMoulton_2: solveABM2(u, h); break;
case AdamsBashfortMoulton_3: solveABM3(u, h); break;
case AdamsBashfortMoulton_4: default: solveABM4(u, h); break;
case AdamsBashfortMoulton_4:
default: solveABM4(u, h); break;
case PolynomialApproximation_2: solvePA2(u, h); break;
case PolynomialApproximation_3: solvePA3(u, h); break;
case PolynomialApproximation_4: solvePA4(u, h); break;
@@ -55,7 +56,8 @@ void PIMathSolver::solve(double u, double h) {
case RungeKutta_4: solveRK4(u, h); break;
case AdamsBashfortMoulton_2: solveABM2(u, h); break;
case AdamsBashfortMoulton_3: solveABM3(u, h); break;
case AdamsBashfortMoulton_4: default: solveABM4(u, h); break;
case AdamsBashfortMoulton_4:
default: solveABM4(u, h); break;
case PolynomialApproximation_2: solvePA2(u, h); break;
case PolynomialApproximation_3: solvePA3(u, h); break;
case PolynomialApproximation_4: solvePA4(u, h); break;
@@ -67,7 +69,7 @@ void PIMathSolver::solve(double u, double h) {
void PIMathSolver::fromTF(const TransferFunction & TF) {
if (TF.vector_An.size() >= TF.vector_Bm.size())
size = TF.vector_An.size()-1;
size = TF.vector_An.size() - 1;
else {
piCout << "PIMathSolver error: {A} should be greater than {B}";
return;
@@ -77,19 +79,29 @@ void PIMathSolver::fromTF(const TransferFunction & TF) {
step = 0;
times.fill(0.);
A.resize(size, size);
d.resize(size + 1); d.fill(0.);
a1.resize(size + 1); a1.fill(0.);
b1.resize(size + 1); b1.fill(0.);
X.resize(size); X.fill(0.);
d.resize(size + 1);
d.fill(0.);
a1.resize(size + 1);
a1.fill(0.);
b1.resize(size + 1);
b1.fill(0.);
X.resize(size);
X.fill(0.);
F.resize(5);
for (uint i = 0; i < 5; ++i)
F[i].resize(size), F[i].fill(0.);
k1.resize(size); k1.fill(0.);
k2.resize(size); k2.fill(0.);
k3.resize(size); k3.fill(0.);
k4.resize(size); k4.fill(0.);
xx.resize(size); xx.fill(0.);
XX.resize(size); XX.fill(0.);
k1.resize(size);
k1.fill(0.);
k2.resize(size);
k2.fill(0.);
k3.resize(size);
k3.fill(0.);
k4.resize(size);
k4.fill(0.);
xx.resize(size);
xx.fill(0.);
XX.resize(size);
XX.fill(0.);
for (uint i = 0; i < size + 1; ++i)
a1[size - i] = TF.vector_An[i];
for (uint i = 0; i < TF.vector_Bm.size(); ++i)
@@ -108,7 +120,7 @@ void PIMathSolver::fromTF(const TransferFunction & TF) {
for (uint i = 0; i < size - 1; ++i)
for (uint j = 0; j < size; ++j)
A[j][i] = (j == i + 1);
A[j][i] = (j == i + 1);
for (uint i = 0; i < size; ++i)
A[i][size - 1] = -a1[size - i];
for (uint i = 0; i < size; ++i)
@@ -132,11 +144,17 @@ void PIMathSolver::solveEyler2(double u, double h) {
void PIMathSolver::solveRK4(double u, double h) {
td = X[0] - F[0][0];
k1 = A * X + d * u; xx = k1 * h / 2.; XX = X + xx;
k2 = A * (XX + k1 * h / 2.) + d * (u + td/3.); xx = k2 * h / 2.; XX += xx;
k3 = A * (XX + k2 * h / 2.) + d * (u + td*2./3.); xx = k3 * h; XX += xx;
k1 = A * X + d * u;
xx = k1 * h / 2.;
XX = X + xx;
k2 = A * (XX + k1 * h / 2.) + d * (u + td / 3.);
xx = k2 * h / 2.;
XX += xx;
k3 = A * (XX + k2 * h / 2.) + d * (u + td * 2. / 3.);
xx = k3 * h;
XX += xx;
k4 = A * (XX + k3 * h) + d * (u + td);
//cout << k1 << k2 << k3 << k4 << endl;
// cout << k1 << k2 << k3 << k4 << endl;
X += (k1 + k2 * 2. + k3 * 2. + k4) * h / 6.;
F[0] = X;
}
@@ -144,7 +162,7 @@ void PIMathSolver::solveRK4(double u, double h) {
void PIMathSolver::solveABM2(double u, double h) {
F[0] = A * X + d * u;
XX = X + (F[0] * 3. - F[1]) * (h / 2.);
XX = X + (F[0] * 3. - F[1]) * (h / 2.);
F[1] = A * XX + d * u;
X += (F[1] + F[0]) * (h / 2.);
moveF();
@@ -153,7 +171,7 @@ void PIMathSolver::solveABM2(double u, double h) {
void PIMathSolver::solveABM3(double u, double h) {
F[0] = A * X + d * u;
XX = X + (F[0] * 23. - F[1] * 16. + F[2] * 5.) * (h / 12.);
XX = X + (F[0] * 23. - F[1] * 16. + F[2] * 5.) * (h / 12.);
F[2] = A * XX + d * u;
X += (F[2] * 5. + F[0] * 8. - F[1]) * (h / 12.);
moveF();
@@ -162,7 +180,7 @@ void PIMathSolver::solveABM3(double u, double h) {
void PIMathSolver::solveABM4(double u, double h) {
F[0] = A * X + d * u;
XX = X + (F[0] * 55. - F[1] * 59. + F[2] * 37. - F[3] * 9.) * (h / 24.);
XX = X + (F[0] * 55. - F[1] * 59. + F[2] * 37. - F[3] * 9.) * (h / 24.);
F[3] = A * XX + d * u;
X += (F[3] * 9. + F[0] * 19. - F[1] * 5. + F[2]) * (h / 24.);
moveF();
@@ -187,9 +205,9 @@ void PIMathSolver::solvePA(double u, double h, uint deg) {
for (uint i = 0; i < deg; ++i)
Y[i] = F[i][k];
/// find polynom
//if (step == 1) cout << M << endl << Y << endl;
// if (step == 1) cout << M << endl << Y << endl;
M.invert(&ok, &Y);
//if (step == 1) cout << Y << endl;
// if (step == 1) cout << Y << endl;
if (!ok) {
solveEyler2(u, h);
break;
@@ -197,7 +215,7 @@ void PIMathSolver::solvePA(double u, double h, uint deg) {
// calc last piece
x0 = 0.;
td = 1.;
t = times[0];
t = times[0];
for (uint i = 0; i < deg; ++i) {
x0 += Y[i] * td / (i + 1.);
td *= t;
@@ -206,7 +224,7 @@ void PIMathSolver::solvePA(double u, double h, uint deg) {
x1 = 0.;
td = 1.;
t = times[1];
t = times[1];
for (uint i = 0; i < deg; ++i) {
x1 += Y[i] * td / (i + 1.);
td *= t;

View File

@@ -1,23 +1,23 @@
/*! \file pimathsolver.h
* \brief PIMathSolver
*/
*/
/*
PIP - Platform Independent Primitives
PIMathSolver
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
PIMathSolver
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMATHSOLVER_H
@@ -31,29 +31,35 @@ struct PIP_EXPORT TransferFunction {
PIVector<double> vector_Bm, vector_An;
};
class PIP_EXPORT PIMathSolver
{
class PIP_EXPORT PIMathSolver {
public:
enum Method {Global = -1,
Eyler_1 = 01,
Eyler_2 = 02,
EylerKoshi = 03,
RungeKutta_4 = 14,
AdamsBashfortMoulton_2 = 22,
AdamsBashfortMoulton_3 = 23,
AdamsBashfortMoulton_4 = 24,
PolynomialApproximation_2 = 32,
PolynomialApproximation_3 = 33,
PolynomialApproximation_4 = 34,
PolynomialApproximation_5 = 35
};
enum Method {
Global = -1,
Eyler_1 = 01,
Eyler_2 = 02,
EylerKoshi = 03,
RungeKutta_4 = 14,
AdamsBashfortMoulton_2 = 22,
AdamsBashfortMoulton_3 = 23,
AdamsBashfortMoulton_4 = 24,
PolynomialApproximation_2 = 32,
PolynomialApproximation_3 = 33,
PolynomialApproximation_4 = 34,
PolynomialApproximation_5 = 35
};
PIMathSolver() {times.resize(4); step = 0;}
PIMathSolver() {
times.resize(4);
step = 0;
}
void solve(double u, double h);
void fromTF(const TransferFunction & TF);
void setMethod(Method m) {method = m;}
void setTime(double time) {times.pop_back(); times.push_front(time);}
void setMethod(Method m) { method = m; }
void setTime(double time) {
times.pop_back();
times.push_front(time);
}
void solveEyler1(double u, double h);
void solveEyler2(double u, double h);
@@ -62,17 +68,40 @@ public:
void solveABM3(double u, double h);
void solveABM4(double u, double h);
void solvePA(double u, double h, uint deg);
void solvePA2(double u, double h) {if (step > 0) solvePA(u, h, 2); else solveEyler1(u, h);}
void solvePA3(double u, double h) {if (step > 1) solvePA(u, h, 3); else solvePA2(u, h);}
void solvePA4(double u, double h) {if (step > 2) solvePA(u, h, 4); else solvePA3(u, h);}
void solvePA5(double u, double h) {if (step > 3) solvePA(u, h, 5); else solvePA4(u, h);}
void solvePA2(double u, double h) {
if (step > 0)
solvePA(u, h, 2);
else
solveEyler1(u, h);
}
void solvePA3(double u, double h) {
if (step > 1)
solvePA(u, h, 3);
else
solvePA2(u, h);
}
void solvePA4(double u, double h) {
if (step > 2)
solvePA(u, h, 4);
else
solvePA3(u, h);
}
void solvePA5(double u, double h) {
if (step > 3)
solvePA(u, h, 5);
else
solvePA4(u, h);
}
PIMathVectord X;
static Method method_global;
static const char methods_desc[];
private:
void moveF() {for (uint i = F.size() - 1; i > 0; --i) F[i] = F[i - 1];}
void moveF() {
for (uint i = F.size() - 1; i > 0; --i)
F[i] = F[i - 1];
}
PIMathMatrixd A, M;
PIMathVectord d, a1, b1;

View File

@@ -5,22 +5,22 @@
* \~russian Математический вектор
*/
/*
PIP - Platform Independent Primitives
PIMathVector
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PIMathVector
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMATHVECTOR_H
@@ -37,15 +37,16 @@ class PIMathMatrixT;
/// Vector templated
#define PIMV_FOR for (uint i = 0; i < Size; ++i)
#define PIMV_FOR for (uint i = 0; i < Size; ++i)
template<uint Size, typename Type = double>
class PIP_EXPORT PIMathVectorT {
typedef PIMathVectorT<Size, Type> _CVector;
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
static_assert(Size > 0, "Size must be > 0");
public:
PIMathVectorT(const Type & v = Type()) {PIMV_FOR c[i] = v;}
PIMathVectorT(const Type & v = Type()) { PIMV_FOR c[i] = v; }
PIMathVectorT(const PIVector<Type> & val) {
assert(Size == val.size());
PIMV_FOR c[i] = val[i];
@@ -60,10 +61,19 @@ public:
return tv;
}
constexpr uint size() const {return Size;}
_CVector & fill(const Type & v) {PIMV_FOR c[i] = v; return *this;}
_CVector & move(const Type & v) {PIMV_FOR c[i] += v; return *this;}
_CVector & move(const _CVector & v) {PIMV_FOR c[i] += v[i]; return *this;}
constexpr uint size() const { return Size; }
_CVector & fill(const Type & v) {
PIMV_FOR c[i] = v;
return *this;
}
_CVector & move(const Type & v) {
PIMV_FOR c[i] += v;
return *this;
}
_CVector & move(const _CVector & v) {
PIMV_FOR c[i] += v[i];
return *this;
}
_CVector & swapElements(uint f, uint s) {
piSwap<Type>(c[f], c[s]);
return *this;
@@ -73,7 +83,7 @@ public:
PIMV_FOR tv += c[i] * c[i];
return tv;
}
Type length() const {return std::sqrt(lengthSqr());}
Type length() const { return std::sqrt(lengthSqr()); }
Type manhattanLength() const {
Type tv(0);
PIMV_FOR tv += piAbs<Type>(c[i]);
@@ -88,9 +98,9 @@ public:
Type tv = angleCos(v);
return std::sqrt(Type(1) - tv * tv);
}
Type angleRad(const _CVector & v) const {return std::acos(angleCos(v));}
Type angleDeg(const _CVector & v) const {return toDeg(angleRad(v));}
Type angleElevation(const _CVector & v) const {return 90.0 - angleDeg(v - *this);}
Type angleRad(const _CVector & v) const { return std::acos(angleCos(v)); }
Type angleDeg(const _CVector & v) const { return toDeg(angleRad(v)); }
Type angleElevation(const _CVector & v) const { return 90.0 - angleDeg(v - *this); }
_CVector projection(const _CVector & v) {
Type tv = v.length();
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
@@ -103,47 +113,60 @@ public:
PIMV_FOR c[i] /= tv;
return *this;
}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
bool isNull() const {PIMV_FOR if (c[i] != Type(0)) return false; return true;}
bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);}
_CVector normalized() {
_CVector tv(*this);
tv.normalize();
return tv;
}
bool isNull() const {
PIMV_FOR if (c[i] != Type(0)) return false;
return true;
}
bool isOrtho(const _CVector & v) const { return ((*this) ^ v) == Type(0); }
Type & operator [](uint index) {return c[index];}
const Type & operator [](uint index) const {return c[index];}
Type at(uint index) const {return c[index];}
Type & operator[](uint index) { return c[index]; }
const Type & operator[](uint index) const { return c[index]; }
Type at(uint index) const { return c[index]; }
_CVector & operator =(const Type & v) {PIMV_FOR c[i] = v; return *this;}
_CVector & operator=(const Type & v) {
PIMV_FOR c[i] = v;
return *this;
}
bool operator ==(const _CVector & v) const {PIMV_FOR if (c[i] != v[i]) return false; return true;}
bool operator !=(const _CVector & v) const {return !(*this == c);}
bool operator==(const _CVector & v) const {
PIMV_FOR if (c[i] != v[i]) return false;
return true;
}
bool operator!=(const _CVector & v) const { return !(*this == c); }
void operator +=(const _CVector & v) {PIMV_FOR c[i] += v[i];}
void operator -=(const _CVector & v) {PIMV_FOR c[i] -= v[i];}
void operator *=(const Type & v) {PIMV_FOR c[i] *= v;}
void operator /=(const Type & v) {
void operator+=(const _CVector & v) { PIMV_FOR c[i] += v[i]; }
void operator-=(const _CVector & v) { PIMV_FOR c[i] -= v[i]; }
void operator*=(const Type & v) { PIMV_FOR c[i] *= v; }
void operator/=(const Type & v) {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
PIMV_FOR c[i] /= v;
}
_CVector operator -() const {
_CVector operator-() const {
_CVector tv;
PIMV_FOR tv[i] = -c[i];
return tv;
}
_CVector operator +(const _CVector & v) const {
_CVector operator+(const _CVector & v) const {
_CVector tv(*this);
PIMV_FOR tv[i] += v[i];
return tv;
}
_CVector operator -(const _CVector & v) const {
_CVector operator-(const _CVector & v) const {
_CVector tv(*this);
PIMV_FOR tv[i] -= v[i];
return tv;
}
_CVector operator *(const Type & v) const {
_CVector operator*(const Type & v) const {
_CVector tv(*this);
PIMV_FOR tv[i] *= v;
return tv;
}
_CVector operator /(const Type & v) const {
_CVector operator/(const Type & v) const {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
_CVector tv = _CVector(*this);
PIMV_FOR tv[i] /= v;
@@ -153,9 +176,9 @@ public:
_CVector cross(const _CVector & v) const {
static_assert(Size == 3, "cross product avalible only for 3D vectors");
_CVector tv;
tv[0] = c[1]*v[2] - v[1]*c[2];
tv[1] = v[0]*c[2] - c[0]*v[2];
tv[2] = c[0]*v[1] - v[0]*c[1];
tv[0] = c[1] * v[2] - v[1] * c[2];
tv[1] = v[0] * c[2] - c[0] * v[2];
tv[2] = c[0] * v[1] - v[0] * c[1];
return tv;
}
Type dot(const _CVector & v) const {
@@ -168,9 +191,7 @@ public:
PIMV_FOR tv[i] *= v[i];
return tv;
}
_CVector mul(const Type & v) const {
return (*this) * v;
}
_CVector mul(const Type & v) const { return (*this) * v; }
_CVector div(const _CVector & v) const {
_CVector tv(*this);
PIMV_FOR {
@@ -179,9 +200,7 @@ public:
}
return tv;
}
_CVector div(const Type & v) const {
return (*this) / v;
}
_CVector div(const Type & v) const { return (*this) / v; }
PIMathMatrixT<1, Size, Type> transposed() const {
PIMathMatrixT<1, Size, Type> ret;
@@ -194,51 +213,37 @@ public:
Type tv = a.length();
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
_CVector b(lp0, *this);
return piAbs<Type>(a[0]*b[1] - a[1]*b[0]) / tv;
return piAbs<Type>(a[0] * b[1] - a[1] * b[0]) / tv;
}
template<uint Size1, typename Type1> /// vector {Size, Type} to vector {Size1, Type1}
PIMathVectorT<Size1, Type1> turnTo() const {
PIMathVectorT<Size1, Type1> tv;
uint sz = piMin<uint>(Size, Size1);
for (uint i = 0; i < sz; ++i) tv[i] = c[i];
for (uint i = 0; i < sz; ++i)
tv[i] = c[i];
return tv;
}
static _CVector cross(const _CVector & v1, const _CVector & v2) {
return v1.cross(v2);
}
static _CVector dot(const _CVector & v1, const _CVector & v2) {
return v1.dot(v2);
}
static _CVector mul(const _CVector & v1, const _CVector & v2) {
return v1.mul(v2);
}
static _CVector mul(const Type & v1, const _CVector & v2) {
return v2 * v1;
}
static _CVector mul(const _CVector & v1, const Type & v2) {
return v1 * v2;
}
static _CVector div(const _CVector & v1, const _CVector & v2) {
return v1.div(v2);
}
static _CVector div(const _CVector & v1, const Type & v2) {
return v1 / v2;
}
static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); }
static _CVector dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); }
static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); }
static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; }
static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; }
static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); }
static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; }
private:
Type c[Size];
};
template<uint Size, typename Type>
inline PIMathVectorT<Size, Type> operator *(const Type & x, const PIMathVectorT<Size, Type> & v) {
inline PIMathVectorT<Size, Type> operator*(const Type & x, const PIMathVectorT<Size, Type> & v) {
return v * x;
}
template<uint Size, typename Type>
inline PICout operator <<(PICout s, const PIMathVectorT<Size, Type> & v) {
inline PICout operator<<(PICout s, const PIMathVectorT<Size, Type> & v) {
s << "Vector{";
PIMV_FOR {
s << v[i];
@@ -266,34 +271,40 @@ typedef PIMathVectorT<4u, double> PIMathVectorT4d;
template<typename Type>
class PIP_EXPORT PIMathVector {
typedef PIMathVector<Type> _CVector;
template <typename P, typename Type1>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMathVector<Type1> & v);
template <typename P, typename Type1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMathVector<Type1> & v);
template<typename P, typename Type1>
friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMathVector<Type1> & v);
template<typename P, typename Type1>
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<Type1> & v);
public:
PIMathVector(const uint size = 0, const Type & new_value = Type()) {c.resize(size, new_value);}
PIMathVector(const PIVector<Type> & val) {c = val;}
PIMathVector(PIVector<Type> && val) : c(std::move(val)) {}
PIMathVector(std::initializer_list<Type> init_list) {c = PIVector<Type>(init_list);}
PIMathVector(const uint size = 0, const Type & new_value = Type()) { c.resize(size, new_value); }
PIMathVector(const PIVector<Type> & val) { c = val; }
PIMathVector(PIVector<Type> && val): c(std::move(val)) {}
PIMathVector(std::initializer_list<Type> init_list) { c = PIVector<Type>(init_list); }
template<uint Size>
PIMathVector(const PIMathVectorT<Size, Type> & val) {c.resize(Size); PIMV_FOR c[i] = val[i];}
PIMathVector(const PIMathVectorT<Size, Type> & val) {
c.resize(Size);
PIMV_FOR c[i] = val[i];
}
static PIMathVector fromTwoPoints(const _CVector & st, const _CVector & fn) {
assert(st.size() == fn.size());
_CVector v(st.size());
for (uint i = 0; i < v.size(); ++i) v.c[i] = fn[i] - st[i];
for (uint i = 0; i < v.size(); ++i)
v.c[i] = fn[i] - st[i];
}
static PIMathVector zeros(const uint size) {return PIMathVector(size, Type());}
static PIMathVector ones(const uint size) {return PIMathVector(size, Type(1));}
static PIMathVector zeros(const uint size) { return PIMathVector(size, Type()); }
static PIMathVector ones(const uint size) { return PIMathVector(size, Type(1)); }
static PIMathVector arange(const Type start, const Type stop, const Type step = Type(1)) {
PIVector<Type> v;
for (Type i = start; i < stop; i+= step) v << i;
for (Type i = start; i < stop; i += step)
v << i;
return PIMathVector(std::move(v));
}
uint size() const {return c.size();}
uint size() const { return c.size(); }
_CVector & resize(uint size, const Type & new_value = Type()) {
c.resize(size, new_value);
return *this;
@@ -325,7 +336,7 @@ public:
PIMV_FOR tv += c[i] * c[i];
return tv;
}
Type length() const {return std::sqrt(lengthSqr());}
Type length() const { return std::sqrt(lengthSqr()); }
Type manhattanLength() const {
Type tv(0);
PIMV_FOR tv += piAbs<Type>(c[i]);
@@ -342,8 +353,8 @@ public:
Type tv = angleCos(v);
return std::sqrt(Type(1) - tv * tv);
}
Type angleRad(const _CVector & v) const {return std::acos(angleCos(v));}
Type angleDeg(const _CVector & v) const {return toDeg(angleRad(v));}
Type angleRad(const _CVector & v) const { return std::acos(angleCos(v)); }
Type angleDeg(const _CVector & v) const { return toDeg(angleRad(v)); }
_CVector projection(const _CVector & v) {
assert(c.size() == v.size());
Type tv = v.length();
@@ -366,54 +377,57 @@ public:
PIMV_FOR if (c[i] != Type(0)) return false;
return true;
}
bool isValid() const {return !c.isEmpty();}
bool isOrtho(const _CVector & v) const {return dot(v) == Type(0);}
bool isValid() const { return !c.isEmpty(); }
bool isOrtho(const _CVector & v) const { return dot(v) == Type(0); }
Type & operator [](uint index) {return c[index];}
const Type & operator [](uint index) const {return c[index];}
Type at(uint index) const {return c[index];}
Type & operator[](uint index) { return c[index]; }
const Type & operator[](uint index) const { return c[index]; }
Type at(uint index) const { return c[index]; }
_CVector & operator =(const Type & v) {PIMV_FOR c[i] = v; return *this;}
_CVector & operator=(const Type & v) {
PIMV_FOR c[i] = v;
return *this;
}
bool operator ==(const _CVector & v) const {return c == v.c;}
bool operator !=(const _CVector & v) const {return c != v.c;}
bool operator==(const _CVector & v) const { return c == v.c; }
bool operator!=(const _CVector & v) const { return c != v.c; }
void operator +=(const _CVector & v) {
void operator+=(const _CVector & v) {
assert(c.size() == v.size());
PIMV_FOR c[i] += v[i];
}
void operator -=(const _CVector & v) {
void operator-=(const _CVector & v) {
assert(c.size() == v.size());
PIMV_FOR c[i] -= v[i];
}
void operator *=(const Type & v) {PIMV_FOR c[i] *= v;}
void operator /=(const Type & v) {
void operator*=(const Type & v) { PIMV_FOR c[i] *= v; }
void operator/=(const Type & v) {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
PIMV_FOR c[i] /= v;
}
_CVector operator -() const {
_CVector operator-() const {
_CVector tv(c.size());
PIMV_FOR tv[i] = -c[i];
return tv;
}
_CVector operator +(const _CVector & v) const {
_CVector operator+(const _CVector & v) const {
assert(c.size() == v.size());
_CVector tv(*this);
PIMV_FOR tv[i] += v[i];
return tv;
}
_CVector operator -(const _CVector & v) const {
_CVector operator-(const _CVector & v) const {
assert(c.size() == v.size());
_CVector tv(*this);
PIMV_FOR tv[i] -= v[i];
return tv;
}
_CVector operator *(const Type & v) const {
_CVector operator*(const Type & v) const {
_CVector tv(*this);
PIMV_FOR tv[i] *= v;
return tv;
}
_CVector operator /(const Type & v) const {
_CVector operator/(const Type & v) const {
assert(piAbs<Type>(v) > PIMATHVECTOR_ZERO_CMP);
_CVector tv(*this);
PIMV_FOR tv[i] /= v;
@@ -423,9 +437,9 @@ public:
assert(c.size() == 3);
assert(v.size() == 3);
_CVector tv(3);
tv[0] = c[1]*v[2] - v[1]*c[2];
tv[1] = c[2]*v[0] - v[2]*c[0];
tv[2] = c[0]*v[1] - v[0]*c[1];
tv[0] = c[1] * v[2] - v[1] * c[2];
tv[1] = c[2] * v[0] - v[2] * c[0];
tv[2] = c[0] * v[1] - v[0] * c[1];
return tv;
}
Type dot(const _CVector & v) const {
@@ -440,9 +454,7 @@ public:
PIMV_FOR tv[i] *= v[i];
return tv;
}
_CVector mul(const Type & v) const {
return (*this) * v;
}
_CVector mul(const Type & v) const { return (*this) * v; }
_CVector div(const _CVector & v) const {
assert(c.size() == v.size());
_CVector tv(*this);
@@ -452,61 +464,44 @@ public:
}
return tv;
}
_CVector div(const Type & v) const {
return (*this) / v;
}
_CVector div(const Type & v) const { return (*this) / v; }
Type distToLine(const _CVector & lp0, const _CVector & lp1) {
assert(c.size() == lp0.size());
assert(c.size() == lp1.size());
_CVector a = _CVector::fromTwoPoints(lp0, lp1);
Type tv = a.length();
Type tv = a.length();
assert(piAbs<Type>(tv) > PIMATHVECTOR_ZERO_CMP);
_CVector b = _CVector::fromTwoPoints(lp0, *this);
return piAbs<Type>(a[0]*b[1] - a[1]*b[0]) / tv;
return piAbs<Type>(a[0] * b[1] - a[1] * b[0]) / tv;
}
PIVector<Type> toVector() const {return c;}
PIVector<Type> toVector() const { return c; }
void forEach(std::function<void(const Type &)> f) const {
c.forEach(f);
}
void forEach(std::function<void(const Type &)> f) const { c.forEach(f); }
_CVector & forEach(std::function<void(Type &)> f) {
c.forEach(f);
return *this;
}
inline Type * data() {return c.data();}
inline const Type * data() const {return c.data();}
inline Type * data() { return c.data(); }
inline const Type * data() const { return c.data(); }
static _CVector cross(const _CVector & v1, const _CVector & v2) {
return v1.cross(v2);
}
static _CVector dot(const _CVector & v1, const _CVector & v2) {
return v1.dot(v2);
}
static _CVector mul(const _CVector & v1, const _CVector & v2) {
return v1.mul(v2);
}
static _CVector mul(const Type & v1, const _CVector & v2) {
return v2 * v1;
}
static _CVector mul(const _CVector & v1, const Type & v2) {
return v1 * v2;
}
static _CVector div(const _CVector & v1, const _CVector & v2) {
return v1.div(v2);
}
static _CVector div(const _CVector & v1, const Type & v2) {
return v1 / v2;
}
static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); }
static _CVector dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); }
static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); }
static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; }
static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; }
static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); }
static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; }
private:
PIVector<Type> c;
};
template<typename Type>
inline PIMathVector<Type> operator *(const Type & x, const PIMathVector<Type> & v) {
inline PIMathVector<Type> operator*(const Type & x, const PIMathVector<Type> & v) {
return v * x;
}
@@ -514,11 +509,19 @@ inline PIMathVector<Type> operator *(const Type & x, const PIMathVector<Type> &
#ifdef PIP_STD_IOSTREAM
template<typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMathVector<Type> & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
inline std::ostream & operator<<(std::ostream & s, const PIMathVector<Type> & v) {
s << "{";
for (uint i = 0; i < v.size(); ++i) {
s << v[i];
if (i < v.size() - 1) s << ", ";
}
s << "}";
return s;
}
#endif
template<typename Type>
inline PICout operator <<(PICout s, const PIMathVector<Type> & v) {
inline PICout operator<<(PICout s, const PIMathVector<Type> & v) {
s << "Vector{";
for (uint i = 0; i < v.size(); ++i) {
s << v[i];
@@ -528,10 +531,16 @@ inline PICout operator <<(PICout s, const PIMathVector<Type> & v) {
return s;
}
template <typename P, typename T>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMathVector<T> & v) {s << v.c; return s;}
template <typename P, typename T>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMathVector<T> & v) {s >> v.c; return s;}
template<typename P, typename T>
inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMathVector<T> & v) {
s << v.c;
return s;
}
template<typename P, typename T>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<T> & v) {
s >> v.c;
return s;
}
typedef PIMathVector<int> PIMathVectori;

View File

@@ -4,19 +4,19 @@
//! \~english Two-dimensional point class
//! \~russian Класс двумерной точки
/*
PIP - Platform Independent Primitives
Two-dimensional point class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
PIP - Platform Independent Primitives
Two-dimensional point class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIPOINT_H
#define PIPOINT_H
@@ -28,22 +28,23 @@
//! \~english Two-dimensional point class
//! \~russian Класс двумерной точки
//! \details
//! Данный класс позволяет хранить и работать с двумерными точками.
//! Данный класс позволяет хранить и работать с двумерными точками.
//! Для работы с объектами реализованы операторы сложения, вычитания и проверки на ревенство и неравенство.
//! Также доступны методы для перемещения точек \a translate(), \a translated(), \a move(), \a moved()
//! Также доступны методы для перемещения точек \a translate(), \a translated(), \a move(), \a moved()
//! и перевода из декартовой системы координат в полярную \a toPolar() и обратно \a fromPolar().
template<typename Type>
class PIP_EXPORT PIPoint {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
Type x;
Type y;
//! \~russian Создает новую точку.
PIPoint() {x = y = Type();}
PIPoint() { x = y = Type(); }
//! \~russian Создает новую точку с заданными координатами.
PIPoint(Type x_, Type y_) {set(x_, y_);}
PIPoint(Type x_, Type y_) { set(x_, y_); }
//! \~russian Задать новые координаты точке.
PIPoint<Type> & set(Type x_, Type y_) {
@@ -89,11 +90,11 @@ public:
//! \~russian Переместить точку.
//! \details Является копией метода \a translate().
PIPoint<Type> & move(Type x_, Type y_) {return translate(x_, y_);}
PIPoint<Type> & move(Type x_, Type y_) { return translate(x_, y_); }
//! \~russian Переместить точку.
//! \details Является копией метода \a translate().
PIPoint<Type> & move(const PIPoint<Type> & p) {return translate(p);}
PIPoint<Type> & move(const PIPoint<Type> & p) { return translate(p); }
//! \~russian Создать копию точки и переместить её.
//! \details Является копией метода \a translated().
@@ -112,47 +113,47 @@ public:
}
//! \~russian Посчитать угол(радианы) в поолярной системе координат.
double angleRad() const {return atan2(y, x);}
double angleRad() const { return atan2(y, x); }
//! \~russian Посчитать угол(градусы) в поолярной системе координат.
double angleDeg() const {return toDeg(atan2(y, x));}
double angleDeg() const { return toDeg(atan2(y, x)); }
//! \~russian Перевести копию точки в полярную систему координат.
PIPoint<Type> toPolar(bool isDeg = false) const {return PIPoint<Type>(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());}
PIPoint<Type> toPolar(bool isDeg = false) const { return PIPoint<Type>(sqrt(x * x + y * y), isDeg ? angleDeg() : angleRad()); }
//! \~russian Перевести копию точки из полярной системы координат в декартовую.
static PIPoint<Type> fromPolar(const PIPoint<Type> & p) {return PIPoint<Type>(p.y * cos(p.x), p.y * sin(p.x));}
static PIPoint<Type> fromPolar(const PIPoint<Type> & p) { return PIPoint<Type>(p.y * cos(p.x), p.y * sin(p.x)); }
//! \~russian
//! \~russian
//! Прибавить координаты второй точки и сохранить.
//! \details Является копией метода \a translate().
void operator +=(const PIPoint<Type> & p) {translate(p);}
void operator+=(const PIPoint<Type> & p) { translate(p); }
//! \~russian Сложить координаты двух точек.
PIPoint<Type> operator +(const PIPoint<Type> & p) {return PIPoint<Type>(x + p.x, y + p.y);}
PIPoint<Type> operator+(const PIPoint<Type> & p) { return PIPoint<Type>(x + p.x, y + p.y); }
//! \~russian Прибавить к координатам одинаковое значение.
PIPoint<Type> operator +(const Type & p) {return PIPoint<Type>(x + p, y + p);}
PIPoint<Type> operator+(const Type & p) { return PIPoint<Type>(x + p, y + p); }
//! \~russian Вычесть из координат координаты второй точки - найти смещение.
PIPoint<Type> operator -(const PIPoint<Type> & p) {return PIPoint<Type>(x - p.x, y - p.y);}
PIPoint<Type> operator-(const PIPoint<Type> & p) { return PIPoint<Type>(x - p.x, y - p.y); }
//! \~russian Вычесть из координат одинаковое значение.
PIPoint<Type> operator -(const Type & p) {return PIPoint<Type>(x - p, y - p);}
PIPoint<Type> operator-(const Type & p) { return PIPoint<Type>(x - p, y - p); }
//! \~russian Инвертировать координаты точки.
PIPoint<Type> operator -() {return PIPoint<Type>(-x, -y);}
PIPoint<Type> operator-() { return PIPoint<Type>(-x, -y); }
//! \~russian Проверить равенство координат двух точек.
bool operator ==(const PIPoint<Type> & p) const {return (x == p.x && y == p.y);}
bool operator==(const PIPoint<Type> & p) const { return (x == p.x && y == p.y); }
//! \~russian Проверить неравенство координат двух точек.
bool operator !=(const PIPoint<Type> & p) const {return (x != p.x || y != p.y);}
bool operator!=(const PIPoint<Type> & p) const { return (x != p.x || y != p.y); }
};
//! \~russian Перегруженный оператор для вывода координат в \a PICout.
template<typename Type>
PICout operator <<(PICout & s, const PIPoint<Type> & v) {
PICout operator<<(PICout & s, const PIPoint<Type> & v) {
s.saveAndSetControls(0);
s << "Point{" << v.x << ", " << v.y << "}";
s.restoreControls();

View File

@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Class for quaternions
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for quaternions
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piquaternion.h"
@@ -30,8 +30,8 @@ PIQuaternion::PIQuaternion(const PIMathVectorT3d & u, double a) {
PIMathVectorT3d PIQuaternion::eyler() const {
PIMathMatrixT33d rmat = rotationMatrix();
double angle_y = asin(rmat[0][2]), angle_x, angle_z;
double c = cos(angle_y);
double angle_y = asin(rmat[0][2]), angle_x, angle_z;
double c = cos(angle_y);
if (fabs(c) < 1.E-5) {
angle_x = 0;
angle_z = atan2(rmat[1][0], rmat[1][1]);
@@ -39,8 +39,8 @@ PIMathVectorT3d PIQuaternion::eyler() const {
angle_x = -atan2(-rmat[1][2] / c, rmat[2][2] / c);
angle_z = atan2(-rmat[0][1] / c, rmat[0][0] / c);
}
if (angle_z < 0) angle_z = 2*M_PI + angle_z;
return PIMathVectorT3d({angle_x,angle_y,angle_z});
if (angle_z < 0) angle_z = 2 * M_PI + angle_z;
return PIMathVectorT3d({angle_x, angle_y, angle_z});
}
@@ -71,7 +71,6 @@ PIMathMatrixT33d PIQuaternion::rotationMatrix() const {
void PIQuaternion::axis(PIMathVectorT3d * ret) const {
if (!ret) return;
ret[0] = vector();
}
@@ -89,7 +88,7 @@ void PIQuaternion::rotate(const PIMathVectorT3d & u, double a) {
void PIQuaternion::normalize() {
double d = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
double d = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
if (d != 0.)
for (int i = 0; i < 4; ++i)
q[i] /= d;
@@ -105,35 +104,35 @@ PIQuaternion PIQuaternion::fromEyler(double ax, double ay, double az) {
q_heading.q[1] = 0;
q_heading.q[2] = sin(ax / 2);
q_heading.q[3] = -cos(ax / 2);
q_pinch.q[0] = 0;
q_pinch.q[1] = sin(ay / 2);
q_pinch.q[2] = 0;
q_pinch.q[3] = -cos(ay / 2);
az = M_PI - az;
q_bank.q[0] = sin(az / 2);
q_bank.q[1] = 0;
q_bank.q[2] = 0;
q_bank.q[3] = cos(az / 2);
q_tmp = q_heading * q_pinch;
q_tmp = q_tmp * q_bank;
q_pinch.q[0] = 0;
q_pinch.q[1] = sin(ay / 2);
q_pinch.q[2] = 0;
q_pinch.q[3] = -cos(ay / 2);
az = M_PI - az;
q_bank.q[0] = sin(az / 2);
q_bank.q[1] = 0;
q_bank.q[2] = 0;
q_bank.q[3] = cos(az / 2);
q_tmp = q_heading * q_pinch;
q_tmp = q_tmp * q_bank;
q_tmp.normalize();
return q_tmp;
}
PIQuaternion PIQuaternion::fromAngles(double ax, double ay, double az) {
double c1 = cos(ay/2);
double s1 = sin(ay/2);
double c2 = cos(az/2);
double s2 = sin(az/2);
double c3 = cos(ax/2);
double s3 = sin(ax/2);
double c1c2 = c1*c2;
double s1s2 = s1*s2;
double a = c1c2*c3 - s1s2*s3;
double x = c1c2*s3 + s1s2*c3;
double y = s1*c2*c3 + c1*s2*s3;
double z = c1*s2*c3 - s1*c2*s3;
double c1 = cos(ay / 2);
double s1 = sin(ay / 2);
double c2 = cos(az / 2);
double s2 = sin(az / 2);
double c3 = cos(ax / 2);
double s3 = sin(ax / 2);
double c1c2 = c1 * c2;
double s1s2 = s1 * s2;
double a = c1c2 * c3 - s1s2 * s3;
double x = c1c2 * s3 + s1s2 * c3;
double y = s1 * c2 * c3 + c1 * s2 * s3;
double z = c1 * s2 * c3 - s1 * c2 * s3;
PIQuaternion res;
res.q[0] = a;
res.q[1] = x;
@@ -143,13 +142,13 @@ PIQuaternion PIQuaternion::fromAngles(double ax, double ay, double az) {
}
PIQuaternion PIQuaternion::fromAngles2(double ax, double ay, double az) {
double om = PIMathVectorT3d({ax,ay,az}).length();
double om = PIMathVectorT3d({ax, ay, az}).length();
if (om == 0.) return PIQuaternion(PIMathVectorT3d(), 1.);
PIQuaternion res;
res.q[0] = cos(om/2);
res.q[1] = ax/om * sin(om/2);
res.q[2] = ay/om * sin(om/2);
res.q[3] = az/om * sin(om/2);
res.q[0] = cos(om / 2);
res.q[1] = ax / om * sin(om / 2);
res.q[2] = ay / om * sin(om / 2);
res.q[3] = az / om * sin(om / 2);
return res;
}
@@ -189,8 +188,8 @@ PIQuaternion PIQuaternion::fromRotationMatrix(const PIMathMatrixT33d & m) {
PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1) {
PIMathVectorT3d v0(q0.vector()), v1(q1.vector());
double r0 = q0.q[0] * q1.q[0] - v0.dot(v1);
PIMathVectorT3d qv = v1*q0.q[0] + v0*q1.q[0] + v0.cross(v1);
double r0 = q0.q[0] * q1.q[0] - v0.dot(v1);
PIMathVectorT3d qv = v1 * q0.q[0] + v0 * q1.q[0] + v0.cross(v1);
PIQuaternion ret;
ret.q[0] = r0;
ret.q[1] = qv[0];
@@ -200,7 +199,7 @@ PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1) {
}
PIQuaternion operator *(const double &a, const PIQuaternion &q1) {
PIQuaternion operator*(const double & a, const PIQuaternion & q1) {
PIQuaternion ret(q1);
ret.q[0] *= a;
ret.q[1] *= a;
@@ -208,4 +207,3 @@ PIQuaternion operator *(const double &a, const PIQuaternion &q1) {
ret.q[3] *= a;
return ret;
}

View File

@@ -5,22 +5,22 @@
* \~russian Кватернион
*/
/*
PIP - Platform Independent Primitives
Class for quaternions
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for quaternions
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIQUATERNION_H

View File

@@ -4,22 +4,22 @@
//! \~english Rect class
//! \~russian Класс прямоугольника
/*
PIP - Platform Independent Primitives
Rect class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Rect class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIRECT_H
#define PIRECT_H
@@ -36,6 +36,7 @@
template<typename Type>
class PIP_EXPORT PIRect {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public:
//!
PIRect() {}
@@ -55,10 +56,10 @@ public:
normalize();
}
// PIRect(const PIPoint<Type> & p0, const PIPoint<Type> & p1, const PIPoint<Type> & p2) {
// set(piMin<Type>(p0.x, p1.x, p2.x), piMin<Type>(p0.y, p1.y, p2.y),
// piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y));
// }
// PIRect(const PIPoint<Type> & p0, const PIPoint<Type> & p1, const PIPoint<Type> & p2) {
// set(piMin<Type>(p0.x, p1.x, p2.x), piMin<Type>(p0.y, p1.y, p2.y),
// piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y));
// }
//!
PIRect<Type> & set(Type left_, Type bottom_, Type width_, Type height_) {
@@ -76,20 +77,14 @@ public:
//! \brief
//! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику
bool pointIn(Type x, Type y) const {
return (x <= bl.x && x >= tr.x && y <= bl.y && y >= tr.y);
}
bool pointIn(Type x, Type y) const { return (x <= bl.x && x >= tr.x && y <= bl.y && y >= tr.y); }
//! \brief
//! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику
bool pointIn(const PIPoint<Type> & p) const {
return pointIn(p.x, p.y);
}
bool pointIn(const PIPoint<Type> & p) const { return pointIn(p.x, p.y); }
//!
bool isEmpty() const {
return (width() == 0 && height() == 0);
}
bool isEmpty() const { return (width() == 0 && height() == 0); }
//!
PIRect<Type> & translate(Type x, Type y) {
@@ -120,10 +115,10 @@ public:
}
//!
PIRect<Type> & move(Type x, Type y) {return translate(x, y);}
PIRect<Type> & move(Type x, Type y) { return translate(x, y); }
//!
PIRect<Type> & move(const PIPoint<Type> & p) {return translate(p);}
PIRect<Type> & move(const PIPoint<Type> & p) { return translate(p); }
//!
PIRect<Type> moved(Type x, Type y) const {
@@ -147,10 +142,10 @@ public:
}
//!
PIRect<Type> & scale(Type s) {return scale(s, s);}
PIRect<Type> & scale(Type s) { return scale(s, s); }
//!
PIRect<Type> & scale(const PIPoint<Type> & p) {return scale(p.x, p.y);}
PIRect<Type> & scale(const PIPoint<Type> & p) { return scale(p.x, p.y); }
//!
PIRect<Type> scaled(Type x, Type y) const {
@@ -221,74 +216,98 @@ public:
}
//!
Type top() const {return tr.y;}
Type top() const { return tr.y; }
//!
Type left() const {return bl.x;}
Type left() const { return bl.x; }
//!
Type right() const {return tr.x;}
Type right() const { return tr.x; }
//!
Type bottom() const {return bl.y;}
Type bottom() const { return bl.y; }
//!
Type width() const {return tr.x - bl.x;}
Type width() const { return tr.x - bl.x; }
//!
Type height() const {return tr.y - bl.y;}
Type height() const { return tr.y - bl.y; }
//!
PIPoint<Type> topLeft() const {return PIPoint<Type>(bl.x, tr.y);}
PIPoint<Type> topLeft() const { return PIPoint<Type>(bl.x, tr.y); }
//!
PIPoint<Type> topRigth() const {return tr;}
PIPoint<Type> topRigth() const { return tr; }
//!
PIPoint<Type> bottomLeft() const {return bl;}
PIPoint<Type> bottomLeft() const { return bl; }
//!
PIPoint<Type> bottomRight() const {return PIPoint<Type>(tr.x, bl.y);}
PIPoint<Type> bottomRight() const { return PIPoint<Type>(tr.x, bl.y); }
//!
PIPoint<Type> center() const {return bl.moved(width()/2, height()/2);}
PIPoint<Type> center() const { return bl.moved(width() / 2, height() / 2); }
//!
void setTop(Type v) {tr.y = v; normalize();}
void setTop(Type v) {
tr.y = v;
normalize();
}
//!
void setLeft(Type v) {bl.x = v; normalize();}
void setLeft(Type v) {
bl.x = v;
normalize();
}
//!
void setRigth(Type v) {tr.x = v; normalize();}
void setRigth(Type v) {
tr.x = v;
normalize();
}
//!
void setBottom(Type v) {bl.y = v; normalize();}
void setBottom(Type v) {
bl.y = v;
normalize();
}
//!
void setWidth(Type v) {setTop(bl.x + v);}
void setWidth(Type v) { setTop(bl.x + v); }
//!
void setHeight(Type v) {setRigth(bl.y + v);}
void setHeight(Type v) { setRigth(bl.y + v); }
//!
void setTopLeft(const PIPoint<Type> & p) {setLeft(p.x); setTop(p.y);}
void setTopLeft(const PIPoint<Type> & p) {
setLeft(p.x);
setTop(p.y);
}
//!
void setBottomRight(const PIPoint<Type> & p) {setRigth(p.x); setBottom(p.y);}
void setBottomRight(const PIPoint<Type> & p) {
setRigth(p.x);
setBottom(p.y);
}
//!
void setBottomLeft(const PIPoint<Type> & p) {bl = p; normalize();}
void setBottomLeft(const PIPoint<Type> & p) {
bl = p;
normalize();
}
//!
void setTopRigth(const PIPoint<Type> & p) {tr = p; normalize();}
void setTopRigth(const PIPoint<Type> & p) {
tr = p;
normalize();
}
//!
void setCenter(const PIPoint<Type> & p) {
Type w = width();
Type h = height();
bl = p.translated(-w/2, -h/2);
tr = PIPoint<Type>(bl.x + w, bl.y + h);
bl = p.translated(-w / 2, -h / 2);
tr = PIPoint<Type>(bl.x + w, bl.y + h);
}
//!
@@ -298,40 +317,40 @@ public:
}
//!
void operator +=(Type x) {translate(x, x);}
void operator+=(Type x) { translate(x, x); }
//!
void operator +=(const PIPoint<Type> & p) {translate(p);}
void operator+=(const PIPoint<Type> & p) { translate(p); }
//!
void operator -=(Type x) {translate(-x, -x);}
void operator-=(Type x) { translate(-x, -x); }
//!
void operator -=(const PIPoint<Type> & p) {translate(-p);}
void operator-=(const PIPoint<Type> & p) { translate(-p); }
//!
void operator |=(const PIRect<Type> & r) {unite(r);}
void operator|=(const PIRect<Type> & r) { unite(r); }
//!
void operator &=(const PIRect<Type> & r) {intersect(r);}
void operator&=(const PIRect<Type> & r) { intersect(r); }
//!
PIRect<Type> operator +(const PIPoint<Type> & p) {return translated(p);}
PIRect<Type> operator+(const PIPoint<Type> & p) { return translated(p); }
//!
PIRect<Type> operator -(const PIPoint<Type> & p) {return translated(-p);}
PIRect<Type> operator-(const PIPoint<Type> & p) { return translated(-p); }
//!
PIRect<Type> operator |(const PIRect<Type> & r) {return united(r);}
PIRect<Type> operator|(const PIRect<Type> & r) { return united(r); }
//!
PIRect<Type> operator &(const PIRect<Type> & r) {return intersected(r);}
PIRect<Type> operator&(const PIRect<Type> & r) { return intersected(r); }
//!
bool operator ==(const PIRect<Type> & r) const {return (bl == r.bl && tr == r.tr);}
bool operator==(const PIRect<Type> & r) const { return (bl == r.bl && tr == r.tr); }
//!
bool operator !=(const PIRect<Type> & r) const {return (bl != r.bl || tr != r.tr);}
bool operator!=(const PIRect<Type> & r) const { return (bl != r.bl || tr != r.tr); }
private:
PIPoint<Type> bl;
@@ -340,7 +359,7 @@ private:
template<typename Type>
PICout operator <<(PICout & s, const PIRect<Type> & v) {
PICout operator<<(PICout & s, const PIRect<Type> & v) {
s.saveAndSetControls(0);
s << "Rect{" << v.bottomLeft() << ":" << v.width() << "x" << v.height() << "}";
s.restoreControls();

View File

@@ -5,22 +5,22 @@
* \~russian Вычисление математической статистики у массива чисел
*/
/*
PIP - Platform Independent Primitives
Class for calculacing math statistic in values array
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for calculacing math statistic in values array
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISTATISTIC_H
@@ -28,17 +28,17 @@
#include "pimathbase.h"
template <typename T>
template<typename T>
class PIStatistic {
static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic");
public:
PIStatistic() {mean = variance = skewness = kurtosis = T();}
PIStatistic() { mean = variance = skewness = kurtosis = T(); }
static T calculateMean(const PIVector<T> & val) {
T ret = T();
int n = val.size();
if (n < 1)
return ret;
if (n < 1) return ret;
for (int i = 0; i < n; i++)
ret += val[i];
return ret / n;
@@ -46,26 +46,24 @@ public:
bool calculate(const PIVector<T> & val, const T & given_mean) {
T v = T(), v1 = T(), v2 = T(), stddev = T(), var = T();
int i, n = val.size();
if (n < 2)
return false;
mean = given_mean;
if (n < 2) return false;
mean = given_mean;
variance = skewness = kurtosis = T();
// Variance (using corrected two-pass algorithm)
for (i = 0; i < n; i++)
v1 += sqr(val[i] - mean);
for (i = 0; i < n; i++)
v2 += val[i] - mean;
v2 = sqr(v2) / n;
v2 = sqr(v2) / n;
variance = v1 / n;
var = (v1 / n - v2) / (n - 1);
if (var < T())
var = T();
var = (v1 / n - v2) / (n - 1);
if (var < T()) var = T();
stddev = sqrt(var);
// Skewness and kurtosis
if (stddev != T()) {
for (i = 0; i < n; i++) {
v = (val[i] - mean) / stddev;
v2 = sqr(v);
v = (val[i] - mean) / stddev;
v2 = sqr(v);
skewness = skewness + v2 * v;
kurtosis = kurtosis + sqr(v2);
}
@@ -74,8 +72,8 @@ public:
}
return true;
}
bool calculate(const PIVector<T> & val) {return calculate(val, calculateMean(val));}
bool calculate(const PIVector<T> & val) { return calculate(val, calculateMean(val)); }
T mean;
T variance;
T skewness;