gt:         return (direction == INCREASING) ? cy0 : cy1;
context: /*
   * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Sun designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Sun in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  package sun.awt.geom;
  
  import java.awt.geom.Rectangle2D;
  import java.awt.geom.PathIterator;
  import java.awt.geom.QuadCurve2D;
  import java.util.Vector;
  
  final class Order3 extends Curve {
      private double x0;
      private double y0;
      private double cx0;
      private double cy0;
      private double cx1;
      private double cy1;
      private double x1;
      private double y1;
  
      private double xmin;
      private double xmax;
  
      private double xcoeff0;
      private double xcoeff1;
      private double xcoeff2;
      private double xcoeff3;
  
      private double ycoeff0;
      private double ycoeff1;
      private double ycoeff2;
      private double ycoeff3;
  
      public static void insert(Vector curves, double tmp[],
                                double x0, double y0,
                                double cx0, double cy0,
                                double cx1, double cy1,
                                double x1, double y1,
                                int direction)
      {
          int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);
          if (numparams == 0) {
              // We are using addInstance here to avoid inserting horisontal
              // segments
              addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);
              return;
          }
          // Store coordinates for splitting at tmp[3..10]
          tmp[3] = x0;  tmp[4]  = y0;
          tmp[5] = cx0; tmp[6]  = cy0;
          tmp[7] = cx1; tmp[8]  = cy1;
          tmp[9] = x1;  tmp[10] = y1;
          double t = tmp[0];
          if (numparams > 1 && t > tmp[1]) {
              // Perform a "2 element sort"...
              tmp[0] = tmp[1];
              tmp[1] = t;
              t = tmp[0];
          }
          split(tmp, 3, t);
          if (numparams > 1) {
              // Recalculate tmp[1] relative to the range [tmp[0]...1]
              t = (tmp[1] - t) / (1 - t);
              split(tmp, 9, t);
          }
          int index = 3;
          if (direction == DECREASING) {
              index += numparams * 6;
          }
          while (numparams >= 0) {
              addInstance(curves,
                          tmp[index + 0], tmp[index + 1],
                          tmp[index + 2], tmp[index + 3],
                          tmp[index + 4], tmp[index + 5],
                          tmp[index + 6], tmp[index + 7],
                          direction);
              numparams--;
              if (direction == INCREASING) {
                  index += 6;
              } else {
                  index -= 6;
              }
          }
      }
  
      public static void addInstance(Vector curves,
                                     double x0, double y0,
                                     double cx0, double cy0,
                                     double cx1, double cy1,
                                     double x1, double y1,
                                     int direction) {
          if (y0 > y1) {
              curves.add(new Order3(x1, y1, cx1, cy1, cx0, cy0, x0, y0,
                                    -direction));
          } else if (y1 > y0) {
              curves.add(new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1,
                                    direction));
          }
      }
  
      /*
       * Return the count of the number of horizontal sections of the
       * specified cubic Bezier curve.  Put the parameters for the
       * horizontal sections into the specified <code>ret</code> array.
       * <p>
       * If we examine the parametric equation in t, we have:
       *   Py(t) = C0(1-t)^3 + 3CP0 t(1-t)^2 + 3CP1 t^2(1-t) + C1 t^3
       *         = C0 - 3C0t + 3C0t^2 - C0t^3 +
       *           3CP0t - 6CP0t^2 + 3CP0t^3 +
       *           3CP1t^2 - 3CP1t^3 +
       *           C1t^3
       *   Py(t) = (C1 - 3CP1 + 3CP0 - C0) t^3 +
       *           (3C0 - 6CP0 + 3CP1) t^2 +
       *           (3CP0 - 3C0) t +
       *           (C0)
       * If we take the derivative, we get:
       *   Py(t) = Dt^3 + At^2 + Bt + C
       *   dPy(t) = 3Dt^2 + 2At + B = 0
       *        0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
       *          + 2*(3*CP1 - 6*CP0 + 3*C0)t
       *          + (3*CP0 - 3*C0)
       *        0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
       *          + 3*2*(CP1 - 2*CP0 + C0)t
       *          + 3*(CP0 - C0)
       *        0 = (C1 - CP1 - CP1 - CP1 + CP0 + CP0 + CP0 - C0)t^2
       *          + 2*(CP1 - CP0 - CP0 + C0)t
       *          + (CP0 - C0)
       *        0 = (C1 - CP1 + CP0 - CP1 + CP0 - CP1 + CP0 - C0)t^2
       *          + 2*(CP1 - CP0 - CP0 + C0)t
       *          + (CP0 - C0)
       *        0 = ((C1 - CP1) - (CP1 - CP0) - (CP1 - CP0) + (CP0 - C0))t^2
       *          + 2*((CP1 - CP0) - (CP0 - C0))t
       *          + (CP0 - C0)
       * Note that this method will return 0 if the equation is a line,
       * which is either always horizontal or never horizontal.
       * Completely horizontal curves need to be eliminated by other
       * means outside of this method.
       */
      public static int getHorizontalParams(double c0, double cp0,
                                            double cp1, double c1,
                                            double ret[]) {
          if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) {
              return 0;
          }
          c1 -= cp1;
          cp1 -= cp0;
          cp0 -= c0;
          ret[0] = cp0;
          ret[1] = (cp1 - cp0) * 2;
          ret[2] = (c1 - cp1 - cp1 + cp0);
          int numroots = QuadCurve2D.solveQuadratic(ret, ret);
          int j = 0;
          for (int i = 0; i < numroots; i++) {
              double t = ret[i];
              // No splits at t==0 and t==1
              if (t > 0 && t < 1) {
                  if (j < i) {
                      ret[j] = t;
                  }
                  j++;
              }
          }
          return j;
      }
  
      /*
       * Split the cubic Bezier stored at coords[pos...pos+7] representing
       * the parametric range [0..1] into two subcurves representing the
       * parametric subranges [0..t] and [t..1].  Store the results back
       * into the array at coords[pos...pos+7] and coords[pos+6...pos+13].
       */
      public static void split(double coords[], int pos, double t) {
          double x0, y0, cx0, cy0, cx1, cy1, x1, y1;
          coords[pos+12] = x1 = coords[pos+6];
          coords[pos+13] = y1 = coords[pos+7];
          cx1 = coords[pos+4];
          cy1 = coords[pos+5];
          x1 = cx1 + (x1 - cx1) * t;
          y1 = cy1 + (y1 - cy1) * t;
          x0 = coords[pos+0];
          y0 = coords[pos+1];
          cx0 = coords[pos+2];
          cy0 = coords[pos+3];
          x0 = x0 + (cx0 - x0) * t;
          y0 = y0 + (cy0 - y0) * t;
          cx0 = cx0 + (cx1 - cx0) * t;
          cy0 = cy0 + (cy1 - cy0) * t;
          cx1 = cx0 + (x1 - cx0) * t;
          cy1 = cy0 + (y1 - cy0) * t;
          cx0 = x0 + (cx0 - x0) * t;
          cy0 = y0 + (cy0 - y0) * t;
          coords[pos+2] = x0;
          coords[pos+3] = y0;
          coords[pos+4] = cx0;
          coords[pos+5] = cy0;
          coords[pos+6] = cx0 + (cx1 - cx0) * t;
          coords[pos+7] = cy0 + (cy1 - cy0) * t;
          coords[pos+8] = cx1;
          coords[pos+9] = cy1;
          coords[pos+10] = x1;
          coords[pos+11] = y1;
      }
  
      public Order3(double x0, double y0,
                    double cx0, double cy0,
                    double cx1, double cy1,
                    double x1, double y1,
                    int direction)
      {
          super(direction);
          // REMIND: Better accuracy in the root finding methods would
          //  ensure that cys are in range.  As it stands, they are never
          //  more than "1 mantissa bit" out of range...
          if (cy0 < y0) cy0 = y0;
          if (cy1 > y1) cy1 = y1;
          this.x0 = x0;
          this.y0 = y0;
          this.cx0 = cx0;
          this.cy0 = cy0;
          this.cx1 = cx1;
          this.cy1 = cy1;
          this.x1 = x1;
          this.y1 = y1;
          xmin = Math.min(Math.min(x0, x1), Math.min(cx0, cx1));
          xmax = Math.max(Math.max(x0, x1), Math.max(cx0, cx1));
          xcoeff0 = x0;
          xcoeff1 = (cx0 - x0) * 3.0;
          xcoeff2 = (cx1 - cx0 - cx0 + x0) * 3.0;
          xcoeff3 = x1 - (cx1 - cx0) * 3.0 - x0;
          ycoeff0 = y0;
          ycoeff1 = (cy0 - y0) * 3.0;
          ycoeff2 = (cy1 - cy0 - cy0 + y0) * 3.0;
          ycoeff3 = y1 - (cy1 - cy0) * 3.0 - y0;
          YforT1 = YforT2 = YforT3 = y0;
      }
  
      public int getOrder() {
          return 3;
      }
  
      public double getXTop() {
          return x0;
      }
  
      public double getYTop() {
          return y0;
      }
  
      public double getXBot() {
          return x1;
      }
  
      public double getYBot() {
          return y1;
      }
  
      public double getXMin() {
          return xmin;
      }
  
      public double getXMax() {
          return xmax;
      }
  
      public double getX0() {
          return (direction == INCREASING) ? x0 : x1;
      }
  
      public double getY0() {
          return (direction == INCREASING) ? y0 : y1;
      }
  
      public double getCX0() {
          return (direction == INCREASING) ? cx0 : cx1;
      }
  
      public double getCY0() {
  