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. 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_X ((uint32_t) ((STEPS_PER_MM_X * 1000.0) + 0.5))
#define STEPS_PER_M_Y ((uint32_t) (STEPS_PER_MM_Y * 1000.0)) #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)) #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)) #define STEPS_PER_M_E ((uint32_t) ((STEPS_PER_MM_E * 1000.0) + 0.5))
/* /*
mm -> inch conversion mm -> inch conversion
@ -50,8 +50,10 @@ GCODE_COMMAND next_target __attribute__ ((__section__ (".bss")));
/* /*
utility functions 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; int32_t r = df->mantissa;
uint8_t e = df->exponent; uint8_t e = df->exponent;
@ -59,36 +61,21 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator)
if (e) if (e)
e--; e--;
// scale factors
// if (multiplicand != 1)
// r *= multiplicand;
// if (denominator != 1)
// r /= denominator;
int32_t rnew1 = r * (multiplicand / denominator); int32_t rnew1 = r * (multiplicand / denominator);
int32_t rnew2 = r * (multiplicand % denominator) / denominator; if (e)
r = rnew1 + rnew2; {
int32_t rnew2 = r * (multiplicand % denominator) / denominator;
r = rnew1 + rnew2;
// sign r = (r + rounding[e]) / powers[e];
if (df->sign) }
r = -r; else
{
// exponent- try to keep divides to a minimum for common (small) values at expense of slightly more code int32_t rnew2 = (r * (multiplicand % denominator) + (denominator / 2)) / denominator;
while (e >= 5) { r = rnew1 + rnew2;
r /= 100000;
e -= 5;
} }
if (e == 1) return df->sign ? -r : r;
r /= 10;
else if (e == 2)
r /= 100;
else if (e == 3)
r /= 1000;
else if (e == 4)
r /= 10000;
return r;
} }
/**************************************************************************** /****************************************************************************
@ -292,10 +279,11 @@ void gcode_parse_char(uint8_t c) {
#endif #endif
default: 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 // can't do ranges in switch..case, so process actual digits here.
if (c >= '0' && c <= '9' && if ( c >= '0'
((next_target.option_inches == 0 && read_digit.exponent < 4) || && c <= '9'
(next_target.option_inches && read_digit.exponent < 5))) { && read_digit.mantissa < (DECFLOAT_MANT_MAX / 10)
&& read_digit.exponent < DECFLOAT_EXP_MAX ) {
// this is simply mantissa = (mantissa * 10) + atoi(c) in different clothes // this is simply mantissa = (mantissa * 10) + atoi(c) in different clothes
read_digit.mantissa = (read_digit.mantissa << 3) + (read_digit.mantissa << 1) + (c - '0'); read_digit.mantissa = (read_digit.mantissa << 3) + (read_digit.mantissa << 1) + (c - '0');
if (read_digit.exponent) if (read_digit.exponent)

View File

@ -16,11 +16,18 @@
// wether to insist on a checksum // wether to insist on a checksum
//#define REQUIRE_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 { typedef struct {
uint32_t sign :1; uint32_t sign :1;
uint32_t mantissa :24; uint32_t mantissa :DECFLOAT_MANT_WIDTH;
uint32_t exponent :7; uint32_t exponent :DECFLOAT_EXP_WIDTH;
} decfloat; } decfloat;
// this holds all the possible data from a received command // this holds all the possible data from a received command
@ -67,9 +74,6 @@ typedef struct {
// the command being processed // the command being processed
extern GCODE_COMMAND next_target; 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 // accept the next character and process it
void gcode_parse_char(uint8_t c); void gcode_parse_char(uint8_t c);

View File

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