mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-06-09 18:29:36 +00:00
180 lines
6.0 KiB
C
180 lines
6.0 KiB
C
// Simple binary division implementation
|
|
// Follows the C99 standard by truncating toward zero on negative results.
|
|
// See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
|
|
|
|
#include <division.h>
|
|
|
|
// Remainder after signed 8 bit division
|
|
char rem8u =0;
|
|
|
|
// Performs division on two 8 bit unsigned chars
|
|
// Returns dividend/divisor.
|
|
// The remainder will be set into the global variable rem8u
|
|
// Implemented using simple binary division
|
|
char div8u(char dividend, char divisor) {
|
|
return divr8u(dividend, divisor, 0);
|
|
}
|
|
|
|
// Performs division on two 8 bit unsigned chars and an initial remainder
|
|
// Returns dividend/divisor.
|
|
// The final remainder will be set into the global variable rem8u
|
|
// Implemented using simple binary division
|
|
char divr8u(char dividend, char divisor, char rem) {
|
|
char quotient = 0;
|
|
for( char i : 0..7) {
|
|
rem = rem << 1;
|
|
if( (dividend & 0x80) != 0 ) {
|
|
rem = rem | 1;
|
|
}
|
|
dividend = dividend << 1;
|
|
quotient = quotient << 1;
|
|
if(rem>=divisor) {
|
|
quotient++;
|
|
rem = rem - divisor;
|
|
}
|
|
}
|
|
rem8u = rem;
|
|
return quotient;
|
|
}
|
|
|
|
// Divide unsigned 16-bit unsigned long dividend with a 8-bit unsigned char divisor
|
|
// The 8-bit unsigned char remainder can be found in rem8u after the division
|
|
unsigned int div16u8u(unsigned int dividend, unsigned char divisor) {
|
|
unsigned char quotient_hi = divr8u(BYTE1(dividend), divisor, 0);
|
|
unsigned char quotient_lo = divr8u(BYTE0(dividend), divisor, rem8u);
|
|
unsigned int quotient = MAKEWORD( quotient_hi, quotient_lo );
|
|
return quotient;
|
|
}
|
|
|
|
// Remainder after unsigned 16-bit division
|
|
unsigned int rem16u = 0;
|
|
|
|
// Performs division on two 16 bit unsigned ints and an initial remainder
|
|
// Returns the quotient dividend/divisor.
|
|
// The final remainder will be set into the global variable rem16u
|
|
// Implemented using simple binary division
|
|
unsigned int divr16u(unsigned int dividend, unsigned int divisor, unsigned int rem) {
|
|
unsigned int quotient = 0;
|
|
for( char i : 0..15) {
|
|
rem = rem << 1;
|
|
if( (BYTE1(dividend) & 0x80) != 0 ) {
|
|
rem = rem | 1;
|
|
}
|
|
dividend = dividend << 1;
|
|
quotient = quotient << 1;
|
|
if(rem>=divisor) {
|
|
quotient++;
|
|
rem = rem - divisor;
|
|
}
|
|
}
|
|
rem16u = rem;
|
|
return quotient;
|
|
}
|
|
|
|
// Performs modulo on two 16 bit unsigned ints and an initial remainder
|
|
// Returns the remainder.
|
|
// Implemented using simple binary division
|
|
unsigned int modr16u(unsigned int dividend, unsigned int divisor, unsigned int rem) {
|
|
divr16u(dividend, divisor, rem);
|
|
return rem16u;
|
|
}
|
|
|
|
// Performs division on two 16 bit unsigned ints
|
|
// Returns the quotient dividend/divisor.
|
|
// The remainder will be set into the global variable rem16u
|
|
// Implemented using simple binary division
|
|
unsigned int div16u(unsigned int dividend, unsigned int divisor) {
|
|
return divr16u(dividend, divisor, 0);
|
|
}
|
|
|
|
// Divide unsigned 32-bit unsigned long dividend with a 16-bit unsigned int divisor
|
|
// The 16-bit unsigned int remainder can be found in rem16u after the division
|
|
unsigned long div32u16u(unsigned long dividend, unsigned int divisor) {
|
|
unsigned int quotient_hi = divr16u(WORD1(dividend), divisor, 0);
|
|
unsigned int quotient_lo = divr16u(WORD0(dividend), divisor, rem16u);
|
|
unsigned long quotient = MAKELONG( quotient_hi, quotient_lo );
|
|
return quotient;
|
|
}
|
|
|
|
// Remainder after signed 8 bit division
|
|
signed char rem8s = 0;
|
|
|
|
// Perform division on two signed 8-bit numbers
|
|
// Returns dividend/divisor.
|
|
// The remainder will be set into the global variable rem8s.
|
|
// Implemented using simple binary division
|
|
// Follows the C99 standard by truncating toward zero on negative results.
|
|
// See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
|
|
signed char div8s(signed char dividend, signed char divisor) {
|
|
char neg = 0;
|
|
char dividendu = 0;
|
|
if(dividend<0) {
|
|
dividendu = (char)-dividend;
|
|
neg = 1;
|
|
} else {
|
|
dividendu = (char)dividend;
|
|
}
|
|
char divisoru = 0;
|
|
if(divisor<0) {
|
|
divisoru = (char)-divisor;
|
|
neg = neg ^ 1;
|
|
} else {
|
|
divisoru = (char)divisor;
|
|
}
|
|
char resultu = div8u(dividendu, divisoru);
|
|
if(neg==0) {
|
|
rem8s = (signed char)rem8u;
|
|
return (signed char)resultu;
|
|
} else {
|
|
rem8s = -(signed char)rem8u;
|
|
return -(signed char)resultu;
|
|
}
|
|
}
|
|
|
|
// Remainder after signed 16 bit division
|
|
signed int rem16s = 0;
|
|
|
|
// Perform division on two signed 16-bit numbers with an initial remainder.
|
|
// Returns dividend/divisor. The remainder will be set into the global variable rem16s.
|
|
// Implemented using simple binary division
|
|
// Follows the C99 standard by truncating toward zero on negative results.
|
|
// See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
|
|
signed int divr16s(signed int dividend, signed int divisor, signed int rem) {
|
|
char neg = 0;
|
|
unsigned int dividendu = 0;
|
|
unsigned int remu = 0;
|
|
if(dividend<0 || rem<0) {
|
|
dividendu = (unsigned int)-dividend;
|
|
remu = (unsigned int)-rem;
|
|
neg = 1;
|
|
} else {
|
|
dividendu = (unsigned int)dividend;
|
|
remu = (unsigned int)rem;
|
|
}
|
|
unsigned int divisoru = 0;
|
|
if(divisor<0) {
|
|
divisoru = (unsigned int)-divisor;
|
|
neg = neg ^ 1;
|
|
} else {
|
|
divisoru = (unsigned int)divisor;
|
|
}
|
|
unsigned int resultu = divr16u(dividendu, divisoru, remu);
|
|
if(neg==0) {
|
|
rem16s = (signed int)rem16u;
|
|
return (signed int)resultu;
|
|
} else {
|
|
rem16s = -(signed int)rem16u;
|
|
return -(signed int)resultu;
|
|
}
|
|
}
|
|
|
|
// Perform division on two signed 16-bit numbers
|
|
// Returns dividend/divisor.
|
|
// The remainder will be set into the global variable rem16s.
|
|
// Implemented using simple binary division
|
|
// Follows the C99 standard by truncating toward zero on negative results.
|
|
// See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
|
|
signed int div16s(signed int dividend, signed int divisor) {
|
|
return divr16s(dividend, divisor, 0);
|
|
}
|