<div dir="ltr"><div>Sorry, I should me more explicit</div><div>What I mean is:</div><div></div><div> - take 9.6.0</div><div> - replace the function pj_conformal_lat_inverse in latitudes.cpp with the new implementation</div><div> - replace its declaration in proj_internal.h <br></div><div> - replace its usage in spilhaus.cpp</div><div><br></div><div>... that is this patch</div><div><br></div><div>------- begin patch --------------</div><div><span style="font-family:monospace">diff --git a/src/latitudes.cpp b/src/latitudes.cpp<br>index 7d49f667..c5e277f8 100644<br>--- a/src/latitudes.cpp<br>+++ b/src/latitudes.cpp<br>@@ -36,33 +36,17 @@ double pj_conformal_lat(double phi, double e) {<br> }<br> <br> /*****************************************************************************/<br>-double pj_conformal_lat_inverse(double chi, double e, double threshold) {<br>+<br>+double pj_conformal_lat_inverse(double chi, const PJ *P) {<br>     /***********************************<br>-     * The inverse formula of the conformal latitude<br>-     * for phi (geodetic latitude) in terms of chi (conformal latitude),<br>-     * Snyder, A working manual, formula 3-4<br>+     * The geodetic latitude, phi, in terms of the conformal latitude, chi.<br>      *<br>      * chi: conformal latitude, in radians<br>-     * e: ellipsoid eccentricity<br>-     * threshold: between two consecutive iteratinons to break the loop, radians<br>-     * returns: geodetic latitude, in radians<br>+     * returns: geodetic latitude, phi, in radians<br>+     * Copied from merc.cpp<br>      ***********************************/<br>-    if (e == 0.0)<br>+    if (P->e == 0.0)<br>         return chi;<br> <br>-    const double taninit = tan(M_PI / 4 + chi / 2);<br>-    double phi = chi;<br>-    for (int i = 0; i < 10; i++) {<br>-        const double esinphi = e * sin(phi);<br>-        const double new_phi =<br>-            2 * atan(taninit *<br>-                     std::pow(((1 + esinphi) / (1 - esinphi)), (e / 2))) -<br>-            0.5 * M_PI;<br>-        if (abs(new_phi - phi) < threshold) {<br>-            phi = new_phi;<br>-            break;<br>-        }<br>-        phi = new_phi;<br>-    }<br>-    return phi;<br>+    return atan(pj_sinhpsi2tanphi(P->ctx, tan(chi), P->e));<br> }<br>diff --git a/src/proj_internal.h b/src/proj_internal.h<br>index 922c7074..54b64341 100644<br>--- a/src/proj_internal.h<br>+++ b/src/proj_internal.h<br>@@ -923,7 +923,7 @@ double *pj_authset(double);<br> double pj_authlat(double, double *);<br> <br> double pj_conformal_lat(double phi, double e);<br>-double pj_conformal_lat_inverse(double chi, double e, double threshold);<br>+double pj_conformal_lat_inverse(double chi, const PJ *P);<br> <br> COMPLEX pj_zpoly1(COMPLEX, const COMPLEX *, int);<br> COMPLEX pj_zpolyd1(COMPLEX, const COMPLEX *, int, COMPLEX *);<br>diff --git a/src/projections/spilhaus.cpp b/src/projections/spilhaus.cpp<br>index 01b86800..ba9a6c57 100644<br>--- a/src/projections/spilhaus.cpp<br>+++ b/src/projections/spilhaus.cpp<br>@@ -98,8 +98,7 @@ static PJ_LP spilhaus_inverse(PJ_XY xy, PJ *P) {<br>              aatan2(cosphi_s * sinlam_s,<br>                     Q->sinalpha * cosphi_s * coslam_s - Q->cosalpha * sinphi_s);<br> <br>-    const double THRESHOLD = 1e-10;<br>-    lp.phi = pj_conformal_lat_inverse(lp.phi, P->e, THRESHOLD);<br>+    lp.phi = pj_conformal_lat_inverse(lp.phi, P);<br> <br>     return lp;<br> }<br></span></div><div>------- end patch --------------</div><div><br></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sun, 4 May 2025 at 20:27, Greg Troxel <<a href="mailto:gdt@lexort.com">gdt@lexort.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Javier Jimenez Shaw <<a href="mailto:j1@jimenezshaw.com" target="_blank">j1@jimenezshaw.com</a>> writes:<br>
<br>
> The PR was <a href="https://github.com/OSGeo/PROJ/pull/4446" rel="noreferrer" target="_blank">https://github.com/OSGeo/PROJ/pull/4446</a><br>
><br>
> Maybe the function that impacts the tests is "pj_conformal_lat_inverse".<br>
> You can try with the new implementation.<br>
> The changes should be small. (See that the signature of the function is a<br>
> bit different). It is used only in one place.<br>
<br>
<br>
Do you mean:<br>
<br>
  take proj 9.6.0<br>
<br>
  read the diff to pj_conformal_lat_inverse from the PR, and hand patch<br>
  it in, except not changing the signature<br>
<br>
  build and rerun tests<br>
<br>
I guess I could further keep the code and compare the two results.<br>
<br>
<br>
I looked at that code, and it jumped out at me that are abs() was used,<br>
which is a C function, not C++, and is integer only.<br>
<br>
With this patch (to 9.6.0), I get a pass:<br>
<br>
--- src/latitudes.cpp.~1~       2025-03-13 10:31:27.000000000 -0400<br>
+++ src/latitudes.cpp   2025-05-04 14:23:04.656697860 -0400<br>
@@ -58,7 +58,7 @@<br>
             2 * atan(taninit *<br>
                      std::pow(((1 + esinphi) / (1 - esinphi)), (e / 2))) -<br>
             0.5 * M_PI;<br>
-        if (abs(new_phi - phi) < threshold) {<br>
+        if (std::abs(new_phi - phi) < threshold) {<br>
             phi = new_phi;<br>
             break;<br>
         }<br>
<br>
Interesting that this only causes trouble with spilhaus, at least as far<br>
as tests catch it.<br>
</blockquote></div>