attotime &attotime::operator*=(UINT32 factor) { // if one of the items is attotime::never, return attotime::never if (seconds >= ATTOTIME_MAX_SECONDS) return *this = never; // 0 times anything is zero if (factor == 0) return *this = zero; // split attoseconds into upper and lower halves which fit into 32 bits UINT32 attolo; UINT32 attohi = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo); // scale the lower half, then split into high/low parts UINT64 temp = mulu_32x32(attolo, factor); UINT32 reslo; temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reslo); // scale the upper half, then split into high/low parts temp += mulu_32x32(attohi, factor); UINT32 reshi; temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reshi); // scale the seconds temp += mulu_32x32(seconds, factor); if (temp >= ATTOTIME_MAX_SECONDS) return *this = never; // build the result seconds = temp; attoseconds = (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT); return *this; }
attotime attotime_mul(attotime _time1, UINT32 factor) { UINT32 attolo, attohi, reslo, reshi; UINT64 temp; /* if one of the items is attotime_never, return attotime_never */ if (_time1.seconds >= ATTOTIME_MAX_SECONDS) return attotime_never; /* 0 times anything is zero */ if (factor == 0) return attotime_zero; /* split attoseconds into upper and lower halves which fit into 32 bits */ attohi = divu_64x32_rem(_time1.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo); /* scale the lower half, then split into high/low parts */ temp = mulu_32x32(attolo, factor); temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reslo); /* scale the upper half, then split into high/low parts */ temp += mulu_32x32(attohi, factor); temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reshi); /* scale the seconds */ temp += mulu_32x32(_time1.seconds, factor); if (temp >= ATTOTIME_MAX_SECONDS) return attotime_never; /* build the result */ return attotime_make(temp, (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT)); }
attotime attotime_div(attotime _time1, UINT32 factor) { UINT32 attolo, attohi, reshi, reslo, remainder; attotime result; UINT64 temp; /* if one of the items is attotime_never, return attotime_never */ if (_time1.seconds >= ATTOTIME_MAX_SECONDS) return attotime_never; /* ignore divide by zero */ if (factor == 0) return _time1; /* split attoseconds into upper and lower halves which fit into 32 bits */ attohi = divu_64x32_rem(_time1.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo); /* divide the seconds and get the remainder */ result.seconds = divu_64x32_rem(_time1.seconds, factor, &remainder); /* combine the upper half of attoseconds with the remainder and divide that */ temp = (INT64)attohi + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT); reshi = divu_64x32_rem(temp, factor, &remainder); /* combine the lower half of attoseconds with the remainder and divide that */ temp = attolo + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT); reslo = divu_64x32_rem(temp, factor, &remainder); /* round based on the remainder */ result.attoseconds = (attoseconds_t)reslo + mulu_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT); if (remainder >= factor / 2) if (++result.attoseconds >= ATTOSECONDS_PER_SECOND) { result.attoseconds = 0; result.seconds++; } return result; }
attotime &attotime::operator/=(UINT32 factor) { // if one of the items is attotime::never, return attotime::never if (seconds >= ATTOTIME_MAX_SECONDS) return *this = never; // ignore divide by zero if (factor == 0) return *this; // split attoseconds into upper and lower halves which fit into 32 bits UINT32 attolo; UINT32 attohi = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo); // divide the seconds and get the remainder UINT32 remainder; seconds = divu_64x32_rem(seconds, factor, &remainder); // combine the upper half of attoseconds with the remainder and divide that UINT64 temp = (INT64)attohi + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT); UINT32 reshi = divu_64x32_rem(temp, factor, &remainder); // combine the lower half of attoseconds with the remainder and divide that temp = attolo + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT); UINT32 reslo = divu_64x32_rem(temp, factor, &remainder); // round based on the remainder attoseconds = (attoseconds_t)reslo + mulu_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT); if (remainder >= factor / 2) if (++attoseconds >= ATTOSECONDS_PER_SECOND) { attoseconds = 0; seconds++; } return *this; }