Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23e3ba53 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 778a616f: am 7c964e78: Merge changes I39804ee6,I6a5a7ea2 into jb-mr1-dev

* commit '778a616f':
  Use spline interpolation for auto-brightness.
  Add FloatMath.hypot.
parents 16296450 778a616f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22876,6 +22876,7 @@ package android.util {
    method public static float cos(float);
    method public static float exp(float);
    method public static float floor(float);
    method public static float hypot(float, float);
    method public static float sin(float);
    method public static float sqrt(float);
  }
+10 −0
Original line number Diff line number Diff line
@@ -80,4 +80,14 @@ public class FloatMath {
     * @return the exponential of value
     */
    public static native float exp(float value);

    /**
     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
     * {@code y}</i><sup>{@code 2}</sup>{@code )}.
     *
     * @param x a float number
     * @param y a float number
     * @return the hypotenuse
     */
    public static native float hypot(float x, float y);
}
+156 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed 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.
 */

package android.util;

/**
 * Performs spline interpolation given a set of control points.
 * @hide
 */
public final class Spline {
    private final float[] mX;
    private final float[] mY;
    private final float[] mM;

    private Spline(float[] x, float[] y, float[] m) {
        mX = x;
        mY = y;
        mM = m;
    }

    /**
     * Creates a monotone cubic spline from a given set of control points.
     *
     * The spline is guaranteed to pass through each control point exactly.
     * Moreover, assuming the control points are monotonic (Y is non-decreasing or
     * non-increasing) then the interpolated values will also be monotonic.
     *
     * This function uses the Fritsch-Carlson method for computing the spline parameters.
     * http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
     *
     * @param x The X component of the control points, strictly increasing.
     * @param y The Y component of the control points, monotonic.
     * @return
     *
     * @throws IllegalArgumentException if the X or Y arrays are null, have
     * different lengths or have fewer than 2 values.
     * @throws IllegalArgumentException if the control points are not monotonic.
     */
    public static Spline createMonotoneCubicSpline(float[] x, float[] y) {
        if (x == null || y == null || x.length != y.length || x.length < 2) {
            throw new IllegalArgumentException("There must be at least two control "
                    + "points and the arrays must be of equal length.");
        }

        final int n = x.length;
        float[] d = new float[n - 1]; // could optimize this out
        float[] m = new float[n];

        // Compute slopes of secant lines between successive points.
        for (int i = 0; i < n - 1; i++) {
            float h = x[i + 1] - x[i];
            if (h <= 0f) {
                throw new IllegalArgumentException("The control points must all "
                        + "have strictly increasing X values.");
            }
            d[i] = (y[i + 1] - y[i]) / h;
        }

        // Initialize the tangents as the average of the secants.
        m[0] = d[0];
        for (int i = 1; i < n - 1; i++) {
            m[i] = (d[i - 1] + d[i]) * 0.5f;
        }
        m[n - 1] = d[n - 2];

        // Update the tangents to preserve monotonicity.
        for (int i = 0; i < n - 1; i++) {
            if (d[i] == 0f) { // successive Y values are equal
                m[i] = 0f;
                m[i + 1] = 0f;
            } else {
                float a = m[i] / d[i];
                float b = m[i + 1] / d[i];
                if (a < 0f || b < 0f) {
                    throw new IllegalArgumentException("The control points must have "
                            + "monotonic Y values.");
                }
                float h = FloatMath.hypot(a, b);
                if (h > 9f) {
                    float t = 3f / h;
                    m[i] = t * a * d[i];
                    m[i + 1] = t * b * d[i];
                }
            }
        }
        return new Spline(x, y, m);
    }

    /**
     * Interpolates the value of Y = f(X) for given X.
     * Clamps X to the domain of the spline.
     *
     * @param x The X value.
     * @return The interpolated Y = f(X) value.
     */
    public float interpolate(float x) {
        // Handle the boundary cases.
        final int n = mX.length;
        if (Float.isNaN(x)) {
            return x;
        }
        if (x <= mX[0]) {
            return mY[0];
        }
        if (x >= mX[n - 1]) {
            return mY[n - 1];
        }

        // Find the index 'i' of the last point with smaller X.
        // We know this will be within the spline due to the boundary tests.
        int i = 0;
        while (x >= mX[i + 1]) {
            i += 1;
            if (x == mX[i]) {
                return mY[i];
            }
        }

        // Perform cubic Hermite spline interpolation.
        float h = mX[i + 1] - mX[i];
        float t = (x - mX[i]) / h;
        return (mY[i] * (1 + 2 * t) + h * mM[i] * t) * (1 - t) * (1 - t)
                + (mY[i + 1] * (3 - 2 * t) + h * mM[i + 1] * (t - 1)) * t * t;
    }

    // For debugging.
    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        final int n = mX.length;
        str.append("[");
        for (int i = 0; i < n; i++) {
            if (i != 0) {
                str.append(", ");
            }
            str.append("(").append(mX[i]);
            str.append(", ").append(mY[i]);
            str.append(": ").append(mM[i]).append(")");
        }
        str.append("]");
        return str.toString();
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -29,6 +29,10 @@ public:
    static float ExpF(JNIEnv* env, jobject clazz, float x) {
        return expf(x);
    }

    static float HypotF(JNIEnv* env, jobject clazz, float x, float y) {
        return hypotf(x, y);
    }
};

static JNINativeMethod gMathUtilsMethods[] = {
@@ -38,6 +42,7 @@ static JNINativeMethod gMathUtilsMethods[] = {
    {"cos", "(F)F", (void*) MathUtilsGlue::CosF},
    {"sqrt", "(F)F", (void*) MathUtilsGlue::SqrtF},
    {"exp", "(F)F", (void*) MathUtilsGlue::ExpF},
    {"hypot", "(FF)F", (void*) MathUtilsGlue::HypotF},
};

int register_android_util_FloatMath(JNIEnv* env)
+17 −5
Original line number Diff line number Diff line
@@ -533,13 +533,22 @@
    <integer name="config_longPressOnHomeBehavior">2</integer>

    <!-- Array of light sensor LUX values to define our levels for auto backlight brightness support.
         The N entries of this array define N + 1 zones as follows:
         The N entries of this array define N + 1 control points as follows:

         Zone 0:        0 <= LUX < array[0]
         Zone 1:        array[0] <= LUX < array[1]
         Point 1:        LUX <= 0 (implicit)
         Point 2:        0 < level[1] == LUX < level[2]
         ...
         Zone N:        array[N - 1] <= LUX < array[N]
         Zone N + 1:    array[N] <= LUX < infinity
         Point N:        level[N - 1] == LUX < level[N]
         Point N + 1:    level[N] <= LUX < infinity

         The control points must be strictly increasing.  Each control point
         corresponds to an entry in the brightness backlight values arrays.
         For example, if LUX == level[1] (first element of the levels array)
         then the brightness will be determined by value[1] (first element
         of the brightness values array).

         Spline interpolation is used to determine the auto-brightness
         backlight values for LUX levels between these control points.

         Must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessLevels">
@@ -552,6 +561,7 @@
    <!-- Array of output values for LCD backlight corresponding to the LUX values
         in the config_autoBrightnessLevels array.  This array should have size one greater
         than the size of the config_autoBrightnessLevels array.
         The brightness values must be between 0 and 255 and be non-decreasing.
         This must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessLcdBacklightValues">
    </integer-array>
@@ -559,6 +569,7 @@
    <!-- Array of output values for button backlight corresponding to the LUX values
         in the config_autoBrightnessLevels array.  This array should have size one greater
         than the size of the config_autoBrightnessLevels array.
         The brightness values must be between 0 and 255 and be non-decreasing.
         This must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessButtonBacklightValues">
    </integer-array>
@@ -566,6 +577,7 @@
    <!-- Array of output values for keyboard backlight corresponding to the LUX values
         in the config_autoBrightnessLevels array.  This array should have size one greater
         than the size of the config_autoBrightnessLevels array.
         The brightness values must be between 0 and 255 and be non-decreasing.
         This must be overridden in platform specific overlays -->
    <integer-array name="config_autoBrightnessKeyboardBacklightValues">
    </integer-array>
Loading