------------------------------------------------------------------ */ decUnitCompare -- compare two >=0 integers in Unit arrays */ / This routine compares A ? B*10**E where A and B are unit arrays */ A is a plain integer */ B has an exponent of E (which must be non-negative) */ / Arg1 is A first Unit (lsu)
| 6229 | /* only occur if E!=0) */ |
| 6230 | /* ------------------------------------------------------------------ */ |
| 6231 | static Int decUnitCompare(const Unit *a, Int alength, |
| 6232 | const Unit *b, Int blength, Int exp) { |
| 6233 | Unit *acc; // accumulator for result |
| 6234 | Unit accbuff[SD2U(DECBUFFER*2+1)]; // local buffer |
| 6235 | Unit *allocacc=NULL; // -> allocated acc buffer, iff allocated |
| 6236 | Int accunits, need; // units in use or needed for acc |
| 6237 | const Unit *l, *r, *u; // work |
| 6238 | Int expunits, exprem, result; // .. |
| 6239 | |
| 6240 | if (exp==0) { // aligned; fastpath |
| 6241 | if (alength>blength) return 1; |
| 6242 | if (alength<blength) return -1; |
| 6243 | // same number of units in both -- need unit-by-unit compare |
| 6244 | l=a+alength-1; |
| 6245 | r=b+alength-1; |
| 6246 | for (;l>=a; l--, r--) { |
| 6247 | if (*l>*r) return 1; |
| 6248 | if (*l<*r) return -1; |
| 6249 | } |
| 6250 | return 0; // all units match |
| 6251 | } // aligned |
| 6252 | |
| 6253 | // Unaligned. If one is >1 unit longer than the other, padded |
| 6254 | // approximately, then can return easily |
| 6255 | if (alength>blength+(Int)D2U(exp)) return 1; |
| 6256 | if (alength+1<blength+(Int)D2U(exp)) return -1; |
| 6257 | |
| 6258 | // Need to do a real subtract. For this, a result buffer is needed |
| 6259 | // even though only the sign is of interest. Its length needs |
| 6260 | // to be the larger of alength and padded blength, +2 |
| 6261 | need=blength+D2U(exp); // maximum real length of B |
| 6262 | if (need<alength) need=alength; |
| 6263 | need+=2; |
| 6264 | acc=accbuff; // assume use local buffer |
| 6265 | if (need*sizeof(Unit)>sizeof(accbuff)) { |
| 6266 | allocacc=(Unit *)malloc(need*sizeof(Unit)); |
| 6267 | if (allocacc==NULL) return BADINT; // hopeless -- abandon |
| 6268 | acc=allocacc; |
| 6269 | } |
| 6270 | // Calculate units and remainder from exponent. |
| 6271 | expunits=exp/DECDPUN; |
| 6272 | exprem=exp%DECDPUN; |
| 6273 | // subtract [A+B*(-m)] |
| 6274 | accunits=decUnitAddSub(a, alength, b, blength, expunits, acc, |
| 6275 | -(Int)powers[exprem]); |
| 6276 | // [UnitAddSub result may have leading zeros, even on zero] |
| 6277 | if (accunits<0) result=-1; // negative result |
| 6278 | else { // non-negative result |
| 6279 | // check units of the result before freeing any storage |
| 6280 | for (u=acc; u<acc+accunits-1 && *u==0;) u++; |
| 6281 | result=(*u==0 ? 0 : +1); |
| 6282 | } |
| 6283 | // clean up and return the result |
| 6284 | if (allocacc!=NULL) free(allocacc); // drop any storage used |
| 6285 | return result; |
| 6286 | } // decUnitCompare |
| 6287 | |
| 6288 | /* ------------------------------------------------------------------ */ |
no test coverage detected