lucene-java-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From markrmil...@apache.org
Subject svn commit: r785238 - in /lucene/java/trunk: CHANGES.txt src/java/org/apache/lucene/search/function/DocValues.java src/test/org/apache/lucene/search/function/TestDocValues.java
Date Tue, 16 Jun 2009 14:49:18 GMT
Author: markrmiller
Date: Tue Jun 16 14:49:18 2009
New Revision: 785238

URL: http://svn.apache.org/viewvc?rev=785238&view=rev
Log:
LUCENE-1681: Fix infinite loop caused by a call to DocValues methods getMinValue, getMaxValue,
getAverageValue.

Added:
    lucene/java/trunk/src/test/org/apache/lucene/search/function/TestDocValues.java
Modified:
    lucene/java/trunk/CHANGES.txt
    lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java

Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?rev=785238&r1=785237&r2=785238&view=diff
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Tue Jun 16 14:49:18 2009
@@ -266,6 +266,9 @@
     on EOF, removed numeric overflow possibilities and added support
     for a hack to unmap the buffers on closing IndexInput.
     (Uwe Schindler)
+    
+16. LUCENE-1681: Fix infinite loop caused by a call to DocValues methods 
+    getMinValue, getMaxValue, getAverageValue. (Simon Willnauer via Mark Miller)
 
  New features
 

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java?rev=785238&r1=785237&r2=785238&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java Tue Jun 16
14:49:18 2009
@@ -114,17 +114,15 @@
   }
 
   // --- some simple statistics on values
-  private float minVal;
-  private float maxVal;
-  private float avgVal;
+  private float minVal = Float.NaN;
+  private float maxVal = Float.NaN;
+  private float avgVal = Float.NaN;
   private boolean computed=false;
   // compute optional values
-  private void compute () {
+  private void compute() {
     if (computed) {
       return;
     }
-    minVal = Float.MAX_VALUE;
-    maxVal = 0;
     float sum = 0;
     int n = 0;
     while (true) {
@@ -135,34 +133,56 @@
         break;
       }
       sum += val;
-      minVal = Math.min(minVal,val);
-      maxVal = Math.max(maxVal,val);
+      minVal = Float.isNaN(minVal) ? val : Math.min(minVal, val);
+      maxVal = Float.isNaN(maxVal) ? val : Math.max(maxVal, val);
+      ++n;
     }
-    avgVal = sum / n;
+
+    avgVal = n == 0 ? Float.NaN : sum / n;
     computed = true;
   }
+
   /**
-   * Optional op.
-   * Returns the minimum of all values.
+   * Returns the minimum of all values or <code>Float.NaN</code> if this
+   * DocValues instance does not contain any value.
+   * <p>
+   * This operation is optional
+   * </p>
+   * 
+   * @return the minimum of all values or <code>Float.NaN</code> if this
+   *         DocValues instance does not contain any value.
    */
-  public float getMinValue () {
+  public float getMinValue() {
     compute();
     return minVal;
   }
-  
+
   /**
-   * Optional op.
-   * Returns the maximum of all values. 
+   * Returns the maximum of all values or <code>Float.NaN</code> if this
+   * DocValues instance does not contain any value.
+   * <p>
+   * This operation is optional
+   * </p>
+   * 
+   * @return the maximum of all values or <code>Float.NaN</code> if this
+   *         DocValues instance does not contain any value.
    */
-  public float getMaxValue () {
+  public float getMaxValue() {
     compute();
     return maxVal;
   }
-  
+
   /**
-   * Returns the average of all values. 
+   * Returns the average of all values or <code>Float.NaN</code> if this
+   * DocValues instance does not contain any value. *
+   * <p>
+   * This operation is optional
+   * </p>
+   * 
+   * @return the average of all values or <code>Float.NaN</code> if this
+   *         DocValues instance does not contain any value
    */
-  public float getAverageValue () {
+  public float getAverageValue() {
     compute();
     return avgVal;
   }

Added: lucene/java/trunk/src/test/org/apache/lucene/search/function/TestDocValues.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/function/TestDocValues.java?rev=785238&view=auto
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/function/TestDocValues.java (added)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/function/TestDocValues.java Tue Jun
16 14:49:18 2009
@@ -0,0 +1,126 @@
+package org.apache.lucene.search.function;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * DocValues TestCase  
+ */
+public class TestDocValues extends LuceneTestCase {
+
+  /* @override constructor */
+  public TestDocValues(String name) {
+    super(name);
+  }
+
+  /* @override */
+  protected void tearDown() throws Exception {
+    super.tearDown();
+  }
+
+  /* @override */
+  protected void setUp() throws Exception {
+    // prepare a small index with just a few documents.
+    super.setUp();
+  }
+
+  public void testGetMinValue() {
+    float[] innerArray = new float[] { 1.0f, 2.0f, -1.0f, 100.0f };
+    DocValuesTestImpl docValues = new DocValuesTestImpl(innerArray);
+    assertEquals("-1.0f is the min value in the source array", -1.0f, docValues
+        .getMinValue());
+
+    // test with without values - NaN
+    innerArray = new float[] {};
+    docValues = new DocValuesTestImpl(innerArray);
+    assertTrue("max is NaN - no values in inner array", Float.isNaN(docValues
+        .getMinValue()));
+  }
+
+  public void testGetMaxValue() {
+    float[] innerArray = new float[] { 1.0f, 2.0f, -1.0f, 10.0f };
+    DocValuesTestImpl docValues = new DocValuesTestImpl(innerArray);
+    assertEquals("10.0f is the max value in the source array", 10.0f, docValues
+        .getMaxValue());
+
+    innerArray = new float[] { -3.0f, -1.0f, -100.0f };
+    docValues = new DocValuesTestImpl(innerArray);
+    assertEquals("-1.0f is the max value in the source array", -1.0f, docValues
+        .getMaxValue());
+
+    innerArray = new float[] { -3.0f, -1.0f, 100.0f, Float.MAX_VALUE,
+        Float.MAX_VALUE - 1 };
+    docValues = new DocValuesTestImpl(innerArray);
+    assertEquals(Float.MAX_VALUE + " is the max value in the source array",
+        Float.MAX_VALUE, docValues.getMaxValue());
+
+    // test with without values - NaN
+    innerArray = new float[] {};
+    docValues = new DocValuesTestImpl(innerArray);
+    assertTrue("max is NaN - no values in inner array", Float.isNaN(docValues
+        .getMaxValue()));
+  }
+
+  public void testGetAverageValue() {
+    float[] innerArray = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
+    DocValuesTestImpl docValues = new DocValuesTestImpl(innerArray);
+    assertEquals("the average is 1.0f", 1.0f, docValues.getAverageValue());
+
+    innerArray = new float[] { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
+    docValues = new DocValuesTestImpl(innerArray);
+    assertEquals("the average is 3.5f", 3.5f, docValues.getAverageValue());
+
+    // test with negative values
+    innerArray = new float[] { -1.0f, 2.0f };
+    docValues = new DocValuesTestImpl(innerArray);
+    assertEquals("the average is 0.5f", 0.5f, docValues.getAverageValue());
+
+    // test with without values - NaN
+    innerArray = new float[] {};
+    docValues = new DocValuesTestImpl(innerArray);
+    assertTrue("the average is NaN - no values in inner array", Float
+        .isNaN(docValues.getAverageValue()));
+  }
+
+  static class DocValuesTestImpl extends DocValues {
+    float[] innerArray;
+
+    DocValuesTestImpl(float[] innerArray) {
+      this.innerArray = innerArray;
+    }
+
+    /**
+     * @see org.apache.lucene.search.function.DocValues#floatVal(int)
+     */
+    /* @Override */
+    public float floatVal(int doc) {
+      return innerArray[doc];
+    }
+
+    /**
+     * @see org.apache.lucene.search.function.DocValues#toString(int)
+     */
+    /* @Override */
+    public String toString(int doc) {
+      return Integer.toString(doc);
+    }
+
+  }
+
+}
\ No newline at end of file



Mime
View raw message