/*
 * Copyright (C) 2018 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.
 */

#define LOG_TAG "Camera3-DistMapper"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0

#include <algorithm>
#include <cmath>

#include "device3/DistortionMapper.h"
#include "utils/SessionConfigurationUtilsHost.h"

namespace android {

namespace camera3 {

DistortionMapper::DistortionMapper() {
    initRemappedKeys();
}

void DistortionMapper::initRemappedKeys() {
    mRemappedKeys.insert(
            kMeteringRegionsToCorrect.begin(),
            kMeteringRegionsToCorrect.end());
    mRemappedKeys.insert(
            kRectsToCorrect.begin(),
            kRectsToCorrect.end());
    mRemappedKeys.insert(
            kResultPointsToCorrectNoClamp.begin(),
            kResultPointsToCorrectNoClamp.end());
    mRemappedKeys.insert(ANDROID_DISTORTION_CORRECTION_MODE);
    if (flags::concert_mode()) {
        mRemappedKeys.insert(ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION);
    }
}

bool DistortionMapper::isDistortionSupported(const CameraMetadata &deviceInfo) {
    bool isDistortionCorrectionSupported = false;
    camera_metadata_ro_entry_t distortionCorrectionModes =
            deviceInfo.find(ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES);
    for (size_t i = 0; i < distortionCorrectionModes.count; i++) {
        if (distortionCorrectionModes.data.u8[i] !=
                ANDROID_DISTORTION_CORRECTION_MODE_OFF) {
            isDistortionCorrectionSupported = true;
            break;
        }
    }
    return isDistortionCorrectionSupported;
}

status_t DistortionMapper::setupStaticInfo(const CameraMetadata &deviceInfo) {
    std::lock_guard<std::mutex> lock(mMutex);
    status_t res = setupStaticInfoLocked(deviceInfo, /*maxResolution*/false);
    if (res != OK) {
        return res;
    }

    bool mMaxResolution = SessionConfigurationUtils::supportsUltraHighResolutionCapture(deviceInfo);
    if (mMaxResolution) {
        res = setupStaticInfoLocked(deviceInfo, /*maxResolution*/true);
    }
    return res;
}

status_t DistortionMapper::setupStaticInfoLocked(const CameraMetadata &deviceInfo,
        bool maxResolution) {
    DistortionMapperInfo *mapperInfo = maxResolution ? &mDistortionMapperInfoMaximumResolution :
            &mDistortionMapperInfo;

    camera_metadata_ro_entry_t array;

    array = deviceInfo.find(
        SessionConfigurationUtils::getAppropriateModeTag(
                ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, maxResolution));
    if (array.count != 4) return BAD_VALUE;

    float arrayX = static_cast<float>(array.data.i32[0]);
    float arrayY = static_cast<float>(array.data.i32[1]);
    mapperInfo->mArrayWidth = static_cast<float>(array.data.i32[2]);
    mapperInfo->mArrayHeight = static_cast<float>(array.data.i32[3]);

    array = deviceInfo.find(
            SessionConfigurationUtils::getAppropriateModeTag(
                    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, maxResolution));
    if (array.count != 4) return BAD_VALUE;

    float activeX = static_cast<float>(array.data.i32[0]);
    float activeY = static_cast<float>(array.data.i32[1]);
    mapperInfo->mActiveWidth = static_cast<float>(array.data.i32[2]);
    mapperInfo->mActiveHeight = static_cast<float>(array.data.i32[3]);

    mapperInfo->mArrayDiffX = activeX - arrayX;
    mapperInfo->mArrayDiffY = activeY - arrayY;

    return updateCalibration(deviceInfo, /*isStatic*/ true, maxResolution);
}

static bool doesSettingsHaveMaxResolution(const CameraMetadata *settings) {
    if (settings == nullptr) {
        return false;
    }
    // First we get the sensorPixelMode from the settings metadata.
    camera_metadata_ro_entry sensorPixelModeEntry = settings->find(ANDROID_SENSOR_PIXEL_MODE);
    if (sensorPixelModeEntry.count != 0) {
        return (sensorPixelModeEntry.data.u8[0] == ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
    }
    return false;
}

bool DistortionMapper::calibrationValid() const {
    std::lock_guard<std::mutex> lock(mMutex);
    bool isValid =  mDistortionMapperInfo.mValidMapping;
    if (mMaxResolution) {
        isValid = isValid && mDistortionMapperInfoMaximumResolution.mValidMapping;
    }
    return isValid;
}

status_t DistortionMapper::correctCaptureRequest(CameraMetadata *request) {
    std::lock_guard<std::mutex> lock(mMutex);
    status_t res;

    bool maxResolution = doesSettingsHaveMaxResolution(request);
    DistortionMapperInfo *mapperInfo = maxResolution ? &mDistortionMapperInfoMaximumResolution :
            &mDistortionMapperInfo;

    if (!mapperInfo->mValidMapping) return OK;

    camera_metadata_entry_t e;
    e = request->find(ANDROID_DISTORTION_CORRECTION_MODE);
    if (e.count != 0 && e.data.u8[0] != ANDROID_DISTORTION_CORRECTION_MODE_OFF) {
        for (auto region : kMeteringRegionsToCorrect) {
            e = request->find(region);
            for (size_t j = 0; j < e.count; j += 5) {
                int32_t weight = e.data.i32[j + 4];
                if (weight == 0) {
                    continue;
                }
                res = mapCorrectedToRaw(e.data.i32 + j, 2, mapperInfo, /*clamp*/true);
                if (res != OK) return res;
            }
        }
        for (auto rect : kRectsToCorrect) {
            e = request->find(rect);
            res = mapCorrectedRectToRaw(e.data.i32, e.count / 4, mapperInfo, /*clamp*/true);
            if (res != OK) return res;
        }
    }
    return OK;
}

status_t DistortionMapper::correctCaptureResult(CameraMetadata *result) {
    std::lock_guard<std::mutex> lock(mMutex);

    bool maxResolution = doesSettingsHaveMaxResolution(result);
    DistortionMapperInfo *mapperInfo = maxResolution ? &mDistortionMapperInfoMaximumResolution :
            &mDistortionMapperInfo;
    status_t res;

    if (!mapperInfo->mValidMapping) return OK;

    res = updateCalibration(*result, /*isStatic*/ false, maxResolution);
    if (res != OK) {
        ALOGE("Failure to update lens calibration information");
        return INVALID_OPERATION;
    }

    camera_metadata_entry_t e;
    e = result->find(ANDROID_DISTORTION_CORRECTION_MODE);
    if (e.count != 0 && e.data.u8[0] != ANDROID_DISTORTION_CORRECTION_MODE_OFF) {
        for (auto region : kMeteringRegionsToCorrect) {
            e = result->find(region);
            for (size_t j = 0; j < e.count; j += 5) {
                int32_t weight = e.data.i32[j + 4];
                if (weight == 0) {
                    continue;
                }
                res = mapRawToCorrected(e.data.i32 + j, 2, mapperInfo, /*clamp*/true);
                if (res != OK) return res;
            }
        }
        for (auto rect : kRectsToCorrect) {
            e = result->find(rect);
            res = mapRawRectToCorrected(e.data.i32, e.count / 4, mapperInfo, /*clamp*/true);
            if (res != OK) return res;
        }
        for (auto pts : kResultPointsToCorrectNoClamp) {
            e = result->find(pts);
            res = mapRawToCorrected(e.data.i32, e.count / 2, mapperInfo, /*clamp*/false);
            if (res != OK) return res;
        }
    }

    return OK;
}

// Utility methods; not guarded by mutex

status_t DistortionMapper::updateCalibration(const CameraMetadata &result, bool isStatic,
        bool maxResolution) {
    camera_metadata_ro_entry_t calib, distortion;
    DistortionMapperInfo *mapperInfo =
            maxResolution ? &mDistortionMapperInfoMaximumResolution : &mDistortionMapperInfo;
    // We only need maximum resolution version of LENS_INTRINSIC_CALIBRATION and
    // LENS_DISTORTION since CaptureResults would still use the same key
    // regardless of sensor pixel mode.
    int calibrationKey =
        SessionConfigurationUtils::getAppropriateModeTag(ANDROID_LENS_INTRINSIC_CALIBRATION,
                maxResolution && isStatic);
    int distortionKey =
        SessionConfigurationUtils::getAppropriateModeTag(ANDROID_LENS_DISTORTION,
                maxResolution && isStatic);

    calib = result.find(calibrationKey);
    distortion = result.find(distortionKey);

    if (calib.count != 5) return BAD_VALUE;
    if (distortion.count != 5) return BAD_VALUE;

    // Skip redoing work if no change to calibration fields
    if (mapperInfo->mValidMapping &&
            mapperInfo->mFx == calib.data.f[0] &&
            mapperInfo->mFy == calib.data.f[1] &&
            mapperInfo->mCx == calib.data.f[2] &&
            mapperInfo->mCy == calib.data.f[3] &&
            mapperInfo->mS == calib.data.f[4]) {
        bool noChange = true;
        for (size_t i = 0; i < distortion.count; i++) {
            if (mapperInfo->mK[i] != distortion.data.f[i]) {
                noChange = false;
                break;
            }
        }
        if (noChange) return OK;
    }

    mapperInfo->mFx = calib.data.f[0];
    mapperInfo->mFy = calib.data.f[1];
    mapperInfo->mCx = calib.data.f[2];
    mapperInfo->mCy = calib.data.f[3];
    mapperInfo->mS = calib.data.f[4];

    mapperInfo->mInvFx = 1 / mapperInfo->mFx;
    mapperInfo->mInvFy = 1 / mapperInfo->mFy;

    for (size_t i = 0; i < distortion.count; i++) {
        mapperInfo->mK[i] = distortion.data.f[i];
    }

    mapperInfo->mValidMapping = true;
    // Need to recalculate grid
    mapperInfo->mValidGrids = false;

    return OK;
}

status_t DistortionMapper::mapRawToCorrected(int32_t *coordPairs, int coordCount,
        DistortionMapperInfo *mapperInfo, bool clamp, bool simple) {
    if (!mapperInfo->mValidMapping) return INVALID_OPERATION;

    if (simple) return mapRawToCorrectedSimple(coordPairs, coordCount, mapperInfo, clamp);

    if (!mapperInfo->mValidGrids) {
        status_t res = buildGrids(mapperInfo);
        if (res != OK) return res;
    }

    for (int i = 0; i < coordCount * 2; i += 2) {
        const GridQuad *quad = findEnclosingQuad(coordPairs + i, mapperInfo->mDistortedGrid);
        if (quad == nullptr) {
            ALOGE("Raw to corrected mapping failure: No quad found for (%d, %d)",
                    *(coordPairs + i), *(coordPairs + i + 1));
            return INVALID_OPERATION;
        }
        ALOGV("src xy: %d, %d, enclosing quad: (%f, %f), (%f, %f), (%f, %f), (%f, %f)",
                coordPairs[i], coordPairs[i+1],
                quad->coords[0], quad->coords[1],
                quad->coords[2], quad->coords[3],
                quad->coords[4], quad->coords[5],
                quad->coords[6], quad->coords[7]);

        const GridQuad *corrQuad = quad->src;
        if (corrQuad == nullptr) {
            ALOGE("Raw to corrected mapping failure: No src quad found");
            return INVALID_OPERATION;
        }
        ALOGV("              corr quad: (%f, %f), (%f, %f), (%f, %f), (%f, %f)",
                corrQuad->coords[0], corrQuad->coords[1],
                corrQuad->coords[2], corrQuad->coords[3],
                corrQuad->coords[4], corrQuad->coords[5],
                corrQuad->coords[6], corrQuad->coords[7]);

        float u = calculateUorV(coordPairs + i, *quad, /*calculateU*/ true);
        float v = calculateUorV(coordPairs + i, *quad, /*calculateU*/ false);

        ALOGV("uv: %f, %f", u, v);

        // Interpolate along top edge of corrected quad (which are axis-aligned) for x
        float corrX = corrQuad->coords[0] + u * (corrQuad->coords[2] - corrQuad->coords[0]);
        // Interpolate along left edge of corrected quad (which are axis-aligned) for y
        float corrY = corrQuad->coords[1] + v * (corrQuad->coords[7] - corrQuad->coords[1]);

        // Clamp to within active array
        if (clamp) {
            corrX = std::min(mapperInfo->mActiveWidth - 1, std::max(0.f, corrX));
            corrY = std::min(mapperInfo->mActiveHeight - 1, std::max(0.f, corrY));
        }

        coordPairs[i] = static_cast<int32_t>(std::round(corrX));
        coordPairs[i + 1] = static_cast<int32_t>(std::round(corrY));
    }

    return OK;
}

status_t DistortionMapper::mapRawToCorrectedSimple(int32_t *coordPairs, int coordCount,
       const DistortionMapperInfo *mapperInfo, bool clamp) const {
    if (!mapperInfo->mValidMapping) return INVALID_OPERATION;

    float scaleX = mapperInfo->mActiveWidth / mapperInfo->mArrayWidth;
    float scaleY = mapperInfo->mActiveHeight / mapperInfo->mArrayHeight;
    for (int i = 0; i < coordCount * 2; i += 2) {
        float x = coordPairs[i];
        float y = coordPairs[i + 1];
        float corrX = x * scaleX;
        float corrY = y * scaleY;
        if (clamp) {
            corrX = std::min(mapperInfo->mActiveWidth - 1, std::max(0.f, corrX));
            corrY = std::min(mapperInfo->mActiveHeight - 1, std::max(0.f, corrY));
        }
        coordPairs[i] = static_cast<int32_t>(std::round(corrX));
        coordPairs[i + 1] = static_cast<int32_t>(std::round(corrY));
    }

    return OK;
}

status_t DistortionMapper::mapRawRectToCorrected(int32_t *rects, int rectCount,
       DistortionMapperInfo *mapperInfo, bool clamp, bool simple) {
    if (!mapperInfo->mValidMapping) return INVALID_OPERATION;
    for (int i = 0; i < rectCount * 4; i += 4) {
        // Map from (l, t, width, height) to (l, t, r, b)
        int32_t coords[4] = {
            rects[i],
            rects[i + 1],
            rects[i] + rects[i + 2] - 1,
            rects[i + 1] + rects[i + 3] - 1
        };

        mapRawToCorrected(coords, 2, mapperInfo, clamp, simple);

        // Map back to (l, t, width, height)
        rects[i] = coords[0];
        rects[i + 1] = coords[1];
        rects[i + 2] = coords[2] - coords[0] + 1;
        rects[i + 3] = coords[3] - coords[1] + 1;
    }

    return OK;
}

status_t DistortionMapper::mapCorrectedToRaw(int32_t *coordPairs, int coordCount,
       const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const {
    return mapCorrectedToRawImpl(coordPairs, coordCount, mapperInfo, clamp, simple);
}

template<typename T>
status_t DistortionMapper::mapCorrectedToRawImpl(T *coordPairs, int coordCount,
       const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const {
    if (!mapperInfo->mValidMapping) return INVALID_OPERATION;

    if (simple) return mapCorrectedToRawImplSimple(coordPairs, coordCount, mapperInfo, clamp);

    float activeCx = mapperInfo->mCx - mapperInfo->mArrayDiffX;
    float activeCy = mapperInfo->mCy - mapperInfo->mArrayDiffY;
    for (int i = 0; i < coordCount * 2; i += 2) {
        // Move to normalized space from active array space
        float ywi = (coordPairs[i + 1] - activeCy) * mapperInfo->mInvFy;
        float xwi = (coordPairs[i] - activeCx - mapperInfo->mS * ywi) * mapperInfo->mInvFx;
        // Apply distortion model to calculate raw image coordinates
        const std::array<float, 5> &kK = mapperInfo->mK;
        float rSq = xwi * xwi + ywi * ywi;
        float Fr = 1.f + (kK[0] * rSq) + (kK[1] * rSq * rSq) + (kK[2] * rSq * rSq * rSq);
        float xc = xwi * Fr + (kK[3] * 2 * xwi * ywi) + kK[4] * (rSq + 2 * xwi * xwi);
        float yc = ywi * Fr + (kK[4] * 2 * xwi * ywi) + kK[3] * (rSq + 2 * ywi * ywi);
        // Move back to image space
        float xr = mapperInfo->mFx * xc + mapperInfo->mS * yc + mapperInfo->mCx;
        float yr = mapperInfo->mFy * yc + mapperInfo->mCy;
        // Clamp to within pre-correction active array
        if (clamp) {
            xr = std::min(mapperInfo->mArrayWidth - 1, std::max(0.f, xr));
            yr = std::min(mapperInfo->mArrayHeight - 1, std::max(0.f, yr));
        }

        coordPairs[i] = static_cast<T>(std::round(xr));
        coordPairs[i + 1] = static_cast<T>(std::round(yr));
    }
    return OK;
}

template<typename T>
status_t DistortionMapper::mapCorrectedToRawImplSimple(T *coordPairs, int coordCount,
       const DistortionMapperInfo *mapperInfo, bool clamp) const {
    if (!mapperInfo->mValidMapping) return INVALID_OPERATION;

    float scaleX = mapperInfo->mArrayWidth / mapperInfo->mActiveWidth;
    float scaleY = mapperInfo->mArrayHeight / mapperInfo->mActiveHeight;
    for (int i = 0; i < coordCount * 2; i += 2) {
        float x = coordPairs[i];
        float y = coordPairs[i + 1];
        float rawX = x * scaleX;
        float rawY = y * scaleY;
        if (clamp) {
            rawX = std::min(mapperInfo->mArrayWidth - 1, std::max(0.f, rawX));
            rawY = std::min(mapperInfo->mArrayHeight - 1, std::max(0.f, rawY));
        }
        coordPairs[i] = static_cast<T>(std::round(rawX));
        coordPairs[i + 1] = static_cast<T>(std::round(rawY));
    }

    return OK;
}

status_t DistortionMapper::mapCorrectedRectToRaw(int32_t *rects, int rectCount,
       const DistortionMapperInfo *mapperInfo, bool clamp, bool simple) const {
    if (!mapperInfo->mValidMapping) return INVALID_OPERATION;

    for (int i = 0; i < rectCount * 4; i += 4) {
        // Map from (l, t, width, height) to (l, t, r, b)
        int32_t coords[4] = {
            rects[i],
            rects[i + 1],
            rects[i] + rects[i + 2] - 1,
            rects[i + 1] + rects[i + 3] - 1
        };

        mapCorrectedToRaw(coords, 2, mapperInfo, clamp, simple);

        // Map back to (l, t, width, height)
        rects[i] = coords[0];
        rects[i + 1] = coords[1];
        rects[i + 2] = coords[2] - coords[0] + 1;
        rects[i + 3] = coords[3] - coords[1] + 1;
    }

    return OK;
}

status_t DistortionMapper::buildGrids(DistortionMapperInfo *mapperInfo) {
    if (mapperInfo->mCorrectedGrid.size() != kGridSize * kGridSize) {
        mapperInfo->mCorrectedGrid.resize(kGridSize * kGridSize);
        mapperInfo->mDistortedGrid.resize(kGridSize * kGridSize);
    }

    float gridMargin = mapperInfo->mArrayWidth * kGridMargin;
    float gridSpacingX = (mapperInfo->mArrayWidth + 2 * gridMargin) / kGridSize;
    float gridSpacingY = (mapperInfo->mArrayHeight + 2 * gridMargin) / kGridSize;

    size_t index = 0;
    float x = -gridMargin;
    for (size_t i = 0; i < kGridSize; i++, x += gridSpacingX) {
        float y = -gridMargin;
        for (size_t j = 0; j < kGridSize; j++, y += gridSpacingY, index++) {
            mapperInfo->mCorrectedGrid[index].src = nullptr;
            mapperInfo->mCorrectedGrid[index].coords = {
                x, y,
                x + gridSpacingX, y,
                x + gridSpacingX, y + gridSpacingY,
                x, y + gridSpacingY
            };
            mapperInfo->mDistortedGrid[index].src = &(mapperInfo->mCorrectedGrid[index]);
            mapperInfo->mDistortedGrid[index].coords = mapperInfo->mCorrectedGrid[index].coords;
            status_t res = mapCorrectedToRawImpl(mapperInfo->mDistortedGrid[index].coords.data(), 4,
                    mapperInfo, /*clamp*/false, /*simple*/false);
            if (res != OK) return res;
        }
    }

    mapperInfo->mValidGrids = true;
    return OK;
}

const DistortionMapper::GridQuad* DistortionMapper::findEnclosingQuad(
        const int32_t pt[2], const std::vector<GridQuad>& grid) {
    const float x = pt[0];
    const float y = pt[1];

    for (const GridQuad& quad : grid) {
        const float &x1 = quad.coords[0];
        const float &y1 = quad.coords[1];
        const float &x2 = quad.coords[2];
        const float &y2 = quad.coords[3];
        const float &x3 = quad.coords[4];
        const float &y3 = quad.coords[5];
        const float &x4 = quad.coords[6];
        const float &y4 = quad.coords[7];

        // Point-in-quad test:

        // Quad has corners P1-P4; if P is within the quad, then it is on the same side of all the
        // edges (or on top of one of the edges or corners), traversed in a consistent direction.
        // This means that the cross product of edge En = Pn->P(n+1 mod 4) and line Ep = Pn->P must
        // have the same sign (or be zero) for all edges.
        // For clockwise traversal, the sign should be negative or zero for Ep x En, indicating that
        // En is to the left of Ep, or overlapping.
        float s1 = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1);
        if (s1 > 0) continue;
        float s2 = (x - x2) * (y3 - y2) - (y - y2) * (x3 - x2);
        if (s2 > 0) continue;
        float s3 = (x - x3) * (y4 - y3) - (y - y3) * (x4 - x3);
        if (s3 > 0) continue;
        float s4 = (x - x4) * (y1 - y4) - (y - y4) * (x1 - x4);
        if (s4 > 0) continue;

        return &quad;
    }
    return nullptr;
}

float DistortionMapper::calculateUorV(const int32_t pt[2], const GridQuad& quad, bool calculateU) {
    const float x = pt[0];
    const float y = pt[1];
    const float &x1 = quad.coords[0];
    const float &y1 = quad.coords[1];
    const float &x2 = calculateU ? quad.coords[2] : quad.coords[6];
    const float &y2 = calculateU ? quad.coords[3] : quad.coords[7];
    const float &x3 = quad.coords[4];
    const float &y3 = quad.coords[5];
    const float &x4 = calculateU ? quad.coords[6] : quad.coords[2];
    const float &y4 = calculateU ? quad.coords[7] : quad.coords[3];

    float a = (x1 - x2) * (y1 - y2 + y3 - y4) - (y1 - y2) * (x1 - x2 + x3 - x4);
    float b = (x - x1) * (y1 - y2 + y3 - y4) + (x1 - x2) * (y4 - y1) -
              (y - y1) * (x1 - x2 + x3 - x4) - (y1 - y2) * (x4 - x1);
    float c = (x - x1) * (y4 - y1) - (y - y1) * (x4 - x1);

    if (a == 0) {
        // One solution may happen if edges are parallel
        float u0 = -c / b;
        ALOGV("u0: %.9g, b: %f, c: %f", u0, b, c);
        return u0;
    }

    float det = b * b - 4 * a * c;
    if (det < 0) {
        // Validation check - should not happen if pt is within the quad
        ALOGE("Bad determinant! a: %f, b: %f, c: %f, det: %f", a,b,c,det);
        return -1;
    }

    // Select more numerically stable solution
    float sqdet = b > 0 ? -std::sqrt(det) : std::sqrt(det);

    float u1 = (-b + sqdet) / (2 * a);
    ALOGV("u1: %.9g", u1);
    if (0 - kFloatFuzz < u1 && u1 < 1 + kFloatFuzz) return u1;

    float u2 = c / (a * u1);
    ALOGV("u2: %.9g", u2);
    if (0 - kFloatFuzz < u2 && u2 < 1 + kFloatFuzz) return u2;

    // Last resort, return the smaller-magnitude solution
    return fabs(u1) < fabs(u2) ? u1 : u2;
}

} // namespace camera3

} // namespace android
