]> git.saurik.com Git - redis.git/commitdiff
Fix ZUNIONSTORE/ZINTERSTORE to never store a NaN score.
authorPieter Noordhuis <pcnoordhuis@gmail.com>
Thu, 29 Jul 2010 19:31:58 +0000 (21:31 +0200)
committerPieter Noordhuis <pcnoordhuis@gmail.com>
Thu, 29 Jul 2010 21:03:11 +0000 (23:03 +0200)
When +inf and -inf are added, the result is NaN. We don't want NaN
scores in a sorted set, so agreed on the result of this operation being
zero.

src/t_zset.c
tests/unit/type/zset.tcl

index 8efe3c2a4005057f7e3934232dc792b7c1a2df99..a85a9dc179f5f285900633307822dfe188603789 100644 (file)
@@ -541,6 +541,10 @@ int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) {
 inline static void zunionInterAggregate(double *target, double val, int aggregate) {
     if (aggregate == REDIS_AGGR_SUM) {
         *target = *target + val;
+        /* The result of adding two doubles is NaN when one variable
+         * is +inf and the other is -inf. When these numbers are added,
+         * we maintain the convention of the result being 0.0. */
+        if (isnan(*target)) *target = 0.0;
     } else if (aggregate == REDIS_AGGR_MIN) {
         *target = val < *target ? val : *target;
     } else if (aggregate == REDIS_AGGR_MAX) {
index da26484578a75c9bcedca818537d0143c3886b3b..a289d88372b97463b2a7c38e1e9dc2620b524300 100644 (file)
@@ -433,6 +433,30 @@ start_server {tags {"zset"}} {
         list [r zinterstore zsetc 2 zseta zsetb aggregate max] [r zrange zsetc 0 -1 withscores]
     } {2 {b 2 c 3}}
     
+    foreach cmd {ZUNIONSTORE ZINTERSTORE} {
+        test "$cmd with +inf/-inf scores" {
+            r zadd zsetinf1 +inf key
+            r zadd zsetinf2 +inf key
+            r $cmd zsetinf3 2 zsetinf1 zsetinf2
+            assert_equal inf [r zscore zsetinf3 key]
+
+            r zadd zsetinf1 -inf key
+            r zadd zsetinf2 +inf key
+            r $cmd zsetinf3 2 zsetinf1 zsetinf2
+            assert_equal 0 [r zscore zsetinf3 key]
+
+            r zadd zsetinf1 +inf key
+            r zadd zsetinf2 -inf key
+            r $cmd zsetinf3 2 zsetinf1 zsetinf2
+            assert_equal 0 [r zscore zsetinf3 key]
+
+            r zadd zsetinf1 -inf key
+            r zadd zsetinf2 -inf key
+            r $cmd zsetinf3 2 zsetinf1 zsetinf2
+            assert_equal -inf [r zscore zsetinf3 key]
+        }
+    }
+
     tags {"slow"} {
         test {ZSETs skiplist implementation backlink consistency test} {
             set diff 0