void resize(void) { Rectangle old, r; int dxo, dyo, dxn, dyn; Win *w; old = screen->r; dxo = Dx(old); dyo = Dy(old); if(getwindow(display, Refnone) < 0) sysfatal("resize failed: %r"); dxn = Dx(screen->r); dyn = Dy(screen->r); freescreen(scr); scr = allocscreen(screen, display->white, 0); if(scr == nil) sysfatal("allocscreen: %r"); for(w = wlist.next; w != &wlist; w = w->next){ r = rectsubpt(w->entire, old.min); r.min.x = muldiv(r.min.x, dxn, dxo); r.max.x = muldiv(r.max.x, dxn, dxo); r.min.y = muldiv(r.min.y, dyn, dyo); r.max.y = muldiv(r.max.y, dyn, dyo); w->entire = rectaddpt(r, screen->r.min); w->inner = insetrect(w->entire, BORDSIZ); freeimage(w->im); w->im = allocwindow(scr, w->entire, Refbackup, 0); if(w->im == nil) sysfatal("allocwindow: %r"); draw(w->im, w->inner, w->tab->cols[BACK], nil, ZP); border(w->im, w->entire, BORDSIZ, w->tab->cols[w == actw ? BORD : DISB], ZP); w->tab->draw(w); } }
mr_small smul(mr_small x,mr_small y,mr_small n) { /* returns x*y mod n */ mr_small r; #ifdef MR_ITANIUM mr_small tm; #endif #ifdef MR_WIN64 mr_small tm; #endif #ifdef MR_FP mr_small dres; #endif #ifndef MR_NOFULLWIDTH if (n==0) { /* Assume n=2^MIRACL */ muldvd(x,y,(mr_small)0,&r); return r; } #endif x=MR_REMAIN(x,n); y=MR_REMAIN(y,n); muldiv(x,y,(mr_small)0,n,&r); return r; }
bool ZLTextView::PositionIndicator::onStylusPress(int x, int y) { x = myTextView.visualX(x); const long bottom = this->bottom(); const long top = this->top(); const long left = this->left(); const long right = this->right(); if ((x < left) || (x > right) || (y < top) || (y > bottom)) { return false; } const std::vector<size_t> &textSizeVector = myTextView.myTextSize; if (textSizeVector.size() <= 1) { return true; } if (myTextView.endCursor().isNull()) { return false; } size_t fullTextSize = sizeOfTextBeforeParagraph(endTextIndex()); size_t textSize = muldiv(fullTextSize, x - left + 1, right - left + 1); myTextView.gotoCharIndex(textSize); return true; }
uint8_t CubeFace::GetFaceCoordinates(const VK::ivec3 &v, int &x, int &y) { uint8_t nFace; int ax = VK::Math::Abs(v.x), ay = VK::Math::Abs(v.y), az = VK::Math::Abs(v.z); int sc, tc, ma; if(ax > ay && ax > az) { ma = ax; sc = v.z; tc = -v.y; if(v.x > 0) { nFace = RightFace; sc = -sc; } else { nFace = LeftFace; } } else if(ay > az) { ma = ay; sc = v.x; tc = v.z; if(v.y > 0) { nFace = TopFace; } else { nFace = BottomFace; tc = -tc; } } else { ma = az; sc = v.x; tc = -v.y; if(v.z > 0) { nFace = FrontFace; } else { nFace = BackFace; sc = -sc; } } // x and y should be approximately from MinCoord to MaxCoord x = (muldiv(sc, MaxCoord, ma) + MaxCoord) >> 1; y = (muldiv(tc, MaxCoord, ma) + MaxCoord) >> 1; return nFace; }
mr_small spmd(mr_small x,mr_small n,mr_small m) { /* returns x^n mod m */ mr_small r,sx; #ifdef MR_FP mr_small dres; #endif x=MR_REMAIN(x,m); r=0; if (x==0) return r; r=1; if (n==0) return r; sx=x; forever { if (MR_REMAIN(n,2)!=0) muldiv(r,sx,(mr_small)0,m,&r); n=MR_DIV(n,2); if (n==0) return r; muldiv(sx,sx,(mr_small)0,m,&sx); } }
size_t ZLTextView::PositionIndicator::sizeOfTextBeforeCursor(const ZLTextWordCursor &cursor) const { const size_t paragraphIndex = cursor.paragraphCursor().index(); const size_t paragraphLength = cursor.paragraphCursor().paragraphLength(); if (paragraphLength == 0) { return sizeOfTextBeforeParagraph(paragraphIndex); } else { return sizeOfTextBeforeParagraph(paragraphIndex) + muldiv(sizeOfParagraph(paragraphIndex), cursor.elementIndex(), paragraphLength); } }
/* * Return the specified percentage of a off_t. */ off_t percent_pos(off_t pos, int percent, long fraction) { /* * Change percent (parts per 100) to perden * (parts per NUM_FRAC_DENOM). */ off_t perden = (percent * (NUM_FRAC_DENOM / 100)) + (fraction / 100); if (perden == 0) return (0); return (muldiv(pos, perden, (off_t)NUM_FRAC_DENOM)); }
void ZLTextView::PositionIndicator::draw() { ZLTextBaseStyle &baseStyle = ZLTextStyleCollection::instance().baseStyle(); ZLPaintContext &context = this->context(); ZLTextWordCursor endCursor = myTextView.endCursor(); bool isEndOfText = false; if (endCursor.isEndOfParagraph()) { isEndOfText = !endCursor.nextParagraph(); } myExtraWidth = 0; if (myInfo.isTimeShown()) { drawExtraText(timeString()); } if (myInfo.isBatteryShown()) { drawExtraText(batteryString()); } if (myInfo.isTextPositionShown()) { drawExtraText(textPositionString()); } const long bottom = this->bottom(); const long top = this->top(); const long left = this->left(); const long right = this->right(); if (left >= right) { return; } size_t fillWidth = right - left - 1; if (!isEndOfText) { fillWidth = muldiv(fillWidth, sizeOfTextBeforeCursor(myTextView.endCursor()), sizeOfTextBeforeParagraph(endTextIndex())); } context.setColor(baseStyle.RegularTextColorOption.value()); context.setFillColor(myInfo.color()); context.fillRectangle(myTextView.visualX(left + 1), top + 1, myTextView.visualX(left + fillWidth + 1), bottom - 1); context.drawLine(myTextView.visualX(left), top, myTextView.visualX(right), top); context.drawLine(myTextView.visualX(left), bottom, myTextView.visualX(right), bottom); context.drawLine(myTextView.visualX(left), bottom, myTextView.visualX(left), top); context.drawLine(myTextView.visualX(right), bottom, myTextView.visualX(right), top); }
void ZLTextView::PositionIndicator::draw() { ZLPaintContext &context = this->context(); ZLTextWordCursor endCursor = myTextView.textArea().endCursor(); bool isEndOfText = false; if (endCursor.isEndOfParagraph()) { isEndOfText = !endCursor.nextParagraph(); } myExtraWidth = 0; if (myInfo.isTimeShown()) { drawExtraText(timeString()); } if (myInfo.isTextPositionShown()) { drawExtraText(textPositionString()); } const long bottom = this->bottom(); const long top = this->top(); const long left = this->left(); const long right = this->right(); if (left >= right) { return; } size_t fillWidth = right - left - 1; if (!isEndOfText) { fillWidth = muldiv(fillWidth, sizeOfTextBeforeCursor(myTextView.textArea().endCursor()), sizeOfTextBeforeParagraph(endTextIndex())); } context.setColor(myTextView.color()); context.setFillColor(myInfo.color()); context.fillRectangle(left + 1, top + 1, left + fillWidth + 1, bottom - 1); context.drawLine(left, top, right, top); context.drawLine(left, bottom, right, bottom); context.drawLine(left, bottom, left, top); context.drawLine(right, bottom, right, top); }
void drawoverlay(void) { int major, minor; int hi, lo, x, y; Point omaj, omin, p; y = muldiv(2000, UNITMAG, scrn.mag); for(x = 0; mmap[x] < y; x++); major = mmap[x]; minor = major/5; omaj.x = ((scrn.br.origin.x+major-1)/major)*major; omaj.y = ((scrn.br.origin.y+major-1)/major)*major; omin.x = ((scrn.br.origin.x+minor-1)/minor)*minor; omin.y = ((scrn.br.origin.y+minor-1)/minor)*minor; lo = scrn.br.origin.y; hi = scrn.br.corner.y; for(x = omaj.x; x < scrn.br.corner.x; x += major){ segment(&screen, pbtos(Pt(x, lo)), pbtos(Pt(x, hi)), 0xf, F_XOR); for(y = omin.y; y < hi; y += minor){ if((y-omaj.y)%major == 0) continue; p = pbtos(Pt(x, y)); segment(&screen, Pt(p.x-10, p.y), Pt(p.x+10, p.y), 0xf, F_XOR); } } lo = scrn.br.origin.x; hi = scrn.br.corner.x; for(y = omaj.y; y < scrn.br.corner.y; y += major){ segment(&screen, pbtos(Pt(lo, y)), pbtos(Pt(hi, y)), 0xf, F_XOR); for(x = omin.x; x < hi; x += minor){ if((x-omaj.x)%major == 0) continue; p = pbtos(Pt(x, y)); segment(&screen, Pt(p.x, p.y-10), Pt(p.x, p.y+10), 0xf, F_XOR); } } }
mr_small sqrmp(mr_small x,mr_small m) { /* square root mod a small prime by Shanks method * * returns 0 if root does not exist or m not prime */ mr_small z,y,v,w,t,q; #ifdef MR_FP mr_small dres; #endif int i,e,n,r; BOOL pp; x=MR_REMAIN(x,m); if (x==0) return 0; if (x==1) return 1; if (spmd(x,(mr_small)((m-1)/2),m)!=1) return 0; /* Legendre symbol not 1 */ if (MR_REMAIN(m,4)==3) return spmd(x,(mr_small)((m+1)/4),m); /* easy case for m=4.k+3 */ if (MR_REMAIN(m,8)==5) { /* also relatively easy */ t=spmd(x,(mr_small)((m-1)/4),m); if (t==1) return spmd(x,(mr_small)((m+3)/8),m); if (t==(mr_small)(m-1)) { muldiv((mr_small)4,x,(mr_small)0,m,&t); t=spmd(t,(mr_small)((m+3)/8),m); muldiv(t,(mr_small)((m+1)/2),(mr_small)0,m,&t); return t; } return 0; } q=m-1; e=0; while (MR_REMAIN(q,2)==0) { q=MR_DIV(q,2); e++; } if (e==0) return 0; /* even m */ for (r=2;;r++) { /* find suitable z */ z=spmd((mr_small)r,q,m); if (z==1) continue; t=z; pp=FALSE; for (i=1;i<e;i++) { /* check for composite m */ if (t==(m-1)) pp=TRUE; muldiv(t,t,(mr_small)0,m,&t); if (t==1 && !pp) return 0; } if (t==(m-1)) break; if (!pp) return 0; /* m is not prime */ } y=z; r=e; v=spmd(x,(mr_small)((q+1)/2),m); w=spmd(x,q,m); while (w!=1) { t=w; for (n=0;t!=1;n++) muldiv(t,t,(mr_small)0,m,&t); if (n>=r) return 0; y=spmd(y,mr_shiftbits(1,r-n-1),m); muldiv(v,y,(mr_small)0,m,&v); muldiv(y,y,(mr_small)0,m,&y); muldiv(w,y,(mr_small)0,m,&w); r=n; } return v; }
/* * Return the ratio of two off_t, as a percentage. * {{ Assumes a off_t is a long int. }} */ int percentage(off_t num, off_t den) { return ((int)muldiv(num, (off_t)100, den)); }
int egcd(_MIPD_ big x,big y,big z) { /* greatest common divisor z=gcd(x,y) by Euclids * * method using Lehmers algorithm for big numbers */ int q,r,a,b,c,d,n; mr_small sr,m,sm; mr_small u,v,lq,lr; #ifdef MR_FP mr_small dres; #endif big t; #ifndef MR_GENERIC_MT miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return 0; MR_IN(12) copy(x,mr_mip->w1); copy(y,mr_mip->w2); insign(PLUS,mr_mip->w1); insign(PLUS,mr_mip->w2); a=b=c=d=0; while (size(mr_mip->w2)!=0) { if (b==0) { /* update w1 and w2 */ divide(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w2); t=mr_mip->w1,mr_mip->w1=mr_mip->w2,mr_mip->w2=t; /* swap(w1,w2) */ } else { premult(_MIPP_ mr_mip->w1,c,z); premult(_MIPP_ mr_mip->w1,a,mr_mip->w1); premult(_MIPP_ mr_mip->w2,b,mr_mip->w0); premult(_MIPP_ mr_mip->w2,d,mr_mip->w2); add(_MIPP_ mr_mip->w1,mr_mip->w0,mr_mip->w1); add(_MIPP_ mr_mip->w2,z,mr_mip->w2); } if (mr_mip->ERNUM || size(mr_mip->w2)==0) break; n=(int)mr_mip->w1->len; if (mr_mip->w2->len==1) { /* special case if mr_mip->w2 is now small */ sm=mr_mip->w2->w[0]; #ifdef MR_FP_ROUNDING sr=mr_sdiv(_MIPP_ mr_mip->w1,sm,mr_invert(sm),mr_mip->w1); #else sr=mr_sdiv(_MIPP_ mr_mip->w1,sm,mr_mip->w1); #endif if (sr==0) { copy(mr_mip->w2,mr_mip->w1); break; } zero(mr_mip->w1); mr_mip->w1->len=1; mr_mip->w1->w[0]=sr; while ((sr=MR_REMAIN(mr_mip->w2->w[0],mr_mip->w1->w[0]))!=0) mr_mip->w2->w[0]=mr_mip->w1->w[0],mr_mip->w1->w[0]=sr; break; } a=1; b=0; c=0; d=1; m=mr_mip->w1->w[n-1]+1; if (mr_mip->base==0) { #ifndef MR_NOFULLWIDTH if (m==0) { u=mr_mip->w1->w[n-1]; v=mr_mip->w2->w[n-1]; } else { u=muldvm(mr_mip->w1->w[n-1],mr_mip->w1->w[n-2],m,&sr); v=muldvm(mr_mip->w2->w[n-1],mr_mip->w2->w[n-2],m,&sr); } #endif } else { u=muldiv(mr_mip->w1->w[n-1],mr_mip->base,mr_mip->w1->w[n-2],m,&sr); v=muldiv(mr_mip->w2->w[n-1],mr_mip->base,mr_mip->w2->w[n-2],m,&sr); } forever { /* work only with most significant piece */ if (((v+c)==0) || ((v+d)==0)) break; lq=MR_DIV((u+a),(v+c)); if (lq!=MR_DIV((u+b),(v+d))) break; if (lq>=(mr_small)(MR_TOOBIG/mr_abs(d))) break; q=(int)lq; r=a-q*c; a=c; c=r; r=b-q*d; b=d; d=r; lr=u-lq*v; u=v; v=lr; } } copy(mr_mip->w1,z); MR_OUT return (size(mr_mip->w1)); }
static int euclid(_MIPD_ big x,int num) { /* outputs next c.f. quotient from gcd(w5,w6) */ mr_small sr,m; #ifdef MR_FP mr_small dres; #endif mr_small lr,lq; big t; #ifndef MR_GENERIC_MT miracl *mr_mip=get_mip(); #endif if (num==0) { mr_mip->oldn=(-1); mr_mip->carryon=FALSE; mr_mip->last=FALSE; if (compare(mr_mip->w6,mr_mip->w5)>0) { /* ensure w5>w6 */ t=mr_mip->w5,mr_mip->w5=mr_mip->w6,mr_mip->w6=t; return (mr_mip->q=0); } } else if (num==mr_mip->oldn || mr_mip->q<0) return mr_mip->q; mr_mip->oldn=num; if (mr_mip->carryon) goto middle; start: if (size(mr_mip->w6)==0) return (mr_mip->q=(-1)); mr_mip->ndig=(int)mr_mip->w5->len; mr_mip->carryon=TRUE; mr_mip->a=1; mr_mip->b=0; mr_mip->c=0; mr_mip->d=1; if (mr_mip->ndig==1) { mr_mip->last=TRUE; mr_mip->u=mr_mip->w5->w[0]; mr_mip->v=mr_mip->w6->w[0]; } else { m=mr_mip->w5->w[mr_mip->ndig-1]+1; if (mr_mip->base==0) { #ifndef MR_NOFULLWIDTH if (m==0) { mr_mip->u=mr_mip->w5->w[mr_mip->ndig-1]; mr_mip->v=mr_mip->w6->w[mr_mip->ndig-1]; } else { mr_mip->u=muldvm(mr_mip->w5->w[mr_mip->ndig-1],mr_mip->w5->w[mr_mip->ndig-2],m,&sr); mr_mip->v=muldvm(mr_mip->w6->w[mr_mip->ndig-1],mr_mip->w6->w[mr_mip->ndig-2],m,&sr); } #endif } else { mr_mip->u=muldiv(mr_mip->w5->w[mr_mip->ndig-1],mr_mip->base,mr_mip->w5->w[mr_mip->ndig-2],m,&sr); mr_mip->v=muldiv(mr_mip->w6->w[mr_mip->ndig-1],mr_mip->base,mr_mip->w6->w[mr_mip->ndig-2],m,&sr); } } mr_mip->ku=mr_mip->u; mr_mip->kv=mr_mip->v; middle: forever { /* work only with most significant piece */ if (mr_mip->last) { if (mr_mip->v==0) return (mr_mip->q=(-1)); lq=MR_DIV(mr_mip->u,mr_mip->v); } else { if (((mr_mip->v+mr_mip->c)==0) || ((mr_mip->v+mr_mip->d)==0)) break; lq=MR_DIV((mr_mip->u+mr_mip->a),(mr_mip->v+mr_mip->c)); if (lq!=MR_DIV((mr_mip->u+mr_mip->b),(mr_mip->v+mr_mip->d))) break; } if (lq>=(mr_small)(MR_TOOBIG/mr_abs(mr_mip->d))) break; mr_mip->q=(int)lq; mr_mip->r=mr_mip->a-mr_mip->q*mr_mip->c; mr_mip->a=mr_mip->c; mr_mip->c=mr_mip->r; mr_mip->r=mr_mip->b-mr_mip->q*mr_mip->d; mr_mip->b=mr_mip->d; mr_mip->d=mr_mip->r; lr=mr_mip->u-lq*mr_mip->v; mr_mip->u=mr_mip->v; mr_mip->v=lr; return mr_mip->q; } mr_mip->carryon=FALSE; if (mr_mip->b==0) { /* update w5 and w6 */ mr_mip->check=OFF; divide(_MIPP_ mr_mip->w5,mr_mip->w6,mr_mip->w7); mr_mip->check=ON; if (mr_lent(mr_mip->w7)>mr_mip->nib) return (mr_mip->q=(-2)); t=mr_mip->w5,mr_mip->w5=mr_mip->w6,mr_mip->w6=t; /* swap(w5,w6) */ copy(mr_mip->w7,x); return (mr_mip->q=size(x)); } else { mr_mip->check=OFF; premult(_MIPP_ mr_mip->w5,mr_mip->c,mr_mip->w7); premult(_MIPP_ mr_mip->w5,mr_mip->a,mr_mip->w5); premult(_MIPP_ mr_mip->w6,mr_mip->b,mr_mip->w0); premult(_MIPP_ mr_mip->w6,mr_mip->d,mr_mip->w6); add(_MIPP_ mr_mip->w5,mr_mip->w0,mr_mip->w5); add(_MIPP_ mr_mip->w6,mr_mip->w7,mr_mip->w6); mr_mip->check=ON; } goto start; }
/** * \brief Find maximum corner speed between two moves. * \details Find out how fast we can move around around a corner without * exceeding the expected jerk. Worst case this speed is zero, which means a * full stop between both moves. Best case it's the lower of the maximum speeds. * * This function is expected to be called from within dda_create(). * * \param [in] prev is the DDA structure of the move previous to the current one. * \param [in] current is the DDA structure of the move currently created. * * \return dda->crossF */ void dda_find_crossing_speed(DDA *prev, DDA *current) { uint32_t F, dv, speed_factor, max_speed_factor; axes_int32_t prevF, currF; enum axis_e i; // Bail out if there's nothing to join (e.g. G1 F1500). if ( ! prev || prev->nullmove) return; // We always look at the smaller of both combined speeds, // else we'd interpret intended speed changes as jerk. F = prev->endpoint.F; if (current->endpoint.F < F) F = current->endpoint.F; if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("Distance: %lu, then %lu\n"), prev->distance, current->distance); // Find individual axis speeds. // TODO: this is eight expensive muldiv()s. It should be possible to store // currF as prevF for the next calculation somehow, to save 4 of // these 8 muldiv()s. This would also allow to get rid of // dda->delta_um[] and using delta_um[] from dda_create() instead. // Caveat: bail out condition above and some other non-continuous // situations might need some extra code for handling. for (i = X; i < AXIS_COUNT; i++) { prevF[i] = muldiv(prev->delta_um[i], F, prev->distance); currF[i] = muldiv(current->delta_um[i], F, current->distance); } if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("prevF: %ld %ld %ld %ld\ncurrF: %ld %ld %ld %ld\n"), prevF[X], prevF[Y], prevF[Z], prevF[E], currF[X], currF[Y], currF[Z], currF[E]); /** * What we want is (for each axis): * * delta velocity = dv = |v1 - v2| < max_jerk * * In case this isn't satisfied, we can slow down by some factor x until * the equitation is satisfied: * * x * |v1 - v2| < max_jerk * * Now computation is pretty straightforward: * * max_jerk * x = ----------- * |v1 - v2| * * if x > 1: continue full speed * if x < 1: v = v_max * x * * See also: https://github.com/Traumflug/Teacup_Firmware/issues/45 */ max_speed_factor = (uint32_t)2 << 8; for (i = X; i < AXIS_COUNT; i++) { dv = currF[i] > prevF[i] ? currF[i] - prevF[i] : prevF[i] - currF[i]; if (dv) { speed_factor = ((uint32_t)pgm_read_dword(&maximum_jerk_P[i]) << 8) / dv; if (speed_factor < max_speed_factor) max_speed_factor = speed_factor; if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("%c: dv %lu of %lu factor %lu of %lu\n"), 'X' + i, dv, (uint32_t)pgm_read_dword(&maximum_jerk_P[i]), speed_factor, (uint32_t)1 << 8); } } if (max_speed_factor >= ((uint32_t)1 << 8)) current->crossF = F; else current->crossF = (F * max_speed_factor) >> 8; if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("Cross speed reduction from %lu to %lu\n"), F, current->crossF); return; }
/** * \brief Join 2 moves by removing the full stop between them, where possible. * \details To join the moves, the deceleration ramp of the previous move and * the acceleration ramp of the current move are shortened, resulting in a * non-zero speed at that point. The target speed at the corner is already to * be found in dda->crossF. See dda_find_corner_speed(). * * Ideally, both ramps can be reduced to actually have Fcorner at the corner, * but the surrounding movements might no be long enough to achieve this speed. * Analysing both moves to find the best result is done here. * * TODO: to achieve better results with short moves (move distance < both ramps), * this function should be able to enhance the corner speed on repeated * calls when reverse-stepping through the movement queue. * * \param [in] prev is the DDA structure of the move previous to the current one. * \param [in] current is the DDA structure of the move currently created. * * Premise: the 'current' move is not dispatched in the queue: it should remain * constant while this function is running. * * Note: the planner always makes sure the movement can be stopped within the * last move (= 'current'); as a result a lot of small moves will still limit the speed. */ void dda_join_moves(DDA *prev, DDA *current) { // Calculating the look-ahead settings can take a while; before modifying // the previous move, we need to locally store any values and write them // when we are done (and the previous move is not already active). uint32_t prev_F, prev_F_in_steps, prev_F_start_in_steps, prev_F_end_in_steps; uint32_t prev_rampup, prev_rampdown, prev_total_steps; uint32_t crossF, crossF_in_steps; uint8_t prev_id; // Similarly, we only want to modify the current move if we have the results of the calculations; // until then, we do not want to touch the current move settings. // Note: we assume 'current' will not be dispatched while this function runs, so we do not to // back up the move settings: they will remain constant. uint32_t this_F, this_F_in_steps, this_F_start_in_steps, this_rampup, this_rampdown, this_total_steps; uint8_t this_id; static uint32_t la_cnt = 0; // Counter: how many moves did we join? #ifdef LOOKAHEAD_DEBUG static uint32_t moveno = 0; // Debug counter to number the moves - helps while debugging moveno++; #endif // Bail out if there's nothing to join (e.g. G1 F1500). if ( ! prev || prev->nullmove || current->crossF == 0) return; // Show the proposed crossing speed - this might get adjusted below. if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("Initial crossing speed: %lu\n"), current->crossF); // Make sure we have 2 moves and the previous move is not already active if (prev->live == 0) { // Perform an atomic copy to preserve volatile parameters during the calculations ATOMIC_START prev_id = prev->id; prev_F = prev->endpoint.F; prev_F_start_in_steps = prev->start_steps; prev_F_end_in_steps = prev->end_steps; prev_rampup = prev->rampup_steps; prev_rampdown = prev->rampdown_steps; prev_total_steps = prev->total_steps; crossF = current->crossF; this_id = current->id; this_F = current->endpoint.F; this_total_steps = current->total_steps; ATOMIC_END // Here we have to distinguish between feedrate along the movement // direction and feedrate of the fast axis. They can differ by a factor // of 2. // Along direction: F, crossF. // Along fast axis already: start_steps, end_steps. // // All calculations here are done along the fast axis, so recalculate // F and crossF to match this, too. prev_F = muldiv(prev->fast_um, prev_F, prev->distance); this_F = muldiv(current->fast_um, current->endpoint.F, current->distance); crossF = muldiv(current->fast_um, crossF, current->distance); // TODO: calculate the steps from the fastest axis and not from X. prev_F_in_steps = ACCELERATE_RAMP_LEN(prev_F); this_F_in_steps = ACCELERATE_RAMP_LEN(this_F); crossF_in_steps = ACCELERATE_RAMP_LEN(crossF); // Show the proposed crossing speed - this might get adjusted below if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("Initial crossing speed: %lu\n"), crossF_in_steps); // Compute the maximum speed we can reach for crossing. crossF_in_steps = MIN(crossF_in_steps, this_total_steps); crossF_in_steps = MIN(crossF_in_steps, prev_total_steps + prev_F_start_in_steps); if (crossF_in_steps == 0) return; // Build ramps for previous move. if (crossF_in_steps == prev_F_in_steps) { prev_rampup = prev_F_in_steps - prev_F_start_in_steps; prev_rampdown = 0; } else if (crossF_in_steps < prev_F_start_in_steps) { uint32_t extra, limit; prev_rampup = 0; prev_rampdown = prev_F_start_in_steps - crossF_in_steps; extra = (prev_total_steps - prev_rampdown) >> 1; limit = prev_F_in_steps - prev_F_start_in_steps; extra = MIN(extra, limit); prev_rampup += extra; prev_rampdown += extra; }
main() { char buff[100]; int cn, r, k, t, dt, lp, x, rx, ry; int oldx, oldy, newx, newy; int offx, offy; Point jstring(); char *getstring(); Point p; int nonstop = NONSTOP; local(); request(MOUSE); /* random number seed is derived from position of dmd layer */ srand(mouse.xy.x); request(KBD); for ( ;; ) { lp = dt = 0; if ( nonstop == 0 ) { /* ask for lp parameter */ jmoveto(Pt(0,0)); p = jstring("loops="); lp = getnum(p); jmoveto(Pt(0,0)); jstring("loops="); } if ( lp < 0 ) exit(); if ( lp == 0 ) lp = rand() % 31 + 1; if ( nonstop == 0 ) { /* ask for dt parameter */ jmoveto(Pt(0,0)); p = jstring("delta="); dt = getnum(p); jmoveto(Pt(0,0)); jstring("delta="); } if ( dt <= 0 ) dt = rand() % 358 + 1; /* clear screen */ jrectf(Jrect,F_CLR); t=0; oldx = offx = XMAX / 2; oldy = offy = YMAX / 2; cn = 1; /* draw rose */ do { t=(t+dt)%360; x=(lp*t)%360; r = Isin(x); rx=muldiv(r,XMAX-1,1024); ry=muldiv(r,YMAX-1,1024); newx = offx + muldiv(rx,Icos(t),1024) / 2; newy = offy + muldiv(ry,Isin(t),1024) / 2; jsegment(Pt(oldx,oldy),Pt(newx,newy),F_STORE); oldx=newx; oldy=newy; /* give up the CPU every 10 times around */ if ( cn++ > 10 ) { cn = 0; sleep(4); } } while ( t != 0 && (k=kbdchar()) != 'q' ) ; if ( nonstop == 1 ) { /* in nonstop mode, any key aborts */ if ( k != -1 ) exit(); /* sleep 2 seconds between random patterns */ sleep(120); } } }
void CubeFace::GetFaceCoordinates(unsigned char nFace, const VK::ivec3 &v, int &x, int &y) { // The vector passed in may not be in the specified face. // If not, the coordinates within nFace closest to v are returned. // (This helps find the shortest distance from a point to a node in the quad-tree) switch(nFace) { case RightFace: if(v.x < 0) { // If v is in the left, force the coordinates to the nearest corner of this face. x = v.z > 0 ? -MaxCoord : MaxCoord; y = v.y > 0 ? -MaxCoord : MaxCoord; } else { x = v.x <= VK::Math::Abs(v.z) ? (v.z > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.z, MaxCoord, v.x); y = v.x <= VK::Math::Abs(v.y) ? (v.y > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.y, MaxCoord, v.x); } break; case LeftFace: if(v.x > 0) { // If v is in the right, force the coordinates to the nearest corner of this face. x = v.z > 0 ? MaxCoord : -MaxCoord; y = v.y > 0 ? -MaxCoord : MaxCoord; } else { x = -v.x <= VK::Math::Abs(v.z) ? (v.z > 0 ? MaxCoord : -MaxCoord) : muldiv(v.z, MaxCoord, -v.x); y = -v.x <= VK::Math::Abs(v.y) ? (v.y > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.y, MaxCoord, -v.x); } break; case TopFace: if(v.y < 0) { // If v is in the bottom, force the coordinates to the nearest corner of this face. x = v.x > 0 ? MaxCoord : -MaxCoord; y = v.z > 0 ? MaxCoord : -MaxCoord; } else { x = v.y <= VK::Math::Abs(v.x) ? (v.x > 0 ? MaxCoord : -MaxCoord) : muldiv(v.x, MaxCoord, v.y); y = v.y <= VK::Math::Abs(v.z) ? (v.z > 0 ? MaxCoord : -MaxCoord) : muldiv(v.z, MaxCoord, v.y); } break; case BottomFace: if(v.y > 0) { // If v is in the top, force the coordinates to the nearest corner of this face. x = v.x > 0 ? MaxCoord : -MaxCoord; y = v.z > 0 ? -MaxCoord : MaxCoord; } else { x = -v.y <= VK::Math::Abs(v.x) ? (v.x > 0 ? MaxCoord : -MaxCoord) : muldiv(v.x, MaxCoord, -v.y); y = -v.y <= VK::Math::Abs(v.z) ? (v.z > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.z, MaxCoord, -v.y); } break; case FrontFace: if(v.z < 0) { // If v is in the back, force the coordinates to the nearest corner of this face. x = v.x > 0 ? MaxCoord : -MaxCoord; y = v.y > 0 ? -MaxCoord : MaxCoord; } else { x = v.z <= VK::Math::Abs(v.x) ? (v.x > 0 ? MaxCoord : -MaxCoord) : muldiv(v.x, MaxCoord, v.z); y = v.z <= VK::Math::Abs(v.y) ? (v.y > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.y, MaxCoord, v.z); } break; case BackFace: if(v.z > 0) { // If v is in the front, force the coordinates to the nearest corner of this face. x = v.x > 0 ? -MaxCoord : MaxCoord; y = v.y > 0 ? -MaxCoord : MaxCoord; } else { x = -v.z <= VK::Math::Abs(v.x) ? (v.x > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.x, MaxCoord, -v.z); y = -v.z <= VK::Math::Abs(v.y) ? (v.y > 0 ? -MaxCoord : MaxCoord) : muldiv(-v.y, MaxCoord, -v.z); } break; } x = (x + MaxCoord) >> 1; y = (y + MaxCoord) >> 1; }
{ if(la&1) { q += qn; r += rn; if(r>=lc) { q++; r -= lc; } } la >>= 1; /* la = la & 0x7FFFFFFF;*/ qn <<= 1; rn <<= 1; if(rn>=lc) {qn++; rn -= lc; } } result2 = rneg ? -r : r; return qneg ? -q : q; } void try(INT32 a, INT32 b, INT32 c) { INT32 x = muldiv(a, b, c), y = muldiva(a, b, c); printf("muldiv (%8x, %8x, %8x) = %8x, remainder %8x\n", a, b, c, x, result2); printf("muldiva(%8x, %8x, %8x) = %8x, remainder %8x\n\n", a, b, c, y, result2a); } int main() { int i,j,k; INT32 w = 0x80000000; try(4,5,6); try(-5,6,7); try(-5,-6,7); try(-5,6,-7); try(5,-6,7);
BCPLWORD dosys(register BCPLWORD *p, register BCPLWORD *g) { register BCPLWORD i; /*PRINTFD("dosys(%" FormD ", ", (BCPLWORD)p); */ /*PRINTFD("%" FormD, g); */ /*PINTFD(") P3=%" FormD " ", p[3]); */ /*PRINTFD("P4=%" FormD "\n", p[4]); */ switch((int)(p[3])) { default: printf("\nBad sys %ld\n", (long)p[3]); return p[3]; /* case Sys_setcount: set count -- done in cinterp ** case Sys_quit: return from interpreter -- done in cinterp ** case Sys_rti: sys(Sys_rti, regs) -- done in cinterp Cintpos ** case Sys_saveregs: sys(Sys_saveregs, regs) -- done in cinterp Cintpos ** case Sys_setst: sys(Sys_setst, st) -- done in cinterp Cintpos */ case Sys_tracing: /* sys(Sys_tracing, b) */ tracing = p[4]; return 0; /* case Sys_watch: sys(Sys_watch, addr) -- done in cinterp */ /* case Sys_tally: // sys(Sys_tally, flag) if(p[4]) { tallylim = tallyupb; for(i=1; i<=tallylim; i++) tallyv[i] = 0; } else { tallylim = 0; } return 0; case Sys_interpret: // call interpreter (recursively) { BCPLWORD regsv = p[4]; if(W[regsv+7]>=0 || slowflag) return interpret(regsv, W); return CINTASM (regsv, W); } */ case Sys_sardch: { BCPLWORD ch; /*printf("parmp=%d parms[0]=%d\n", parmp, parms[0]); */ if(parmp<=parms[0]) { /* Added MR 10/04/06 */ /* Read the command arguments (without echo) first. */ /*printf("sardch: parmp=%d parms[0]=%d\n", parmp, parms[0]); */ /*printf("sardch: returning %d\n", parms[parmp]); */ return parms[parmp++]; } ch = Readch(); if (ttyinp) { /* echo tty input only */ if (ch>=0) putchar((char)ch); if(ch==13) { ch = 10; putchar(10); } fflush(stdout); } return ch; } case Sys_sawrch: if(p[4] == 10) putchar(13); putchar((char)p[4]); fflush(stdout); return 0; case Sys_read: /* bytesread := sys(Sys_read, fp, buf, bytecount) */ { FILE *fp = findfp(p[4]); char *bbuf = (char *)(p[5]<<B2Wsh); BCPLWORD len = p[6]; len = fread(bbuf, (size_t)1, (size_t)len, fp); return len; } case Sys_write: { FILE *fp = findfp(p[4]); char *bbuf = (char *)(p[5]<<B2Wsh); BCPLWORD len = p[6]; len = WD fwrite(bbuf, (size_t)1, (size_t)len, fp); fflush(fp); return len; } case Sys_openread: { char *name = b2c_str(p[4], chbuf1); FILEPT fp; fp = pathinput(name, /* Filename */ b2c_str(p[5], chbuf2)); /* Environment variable */ if(fp==0) return 0L; return newfno(fp); } case Sys_openwrite: { char *name = b2c_str(p[4], chbuf1); FILEPT fp; fp = fopen(osfname(name, chbuf4), "wb"); if(fp==0) return 0L; return newfno(fp); } case Sys_openappend: { char *name = b2c_str(p[4], chbuf1); FILEPT fp; fp = fopen(osfname(name, chbuf4), "ab"); if(fp==0) return 0L; return newfno(fp); } case Sys_openreadwrite: { char *name = b2c_str(p[4], chbuf1); FILEPT fp; fp = fopen(osfname(name, chbuf4), "rb+"); if(fp==0) fp = fopen(name, "wb+"); if(fp==0) return 0L; return newfno(fp); } case Sys_close: { BCPLWORD res = fclose(findfp(p[4])); freefno(p[4]); return res==0 ? -1 : 0; /* res==0 means success */ } case Sys_deletefile: { char *name = b2c_str(p[4], chbuf1); FILEPT fp; name = osfname(name, chbuf4); #ifdef VMSNAMES { /* Append ';*' to name */ int len = 0; while (name[len]) len++; name[len++] = ';'; name[len++] = '*'; name[len] = 0; } #endif return ! REMOVE(name); } case Sys_renamefile: { char *name1 = b2c_str(p[4], chbuf1); char *name2 = b2c_str(p[5], chbuf2); int len = 0; name1 = osfname(name1, chbuf3); name2 = osfname(name2, chbuf4); #ifdef VMSNAMES { /* Append ';*' to name2 */ len = 0; while (name2[len]) len++; name2[len] = ';'; name2[len+1] = '*'; name2[len+2] = 0; } #endif REMOVE(name2); #ifdef VMSNAMES name2[len] = 0; #endif return ! rename(name1, name2); } case Sys_getvec: return ((BCPLWORD)(malloc((1+p[4])<<B2Wsh)))>>B2Wsh; case Sys_freevec: free((void *)(p[4]<<B2Wsh)); return -1; /* case Sys_loadseg: return loadseg(b2c_str(p[4], chbuf1)); case Sys_globin: return globin(p[4], g); case Sys_unloadseg: unloadseg(p[4]); return 0; */ case Sys_muldiv: //printf("dosys: calling muldiv(%d, %d, %d)\n", p[4], p[5], p[6]); { BCPLWORD res = muldiv(p[4], p[5], p[6]); //printf("res=%d result2=%d\n", res, result2); globbase[Gn_result2] = result2; return res; } case Sys_intflag: return intflag() ? -1L : 0L; /* case Sys_setraster: return setraster(p[4], p[5]); */ case Sys_cputime: /* Return CPU time in milliseconds */ return muldiv(clock(), 1000, TICKS_PER_SEC); #ifndef forWinCE case Sys_filemodtime: /* sys(Sys_filemodtime, filename, datv) Set the elements of datv to represent the date and time of the last modification of the given file, returning TRUE if successful and FALSE otherwise. datv!0 is the number of days since 1 January 1970, datv!1 is the number of milli-seconds since midnight and datv!2=-1 indicating that the new date and time format is being used. If the file does not exist or there is an error then FALSE is returned and the elements of datv are set to 0, 0 and -1, respectively. */ { struct stat buf; BCPLWORD days, secs, msecs; char *name = b2c_str(p[4], chbuf1); BCPLWORD *datestamp = (BCPLWORD *)(p[5]<<B2Wsh); if (stat(osfname(name, chbuf4), &buf)) { datestamp[0] = 0; datestamp[1] = 0; datestamp[2] = -1; return 0; } secs = buf.st_mtime; // nsecs = buf.st_mtimensec; // nano second time, if poss days = secs / (24*60*60); msecs = (secs % (24*60*60)) * 1000; datestamp[0] = days; datestamp[1] = msecs; datestamp[2] = -1; // New dat format //printf("filemodtime: name=%s days=%" FormD " msecs=%" FormD "\n", // name, days, msecs); return -1; } #endif case Sys_setprefix: /* Set the file name prefix string */ { BCPLWORD str = p[4]; char *fp = (char*)(str<<B2Wsh); char *tp = prefixbp; int i, len=*fp; if(len>63) return 0; for (i=0; i<=len; i++) *tp++ = *fp++; return prefixstr; } case Sys_getprefix: /* Return the file name prefix string */ return prefixstr; case Sys_graphics: /* Perform an operation on the graphics window */ return sysGraphics(p); case 35: /* Return TRUE if no keyboard character is available */ #ifdef forWinCE return chBufEmpty() ? -1 : 0; #else return -1; #endif case 36: return 0; /* Spare */ case 37: return 0; /* Spare */ case Sys_seek: /* res := sys(Sys_seek, fd, pos) */ { FILEPT fp = findfp(p[4]); BCPLWORD pos = p[5]; BCPLWORD res = fseek(fp, pos, SEEK_SET); /*printf("fseek => res=%d errno=%d\n", res, errno); */ /*g[Gn_result2] = errno; */ return res==0 ? -1 : 0; /* res=0 succ, res=-1 error */ } case Sys_tell: /* pos := sys(Sys_tell,fd) */ { FILE *fp = findfp(p[4]); BCPLWORD pos = ftell(fp); /*g[Gn_result2] = errno; */ return pos; /* >=0 succ, -1=error */ } case Sys_waitirq: /* Wait for irq */ /* pthread_mutex_lock ( &irq_mutex); pthread_cond_wait (&irq_cv, &irq_mutex); pthread_mutex_unlock( &irq_mutex); */ return 0; case Sys_lockirq: /* Stop all devices from modifying */ /* packets or generating interrupts */ /* pthread_mutex_lock(&irq_mutex); */ return 0; case Sys_unlockirq: /* Allow devices to modify packets */ /* and generate interrupts */ /* pthread_mutex_unlock(&irq_mutex); */ return 0; case Sys_devcom: /* res := sys(Sys_devcom, dcb, com, arg) */ return 0; /*devcommand(W[p+4], W[p+5], W[p+6]); */ case Sys_datstamp: /* res := sys(Sys_datstamp, v) */ // Set v!0 = days since 1 January 1970 // v!1 = msecs since midnight // v!2 = ticks =-1 for new dat format // Return -1 if successful return timestamp((BCPLWORD*)(p[4])); case Sys_filesize: /* res := sys(Sys_filesize, fd) */ { FILEPT fp = findfp(p[4]); long pos = ftell(fp); BCPLWORD rc = fseek(fp, 0, SEEK_END); BCPLWORD size = ftell(fp); rc = fseek(fp, pos, SEEK_SET); if (rc) size = -1; return size; /* >=0 succ, -1=error */ } case Sys_getsysval: /* res := sys(Sys_getsysval, addr) */ { BCPLWORD *addr = (BCPLWORD*)p[4]; return *addr; } case Sys_putsysval: /* res := sys(Sys_putsysval, addr, val) */ { BCPLWORD *addr = (BCPLWORD*)p[4]; *addr = p[5]; return 0; } case Sys_shellcom: /* res := sys(Sys_shellcom, comstr) */ { char *comstr = (char*)(p[4]<<2); int i; char com[256]; int len = strlen(comstr); for(i=0; i<len; i++) com[i] = comstr[i+1]; com[len] = 0; /* printf("\ndosys: calling shell command %s\n", com); */ return system(com); } case Sys_getpid: /* res := sys(Sys_getpid) */ return getpid(); case Sys_dumpmem: /* sys(Sys_dumpmem, context) */ printf("\nCintpos memory not dumped to DUMP.mem\n"); return 0; case Sys_callnative: { /* Call native code. */ int(*rasmfn)(void) = (int(*)(void))&p[4]; return rasmfn(); } case Sys_platform: { /* Return platform code, 0 if unknown */ BCPLWORD res = 0; #ifdef forMAC res = 1; #endif #ifdef forMIPS res = 2; #endif #ifdef forSGI res = 3; #endif #ifdef forARM res = 4; #endif #ifdef forLINUX res = 5; #endif #ifdef forLINUXamd64 res = 6; #endif #ifdef forCYGWIN32 res = 7; #endif #ifdef forLINUXPPC res = 8; #endif #ifdef forSUN4 res = 9; #endif #ifdef forSPARC res = 10; #endif #ifdef forALPHA res = 11; #endif #ifdef forMSDOS res = 12; #endif #ifdef forOS2 res = 13; #endif #ifdef forSHwinCE res = 14; #endif #ifdef forMIPSwinCE res = 15; #endif return res; } case Sys_inc: /* newval := sys(Sys_inc, ptr, amount) */ { /* !ptr := !ptr + amount; RESULTIS !ptr */ return 0; /**p[4] += p[5];*/ } case Sys_buttons: /* Return bit pattern of buttons currently pressed on the GP2X */ #ifdef forGP2X { unsigned long buttons = 0; int fd = open("/dev/GPIO", O_RDWR | O_NDELAY); if (fd<0) return -1; if (read(fd, &buttons, 4) != 4) return -2; close(fd); return (BCPLWORD)buttons; } #else return -3; #endif case Sys_delay: /* sys(Sys_delay, msecs) */ { unsigned int msecs = (unsigned int)p[4]; msecdelay(msecs); return 0; } case Sys_sound: /* res := sys(Sys_sound, fno, a1, a2,...) */ #ifdef SOUND return soundfn(&p[4], &g[0]); #else return 0; #endif case Sys_sdl: /* res := sys(Sys_sdl, fno, a1, a2,...) */ #ifdef SDLavail return sdlfn(&((BCPLWORD*)p)[4], &((BCPLWORD*)g)[0], 0/*W*/); #else return 0; #endif case Sys_callc: /* res := sys(Sys_callc, fno, a1, a2,...) */ #ifdef CALLC /* printf("dosys: sys(Sys_callc, %" FormD ", %" FormD ", %" FormD", ...)\n", W[p+4], W[p+5], W[p+6]); */ return 0;//callc(&p[4], &g[0]); #else return -1; #endif case Sys_trpush: /* sys(Sys_trpush, val) */ trpush(p[4]); return 0; case Sys_settrcount: /* res := sys(Sys_settrcount, count) */ return settrcount(p[4]); case Sys_gettrval: /* res := sys(Sys_gettrval, count) */ return gettrval(p[4]); case Sys_flt: /* res := sys(Sys_flt, op, a, b)) */ { BCPLWORD res = doflt(p[4], p[5], p[6], p[7]); globbase[Gn_result2] = result2; //g[Gn_result2] = result2; //if(W[p+4]==35) //printf("sys_flt: op=%d res=%08" FormX " result2=%08" FormX "\n", // W[p+4], (UBCPLWORD)res, (UBCPLWORD)result2); return res; } case Sys_pollsardch: /* res := sys(Sys_pollsardch) */ { // Return a character if available otherwise pollch (=-3) return pollReadch(); } case Sys_incdcount: /* res := sys(Sys_incdcount, n) */ return incdcount(p[4]); //#ifndef forWinCE case 135: { /* Return system date and time in VEC 5 */ time_t clk = time(0); struct tm *now = gmtime(&clk); BCPLWORD *arg = PT(p[4] << B2Wsh); arg[0] = now->tm_year+1900; arg[1] = now->tm_mon+1; arg[2] = now->tm_mday; arg[3] = now->tm_hour; arg[4] = now->tm_min; arg[5] = now->tm_sec; return 0; } case 136: /* Return current directory in VEC 1 + 256/bytesperword */ { char *res = getcwd(chbuf1, 256); c2b_str(chbuf1, p[4]); return 0; } case 137: return (BCPLWORD)parms >> B2Wsh; } // This is unreadchable // return 0; }
int xgcd(_MIPD_ big x,big y,big xd,big yd,big z) { /* greatest common divisor by Euclids method * * extended to also calculate xd and yd where * * z = x.xd + y.yd = gcd(x,y) * * if xd, yd not distinct, only xd calculated * * z only returned if distinct from xd and yd * * xd will always be positive, yd negative */ int s,n,iter; mr_small r,a,b,c,d; mr_small q,m,sr; #ifdef MR_FP mr_small dres; #endif #ifdef mr_dltype union doubleword uu,vv; mr_large u,v,lr; #else mr_small u,v,lr; #endif BOOL last,dplus=TRUE; big t; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return 0; MR_IN(30) #ifdef MR_COUNT_OPS fpx++; #endif copy(x,mr_mip->w1); copy(y,mr_mip->w2); s=exsign(mr_mip->w1); insign(PLUS,mr_mip->w1); insign(PLUS,mr_mip->w2); convert(_MIPP_ 1,mr_mip->w3); zero(mr_mip->w4); last=FALSE; a=b=c=d=0; iter=0; while (size(mr_mip->w2)!=0) { if (b==0) { /* update mr_mip->w1 and mr_mip->w2 */ divide(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w5); t=mr_mip->w1,mr_mip->w1=mr_mip->w2,mr_mip->w2=t; /* swap(mr_mip->w1,mr_mip->w2) */ multiply(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w0); add(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3); t=mr_mip->w3,mr_mip->w3=mr_mip->w4,mr_mip->w4=t; /* swap(xd,yd) */ iter++; } else { /* printf("a= %I64u b= %I64u c= %I64u d= %I64u \n",a,b,c,d); */ mr_pmul(_MIPP_ mr_mip->w1,c,mr_mip->w5); /* c*w1 */ mr_pmul(_MIPP_ mr_mip->w1,a,mr_mip->w1); /* a*w1 */ mr_pmul(_MIPP_ mr_mip->w2,b,mr_mip->w0); /* b*w2 */ mr_pmul(_MIPP_ mr_mip->w2,d,mr_mip->w2); /* d*w2 */ if (!dplus) { mr_psub(_MIPP_ mr_mip->w0,mr_mip->w1,mr_mip->w1); /* b*w2-a*w1 */ mr_psub(_MIPP_ mr_mip->w5,mr_mip->w2,mr_mip->w2); /* c*w1-d*w2 */ } else { mr_psub(_MIPP_ mr_mip->w1,mr_mip->w0,mr_mip->w1); /* a*w1-b*w2 */ mr_psub(_MIPP_ mr_mip->w2,mr_mip->w5,mr_mip->w2); /* d*w2-c*w1 */ } mr_pmul(_MIPP_ mr_mip->w3,c,mr_mip->w5); mr_pmul(_MIPP_ mr_mip->w3,a,mr_mip->w3); mr_pmul(_MIPP_ mr_mip->w4,b,mr_mip->w0); mr_pmul(_MIPP_ mr_mip->w4,d,mr_mip->w4); if (a==0) copy(mr_mip->w0,mr_mip->w3); else mr_padd(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3); mr_padd(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w4); } if (mr_mip->ERNUM || size(mr_mip->w2)==0) break; n=(int)mr_mip->w1->len; if (n==1) { last=TRUE; u=mr_mip->w1->w[0]; v=mr_mip->w2->w[0]; } else { m=mr_mip->w1->w[n-1]+1; #ifndef MR_SIMPLE_BASE if (mr_mip->base==0) { #endif #ifndef MR_NOFULLWIDTH #ifdef mr_dltype /* use double length type if available */ if (n>2 && m!=0) { /* squeeze out as much significance as possible */ uu.h[MR_TOP]=muldvm(mr_mip->w1->w[n-1],mr_mip->w1->w[n-2],m,&sr); uu.h[MR_BOT]=muldvm(sr,mr_mip->w1->w[n-3],m,&sr); vv.h[MR_TOP]=muldvm(mr_mip->w2->w[n-1],mr_mip->w2->w[n-2],m,&sr); vv.h[MR_BOT]=muldvm(sr,mr_mip->w2->w[n-3],m,&sr); } else { uu.h[MR_TOP]=mr_mip->w1->w[n-1]; uu.h[MR_BOT]=mr_mip->w1->w[n-2]; vv.h[MR_TOP]=mr_mip->w2->w[n-1]; vv.h[MR_BOT]=mr_mip->w2->w[n-2]; if (n==2) last=TRUE; } u=uu.d; v=vv.d; #else if (m==0) { u=mr_mip->w1->w[n-1]; v=mr_mip->w2->w[n-1]; } else { u=muldvm(mr_mip->w1->w[n-1],mr_mip->w1->w[n-2],m,&sr); v=muldvm(mr_mip->w2->w[n-1],mr_mip->w2->w[n-2],m,&sr); } #endif #endif #ifndef MR_SIMPLE_BASE } else { #ifdef mr_dltype if (n>2) { /* squeeze out as much significance as possible */ u=muldiv(mr_mip->w1->w[n-1],mr_mip->base,mr_mip->w1->w[n-2],m,&sr); u=u*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w1->w[n-3],m,&sr); v=muldiv(mr_mip->w2->w[n-1],mr_mip->base,mr_mip->w2->w[n-2],m,&sr); v=v*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w2->w[n-3],m,&sr); } else { u=(mr_large)mr_mip->base*mr_mip->w1->w[n-1]+mr_mip->w1->w[n-2]; v=(mr_large)mr_mip->base*mr_mip->w2->w[n-1]+mr_mip->w2->w[n-2]; last=TRUE; } #else u=muldiv(mr_mip->w1->w[n-1],mr_mip->base,mr_mip->w1->w[n-2],m,&sr); v=muldiv(mr_mip->w2->w[n-1],mr_mip->base,mr_mip->w2->w[n-2],m,&sr); #endif } #endif } dplus=TRUE; a=1; b=0; c=0; d=1; forever { /* work only with most significant piece */ if (last) { if (v==0) break; q=qdiv(u,v); if (q==0) break; } else { if (dplus) { if ((mr_small)(v-c)==0 || (mr_small)(v+d)==0) break; q=qdiv(u+a,v-c); if (q==0) break; if (q!=qdiv(u-b,v+d)) break; } else { if ((mr_small)(v+c)==0 || (mr_small)(v-d)==0) break; q=qdiv(u-a,v+c); if (q==0) break; if (q!=qdiv(u+b,v-d)) break; } } if (q==1) { if ((mr_small)(b+d) >= MAXBASE) break; r=a+c; a=c; c=r; r=b+d; b=d; d=r; lr=u-v; u=v; v=lr; } else { if (q>=MR_DIV(MAXBASE-b,d)) break; r=a+q*c; a=c; c=r; r=b+q*d; b=d; d=r; lr=u-q*v; u=v; v=lr; } iter++; dplus=!dplus; } iter%=2; } if (s==MINUS) iter++; if (iter%2==1) subtract(_MIPP_ y,mr_mip->w3,mr_mip->w3); if (xd!=yd) { negify(x,mr_mip->w2); mad(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w1,y,mr_mip->w4,mr_mip->w4); copy(mr_mip->w4,yd); } copy(mr_mip->w3,xd); if (z!=xd && z!=yd) copy(mr_mip->w1,z); MR_OUT return (size(mr_mip->w1)); }
int xgcd(_MIPD_ big x,big y,big xd,big yd,big z) { /* greatest common divisor by Euclids method * * extended to also calculate xd and yd where * * z = x.xd + y.yd = gcd(x,y) * * if xd, yd not distinct, only xd calculated * * z only returned if distinct from xd and yd * * xd will always be positive, yd negative */ int q,r,a,b,c,d,s,n; mr_small m,sr; #ifdef mr_dltype mr_large u,v,lq,lr; #else mr_small u,v,lq,lr; #endif BOOL last; big t; #ifndef MR_GENERIC_MT miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return 0; MR_IN(30) copy(x,mr_mip->w1); copy(y,mr_mip->w2); s=exsign(mr_mip->w1); insign(PLUS,mr_mip->w1); insign(PLUS,mr_mip->w2); /* copy(mr_mip->w1,mr_mip->w3); copy(mr_mip->w2,mr_mip->w4); */ convert(_MIPP_ 1,mr_mip->w3); zero(mr_mip->w4); last=FALSE; a=b=c=d=0; while (size(mr_mip->w2)!=0) { if (b==0) { /* update mr_mip->w1 and mr_mip->w2 */ divide(_MIPP_ mr_mip->w1,mr_mip->w2,mr_mip->w5); t=mr_mip->w1,mr_mip->w1=mr_mip->w2,mr_mip->w2=t; /* swap(mr_mip->w1,mr_mip->w2) */ multiply(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w0); subtract(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3); t=mr_mip->w3,mr_mip->w3=mr_mip->w4,mr_mip->w4=t; /* swap(xd,yd) */ } else { premult(_MIPP_ mr_mip->w1,c,mr_mip->w5); premult(_MIPP_ mr_mip->w1,a,mr_mip->w1); premult(_MIPP_ mr_mip->w2,b,mr_mip->w0); premult(_MIPP_ mr_mip->w2,d,mr_mip->w2); add_r(_MIPP_ mr_mip->w1,mr_mip->w0,mr_mip->w1); add_r(_MIPP_ mr_mip->w2,mr_mip->w5,mr_mip->w2); premult(_MIPP_ mr_mip->w3,c,mr_mip->w5); premult(_MIPP_ mr_mip->w3,a,mr_mip->w3); premult(_MIPP_ mr_mip->w4,b,mr_mip->w0); premult(_MIPP_ mr_mip->w4,d,mr_mip->w4); add_r(_MIPP_ mr_mip->w3,mr_mip->w0,mr_mip->w3); add_r(_MIPP_ mr_mip->w4,mr_mip->w5,mr_mip->w4); } if (mr_mip->ERNUM || size(mr_mip->w2)==0) break; n=(int)mr_mip->w1[0]; a=1; b=0; c=0; d=1; if (n==1) { last=TRUE; u=mr_mip->w1[1]; v=mr_mip->w2[1]; } else { m=mr_mip->w1[n]+1; if (mr_mip->base==0) { #ifdef mr_dltype /* use double length type if available */ if (n>2 && m!=0) { /* squeeze out as much significance as possible */ MR_TOP(u)=muldvm(mr_mip->w1[n],mr_mip->w1[n-1],m,&sr); MR_BOT(u)=muldvm(sr,mr_mip->w1[n-2],m,&sr); MR_TOP(v)=muldvm(mr_mip->w2[n],mr_mip->w2[n-1],m,&sr); MR_BOT(v)=muldvm(sr,mr_mip->w2[n-2],m,&sr); } else { MR_TOP(u)=mr_mip->w1[n]; MR_BOT(u)=mr_mip->w1[n-1]; MR_TOP(v)=mr_mip->w2[n]; MR_BOT(v)=mr_mip->w2[n-1]; if (n==2) last=TRUE; } #else if (m==0) { u=mr_mip->w1[n]; v=mr_mip->w2[n]; } else { u=muldvm(mr_mip->w1[n],mr_mip->w1[n-1],m,&sr); v=muldvm(mr_mip->w2[n],mr_mip->w2[n-1],m,&sr); } #endif } else { #ifdef mr_dltype /* use double length type if available */ if (n>2) { /* squeeze out as much significance as possible */ u=muldiv(mr_mip->w1[n],mr_mip->base,mr_mip->w1[n-1],m,&sr); u=u*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w1[n-2],m,&sr); v=muldiv(mr_mip->w2[n],mr_mip->base,mr_mip->w2[n-1],m,&sr); v=v*mr_mip->base+muldiv(sr,mr_mip->base,mr_mip->w2[n-2],m,&sr); } else { u=(mr_large)mr_mip->base*mr_mip->w1[n]+mr_mip->w1[n-1]; v=(mr_large)mr_mip->base*mr_mip->w2[n]+mr_mip->w2[n-1]; last=TRUE; } #else u=muldiv(mr_mip->w1[n],mr_mip->base,mr_mip->w1[n-1],m,&sr); v=muldiv(mr_mip->w2[n],mr_mip->base,mr_mip->w2[n-1],m,&sr); #endif } } forever { /* work only with most significant piece */ if (last) { if (v==0) break; lq=u/v; } else { if (((v+c)==0) || ((v+d)==0)) break; lq=(u+a)/(v+c); if (lq!=(u+b)/(v+d)) break; } #ifdef mr_dltype if (lq>=(mr_large)(MR_TOOBIG/abs(d))) break; #else if (lq>=(mr_small)(MR_TOOBIG/abs(d))) break; #endif q=(int)lq; r=a-q*c; a=c; c=r; r=b-q*d; b=d; d=r; lr=u-lq*v; u=v; v=lr; } } if (s==MINUS) negate(mr_mip->w3,mr_mip->w3); if (size(mr_mip->w3)<=0) add_r(_MIPP_ mr_mip->w3,y,mr_mip->w3); if (xd!=yd) { negate(x,mr_mip->w2); mad(_MIPP_ mr_mip->w2,mr_mip->w3,mr_mip->w1,y,mr_mip->w4,mr_mip->w4); copy(mr_mip->w4,yd); } copy(mr_mip->w3,xd); if (z!=xd && z!=yd) copy(mr_mip->w1,z); MR_OUT return (size(mr_mip->w1)); }