fix decfloat_to_int, Less divisions in decfloat_to_int.

Signed-off-by: Michael Moon <triffid.hunter@gmail.com>
This commit is contained in:
Stephan Walter 2011-01-11 19:17:52 +11:00 committed by Michael Moon
parent c364e8f873
commit 4febbea2f8
3 changed files with 44 additions and 102 deletions

View File

@ -25,10 +25,10 @@
which is about the worst case we have. All other machines have a bigger build volume.
*/
#define STEPS_PER_M_X ((uint32_t) (STEPS_PER_MM_X * 1000.0))
#define STEPS_PER_M_Y ((uint32_t) (STEPS_PER_MM_Y * 1000.0))
#define STEPS_PER_M_Z ((uint32_t) (STEPS_PER_MM_Z * 1000.0))
#define STEPS_PER_M_E ((uint32_t) (STEPS_PER_MM_E * 1000.0))
#define STEPS_PER_M_X ((uint32_t) ((STEPS_PER_MM_X * 1000.0) + 0.5))
#define STEPS_PER_M_Y ((uint32_t) ((STEPS_PER_MM_Y * 1000.0) + 0.5))
#define STEPS_PER_M_Z ((uint32_t) ((STEPS_PER_MM_Z * 1000.0) + 0.5))
#define STEPS_PER_M_E ((uint32_t) ((STEPS_PER_MM_E * 1000.0) + 0.5))
/*
mm -> inch conversion
@ -50,8 +50,10 @@ GCODE_COMMAND next_target __attribute__ ((__section__ (".bss")));
/*
utility functions
*/
extern const uint32_t powers[]; // defined in sermsg.c
const int32_t rounding[DECFLOAT_EXP_MAX] = {0, 5, 50, 500, 5000, 50000, 500000};
int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) {
static int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, uint32_t denominator) {
int32_t r = df->mantissa;
uint8_t e = df->exponent;
@ -59,36 +61,21 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator)
if (e)
e--;
// scale factors
// if (multiplicand != 1)
// r *= multiplicand;
// if (denominator != 1)
// r /= denominator;
int32_t rnew1 = r * (multiplicand / denominator);
if (e)
{
int32_t rnew2 = r * (multiplicand % denominator) / denominator;
r = rnew1 + rnew2;
// sign
if (df->sign)
r = -r;
// exponent- try to keep divides to a minimum for common (small) values at expense of slightly more code
while (e >= 5) {
r /= 100000;
e -= 5;
r = (r + rounding[e]) / powers[e];
}
else
{
int32_t rnew2 = (r * (multiplicand % denominator) + (denominator / 2)) / denominator;
r = rnew1 + rnew2;
}
if (e == 1)
r /= 10;
else if (e == 2)
r /= 100;
else if (e == 3)
r /= 1000;
else if (e == 4)
r /= 10000;
return r;
return df->sign ? -r : r;
}
/****************************************************************************
@ -292,10 +279,11 @@ void gcode_parse_char(uint8_t c) {
#endif
default:
// can't do ranges in switch..case, so process actual digits here. Limit the digits right of the decimal to avoid variable overflow in decfloat_to_int() due to excess precision
if (c >= '0' && c <= '9' &&
((next_target.option_inches == 0 && read_digit.exponent < 4) ||
(next_target.option_inches && read_digit.exponent < 5))) {
// can't do ranges in switch..case, so process actual digits here.
if ( c >= '0'
&& c <= '9'
&& read_digit.mantissa < (DECFLOAT_MANT_MAX / 10)
&& read_digit.exponent < DECFLOAT_EXP_MAX ) {
// this is simply mantissa = (mantissa * 10) + atoi(c) in different clothes
read_digit.mantissa = (read_digit.mantissa << 3) + (read_digit.mantissa << 1) + (c - '0');
if (read_digit.exponent)

View File

@ -16,11 +16,18 @@
// wether to insist on a checksum
//#define REQUIRE_CHECKSUM
// this is a very crude decimal-based floating point structure. a real floating point would at least have signed exponent
// this is a very crude decimal-based floating point structure.
// a real floating point would at least have signed exponent.
// max (DECFLOAT_EXP_MAX - 1) digits after decimal point, because point is
// counted as well
#define DECFLOAT_EXP_WIDTH 3
#define DECFLOAT_EXP_MAX ((1 << DECFLOAT_EXP_WIDTH) - 1)
#define DECFLOAT_MANT_WIDTH (32 - 1 - DECFLOAT_EXP_WIDTH)
#define DECFLOAT_MANT_MAX (((uint32_t)1 << DECFLOAT_MANT_WIDTH) - 1)
typedef struct {
uint32_t sign :1;
uint32_t mantissa :24;
uint32_t exponent :7;
uint32_t mantissa :DECFLOAT_MANT_WIDTH;
uint32_t exponent :DECFLOAT_EXP_WIDTH;
} decfloat;
// this holds all the possible data from a received command
@ -67,9 +74,6 @@ typedef struct {
// the command being processed
extern GCODE_COMMAND next_target;
// utility functions
int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator);
// accept the next character and process it
void gcode_parse_char(uint8_t c);

View File

@ -25,72 +25,22 @@ void serwrite_hex32(uint32_t v) {
serwrite_hex8(v & 0xFFFF);
}
const uint32_t powers[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
void serwrite_uint32(uint32_t v) {
uint8_t t = 0;
if (v >= 1000000000) {
for (t = 0; v >= 1000000000; v -= 1000000000, t++);
serial_writechar(t + '0');
uint8_t e, t;
for (e = 9; e > 0; e--) {
if (v >= powers[e])
break;
}
if (v >= 100000000) {
for (t = 0; v >= 100000000; v -= 100000000, t++);
do
{
for (t = 0; v >= powers[e]; v -= powers[e], t++);
serial_writechar(t + '0');
}
else if (t != 0)
serial_writechar('0');
if (v >= 10000000) {
for (t = 0; v >= 10000000; v -= 10000000, t++);
serial_writechar(t + '0');
}
else if (t != 0)
serial_writechar('0');
if (v >= 1000000) {
for (t = 0; v >= 1000000; v -= 1000000, t++);
serial_writechar(t + '0');
}
else if (t != 0)
serial_writechar('0');
if (v >= 100000) {
for (t = 0; v >= 100000; v -= 100000, t++);
serial_writechar(t + '0');
}
else if (t != 0)
serial_writechar('0');
if (v >= 10000) {
for (t = 0; v >= 10000; v -= 10000, t++);
serial_writechar(t + '0');
}
else if (t != 0)
serial_writechar('0');
if (v >= 1000) {
for (t = 0; v >= 1000; v -= 1000, t++);
serial_writechar(t + '0');
}
else if (t != 0)
serial_writechar('0');
if (v >= 100) {
t = v / 100;
serial_writechar(t + '0');
v -= (t * 100);
}
else if (t != 0)
serial_writechar('0');
if (v >= 10) {
t = v / 10;
serial_writechar(t + '0');
v -= (t * 10);
}
else if (t != 0)
serial_writechar('0');
serial_writechar(v + '0');
while (e--);
}
void serwrite_int32(int32_t v) {