mirror of
https://github.com/fluencelabs/redis
synced 2025-03-18 16:40:50 +00:00
Fast conversion of double when representable as long long
This commit is contained in:
parent
45290ad9bb
commit
672b0a1b25
@ -887,6 +887,7 @@ int stringmatchlen(const char *pattern, int patternLen,
|
||||
int stringmatch(const char *pattern, const char *string, int nocase);
|
||||
long long memtoll(const char *p, int *err);
|
||||
int ll2string(char *s, size_t len, long long value);
|
||||
int d2string(char *s, size_t len, double value);
|
||||
int isStringRepresentableAsLong(sds s, long *longval);
|
||||
int isStringRepresentableAsLongLong(sds s, long long *longval);
|
||||
int isObjectRepresentableAsLongLong(robj *o, long long *llongval);
|
||||
|
40
src/util.c
40
src/util.c
@ -1,6 +1,7 @@
|
||||
#include "redis.h"
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Glob-style pattern matching. */
|
||||
int stringmatchlen(const char *pattern, int patternLen,
|
||||
@ -200,6 +201,45 @@ int ll2string(char *s, size_t len, long long value) {
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Convert a double to a string representation. Returns the number of bytes
|
||||
* required. The representation should always be parsable by stdtod(3). */
|
||||
int d2string(char *buf, size_t len, double value) {
|
||||
if (isnan(value)) {
|
||||
len = snprintf(buf,len,"nan");
|
||||
} else if (isinf(value)) {
|
||||
if (value < 0)
|
||||
len = snprintf(buf,len,"-inf");
|
||||
else
|
||||
len = snprintf(buf,len,"inf");
|
||||
} else if (value == 0) {
|
||||
/* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */
|
||||
if (1.0/value < 0)
|
||||
len = snprintf(buf,len,"-0");
|
||||
else
|
||||
len = snprintf(buf,len,"0");
|
||||
} else {
|
||||
#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
|
||||
/* Check if the float is in a safe range to be casted into a
|
||||
* long long. We are assuming that long long is 64 bit here.
|
||||
* Also we are assuming that there are no implementations around where
|
||||
* double has precision < 52 bit.
|
||||
*
|
||||
* Under this assumptions we test if a double is inside an interval
|
||||
* where casting to long long is safe. Then using two castings we
|
||||
* make sure the decimal part is zero. If all this is true we use
|
||||
* integer printing function that is much faster. */
|
||||
double min = -4503599627370495; /* (2^52)-1 */
|
||||
double max = 4503599627370496; /* -(2^52) */
|
||||
if (val > min && val < max && value == ((double)((long long)value)))
|
||||
len = ll2string(buf,len,(long long)value);
|
||||
else
|
||||
#endif
|
||||
len = snprintf(buf,len,"%.17g",value);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Check if the sds string 's' can be represented by a long long
|
||||
* (that is, is a number that fits into long without any other space or
|
||||
* character before or after the digits, so that converting this number
|
||||
|
Loading…
x
Reference in New Issue
Block a user