summaryrefslogtreecommitdiffstats
path: root/src/storage_number.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/storage_number.c')
-rw-r--r--src/storage_number.c76
1 files changed, 65 insertions, 11 deletions
diff --git a/src/storage_number.c b/src/storage_number.c
index 27fe5f2c7..054941202 100644
--- a/src/storage_number.c
+++ b/src/storage_number.c
@@ -2,12 +2,13 @@
extern char *print_number_lu_r(char *str, unsigned long uvalue);
extern char *print_number_llu_r(char *str, unsigned long long uvalue);
+extern char *print_number_llu_r_smart(char *str, unsigned long long uvalue);
storage_number pack_storage_number(calculated_number value, uint32_t flags)
{
// bit 32 = sign 0:positive, 1:negative
// bit 31 = 0:divide, 1:multiply
- // bit 30, 29, 28 = (multiplier or divider) 0-6 (7 total)
+ // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total)
// bit 27, 26, 25 flags
// bit 24 to bit 1 = the value
@@ -105,6 +106,7 @@ calculated_number unpack_storage_number(storage_number value)
return n;
}
+/*
int print_calculated_number(char *str, calculated_number value)
{
char *wstr = str;
@@ -113,21 +115,14 @@ int print_calculated_number(char *str, calculated_number value)
if(sign) value = -value;
#ifdef STORAGE_WITH_MATH
- // without llrint() there are rounding problems
+ // without llrintl() there are rounding problems
// for example 0.9 becomes 0.89
- unsigned long long uvalue = (unsigned long long int) llrint(value * (calculated_number)100000);
+ unsigned long long uvalue = (unsigned long long int) llrintl(value * (calculated_number)100000);
#else
unsigned long long uvalue = value * (calculated_number)100000;
#endif
-#ifdef ENVIRONMENT32
- if(uvalue > (unsigned long long)0xffffffff)
- wstr = print_number_llu_r(str, uvalue);
- else
- wstr = print_number_lu_r(str, uvalue);
-#else
- do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
-#endif
+ wstr = print_number_llu_r_smart(str, uvalue);
// make sure we have 6 bytes at least
while((wstr - str) < 6) *wstr++ = '0';
@@ -166,3 +161,62 @@ int print_calculated_number(char *str, calculated_number value)
// return the buffer length
return (int) ((wstr - str) + 2 + decimal );
}
+*/
+
+int print_calculated_number(char *str, calculated_number value) {
+ char integral_str[50], fractional_str[50];
+
+ char *wstr = str;
+
+ if(unlikely(value < 0)) {
+ *wstr++ = '-';
+ value = -value;
+ }
+
+ calculated_number integral, fractional;
+
+#ifdef STORAGE_WITH_MATH
+ fractional = modfl(value, &integral) * 10000000.0;
+#else
+ fractional = ((unsigned long long)(value * 10000000ULL) % 10000000ULL);
+#endif
+
+ char *istre;
+ if(integral == 0.0) {
+ integral_str[0] = '0';
+ istre = &integral_str[1];
+ }
+ else
+ // convert the integral part to string (reversed)
+ istre = print_number_llu_r_smart(integral_str, (unsigned long long)integral);
+
+ // copy reversed the integral string
+ istre--;
+ while( istre >= integral_str ) *wstr++ = *istre--;
+
+ if(fractional != 0.0) {
+ // add a dot
+ *wstr++ = '.';
+
+ // convert the fractional part to string (reversed)
+ char *fstre = print_number_llu_r_smart(fractional_str, (unsigned long long)calculated_number_llrint(fractional));
+
+ // prepend zeros to reach 7 digits length
+ int decimal = 7;
+ int len = (int)(fstre - fractional_str);
+ while(len < decimal) {
+ *wstr++ = '0';
+ len++;
+ }
+
+ char *begin = fractional_str;
+ while(begin < fstre && *begin == '0') begin++;
+
+ // copy reversed the fractional string
+ fstre--;
+ while( fstre >= begin ) *wstr++ = *fstre--;
+ }
+
+ *wstr = '\0';
+ return (int)(wstr - str);
+}