File indexing completed on 2024-04-28 03:40:45
0001 /************************************************************************************* 0002 * Copyright (C) 2007 by Aleix Pol <aleixpol@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or * 0005 * modify it under the terms of the GNU General Public License * 0006 * as published by the Free Software Foundation; either version 2 * 0007 * of the License, or (at your option) any later version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, * 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0012 * GNU General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU General Public License * 0015 * along with this program; if not, write to the Free Software * 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 0017 *************************************************************************************/ 0018 0019 #include "operations.h" 0020 0021 #include <math.h> 0022 0023 #include <cmath> 0024 #include <complex> 0025 #include <QCoreApplication> 0026 0027 #include "value.h" 0028 #include "vector.h" 0029 #include "expression.h" 0030 #include "list.h" 0031 #include "expressiontypechecker.h" 0032 #include "customobject.h" 0033 #include "matrix.h" 0034 #include "container.h" 0035 #include "additionchains.h" 0036 0037 using namespace std; 0038 using namespace Analitza; 0039 0040 Object* reduceRealReal(enum Operator::OperatorType op, Cn *oper, double a, double b, QString** correct) 0041 { 0042 Object *ret = oper; 0043 switch(op) { 0044 case Operator::plus: 0045 oper->setValue(a+b); 0046 break; 0047 case Operator::times: 0048 oper->setValue(a*b); 0049 break; 0050 case Operator::divide: 0051 if(Q_LIKELY(b!=0.)) 0052 oper->setValue(a / b); 0053 else { 0054 *correct=new QString(QCoreApplication::tr("Cannot divide by 0.")); 0055 ret=new None(); 0056 } 0057 break; 0058 case Operator::minus: 0059 oper->setValue(a - b); 0060 break; 0061 case Operator::power: 0062 if (b<1 && b>-1 && a<0) { 0063 oper->setValue(pow(complex<double>(a), complex<double>(b))); 0064 } else { 0065 oper->setValue(b==2 ? a*a : pow(a, b)); 0066 } 0067 break; 0068 case Operator::rem: 0069 if(Q_LIKELY(floor(b)!=0.)) 0070 oper->setValue(int(remainder(a, b))); 0071 else { 0072 *correct=new QString(QCoreApplication::tr("Cannot calculate the remainder on 0.")); 0073 ret=new None(); 0074 } 0075 break; 0076 case Operator::quotient: 0077 oper->setValue(int(floor(a / b))); 0078 break; 0079 case Operator::factorof: { 0080 int fb = int(floor(b)); 0081 if(Q_LIKELY(fb!=0)) 0082 oper->setValue((int(floor(a)) % fb)==0); 0083 else { 0084 *correct=new QString(QCoreApplication::tr("Cannot calculate the factor on 0.")); 0085 ret=new None(); 0086 } 0087 } break; 0088 case Operator::min: 0089 oper->setValue(a < b? a : b); 0090 break; 0091 case Operator::max: 0092 oper->setValue(a > b? a : b); 0093 break; 0094 case Operator::gt: 0095 oper->setValue(a > b); 0096 break; 0097 case Operator::lt: 0098 oper->setValue(a < b); 0099 break; 0100 case Operator::eq: 0101 oper->setValue(a == b); 0102 break; 0103 case Operator::approx: 0104 oper->setValue(fabs(a-b)<0.001); 0105 break; 0106 case Operator::neq: 0107 oper->setValue(a != b); 0108 break; 0109 case Operator::geq: 0110 oper->setValue(a >= b); 0111 break; 0112 case Operator::leq: 0113 oper->setValue(a <= b); 0114 break; 0115 case Operator::_and: 0116 oper->setValue(a && b); 0117 break; 0118 case Operator::_or: 0119 oper->setValue(a || b); 0120 break; 0121 case Operator::_xor: 0122 oper->setValue((a || b) && !(a&&b)); 0123 break; 0124 case Operator::implies: 0125 oper->setValue(a || !b); 0126 break; 0127 case Operator::gcd: { 0128 //code by michael cane aka kiko :) 0129 int ia=floor(a), ib=floor(b); 0130 while (ib > 0) { 0131 int residu = ia % ib; 0132 ia = ib; 0133 ib = residu; 0134 } 0135 oper->setValue(ia); 0136 } break; 0137 case Operator::lcm: 0138 //code by michael cane aka kiko :) 0139 if(Q_UNLIKELY(floor(a)==0. || floor(b)==0.)) { 0140 *correct=new QString(QCoreApplication::tr("Cannot calculate the lcm of 0.")); 0141 ret=new None(); 0142 } 0143 else { 0144 int ia=floor(a), ib=floor(b); 0145 int ic=ia*ib; 0146 while (ib > 0) { 0147 int residu = ia % ib; 0148 ia = ib; 0149 ib = residu; 0150 } 0151 ia=ic/ia; 0152 oper->setValue(ia); 0153 } 0154 break; 0155 case Operator::root: 0156 oper->setValue( b==2.0 ? sqrt(a) 0157 : (b>1 || b<-1) && a<0 ? pow(complex<double>(a), complex<double>(1./b)).real() 0158 : pow(a, 1.0/b)); 0159 break; 0160 default: 0161 break; 0162 } 0163 return ret; 0164 } 0165 0166 static bool operator<(complex<double> a, complex<double> b) 0167 { return a.real() < b.real() || (a.real() == b.real() && a.imag()<b.imag()); } 0168 0169 static bool operator>(complex<double> a, complex<double> b) 0170 { return a.real() > b.real() || (a.real() == b.real() && a.imag()>b.imag()); } 0171 0172 static bool operator<=(complex<double> a, complex<double> b) 0173 { return a.real() <= b.real() || (a.real() == b.real() && a.imag()<=b.imag()); } 0174 0175 static bool operator>=(complex<double> a, complex<double> b) 0176 { return a.real() >= b.real() || (a.real() == b.real() && a.imag()>=b.imag()); } 0177 0178 Cn* reduceComplexComplex(enum Operator::OperatorType op, Cn *oper, complex<double> a, complex<double> b, QString** correct) 0179 { 0180 switch(op) { 0181 case Operator::plus: 0182 oper->setValue(a+b); 0183 break; 0184 case Operator::times: 0185 oper->setValue(a*b); 0186 break; 0187 case Operator::divide: 0188 if(Q_LIKELY(b.real()!=0. || b.imag()!=0.)) 0189 oper->setValue(a / b); 0190 else 0191 *correct=new QString(QCoreApplication::tr("Cannot divide by 0.")); 0192 break; 0193 case Operator::minus: 0194 oper->setValue(a - b); 0195 break; 0196 case Operator::power: 0197 oper->setValue(pow(a, b)); 0198 break; 0199 case Operator::rem: 0200 if(Q_LIKELY(floor(b.real())!=0.)) 0201 oper->setValue(int(remainder(a.real(), b.real()))); 0202 else 0203 *correct=new QString(QCoreApplication::tr("Cannot calculate the remainder on 0.")); 0204 break; 0205 case Operator::quotient: 0206 oper->setValue(int(floor((a / b).real()))); 0207 break; 0208 case Operator::factorof: { 0209 int fb = int(floor(b.real())); 0210 if(Q_LIKELY(fb!=0)) 0211 oper->setValue((int(floor(a.real())) % fb)==0); 0212 else 0213 *correct=new QString(QCoreApplication::tr("Cannot calculate the factor on 0.")); 0214 } break; 0215 case Operator::min: 0216 oper->setValue(a < b ? a : b); 0217 break; 0218 case Operator::max: 0219 oper->setValue(a > b? a : b); 0220 break; 0221 case Operator::gt: 0222 oper->setValue(a > b); 0223 break; 0224 case Operator::lt: 0225 oper->setValue(a < b); 0226 break; 0227 case Operator::eq: 0228 oper->setValue(a == b); 0229 break; 0230 case Operator::approx: 0231 oper->setValue(fabs(a.real()-b.real())+fabs(a.imag()-b.imag())<0.001); 0232 break; 0233 case Operator::neq: 0234 oper->setValue(a != b); 0235 break; 0236 case Operator::geq: 0237 oper->setValue(a >= b); 0238 break; 0239 case Operator::leq: 0240 oper->setValue(a <= b); 0241 break; 0242 case Operator::_and: 0243 case Operator::_or: 0244 case Operator::_xor: 0245 case Operator::implies: 0246 *correct = new QString(QCoreApplication::tr("Boolean operations on complex numbers not available")); 0247 break; 0248 case Operator::gcd: { 0249 //code by michael cane aka kiko :) 0250 int ia=floor(a.real()), ib=floor(b.real()); 0251 while (ib > 0) { 0252 int residu = ia % ib; 0253 ia = ib; 0254 ib = residu; 0255 } 0256 oper->setValue(ia); 0257 } break; 0258 case Operator::lcm: 0259 //code by michael cane aka kiko :) 0260 if(Q_UNLIKELY(floor(a.real())==0. || floor(b.real())==0.)) 0261 *correct=new QString(QCoreApplication::tr("Cannot calculate the lcm of 0.")); 0262 else { 0263 int ia=floor(a.real()), ib=floor(b.real()); 0264 int ic=ia*ib; 0265 while (ib > 0) { 0266 int residu = ia % ib; 0267 ia = ib; 0268 ib = residu; 0269 } 0270 ia=ic/ia; 0271 oper->setValue(ia); 0272 } 0273 break; 0274 case Operator::root: 0275 if(b.real()!=2.0 && b.imag()==0) 0276 *correct = new QString(QCoreApplication::tr("Only square root implemented for complex numbers")); 0277 else 0278 oper->setValue(sqrt(a)); 0279 break; 0280 default: 0281 break; 0282 } 0283 return oper; 0284 } 0285 0286 Object* Operations::reduceValueValue(enum Operator::OperatorType op, Cn *oper, const Cn *oper1, QString** correct) 0287 { 0288 if(Q_UNLIKELY(oper->isComplex() || oper1->isComplex())) { 0289 const complex<double> a=oper->complexValue(), b=oper1->complexValue(); 0290 return reduceComplexComplex(op, oper, a, b, correct); 0291 } else { 0292 const double a=oper->value(), b=oper1->value(); 0293 return reduceRealReal(op, oper, a, b, correct); 0294 } 0295 } 0296 0297 Cn* reduceUnaryComplex(Operator::OperatorType op, Cn* oper, QString** correct) 0298 { 0299 const complex<double> a=oper->complexValue(); 0300 0301 switch(op) { 0302 case Operator::minus: 0303 oper->setValue(-a); 0304 break; 0305 case Operator::sin: 0306 oper->setValue(sin(a)); 0307 break; 0308 case Operator::cos: 0309 oper->setValue(cos(a)); 0310 break; 0311 case Operator::tan: 0312 oper->setValue(tan(a)); 0313 break; 0314 case Operator::sinh: 0315 oper->setValue(sinh(a)); 0316 break; 0317 case Operator::cosh: 0318 oper->setValue(cosh(a)); 0319 break; 0320 case Operator::tanh: 0321 oper->setValue(tanh(a)); 0322 break; 0323 case Operator::coth: 0324 oper->setValue(cosh(a)/sinh(a)); 0325 break; 0326 case Operator::exp: 0327 oper->setValue(exp(a)); 0328 break; 0329 case Operator::ln: 0330 oper->setValue(log(a)); 0331 break; 0332 case Operator::log: 0333 oper->setValue(log10(a)); 0334 break; 0335 case Operator::abs: 0336 oper->setValue(std::abs(a)); 0337 break; 0338 case Operator::conjugate: 0339 oper->setValue(std::conj(a)); 0340 break; 0341 case Operator::arg: 0342 oper->setValue(std::arg(a)); 0343 break; 0344 case Operator::real: 0345 oper->setValue(a.real()); 0346 break; 0347 case Operator::imaginary: 0348 oper->setValue(a.imag()); 0349 break; 0350 default: 0351 *correct=new QString(QCoreApplication::tr("Could not calculate a value %1").arg(Operator(op).toString())); 0352 } 0353 return oper; 0354 } 0355 0356 Cn* reduceUnaryReal(Operator::OperatorType op, Cn* oper, QString** correct) 0357 { 0358 const double a=oper->value(); 0359 0360 switch(op) { 0361 case Operator::minus: 0362 oper->setValue(-a); 0363 break; 0364 case Operator::factorial: { 0365 //Use gamma from math.h? 0366 uint res=1; 0367 for(int i=a; i>1.; i--) { 0368 res*=floor(i); 0369 } 0370 oper->setValue(res); 0371 } break; 0372 case Operator::sin: 0373 oper->setValue(sin(a)); 0374 break; 0375 case Operator::cos: 0376 oper->setValue(cos(a)); 0377 break; 0378 case Operator::tan: 0379 oper->setValue(tan(a)); 0380 break; 0381 case Operator::sec: 0382 oper->setValue(1./cos(a)); 0383 break; 0384 case Operator::csc: 0385 oper->setValue(1./sin(a)); 0386 break; 0387 case Operator::cot: 0388 oper->setValue(1./tan(a)); 0389 break; 0390 case Operator::sinh: 0391 oper->setValue(sinh(a)); 0392 break; 0393 case Operator::cosh: 0394 oper->setValue(cosh(a)); 0395 break; 0396 case Operator::tanh: 0397 oper->setValue(tanh(a)); 0398 break; 0399 case Operator::sech: 0400 oper->setValue(1.0/cosh(a)); 0401 break; 0402 case Operator::csch: 0403 oper->setValue(1.0/sinh(a)); 0404 break; 0405 case Operator::coth: 0406 oper->setValue(cosh(a)/sinh(a)); 0407 break; 0408 case Operator::arcsin: 0409 oper->setValue(asin(a)); 0410 break; 0411 case Operator::arccos: 0412 oper->setValue(acos(a)); 0413 break; 0414 case Operator::arctan: 0415 oper->setValue(atan(a)); 0416 break; 0417 case Operator::arccot: 0418 oper->setValue(log(a+pow(a*a+1., 0.5))); 0419 break; 0420 case Operator::arcsinh: //see https://en.wikipedia.org/wiki/Inverse_hyperbolic_function 0421 oper->setValue(asinh(a)); 0422 break; 0423 case Operator::arccosh: 0424 oper->setValue(acosh(a)); 0425 break; 0426 case Operator::arccsc: 0427 oper->setValue(1/asin(a)); 0428 break; 0429 case Operator::arccsch: 0430 oper->setValue(log(1/a+sqrt(1/(a*a)+1))); 0431 break; 0432 case Operator::arcsec: 0433 oper->setValue(1/(acos(a))); 0434 break; 0435 case Operator::arcsech: 0436 oper->setValue(log(1/a+sqrt(1/a+1)*sqrt(1/a-1))); 0437 break; 0438 case Operator::arctanh: 0439 oper->setValue(atanh(a)); 0440 break; 0441 case Operator::exp: 0442 oper->setValue(exp(a)); 0443 break; 0444 case Operator::ln: 0445 oper->setValue(log(a)); 0446 break; 0447 case Operator::log: 0448 oper->setValue(log10(a)); 0449 break; 0450 case Operator::abs: 0451 oper->setValue(a>=0. ? a : -a); 0452 break; 0453 case Operator::floor: 0454 oper->setValue(floor(a)); 0455 break; 0456 case Operator::ceiling: 0457 oper->setValue(ceil(a)); 0458 break; 0459 case Operator::_not: 0460 oper->setValue(!a); 0461 break; 0462 default: 0463 *correct=new QString(QCoreApplication::tr("Could not calculate a value %1").arg(Operator(op).toString())); 0464 break; 0465 } 0466 return oper; 0467 } 0468 0469 Object* Operations::reduceUnaryValue(Operator::OperatorType op, Cn* oper, QString** correct) 0470 { 0471 if(Q_UNLIKELY(oper->isComplex())) 0472 return reduceUnaryComplex(op, oper, correct); 0473 else 0474 return reduceUnaryReal(op, oper, correct); 0475 } 0476 0477 Object* Operations::reduceNoneValue(Operator::OperatorType op, None*, Cn*, QString** correct) 0478 { 0479 return errorCase(QCoreApplication::tr("Cannot calculate %1 between a value and an error type").arg(Operator(op).name()), correct); 0480 } 0481 0482 Object* Operations::reduceValueNone(Operator::OperatorType op, Cn* oper, None* cntr, QString** correct) 0483 { 0484 return reduceNoneValue(op, cntr, oper, correct); 0485 } 0486 0487 Object * Operations::reduceValueVector(Operator::OperatorType op, Cn * oper, Vector * v1, QString** correct) 0488 { 0489 switch(op) { 0490 case Operator::selector: { 0491 int select=oper->intValue(); 0492 delete oper; 0493 Object* ret=nullptr; 0494 if(select<1 || (select-1) >= v1->size()) { 0495 *correct=new QString(QCoreApplication::tr("Invalid index for a container")); 0496 ret=new None(); 0497 } else { 0498 ret=v1->at(select-1)->copy(); 0499 } 0500 return ret; 0501 } break; 0502 default: { 0503 Vector *ret = v1->copy(); 0504 for(Vector::iterator it=ret->begin(); it!=ret->end(); ++it) 0505 { 0506 *it=reduce(op, new Cn(*oper), *it, correct); 0507 } 0508 0509 delete oper; 0510 return ret; 0511 } 0512 } 0513 } 0514 0515 Object * Operations::reduceVectorValue(Operator::OperatorType op, Vector * v1, Cn * oper, QString** correct) 0516 { 0517 for(Vector::iterator it=v1->begin(); it!=v1->end(); ++it) 0518 { 0519 *it=reduce(op, *it, new Cn(*oper), correct); 0520 } 0521 return v1; 0522 } 0523 0524 Object * Operations::reduceVectorVector(Operator::OperatorType op, Vector * v1, Vector * v2, QString** correct) 0525 { 0526 if(v1->size()!=v2->size()) { //FIXME: unneeded? ... aucahuasi: I think is needed ... 0527 *correct=new QString(QCoreApplication::tr("Cannot operate '%1' on different sized vectors.").arg(Operator(op).name())); 0528 return new None(); 0529 } 0530 0531 if(op==Operator::scalarproduct) 0532 op=Operator::times; 0533 Vector::iterator it2=v2->begin(); 0534 for(Vector::iterator it1=v1->begin(); it1!=v1->end(); ++it1, ++it2) 0535 { 0536 *it1=reduce(op, *it1, *it2, correct); 0537 } 0538 return v1; 0539 } 0540 0541 Object* Operations::reduceMatrixVector(Operator::OperatorType op, Matrix* matrix, Vector* vector, QString** correct) 0542 { 0543 Object* ret = nullptr; 0544 if (op == Operator::times) { 0545 if (matrix->hasOnlyNumbers() && vector->hasOnlyNumbers()) { 0546 const int maxk = matrix->columnCount(); 0547 0548 if (maxk == vector->size()) { 0549 const int m = matrix->rowCount(); 0550 0551 Vector *newvec = new Vector(m); 0552 0553 for (int i = 0; i < m; ++i) { 0554 std::complex<double> sum = 0.; 0555 for (int k = 0; k < maxk; ++k) 0556 sum += static_cast<const Cn*>(reduceValueValue(op, (Cn*)matrix->at(i,k), (Cn*)vector->at(k), correct))->complexValue(); 0557 0558 if (sum.imag() == 0) 0559 newvec->appendBranch(new Cn(sum.real())); 0560 else 0561 newvec->appendBranch(new Cn(sum.real(), sum.imag())); 0562 } 0563 0564 ret = newvec; 0565 } else { 0566 *correct=new QString(QCoreApplication::tr("Multiplication between a matrix and a vector is allowed provided that the number of columns of the matrix equals the size of the vector")); 0567 ret=new None(); 0568 } 0569 } else { 0570 *correct=new QString(QCoreApplication::tr("Matrix and vector entries must be numbers")); 0571 ret=new None(); 0572 } 0573 } 0574 0575 return ret; 0576 } 0577 0578 Object* Operations::reduceUnaryVector(Operator::OperatorType op, Vector* c, QString** correct) 0579 { 0580 Object *ret=nullptr; 0581 switch(op) { 0582 case Operator::card: 0583 ret=new Cn(c->size()); 0584 break; 0585 case Operator::transpose: { 0586 const int n = c->size(); 0587 0588 Matrix* mret = new Matrix; 0589 MatrixRow* row = new MatrixRow(n); 0590 for(int j=0; j<n; ++j) { 0591 row->appendBranch(c->at(j)->copy()); 0592 } 0593 0594 mret->appendBranch(row); 0595 ret = mret; 0596 } break; 0597 default: 0598 //Should be dealt by typechecker. not necessary 0599 *correct=new QString(QCoreApplication::tr("Could not calculate a vector's %1").arg(Operator(op).toString())); 0600 ret=new None(); 0601 break; 0602 } 0603 delete c; 0604 return ret; 0605 } 0606 0607 Object* Operations::reduceListList(Operator::OperatorType op, List* l1, List* l2, QString** correct) 0608 { 0609 Object* ret=nullptr; 0610 switch(op) { 0611 case Operator::_union: { 0612 List::iterator itEnd=l2->end(); 0613 for(List::iterator it=l2->begin(); it!=itEnd; ++it) { 0614 l1->appendBranch((*it)->copy()); 0615 } 0616 0617 ret=l1; 0618 } break; 0619 default: 0620 //Should be dealt by typechecker. not necessary 0621 *correct=new QString(QCoreApplication::tr("Could not calculate a list's %1").arg(Operator(op).toString())); 0622 delete l1; 0623 ret=new None(); 0624 break; 0625 } 0626 return ret; 0627 } 0628 0629 Object* Operations::reduceUnaryList(Operator::OperatorType op, List* l, QString** correct) 0630 { 0631 Object *ret=nullptr; 0632 switch(op) { 0633 case Operator::card: 0634 ret=new Cn(l->size()); 0635 break; 0636 default: 0637 *correct=new QString(QCoreApplication::tr("Could not calculate a list's %1").arg(Operator(op).toString())); 0638 ret=new None(); 0639 break; 0640 } 0641 delete l; 0642 return ret; 0643 } 0644 0645 Object* Operations::reduceValueList(Operator::OperatorType op, Cn* oper, List* v1, QString** correct) 0646 { 0647 switch(op) { 0648 case Operator::selector: { 0649 int select=oper->intValue(); 0650 Object* ret=nullptr; 0651 if(select<1 || (select-1) >= v1->size()) { 0652 *correct=new QString(QCoreApplication::tr("Invalid index for a container")); 0653 ret=new None(); 0654 } else { 0655 ret=v1->at(select-1); 0656 v1->setAt(select-1, nullptr); 0657 } 0658 delete oper; 0659 return ret; 0660 } break; 0661 default: 0662 break; 0663 } 0664 return nullptr; 0665 } 0666 0667 Object* Operations::reduceCustomCustom(Operator::OperatorType op, CustomObject* v1, CustomObject* v2, QString** ) 0668 { 0669 switch(op) { 0670 case Operator::neq: 0671 return new Cn(v1->value()!=v2->value()); 0672 case Operator::eq: 0673 return new Cn(v1->value()==v2->value()); 0674 default: 0675 break; 0676 } 0677 0678 Q_ASSERT(false && "not implemented, please report"); 0679 return nullptr; 0680 } 0681 0682 Object* Operations::reduceVectorMatrix(Operator::OperatorType op, Vector* vector, Matrix* matrix, QString** correct) 0683 { 0684 Object* ret = nullptr; 0685 if (op == Operator::times) { 0686 if (vector->hasOnlyNumbers() && matrix->hasOnlyNumbers()) { 0687 if (1 == matrix->rowCount()) { 0688 const int m = vector->size(); 0689 const int n = matrix->columnCount(); 0690 0691 Matrix *newmat = new Matrix(); 0692 0693 for (int i = 0; i < m; ++i) { 0694 MatrixRow *row = new MatrixRow(n); 0695 for (int j = 0; j < n; ++j) 0696 row->appendBranch(reduceValueValue(op, (Cn*)vector->at(i), (Cn*)matrix->at(0,j), correct)->copy()); 0697 0698 newmat->appendBranch(row); 0699 } 0700 0701 ret = newmat; 0702 } else { 0703 *correct=new QString(QCoreApplication::tr("Multiplication between a vector and a matrix is allowed provided that the matrix has only one matrixrow element")); 0704 ret=new None(); 0705 } 0706 } else { 0707 *correct=new QString(QCoreApplication::tr("Matrix and vector entries must be numbers")); 0708 ret=new None(); 0709 } 0710 } 0711 0712 return ret; 0713 } 0714 0715 Object* Operations::reduceMatrixMatrix(Operator::OperatorType op, Matrix* m1, Matrix* m2, QString** correct) 0716 { 0717 Object* ret = nullptr; 0718 switch(op) { 0719 //TODO see if we can use here and or xor for matrix too 0720 case Operator::plus: 0721 case Operator::minus: { 0722 if(m1->rowCount() == m2->rowCount() && m1->columnCount() == m2->columnCount()) { 0723 Matrix::iterator it2=m2->begin(); 0724 for(Matrix::iterator it1=m1->begin(); it1!=m1->end(); ++it1, ++it2) 0725 { 0726 *it1 = static_cast<MatrixRow*>(reduceVectorVector(op, *it1, *it2, correct)); 0727 } 0728 ret = m1; 0729 } else { 0730 *correct=new QString(QCoreApplication::tr("Addition of two matrices is allowed provided that both matrices have the same number of rows and the same number of columns")); 0731 ret=new None(); 0732 } 0733 } break; 0734 case Operator::times: { 0735 if (m1->hasOnlyNumbers() && m2->hasOnlyNumbers()) { 0736 const int maxk = m1->columnCount(); 0737 if (maxk == m2->rowCount()) { 0738 const int m = m1->rowCount(); 0739 const int n = m2->columnCount(); 0740 0741 Matrix *matrix = new Matrix(); 0742 0743 for (int i = 0; i < m; ++i) { 0744 MatrixRow *row = new MatrixRow(n); 0745 for (int j = 0; j < n; ++j) { 0746 std::complex<double> sum = 0; 0747 for (int k = 0; k < maxk; ++k) { 0748 sum += static_cast<const Cn*>(reduceValueValue(op, (Cn*)m1->at(i,k)->copy(), (Cn*)m2->at(k,j)->copy(), correct))->complexValue(); 0749 } 0750 0751 if (sum.imag() == 0) 0752 row->appendBranch(new Cn(sum.real())); 0753 else 0754 row->appendBranch(new Cn(sum.real(), sum.imag())); 0755 } 0756 0757 matrix->appendBranch(row); 0758 } 0759 0760 ret = matrix; 0761 } else { 0762 *correct=new QString(QCoreApplication::tr("Multiplication of two matrices is allowed provided that the number of columns of the first matrix equals the number of rows of the second matrix")); 0763 ret=new None(); 0764 } 0765 } else { 0766 *correct=new QString(QCoreApplication::tr("Matrix entries must be numbers")); 0767 ret=new None(); 0768 } 0769 } break; 0770 default: 0771 break; 0772 } 0773 0774 return ret; 0775 } 0776 0777 Object* Operations::reduceValueMatrix(Operator::OperatorType op, Cn* v, Matrix* m1, QString** correct) 0778 { 0779 Object* ret = nullptr; 0780 switch(op) { 0781 case Operator::selector: { 0782 int select=v->intValue(); 0783 if(select<1 || (select-1) >= m1->rowCount()) { 0784 *correct=new QString(QCoreApplication::tr("Invalid index for a container")); 0785 ret=new None(); 0786 } else { 0787 MatrixRow* row = static_cast<MatrixRow*>(m1->rows().at(select-1)); 0788 Vector* nv = new Vector(row->size()); 0789 for(Vector::iterator it=row->begin(); it!=row->end(); ++it) { 0790 nv->appendBranch((*it)); 0791 *it = nullptr; 0792 } 0793 ret = nv; 0794 } 0795 delete v; 0796 } break; 0797 case Operator::times: { 0798 if (m1->hasOnlyNumbers()) { 0799 Matrix *nm = new Matrix(); 0800 for(Matrix::iterator it=m1->begin(); it!=m1->end(); ++it) 0801 nm->appendBranch(static_cast<MatrixRow*>(reduceValueVector(op, static_cast<Cn*>(v->copy()), static_cast<MatrixRow*>(*it), correct))); 0802 ret = nm; 0803 } else { 0804 *correct=new QString(QCoreApplication::tr("Matrix entries must be numbers")); 0805 ret=new None(); 0806 } 0807 } break; 0808 default: 0809 break; 0810 } 0811 return ret; 0812 } 0813 0814 Object* Operations::reduceMatrixValue(Operator::OperatorType op, Matrix* matrix, Cn* value, QString** correct) 0815 { 0816 Object* ret = nullptr; 0817 switch(op) { 0818 case Operator::power: { 0819 if (matrix->hasOnlyNumbers()) { 0820 if (matrix->isSquare()) { 0821 if (value->isInteger()) { 0822 const int exp = qAbs(value->intValue()); 0823 0824 switch(exp) { 0825 case 0: ret = Matrix::identity(matrix->rowCount()); break; 0826 case 1: ret = matrix; break; 0827 default: { 0828 //base = value->intValue() < 0? invert(matrix) : matrix;//TODO negative exponents 0829 Matrix *base = matrix; 0830 0831 if (exp <= MAX_EXPONENT) { // then: use Addition-chain exponentiation 0832 const int len = additionChains[exp][0]; 0833 int i, j, k; 0834 QVector<Matrix*> products(len+1); 0835 products[0] = base; 0836 0837 if (exp>1) 0838 products[1] = static_cast<Matrix*>(reduceMatrixMatrix(Operator::times, matrix, matrix, correct)); 0839 0840 //NOTE see https://rosettacode.org/wiki/Addition-chain_exponentiation#C for more details 0841 for (i = 2; i <= len; ++i) 0842 for (j = i - 1; j; --j) 0843 for (k = j; k >= 0; --k) 0844 { 0845 if (additionChains[exp][k+1] + additionChains[exp][j+1] < additionChains[exp][i+1]) break; 0846 if (additionChains[exp][k+1] + additionChains[exp][j+1] > additionChains[exp][i+1]) continue; 0847 products[i] = static_cast<Matrix*>(reduceMatrixMatrix(Operator::times, products[j], products[k], correct)); 0848 j = 1; 0849 break; 0850 } 0851 ret = products[len]; 0852 0853 //NOTE free the memory, except products[len] 0854 for (i = 0; i < len; ++i) 0855 delete products[i]; 0856 } else { // else: use Exponentiation by squaring 0857 Matrix *product = Matrix::identity(base->rowCount()); 0858 Matrix *newbase = base->copy(); 0859 int n = exp; 0860 0861 while (n != 0) { 0862 if (n % 2 != 0) { 0863 Matrix *oldproduct = product; 0864 product = static_cast<Matrix*>(reduceMatrixMatrix(Operator::times, product, newbase, correct)); 0865 delete oldproduct; 0866 --n; 0867 } 0868 Matrix *oldbase = newbase; 0869 newbase = static_cast<Matrix*>(reduceMatrixMatrix(Operator::times, newbase, newbase, correct)); 0870 delete oldbase; 0871 n /= 2; 0872 } 0873 0874 ret = product; 0875 } 0876 } break; 0877 } 0878 } else { 0879 *correct=new QString(QCoreApplication::tr("The exponent of 'power' must be some integer number")); 0880 ret=new None(); 0881 } 0882 } else { 0883 *correct=new QString(QCoreApplication::tr("Cannot compute 'power' for non square matrix")); 0884 ret=new None(); 0885 } 0886 } else { 0887 *correct=new QString(QCoreApplication::tr("Matrix entries must be numbers")); 0888 ret=new None(); 0889 } 0890 } break; 0891 //TODO root 0892 default: 0893 break; 0894 } 0895 return ret; 0896 } 0897 0898 Object* Operations::reduceUnaryMatrix(Operator::OperatorType op, Matrix* m, QString** ) 0899 { 0900 Object* ret = nullptr; 0901 switch(op) { 0902 case Operator::transpose: { 0903 int sizeA = m->rowCount(), sizeB = static_cast<MatrixRow*>(*m->constBegin())->size(); 0904 Matrix* mret = new Matrix; 0905 for(int i=0; i<sizeB; ++i) { 0906 MatrixRow* row = new MatrixRow(sizeA); 0907 for(int j=0; j<sizeA; ++j) { 0908 row->appendBranch(m->at(j, i)->copy()); 0909 } 0910 mret->appendBranch(row); 0911 } 0912 ret = mret; 0913 } break; 0914 default: 0915 break; 0916 } 0917 return ret; 0918 } 0919 0920 Object* Operations::reduceMatrixNone(Operator::OperatorType op, Matrix*, None*, QString** correct) 0921 { 0922 return errorCase(QCoreApplication::tr("Cannot calculate %1 between a matrix and an error type").arg(Operator(op).name()), correct); 0923 } 0924 0925 Object* Operations::reduceNoneMatrix(Operator::OperatorType op, None* cntr, Matrix* m, QString** correct) 0926 { 0927 return reduceMatrixNone(op, m, cntr, correct); 0928 } 0929 0930 ExpressionType TypeTriplet(const ExpressionType& a,const ExpressionType& b,const ExpressionType& c) { return ExpressionType(ExpressionType::Lambda).addParameter(a).addParameter(b).addParameter(c); } 0931 0932 //TODO: test that there's one output per input 0933 QList<ExpressionType> Operations::infer(Operator::OperatorType op) 0934 { 0935 QList<ExpressionType> ret; 0936 0937 switch(op) { 0938 case Operator::plus: 0939 case Operator::minus: 0940 ret << TypeTriplet(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 0941 ret << TypeTriplet(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0942 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0943 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0944 ret << TypeTriplet(ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 0945 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 0946 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1)); 0947 break; 0948 case Operator::divide: 0949 ret << TypeTriplet(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 0950 ret << TypeTriplet(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0951 ExpressionType(ExpressionType::Value), 0952 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0953 ret << TypeTriplet(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0954 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0955 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0956 break; 0957 case Operator::times: 0958 ret << TypeTriplet(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 0959 ret << TypeTriplet(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0960 ExpressionType(ExpressionType::Value), 0961 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0962 ret << TypeTriplet(ExpressionType(ExpressionType::Value), 0963 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0964 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0965 ret << TypeTriplet(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0966 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0967 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0968 ret << TypeTriplet(ExpressionType(ExpressionType::Value), 0969 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 0970 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1)); 0971 ret << TypeTriplet(ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 0972 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 0973 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1)); 0974 ret << TypeTriplet(ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 0975 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), 0976 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0977 ret << TypeTriplet(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0978 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), 1), 0979 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1)); 0980 break; 0981 case Operator::eq: 0982 case Operator::neq: 0983 ret << TypeTriplet(ExpressionType(ExpressionType::Any, 1), 0984 ExpressionType(ExpressionType::Any, 1), 0985 ExpressionType(ExpressionType::Bool)); 0986 break; 0987 case Operator::scalarproduct: 0988 ret << TypeTriplet( 0989 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0990 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 0991 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1)); 0992 break; 0993 case Operator::power: 0994 ret << TypeTriplet(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 0995 ret << TypeTriplet(ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), -1), 0996 ExpressionType(ExpressionType::Value), 0997 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), -1)); 0998 break; 0999 case Operator::rem: 1000 case Operator::quotient: 1001 case Operator::factorof: 1002 case Operator::min: 1003 case Operator::max: 1004 case Operator::gcd: 1005 case Operator::lcm: 1006 case Operator::root: 1007 ret << TypeTriplet(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 1008 break; 1009 case Operator::gt: 1010 case Operator::lt: 1011 case Operator::approx: 1012 case Operator::geq: 1013 case Operator::leq: 1014 ret << TypeTriplet(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Bool)); 1015 break; 1016 case Operator::_and: 1017 case Operator::_or: 1018 case Operator::_xor: 1019 case Operator::implies: 1020 ret << TypeTriplet(ExpressionType(ExpressionType::Bool), ExpressionType(ExpressionType::Bool), ExpressionType(ExpressionType::Bool)); 1021 break; 1022 case Operator::selector: 1023 ret << TypeTriplet(ExpressionType(ExpressionType::Value), 1024 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1), 1025 ExpressionType(ExpressionType::Any, 1)); 1026 ret << TypeTriplet(ExpressionType(ExpressionType::Value), 1027 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1)), 1028 ExpressionType(ExpressionType::Any, 1)); 1029 ret << TypeTriplet(ExpressionType(ExpressionType::Value), 1030 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1), -2), 1031 ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1)); 1032 break; 1033 case Operator::_union: 1034 ret << TypeTriplet(ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1)), 1035 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1)), 1036 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1))); 1037 break; 1038 case Operator::map: 1039 ret << TypeTriplet(ExpressionType(ExpressionType::Lambda).addParameter(ExpressionType(ExpressionType::Any, 1)).addParameter(ExpressionType(ExpressionType::Any, 2)), 1040 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1)), 1041 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 2))); 1042 break; 1043 case Operator::filter: 1044 ret << TypeTriplet(ExpressionType(ExpressionType::Lambda).addParameter(ExpressionType(ExpressionType::Any, 1)).addParameter(ExpressionType::Bool), 1045 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1)), 1046 ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1))); 1047 break; 1048 default: 1049 break; 1050 } 1051 return ret; 1052 } 1053 1054 ExpressionType TypePair(const ExpressionType& a, const ExpressionType& b) { return ExpressionType(ExpressionType::Lambda).addParameter(a).addParameter(b); } 1055 1056 QList<ExpressionType> Operations::inferUnary(Operator::OperatorType op) 1057 { 1058 QList<ExpressionType> ret; 1059 switch(op) { 1060 case Operator::minus: 1061 ret << TypePair(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 1062 ret << TypePair(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1), ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1)); 1063 break; 1064 case Operator::card: 1065 ret << TypePair(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1), ExpressionType(ExpressionType::Value)); 1066 ret << TypePair(ExpressionType(ExpressionType::List, ExpressionType(ExpressionType::Any, 1)), ExpressionType(ExpressionType::Value)); 1067 break; 1068 case Operator::sum: 1069 case Operator::product: 1070 ret << TypePair(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 1071 ret << TypePair(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1), ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Any, 1), -1)); 1072 break; 1073 case Operator::transpose: 1074 ret << TypePair(ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1), 1075 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), -2)); 1076 ret << TypePair(ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 1077 ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -1), 1)); 1078 break; 1079 case Operator::factorial: 1080 case Operator::sin: 1081 case Operator::cos: 1082 case Operator::tan: 1083 case Operator::sec: 1084 case Operator::csc: 1085 case Operator::cot: 1086 case Operator::sinh: 1087 case Operator::cosh: 1088 case Operator::tanh: 1089 case Operator::sech: 1090 case Operator::csch: 1091 case Operator::coth: 1092 case Operator::arcsin: 1093 case Operator::arccos: 1094 case Operator::arctan: 1095 case Operator::arccot: 1096 case Operator::arcsinh: 1097 case Operator::arccosh: 1098 case Operator::arccsc: 1099 case Operator::arccsch: 1100 case Operator::arcsec: 1101 case Operator::arcsech: 1102 case Operator::arctanh: 1103 case Operator::exp: 1104 case Operator::ln: 1105 case Operator::log: 1106 case Operator::abs: 1107 case Operator::conjugate: 1108 case Operator::arg: 1109 case Operator::real: 1110 case Operator::imaginary: 1111 case Operator::floor: 1112 case Operator::ceiling: 1113 ret << TypePair(ExpressionType(ExpressionType::Value), ExpressionType(ExpressionType::Value)); 1114 break; 1115 case Operator::_not: 1116 case Operator::exists: 1117 case Operator::forall: 1118 ret << TypePair(ExpressionType(ExpressionType::Bool), ExpressionType(ExpressionType::Bool)); 1119 break; 1120 default: 1121 break; 1122 } 1123 return ret; 1124 } 1125 1126 Operations::BinaryOp Operations::opsBinary[Object::custom+1][Object::custom+1] = { 1127 {nullptr,(Operations::BinaryOp) reduceNoneValue,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,(Operations::BinaryOp) reduceNoneMatrix,nullptr,nullptr}, 1128 {(Operations::BinaryOp) reduceValueNone, (Operations::BinaryOp) reduceValueValue, nullptr, (Operations::BinaryOp) reduceValueVector, (Operations::BinaryOp) reduceValueList,nullptr,nullptr,nullptr,(Operations::BinaryOp) reduceValueMatrix,nullptr}, 1129 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}, 1130 {nullptr, (Operations::BinaryOp) reduceVectorValue, nullptr, (Operations::BinaryOp) reduceVectorVector, nullptr,nullptr,nullptr,nullptr,(Operations::BinaryOp) reduceVectorMatrix,nullptr,nullptr}, 1131 {nullptr, nullptr, nullptr,nullptr, (Operations::BinaryOp) reduceListList, nullptr,nullptr,nullptr,nullptr,nullptr}, 1132 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}, 1133 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}, 1134 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}, 1135 {(Operations::BinaryOp) reduceMatrixNone, (Operations::BinaryOp) reduceMatrixValue,nullptr, (Operations::BinaryOp) reduceMatrixVector,nullptr,nullptr,nullptr,nullptr, (Operations::BinaryOp) reduceMatrixMatrix,nullptr,nullptr}, 1136 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}, 1137 {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,(Operations::BinaryOp) reduceCustomCustom} 1138 }; 1139 1140 Object * Operations::reduce(Operator::OperatorType op, Object * val1, Object * val2, QString** correct) 1141 { 1142 Object::ObjectType t1=val1->type(), t2=val2->type(); 1143 1144 BinaryOp f=opsBinary[t1][t2]; 1145 Q_ASSERT(f); 1146 return f(op, val1, val2, correct); 1147 } 1148 1149 Operations::UnaryOp Operations::opsUnary[] = { 1150 nullptr, 1151 (Operations::UnaryOp) Operations::reduceUnaryValue, 1152 nullptr, //variable 1153 (Operations::UnaryOp) Operations::reduceUnaryVector, 1154 (Operations::UnaryOp) Operations::reduceUnaryList, 1155 nullptr, //apply 1156 nullptr, //oper 1157 nullptr, //container 1158 (Operations::UnaryOp) Operations::reduceUnaryMatrix 1159 }; 1160 1161 Object * Operations::reduceUnary(Operator::OperatorType op, Object * val, QString** correct) 1162 { 1163 Q_ASSERT(val->type()<=Operator::matrix); 1164 UnaryOp f=opsUnary[val->type()]; 1165 1166 Q_ASSERT(f && "using reduceUnary in a wrong way"); 1167 return f(op, val, correct); 1168 } 1169 1170 Object* Operations::errorCase(const QString& error, QString** correct) 1171 { 1172 *correct = new QString(error); 1173 return new None; 1174 }