
(FPCore (lambda1 lambda2 phi1 phi2) :precision binary64 (+ lambda1 (atan2 (* (cos phi2) (sin (- lambda1 lambda2))) (+ (cos phi1) (* (cos phi2) (cos (- lambda1 lambda2)))))))
double code(double lambda1, double lambda2, double phi1, double phi2) {
return lambda1 + atan2((cos(phi2) * sin((lambda1 - lambda2))), (cos(phi1) + (cos(phi2) * cos((lambda1 - lambda2)))));
}
real(8) function code(lambda1, lambda2, phi1, phi2)
real(8), intent (in) :: lambda1
real(8), intent (in) :: lambda2
real(8), intent (in) :: phi1
real(8), intent (in) :: phi2
code = lambda1 + atan2((cos(phi2) * sin((lambda1 - lambda2))), (cos(phi1) + (cos(phi2) * cos((lambda1 - lambda2)))))
end function
public static double code(double lambda1, double lambda2, double phi1, double phi2) {
return lambda1 + Math.atan2((Math.cos(phi2) * Math.sin((lambda1 - lambda2))), (Math.cos(phi1) + (Math.cos(phi2) * Math.cos((lambda1 - lambda2)))));
}
def code(lambda1, lambda2, phi1, phi2): return lambda1 + math.atan2((math.cos(phi2) * math.sin((lambda1 - lambda2))), (math.cos(phi1) + (math.cos(phi2) * math.cos((lambda1 - lambda2)))))
function code(lambda1, lambda2, phi1, phi2) return Float64(lambda1 + atan(Float64(cos(phi2) * sin(Float64(lambda1 - lambda2))), Float64(cos(phi1) + Float64(cos(phi2) * cos(Float64(lambda1 - lambda2)))))) end
function tmp = code(lambda1, lambda2, phi1, phi2) tmp = lambda1 + atan2((cos(phi2) * sin((lambda1 - lambda2))), (cos(phi1) + (cos(phi2) * cos((lambda1 - lambda2))))); end
code[lambda1_, lambda2_, phi1_, phi2_] := N[(lambda1 + N[ArcTan[N[(N[Cos[phi2], $MachinePrecision] * N[Sin[N[(lambda1 - lambda2), $MachinePrecision]], $MachinePrecision]), $MachinePrecision] / N[(N[Cos[phi1], $MachinePrecision] + N[(N[Cos[phi2], $MachinePrecision] * N[Cos[N[(lambda1 - lambda2), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\lambda_1 + \tan^{-1}_* \frac{\cos \phi_2 \cdot \sin \left(\lambda_1 - \lambda_2\right)}{\cos \phi_1 + \cos \phi_2 \cdot \cos \left(\lambda_1 - \lambda_2\right)}
\end{array}
Sampling outcomes in binary64 precision:
Herbie found 20 alternatives:
| Alternative | Accuracy | Speedup |
|---|
(FPCore (lambda1 lambda2 phi1 phi2) :precision binary64 (+ lambda1 (atan2 (* (cos phi2) (sin (- lambda1 lambda2))) (+ (cos phi1) (* (cos phi2) (cos (- lambda1 lambda2)))))))
double code(double lambda1, double lambda2, double phi1, double phi2) {
return lambda1 + atan2((cos(phi2) * sin((lambda1 - lambda2))), (cos(phi1) + (cos(phi2) * cos((lambda1 - lambda2)))));
}
real(8) function code(lambda1, lambda2, phi1, phi2)
real(8), intent (in) :: lambda1
real(8), intent (in) :: lambda2
real(8), intent (in) :: phi1
real(8), intent (in) :: phi2
code = lambda1 + atan2((cos(phi2) * sin((lambda1 - lambda2))), (cos(phi1) + (cos(phi2) * cos((lambda1 - lambda2)))))
end function
public static double code(double lambda1, double lambda2, double phi1, double phi2) {
return lambda1 + Math.atan2((Math.cos(phi2) * Math.sin((lambda1 - lambda2))), (Math.cos(phi1) + (Math.cos(phi2) * Math.cos((lambda1 - lambda2)))));
}
def code(lambda1, lambda2, phi1, phi2): return lambda1 + math.atan2((math.cos(phi2) * math.sin((lambda1 - lambda2))), (math.cos(phi1) + (math.cos(phi2) * math.cos((lambda1 - lambda2)))))
function code(lambda1, lambda2, phi1, phi2) return Float64(lambda1 + atan(Float64(cos(phi2) * sin(Float64(lambda1 - lambda2))), Float64(cos(phi1) + Float64(cos(phi2) * cos(Float64(lambda1 - lambda2)))))) end
function tmp = code(lambda1, lambda2, phi1, phi2) tmp = lambda1 + atan2((cos(phi2) * sin((lambda1 - lambda2))), (cos(phi1) + (cos(phi2) * cos((lambda1 - lambda2))))); end
code[lambda1_, lambda2_, phi1_, phi2_] := N[(lambda1 + N[ArcTan[N[(N[Cos[phi2], $MachinePrecision] * N[Sin[N[(lambda1 - lambda2), $MachinePrecision]], $MachinePrecision]), $MachinePrecision] / N[(N[Cos[phi1], $MachinePrecision] + N[(N[Cos[phi2], $MachinePrecision] * N[Cos[N[(lambda1 - lambda2), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\lambda_1 + \tan^{-1}_* \frac{\cos \phi_2 \cdot \sin \left(\lambda_1 - \lambda_2\right)}{\cos \phi_1 + \cos \phi_2 \cdot \cos \left(\lambda_1 - \lambda_2\right)}
\end{array}
(FPCore (lambda1 lambda2 phi1 phi2)
:precision binary64
(+
lambda1
(atan2
(*
(cos phi2)
(fma (sin (- lambda2)) (cos lambda1) (* (cos lambda2) (sin lambda1))))
(fma
(cos phi2)
(fma (cos lambda1) (cos lambda2) (* (sin lambda1) (sin lambda2)))
(cos phi1)))))
double code(double lambda1, double lambda2, double phi1, double phi2) {
return lambda1 + atan2((cos(phi2) * fma(sin(-lambda2), cos(lambda1), (cos(lambda2) * sin(lambda1)))), fma(cos(phi2), fma(cos(lambda1), cos(lambda2), (sin(lambda1) * sin(lambda2))), cos(phi1)));
}
function code(lambda1, lambda2, phi1, phi2) return Float64(lambda1 + atan(Float64(cos(phi2) * fma(sin(Float64(-lambda2)), cos(lambda1), Float64(cos(lambda2) * sin(lambda1)))), fma(cos(phi2), fma(cos(lambda1), cos(lambda2), Float64(sin(lambda1) * sin(lambda2))), cos(phi1)))) end
code[lambda1_, lambda2_, phi1_, phi2_] := N[(lambda1 + N[ArcTan[N[(N[Cos[phi2], $MachinePrecision] * N[(N[Sin[(-lambda2)], $MachinePrecision] * N[Cos[lambda1], $MachinePrecision] + N[(N[Cos[lambda2], $MachinePrecision] * N[Sin[lambda1], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision] / N[(N[Cos[phi2], $MachinePrecision] * N[(N[Cos[lambda1], $MachinePrecision] * N[Cos[lambda2], $MachinePrecision] + N[(N[Sin[lambda1], $MachinePrecision] * N[Sin[lambda2], $MachinePrecision]), $MachinePrecision]), $MachinePrecision] + N[Cos[phi1], $MachinePrecision]), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\lambda_1 + \tan^{-1}_* \frac{\cos \phi_2 \cdot \mathsf{fma}\left(\sin \left(-\lambda_2\right), \cos \lambda_1, \cos \lambda_2 \cdot \sin \lambda_1\right)}{\mathsf{fma}\left(\cos \phi_2, \mathsf{fma}\left(\cos \lambda_1, \cos \lambda_2, \sin \lambda_1 \cdot \sin \lambda_2\right), \cos \phi_1\right)}
\end{array}
Initial program 98.2%
lift-+.f64N/A
+-commutativeN/A
lift-*.f64N/A
lift-cos.f64N/A
lift--.f64N/A
cos-diffN/A
distribute-lft-inN/A
associate-+l+N/A
*-commutativeN/A
associate-*r*N/A
*-commutativeN/A
lower-fma.f64N/A
lower-*.f64N/A
lower-cos.f64N/A
lower-cos.f64N/A
Applied rewrites98.3%
lift-sin.f64N/A
lift--.f64N/A
sub-negN/A
+-commutativeN/A
sin-sumN/A
lift-cos.f64N/A
cos-negN/A
lift-cos.f64N/A
lift-sin.f64N/A
*-commutativeN/A
lift-sin.f64N/A
lift-cos.f64N/A
lower-fma.f64N/A
lower-sin.f64N/A
lower-neg.f64N/A
lift-sin.f64N/A
lift-cos.f64N/A
*-commutativeN/A
lower-*.f6499.6
Applied rewrites99.6%
Taylor expanded in phi2 around inf
+-commutativeN/A
cos-negN/A
associate-*r*N/A
cos-negN/A
*-commutativeN/A
distribute-rgt-outN/A
lower-fma.f64N/A
Applied rewrites99.6%
(FPCore (lambda1 lambda2 phi1 phi2)
:precision binary64
(let* ((t_0 (cos (- lambda1 lambda2)))
(t_1 (* (cos phi2) (sin (- lambda1 lambda2))))
(t_2 (+ lambda1 (atan2 t_1 (* (* phi1 phi1) -0.5))))
(t_3 (+ lambda1 (atan2 t_1 (+ (cos phi1) (* (cos phi2) t_0))))))
(if (<= t_3 -0.01)
t_2
(if (<= t_3 2e-6)
(+
lambda1
(atan2
(fma
lambda2
(fma 0.16666666666666666 (* lambda2 lambda2) -1.0)
(fma
lambda1
(fma
lambda1
(fma
lambda1
(fma (* lambda2 lambda2) 0.08333333333333333 -0.16666666666666666)
(* lambda2 (fma (* lambda2 lambda2) -0.08333333333333333 0.5)))
(* -0.5 (* lambda2 lambda2)))
lambda1))
(+ (cos phi1) t_0)))
t_2))))
double code(double lambda1, double lambda2, double phi1, double phi2) {
double t_0 = cos((lambda1 - lambda2));
double t_1 = cos(phi2) * sin((lambda1 - lambda2));
double t_2 = lambda1 + atan2(t_1, ((phi1 * phi1) * -0.5));
double t_3 = lambda1 + atan2(t_1, (cos(phi1) + (cos(phi2) * t_0)));
double tmp;
if (t_3 <= -0.01) {
tmp = t_2;
} else if (t_3 <= 2e-6) {
tmp = lambda1 + atan2(fma(lambda2, fma(0.16666666666666666, (lambda2 * lambda2), -1.0), fma(lambda1, fma(lambda1, fma(lambda1, fma((lambda2 * lambda2), 0.08333333333333333, -0.16666666666666666), (lambda2 * fma((lambda2 * lambda2), -0.08333333333333333, 0.5))), (-0.5 * (lambda2 * lambda2))), lambda1)), (cos(phi1) + t_0));
} else {
tmp = t_2;
}
return tmp;
}
function code(lambda1, lambda2, phi1, phi2) t_0 = cos(Float64(lambda1 - lambda2)) t_1 = Float64(cos(phi2) * sin(Float64(lambda1 - lambda2))) t_2 = Float64(lambda1 + atan(t_1, Float64(Float64(phi1 * phi1) * -0.5))) t_3 = Float64(lambda1 + atan(t_1, Float64(cos(phi1) + Float64(cos(phi2) * t_0)))) tmp = 0.0 if (t_3 <= -0.01) tmp = t_2; elseif (t_3 <= 2e-6) tmp = Float64(lambda1 + atan(fma(lambda2, fma(0.16666666666666666, Float64(lambda2 * lambda2), -1.0), fma(lambda1, fma(lambda1, fma(lambda1, fma(Float64(lambda2 * lambda2), 0.08333333333333333, -0.16666666666666666), Float64(lambda2 * fma(Float64(lambda2 * lambda2), -0.08333333333333333, 0.5))), Float64(-0.5 * Float64(lambda2 * lambda2))), lambda1)), Float64(cos(phi1) + t_0))); else tmp = t_2; end return tmp end
code[lambda1_, lambda2_, phi1_, phi2_] := Block[{t$95$0 = N[Cos[N[(lambda1 - lambda2), $MachinePrecision]], $MachinePrecision]}, Block[{t$95$1 = N[(N[Cos[phi2], $MachinePrecision] * N[Sin[N[(lambda1 - lambda2), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]}, Block[{t$95$2 = N[(lambda1 + N[ArcTan[t$95$1 / N[(N[(phi1 * phi1), $MachinePrecision] * -0.5), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]}, Block[{t$95$3 = N[(lambda1 + N[ArcTan[t$95$1 / N[(N[Cos[phi1], $MachinePrecision] + N[(N[Cos[phi2], $MachinePrecision] * t$95$0), $MachinePrecision]), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]}, If[LessEqual[t$95$3, -0.01], t$95$2, If[LessEqual[t$95$3, 2e-6], N[(lambda1 + N[ArcTan[N[(lambda2 * N[(0.16666666666666666 * N[(lambda2 * lambda2), $MachinePrecision] + -1.0), $MachinePrecision] + N[(lambda1 * N[(lambda1 * N[(lambda1 * N[(N[(lambda2 * lambda2), $MachinePrecision] * 0.08333333333333333 + -0.16666666666666666), $MachinePrecision] + N[(lambda2 * N[(N[(lambda2 * lambda2), $MachinePrecision] * -0.08333333333333333 + 0.5), $MachinePrecision]), $MachinePrecision]), $MachinePrecision] + N[(-0.5 * N[(lambda2 * lambda2), $MachinePrecision]), $MachinePrecision]), $MachinePrecision] + lambda1), $MachinePrecision]), $MachinePrecision] / N[(N[Cos[phi1], $MachinePrecision] + t$95$0), $MachinePrecision]], $MachinePrecision]), $MachinePrecision], t$95$2]]]]]]
\begin{array}{l}
\\
\begin{array}{l}
t_0 := \cos \left(\lambda_1 - \lambda_2\right)\\
t_1 := \cos \phi_2 \cdot \sin \left(\lambda_1 - \lambda_2\right)\\
t_2 := \lambda_1 + \tan^{-1}_* \frac{t\_1}{\left(\phi_1 \cdot \phi_1\right) \cdot -0.5}\\
t_3 := \lambda_1 + \tan^{-1}_* \frac{t\_1}{\cos \phi_1 + \cos \phi_2 \cdot t\_0}\\
\mathbf{if}\;t\_3 \leq -0.01:\\
\;\;\;\;t\_2\\
\mathbf{elif}\;t\_3 \leq 2 \cdot 10^{-6}:\\
\;\;\;\;\lambda_1 + \tan^{-1}_* \frac{\mathsf{fma}\left(\lambda_2, \mathsf{fma}\left(0.16666666666666666, \lambda_2 \cdot \lambda_2, -1\right), \mathsf{fma}\left(\lambda_1, \mathsf{fma}\left(\lambda_1, \mathsf{fma}\left(\lambda_1, \mathsf{fma}\left(\lambda_2 \cdot \lambda_2, 0.08333333333333333, -0.16666666666666666\right), \lambda_2 \cdot \mathsf{fma}\left(\lambda_2 \cdot \lambda_2, -0.08333333333333333, 0.5\right)\right), -0.5 \cdot \left(\lambda_2 \cdot \lambda_2\right)\right), \lambda_1\right)\right)}{\cos \phi_1 + t\_0}\\
\mathbf{else}:\\
\;\;\;\;t\_2\\
\end{array}
\end{array}
if (+.f64 lambda1 (atan2.f64 (*.f64 (cos.f64 phi2) (sin.f64 (-.f64 lambda1 lambda2))) (+.f64 (cos.f64 phi1) (*.f64 (cos.f64 phi2) (cos.f64 (-.f64 lambda1 lambda2)))))) < -0.0100000000000000002 or 1.99999999999999991e-6 < (+.f64 lambda1 (atan2.f64 (*.f64 (cos.f64 phi2) (sin.f64 (-.f64 lambda1 lambda2))) (+.f64 (cos.f64 phi1) (*.f64 (cos.f64 phi2) (cos.f64 (-.f64 lambda1 lambda2)))))) Initial program 98.7%
lift-+.f64N/A
flip3-+N/A
clear-numN/A
lower-/.f64N/A
clear-numN/A
flip3-+N/A
Applied rewrites98.7%
Taylor expanded in phi1 around 0
associate-+r+N/A
+-commutativeN/A
lower-fma.f64N/A
lower-cos.f64N/A
lower-cos.f64N/A
lower--.f64N/A
+-commutativeN/A
*-commutativeN/A
unpow2N/A
associate-*l*N/A
lower-fma.f64N/A
lower-*.f6485.3
Applied rewrites85.3%
Taylor expanded in phi1 around inf
Applied rewrites72.2%
if -0.0100000000000000002 < (+.f64 lambda1 (atan2.f64 (*.f64 (cos.f64 phi2) (sin.f64 (-.f64 lambda1 lambda2))) (+.f64 (cos.f64 phi1) (*.f64 (cos.f64 phi2) (cos.f64 (-.f64 lambda1 lambda2)))))) < 1.99999999999999991e-6Initial program 99.0%
Taylor expanded in phi2 around 0
lower-sin.f64N/A
lower--.f6461.9
Applied rewrites61.9%
Taylor expanded in phi2 around 0
lower-+.f64N/A
lower-cos.f64N/A
lower-cos.f64N/A
lower--.f6462.4
Applied rewrites62.4%
Taylor expanded in lambda2 around 0
Applied rewrites62.1%
Taylor expanded in lambda1 around 0
Applied rewrites62.1%
Final simplification70.1%
herbie shell --seed 2024226
(FPCore (lambda1 lambda2 phi1 phi2)
:name "Midpoint on a great circle"
:precision binary64
(+ lambda1 (atan2 (* (cos phi2) (sin (- lambda1 lambda2))) (+ (cos phi1) (* (cos phi2) (cos (- lambda1 lambda2)))))))