001/* 002 * Shredzone Commons - suncalc 003 * 004 * Copyright (C) 2017 Richard "Shred" Körber 005 * http://commons.shredzone.org 006 * 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 013 */ 014package org.shredzone.commons.suncalc.util; 015 016import static java.lang.Math.abs; 017import static java.lang.Math.sqrt; 018 019/** 020 * Calculates the roots and extremum of a quadratic equation. 021 */ 022public class QuadraticInterpolation { 023 024 private final double xe; 025 private final double ye; 026 private final double root1; 027 private final double root2; 028 private final int nRoot; 029 private final boolean maximum; 030 031 /** 032 * Creates a new quadratic equation. 033 * 034 * @param yMinus 035 * y at x == -1 036 * @param y0 037 * y at x == 0 038 * @param yPlus 039 * y at x == 1 040 */ 041 public QuadraticInterpolation(double yMinus, double y0, double yPlus) { 042 double a = 0.5 * (yPlus + yMinus) - y0; 043 double b = 0.5 * (yPlus - yMinus); 044 double c = y0; 045 046 xe = -b / (2.0 * a); 047 ye = (a * xe + b) * xe + c; 048 maximum = a < 0.0; 049 double dis = b * b - 4.0 * a * c; 050 051 int rootCount = 0; 052 053 if (dis >= 0.0) { 054 double dx = 0.5 * sqrt(dis) / abs(a); 055 root1 = xe - dx; 056 root2 = xe + dx; 057 058 if (abs(root1) <= 1.0) { 059 rootCount++; 060 } 061 062 if (abs(root2) <= 1.0) { 063 rootCount++; 064 } 065 } else { 066 root1 = Double.NaN; 067 root2 = Double.NaN; 068 } 069 070 nRoot = rootCount; 071 } 072 073 /** 074 * Returns X of extremum. Can be outside [-1 .. 1]. 075 * 076 * @return X 077 */ 078 public double getXe() { 079 return xe; 080 } 081 082 /** 083 * Returns the Y value at the extremum. 084 * 085 * @return Y 086 */ 087 public double getYe() { 088 return ye; 089 } 090 091 /** 092 * Returns the first root that was found. 093 * 094 * @return X of first root 095 */ 096 public double getRoot1() { 097 return root1 < -1.0 ? root2 : root1; 098 } 099 100 /** 101 * Returns the second root that was found. 102 * 103 * @return X of second root 104 */ 105 public double getRoot2() { 106 return root2; 107 } 108 109 /** 110 * Returns the number of roots found in [-1 .. 1]. 111 * 112 * @return Number of roots 113 */ 114 public int getNumberOfRoots() { 115 return nRoot; 116 } 117 118 /** 119 * Returns whether the extremum is a minimum or a maximum. 120 * 121 * @return {@code true}: Extremum at xe is a maximum. {@code false}: Extremum at xe is 122 * a minimum. 123 */ 124 public boolean isMaximum() { 125 return maximum; 126 } 127 128}