001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.search.function;
017:
018: import org.apache.lucene.index.IndexReader;
019:
020: import java.io.IOException;
021:
022: /**
023: * <code>ReciprocalFloatFunction</code> implements a reciprocal function f(x) = a/(mx+b), based on
024: * the float value of a field as exported by {@link org.apache.solr.search.function.ValueSource}.
025: * <br>
026: *
027: * When a and b are equal, and x>=0, this function has a maximum value of 1 that drops as x increases.
028: * Increasing the value of a and b together results in a movement of the entire function to a flatter part of the curve.
029: * <br>These properties make this an idea function for boosting more recent documents.
030: * <br>Example:<code>ReciprocalFloatFunction(new ReverseOrdFieldSource("my_date"),1,1000,1000)</code>
031: *
032: * @see FunctionQuery
033: *
034: *
035: * @author yonik
036: * @version $Id: ReciprocalFloatFunction.java 472574 2006-11-08 18:25:52Z yonik $
037: */
038: public class ReciprocalFloatFunction extends ValueSource {
039: protected final ValueSource source;
040: protected final float m;
041: protected final float a;
042: protected final float b;
043:
044: /**
045: * f(source) = a/(m*float(source)+b)
046: */
047: public ReciprocalFloatFunction(ValueSource source, float m,
048: float a, float b) {
049: this .source = source;
050: this .m = m;
051: this .a = a;
052: this .b = b;
053: }
054:
055: public DocValues getValues(IndexReader reader) throws IOException {
056: final DocValues vals = source.getValues(reader);
057: return new DocValues() {
058: public float floatVal(int doc) {
059: return a / (m * vals.floatVal(doc) + b);
060: }
061:
062: public int intVal(int doc) {
063: return (int) floatVal(doc);
064: }
065:
066: public long longVal(int doc) {
067: return (long) floatVal(doc);
068: }
069:
070: public double doubleVal(int doc) {
071: return (double) floatVal(doc);
072: }
073:
074: public String strVal(int doc) {
075: return Float.toString(floatVal(doc));
076: }
077:
078: public String toString(int doc) {
079: return Float.toString(a) + "/(" + m + "*float("
080: + vals.toString(doc) + ')' + '+' + b + ')';
081: }
082: };
083: }
084:
085: public String description() {
086: return Float.toString(a) + "/(" + m + "*float("
087: + source.description() + ")" + "+" + b + ')';
088: }
089:
090: public int hashCode() {
091: int h = Float.floatToIntBits(a) + Float.floatToIntBits(m);
092: h ^= (h << 13) | (h >>> 20);
093: return h + (Float.floatToIntBits(b)) + source.hashCode();
094: }
095:
096: public boolean equals(Object o) {
097: if (ReciprocalFloatFunction.class != o.getClass())
098: return false;
099: ReciprocalFloatFunction other = (ReciprocalFloatFunction) o;
100: return this.m == other.m && this.a == other.a
101: && this.b == other.b
102: && this.source.equals(other.source);
103: }
104: }
|