File indexing completed on 2022-12-06 18:52:35

0001 /*
0002     Task.cpp  -  source code of class Task
0003     SPDX-FileCopyrightText: 2001 Sebastian Stein <seb.kde@hpfsc.de>
0004     SPDX-FileCopyrightText: 2008 Tiago Porangaba <tiago.porangaba@ltia.fc.unesp.br>
0005     SPDX-FileCopyrightText: 2008 Tadeu Araujo <tadeu.araujo@ltia.fc.unesp.br>
0006     SPDX-FileCopyrightText: 2008 Danilo Balzaque <danilo.balzaque@ltia.fc.unesp.br>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "Task.h"
0012 
0013 #include <cmath>
0014 #include <ctime>
0015 #include <QRandomGenerator>
0016 
0017 #include <QDebug>
0018 
0019 /** constructor of class task */
0020 Task::Task()
0021 {
0022 #ifdef DEBUG
0023     qDebug() << "constructor task";
0024 #endif
0025 }
0026 
0027 /** destructor of class task */
0028 Task::~Task()
0029 {
0030 #ifdef DEBUG
0031     qDebug() << "destructor task";
0032 #endif
0033 }
0034 
0035 /** create a task with random ratios and operations; the generated task
0036  * can be customized by the given parameters:
0037  * pmax_md: maximum main denominator
0038  * pnr_ratios: number of ratios -> pnr_ratios - 1 operations
0039 */
0040 void Task::create_task(unsigned int pmax_md, short pnr_ratios,
0041                        short padd_add, short padd_div,
0042                        short padd_mult, short padd_sub)
0043 {
0044     unsigned int max_product_length = 0;
0045     int main_denominator = 1;
0046 
0047     do {
0048         /* delete a maybe given task */
0049         clean();
0050 
0051         /* generate the operations and count the max. mul/div in one block */
0052         max_product_length = make_operation(padd_add, padd_div, padd_mult, padd_sub, pnr_ratios);
0053 
0054 #ifdef DEBUG
0055         qDebug() << "1: max_product_length: " << max_product_length;
0056 #endif
0057 
0058         /* later we must be able to find a main denominator;
0059          * so 2 ^ max_product_length couldn't be bigger than the max. denominator */
0060     } while ((unsigned int) pow(2.0, (double) max_product_length) > pmax_md);
0061 
0062 #ifdef DEBUG
0063     qDebug() << "2: max_product_length: " << max_product_length;
0064 #endif
0065 
0066     /* find a main denominator */
0067     main_denominator = make_main_dn(pmax_md, max_product_length);
0068 
0069 #ifdef DEBUG
0070     qDebug() << "after make_main_dn()";
0071 #endif
0072 
0073     /* create the ratios' numerators */
0074     make_numerators(main_denominator, pnr_ratios);
0075 
0076 #ifdef DEBUG
0077     qDebug() << "after make_numerators()";
0078 #endif
0079 
0080     /* create the ratios' denominators */
0081     make_denominators(main_denominator, pmax_md, padd_div, padd_mult);
0082 
0083 #ifdef DEBUG
0084     qDebug() << "main deno: " << main_denominator;
0085     qDebug() << "prim fakt: " << prim_fac_vector.size();
0086 #endif
0087 
0088     return;
0089 }
0090 
0091 /** set ratio n in the ratio_vector */
0092 void Task::set_ratio_n(unsigned short number, int numerator, int denominator)
0093 {
0094     /* do not set something outside our vector */
0095     if (number > ratio_vector.size() - 1)
0096         number = 0;
0097     ratio_vector[number].setNumerator(numerator);  // set numerator
0098     ratio_vector[number].setDenominator(denominator);  // set denominator
0099     return;
0100 }
0101 
0102 /** set ratio n in the ratio_vector */
0103 void Task::set_ratio_n(unsigned short number, const Ratio &fraction)
0104 {
0105     /* do not set something outside our vector */
0106     if (number > ratio_vector.size() - 1)
0107         number = 0;
0108     ratio_vector[number].setNumerator(fraction.numerator());  // set numerator
0109     ratio_vector[number].setDenominator(fraction.denominator());  // set denominator
0110     return;
0111 }
0112 
0113 /** returns the ratio given by number from the ratio_vector */
0114 Ratio Task::get_ratio_n(unsigned short number) const
0115 {
0116     /* do not set something outside our vector */
0117     if (number > ratio_vector.size() - 1)
0118         number = 0;
0119     return ratio_vector[number];
0120 }
0121 
0122 /** set operation given by the number in the op_vector */
0123 void Task::set_op_n(unsigned short number, short operation)
0124 {
0125     /* do not set something outside our vector */
0126     if (number > op_vector.size() - 1)
0127         number = 0;
0128     op_vector[number] = operation;
0129     return;
0130 }
0131 
0132 /** returns the operation given by number from the op_vector */
0133 short Task::get_op_n(unsigned short number) const
0134 {
0135     /* do not set something outside our vector */
0136     if (number > op_vector.size() - 1)
0137         number = 0;
0138     return op_vector[number];
0139 }
0140 
0141 /** add a new ratio at the end of the ratio vector */
0142 void Task::add_ratio(const Ratio &new_ratio)
0143 {
0144     ratio_vector.push_back(new_ratio);
0145     return;
0146 }
0147 
0148 /** add a new ratio at the end of the ratio vector */
0149 void Task::add_ratio(int numerator, int denominator)
0150 {
0151     Ratio new_ratio(numerator, denominator);
0152     ratio_vector.push_back(new_ratio);
0153     return;
0154 }
0155 
0156 /** add a new operation at the end of the operation vector */
0157 void Task::add_operation(short operation)
0158 {
0159     op_vector.push_back(operation);
0160     return;
0161 }
0162 
0163 /** just outputs the whole given task to stdout; for debugging */
0164 QTextStream & Task::display(QTextStream & str)
0165 {
0166 #ifdef DEBUG
0167     qDebug() << "task::display()";
0168 #endif
0169 
0170     /* this is our pointer on the ratio_vector, set it to the beginning */
0171     RatioArray::iterator ratio_pointer = ratio_vector.begin();
0172 
0173     /* this is our pointer on the op_vector, set it to the beginning */
0174     ShortArray::iterator op_pointer = op_vector.begin();
0175 
0176     /* we need this array to look up the fitting chars for the operations */
0177     const char a[] = "+-*/";
0178 
0179     /* check, if a qSetFieldWidth() was given to the stream */
0180     int weite = str.fieldWidth();
0181     int pweite = weite;
0182     str << qSetFieldWidth(0);
0183 
0184     /* check, if ratio number and operation number fit together */
0185     if (ratio_vector.size() != op_vector.size() + 1) {
0186         qDebug() << "Number of ratios and operations do not fit.";
0187         return str;
0188     }
0189 
0190     while (pweite-- > 0)
0191         str << " ";
0192 
0193     /* display all numerators */
0194     for (ratio_pointer = ratio_vector.begin();
0195             ratio_pointer != ratio_vector.end(); ++ratio_pointer) {
0196         str << qSetFieldWidth(5) << ratio_pointer->numerator() << "   ";
0197     }
0198     str << QLatin1Char('\n');
0199 
0200     pweite = weite;
0201     while (pweite-- > 0)
0202         str << " ";
0203 
0204     /* display all operations */
0205     for (op_pointer = op_vector.begin();
0206             op_pointer != op_vector.end(); ++op_pointer) {
0207         str << " ----- " << a[*op_pointer];
0208     }
0209     str << " ----- = \n";
0210 
0211     pweite = weite;
0212     while (pweite-- > 0)
0213         str << " ";
0214 
0215     /* display all denominators */
0216     for (ratio_pointer = ratio_vector.begin();
0217             ratio_pointer != ratio_vector.end(); ++ratio_pointer) {
0218         if (ratio_pointer == ratio_vector.end() - 1)
0219             return str << qSetFieldWidth(5) << ratio_pointer->denominator() << "   ";
0220         str << qSetFieldWidth(5) << ratio_pointer->denominator() << "   ";
0221     }
0222     str.flush();
0223     return str;
0224 }
0225 
0226 /** solves the given task and returns the result as a ratio */
0227 Ratio Task::solve()
0228 {
0229     Ratio ergebnis(0, 1);  /* that is the starting point */
0230 
0231     /* this is our pointer on the ratio_vector, set it to the beginning */
0232     RatioArray::iterator ratio_pointer = ratio_vector.begin();
0233 
0234     /* add a temp operation at the beginning */
0235     op_vector.insert(op_vector.begin(), ADD);
0236 
0237     /* this is our pointer on the op_vector, set it to the beginning */
0238     ShortArray::iterator op_pointer = op_vector.begin() + 1;
0239 
0240     /* check, if ratio number and operation number fit together */
0241     if (ratio_vector.size() != op_vector.size()) {
0242         qDebug() << "Number of ratios and operations do not fit.";
0243         return ergebnis;
0244     }
0245 
0246     do {
0247         /* we have to decide our next action by the given operation */
0248         switch (*op_pointer) {
0249         case ADD :
0250         case SUB :
0251             switch (*(op_pointer - 1)) {
0252                 /* we only have to add/sub the next ratio */
0253             case ADD :
0254                 ergebnis = ergebnis + *ratio_pointer++;
0255                 break;
0256             case SUB :
0257                 ergebnis = ergebnis - *ratio_pointer++;
0258                 break;
0259             }
0260             break;
0261         case MUL :
0262         case DIV :
0263             switch (*(op_pointer - 1)) {
0264                 /* the next ratio is a product, so we have to
0265                  * compute this product first and than add/sub it */
0266             case ADD :
0267                 ergebnis = ergebnis +
0268                            product(ratio_pointer, op_pointer);
0269                 break;
0270             case SUB :
0271                 ergebnis = ergebnis -
0272                            product(ratio_pointer, op_pointer);
0273                 break;
0274             }
0275             break;
0276         }
0277         /* check if we reached the and of the task */
0278         if (ratio_pointer == ratio_vector.end())
0279             break;
0280 
0281 #ifdef DEBUG
0282         qDebug() << "Schleifenende";
0283 #endif
0284 
0285     } while (++op_pointer != op_vector.end());
0286 
0287 #ifdef DEBUG
0288     qDebug() << "after do while in solve()";
0289 #endif
0290 
0291     /* if the last operation was an add/sub we haven't add/subed it until now */
0292     --op_pointer;
0293     switch (*op_pointer) {
0294     case ADD :
0295         ergebnis = ergebnis + *ratio_pointer;
0296         break;
0297     case SUB :
0298         ergebnis = ergebnis - *ratio_pointer;
0299         break;
0300     }
0301 
0302     /* erase the temp operation */
0303     op_vector.erase(op_vector.begin());
0304 
0305     /* before we return the result we have to reduce it */
0306     ergebnis.reduce();
0307 
0308     return ergebnis; /* return the solution */
0309 }
0310 
0311 /* returns the number of ratios in the vector */
0312 int Task::getNumberOfRatios() const
0313 {
0314 #ifdef DEBUG
0315     qDebug() << "task::getNumberOfRatios()";
0316 #endif
0317     return ratio_vector.count();
0318 }
0319 
0320 /* returns the number of operations in the vector */
0321 int Task::getNumberOfOperations() const
0322 {
0323 #ifdef DEBUG
0324     qDebug() << "task::getNumberOfOperations()";
0325 #endif
0326     return op_vector.count();
0327 }
0328 
0329 /* removes all ratios and operations from the given task */
0330 void Task::clean()
0331 {
0332 #ifdef DEBUG
0333     qDebug() << "task::clean()";
0334 #endif
0335     ratio_vector.clear();
0336     op_vector.clear();
0337 
0338     return;
0339 }
0340 
0341 /** this function is called by the solving function to compute a given
0342  * product (or div) and return the solution */
0343 Ratio Task::product(RatioArray::iterator & ratio_pointer,
0344                     ShortArray::iterator & op_pointer)
0345 {
0346 #ifdef DEBUG
0347     qDebug() << "task::product()";
0348 #endif
0349     /* the function's parameters are pointing to the next ratio;
0350      * to the starting point of the product */
0351     Ratio product(ratio_pointer->numerator(), ratio_pointer->denominator());
0352 
0353     ++ratio_pointer;
0354     do {
0355         switch (*op_pointer) {
0356         case ADD :
0357             product = product + *ratio_pointer++;
0358             ++op_pointer;
0359             break;
0360         case SUB :
0361             product = product - *ratio_pointer++;
0362             ++op_pointer;
0363             break;
0364         case MUL :
0365             product = product * *ratio_pointer++;
0366             ++op_pointer;
0367             break;
0368         case DIV :
0369             product = product / *ratio_pointer++;
0370             ++op_pointer;
0371             break;
0372         }
0373     } while (op_pointer != op_vector.end());
0374 
0375     /* we get here if the product consists of the whole given task starting
0376      * at the point given by the function's parameters */
0377     return product;
0378 }
0379 
0380 /** generate the operations randomly; return how many mul or div
0381  * are in one block */
0382 unsigned short Task::make_operation(short padd_add, short padd_div, short padd_mult, short padd_sub,
0383                                     short pnr_ratios)
0384 {
0385 #ifdef DEBUG
0386     qDebug() << "task::make_operation()";
0387 #endif
0388     unsigned short max_product_length = 0;
0389     unsigned short operations = 0;
0390     unsigned short counter = 0;
0391 
0392     /* this is our pointer on the op_vector, set it to the beginning */
0393     ShortArray::iterator op_pointer;
0394 
0395     /* clear the old operations */
0396     op_vector.clear();
0397 
0398     /* generate the operations */
0399     if (padd_add == YES && padd_div == NO && padd_mult == NO && padd_sub == NO) {
0400         for (short counter = 0; counter < pnr_ratios - 1; counter++)
0401             op_vector.push_back(ADD);
0402     } else if (padd_div == YES && padd_add == NO && padd_mult == NO && padd_sub == NO) {
0403         for (short counter = 0; counter < pnr_ratios - 1; counter++)
0404             op_vector.push_back(DIV);
0405     } else if (padd_mult == YES && padd_add == NO && padd_div == NO && padd_sub == NO) {
0406         for (short counter = 0; counter < pnr_ratios - 1; counter++)
0407             op_vector.push_back(MUL);
0408     } else if (padd_sub == YES && padd_add == NO && padd_div == NO && padd_mult == NO) {
0409         for (short counter = 0; counter < pnr_ratios - 1; counter++)
0410             op_vector.push_back(SUB);
0411     } else {
0412         do {
0413             operations = QRandomGenerator::global()->bounded(4);
0414             switch (operations) {
0415             case ADD:
0416                 if (padd_add == YES) {
0417                     op_vector.push_back(ADD);
0418                     counter++;
0419                 }
0420                 break;
0421             case SUB:
0422                 if (padd_sub == YES) {
0423                     op_vector.push_back(SUB);
0424                     counter++;
0425                 }
0426                 break;
0427             case DIV:
0428                 if (padd_div == YES) {
0429                     op_vector.push_back(DIV);
0430                     counter++;
0431                 }
0432                 break;
0433             case  MUL:
0434                 if (padd_mult == YES) {
0435                     op_vector.push_back(MUL);
0436                     counter++;
0437                 }
0438                 break;
0439             }
0440         } while (counter < (pnr_ratios - 1));
0441     }
0442 
0443     if (padd_mult == YES || padd_div == YES) {
0444         short flag_counter = 0;
0445 
0446         /* loop through all operations */
0447         for (op_pointer = op_vector.begin();
0448                 op_pointer != op_vector.end(); ++op_pointer) {
0449             /* look if we got a mul/div or add/sub */
0450             if (*op_pointer == DIV || *op_pointer == MUL) {
0451                 flag_counter++;
0452             } else {
0453                 /* we have to decide, if this was the end of a mul/div block or
0454                  * just another add/sub */
0455                 if (flag_counter > 0) {
0456                     /* it was the end of a mul/div block; lets look if it was
0457                      * longer than the blocks before and save it; than restart */
0458                     if (flag_counter > max_product_length)
0459                         max_product_length = flag_counter;
0460                     flag_counter = 0;
0461                 } /* if (flag_counter > 0) */
0462             } /* if (*op_pointer == DIV || *op_pointer == MUL) */
0463         } /* for (op_pointer = op_vector.begin(); ...) */
0464 
0465         /* just to correct the things a little bit if the last operation was a
0466          * mul/div as well */
0467         if (flag_counter > max_product_length)
0468             max_product_length = flag_counter;
0469         max_product_length++;
0470     } else {
0471         /* if (pmul_div == YES) */
0472         /* a task is given only with add/sub ops; so we want a max.
0473          * of pnr_ratios / 2 + 1 prime factors, but at least  */
0474         max_product_length = (unsigned short)(float(pnr_ratios) / 2) + 1;
0475         if (max_product_length < 2)
0476             max_product_length = 2;
0477     } /* if (pmul_div == YES) */
0478 
0479     return max_product_length;
0480 }
0481 
0482 /** find a denominator for the task */
0483 int Task::make_main_dn(unsigned int pmax_md, unsigned short max_product_length)
0484 {
0485     int denominator;
0486 
0487     /* find a main denominator in the given limits by pmax_md and check
0488      * if the main denominator has enough prime factors */
0489     do {
0490         denominator = QRandomGenerator::global()->bounded(pmax_md) + 1;
0491     } while ((pmax_md < 1) ||
0492              (prim_factor_nr(denominator) < max_product_length));
0493 
0494     return denominator;
0495 }
0496 
0497 /** returns the count number's prime factors and stores the prime factors
0498  * in the prim_fac_vektor vektor */
0499 unsigned short Task::prim_factor_nr(int number)
0500 {
0501     unsigned int tmp_number = number;
0502     PrimeNumber primeNumber;
0503     Tprime_factor prim_fac_struct;
0504 
0505     /* delete all the prime factors of the old main denominator */
0506     prim_fac_vector.clear();
0507 
0508     /* test if we can find prime factors */
0509     for (primeNumber.move_first(); primeNumber.get_current() <= tmp_number;) {
0510         /* if the current selected prime number is a divisor */
0511         if (tmp_number % primeNumber.get_current() != 0) {
0512             primeNumber.move_forward(); /* no, test next one */
0513         } else {
0514             /* yes, we found a new prime factor; so first we use the divisor */
0515             tmp_number = int (tmp_number / primeNumber.get_current());
0516 
0517             /* now we add the prime factor to our prime factor vector */
0518             prim_fac_struct.factor = primeNumber.get_current();
0519             prim_fac_struct.flag = UNUSED;
0520             prim_fac_vector.push_back(prim_fac_struct);
0521         }
0522     }
0523 #ifdef DEBUG
0524     PrimeFactorArray::iterator prim_fac_pointer = prim_fac_vector.begin();
0525     qDebug() << "Primfaktoren von: " << number;
0526     for (prim_fac_pointer = prim_fac_vector.begin();
0527             prim_fac_pointer != prim_fac_vector.end();
0528             ++prim_fac_pointer)
0529         qDebug() << (*prim_fac_pointer).factor;
0530     qDebug() << "Anzahl: " << prim_fac_vector.size();
0531 #endif
0532 
0533     return prim_fac_vector.size();
0534 }
0535 
0536 /** set the numerators randomly */
0537 void Task::make_numerators(int main_denominator, short pnr_ratios)
0538 {
0539     /* I think it is to easy to deal with ratios like 1/1 or 4/4; so
0540      * I limit the maximum of a numerator */
0541     int max_numerator = int (main_denominator * float(0.7));
0542 
0543     /* add a new ratio to the task and compute the numerator randomly */
0544     for (short tmpcounter = 0; tmpcounter < pnr_ratios; tmpcounter++) {
0545         (*this).add_ratio(QRandomGenerator::global()->bounded(max_numerator) + 1, 1);
0546     }
0547     return;
0548 }
0549 
0550 /** create the ratios' denominators */
0551 void Task::make_denominators(int main_denominator, short pmax_md,
0552                              short padd_div, short padd_mult)
0553 {
0554     /* this is our pointer on the ratio_vector, set it to the beginning */
0555     RatioArray::iterator ratio_pointer = ratio_vector.begin();
0556 
0557     /* this is our pointer on the op_vector, set it to the beginning */
0558     ShortArray::iterator op_pointer = op_vector.begin() + 1;
0559 
0560     /* this is a pointer on the array with the prime factors of the main
0561      * denominator */
0562     PrimeFactorArray::iterator prim_fac_pointer;
0563 
0564     unsigned short unused_fac = prim_fac_vector.size();
0565     unsigned short next_fac;
0566     unsigned short tmp_counter;
0567     int tmp_deno;
0568 
0569     /* check, if ratio number and operation number fit together */
0570     if (ratio_vector.size() != op_vector.size() + 1) {
0571         qDebug() << "Number of ratios and operations do not fit.";
0572         return;
0573     }
0574 
0575     /* first make all denominators */
0576     for (ratio_pointer = ratio_vector.begin();
0577             ratio_pointer != ratio_vector.end(); ++ratio_pointer) {
0578         do {
0579             tmp_deno = QRandomGenerator::global()->bounded(pmax_md) + 1;
0580         } while (main_denominator % tmp_deno != 0);
0581         (*ratio_pointer).setDenominator(tmp_deno);
0582     }
0583 
0584     /* if the ratio is connected to a mul or div operation, we have to do some
0585      * extra work and regenerate the denominators */
0586     if (padd_mult == YES || padd_div == YES) {
0587         /* lets loop through all ratios and check, if there is a mul/div
0588          * after the ratio */
0589         ratio_pointer = ratio_vector.begin();
0590         op_pointer = op_vector.begin();
0591         do {
0592             if (*op_pointer == MUL || *op_pointer == DIV) {
0593                 /* yes, there is a mul/div after the ratio;
0594                  * reset the prime number structure */
0595                 for (prim_fac_pointer = prim_fac_vector.begin();
0596                         prim_fac_pointer != prim_fac_vector.end();
0597                         ++prim_fac_pointer)
0598                     (*prim_fac_pointer).flag = UNUSED;
0599 
0600                 /* how many prime factors are available? */
0601                 unused_fac = prim_fac_vector.size() - 1;
0602 
0603                 /* now loop through this mul/div section until we find a add/sub */
0604                 do {
0605                     /* the prim_fac_vector is sorted, but we do not want the
0606                      * factors in this sorted way as our denominators;
0607                      * so we choose one randomly */
0608                     next_fac = QRandomGenerator::global()->bounded(unused_fac);
0609                     tmp_counter = 0;
0610 
0611                     /* check the prime factors, if they are unused */
0612                     for (prim_fac_pointer = prim_fac_vector.begin();
0613                             prim_fac_pointer != prim_fac_vector.end();
0614                             ++prim_fac_pointer) {
0615                         if ((*prim_fac_pointer).flag == UNUSED) {
0616                             tmp_counter++; /* we found a unused factor */
0617                         }
0618                         /* we found the factor, which we have chosen randomly */
0619                         if (tmp_counter > next_fac)
0620                             break;
0621                     }
0622                     /* mark the factor as used, so we can not use it again in
0623                      * this mul/div section */
0624                     (*prim_fac_pointer).flag = USED;
0625 
0626                     /* store the factor as our new denominator for this ratio */
0627                     (*ratio_pointer).setDenominator((*prim_fac_pointer).factor, false);
0628                     unused_fac--; /* now there is one factor less available */
0629 
0630                     /* move to the next ratio */
0631                     ratio_pointer++;
0632                     op_pointer++;
0633                 } while ((op_pointer != op_vector.end()) &&
0634                          (*op_pointer == MUL || *op_pointer == DIV));
0635 
0636                 /* we always miss to set the last ratio in a mul/div section;
0637                  * so we have to fix this here */
0638                 if (ratio_pointer != ratio_vector.end()) {
0639                     /* the prim_fac_vector is sorted, but we do not want the
0640                      * factors in this sorted way as our denominators;
0641                      * so we choose one randomly */
0642                     next_fac = QRandomGenerator::global()->bounded(unused_fac);
0643                     tmp_counter = 0;
0644 
0645                     /* check the prime factors, if they are unused */
0646                     for (prim_fac_pointer = prim_fac_vector.begin();
0647                             prim_fac_pointer != prim_fac_vector.end();
0648                             ++prim_fac_pointer) {
0649                         if ((*prim_fac_pointer).flag == UNUSED) {
0650                             tmp_counter++; /* we found a unused factor */
0651                         }
0652                         /* we found the factor, which we have chosen randomly */
0653                         if (tmp_counter > next_fac)
0654                             break;
0655                     }
0656                     /* mark the factor as used, so we can not use it again in
0657                      * this mul/div section */
0658                     (*prim_fac_pointer).flag = USED;
0659 
0660                     /* store the factor as our new denominator for this ratio */
0661                     (*ratio_pointer).setDenominator((*prim_fac_pointer).factor, false);
0662                     unused_fac--; /* now there is one factor less available */
0663 
0664                     /* move to the next ratio */
0665                     ratio_pointer++;
0666                     op_pointer++;
0667                 }
0668             } else {
0669                 /* if (*op_pointer == MUL || ...) */
0670                 ratio_pointer++;
0671                 op_pointer++;
0672             }
0673         } while (ratio_pointer != ratio_vector.end() &&
0674                  op_pointer != op_vector.end());
0675 
0676         /* now we will swap all ratios, if there is a div in front of */
0677         ratio_pointer = ratio_vector.begin();
0678         ratio_pointer++;
0679 
0680         for (op_pointer = op_vector.begin(); op_pointer != op_vector.end();
0681                 ++op_pointer) {
0682             if (*op_pointer == DIV) {
0683                 (*ratio_pointer).reziproc();
0684             }
0685             ratio_pointer++;
0686         }
0687     } /* if (pmul_div == YES) */
0688 
0689     return;
0690 }
0691 
0692 
0693 /* ------ some prototyps of non class functions ------ */
0694 
0695 /** it is possible to code: cout << task_object << endl; */
0696 QTextStream & operator<< (QTextStream & str, Task & ptask)
0697 {
0698     return ptask.display(str);
0699 }