added detection of float format to autoconf, fix for signed values

This commit is contained in:
john30
2016-02-20 12:35:28 +01:00
parent a91d8ffd3b
commit 8c1431954a
2 changed files with 96 additions and 41 deletions
+42
View File
@@ -38,6 +38,48 @@ else
AC_MSG_ERROR([argp library not found, specify argp-standalone location in --with-argp-lib= and --with-argp-include= options.])
fi
AC_MSG_CHECKING([for direct float format conversion])
AC_TRY_RUN(
[
#include <stdint.h>
int main() {
union {
uint32_t i;
float f;
} test;
test.f = 0.15;
return test.i == 0x3e19999a ? 0 : 1;
}
],
[direct_float=1],
[direct_float=],
[direct_float=no],
)
if [[ "x$direct_float" == "x" ]]; then
AC_TRY_RUN(
[
#include <stdint.h>
int main() {
union {
uint32_t i;
float f;
} test;
test.f = 0.15;
return test.i == 0x9a99193e ? 0 : 1;
}
],
[direct_float=2],
[direct_float=no],
[direct_float=no],
)
fi
if [[ "x$direct_float" == "xno" ]]; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED([HAVE_DIRECT_FLOAT_FORMAT], $direct_float, [Define for direct conversion from float to int (2 for swapped by order).])
fi
AC_CONFIG_SRCDIR([src/ebusd/main.cpp])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile
+54 -41
View File
@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "data.h"
#include <iostream>
#include <sstream>
@@ -813,7 +817,7 @@ result_t StringDataField::writeSymbols(istringstream& input,
t.tm_mon = last-1; // January=0
t.tm_year = (value < 100 ? value + 2000 : value) - 1900;
t.tm_isdst = 0; // automatic
if (mktime(&t) < 0)
if (mktime(&t) == -1)
return RESULT_ERR_INVALID_NUM; // invalid date
unsigned char daysSinceSunday = (unsigned char)t.tm_wday; // Sun=0
if ((m_dataType.flags & BCD) != 0)
@@ -1116,7 +1120,12 @@ result_t NumberDataField::readSymbols(SymbolString& input, const unsigned char b
if (m_bitCount == 32) {
if ((m_dataType.flags & EXP) != 0) { // IEEE 754 binary32
float val;
/*int exp = (value >> 23) & 0xff; // 8 bits, signed
#ifdef HAVE_DIRECT_FLOAT_FORMAT
# if HAVE_DIRECT_FLOAT_FORMAT == 2
value = __builtin_bswap32(value);
# endif
#else
int exp = (value >> 23) & 0xff; // 8 bits, signed
if (exp == 0) {
val = 0.0;
} else {
@@ -1131,9 +1140,7 @@ result_t NumberDataField::readSymbols(SymbolString& input, const unsigned char b
} else if (m_divisor > 1) {
val /= (float)m_divisor;
}
}*/
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
value = __builtin_bswap32(value);
}
#endif
unsigned char* pval = (unsigned char*)&value;
val = *((float*)pval);
@@ -1189,13 +1196,45 @@ result_t NumberDataField::writeSymbols(istringstream& input,
unsigned int value;
const char* str = input.str().c_str();
if ((m_dataType.flags & REQ) == 0 && (isIgnored() || strcasecmp(str, NULL_VALUE) == 0))
if ((m_dataType.flags & REQ) == 0 && (isIgnored() || strcasecmp(str, NULL_VALUE) == 0)) {
value = m_dataType.replacement; // replacement value
else if (str == NULL || *str == 0)
} else if (str == NULL || *str == 0) {
return RESULT_ERR_EOF; // input too short
else {
} else if ((m_dataType.flags & EXP) != 0) { // IEEE 754 binary32
char* strEnd = NULL;
if (m_divisor == 1 && (m_dataType.flags & EXP) == 0) {
double dvalue = strtod(str, &strEnd);
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
return RESULT_ERR_INVALID_NUM; // invalid value
}
#ifdef HAVE_DIRECT_FLOAT_FORMAT
float val = (float)dvalue;
unsigned char* pval = (unsigned char*)&val;
value = *((int32_t*)pval);
# if HAVE_DIRECT_FLOAT_FORMAT == 2
value = __builtin_bswap32(value);
# endif
#else
value = 0;
if (dvalue != 0) {
bool negative = dvalue < 0;
if (negative) {
dvalue = -dvalue;
}
int exp = ilogb(dvalue);
if (exp < -126 || exp > 127)
return RESULT_ERR_INVALID_NUM; // invalid value
dvalue = scalbln(dvalue, -exp) - 1.0;
unsigned int sig = (unsigned int)(dvalue * exp2(23));
exp += 127;
value = (exp << 23) | sig;
if (negative) {
value |= 0x80000000;
}
}
#endif
} else {
char* strEnd = NULL;
if (m_divisor == 1) {
if ((m_dataType.flags & SIG) != 0) {
long int signedValue = strtol(str, &strEnd, 10);
if (signedValue < 0 && m_bitCount != 32)
@@ -1213,46 +1252,20 @@ result_t NumberDataField::writeSymbols(istringstream& input,
if (strEnd == NULL || strEnd == str || *strEnd != 0)
return RESULT_ERR_INVALID_NUM; // invalid value
if (m_divisor < 0)
dvalue /= -m_divisor;
dvalue = round(dvalue / -m_divisor);
else
dvalue *= m_divisor;
if ((m_dataType.flags & EXP) != 0) { // IEEE 754 binary32
/*value = 0;
if (dvalue != 0) {
bool negative = dvalue < 0;
if (negative) {
dvalue = -dvalue;
}
int exp = ilogb(dvalue);
if (exp < -126 || exp > 127)
return RESULT_ERR_INVALID_NUM; // invalid value
dvalue = scalbln(dvalue, -exp) - 1.0;
unsigned int sig = (unsigned int)(dvalue * exp2(23));
exp += 127;
value = (exp << 23) | sig;
if (negative) {
value |= 0x80000000;
}
}*/
float val = (float)dvalue;
unsigned char* pval = (unsigned char*)&val;
value = *((int32_t*)pval);
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
value = __builtin_bswap32(value);
#endif
} else if ((m_dataType.flags & SIG) != 0) {
dvalue = round(dvalue);
dvalue = round(dvalue * m_divisor);
if ((m_dataType.flags & SIG) != 0) {
if (dvalue < -(1LL << (8 * m_length)) || dvalue >= (1LL << (8 * m_length)))
return RESULT_ERR_OUT_OF_RANGE; // value out of range
if (dvalue < 0 && m_bitCount != 32)
value = (unsigned int)(dvalue + (1 << m_bitCount));
value = (int)(dvalue + (1 << m_bitCount));
else
value = (unsigned int)dvalue;
value = (int)dvalue;
} else {
dvalue = round(dvalue);
if (dvalue < 0.0 || dvalue >= (1LL << (8 * m_length)))
return RESULT_ERR_OUT_OF_RANGE; // value out of range
value = (unsigned int) dvalue;
value = (unsigned int)dvalue;
}
}