hikyuu2/hikyuu_cpp/hikyuu/indicator/IndicatorImp.cpp
2019-11-10 23:31:41 +08:00

1185 lines
33 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* IndicatorImp.cpp
*
* Created on: 2013-2-9
* Author: fasiondog
*/
#include <stdexcept>
#include <algorithm>
#include "Indicator.h"
#include "../Stock.h"
#include "../Log.h"
#if HKU_SUPPORT_SERIALIZATION
BOOST_CLASS_EXPORT(hku::IndicatorImp)
#endif
namespace hku {
HKU_API std::ostream &operator<<(std::ostream &os, const IndicatorImp &imp) {
os << "Indicator(" << imp.name() << ", " << imp.getParameter() << ")";
return os;
}
HKU_API std::ostream &operator<<(std::ostream &os, const IndicatorImpPtr &imp) {
if (!imp) {
os << "Indicator(NULL)";
} else {
os << *imp;
}
return os;
}
IndicatorImp::IndicatorImp()
: m_name("IndicatorImp"), m_discard(0), m_result_num(0), m_need_calculate(true), m_optype(LEAF) {
initContext();
memset(m_pBuffer, 0, sizeof(PriceList *) * MAX_RESULT_NUM);
}
IndicatorImp::IndicatorImp(const string &name)
: m_name(name), m_discard(0), m_result_num(0), m_need_calculate(true), m_optype(LEAF) {
initContext();
memset(m_pBuffer, 0, sizeof(PriceList *) * MAX_RESULT_NUM);
}
IndicatorImp::IndicatorImp(const string &name, size_t result_num)
: m_name(name), m_discard(0), m_need_calculate(true), m_optype(LEAF) {
initContext();
memset(m_pBuffer, 0, sizeof(PriceList *) * MAX_RESULT_NUM);
m_result_num = result_num < MAX_RESULT_NUM ? result_num : MAX_RESULT_NUM;
}
void IndicatorImp::initContext() {
setParam<KData>("kdata", KData());
}
void IndicatorImp::setContext(const Stock &stock, const KQuery &query) {
m_need_calculate = true;
//子节点设置上下文
if (m_left)
m_left->setContext(stock, query);
if (m_right)
m_right->setContext(stock, query);
if (m_three)
m_three->setContext(stock, query);
//如果上下文有变化则重设上下文
KData kdata = getContext();
if (kdata.getStock() != stock || kdata.getQuery() != query) {
setParam<KData>("kdata", stock.getKData(query));
}
//启动重新计算
calculate();
}
void IndicatorImp::setContext(const KData &k) {
m_need_calculate = true;
//子节点设置上下文
if (m_left)
m_left->setContext(k);
if (m_right)
m_right->setContext(k);
if (m_three)
m_three->setContext(k);
//如果上下文有变化则重设上下文
KData old_k = getParam<KData>("kdata");
if (old_k.getStock() != k.getStock() || old_k.getQuery() != k.getQuery()) {
setParam<KData>("kdata", k);
}
//启动重新计算
calculate();
}
void IndicatorImp::_readyBuffer(size_t len, size_t result_num) {
if (result_num > MAX_RESULT_NUM) {
throw(
std::invalid_argument("result_num oiverload MAX_RESULT_NUM! "
"[IndicatorImp::_readyBuffer]" +
name()));
}
if (result_num == 0) {
// HKU_TRACE("result_num is zeror! (" << name() << ") [IndicatorImp::_readyBuffer]")
return;
}
price_t null_price = Null<price_t>();
for (size_t i = 0; i < result_num; ++i) {
if (!m_pBuffer[i]) {
m_pBuffer[i] = new PriceList(len, null_price);
} else {
m_pBuffer[i]->clear();
m_pBuffer[i]->reserve(len);
for (size_t j = 0; j < len; ++j) {
m_pBuffer[i]->push_back(null_price);
}
}
}
for (size_t i = result_num; i < m_result_num; ++i) {
delete m_pBuffer[i];
m_pBuffer[i] = NULL;
}
m_result_num = result_num;
}
IndicatorImp::~IndicatorImp() {
for (size_t i = 0; i < m_result_num; ++i) {
delete m_pBuffer[i];
}
}
IndicatorImpPtr IndicatorImp::clone() {
IndicatorImpPtr p = _clone();
p->m_params = m_params;
p->m_name = m_name;
p->m_discard = m_discard;
p->m_result_num = m_result_num;
p->m_need_calculate = m_need_calculate;
p->m_optype = m_optype;
for (size_t i = 0; i < m_result_num; ++i) {
if (m_pBuffer[i]) {
p->m_pBuffer[i] = new PriceList(m_pBuffer[i]->begin(), m_pBuffer[i]->end());
}
}
if (m_left) {
p->m_left = m_left->clone();
}
if (m_right) {
p->m_right = m_right->clone();
}
if (m_three) {
p->m_three = m_three->clone();
}
return p;
}
IndicatorImpPtr IndicatorImp::operator()(const Indicator &ind) {
HKU_INFO("This indicator not support operator()! {}", *this);
//保证对齐
IndicatorImpPtr result = make_shared<IndicatorImp>();
size_t total = ind.size();
result->_readyBuffer(total, m_result_num);
result->setDiscard(total);
return result;
}
void IndicatorImp::setDiscard(size_t discard) {
size_t tmp_discard = discard > size() ? size() : discard;
if (tmp_discard > m_discard) {
price_t null_price = Null<price_t>();
for (size_t i = 0; i < m_result_num; ++i) {
for (size_t j = m_discard; j < tmp_discard; ++j) {
_set(null_price, j, i);
}
}
m_discard = tmp_discard;
}
}
string IndicatorImp::long_name() const {
return name() + "(" + m_params.getNameValueList() + ")";
}
PriceList IndicatorImp::getResultAsPriceList(size_t result_num) {
if (result_num >= m_result_num || m_pBuffer[result_num] == NULL) {
return PriceList();
}
return (*m_pBuffer[result_num]);
}
IndicatorImpPtr IndicatorImp::getResult(size_t result_num) {
if (result_num >= m_result_num || m_pBuffer[result_num] == NULL) {
return IndicatorImpPtr();
}
IndicatorImpPtr imp = make_shared<IndicatorImp>();
size_t total = size();
imp->_readyBuffer(total, 1);
imp->setDiscard(discard());
for (size_t i = discard(); i < total; ++i) {
imp->_set(get(i, result_num), i);
}
return imp;
}
price_t IndicatorImp::get(size_t pos, size_t num) {
#if CHECK_ACCESS_BOUND
if ((m_pBuffer[num] == NULL) || pos >= m_pBuffer[num]->size()) {
throw(std::out_of_range("Try to access value out of bounds! " + name() +
" [IndicatorImp::get]"));
return Null<price_t>();
}
#endif
return (*m_pBuffer[num])[pos];
}
void IndicatorImp::_set(price_t val, size_t pos, size_t num) {
#if CHECK_ACCESS_BOUND
if ((m_pBuffer[num] == NULL) || pos >= m_pBuffer[num]->size()) {
std::stringstream buf;
buf << "Try to access value out of bounds! (pos=" << pos << ") " << name()
<< " [IndicatorImp::_set]";
throw(std::out_of_range(buf.str()));
}
(*m_pBuffer[num])[pos] = val;
#else
(*m_pBuffer[num])[pos] = val;
#endif
}
DatetimeList IndicatorImp::getDatetimeList() const {
if (haveParam("align_date_list")) {
return getParam<DatetimeList>("align_date_list");
}
return getContext().getDatetimeList();
}
Datetime IndicatorImp::getDatetime(size_t pos) const {
if (haveParam("align_date_list")) {
DatetimeList dates(getParam<DatetimeList>("align_date_list"));
return pos < dates.size() ? dates[pos] : Null<Datetime>();
}
KData k = getContext();
return pos < k.size() ? k[pos].datetime : Null<Datetime>();
}
price_t IndicatorImp::getByDate(Datetime date, size_t num) {
size_t pos = getPos(date);
return (pos != Null<size_t>()) ? get(pos, num) : Null<price_t>();
}
size_t IndicatorImp::getPos(Datetime date) const {
if (haveParam("align_date_list")) {
DatetimeList dates(getParam<DatetimeList>("align_date_list"));
auto iter = std::lower_bound(dates.begin(), dates.end(), date);
if (iter != dates.end() && *iter == date) {
return iter - dates.begin();
} else {
return Null<size_t>();
}
}
return getContext().getPos(date);
}
string IndicatorImp::formula() const {
std::stringstream buf;
switch (m_optype) {
case LEAF:
buf << m_name;
break;
case OP:
buf << m_name << "(" << m_right->formula() << ")";
break;
case ADD:
buf << m_left->formula() << " + " << m_right->formula();
break;
case SUB:
buf << m_left->formula() << " + " << m_right->formula();
break;
case MUL:
buf << m_left->formula() << " * " << m_right->formula();
break;
case DIV:
buf << m_left->formula() << " / " << m_right->formula();
break;
case MOD:
buf << m_left->formula() << " % " << m_right->formula();
break;
case EQ:
buf << m_left->formula() << " == " << m_right->formula();
break;
case GT:
buf << m_left->formula() << " > " << m_right->formula();
break;
case LT:
buf << m_left->formula() << " < " << m_right->formula();
break;
case NE:
buf << m_left->formula() << " != " << m_right->formula();
break;
case GE:
buf << m_left->formula() << " >= " << m_right->formula();
break;
case LE:
buf << m_left->formula() << " <= " << m_right->formula();
break;
case AND:
buf << m_left->formula() << " & " << m_right->formula();
break;
case OR:
buf << m_left->formula() << " | " << m_right->formula();
break;
case WEAVE:
buf << "WEAVE(" << m_left->formula() << ", " << m_right->formula() << ")";
case OP_IF:
buf << "IF(" << m_three->formula() << ", " << m_left->formula() << ", "
<< m_right->formula() << ")";
break;
default:
HKU_ERROR("Wrong optype! {}", m_optype);
break;
}
return buf.str();
}
void IndicatorImp::add(OPType op, IndicatorImpPtr left, IndicatorImpPtr right) {
if (op == LEAF || op >= INVALID || !right) {
HKU_ERROR("Wrong used!");
return;
}
if (OP == op && !isLeaf()) {
if (m_left) {
if (m_left->isNeedContext()) {
if (m_left->isLeaf()) {
m_need_calculate = true;
m_left = right->clone();
} else {
HKU_WARN(
"Context-dependent indicator can only be at the leaf node!"
"parent node: {}, try add node: {}",
name(), right->name());
}
} else {
if (m_left->isLeaf()) {
m_left->m_need_calculate = true;
m_left->m_optype = op;
m_left->m_right = right->clone();
} else {
m_left->add(OP, left, right);
}
}
}
if (m_right) {
if (m_right->isNeedContext()) {
if (m_right->isLeaf()) {
m_need_calculate = true;
m_right = right->clone();
} else {
HKU_WARN(
"Context-dependent indicator can only be at the leaf node!"
"parent node: {}, try add node: {}",
name(), right->name());
}
} else {
if (m_right->isLeaf()) {
m_right->m_need_calculate = true;
m_right->m_optype = op;
m_right->m_right = right->clone();
} else {
m_right->add(OP, left, right);
}
}
}
} else {
m_need_calculate = true;
m_optype = op;
m_left = left ? left->clone() : left;
m_right = right->clone();
}
}
void IndicatorImp::add_if(IndicatorImpPtr cond, IndicatorImpPtr left, IndicatorImpPtr right) {
if (!cond || !left || !right) {
HKU_ERROR("Wrong used!");
return;
}
m_need_calculate = true;
m_optype = IndicatorImp::OP_IF;
m_three = cond->clone();
m_left = left->clone();
m_right = right->clone();
}
bool IndicatorImp::needCalculate() {
if (m_need_calculate) {
return true;
}
//子节点设置上下文
if (m_left) {
m_need_calculate = m_left->needCalculate();
if (m_need_calculate) {
return true;
}
}
if (m_right) {
m_need_calculate = m_right->needCalculate();
if (m_need_calculate) {
return true;
}
}
if (m_three) {
m_need_calculate = m_three->needCalculate();
if (m_need_calculate) {
return true;
}
}
return false;
}
Indicator IndicatorImp::calculate() {
IndicatorImpPtr result;
if (!check()) {
HKU_ERROR("Invalid param! {} : {}", formula(), long_name());
if (m_right) {
m_right->calculate();
_readyBuffer(m_right->size(), m_result_num);
m_discard = m_right->size();
try {
result = shared_from_this();
} catch (...) {
// Python中继承的实现会出现bad_weak_ptr错误通过此方式避免
result = clone();
}
}
return Indicator(result);
}
if (!needCalculate()) {
try {
result = shared_from_this();
} catch (...) {
result = clone();
}
return Indicator(result);
}
switch (m_optype) {
case LEAF:
_calculate(Indicator());
break;
case OP:
m_right->calculate();
_readyBuffer(m_right->size(), m_result_num);
_calculate(Indicator(m_right));
setParam<KData>("kdata", m_right->getParam<KData>("kdata"));
break;
case ADD:
execute_add();
break;
case SUB:
execute_sub();
break;
case MUL:
execute_mul();
break;
case DIV:
execute_div();
break;
case MOD:
execute_mod();
break;
case EQ:
execute_eq();
break;
case NE:
execute_ne();
break;
case GT:
execute_gt();
break;
case LT:
execute_lt();
break;
case GE:
execute_ge();
break;
case LE:
execute_le();
break;
case AND:
execute_and();
break;
case OR:
execute_or();
break;
case WEAVE:
execute_weave();
break;
case OP_IF:
execute_if();
break;
default:
HKU_ERROR("Unkown Indicator::OPType! {}", m_optype);
break;
}
//使用原型方式时,不加此判断无法立刻重新计算
if (size() != 0) {
m_need_calculate = false;
}
try {
result = shared_from_this();
} catch (...) {
// Python中继承的实现会出现bad_weak_ptr错误通过此方式避免
result = clone();
}
return Indicator(result);
}
void IndicatorImp::execute_weave() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = minp->getResultNumber() + maxp->getResultNumber();
if (result_number > MAX_RESULT_NUM) {
result_number = MAX_RESULT_NUM;
}
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() >= m_right->size()) {
size_t num = m_left->getResultNumber();
for (size_t r = 0; r < num; ++r) {
for (size_t i = discard; i < total; ++i) {
_set(m_left->get(i, r), i, r);
}
}
for (size_t r = num; r < result_number; r++) {
for (size_t i = discard; i < total; i++) {
_set(m_right->get(i - diff, r - num), i, r);
}
}
} else {
size_t num = m_left->getResultNumber();
for (size_t r = 0; r < num; ++r) {
for (size_t i = discard; i < total; ++i) {
_set(m_left->get(i - diff, r), i, r);
}
}
for (size_t r = num; r < result_number; r++) {
for (size_t i = discard; i < total; i++) {
_set(m_right->get(i, r - num), i, r);
}
}
}
}
void IndicatorImp::execute_add() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
_set(maxp->get(i, r) + minp->get(i - diff, r), i, r);
}
}
}
void IndicatorImp::execute_sub() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
_set(m_left->get(i, r) - m_right->get(i - diff, r), i, r);
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
_set(m_left->get(i - diff, r) - m_right->get(i, r), i, r);
}
}
}
}
void IndicatorImp::execute_mul() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
_set(maxp->get(i, r) * minp->get(i - diff, r), i, r);
}
}
}
void IndicatorImp::execute_div() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_right->get(i - diff, r) == 0.0) {
_set(Null<price_t>(), i, r);
} else {
_set(m_left->get(i, r) / m_right->get(i - diff, r), i, r);
}
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_right->get(i, r) == 0.0) {
_set(Null<price_t>(), i, r);
} else {
_set(m_left->get(i - diff, r) / m_right->get(i, r), i, r);
}
}
}
}
}
void IndicatorImp::execute_mod() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_right->get(i - diff, r) == 0.0) {
_set(Null<price_t>(), i, r);
} else {
_set(int64(m_left->get(i, r)) % int64(m_right->get(i - diff, r)), i, r);
}
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_right->get(i, r) == 0.0) {
_set(Null<price_t>(), i, r);
} else {
_set(int64(m_left->get(i - diff, r)) % int64(m_right->get(i, r)), i, r);
}
}
}
}
}
void IndicatorImp::execute_eq() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (std::fabs(maxp->get(i, r) - minp->get(i - diff, r)) < IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
void IndicatorImp::execute_ne() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (std::fabs(maxp->get(i, r) - minp->get(i - diff, r)) < IND_EQ_THRESHOLD) {
_set(0, i, r);
} else {
_set(1, i, r);
}
}
}
}
void IndicatorImp::execute_gt() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_left->get(i, r) - m_right->get(i - diff, r) >= IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_left->get(i - diff, r) - m_right->get(i, r) >= IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
}
void IndicatorImp::execute_lt() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_right->get(i - diff, r) - m_left->get(i, r) >= IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_right->get(i, r) - m_left->get(i - diff, r) >= IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
}
void IndicatorImp::execute_ge() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_left->get(i, r) > m_right->get(i - diff, r) - IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_left->get(i - diff, r) > m_right->get(i, r) - IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
}
void IndicatorImp::execute_le() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_left->size() > m_right->size()) {
maxp = m_left.get();
minp = m_right.get();
} else {
maxp = m_right.get();
minp = m_left.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
if (m_left->size() > m_right->size()) {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_left->get(i, r) < m_right->get(i - diff, r) + IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
} else {
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_left->get(i - diff, r) < m_right->get(i, r) + IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
}
void IndicatorImp::execute_and() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (maxp->get(i, r) >= IND_EQ_THRESHOLD && minp->get(i - diff, r) >= IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
void IndicatorImp::execute_or() {
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
size_t diff = maxp->size() - minp->size();
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (maxp->get(i, r) >= IND_EQ_THRESHOLD || minp->get(i - diff, r) >= IND_EQ_THRESHOLD) {
_set(1, i, r);
} else {
_set(0, i, r);
}
}
}
}
void IndicatorImp::execute_if() {
m_three->calculate();
m_right->calculate();
m_left->calculate();
IndicatorImp *maxp, *minp;
if (m_right->size() > m_left->size()) {
maxp = m_right.get();
minp = m_left.get();
} else {
maxp = m_left.get();
minp = m_right.get();
}
size_t total = maxp->size();
size_t discard = maxp->size() - minp->size() + minp->discard();
if (discard < maxp->discard()) {
discard = maxp->discard();
}
if (m_three->size() >= maxp->size()) {
total = m_three->size();
discard = total + discard - maxp->size();
} else {
discard = total - m_three->size();
}
size_t diff_right = total - m_right->size();
size_t diff_left = total - m_left->size();
size_t diff_cond = total - m_three->size();
size_t result_number = std::min(minp->getResultNumber(), maxp->getResultNumber());
_readyBuffer(total, result_number);
setDiscard(discard);
for (size_t r = 0; r < result_number; ++r) {
for (size_t i = discard; i < total; ++i) {
if (m_three->get(i - diff_cond) > 0.0) {
_set(m_left->get(i - diff_left), i, r);
} else {
_set(m_right->get(i - diff_right), i, r);
}
}
}
}
} /* namespace hku */