| #include <stdint.h> |
| #include <signal.h> |
| |
| #if BITS == 64 |
| typedef uint64_t unum; |
| typedef int64_t snum; |
| #else |
| typedef uint32_t unum; |
| typedef int32_t snum; |
| #endif |
| |
| #ifdef SIGNED |
| typedef snum xnum; |
| #else |
| typedef unum xnum; |
| #endif |
| |
| #ifdef __cris__ |
| static inline unum __attribute__((const)) dstep(unum rs, unum rd) { |
| asm("dstep %1,%0" : "+r" (rd) : "r" (rs)); |
| return rd; |
| } |
| |
| static inline unum __attribute__((const)) lz(unum rs) { |
| unum rd; |
| asm("lz %1,%0" : "=r" (rd) : "r" (rs)); |
| return rd; |
| } |
| |
| #else |
| /* For testing */ |
| static inline unum __attribute__ ((const)) dstep(unum rs, unum rd) { |
| rd <<= 1; |
| if ( rd >= rs ) |
| rd -= rs; |
| |
| return rd; |
| } |
| |
| static inline unum __attribute__((const)) lz(unum rs) { |
| unum rd = 0; |
| while ( rs >= 0x7fffffff ) { |
| rd++; |
| rs <<= 1; |
| } |
| return rd; |
| } |
| |
| #endif |
| |
| xnum NAME (unum num, unum den) |
| { |
| unum quot = 0, qbit = 1; |
| int minus = 0; |
| xnum v; |
| |
| if ( den == 0 ) { |
| raise(SIGFPE); |
| return 0; /* If signal ignored... */ |
| } |
| |
| #if SIGNED |
| if ( (snum)(num^den) < 0 ) |
| minus = 1; |
| if ( (snum)num < 0 ) num = -num; |
| if ( (snum)den < 0 ) den = -den; |
| #endif |
| |
| den--; |
| |
| |
| /* Left-justify denominator and count shift */ |
| while ( (snum)den >= 0 ) { |
| den <<= 1; |
| qbit <<= 1; |
| } |
| |
| while ( qbit ) { |
| if ( den <= num ) { |
| num -= den; |
| quot += qbit; |
| } |
| den >>= 1; |
| qbit >>= 1; |
| } |
| |
| v = (xnum)(REM ? num : quot); |
| if ( minus ) v = -v; |
| return v; |
| } |