diff --git a/dev/docker/boost_bcp_docker/Dockerfile b/dev/docker/boost_bcp_docker/Dockerfile
index f6afb130024fd58c646dc7ddeaf8e4b10bbf57c1..fa45df86246522b769b89201292ba85aea3f3161 100644
--- a/dev/docker/boost_bcp_docker/Dockerfile
+++ b/dev/docker/boost_bcp_docker/Dockerfile
@@ -12,7 +12,7 @@ RUN mkdir /boost && \
 
 WORKDIR /boost/boost_1_77_0
 RUN mkdir /boost_teqp && \
-	bin.v2/tools/bcp/gcc-9/release/link-static/bcp multiprecision/cpp_bin_float.hpp multiprecision/eigen.hpp functional/hash.hpp numeric/odeint.hpp typeof/incr_registration_group.hpp mp11.hpp algorithm/string/join.hpp asio/thread_pool.hpp asio/post.hpp /boost_teqp && \
+	bin.v2/tools/bcp/gcc-9/release/link-static/bcp multiprecision/cpp_bin_float.hpp multiprecision/cpp_complex.hpp multiprecision/eigen.hpp functional/hash.hpp numeric/odeint.hpp typeof/incr_registration_group.hpp mp11.hpp algorithm/string/join.hpp asio/thread_pool.hpp asio/post.hpp /boost_teqp && \
 	zip -r /boost_teqp.zip /boost_teqp &&  \
 	tar cJf /boost_teqp.tar.xz /boost_teqp	
 
diff --git a/dev/docker/boost_bcp_docker/boost_teqp.tar.xz b/dev/docker/boost_bcp_docker/boost_teqp.tar.xz
index c07395ca9041ba3cc8d1bf708e7d7d6a126fa6ca..a73fe375fb8a8245e6893bc29fcbb7f3df9c8c99 100644
Binary files a/dev/docker/boost_bcp_docker/boost_teqp.tar.xz and b/dev/docker/boost_bcp_docker/boost_teqp.tar.xz differ
diff --git a/externals/mcx b/externals/mcx
index e76d2bf7a269a896aa816286d720cad94d55bcad..8203876bc834a4ddc47e785c6a4b366f31cf535e 160000
--- a/externals/mcx
+++ b/externals/mcx
@@ -1 +1 @@
-Subproject commit e76d2bf7a269a896aa816286d720cad94d55bcad
+Subproject commit 8203876bc834a4ddc47e785c6a4b366f31cf535e
diff --git a/include/teqp/algorithms/VLE.hpp b/include/teqp/algorithms/VLE.hpp
index f9ef0a9d0bbf82c856fc6d2bfa8a2aea4e3ce783..cdfa9a976bac8b4ef3129084f0f5a76e789b5113 100644
--- a/include/teqp/algorithms/VLE.hpp
+++ b/include/teqp/algorithms/VLE.hpp
@@ -296,9 +296,9 @@ auto solve_pure_critical(const Model& model, const Scalar T0, const Scalar rho0,
 }
 
 template<typename Model, typename Scalar>
-Eigen::ArrayXd extrapolate_from_critical(const Model& model, const Scalar Tc, const Scalar rhoc, const Scalar T) {
+Eigen::ArrayXd extrapolate_from_critical(const Model& model, const Scalar& Tc, const Scalar& rhoc, const Scalar& T) {
     
-    using tdx = TDXDerivatives<Model>;
+    using tdx = TDXDerivatives<Model, Scalar>;
     auto z = (Eigen::ArrayXd(1) << 1.0).finished();
     auto R = model.R(z);
     auto ders = tdx::template get_Ar0n<4>(model, Tc, rhoc, z);
diff --git a/include/teqp/models/pcsaft.hpp b/include/teqp/models/pcsaft.hpp
index d1d5677adefb0868c5e9e0ed948644523aa33752..fd0f413d78f74d21a7e42a05a849742871ebb579 100644
--- a/include/teqp/models/pcsaft.hpp
+++ b/include/teqp/models/pcsaft.hpp
@@ -66,7 +66,7 @@ auto get_a(TYPE mbar) {
     static Eigen::ArrayXd a_0 = (Eigen::ArrayXd(7) << 0.9105631445, 0.6361281449, 2.6861347891, -26.547362491, 97.759208784, -159.59154087, 91.297774084).finished();
     static Eigen::ArrayXd a_1 = (Eigen::ArrayXd(7) << -0.3084016918, 0.1860531159, -2.5030047259, 21.419793629, -65.255885330, 83.318680481, -33.746922930).finished();
     static Eigen::ArrayXd a_2 = (Eigen::ArrayXd(7) << -0.0906148351, 0.4527842806, 0.5962700728, -1.7241829131, -4.1302112531, 13.776631870, -8.6728470368).finished();
-    return forceeval(a_0 + ((mbar - 1.0) / mbar) * a_1 + ((mbar - 1.0) / mbar * (mbar - 2.0) / mbar) * a_2).eval();
+    return forceeval(a_0.cast<TYPE>() + ((mbar - 1.0) / mbar) * a_1.cast<TYPE>() + ((mbar - 1.0) / mbar * (mbar - 2.0) / mbar) * a_2.cast<TYPE>()).eval();
 }
 /// Eqn. A.19
 template<typename TYPE>
@@ -75,7 +75,7 @@ auto get_b(TYPE mbar) {
     static Eigen::ArrayXd b_0 = (Eigen::ArrayXd(7) << 0.724094694, 2.2382791861, -4.0025849485, -21.003576815, 26.855641363, 206.55133841, -355.60235612).finished();
     static Eigen::ArrayXd b_1 = (Eigen::ArrayXd(7) << -0.5755498075, 0.6995095521, 3.8925673390, -17.215471648, 192.67226447, -161.82646165, -165.20769346).finished();
     static Eigen::ArrayXd b_2 = (Eigen::ArrayXd(7) << 0.0976883116, -0.2557574982, -9.1558561530, 20.642075974, -38.804430052, 93.626774077, -29.666905585).finished();
-    return forceeval(b_0 + (mbar - 1.0) / mbar * b_1 + (mbar - 1.0) / mbar * (mbar - 2.0) / mbar * b_2).eval();
+    return forceeval(b_0.cast<TYPE>() + (mbar - 1.0) / mbar * b_1.cast<TYPE>() + (mbar - 1.0) / mbar * (mbar - 2.0) / mbar * b_2.cast<TYPE>()).eval();
 }
 /// Residual contribution to alphar from hard-sphere (Eqn. A.6)
 template<typename VecType>
@@ -180,7 +180,7 @@ private:
     std::vector<std::string> names;
     Eigen::ArrayXXd kmat; ///< binary interaction parameter matrix
 
-    void check_kmat(int N) {
+    void check_kmat(std::size_t N) {
         if (kmat.cols() != kmat.rows()) {
             throw teqp::InvalidArgument("kmat rows and columns are not identical");
         }
@@ -263,12 +263,15 @@ public:
             throw std::invalid_argument("Length of mole_fractions (" + std::to_string(mole_fractions.size()) + ") is not the length of components (" + std::to_string(N) + ")");
         }
 
-        using TRHOType = std::common_type_t<decltype(T), decltype(mole_fractions[0]), decltype(m[0])>;
+        using TRHOType = decltype(forceeval(T*rhomolar*mole_fractions[0]*m[0]));
 
         SAFTCalc<TTYPE, TRHOType> c;
-        c.m2_epsilon_sigma3_bar = 0;
-        c.m2_epsilon2_sigma3_bar = 0;
-        c.d = sigma_Angstrom*(1.0 - 0.12*exp(-3.0*epsilon_over_k/T)); // [A]
+        c.m2_epsilon_sigma3_bar = static_cast<TRHOType>(0.0);
+        c.m2_epsilon2_sigma3_bar = static_cast<TRHOType>(0.0);
+        c.d.resize(N);
+        for (std::size_t i = 0; i < N; ++i) {
+            c.d[i] = sigma_Angstrom[i]*(1.0 - 0.12 * exp(-3.0*epsilon_over_k[i]/T)); // [A]
+        }
         for (std::size_t i = 0; i < N; ++i) {
             for (std::size_t j = 0; j < N; ++j) {
                 // Eq. A.5
@@ -278,7 +281,7 @@ public:
                 c.m2_epsilon2_sigma3_bar = c.m2_epsilon2_sigma3_bar + mole_fractions[i] * mole_fractions[j] * m[i] * m[j] * pow(eij_over_k / T, 2) * pow(sigma_ij, 3);
             }
         }
-        auto mbar = (mole_fractions*m).sum();
+        auto mbar = (mole_fractions.cast<TRHOType>()*m.cast<TRHOType>()).sum();
 
         /// Convert from molar density to number density in molecules/Angstrom^3
         RhoType rho_A3 = rhomolar * N_A * 1e-30; //[molecules (not moles)/A^3]
@@ -292,7 +295,7 @@ public:
         for (std::size_t n = 0; n < 4; ++n) {
             // Eqn A.8
             auto dn = c.d.pow(n).eval();
-            TRHOType xmdn = forceeval((mole_fractions*m*dn).sum());
+            TRHOType xmdn = forceeval((mole_fractions.cast<TRHOType>()*m.cast<TRHOType>()*dn.cast<TRHOType>()).sum());
             zeta[n] = forceeval(pi6*rho_A3*xmdn);
         }
 
@@ -304,7 +307,7 @@ public:
 
         using tt = std::common_type_t<decltype(zeta[0]), decltype(c.d[0])>;
         Eigen::ArrayX<tt> lngii_hs(mole_fractions.size());
-        for (std::size_t i = 0; i < lngii_hs.size(); ++i) {
+        for (auto i = 0; i < lngii_hs.size(); ++i) {
             lngii_hs[i] = log(gij_HS(zeta, c.d, i, i));
         }
         auto alphar_hc = mbar * get_alphar_hs(zeta) - sumproduct(mole_fractions, mminus1, lngii_hs); // Eq. A.4
diff --git a/src/test_mpderivs.cpp b/src/test_mpderivs.cpp
index 80a19a2b0f95fa59cfcb6dc54de13375c344c050..9599a805721970d637e64f36fdc966b540f024c7 100644
--- a/src/test_mpderivs.cpp
+++ b/src/test_mpderivs.cpp
@@ -12,16 +12,13 @@ int main() {
     std::valarray<double> Tc_K = { 154.581}, pc_Pa = { 5042800}, acentric = { 0.022};
     auto modelPR = teqp::canonical_PR(Tc_K, pc_Pa, acentric);
 
-    using my_float = boost::multiprecision::number<boost::multiprecision::cpp_bin_float<200>>;
+    using my_float = boost::multiprecision::number<boost::multiprecision::cpp_bin_float<200>>; // Overkill: 200 digits of working precision!
+    
+    // Get the already very accurate values from the superancillary equation
     auto [rhoLdbl, rhoVdbl] = modelPR.superanc_rhoLV(125);
+    
+    // Now iterate in extended precision to find the VLE solution
     my_float T = 125;
     auto soln = teqp::pure_VLE_T<decltype(modelPR), my_float, teqp::ADBackends::multicomplex>(modelPR, T, static_cast<my_float>(rhoLdbl), static_cast<my_float>(rhoVdbl), 20).cast<double>();
     std::cout << soln << std::endl;
-
-    my_float x = 10567.6789;
-    std::function<mcx::MultiComplex<my_float>(const mcx::MultiComplex<my_float>&)> ff = [](const auto & x) {return 1.0 - x;};
-    auto o = mcx::diff_mcx1<my_float>(ff, x, 3, true);
-    std::cout << o[1] << std::endl; 
-
-    std::cout << std::is_arithmetic_v<my_float> << std::endl;
 }
\ No newline at end of file