import java.util.Date;

public class Shi3z {
  public static void main(String[] args) {
    float[] or = null, mr = null, nr = null;

    for (int i = 0; i < 1000; i++) {
      or = orig(0, 0, 0, 100, 150, 200, 250, 300, 350, 400, 450, 500);
    }
    Date d = new Date();
    for (int i = 0; i < 3000000; i++) {
      or = orig(0, 0, 0, 100, 150, 200, 250, 300, 350, 400, 450, 500);
    }
    System.out.println(new Date().getTime() - d.getTime());

    for (int i = 0; i < 1000; i++) {
      mr = mine(0, 0, 0, 100, 150, 200, 250, 300, 350, 400, 450, 500);
    }
    d = new Date();
    for (int i = 0; i < 3000000; i++) {
      mr = mine(0, 0, 0, 100, 150, 200, 250, 300, 350, 400, 450, 500);
    }
    System.out.println(new Date().getTime() - d.getTime());

    for (int i = 0; i < 1000; i++) {
      nr = nomul(0, 0, 0, 100, 150, 200, 250, 300, 350, 400, 450, 500);
    }
    d = new Date();
    for (int i = 0; i < 3000000; i++) {
      nr = nomul(0, 0, 0, 100, 150, 200, 250, 300, 350, 400, 450, 500);
    }
    System.out.println(new Date().getTime() - d.getTime());

    boolean ok = true;
    for (int i = 0; i < or.length; i++) {
      if (Math.abs(or[i] - mr[i]) > 0.0001) {
        System.out.println(or[i] + " vs " + mr[i]);
        ok = false;
      }
    }
    System.out.println(ok);
    for (int i = 0; i < or.length; i++) {
      if (Math.abs(or[i] - nr[i]) > 0.0001) {
        System.out.println(or[i] + " vs " + nr[i]);
        ok = false;
      }
    }
    System.out.println(ok);
  }

  private static float[] orig(
      float xp0, float yp0, float pp0,
      float xp1, float yp1, float pp1,
      float xp2, float yp2, float pp2,
      float xp3, float yp3, float pp3) {
    float dx = xp1-xp2;
    float dy = yp1-yp2;
    float d =(float)Math.sqrt(dx*dx+dy*dy);
    int num = (int)Math.ceil((double)(d / 5.0d) + 0.5d);
    float[] ret = new float[num * 3];
    float x,y,p;
    float invertNum = 1.0f/num;
    float deltaT = 0;
    float xv0 = (xp2-xp0)*0.5f;
    float xv1 = (xp3-xp1)*0.5f;
    float xfact1=((xp1 - xp2)*2.0f + xv0 + xv1);
    float xfact2=((xp2 - xp1)*3.0f - 2.0f * xv0 - xv1) ;
    float yv0 = (yp2-yp0)*0.5f;
    float yv1 = (yp3-yp1)*0.5f;
    float yfact1=((yp1 - yp2)*2.0f + yv0 + yv1);
    float yfact2=((yp2 - yp1)*3.0f - 2.0f * yv0 - yv1) ;
    float pv0 = (pp2-pp0)*0.5f;
    float pv1 = (pp3-pp1)*0.5f;
    float pfact1=((pp1 - pp2)*2.0f + pv0 + pv1);
    float pfact2=((pp2 - pp1)*3.0f - 2.0f * pv0 - pv1);
    for(int i = 0; i < num; i++, deltaT+=invertNum){
      float t2 = deltaT*deltaT;
      float t3 = t2*deltaT;

      x =  xfact1* t3 + xfact2*t2+xv0 * deltaT + xp1;
      y =  yfact1* t3 + yfact2*t2 + yv0 * deltaT + yp1;
      p =  pfact1* t3 + pfact2*t2 + pv0 * deltaT + pp1;

      ret[i + i + i] = x;
      ret[i + i + i + 1] = y;
      ret[i + i + i + 2] = p;
    }

    return ret;
  }

  private static float[] mine(
      float xp0, float yp0, float pp0,
      float xp1, float yp1, float pp1,
      float xp2, float yp2, float pp2,
      float xp3, float yp3, float pp3) {
    float dx = xp1-xp2;
    float dy = yp1-yp2;
    float d =(float)Math.sqrt(dx*dx+dy*dy);
    int num = (int)Math.ceil((double)(d / 5.0d) + 0.5d);
    float[] ret = new float[num * 3];
    float x,y,p;
    float invertNum = 1.0f/num;
    float deltaT = 0;
    float xv0 = (xp2-xp0)*0.5f;
    float xv1 = (xp3-xp1)*0.5f;
    float xfact1=((xp1 - xp2)*2.0f + xv0 + xv1);
    float xfact2=((xp2 - xp1)*3.0f - 2.0f * xv0 - xv1) ;
    float yv0 = (yp2-yp0)*0.5f;
    float yv1 = (yp3-yp1)*0.5f;
    float yfact1=((yp1 - yp2)*2.0f + yv0 + yv1);
    float yfact2=((yp2 - yp1)*3.0f - 2.0f * yv0 - yv1) ;
    float pv0 = (pp2-pp0)*0.5f;
    float pv1 = (pp3-pp1)*0.5f;
    float pfact1=((pp1 - pp2)*2.0f + pv0 + pv1);
    float pfact2=((pp2 - pp1)*3.0f - 2.0f * pv0 - pv1);
    float xfact1n = 0;
    float yfact1n = 0;
    float pfact1n = 0;
    float xfact1Step = xfact1 * invertNum;
    float yfact1Step = yfact1 * invertNum;
    float pfact1Step = pfact1 * invertNum;
    for(int i = 0; i < num; i++, deltaT += invertNum){
      x =  ((xfact1n + xfact2) * deltaT + xv0) * deltaT + xp1;
      y =  ((yfact1n + yfact2) * deltaT + yv0) * deltaT + yp1;
      p =  ((pfact1n + pfact2) * deltaT + pv0) * deltaT + pp1;
      xfact1n += xfact1Step;
      yfact1n += yfact1Step;
      pfact1n += pfact1Step;

      ret[i + i + i] = x;
      ret[i + i + i + 1] = y;
      ret[i + i + i + 2] = p;
    }

    return ret;
  }

  private static float[] nomul(
      float xp0, float yp0, float pp0,
      float xp1, float yp1, float pp1,
      float xp2, float yp2, float pp2,
      float xp3, float yp3, float pp3) {
    float dx = xp1-xp2;
    float dy = yp1-yp2;
    float d =(float)Math.sqrt(dx*dx+dy*dy);
    int num = (int)Math.ceil((double)(d / 5.0d) + 0.5d);
    float[] ret = new float[num * 3];
    float x,y,p;
    float invertNum = 1.0f/num;
    float deltaT = 0;
    float xv0 = (xp2-xp0)*0.5f;
    float xv1 = (xp3-xp1)*0.5f;
    float xfact1=((xp1 - xp2)*2.0f + xv0 + xv1);
    float xfact2=((xp2 - xp1)*3.0f - 2.0f * xv0 - xv1) ;
    float yv0 = (yp2-yp0)*0.5f;
    float yv1 = (yp3-yp1)*0.5f;
    float yfact1=((yp1 - yp2)*2.0f + yv0 + yv1);
    float yfact2=((yp2 - yp1)*3.0f - 2.0f * yv0 - yv1) ;
    float pv0 = (pp2-pp0)*0.5f;
    float pv1 = (pp3-pp1)*0.5f;
    float pfact1=((pp1 - pp2)*2.0f + pv0 + pv1);
    float pfact2=((pp2 - pp1)*3.0f - 2.0f * pv0 - pv1);
    float xv0n = 0;
    float yv0n = 0;
    float pv0n = 0;
    float xv0Step = xv0 * invertNum;
    float yv0Step = yv0 * invertNum;
    float pv0Step = pv0 * invertNum;
    float xfact2n = 0;
    float yfact2n = 0;
    float pfact2n = 0;
    float xfact2n2 = 0;
    float yfact2n2 = 0;
    float pfact2n2 = 0;
    float xfact2Step = xfact2 * invertNum * invertNum;
    float yfact2Step = yfact2 * invertNum * invertNum;
    float pfact2Step = pfact2 * invertNum * invertNum;
    float xfact1n = 0;
    float yfact1n = 0;
    float pfact1n = 0;
    float xfact1n2 = 0;
    float yfact1n2 = 0;
    float pfact1n2 = 0;
    float xfact1n3 = 0;
    float yfact1n3 = 0;
    float pfact1n3 = 0;
    float xfact1Step = xfact1 * invertNum * invertNum * invertNum;
    float yfact1Step = yfact1 * invertNum * invertNum * invertNum;
    float pfact1Step = pfact1 * invertNum * invertNum * invertNum;
    for(int i = 0; i < num; i++, deltaT += invertNum) {
      x = (xfact1n3 + xfact1n3 + xfact1n3 + xfact1n3 + xfact1n3 + xfact1n3 -
           (xfact1n2 + xfact1n2 + xfact1n2 + xfact1n2 + xfact1n2 + xfact1n2) + xfact1n +
           xfact2n2 + xfact2n2 - xfact2n + xv0n + xp1);
      y = (yfact1n3 + yfact1n3 + yfact1n3 + yfact1n3 + yfact1n3 + yfact1n3 -
           (yfact1n2 + yfact1n2 + yfact1n2 + yfact1n2 + yfact1n2 + yfact1n2) + yfact1n +
           yfact2n2 + yfact2n2 - yfact2n + yv0n + yp1);
      p = (pfact1n3 + pfact1n3 + pfact1n3 + pfact1n3 + pfact1n3 + pfact1n3 -
           (pfact1n2 + pfact1n2 + pfact1n2 + pfact1n2 + pfact1n2 + pfact1n2) + pfact1n +
           pfact2n2 + pfact2n2 - pfact2n + pv0n + pp1);
      xv0n += xv0Step;
      yv0n += yv0Step;
      pv0n += pv0Step;
      xfact2n2 += xfact2n += xfact2Step;
      yfact2n2 += yfact2n += yfact2Step;
      pfact2n2 += pfact2n += pfact2Step;
      xfact1n3 += xfact1n2 += xfact1n += xfact1Step;
      yfact1n3 += yfact1n2 += yfact1n += yfact1Step;
      pfact1n3 += pfact1n2 += pfact1n += pfact1Step;

      ret[i + i + i] = x;
      ret[i + i + i + 1] = y;
      ret[i + i + i + 2] = p;
    }

    return ret;
  }
}
