natural DIV_NN_N(const natural& a, const natural& b) { if (NZER_N_B(b)) throw std::invalid_argument("Your divider is equal to zero"); // // natural res = natural(); // // natural divident = a; // // natural divider = b; // // natural fact = natural(); // // while (COM_NN_D(divident, b) == ordinal::GT) { // // divider = b; // // fact = DIV_NN_Dk(divident, divider); // // divider = MUL_NN_N(divider, fact); // // divident = SUB_NN_N(divident, divider); // // res = ADD_NN_N(res, fact); // // } // // return res; natural res; natural _a = a; while (_a >= b) { std::pair<digit, std::int16_t> k = DIV_NN_Dk(_a, b); natural sub = MUL_Nk_N(b, k.second); natural c = SUB_NDN_N(_a, sub, k.first); _a = c; res = res + MUL_Nk_N(natural({ k.first }), k.second); } return res; }
natural MUL_ND_N(const natural &a, const digit &n) { // учитываем случаи, когда n = 0 и n = 1 natural a_c = a; switch (n) { case _0: return natural({_0}); break; case _1: return a; break; default: natural res = a; digit dem = _0; digit fact = n; // умножаем каждую цифру числа на n методом mul // переполнение самого старшего разряда учитывается for (int i = 0; i <= res.order(); i++) { auto temp = res[i]; res[i] = mul(temp, fact, dem); } // удаляем возможные незначащие нули res.reduce(); return res; } }
/** Return an integer between min and max inclusive. */ int integer(int min, int max) { return natural() % (max - min + 1) + min; }
rmove() { register struct node *p; register int r; register r1, flt; for (p=first.forw; p!=0; p = p->forw) { flt = 0; switch (p->op) { case MOVF: case MOVFO: case MOVOF: flt = NREG; case MOV: if (p->subop==BYTE) goto dble; dualop(p); if ((r = findrand(regs[RT1], flt)) >= 0) { if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR && p->forw->op!=SXT && p->forw->op!=CFCC) { p->forw->back = p->back; p->back->forw = p->forw; redunm++; nchange++; continue; } } if (equstr(regs[RT1], "$0")) { p->op = CLR; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; goto sngl; } repladdr(p, 0, flt); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2], flt); if (r >= 0) if (r1 >= 0) savereg(r1+flt, regs[r+flt]); else savereg(r+flt, regs[RT2]); else if (r1 >= 0) savereg(r1+flt, regs[RT1]); else setcon(regs[RT1], regs[RT2]); source(regs[RT1]); setcc(regs[RT2]); continue; case ADDF: case SUBF: case DIVF: case MULF: flt = NREG; goto dble; case ADD: case SUB: case BIC: case BIS: case MUL: case DIV: case ASH: dble: dualop(p); if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) { p->op = CLR; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; goto sngl; } if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) { if (p->forw->op!=CBR) { p->back->forw = p->forw; p->forw->back = p->back; nchange++; continue; } } /* * the next block of code looks for the sequences (which extract the * high byte of a word or the low byte respectively): * ash $-10,r * bic $-400,r * or * mov natural,r * bic $-400,r * and transforms them into: * clrb r * swab r * or * clr r * bisb natural,r * These constructs occur often enough in the kernel (dealing with major/minor * device numbers, etc) it's worth a little extra work at compile time. */ if (p->op == BIC && (equstr(regs[RT1],"$-400") || equstr(regs[RT1],"$-177400"))) { if (p->back->op == ASH) { r = isreg(regs[RT2]); dualop(p->back); if ((equstr(regs[RT1], "$-10") || equstr(regs[RT1], "$177770")) && r == isreg(regs[RT2])) { strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->back->op = CLR; p->back->subop = BYTE; p->back->code = copy(1, regs[RT1]); p->op = SWAB; p->code = copy(1, regs[RT1]); nchange++; goto sngl; } } else if (p->back->op == MOV && p->forw->op != CBR) { char temp[50]; r = isreg(regs[RT2]); if (r < 0 && !xnatural(regs[RT2])) goto out; strcpy(temp, regs[RT2]); dualop(p->back); if (isreg(regs[RT2]) == r && natural(regs[RT1])) { if (r < 0 && (!xnatural(regs[RT2]) || !equstr(temp, regs[RT2]))) goto out; /* * XXX - the sequence "movb rN,rN; bic $-400,rN" can not be transformed * because the 'clr' would lose all information about 'rN'. The best that can * be done is to remove the 'movb' instruction and leave the 'bic'. */ if (isreg(regs[RT1]) == r && r >= 0) { p = p->back; p->forw->back = p->back; p->back->forw = p->forw; nchange++; continue; } dest(regs[RT1], flt); p->back->op = CLR; p->back->subop = 0; p->back->code = copy(1, regs[RT2]); p->op = BIS; p->subop = BYTE; strcat(regs[RT1], ","); p->code = copy(2, regs[RT1], regs[RT2]); nchange++; } } out: dualop(p); /* restore banged up parsed operands */ } repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); if (p->op==DIV && (r = isreg(regs[RT2]))>=0) regs[r|1][0] = 0; switch (p->op) { case ADD: case SUB: case BIC: case BIS: case ASH: setcc(regs[RT2]); break; default: ccloc[0] = 0; } continue; case SXT: singop(p); if (p->forw->op == CLR && p->forw->subop != BYTE && xnatural(regs[RT1]) && !strcmp(p->code, p->forw->code)){ p->forw->back = p->back; p->back->forw = p->forw; nchange++; continue; } goto sngl; case CLRF: case NEGF: flt = NREG; case CLR: case COM: case INC: case DEC: case NEG: case ASR: case ASL: case SWAB: singop(p); sngl: dest(regs[RT1], flt); if (p->op==CLR && flt==0) { if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0"); else setcon("$0", regs[RT1]); ccloc[0] = 0; } else setcc(regs[RT1]); continue; case TSTF: flt = NREG; case TST: singop(p); repladdr(p, 0, flt); source(regs[RT1]); if (p->back->op == TST && !flt && not_sp(regs[RT1])) { char rt1[MAXCPS + 2]; strcpy(rt1, regs[RT1]); singop(p->back); if (!strcmp("(sp)+", regs[RT1])) { p->back->subop = p->subop; p->back->forw = p->forw; p->forw->back = p->back; p = p->back; p->op = MOV; p->code = copy(2, rt1, ",(sp)+"); nrtst++; nchange++; continue; } singop(p); } if (p->back->op == MOV && p->back->subop == BYTE) { dualop(p->back); setcc(regs[RT2]); singop(p); } if (equstr(regs[RT1], ccloc) && p->subop == p->back->subop) { p->back->forw = p->forw; p->forw->back = p->back; p = p->back; nrtst++; nchange++; } else setcc(regs[RT1]); /* XXX - double TST in a row */ continue; case CMPF: flt = NREG; case CMP: case BIT: dualop(p); source(regs[RT1]); source(regs[RT2]); if(p->op==BIT) { if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) { p->op = TST; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) { p->op = TST; regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } if (equstr(regs[RT1], "$0")) { p->op = TST; regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } else if (equstr(regs[RT2], "$0")) { p->op = TST; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } } repladdr(p, 1, flt); ccloc[0] = 0; continue; case CBR: r = -1; if (p->back->op==TST || p->back->op==CMP) { if (p->back->op==TST) { singop(p->back); savereg(RT2, "$0"); } else dualop(p->back); if (equstr(regs[RT1], regs[RT2]) && natural(regs[RT1]) && natural(regs[RT2])) r = compare(p->subop, "$1", "$1"); else r = compare(p->subop, findcon(RT1), findcon(RT2)); if (r==0) { if (p->forw->op==CBR || p->forw->op==SXT || p->forw->op==CFCC) { p->back->forw = p->forw; p->forw->back = p->back; } else { p->back->back->forw = p->forw; p->forw->back = p->back->back; } decref(p->ref); p = p->back->back; nchange++; } else if (r>0) { p->op = JBR; p->subop = 0; p->back->back->forw = p; p->back = p->back->back; p = p->back; nchange++; } /* * If the instruction prior to the conditional branch was a 'tst' then * save the condition code status. The C construct: * if (x) * if (x > 0) * generates "tst _x; jeq ...; tst _x; jmi ...;jeq ...". The code below removes * the second "tst _x", leaving "tst _x; jeq ...;jmi ...; jeq ...". */ if (p->back->op == TST) { singop(p->back); setcc(regs[RT1]); break; } } /* * If the previous instruction was also a conditional branch then * attempt to merge the two into a single branch. */ if (p->back->op == CBR) fixupbr(p); case CFCC: ccloc[0] = 0; continue; /* * Unrecognized (unparsed) instructions, assignments (~foo=r2), and * data arrive here. In order to prevent throwing away information * about register contents just because a local assignment is done * we check for the first character being a tilde. */ case 0: if (p->code[0] != '~') clearreg(); continue; case JBR: redunbr(p); default: clearreg(); } } }
mat pca::orth() const throw(exception::full) { if( full() ) throw exception::full(); return basis().rightCols( natural(mean().rows()) - rank()); }
bool pca::full() const { return rank() == natural( mean().rows() ); }