Skip to content

Commit

Permalink
mpn jtxminus
Browse files Browse the repository at this point in the history
also make jmpn_neg macro reusable
  • Loading branch information
rdm committed Jan 15, 2025
1 parent 03d94c8 commit bf0ad1e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 10 deletions.
16 changes: 8 additions & 8 deletions jsrc/jgmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,14 @@ EXTERN Q Q__; // x: __ NB. _1r0 internal form

// workalike for mpn_neg (could be better optimized)
// see: https://gmplib.org/manual/Low_002dlevel-Functions
#define jmpn_neg(z, w, wn) ({mp_ptr Z=z, W=w; mp_size_t N=wn; B r;\
while (0 == *W) { /* find lowest non-zero limb */\
*Z= 0; /* -0 is 0 */\
if (!--N) {r= 0; goto done;} /* all zeros? */\
++Z; ++W; /* next... */\
} *Z= GMP_NUMB_MASK&-*W; /* C's - works on lowest limb */\
if (--N) jmpn_com(++Z, ++W, N); /* complement any remaining */\
r= 1; done: r;})
#define jmpn_neg(z, w, wn) ({mp_ptr Z=z, W=w; mp_size_t N=wn; B r=1;\
while (0 == *W) { /* find lowest non-zero limb */\
*Z= 0; /* -0 is 0 */\
if (!--N) {r= 0; break;} /* all zeros? */\
++Z; ++W; /* next... */\
} *Z= GMP_NUMB_MASK&-*W; /* C's - works on lowest non-zero limb */\
if (r&&--N) jmpn_com(++Z, ++W, N); /* complement any remaining */\
r;})

#ifdef _WIN32
// workalike for mpn_com which mpir does not support
Expand Down
31 changes: 29 additions & 2 deletions jsrc/vx.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ I jtxcompare(J jt,X a,X w){ // *a-w NB. J's *
XF1(jtxsgn){ // *w NB. X w, X result
R xc(XSGN(w)<0 ?-1 :XSGN(w)>0);
}
XF2(jtxplus){ // a+w
XF2(jtxplus){ // a+w NB. X a, w
ARGCHK2(a,w);
if (unlikely(ISX0(a))) R w;
if (unlikely(ISX0(w))) R a;
Expand All @@ -59,7 +59,34 @@ XF2(jtxplus){ // a+w
}
XF2(jtxminus){ // a-w NB. X a, w
ARGCHK2(a,w);
R XsubXX(a,w);
if (unlikely(ISX0(w))) R a;
if (unlikely(ISX0(a))) {
X z; mp_size_t n= XLIMBLEN(w);
GAX(z, n); mp_ptr zd= voidAV1(z), wd= voidAV1(w);
DO(n, {*zd++= *wd++;}); // maybe/eventually should use virtual block here
XSGN(z)= -XSGN(w);
R z;
}
// X z= XaddXX(a,w); // XaddXX could become [temporary] syntactic sugar for jtxplus
mp_size_t an= XLIMBLEN(a), wn= XLIMBLEN(w); // arg sizes
mp_size_t m= MIN(an, wn), n= MAX(an, wn); // result sizes
X z; GAX(z, n+1); const mp_ptr zd= voidAV1(z), ad= voidAV1(a), wd= voidAV1(w); // data locations
B ap= XSGN(a)>0; B wnp= XSGN(w)<0; // positive or negative?
B ax= an>= wn; // when w and a have different lengths, larger should be first arg to mpn_add/mpn_sub
if (ap==wnp) { // work with unsigned magnitudes:
if (jmpn_add(zd, ax?ad:wd, n, ax?wd:ad, m)) zd[n++]= 1;
XSGN(z)= ap ?n :-n; // signs matched, result has sign of both args
} else {
B zp= ax ?ap :wnp;
if (jmpn_sub(zd, ax?ad:wd, n, ax?wd:ad, m)) {
zp= 1-zp; // borrow means need to negate result
if(unlikely(!jmpn_neg(zd, zd, n))) R X0; /* this X0 presumably never happens */
}
while (likely(n) && unlikely(!zd[n-1])) n--; /* trim leading zeros */
if (unlikely(!n)) R X0;
XSGN(z)= zp ?n :-n;
}
R z;
}
XF2(jtxtymes){ // a*w NB. X a, w
ARGCHK2(a,w); A z;
Expand Down

0 comments on commit bf0ad1e

Please sign in to comment.