/*
 * MIT License
 *
 * Copyright (c) 2002-2026 Mikko Tommila
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.apfloat;

import junit.framework.TestSuite;

/**
 * @version 1.16.0
 * @author Mikko Tommila
 */

public class ApcomplexMathTest
    extends ApfloatTestCase
{
    public ApcomplexMathTest(String methodName)
    {
        super(methodName);
    }

    public static void main(String[] args)
    {
        junit.textui.TestRunner.run(suite());
    }

    public static TestSuite suite()
    {
        TestSuite suite = new TestSuite();

        suite.addTest(new ApcomplexMathTest("testNegate"));
        suite.addTest(new ApcomplexMathTest("testAbs"));
        suite.addTest(new ApcomplexMathTest("testNorm"));
        suite.addTest(new ApcomplexMathTest("testScale"));
        suite.addTest(new ApcomplexMathTest("testIntegerPow"));
        suite.addTest(new ApcomplexMathTest("testInverseRoot"));
        suite.addTest(new ApcomplexMathTest("testRoot"));
        suite.addTest(new ApcomplexMathTest("testAllRoots"));
        suite.addTest(new ApcomplexMathTest("testAgm"));
        suite.addTest(new ApcomplexMathTest("testLog"));
        suite.addTest(new ApcomplexMathTest("testLogBase"));
        suite.addTest(new ApcomplexMathTest("testExp"));
        suite.addTest(new ApcomplexMathTest("testPow"));
        suite.addTest(new ApcomplexMathTest("testArg"));
        suite.addTest(new ApcomplexMathTest("testAcosh"));
        suite.addTest(new ApcomplexMathTest("testAsinh"));
        suite.addTest(new ApcomplexMathTest("testAtanh"));
        suite.addTest(new ApcomplexMathTest("testCosh"));
        suite.addTest(new ApcomplexMathTest("testSinh"));
        suite.addTest(new ApcomplexMathTest("testTanh"));
        suite.addTest(new ApcomplexMathTest("testAcos"));
        suite.addTest(new ApcomplexMathTest("testAsin"));
        suite.addTest(new ApcomplexMathTest("testAtan"));
        suite.addTest(new ApcomplexMathTest("testCos"));
        suite.addTest(new ApcomplexMathTest("testSin"));
        suite.addTest(new ApcomplexMathTest("testTan"));
        suite.addTest(new ApcomplexMathTest("testCot"));
        suite.addTest(new ApcomplexMathTest("testSinc"));
        suite.addTest(new ApcomplexMathTest("testW"));
        suite.addTest(new ApcomplexMathTest("testProduct"));
        suite.addTest(new ApcomplexMathTest("testSum"));
        suite.addTest(new ApcomplexMathTest("testGamma"));
        suite.addTest(new ApcomplexMathTest("testGammaIncomplete"));
        suite.addTest(new ApcomplexMathTest("testGammaIncompleteGeneralized"));
        suite.addTest(new ApcomplexMathTest("testLogGamma"));
        suite.addTest(new ApcomplexMathTest("testDigamma"));
        suite.addTest(new ApcomplexMathTest("testPolygamma"));
        suite.addTest(new ApcomplexMathTest("testBarnesG"));
        suite.addTest(new ApcomplexMathTest("testLogBarnesG"));
        suite.addTest(new ApcomplexMathTest("testBeta"));
        suite.addTest(new ApcomplexMathTest("testBetaIncomplete"));
        suite.addTest(new ApcomplexMathTest("testBetaIncompleteGeneralized"));
        suite.addTest(new ApcomplexMathTest("testPochhammer"));
        suite.addTest(new ApcomplexMathTest("testBinomial"));
        suite.addTest(new ApcomplexMathTest("testZeta"));
        suite.addTest(new ApcomplexMathTest("testZetaHurwitz"));
        suite.addTest(new ApcomplexMathTest("testHypergeometric0F1"));
        suite.addTest(new ApcomplexMathTest("testHypergeometric1F1"));
        suite.addTest(new ApcomplexMathTest("testHypergeometric2F1"));
        suite.addTest(new ApcomplexMathTest("testHypergeometric0F1Regularized"));
        suite.addTest(new ApcomplexMathTest("testHypergeometric1F1Regularized"));
        suite.addTest(new ApcomplexMathTest("testHypergeometric2F1Regularized"));
        suite.addTest(new ApcomplexMathTest("testHypergeometricU"));
        suite.addTest(new ApcomplexMathTest("testErf"));
        suite.addTest(new ApcomplexMathTest("testErfc"));
        suite.addTest(new ApcomplexMathTest("testErfi"));
        suite.addTest(new ApcomplexMathTest("testDawsonF"));
        suite.addTest(new ApcomplexMathTest("testFresnelS"));
        suite.addTest(new ApcomplexMathTest("testFresnelC"));
        suite.addTest(new ApcomplexMathTest("testExpIntegralE"));
        suite.addTest(new ApcomplexMathTest("testExpIntegralEi"));
        suite.addTest(new ApcomplexMathTest("testLogIntegral"));
        suite.addTest(new ApcomplexMathTest("testSinIntegral"));
        suite.addTest(new ApcomplexMathTest("testCosIntegral"));
        suite.addTest(new ApcomplexMathTest("testSinhIntegral"));
        suite.addTest(new ApcomplexMathTest("testCoshIntegral"));
        suite.addTest(new ApcomplexMathTest("testAiryAi"));
        suite.addTest(new ApcomplexMathTest("testAiryAiPrime"));
        suite.addTest(new ApcomplexMathTest("testAiryBi"));
        suite.addTest(new ApcomplexMathTest("testAiryBiPrime"));
        suite.addTest(new ApcomplexMathTest("testBesselJ"));
        suite.addTest(new ApcomplexMathTest("testBesselI"));
        suite.addTest(new ApcomplexMathTest("testBesselY"));
        suite.addTest(new ApcomplexMathTest("testBesselK"));
        suite.addTest(new ApcomplexMathTest("testStruveH"));
        suite.addTest(new ApcomplexMathTest("testStruveL"));
        suite.addTest(new ApcomplexMathTest("testAngerJ"));
        suite.addTest(new ApcomplexMathTest("testWeberE"));
        suite.addTest(new ApcomplexMathTest("testEllipticK"));
        suite.addTest(new ApcomplexMathTest("testEllipticE"));
        suite.addTest(new ApcomplexMathTest("testHermiteH"));
        suite.addTest(new ApcomplexMathTest("testLaguerreL"));
        suite.addTest(new ApcomplexMathTest("testLaguerreLGeneralized"));
        suite.addTest(new ApcomplexMathTest("testLegendreP"));
        suite.addTest(new ApcomplexMathTest("testLegendrePAssociated"));
        suite.addTest(new ApcomplexMathTest("testLegendreQ"));
        suite.addTest(new ApcomplexMathTest("testLegendreQAssociated"));
        suite.addTest(new ApcomplexMathTest("testSphericalHarmonicY"));
        suite.addTest(new ApcomplexMathTest("testChebyshevT"));
        suite.addTest(new ApcomplexMathTest("testChebyshevU"));
        suite.addTest(new ApcomplexMathTest("testGegenbauerCRenormalized"));
        suite.addTest(new ApcomplexMathTest("testGegenbauerC"));
        suite.addTest(new ApcomplexMathTest("testJacobiP"));
        suite.addTest(new ApcomplexMathTest("testFibonacci"));
        suite.addTest(new ApcomplexMathTest("testEulerE"));
        suite.addTest(new ApcomplexMathTest("testBernoulliB"));
        suite.addTest(new ApcomplexMathTest("testHarmonicNumber"));
        suite.addTest(new ApcomplexMathTest("testHarmonicNumberGeneralized"));
        suite.addTest(new ApcomplexMathTest("testPolylog"));
        suite.addTest(new ApcomplexMathTest("testClausenCl"));
        suite.addTest(new ApcomplexMathTest("testClausenSl"));
        suite.addTest(new ApcomplexMathTest("testClausenS"));
        suite.addTest(new ApcomplexMathTest("testClausenC"));
        suite.addTest(new ApcomplexMathTest("testLogisticSigmoid"));
        suite.addTest(new ApcomplexMathTest("testUlp"));

        return suite;
    }

    @SuppressWarnings("deprecation")
    public static void testNegate()
    {
        Apcomplex z = new Apcomplex("(2,3)");
        assertEquals("(2,3)", new Apcomplex("(-2,-3)"), ApcomplexMath.negate(z));

        z = new Apcomplex("0");
        assertEquals("0", new Apcomplex("0"), ApcomplexMath.negate(z));
    }

    public static void testAbs()
    {
        Apcomplex z = new Apcomplex("(3,4)");
        assertEquals("(3,4)", new Apfloat(5), ApcomplexMath.abs(z));

        z = new Apcomplex("-4");
        assertEquals("-4", new Apfloat(4), ApcomplexMath.abs(z));

        z = new Apcomplex("(0,-4)");
        assertEquals("(0,-4)", new Apfloat(4), ApcomplexMath.abs(z));

        z = new Apcomplex("0");
        assertEquals("0", new Apfloat(0), ApcomplexMath.abs(z));
    }

    public static void testNorm()
    {
        Apcomplex z = new Apcomplex(new Apfloat(2), new Apfloat(3));
        assertEquals("(2,3)", new Apfloat(13), ApcomplexMath.norm(z));

        z = new Apcomplex("0");
        assertEquals("0", new Apfloat(0), ApcomplexMath.norm(z));
    }

    public static void testScale()
    {
        Apcomplex z = new Apcomplex("(2,3)");
        assertEquals("(2,3)", new Apcomplex("(20,30)"), ApcomplexMath.scale(z, 1));

        z = new Apcomplex("0");
        assertEquals("0", new Apfloat(0), ApcomplexMath.scale(z, 1));
    }

    public static void testIntegerPow()
    {
        Apcomplex z = new Apcomplex(new Apfloat(2, 1000), new Apfloat(3, 1000));
        assertEquals("(2,3)^3", new Apcomplex("(-46,9)"), ApcomplexMath.pow(z, 3));
        z = new Apcomplex(new Apfloat(3, 1000), new Apfloat(4, 1000));
        assertEquals("(3,4)^-1", new Apcomplex("(0.12,-0.16)"), ApcomplexMath.pow(z, -1));
        assertEquals("(3,4)^-2", new Apcomplex("(-0.0112,-0.0384)"), ApcomplexMath.pow(z, -2));
        assertEquals("(3,4)^0", new Apcomplex("1"), ApcomplexMath.pow(z, 0));
        z = new Apcomplex(Apfloat.ZERO, new Apfloat(4, 1000));
        assertEquals("(0,4)^0", new Apcomplex("1"), ApcomplexMath.pow(z, 0));

        assertEquals("(2,3)^1000000000", ApcomplexMath.pow(z, 1000000000).precision(10), ApcomplexMath.pow(z.precision(11), 1000000000).precision(10));

        z = new Apcomplex("(0,1.0000000000000000000000000000000000000000100000000)");
        assertEquals("1.00000000000000000000000000000000000000001^0x7FFFFFFFFFFFFFFF", new Apcomplex("(0,-1.0000000000000000000000922337203685477580700042535)"), ApcomplexMath.pow(z, 0x7FFFFFFFFFFFFFFFL), new Apfloat(1e-48));
        assertEquals("1.00000000000000000000000000000000000000001^0x8000000000000000", new Apfloat("0.99999999999999999999990776627963145224192000425352"), ApcomplexMath.pow(z, 0x8000000000000000L), new Apfloat(1e-48));

        try
        {
            ApcomplexMath.pow(new Apcomplex("0"), 0);
            fail("0^0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be undefined
            assertEquals("Localization key", "pow.zeroToZero", aae.getLocalizationKey());
        }
    }

    public static void testInverseRoot()
    {
        Apcomplex z = new Apcomplex(new Apfloat(0), new Apfloat(1, 30));
        assertEquals("(0,1)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,1)^-1/2, value", new Apcomplex("(0.707106781186547524400844362105, -0.707106781186547524400844362105)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-30"));

        z = new Apcomplex(new Apfloat(0), new Apfloat(1, 20));
        assertEquals("(0,1)^-1/2, precision", 20, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,1)^-1/2, value", new Apcomplex("(0.70710678118654752440, -0.70710678118654752440)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-20"));

        z = new Apcomplex(new Apfloat(0), new Apfloat(1, 10));
        assertEquals("(0,1)^-1/2, precision", 10, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,1)^-1/2, value", new Apcomplex("(0.7071067812, -0.7071067812)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-10"));

        z = new Apcomplex(new Apfloat(0), new Apfloat(1, 5));
        assertEquals("(0,1)^-1/2, precision", 5, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,1)^-1/2, value", new Apcomplex("(0.70711, -0.70711)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-5"));

        z = new Apcomplex(new Apfloat(0), new Apfloat(-1, 30));
        assertEquals("(0,-1)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,-1)^-1/2, value", new Apcomplex("(0.707106781186547524400844362105, 0.707106781186547524400844362105)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-30"));

        z = new Apcomplex(new Apfloat(-1, 30), new Apfloat(0));
        assertEquals("(-1,0)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(-1,0)^-1/2, value", new Apcomplex("(0, -1)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-30"));

        z = new Apcomplex(new Apfloat(-1, 30), new Apfloat(0));
        assertEquals("(-1,0)^-1/3, precision", 30, ApcomplexMath.inverseRoot(z, 3).precision());
        assertEquals("(-1,0)^-1/3, value", new Apcomplex("(0.5, -0.866025403784438646763723170753)"), ApcomplexMath.inverseRoot(z, 3), new Apfloat("5e-30"));

        z = new Apcomplex(new Apfloat(-1, 30), new Apfloat(0));
        assertEquals("(-1,0)^-1/4, precision", 30, ApcomplexMath.inverseRoot(z, 4).precision());
        assertEquals("(-1,0)^-1/4, value", new Apcomplex("(0.707106781186547524400844362105, -0.707106781186547524400844362105)"), ApcomplexMath.inverseRoot(z, 4), new Apfloat("5e-30"));

        z = new Apcomplex("(-0.707106781186547524400844362105, 0.707106781186547524400844362105)");
        assertEquals("(-1/sqrt(2),1/sqrt(2))^-1/3, precision", 30, ApcomplexMath.inverseRoot(z, 3).precision());
        assertEquals("(-1/sqrt(2),1/sqrt(2))^-1/3, value", new Apcomplex("(0.707106781186547524400844362105, -0.707106781186547524400844362105)"), ApcomplexMath.inverseRoot(z, 3), new Apfloat("5e-30"));

        z = new Apcomplex("(0.707106781186547524400844362105, 0.707106781186547524400844362105)");
        assertEquals("(1/sqrt(2),1/sqrt(2))^-1/3, precision", 30, ApcomplexMath.inverseRoot(z, 3).precision());
        assertEquals("(1/sqrt(2),1/sqrt(2))^-1/3, value", new Apcomplex("(0.965925826289068286749743199729, -0.258819045102520762348898837624)"), ApcomplexMath.inverseRoot(z, 3), new Apfloat("5e-30"));

        z = new Apcomplex(new Apfloat(2, 30), new Apfloat(0));
        assertEquals("2^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("2^-1/2, value", new Apcomplex("0.707106781186547524400844362105"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-30"));

        z = new Apcomplex(new Apfloat("-1e20", 30), new Apfloat(1));
        assertEquals("(-1e20,1)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(-1e20,1)^-1/2, value", new Apcomplex(new Apfloat("5e-31", 30), new Apfloat("-1e-10", 30)), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-40"));

        z = new Apcomplex(new Apfloat("-1e20", 30), new Apfloat(-1));
        assertEquals("(-1e20,-1)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(-1e20,-1)^-1/2, value", new Apcomplex(new Apfloat("5e-31", 30), new Apfloat("1e-10", 30)), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-40"));

        z = new Apcomplex(new Apfloat(0), new Apfloat("1e2000", 30));
        assertEquals("(0,1e2000)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,1e2000)^-1/2, value", new Apcomplex("(0.707106781186547524400844362105e-1000, -0.707106781186547524400844362105e-1000)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat(1), new Apfloat("1e2000", 30));
        assertEquals("(1,1e2000)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(1,1e2000)^-1/2, value", new Apcomplex("(0.707106781186547524400844362105e-1000, -0.707106781186547524400844362105e-1000)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat(0), new Apfloat("-1e2000", 30));
        assertEquals("(0,-1e2000)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(0,-1e2000)^-1/2, value", new Apcomplex("(0.707106781186547524400844362105e-1000, 0.707106781186547524400844362105e-1000)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat(1), new Apfloat("-1e2000", 30));
        assertEquals("(1,-1e2000)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(1,-1e2000)^-1/2, value", new Apcomplex("(0.707106781186547524400844362105e-1000, 0.707106781186547524400844362105e-1000)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat("1e2000", 30), new Apfloat(0));
        assertEquals("(1e2000,0)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(1e2000,0)^-1/2, value", new Apcomplex("1e-1000"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat("1e2000", 30), new Apfloat(1));
        assertEquals("(1e2000,1)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(1e2000,1)^-1/2, value", new Apcomplex("1e-1000"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat("-1e2000", 30), new Apfloat(0));
        assertEquals("(-1e2000,0)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(-1e2000,0)^-1/2, value", new Apcomplex("(0, -1e-1000)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex(new Apfloat("-1e2000", 30), new Apfloat(1));
        assertEquals("(-1e2000,1)^-1/2, precision", 30, ApcomplexMath.inverseRoot(z, 2).precision());
        assertEquals("(-1e2000,1)^-1/2, value", new Apcomplex("(0, -1e-1000)"), ApcomplexMath.inverseRoot(z, 2), new Apfloat("5e-1030"));

        z = new Apcomplex("(-0.707106781186547524400844362105e3000, 0.707106781186547524400844362105e3000)");
        assertEquals("(-1e3000/sqrt(2),1e3000/sqrt(2))^-1/3, precision", 30, ApcomplexMath.inverseRoot(z, 3).precision());
        assertEquals("(-1e3000/sqrt(2),1e3000/sqrt(2))^-1/3, value", new Apcomplex("(0.707106781186547524400844362105e-1000, -0.707106781186547524400844362105e-1000)"), ApcomplexMath.inverseRoot(z, 3), new Apfloat("5e-1030"));

        assertEquals("1", new Apfloat(1), ApcomplexMath.inverseRoot(Apcomplex.ONE, 5));
        assertEquals("i^1/2", new Apcomplex("(0.70710678,0.70710678)"), ApcomplexMath.inverseRoot(new Apcomplex("(0,1.0000000)"), -2));

        z = new Apcomplex(new Apfloat("3.[encoded data, 50000 characters]"), new Apfloat("3.[encoded data, 50000 characters]"));
        Apcomplex invZ = new Apcomplex(new Apfloat("0.[encoded data, 50000 characters]"), new Apfloat("-0.[encoded data, 50000 characters]")),
                  invSqrtZ = new Apcomplex(new Apfloat("0.[encoded data, 50000 characters]"), new Apfloat("-0.[encoded data, 50000 characters]"));

        for (int prec = 25000; prec <= 50000; prec += 1000)
        {
            Apcomplex tmpZ = z.precision(prec),
                      expectedInvZ = invZ.precision(prec),
                      expectedInvSqrtZ = invSqrtZ.precision(prec),
                      actualInvZ = ApcomplexMath.inverseRoot(tmpZ, 1),
                      actualInvSqrtZ = ApcomplexMath.inverseRoot(tmpZ, 2);

            assertEquals("inv prec " + prec + " precision", prec, actualInvZ.precision());
            assertEquals("inv prec " + prec + " value", expectedInvZ, actualInvZ, new Apfloat("5e-" + prec));
            assertEquals("invsqrt prec " + prec + " precision", prec, actualInvSqrtZ.precision());
            assertEquals("invsqrt prec " + prec + " value", expectedInvSqrtZ, actualInvSqrtZ, new Apfloat("5e-" + prec));
        }

        z = new Apcomplex("(3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199,3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199e-20)");
        invZ = new Apcomplex("(0.318309886183790671537767526745028724068887460492294518428180911365119092396046181434178376080663353821009173544276311455642405854621090970373833904108972047312915693289356046049118109403439718172703494223105859718781812969543103286206394410806134813539553699626825863476727272799898208392521732801094763613545214073217354874639667048516536717204795290926651190121934930599524109477852654399389412872736085204160015325250614659445812229055084108341819036001796031629129394796573412318684485632518425385830357671174656209774572200992380951793462857729121730710703754813506833901088477689224753400237800184028789349091246281008776667281736464380349416427846404847680388469364742310525487683211843499436782010153659045483125565037272385913106741831620126137301310655977395673814982293995334905769140292085217372834361554984204900827704600919956923458209134644251890168698857503452823024163773233193012892383081929565070416391662340642298133395889765186066818049772720421198307486712656459423699740714924,-3.18309886183790671537767526745028724068887460492294518428180911365119092396046181434178376080663353821009173544276311455642405854621090970373833904108972047312915693289356046049118109403439718172703494223105859718781812969543103286206394410806134813539553699626825863476727272799898208392521732801094763613545214073217354874639667048516536717204795290926651190121934930599524109477852654399389412872736085204160015325250614659445812229055084108341819036001796031629129394796573412318684485632518425385830357671174656209774572200992380951793462857729121730710703754813506833901088477689224753400237800184028789349091246281008776667281736464380349416427846404847680388469364742310525487683211843499436782010153659045483125565037272385913106741831620126137301310655977395673814982293995334905769140292085217372834361554984204900827704600919956923458209134644251890168698857503452823024163773233193012892383081929565070416391662340642298133395889765186066818049772720421198307486712656459423699740714924e-21)");
        invSqrtZ = new Apcomplex("(0.564189583547756286948079451560772585844029472219615815983325168731208939469524264130849715258371807352118949175282690765845344942917477845270569742604457351973786191393343714152098802730948710056242456913534549142144868681124341539089763512011185016222112993127514023862896805089668633982814102772802015847857223491343393161133327212199033121274114199242243886056093480418532190764567074258299440784132207644069312567711083044479177537911030563217695713287365789838112929530752269146700963429727905088214177563066678695686031445447823998180399322898599028069989982482713328037727115586100854156652407125940257202088435542491586162644131107913481116958281820113230632775481749843710252733830295427323497470038385845571714020385150993253030073443070150859109512539452193591487227624349141289194482012167462681566049156405755813963874741659799112317643080264922748938583144492735585571155995975646825688024585904442417990229905395179613654357994285027995462492448607663494664326023222904298961716735477,-2.820947917738781434740397257803862929220076837400135610380757333724599600774390820496406021488337914539999917013808424821174183316705600346627044878665321316704542521132711956696115985692225461524144103674892886692811597954261197086278401249934262903436722704995347238317043044430197303220059198367524344827033735111145878843692931588007247802420701476138362763155773255754035575528173694450204821839899996342068039557128799949289686121250460169211402363399566614236747718540967339344797060583864253993886722179688695573684192522504572880979317725720745670246767341402104495822263278183453247632255562470843252936393521379423529102137851920938395838025560822786482305398364309855882826387811383500700796209016865318095637641931144775510847692507725489704866162502275965441880142102620023692574058012436283742735333878669894160523634912142148192752225318741559491075014194590494884342987343226966477362759864182357605917102577568819758568478928831698791913034318162836596723514735177322541225949696045e-21)");

        for (int prec = 500; prec <= 1000; prec += 50)
        {
            Apcomplex tmpZ = z.precision(prec),
                      expectedInvZ = invZ.precision(prec),
                      expectedInvSqrtZ = invSqrtZ.precision(prec),
                      actualInvZ = ApcomplexMath.inverseRoot(tmpZ, 1),
                      actualInvSqrtZ = ApcomplexMath.inverseRoot(tmpZ, 2);

            assertEquals("inv prec " + prec + " precision", prec, actualInvZ.precision());
            assertEquals("inv prec " + prec + " value", expectedInvZ, actualInvZ, new Apfloat("5e-" + prec));
            assertEquals("invsqrt prec " + prec + " precision", prec, actualInvSqrtZ.precision());
            assertEquals("invsqrt prec " + prec + " value", expectedInvSqrtZ, actualInvSqrtZ, new Apfloat("5e-" + prec));
        }

        z = new Apcomplex("(3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199e-20,3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199)");
        invZ = new Apcomplex("(3.18309886183790671537767526745028724068887460492294518428180911365119092396046181434178376080663353821009173544276311455642405854621090970373833904108972047312915693289356046049118109403439718172703494223105859718781812969543103286206394410806134813539553699626825863476727272799898208392521732801094763613545214073217354874639667048516536717204795290926651190121934930599524109477852654399389412872736085204160015325250614659445812229055084108341819036001796031629129394796573412318684485632518425385830357671174656209774572200992380951793462857729121730710703754813506833901088477689224753400237800184028789349091246281008776667281736464380349416427846404847680388469364742310525487683211843499436782010153659045483125565037272385913106741831620126137301310655977395673814982293995334905769140292085217372834361554984204900827704600919956923458209134644251890168698857503452823024163773233193012892383081929565070416391662340642298133395889765186066818049772720421198307486712656459423699740714924e-21,-0.318309886183790671537767526745028724068887460492294518428180911365119092396046181434178376080663353821009173544276311455642405854621090970373833904108972047312915693289356046049118109403439718172703494223105859718781812969543103286206394410806134813539553699626825863476727272799898208392521732801094763613545214073217354874639667048516536717204795290926651190121934930599524109477852654399389412872736085204160015325250614659445812229055084108341819036001796031629129394796573412318684485632518425385830357671174656209774572200992380951793462857729121730710703754813506833901088477689224753400237800184028789349091246281008776667281736464380349416427846404847680388469364742310525487683211843499436782010153659045483125565037272385913106741831620126137301310655977395673814982293995334905769140292085217372834361554984204900827704600919956923458209134644251890168698857503452823024163773233193012892383081929565070416391662340642298133395889765186066818049772720421198307486712656459423699740714924)");
        invSqrtZ = new Apcomplex("(0.398942280401432677941940771336389031865543401129091513282882250179772434419851767808651006965474553450231659632699401869161244597728783897275069734495032085216111887271560916882166876402125564868424323893838395079833719085290052945723478416783792406475917822229067524633036157052429629054952336706428571030187185130368246152628279046184365255879570477684594489756177508286624891300014994270929571804086453067394014233254639503393473181933215576035395390550639697849997906045852679378668246627935464340165981060328216264423323994665445336102173311228974531563690928652600365857426055953950317930869595684120658335492212442508507834457013088943568704831703105447241317646019451168564794944585905138454975351406084372143958122058613660877516675727140023601583669342317551944445825346281293391559591715805382904811500194433043087334063140186294620627312015177933295795822130423296667674673191468264898033406590955879437301865909636832022723153732099412803030603571832486087242410216578677303181161040972,-0.398942280401432677937951348532374705086143940529747694598123913207048338738616221978231886695149332457228174014279359091145043032910761545024527444992360506013704395545023729865459628156657910811196135090840777534898858802933750807644091893566642264434784387109684567850959336493692171697673283014869432855022112957977024436179321320242753133483455376103275583952799802580664801293539197676129806963898925886048129072348894165986263992243095527749288022655331420135724260556412139641344190345395202430297370019028628884610807050626790668495513149123868244378285115997893768231577855442515532795450441140924271501021684964050090674386687217757800362815660179461720592095429628585826372342230264108452648535563601356604345631990883903623336860080341288484907446373257062910833105988975533864466874928921595164065602310594305200462213282003201942543469515879364472417744667720718931280198196245354196327124908226579329264507159226749362033448374883848585906758047055682395695022774374795093935940257888)");

        for (int prec = 500; prec <= 1000; prec += 50)
        {
            Apcomplex tmpZ = z.precision(prec),
                      expectedInvZ = invZ.precision(prec),
                      expectedInvSqrtZ = invSqrtZ.precision(prec),
                      actualInvZ = ApcomplexMath.inverseRoot(tmpZ, 1),
                      actualInvSqrtZ = ApcomplexMath.inverseRoot(tmpZ, 2);

            // NOTE: EXTRA ALLOWED ERROR NEEDED FOR CASE prec=1000
            assertEquals("inv prec " + prec + " precision", prec, actualInvZ.precision());
            assertEquals("inv prec " + prec + " value", expectedInvZ, actualInvZ, new Apfloat("5e-" + prec));
            assertEquals("invsqrt prec " + prec + " precision", prec, actualInvSqrtZ.precision());
            assertEquals("invsqrt prec " + prec + " value", expectedInvSqrtZ, actualInvSqrtZ, new Apfloat("7e-" + prec));
        }

        assertEquals("1 branch 0", new Apfloat(1), ApcomplexMath.inverseRoot(Apcomplex.ONE, 5, 0));
        assertEquals("1 branch 10", new Apfloat(1), ApcomplexMath.inverseRoot(Apcomplex.ONE, 5, 10));
        assertEquals("1 branch 4", new Apfloat("-1.000"), ApcomplexMath.inverseRoot(new Apfloat("1.000"), 8, 4), new Apfloat("0.005"));
        assertEquals("1 branch 6", new Apcomplex("(0,1.000)"), ApcomplexMath.inverseRoot(new Apfloat("1.000"), 8, 6), new Apfloat("0.005"));
        assertEquals("(18,26) branch 1", new Apcomplex("(-0.2366,-0.2098)"), ApcomplexMath.inverseRoot(new Apcomplex("(18.000,26.000)"), 3, 1), new Apfloat("0.005"));
        assertEquals("(18,26) branch 2", new Apcomplex("(-0.0634,0.3098)"), ApcomplexMath.inverseRoot(new Apcomplex("(18.000,26.000)"), 3, 2), new Apfloat("0.005"));

        try
        {
            ApcomplexMath.inverseRoot(z, 0);
            fail("inverse zeroth root accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: inverse zeroth root
            assertEquals("Localization key", "inverseRoot.zeroth", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.inverseRoot(new Apcomplex("0"), 2);
            fail("inverse sqrt of 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: result would be infinite
            assertEquals("Localization key", "inverseRoot.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.inverseRoot(new Apcomplex(new Apfloat(0), new Apfloat(3)), 2);
            fail("infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK: can't have infinite memory
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testRoot()
    {
        assertEquals("0", new Apfloat(0), ApcomplexMath.root(Apcomplex.ZERO, 3));
        assertEquals("1", new Apfloat(1), ApcomplexMath.root(Apcomplex.ONE, 5));
        assertEquals("1st root", new Apcomplex(new Apfloat(2), new Apfloat(3)), ApcomplexMath.root(new Apcomplex(new Apfloat(2), new Apfloat(3)), 1));
        assertEquals("root(-2, 2)", new Apcomplex(Apfloat.ZERO, new Apfloat(1.4142135623730950488016887242097)), ApcomplexMath.root(new Apfloat(-2.0), 2), new Apfloat(1e-15));
        assertEquals("root(-2, -2)", new Apcomplex(Apfloat.ZERO, new Apfloat(-0.70710678118654752440084436210485)), ApcomplexMath.root(new Apfloat(-2.0), -2), new Apfloat(5e-16));
        assertEquals("root((-46,9), 3)", new Apcomplex("(2.0,3.0)"), ApcomplexMath.root(new Apcomplex("(-46.000,9.000)"), 3), new Apfloat("0.5"));
        assertEquals("root((-46,-9), 3)", new Apcomplex("(2.0,-3.0)"), ApcomplexMath.root(new Apcomplex("(-46.000,-9.000)"), 3), new Apfloat("0.5"));
        //assertEquals("0x7FFFFFFFFFFFFFFFth root of 2", new Apfloat("1.0000000000000000000751511679015"), ApcomplexMath.root(new Apfloat(2, 30), 0x7FFFFFFFFFFFFFFFL), new Apfloat(2e-29));
        //assertEquals("0x8000000000000000th root of 2", new Apfloat("0.99999999999999999992484883209847"), ApcomplexMath.root(new Apfloat(2, 30), 0x8000000000000000L), new Apfloat(2e-29));
        assertEquals("sqrt(-2)", new Apcomplex(Apfloat.ZERO, new Apfloat(1.4142135623730950488016887242097)), ApcomplexMath.sqrt(new Apfloat(-2.0)), new Apfloat(1e-15));
        assertEquals("cbrt(3/4pi theta)", new Apcomplex(new Apfloat(0.70710678118654752440084436210485), new Apfloat(0.70710678118654752440084436210485)), ApcomplexMath.cbrt(new Apcomplex(new Apfloat(-0.70710678118654752440084436210485), new Apfloat(0.70710678118654752440084436210485))), new Apfloat(1e-15));
        assertEquals("cbrt(-1)", new Apcomplex(new Apfloat(0.5), new Apfloat(0.86602540378443864676372317075294)), ApcomplexMath.cbrt(new Apcomplex(new Apfloat(-1.0))), new Apfloat(1e-15));
        assertEquals("cbrt((-46,9), 3)", new Apcomplex("(2.0,3.0)"), ApcomplexMath.cbrt(new Apcomplex("(-46.0,9.0)")), new Apfloat("0.05"));
        assertEquals("cbrt((-46,-9), 3)", new Apcomplex("(2.0,-3.0)"), ApcomplexMath.cbrt(new Apcomplex("(-46.0,-9.0)")), new Apfloat("0.05"));
        assertEquals("cbrt((18,26), 3)", new Apcomplex("(3.0,1.0)"), ApcomplexMath.cbrt(new Apcomplex("(18.0,26.0)")), new Apfloat("0.05"));

        assertEquals("0 branch 1", new Apfloat(0), ApcomplexMath.root(Apcomplex.ZERO, 3, 1));
        assertEquals("0 branch 2", new Apfloat(0), ApcomplexMath.root(Apcomplex.ZERO, 3, 2));
        assertEquals("1 branch 10", new Apfloat(1), ApcomplexMath.root(Apcomplex.ONE, 5, 10));
        assertEquals("1 branch 4", new Apfloat("-1.000"), ApcomplexMath.root(new Apfloat("1.000"), 8, 4), new Apfloat("0.005"));
        assertEquals("1st root branch 2", new Apcomplex(new Apfloat(2), new Apfloat(3)), ApcomplexMath.root(new Apcomplex(new Apfloat(2), new Apfloat(3)), 1, 2));
        assertEquals("root(-2, 2) branch 1", new Apcomplex(Apfloat.ZERO, new Apfloat(-1.4142135623730950488016887242097)), ApcomplexMath.root(new Apfloat(-2.0), 2, 1), new Apfloat(1e-15));
        assertEquals("root(-2, -2) branch -1", new Apcomplex(Apfloat.ZERO, new Apfloat(0.70710678118654752440084436210485)), ApcomplexMath.root(new Apfloat(-2.0), -2, -1), new Apfloat(5e-16));
        assertEquals("root(-2, -2) branch 3", new Apcomplex(Apfloat.ZERO, new Apfloat(0.70710678118654752440084436210485)), ApcomplexMath.root(new Apfloat(-2.0), -2, 3), new Apfloat(5e-16));
        assertEquals("roots((-46,9), 3) branch 1", new Apcomplex("(-3.598,0.232)"), ApcomplexMath.root(new Apcomplex("(-46.000,9.000)"), 3, 1), new Apfloat("0.005"));
        assertEquals("roots((-46,9), 3) branch 2", new Apcomplex("(1.598,-3.232)"), ApcomplexMath.root(new Apcomplex("(-46.000,9.000)"), 3, 2), new Apfloat("0.005"));
        assertEquals("roots((-46,-9), 3) branch 1", new Apcomplex("(-3.598,-0.232)"), ApcomplexMath.root(new Apcomplex("(-46.000,-9.000)"), 3, 1), new Apfloat("0.005"));
        assertEquals("roots((-46,-9), 3) branch 2", new Apcomplex("(1.598,3.232)"), ApcomplexMath.root(new Apcomplex("(-46.000,-9.000)"), 3, 2), new Apfloat("0.005"));
        assertEquals("cbrt((18,26), 3) branch 1", new Apcomplex("(-2.366,2.098)"), ApcomplexMath.root(new Apcomplex("(18.000,26.000)"), 3, 1), new Apfloat("0.005"));
        assertEquals("cbrt((18,26), 3) branch 2", new Apcomplex("(-0.634,-3.098)"), ApcomplexMath.root(new Apcomplex("(18.000,26.000)"), 3, 2), new Apfloat("0.005"));

        assertEquals("0 radix 12", 12, ApcomplexMath.root(new Apint(0, 12), 3).radix());
        assertEquals("-4 real part radix 12", 12, ApcomplexMath.root(new Apfloat(-4, 5, 12), 2).real().radix());

        try
        {
            ApcomplexMath.root(new Apcomplex("(2.0, 3.0)"), 0);
            fail("0th root accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: zeroth root
            assertEquals("Localization key", "root.zeroth", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.root(new Apcomplex("0"), -5);
            fail("Inverse root of zero accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: inverse root of zero
            assertEquals("Localization key", "inverseRoot.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.root(new Apcomplex("0"), 0);
            fail("0th root of 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: result would be undefined
            assertEquals("Localization key", "root.zeroth", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.root(new Apcomplex(new Apfloat(2), new Apfloat(3)), 2);
            fail("infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK: can't have infinite memory
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAllRoots()
    {
        Apcomplex[] allRoots = ApcomplexMath.allRoots(Apcomplex.ZERO, 3);
        assertEquals("0 length", 3, allRoots.length);
        assertEquals("0[0]", new Apfloat(0), allRoots[0]);
        assertEquals("0[1]", new Apfloat(0), allRoots[1]);
        assertEquals("0[2]", new Apfloat(0), allRoots[2]);

        allRoots = ApcomplexMath.allRoots(new Apcomplex("1"), 4);
        assertEquals("1 length", 4, allRoots.length);
        assertEquals("1[0]", new Apcomplex("1"), allRoots[0]);
        assertEquals("1[1]", new Apcomplex("(0,1)"), allRoots[1]);
        assertEquals("1[2]", new Apcomplex("-1"), allRoots[2]);
        assertEquals("1[3]", new Apcomplex("(0,-1)"), allRoots[3]);

        allRoots = ApcomplexMath.allRoots(new Apcomplex("-1.0"), 2);
        assertEquals("-1 length", 2, allRoots.length);
        assertEquals("-1[0]", new Apcomplex("(0,1.0)"), allRoots[0]);
        assertEquals("-1[1]", new Apcomplex("(0,-1.0)"), allRoots[1]);

        allRoots = ApcomplexMath.allRoots(new Apcomplex("(0,1.00)"), 2);
        assertEquals("i length", 2, allRoots.length);
        assertEquals("i[0]", new Apcomplex("(0.707,0.707)"), allRoots[0]);
        assertEquals("i[1]", new Apcomplex("(-0.707,-0.707)"), allRoots[1]);

        allRoots = ApcomplexMath.allRoots(new Apcomplex(new Apfloat(2), new Apfloat(3)), 1);
        assertEquals("1st root length", 1, allRoots.length);
        assertEquals("1st root[0]", new Apcomplex(new Apfloat(2), new Apfloat(3)), allRoots[0]);

        allRoots = ApcomplexMath.allRoots(new Apcomplex("(-46.000,9.000)"), 3);
        assertEquals("allRoots((-46,9), 3) length", 3, allRoots.length);
        assertEquals("allRoots((-46,9), 3)[0]", new Apcomplex("(2.000,3.000)"), allRoots[0], new Apfloat("0.005"));
        assertEquals("allRoots((-46,9), 3)[1]", new Apcomplex("(-3.598,0.232)"), allRoots[1], new Apfloat("0.005"));
        assertEquals("allRoots((-46,9), 3)[2]", new Apcomplex("(1.598,-3.232)"), allRoots[2], new Apfloat("0.005"));

        allRoots = ApcomplexMath.allRoots(new Apcomplex("(-46.000,-9.000)"), 3);
        assertEquals("allRoots((-46,-9), 3) length", 3, allRoots.length);
        assertEquals("allRoots((-46,-9), 3)[0]", new Apcomplex("(2.000,-3.000)"), allRoots[0], new Apfloat("0.005"));
        assertEquals("allRoots((-46,-9), 3)[1]", new Apcomplex("(-3.598,-0.232)"), allRoots[1], new Apfloat("0.005"));
        assertEquals("allRoots((-46,-9), 3)[2]", new Apcomplex("(1.598,3.232)"), allRoots[2], new Apfloat("0.005"));

        allRoots = ApcomplexMath.allRoots(new Apcomplex("-4.000"), -4);
        assertEquals("allRoots(-4,-4) length", 4, allRoots.length);
        assertEquals("allRoots(-4,-4)[0]", new Apcomplex("(0.500,-0.500)"), allRoots[0], new Apfloat("0.005"));
        assertEquals("allRoots(-4,-4)[1]", new Apcomplex("(-0.500,-0.500)"), allRoots[1], new Apfloat("0.005"));
        assertEquals("allRoots(-4,-4)[2]", new Apcomplex("(-0.500,0.500)"), allRoots[2], new Apfloat("0.005"));
        assertEquals("allRoots(-4,-4)[3]", new Apcomplex("(0.500,0.500)"), allRoots[3], new Apfloat("0.005"));

        allRoots = ApcomplexMath.allRoots(new Apint(0, 12), 2);
        assertEquals("allRoots(0, 2) length", 2, allRoots.length);
        assertEquals("allRoots(0, 2)[0] radix", 12, allRoots[0].radix());
        assertEquals("allRoots(0, 2)[1] radix", 12, allRoots[0].radix());

        try
        {
            ApcomplexMath.allRoots(new Apcomplex("(2.0, 3.0)"), 0);
            fail("0th root accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: zeroth root
            assertEquals("Localization key", "root.zeroth", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.allRoots(Apcomplex.ZERO, -1);
            fail("inverse root of zero accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK: inverse root of zero
            assertEquals("Localization key", "inverseRoot.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.allRoots(new Apcomplex(new Apfloat(2), new Apfloat(3)), 2);
            fail("infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK: can't have infinite memory
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.allRoots(new Apcomplex("1"), 0x80000000);
            fail("negative array size accepted");
        }
        catch (ApfloatRuntimeException are)
        {
            // OK: result would not fit in an array
            assertEquals("Localization key", "maximumArraySizeExceeded", are.getLocalizationKey());
        }
    }

    public static void testAgm()
    {
        Apcomplex a = ApcomplexMath.agm(new Apcomplex(new Apfloat(2, 100), new Apfloat(3, 100)),
                                        new Apcomplex(new Apfloat(4, 100), new Apfloat(5, 100)));
        assertEquals("(2,3), (4,5) precision", 100, a.precision());
        assertEquals("(2,3), (4,5) value", new Apcomplex("(2.917544260525786263696583078746606829791948283056476178719125080604001346981059514497122989501231285,3.939113046692836869408348425071199799284873423064425353396384561367021573926690156072311985300901402)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 1), new Apfloat(2, 1)),
                              new Apcomplex(new Apfloat(2, 1), new Apfloat(1, 1)));
        assertEquals("(1,2), (2,1), prec 1, precision", 1, a.precision());
        assertEquals("(1,2), (2,1), prec 1, value", new Apcomplex("(1,1)"), a, new Apfloat(1));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 20), new Apfloat(2, 20)),
                              new Apcomplex(new Apfloat(1, 10), new Apfloat(2, 10)));
        assertEquals("(1,2), (1,2), prec 10-20, precision", 10, a.precision());
        assertEquals("(1,2), (1,2), prec 10-20, value", new Apcomplex("(1,2)"), a);

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("(1,2), (3,4), prec 10-20, precision", 10, a.precision());
        assertEquals("(1,2), (3,4), prec 10-20, value", new Apcomplex("(1.877468123,2.921948542)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(4, 10)));
        assertEquals("(-1,2), (3,4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,2), (3,4), prec 10, value", new Apcomplex("(0.657368426,3.174083677)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(4, 10)));
        assertEquals("(1,-2), (3,4), prec 10, precision", 10, a.precision());
        assertEquals("(1,-2), (3,4), prec 10, value", new Apcomplex("(2.676463508,0.428671830)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(4, 10)));
        assertEquals("(-1,-2), (3,4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,-2), (3,4), prec 10, value", new Apcomplex("(2.051752596,-0.072458699)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(4, 10)));
        assertEquals("(1,2), (-3,4), prec 10, precision", 10, a.precision());
        assertEquals("(1,2), (-3,4), prec 10, value", new Apcomplex("(-0.657368426,3.174083677)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(4, 10)));
        assertEquals("(-1,2), (-3,4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,2), (-3,4), prec 10, value", new Apcomplex("(-1.877468123,2.921948542)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(4, 10)));
        assertEquals("(1,-2), (-3,4), prec 10, precision", 10, a.precision());
        assertEquals("(1,-2), (-3,4), prec 10, value", new Apcomplex("(-2.051752596,-0.072458699)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(4, 10)));
        assertEquals("(-1,-2), (-3,4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,-2), (-3,4), prec 10, value", new Apcomplex("(-2.676463508,0.428671830)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(-4, 10)));
        assertEquals("(1,2), (3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(1,2), (3,-4), prec 10, value", new Apcomplex("(2.676463508,-0.428671830)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(-4, 10)));
        assertEquals("(-1,2), (3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,2), (3,-4), prec 10, value", new Apcomplex("(2.051752596,0.072458699)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(-4, 10)));
        assertEquals("(1,-2), (3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(1,-2), (3,-4), prec 10, value", new Apcomplex("(1.877468123,-2.921948542)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(3, 10), new Apfloat(-4, 10)));
        assertEquals("(-1,-2), (3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,-2), (3,-4), prec 10, value", new Apcomplex("(0.657368426,-3.174083677)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(-4, 10)));
        assertEquals("(1,2), (-3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(1,2), (-3,-4), prec 10, value", new Apcomplex("(-2.051752596,0.072458699)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(-4, 10)));
        assertEquals("(-1,2), (-3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,2), (-3,-4), prec 10, value", new Apcomplex("(-2.676463508,-0.428671830)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(-4, 10)));
        assertEquals("(1,-2), (-3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(1,-2), (-3,-4), prec 10, value", new Apcomplex("(-0.657368426,-3.174083677)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 10), new Apfloat(-2, 10)),
                              new Apcomplex(new Apfloat(-3, 10), new Apfloat(-4, 10)));
        assertEquals("(-1,-2), (-3,-4), prec 10, precision", 10, a.precision());
        assertEquals("(-1,-2), (-3,-4), prec 10, value", new Apcomplex("(-1.877468123,-2.921948542)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(0)), new Apcomplex(new Apfloat(1)));
        assertEquals("0, 1", new Apfloat(0), a);

        a = ApcomplexMath.agm(Apcomplex.ONE, Apcomplex.ZERO);
        assertEquals("1, 0", new Apfloat(0), a);

        a = ApcomplexMath.agm(Apcomplex.ZERO, new Apcomplex("(0,1)"));
        assertEquals("0, i", new Apfloat(0), a);

        a = ApcomplexMath.agm(new Apcomplex("(0,1)"), Apcomplex.ZERO);
        assertEquals("i, 0", new Apfloat(0), a);

        a = ApcomplexMath.agm(new Apfloat(-1.2, 10), new Apfloat(1.2, 10));
        assertEquals("-1.2, 1.2", new Apcomplex("0"), a);

        a = ApcomplexMath.agm(new Apfloat(1.2, 10), new Apfloat(1.3, 10));
        assertEquals("1.2, 1.3 precision", 10, a.precision());
        assertEquals("1.2, 1.3 value", new Apcomplex("1.249499750"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apfloat(-1.2, 10), new Apfloat(-1.3, 10));
        assertEquals("-1.2, -1.3 precision", 10, a.precision());
        assertEquals("-1.2, -1.3 value", new Apcomplex("-1.249499750"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apfloat(-1.2, 10), new Apfloat(1.3, 10));
        assertEquals("-1.2, 1.3 precision", 10, a.precision());
        assertEquals("-1.2, 1.3 value", new Apcomplex("(0.1302427887,0.3818051176)"), a, new Apfloat("5e-10"));

        a = ApcomplexMath.agm(new Apcomplex(Apfloat.ZERO, new Apfloat(1, 10)),
                              new Apcomplex(Apfloat.ZERO, new Apfloat(2, 20)));
        assertEquals("1i, 2i, prec 10-20, precision", 10, a.precision());
        assertEquals("1i, 2i, prec 10-20, value", new Apcomplex("(0,1.456791031)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(Apfloat.ZERO, new Apfloat(-1, 20)),
                              new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("-1i, -2i, prec 10-20, precision", 10, a.precision());
        assertEquals("-1i, -2i, prec 10-20, value", new Apcomplex("(0,-1.456791031)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.agm(new Apcomplex(Apfloat.ZERO, new Apfloat(1, 10)),
                              new Apcomplex(Apfloat.ZERO, new Apfloat(1, 20)));
        assertEquals("i, i, prec 10-20, precision", 10, a.precision());
        assertEquals("i, i, prec 10-20, value", new Apcomplex("(0,1)"), a);

        a = ApcomplexMath.agm(new Apcomplex(Apfloat.ZERO, new Apfloat(1, 20)),
                              new Apcomplex(Apfloat.ZERO, new Apfloat(1, 10)));
        assertEquals("i, i, prec 20-10, precision", 10, a.precision());
        assertEquals("i, i, prec 20-10, value", new Apcomplex("(0,1)"), a);

        a = ApcomplexMath.agm(new Apcomplex(Apfloat.ZERO, new Apfloat("1.000000000e10")),
                              new Apcomplex(Apfloat.ZERO, new Apfloat("1.000000000e-10")));
        assertEquals("1e10i, 1e-10i, precision", 10, a.precision());
        assertEquals("1e10i, 1e-10i, value", new Apcomplex("(0,331126196.7)"), a, new Apfloat("0.5"));

        a = ApcomplexMath.agm(new Apcomplex(Apfloat.ZERO, new Apfloat("1.0000000000000000000e10")),
                              new Apcomplex(Apfloat.ZERO, new Apfloat("1.000000000e-10")));
        assertEquals("1e10i, 1e-10i, precision 10-20", 10, a.precision());
        assertEquals("1e10i, 1e-10i, value, precision 10-20", new Apcomplex("(0,331126196.7)"), a, new Apfloat("0.5"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(2, 3000), new Apfloat(3, 3000)),
                              new Apcomplex(new Apfloat(4, 3000), new Apfloat(5, 3000)));
        assertEquals("(2,3), (4,5) precision 3000", 3000, a.precision());
        assertEquals("(2,3), (4,5) value 3000", new Apcomplex("(2.91754426052578626369658307874660682979194828305647617871912508060400134698105951449712298950123128562803369971608115858308936341123999327021346691138617183468446010737173164686210382470722972480385653096197955212595851386829730542017554834566076203624841629838837088111415383201962147391676642929058049817171098768157845839182061367660407624587113859085064455636920311607051981588597485536439305356293985101422595947649995371848599841753952499159126778852783849867972638132163229170462055215173927004466893155827350288414651232923783719736757181961513759146922026017058314213265164777972026914569278829769779023008225176184785498679682429641281302037486486521259687322336298021286618318415793710998463135836032875126545906276937050649443180086254169974282261221943615961474499125922697942531490842409305517925243257370218203245337833554418491842015943129213675762563419679038299132768627013663409472496225092290179397048258626692981873018305739254012305825026785891069123260517749979272211407491610089628959933724343122851980961660974260652181762103017936720767079145977839033281414352440639482552619868342969287513114456467494665868602786146218358077830070649048842337372991463043085279850727992640025660675380800254896810540213312123740821486832723122822609732501981710205986586577716162755069535207170070281037295556916467016669193561963726840316454962656506333047304666768044715822566242597700196677480301214952192861971988192656671744822490672697455664407140156730909231414013792802915135066242203113030716533667093257173402035594912939322282536077875674712764039027921927395197312547828266486016427640712420409764391754400652438995087760043085410360352341590241567046208031995471079328190006083782215711890791023443288680631383270729328245112098679248986918816410547156221869838319395337641455545236996980728609516738564908590670336904562106389447988845227636370340561649189020526564471128076963110284359493508944882615621434470215215697096025821872457004381345157727508034579204708799556234634004705842562329299420551585588232322265609498279231361039397683526002176899737997607538350921282494819816685120478868231090842595792591353576389181664605419273590632452310701393757926374438862479436554656101458985479249471472107699248705141561173712162097645050207626741418394746768164124670747173806773839597678289144754574734901040652010616194325729394023497262795568290483391326776172203388816276143223100903063086097060671378537506215702097576424605396225829921915151624090646742547987876299045332164101681114965791902981323550059875554202160881410486800946958238200767776068800905156439104937878902630802229026038558376052682025048018360113971819953917492535105743883667564195635498783445254231425089663831105369011694312663969400247121569845918627337905950490146786267588981716145101263064118596121741830302772515682282427194397934820742615189129211740981191425117917799767751060222539769267812947175474295243812595876964356919305482207550832587361273920159765406099319385252761850724428775715,3.93911304669283686940834842507119979928487342306442535339638456136702157392669015607231198530090140243949188290043429681557054024497519997714555187094318119446656556235082719330646782894759630438224022549553159147839217538004290128346087094038704007635212437747396661652367449483064282116458523952847341804070956765337261810846795283243730734590753449997447035281029295162928561049306004649118029649069256105503936796313664026977955159526283914846577547135764309851062923566730093681247668624871510666978126929508258099172045717391063101370239395419225705660926248842628084124376628056009064933668417324363913211419327954479103622167143221861590472148278185932670718814750047414193099895865869943477950105875157760091959759003434005966714649800873204258385294726671809906947015516595685711589454524234633598253319737514012268529650713739946676006981825396015444889386661029474872321206464973652372992130362462446398118626962435894308122356649646871349298187623711624971863476352762452221531183277320146100515317455662186611756111268760306975797019057296312184964013993084636666054078035009036249564083908773875800800166359587268483598525125806091226592778234809046332031551598992262638508581536585324305299591750302881483402739828364598398277730258197204969256091757799115119279623658639479367023067719518871651401707913451169051716348607113140192819952450181861796320610091212802617662333291955214929303347143495395840187888757139608191824192807233083558513911809059740349333087862760616275786722727908487366481453538363428895942223277133414813782540149625894704335654023680217631160052319030202630292942814891747431353863732117821363156846713863280617323679888536660636763839907093252497571827138167886149907772607307351368861795816765379220178268412856307579450653416268935107888700416468284108022921355702851498202881502762305540563232079766276637149902654506931054207254907043868092497807310230653405754717803877751418950428686594560372055456167827239476527970744301094268551441890020407558514144268177782841988620322994163840112592854907705270880910991400937352699877335762302999419793473129331441989800560461441763701563331940266726598599293771986578531341036022144096025745155626608882782484494825814636845245413589466189311555767748030432015023292022231992210329782566184971816685421724834819675158353561452463411398141131533561617853176875463475127794571247641075930817108546879442258495905380115608124074575312893808818647331957099686532636924786401829250331323516175691344769031519765960343036596327787933330699717223235941567369627380749831452883229157945444590678814697824995710977262891494397099520222876736838798922496231008700179679987264466109787010313153842130194074782194326215333849204597293821883655534230029263086716683924996834814477422800580002681248614408636157256745534681222987070933199461219239318856812325932811189024056557789637085405421384060709459119263501223615502437218473705700310779175993531915209583296165864005423678994006648697891946757802094451363373198938559)"), a, new Apfloat("5e-2999"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-2, 30), new Apfloat("1.000000000e-40")),
                              new Apfloat(1));
        assertEquals("(-2,1e-40), (1,0) precision", 30, a.precision());
        assertEquals("(-2,1e-40), (1,0) value", new Apcomplex("(-0.422966208408801687364597406061,0.661266183461804764467239865563)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-2, 30), new Apfloat("-1.000000000e-40")),
                              new Apfloat(1));
        assertEquals("(-2,-1e-40), (1,0) precision", 30, a.precision());
        assertEquals("(-2,-1e-40), (1,0) value", new Apcomplex("(-0.422966208408801687364597406061,-0.661266183461804764467239865563)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(-1, 30), new Apfloat(1, 30)),
                              new Apcomplex(new Apfloat(-1, 30), new Apfloat(-1, 30)));
        assertEquals("(-1,1), (-1,-1) precision", 30, a.precision());
        assertEquals("(-1,1), (-1,-1) value", new Apcomplex("-1.198140234735592207439922492280"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.agm(new Apcomplex(new Apfloat(1, 30), new Apfloat(1, 30)),
                              new Apcomplex(new Apfloat(1, 30), new Apfloat(-1, 30)));
        assertEquals("(1,1), (1,-1) precision", 30, a.precision());
        assertEquals("(1,1), (1,-1) value", new Apcomplex("1.198140234735592207439922492280"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.agm(new Apint(1, 12), new Apint(0, 12));
        assertEquals("1, 0 radix", 12, a.radix());
        a = ApcomplexMath.agm(new Apcomplex(Apint.ZERO, new Apint(1, 12)), new Apcomplex(Apint.ZERO, new Apint(-1, 12)));
        assertEquals("i, -i radix", 12, a.radix());

        try
        {
            ApcomplexMath.agm(new Apcomplex(new Apfloat(1)), new Apcomplex(new Apfloat(2), new Apfloat(3)));
            fail("AGM to infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; can't calculate this to infinite precision
            assertEquals("Localization key", "agm.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLog()
    {
        Apcomplex a = ApcomplexMath.log(new Apcomplex(new Apfloat(2, 100)));
        assertEquals("2, 100 precision", 100, a.precision());
        assertEquals("2, 100 value", new Apcomplex("0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex(new Apfloat(-2, 100)));
        assertEquals("-2, 100 precision", 100, a.precision());
        assertEquals("-2, 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 100)));
        assertEquals("2i, 100 precision", 100, a.precision());
        assertEquals("2i, 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 100)));
        assertEquals("-2i, 100 precision", 100, a.precision());
        assertEquals("-2i, 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,-1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex("(1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"));
        assertEquals("(sqrt2,sqrt2), 100 precision", 99, a.precision());
        assertEquals("(sqrt2,sqrt2), 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529266996)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex("(1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"));
        assertEquals("(sqrt2,-sqrt2), 100 precision", 99, a.precision());
        assertEquals("(sqrt2,-sqrt2), 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,-0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529266996)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex("(-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"));
        assertEquals("(-sqrt2,sqrt2), 100 precision", 100, a.precision());
        assertEquals("(-sqrt2,sqrt2), 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,2.356194490192344928846982537459627163147877049531329365731208444230862304714656748971026119006587801)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex("(-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"));
        assertEquals("(-sqrt2,-sqrt2), 100 precision", 100, a.precision());
        assertEquals("(-sqrt2,-sqrt2), 100 value", new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,-2.356194490192344928846982537459627163147877049531329365731208444230862304714656748971026119006587801)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex(new Apfloat(3, 150, 16), new Apfloat(3, 150, 16)));
        assertEquals("(3,3), 150 precision", 150, a.precision());
        assertEquals("(3,3), 150 value", new Apcomplex(new Apfloat("1.71F7B3A6B918664C890B67210734F80D5E8DE46CF12CE907029E7A98171EB2A29E73BDE243BC6E9C7B3CA0B0A9179C5DD8F36C21FF43CD43E2E3768598D9A277261BF9ED2F9A4507D5456", Apfloat.DEFAULT, 16), new Apfloat("0.C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C43", Apfloat.DEFAULT, 16)), a, ApfloatMath.scale(new Apfloat(5, 1, 16), -148));

        a = ApcomplexMath.log(new Apcomplex("1"));
        assertEquals("1", new Apcomplex("0"), a);

        a = ApcomplexMath.log(new Apcomplex("-1.1"));
        assertEquals("-1.1, real precision", 1, a.real().precision());
        assertEquals("-1.1, precision", 2, a.precision());

        a = ApcomplexMath.log(new Apcomplex("-1.01"));
        assertEquals("-1.01, real precision", 1, a.real().precision());
        assertEquals("-1.01, precision", 3, a.precision());

        a = ApcomplexMath.log(new Apcomplex(new Apfloat("-1.1", 3)));
        assertEquals("-1.1, 3, real precision", 2, a.real().precision());
        assertEquals("-1.1, 3, precision", 3, a.precision());

        a = ApcomplexMath.log(new Apcomplex("(1.1,0.1)"));
        assertEquals("(1.1,0.1), precision", 1, a.precision());

        a = ApcomplexMath.log(new Apcomplex("(1.01,0.01)"));
        assertEquals("(1.01,0.01), precision", 1, a.precision());

        a = ApcomplexMath.log(new Apcomplex("(0.100000,0.100000)"));
        assertEquals("(0.1,0.1) precision", 6, a.precision());
        assertEquals("(0.1,0.1) value", new Apcomplex("(-1.95601,0.785398)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.log(new Apcomplex(Apfloat.ZERO, new Apfloat("2.567534329783818000500533029709932117494558299117260796421579784603311989535237879614227625064708170e2171472", 100)));
        assertEquals("(0,e^5000000), 100 precision", 106, a.precision());
        assertEquals("(0,e^5000000), 100 value", new Apcomplex(new Apfloat(5000000), new Apfloat("1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534")), a, new Apfloat("5e-99"));

        a = ApcomplexMath.log(new Apcomplex(Apfloat.ZERO, new Apfloat("3.894787261069254290252471079176073765185215930321023940272302235080330044710873765250549604329029361e-2171473", 100)));
        assertEquals("(0,-e^5000000), 100 precision", 100, a.precision());
        assertEquals("(0,-e^5000000), 100 value", new Apcomplex(new Apfloat(-5000000), new Apfloat("1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534")), a, new Apfloat("5e-92"));

        a = ApcomplexMath.log(new Apcomplex(new Apfloat(-2, 100, 2)));
        assertEquals("-2, 100 radix 2 precision", 100, a.precision());
        assertEquals("-2, 100 radix 2 value", new Apcomplex(new Apfloat("0.10110001011100100001011111110111110100011100111101111001101010111100100111100011101100111001100000000011111100101111011010101111010000001111001101000011001001100111001010011000101101100010110110001010000011010001011101011011100010111010101011111010001010111110011110111000011101100010000001101101111010111010110010011000010101011001", Apfloat.DEFAULT, 2), new Apfloat("11.001001000011111101101010100010001000010110100011000010001101001100010011000110011000101000101110000000110111000001110011010001001010010000001001001110000010001000101001100111110011000111010000000010000010111011111010100110001110110001001110011011001000100101000101001010000010000111100110001110001101000000010011011101111011111001", Apfloat.DEFAULT, 2)), a, new Apfloat("1e-99", 1, 2));

        a = ApcomplexMath.log(new Apcomplex(new Apfloat(-2, 100, 2), new Apfloat(-2, 100, 2)));
        assertEquals("-2-2i, 100 radix 2 precision", 101, a.precision());
        assertEquals("-2-2i, 100 radix 2 value", new Apcomplex(new Apfloat("1.0000101000101011001000111111001110111010101101110011011010000001101011101101010110001101011001000000", Apfloat.DEFAULT, 2), new Apfloat("-10.010110110010111110001111111001100110010000111010010001101001111001001110010100110010011110100010100", Apfloat.DEFAULT, 2)), a, new Apfloat("1e-99", 1, 2));

        a = ApcomplexMath.log(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 100, 11)));
        assertEquals("-2, 100 radix 11 precision", 100, a.precision());
        assertEquals("-2, 100 radix 11 value", new Apcomplex(new Apfloat("0.76964056aa1953a291444455a87588497353a063511118935186a366a24a331895629125a9a14432876a887204a134a72a99", Apfloat.DEFAULT, 11), new Apfloat("-1.63080356988524267266268493926a2097433442442708750a82107002329588113725817362690940a8831908396172469a", Apfloat.DEFAULT, 11)), a, new Apfloat("1e-100", 1, 11));

        try
        {
            ApcomplexMath.log(new Apcomplex("0"));
            fail("log of zero accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be -infinite
            assertEquals("Localization key", "log.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.log(new Apcomplex(Apfloat.ZERO, new Apfloat(2)));
            fail("log to infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; can't calculate this to infinite precision
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLogBase()
    {
        Apcomplex a = ApcomplexMath.log(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)), new Apcomplex(new Apfloat(2, 100), new Apfloat(3, 100)));
        assertEquals("(3,4) base (2,3), 100 precision", 100, a.precision());
        assertEquals("(3,4) base (2,3), 100 value", new Apcomplex("(1.1397284224569002062964218052429388242925638371440336662842481166316121503938668267670478367736422303,-0.1503520693183908310389743432512223715076049306602668639335618106843010268220651900947797357015316935)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.log(new Apcomplex("(3.0000,4.0000)"), new Apcomplex("2.000"));
        assertEquals("(3,4) base 2, precision", 4, a.precision());
        assertEquals("(3,4) base 2, value", new Apcomplex("(2.322,1.338)"), a, new Apfloat("0.005"));

        a = ApcomplexMath.log(new Apcomplex("3.0000"), new Apcomplex("(2.00000,3.00000)"));
        assertEquals("3 base (2,3), precision", 5, a.precision());
        assertEquals("3 base (2,3), value", new Apcomplex("(0.53970,-0.41358)"), a, new Apfloat("0.00005"));

        a = ApcomplexMath.log(new Apfloat("3.00"), new Apfloat("-2.00"));
        assertEquals("3 base -2, precision", 3, a.precision());
        assertEquals("3 base -2, value", new Apcomplex("(0.0736,-0.3335)"), a, new Apfloat("0.0005"));

        a = ApcomplexMath.log(new Apfloat("-3.00"), new Apfloat("2.00"));
        assertEquals("-3 base 2, precision", 3, a.precision());
        assertEquals("-3 base 2, value", new Apcomplex("(1.58,4.53)"), a, new Apfloat("0.05"));

        a = ApcomplexMath.log(new Apfloat(16, 400), new Apfloat(2));
        assertEquals("4 base 2, precision 400", 400, a.precision());
        assertEquals("4 base 2, value", new Apfloat(4), a, new Apfloat("5e-399"));

        a = ApcomplexMath.log(new Apfloat(16), new Apfloat(2, 500));
        assertEquals("4 base 2, precision 500", 500, a.precision());
        assertEquals("4 base 2, value", new Apfloat(4), a, new Apfloat("5e-499"));

        a = ApcomplexMath.log(new Apcomplex("(2.0000, 4.0000)"), new Apfloat("1.01", 7));
        assertEquals("(2,4) base 1.01, precision", 5, a.precision());
        assertEquals("(2,4) base 1.01, value", new Apcomplex("(150.53,111.27)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.log(new Apfloat("1.01", 7), new Apcomplex("(2.0000, 4.0000)"));
        assertEquals("1.01 base (2,4), precision", 5, a.precision());
        assertEquals("1.01 base (2,4), value", new Apcomplex("(0.0042959,-0.0031753)"), a, new Apfloat("5e-7"));
    }

    public static void testExp()
    {
        Apcomplex a = ApcomplexMath.exp(new Apcomplex(new Apfloat(2, 100)));
        assertEquals("2, 100 precision", 100, a.precision());
        assertEquals("2, 100 value", new Apfloat("7.389056098930650227230427460575007813180315570551847324087127822522573796079057763384312485079121794"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(0), new Apfloat("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")));
        assertEquals("(0,pi), 100 precision", 100, a.precision());
        assertEquals("(0,pi), 100 value", new Apfloat("-1"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(2, 100), new Apfloat("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")));
        assertEquals("(2,pi), 100 precision", 100, a.precision());
        assertEquals("(2,pi), 100 value", new Apfloat("-7.389056098930650227230427460575007813180315570551847324087127822522573796079057763384312485079121794"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.exp(new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534)"));
        assertEquals("(log2,pi/2), 100 precision", 100, a.precision());
        assertEquals("(log2,pi/2), 100 value", new Apcomplex(Apfloat.ZERO, new Apfloat(2)), a, new Apfloat("5e-99"));

        a = ApcomplexMath.exp(new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,-1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017412671058534)"));
        assertEquals("(log2,-pi/2), 100 precision", 100, a.precision());
        assertEquals("(log2,-pi/2), 100 value", new Apcomplex(Apfloat.ZERO, new Apfloat(-2)), a, new Apfloat("5e-99"));

        a = ApcomplexMath.exp(new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529266996)"));
        assertEquals("(log2,pi/4), 100 precision", 100, a.precision());
        assertEquals("(log2,pi/4), 100 value", new Apcomplex("(1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.exp(new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,-0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529266996)"));
        assertEquals("(log2,-pi/4), 100 precision", 100, a.precision());
        assertEquals("(log2,-pi/4), 100 value", new Apcomplex("(1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.exp(new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,2.356194490192344928846982537459627163147877049531329365731208444230862304714656748971026119006587801)"));
        assertEquals("(log2,3pi/4), 100 precision", 100, a.precision());
        assertEquals("(log2,3pi/4), 100 value", new Apcomplex("(-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.exp(new Apcomplex("(0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687,-2.356194490192344928846982537459627163147877049531329365731208444230862304714656748971026119006587801)"));
        assertEquals("(log2,-3pi/4), 100 precision", 100, a.precision());
        assertEquals("(log2,-3pi/4), 100 value", new Apcomplex("(-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573,-1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(3, 150, 16), new Apfloat("3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD1311", 150, 16)));
        assertEquals("(3,pi), 150 precision", 150, a.precision());
        assertEquals("(3,pi), 150 value", new Apfloat("-14.15E5BF6FB105F2D4BDFC53744C3A390585839728AA90A12389790C837E6FF2A68ABFE2D58DAFA5273C74EB175B9D0BD5584DFC81BE96F62CE66F428A2A50FFCBDF4083E8EE811BE42F", Apfloat.DEFAULT, 16), a, ApfloatMath.scale(new Apfloat(5, 1, 16), -147));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(0, 1, 17), new Apfloat(0, 1, 17)));
        assertEquals("1 radix", 17, a.radix());
        assertEquals("1 prec", Apfloat.INFINITE, a.precision());
        assertEquals("1 value", new Apfloat(1), a);

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat("-100000000000000000000", 20, 17), new Apfloat("0.1", 1, 17)));
        assertEquals("underflow radix", 17, a.radix());
        assertEquals("underflow prec", Apfloat.INFINITE, a.precision());
        assertEquals("underflow value", new Apfloat(0), a);

        a = ApcomplexMath.exp(new Apcomplex("(0.1,3.14159)"));
        assertEquals("(0.1,pi), precision", 2, a.precision());

        a = ApcomplexMath.exp(new Apcomplex("(0.01,3.14159)"));
        assertEquals("(0.01,pi), precision", 3, a.precision());

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat("0.1", 2), new Apfloat("3.14159")));
        assertEquals("(0.1,pi), 2, precision", 3, a.precision());

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat("1e-10", 32), new Apfloat("3.1415926535897932384626433832795")));
        assertEquals("(1e-10,pi)", new Apcomplex("-1.0000000001000000000050000000002"), a, new Apfloat("5e-31"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(5000000, 21), new Apfloat("1.570796326794897")));
        assertEquals("(5000000,pi/2), 15 precision", 15, a.precision());
        assertEquals("(5000000,pi/2), 15 value", new Apcomplex(Apfloat.ZERO, new Apfloat("2.56753432978382e2171472")), a, new Apfloat("5e2171458"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(5000000, 106), new Apfloat("4.712388980384689857693965074919254326295754099062658731462416888461724609429313497942052238013175602")));
        assertEquals("(5000000,3pi/2), 100 precision", 100, a.precision());
        assertEquals("(5000000,3pi/2), 100 value", new Apcomplex(Apfloat.ZERO, new Apfloat("-2.567534329783818000500533029709932117494558299117260796421579784603311989535237879614227625064708170e2171472")), a, new Apfloat("5e2171373"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat(-5000000, 106), new Apfloat("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")));
        assertEquals("(-5000000,pi), 100 precision", 100, a.precision());
        assertEquals("(-5000000,pi), 100 value", new Apfloat("-3.894787261069254290252471079176073765185215930321023940272302235080330044710873765250549604329029362e-2171473"), a, new Apfloat("5e-2171572"));

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat("-1e25", 50), new Apfloat("3.1415926535897932384626433832795028841971693993751")));
        assertEquals("(-1e25,pi), 50 value", new Apfloat(0), a);

        a = ApcomplexMath.exp(new Apcomplex(new Apfloat("-1e25"), new Apfloat("1e100")));
        assertEquals("(-1e25,1e100) value", new Apfloat(0), a);

        a = ApcomplexMath.exp(new Apcomplex("(-21237598959199934509.830775042768,3.1415926535897932384626433832795)"));
        assertEquals("(-21237598959199934509.830775042768,pi) value", new Apfloat(0), a);

        a = ApcomplexMath.exp(new Apcomplex("(-2.1237598959199920000000000000000000e19,3.141592653589793)"));
        assertEquals("(-2.123759895919992e19,pi) precision", 16, a.precision());
        assertEquals("(-2.123759895919992e19,pi) value", new Apfloat("-3.462892031805012e-9223372036854769507"), a, new Apfloat("5e-9223372036854769491"));

        Apfloat r = new Apfloat("-2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069551702761838606261331384583000752044933826560297606737113200709328709127443747047230696977209310141692836819025515108657463772111252389784425056953696770785449969967946864454905987931636889230098793127736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117301238197068416140397019837679320683282376464804295311802328782509819455815301756717361332069811250996181881593041690351598888519345807273866738589422879228499892086805825749279610484198444363463244968487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016768396424378140592714563549061303107208510383750510115747704171898610687396965521267154688957035035"),
                pi = new Apfloat("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199");

        for (int prec = 500; prec <= 800; prec += 100)
        {
            Apcomplex exp = ApcomplexMath.exp(new Apcomplex(new Apfloat(1, prec), pi.precision(prec)));

            assertEquals("exp prec " + prec + " precision", prec, exp.precision());
            assertEquals("exp prec " + prec + " value", r.precision(prec), exp, new Apfloat("5e-" + (prec - 1)));
        }

        for (int prec = 900; prec <= 1000; prec++)
        {
            Apcomplex exp = ApcomplexMath.exp(new Apcomplex(new Apfloat(1, prec), pi.precision(prec)));

            assertEquals("exp prec " + prec + " precision", prec, exp.precision());
            assertEquals("exp prec " + prec + " value", r.precision(prec), exp, new Apfloat("5e-" + (prec - 1)));
        }

        try
        {
            ApcomplexMath.exp(new Apcomplex(new Apfloat("50000000000000000000", 500000000), new Apfloat(3, 500000000)));
            fail("Overflow should have occurred");
        }
        catch (OverflowException oe)
        {
            // OK; result would overflow
            assertEquals("Localization key", "overflow", oe.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.exp(new Apcomplex(new Apfloat(2), new Apfloat(2)));
            fail("exp to infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; can't calculate this to infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testPow()
    {
        Apcomplex a = ApcomplexMath.pow(new Apcomplex(new Apfloat(2, 100)), new Apcomplex(new Apfloat("0.5", 100)));
        assertEquals("2^0.5, 100 precision", 100, a.precision(), 1);
        assertEquals("2^0.5, 100 value", new Apfloat("1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.pow(new Apcomplex(new Apfloat(-2, 100)), new Apcomplex(new Apfloat("0.5", 100)));
        assertEquals("(-2)^0.5, 100 precision", 100, a.precision(), 1);
        assertEquals("(-2)^0.5, 100 value", new Apcomplex("(0,1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.pow(new Apcomplex(new Apfloat(5, 100), new Apfloat(4, 100)), new Apcomplex(new Apfloat(3, 100), new Apfloat(2, 100)));
        assertEquals("(5,4)^(3,2), 100 precision", 99, a.precision(), 1);
        assertEquals("(5,4)^(3,2), 100 value", new Apcomplex("(58.2145009705915246565265271223031301774886834072803476475245473202072182772155725270313930579883159,-35.3234369348583753301237874184698198860952187848530861615372916445617840467298560954959137658317125)"), a, new Apfloat("5e-97"));

        Apfloat r = new Apfloat("1.193EA7AAD030A976A4198D55053B7CB5BE1442D9B7E08DF03D97EEEA5149358CAA9782D20CC698505071F733039A8ED5625C15071EA7BCA1CF37D8F11024C66486D094E21E74D0A547DF6", 150, 16);
        a = ApcomplexMath.pow(new Apcomplex(r, r), new Apcomplex(r, r));
        assertEquals("3, 150 precision", 150, a.precision(), 1);
        assertEquals("3, 150 value", new Apcomplex(new Apfloat("0.26ea28ff7cb530fc94a0b61e891cb2a15e1c72d7e9421ab41a2d0c46f1ba18f0b43409b5440adf17b33a95646b30b96f44634e286d546b2f543415d6d2deaaf79a715fa30e30cb858edb14", Apfloat.DEFAULT, 16),
                                                   new Apfloat("0.aae89b585652b078f623e7f850ebc3cd7c87afeb0a32feb1003d57a82352857778a89519b99e0001e1c276d3ddb09e1c07fc6b8129240a724aea584a7283a5e98bba61f57b20926ffac626", Apfloat.DEFAULT, 16)), a, ApfloatMath.scale(new Apfloat(5, 1, 16), -149));

        a = ApcomplexMath.pow(new Apfloat(2), new Apfloat(0));
        assertEquals("2^0", new Apfloat(1), a);

        a = ApcomplexMath.pow(new Apfloat(2), new Apfloat(1));
        assertEquals("2^1", new Apfloat(2), a);

        a = ApcomplexMath.pow(new Apfloat(-2), new Apfloat(0));
        assertEquals("(-2)^0", new Apfloat(1), a);

        a = ApcomplexMath.pow(new Apfloat(-2), new Apfloat(1));
        assertEquals("(-2)^1", new Apfloat(-2), a);

        a = ApcomplexMath.pow(Apcomplex.I, new Apfloat(0));
        assertEquals("i^0", new Apfloat(1), a);

        a = ApcomplexMath.pow(Apcomplex.I, new Apfloat(1));
        assertEquals("i^1", Apcomplex.I, a);

        a = ApcomplexMath.pow(new Apfloat(0), new Apfloat(2));
        assertEquals("0^2", new Apfloat(0), a);

        a = ApcomplexMath.pow(new Apfloat(1), new Apfloat(2));
        assertEquals("1^2", new Apfloat(1), a);

        a = ApcomplexMath.pow(new Apfloat(1), Apcomplex.I);
        assertEquals("1^i", new Apfloat(1), a);

        try
        {
            ApcomplexMath.pow(new Apfloat("1.2"), new Apfloat("57"));
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "lossOfPrecision", lope.getLocalizationKey());
        }

        a = ApcomplexMath.pow(new Apfloat("1.02"), new Apfloat("57"));
        assertEquals("1.02^57, precision", 1, a.precision());

        a = ApcomplexMath.pow(new Apfloat("1.2"), new Apfloat("1.0"));
        assertEquals("1.2^1.0, precision", 2, a.precision());

        a = ApcomplexMath.pow(new Apfloat("1.2"), new Apfloat("1"));
        assertEquals("1.2^1, precision", 1, a.precision());

        a = ApcomplexMath.pow(new Apfloat("1.02"), new Apfloat("1.00"));
        assertEquals("1.02^1.00, precision", 3, a.precision());

        a = ApcomplexMath.pow(new Apfloat("1.02"), new Apfloat("1"));
        assertEquals("1.02^1, precision", 1, a.precision());

        a = ApcomplexMath.pow(new Apfloat("1.2"), new Apfloat("0.01"));
        assertEquals("1.2^0.01, precision", 4, a.precision());

        a = ApcomplexMath.pow(new Apfloat("1.02"), new Apfloat("0.01"));
        assertEquals("1.02^0.01, precision", 5, a.precision());

        try
        {
            ApcomplexMath.pow(new Apcomplex(new Apfloat(0)), new Apcomplex(new Apfloat(0)));
            fail("0^0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be undefined
            assertEquals("Localization key", "pow.zeroToZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.pow(new Apcomplex(new Apfloat(0)), new Apcomplex("-0.1"));
            fail("0^-0.1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be undefined
            assertEquals("Localization key", "pow.zeroToNegative", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.pow(new Apfloat(0), Apcomplex.I);
            fail("0^i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be undefined
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.pow(new Apcomplex(new Apfloat(0)), new Apcomplex("(0,0.1)"));
            fail("0^0.1i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be undefined
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.pow(new Apcomplex(new Apfloat(100, 100), new Apfloat(100, 100)),
                              new Apcomplex(new Apfloat(5000000000000000000L, 100), new Apfloat(5000000000000000000L, 100)));
            fail("Overflow should have occurred");
        }
        catch (OverflowException oe)
        {
            // OK; result would overflow
            assertEquals("Localization key", "overflow", oe.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.pow(new Apcomplex(new Apfloat(3), new Apfloat(3)),
                              new Apcomplex(new Apfloat(-1), new Apfloat(-1)));
            fail("pow to infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; can't calculate this to infinite precision
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testArg()
    {
        Apcomplex a = ApcomplexMath.arg(new Apcomplex("(-2.0000,2.0000)"));
        assertEquals("(-2,2), precision", 5, a.precision());
        assertEquals("(-2,2), value", new Apfloat("2.3562"), a, new Apfloat("0.0005"));
    }

    public static void testAcosh()
    {
        Apcomplex a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(2.30550903124347694204183593813343089732908234612766434427244403789502387715767721380519816885689075,0.9368124611557199029125245765756089164871812290143448233044479241680079302681295000053794681278219233)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(2.30550903124347694204183593813343089732908234612766434427244403789502387715767721380519816885689075,-0.9368124611557199029125245765756089164871812290143448233044479241680079302681295000053794681278219233)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(2.30550903124347694204183593813343089732908234612766434427244403789502387715767721380519816885689075,2.204780192434073335550118806703893967709988170360760997670496668139808476018079498622655357214295145)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(2.30550903124347694204183593813343089732908234612766434427244403789502387715767721380519816885689075,-2.204780192434073335550118806703893967709988170360760997670496668139808476018079498622655357214295145)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.acosh(new Apfloat(2, 10));
        assertEquals("(2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(2,0), 10 value", new Apcomplex("1.316957897"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acosh(new Apfloat(-2, 10));
        assertEquals("(-2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(-2,0), 10 value", new Apcomplex("(1.316957897,3.141592654)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acosh(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("(0,2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,2), 10 value", new Apcomplex("(1.443635475,1.570796327)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acosh(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("(0,-2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,-2), 10 value", new Apcomplex("(1.443635475,-1.570796327)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acosh(new Apfloat("8e17", 30));
        assertEquals("(8e17,0), 30 precision", 32, a.precision());
        assertEquals("(8e17,0), 30 value", new Apcomplex("41.916535303138557865974783215467"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acosh(new Apfloat("-8e17", 30));
        assertEquals("(-8e17,0), 30 precision", 32, a.precision());
        assertEquals("(-8e17,0), 30 value", new Apcomplex("(41.916535303138557865974783215467,3.141592653589793238462643383280)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(0), new Apfloat("8e17", 30)));
        assertEquals("(0,8e17), 30 precision", 32, a.precision());
        assertEquals("(0,8e17), 30 value", new Apcomplex("(41.916535303138557865974783215467,1.570796326794896619231321691640)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(0), new Apfloat("-8e17", 30)));
        assertEquals("(0,-8e17), 30 precision", 32, a.precision());
        assertEquals("(0,-8e17), 30 value", new Apcomplex("(41.916535303138557865974783215467,-1.570796326794896619231321691640)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acosh(new Apcomplex(new Apfloat(1, 100)));
        assertEquals("1, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.acosh(new Apcomplex("0"));
            fail("acosh(0) accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAsinh()
    {
        Apcomplex a = ApcomplexMath.asinh(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(2.299914040879269649955789630663175555365313484764636466611830082402437121311729696004733902877606405,0.9176168533514786557598627486701745415899523820362300027773647609161124445462833451286169894870273957)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asinh(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(2.299914040879269649955789630663175555365313484764636466611830082402437121311729696004733902877606405,-0.9176168533514786557598627486701745415899523820362300027773647609161124445462833451286169894870273957)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asinh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-2.299914040879269649955789630663175555365313484764636466611830082402437121311729696004733902877606405,0.9176168533514786557598627486701745415899523820362300027773647609161124445462833451286169894870273957)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asinh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-2.299914040879269649955789630663175555365313484764636466611830082402437121311729696004733902877606405,-0.9176168533514786557598627486701745415899523820362300027773647609161124445462833451286169894870273957)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asinh(new Apfloat(2, 10));
        assertEquals("(2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(2,0), 10 value", new Apcomplex("1.443635475"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asinh(new Apfloat(-2, 10));
        assertEquals("(-2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(-2,0), 10 value", new Apcomplex("(-1.443635475)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asinh(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("(0,2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,2), 10 value", new Apcomplex("(1.316957897,1.570796327)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asinh(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("(0,-2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,-2), 10 value", new Apcomplex("(-1.316957897,-1.570796327)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asinh(new Apfloat("8e17", 30));
        assertEquals("(8e17,0), 30 precision", 32, a.precision());
        assertEquals("(8e17,0), 30 value", new Apcomplex("41.916535303138557865974783215467"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asinh(new Apfloat("-8e17", 30));
        assertEquals("(-8e17,0), 30 precision", 32, a.precision());
        assertEquals("(-8e17,0), 30 value", new Apcomplex("-41.916535303138557865974783215467"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asinh(new Apcomplex(new Apfloat(0), new Apfloat("8e17", 30)));
        assertEquals("(0,8e17), 30 precision", 32, a.precision());
        assertEquals("(0,8e17), 30 value", new Apcomplex("(41.916535303138557865974783215467,1.570796326794896619231321691640)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asinh(new Apcomplex(new Apfloat(0), new Apfloat("-8e17", 30)));
        assertEquals("(0,-8e17), 30 precision", 32, a.precision());
        assertEquals("(0,-8e17), 30 value", new Apcomplex("(-41.916535303138557865974783215467,-1.570796326794896619231321691640)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asinh(new Apcomplex("0"));
        assertEquals("0, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.asinh(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAtanh()
    {
        Apcomplex a = ApcomplexMath.atanh(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(0.1175009073114338884127342577870855161752247622030620101123480342515004695503565955468640257240191129,1.409921049596575522530619384460420782588207051908724814771070766475530084440199227135813201495737847)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atanh(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(0.1175009073114338884127342577870855161752247622030620101123480342515004695503565955468640257240191129,-1.409921049596575522530619384460420782588207051908724814771070766475530084440199227135813201495737847)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atanh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-0.1175009073114338884127342577870855161752247622030620101123480342515004695503565955468640257240191129,1.409921049596575522530619384460420782588207051908724814771070766475530084440199227135813201495737847)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atanh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-0.1175009073114338884127342577870855161752247622030620101123480342515004695503565955468640257240191129,-1.409921049596575522530619384460420782588207051908724814771070766475530084440199227135813201495737847)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atanh(new Apfloat(2, 10));
        assertEquals("(2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(2,0), 10 value", new Apcomplex("(0.549306144,-1.570796327)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atanh(new Apfloat(-2, 10));
        assertEquals("(-2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(-2,0), 10 value", new Apcomplex("(-0.549306144,1.570796327)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atanh(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("(0,2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,2), 10 value", new Apcomplex("(0,1.107148718)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atanh(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("(0,-2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,-2), 10 value", new Apcomplex("(0,-1.107148718)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atanh(new Apcomplex("0"));
        assertEquals("0, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.atanh(new Apcomplex("1"));
            fail("atanh(1) accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.atanh(new Apcomplex("-1"));
            fail("atanh(-1) accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; result would be infinite
            assertEquals("Localization key", "log.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.atanh(new Apcomplex(new Apfloat(2)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testCosh()
    {
        Apcomplex a = ApcomplexMath.cosh(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(-6.580663040551156432560744126538803616711267345515897773220218329756121215365251384163430874396326777,-7.581552742746544353716345286538426009387527590948852812949363456244614022672964969341075109130625439)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.cosh(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(-6.580663040551156432560744126538803616711267345515897773220218329756121215365251384163430874396326777,7.581552742746544353716345286538426009387527590948852812949363456244614022672964969341075109130625439)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.cosh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-6.580663040551156432560744126538803616711267345515897773220218329756121215365251384163430874396326777,7.581552742746544353716345286538426009387527590948852812949363456244614022672964969341075109130625439)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.cosh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-6.580663040551156432560744126538803616711267345515897773220218329756121215365251384163430874396326777,-7.581552742746544353716345286538426009387527590948852812949363456244614022672964969341075109130625439)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.cosh(new Apcomplex("1.00000"));
        assertEquals("1 value", new Apfloat("1.54308"), a, new Apfloat("5e-5"));
        assertEquals("1 imag value", new Apfloat(0), a.imag());

        a = ApcomplexMath.cosh(new Apcomplex("0"));
        assertEquals("0 value", new Apfloat(1), a);

        try
        {
            ApcomplexMath.cosh(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testSinh()
    {
        Apcomplex a = ApcomplexMath.sinh(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(-6.548120040911001647766811018835324740820888396888583499736134313039666841835229556393917343956455199,-7.619231720321410208487135736804311796557265472675575619426852074665542955161180340917983240028178743)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.sinh(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(-6.548120040911001647766811018835324740820888396888583499736134313039666841835229556393917343956455199,7.619231720321410208487135736804311796557265472675575619426852074665542955161180340917983240028178743)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.sinh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(6.548120040911001647766811018835324740820888396888583499736134313039666841835229556393917343956455199,-7.619231720321410208487135736804311796557265472675575619426852074665542955161180340917983240028178743)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.sinh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(6.548120040911001647766811018835324740820888396888583499736134313039666841835229556393917343956455199,7.619231720321410208487135736804311796557265472675575619426852074665542955161180340917983240028178743)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.sinh(new Apcomplex("1.0000"));
        assertEquals("1 value", new Apfloat("1.1752"), a, new Apfloat("5e-4"));
        assertEquals("1 imag value", new Apfloat(0), a.imag());

        a = ApcomplexMath.sinh(new Apcomplex("0"));
        assertEquals("0, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.sinh(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testTanh()
    {
        Apcomplex a = ApcomplexMath.tanh(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 101, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(1.0007095360672329393295854724041727462153209051467602180192607299042866403616169551650374279065226404,0.0049082580674960602590787869299327668433742155793555069748955113426747384320810439493273599689927112)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tanh(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 101, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(1.0007095360672329393295854724041727462153209051467602180192607299042866403616169551650374279065226404,-0.0049082580674960602590787869299327668433742155793555069748955113426747384320810439493273599689927112)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tanh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 101, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-1.0007095360672329393295854724041727462153209051467602180192607299042866403616169551650374279065226404,0.0049082580674960602590787869299327668433742155793555069748955113426747384320810439493273599689927112)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tanh(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 101, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-1.0007095360672329393295854724041727462153209051467602180192607299042866403616169551650374279065226404,-0.0049082580674960602590787869299327668433742155793555069748955113426747384320810439493273599689927112)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tanh(new Apcomplex("1.0000"));
        assertEquals("1 value", new Apfloat("0.76159"), a, new Apfloat("5e-5"));
        assertEquals("1 imag value", new Apfloat(0), a.imag());

        a = ApcomplexMath.tanh(new Apcomplex(new Apfloat(5000000, 100), new Apfloat("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")));
        assertEquals("(5000000,pi), 100 precision", 4343037, a.precision(), 1);
        assertEquals("(5000000,pi), 100 value", new Apfloat(1).subtract(new Apfloat("3.03387356179746871517892756452203249280217116298171287391802587502345779082540217305405121824e-4342945")), a, new Apfloat("5e-4343037"));

        a = ApcomplexMath.tanh(new Apcomplex(new Apfloat(-5000000, 100), new Apfloat("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")));
        assertEquals("(-5000000,pi), 100 precision", 4343037, a.precision(), 1);
        assertEquals("(-5000000,pi), 100 value", new Apfloat(-1).add(new Apfloat("3.03387356179746871517892756452203249280217116298171287391802587502345779082540217305405121824e-4342945")), a, new Apfloat("5e-4343037"));

        a = ApcomplexMath.tanh(new Apcomplex("0"));
        assertEquals("0, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.tanh(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAcos()
    {
        Apcomplex a = ApcomplexMath.acos(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision());
        assertEquals("(3,4), 100 value", new Apcomplex("(0.9368124611557199029125245765756089164871812290143448233044479241680079302681295000053794681278219233,-2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision());
        assertEquals("(3,-4), 100 value", new Apcomplex("(0.9368124611557199029125245765756089164871812290143448233044479241680079302681295000053794681278219233,2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision());
        assertEquals("(-3,4), 100 value", new Apcomplex("(2.204780192434073335550118806703893967709988170360760997670496668139808476018079498622655357214295145,-2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision());
        assertEquals("(-3,-4), 100 value", new Apcomplex("(2.204780192434073335550118806703893967709988170360760997670496668139808476018079498622655357214295145,2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.acos(new Apfloat(2, 10));
        assertEquals("(2,0), 10 precision", 10, a.precision());
        assertEquals("(2,0), 10 value", new Apcomplex("(0,1.316957897)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acos(new Apfloat(-2, 10));
        assertEquals("(-2,0), 10 precision", 10, a.precision());
        assertEquals("(-2,0), 10 value", new Apcomplex("(3.141592654,-1.316957897)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acos(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("(0,2), 10 precision", 10, a.precision());
        assertEquals("(0,2), 10 value", new Apcomplex("(1.570796327,-1.443635475)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acos(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("(0,-2), 10 precision", 10, a.precision());
        assertEquals("(0,-2), 10 value", new Apcomplex("(1.570796327,1.443635475)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.acos(new Apfloat("8e17", 30));
        assertEquals("(8e17,0), 30 precision", 32, a.precision());
        assertEquals("(8e17,0), 30 value", new Apcomplex("(0,41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acos(new Apfloat("-8e17", 30));
        assertEquals("(-8e17,0), 30 precision", 32, a.precision());
        assertEquals("(-8e17,0), 30 value", new Apcomplex("(3.141592653589793238462643383280,-41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat(0), new Apfloat("8e17", 30)));
        assertEquals("(0,8e17), 30 precision", 32, a.precision());
        assertEquals("(0,8e17), 30 value", new Apcomplex("(1.570796326794896619231321691640,-41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat(0), new Apfloat("-8e17", 30)));
        assertEquals("(0,-8e17), 30 precision", 32, a.precision());
        assertEquals("(0,-8e17), 30 value", new Apcomplex("(1.570796326794896619231321691640,41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat(1, 100)));
        assertEquals("1, 100 value", new Apfloat(0), a);

        a = ApcomplexMath.acos(new Apcomplex(new Apfloat("0.5", 30)));
        assertEquals("0.5, 30 value", new Apfloat("1.04719755119659774615421446109"), a, new Apfloat("5e-29"));

        try
        {
            ApcomplexMath.acos(new Apcomplex("0"));
            fail("acos(0) accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAsin()
    {
        Apcomplex a = ApcomplexMath.asin(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(0.6339838656391767163187971150641425256114034706732080871830243719859002728749749993086379445432366107,2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asin(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(0.6339838656391767163187971150641425256114034706732080871830243719859002728749749993086379445432366107,-2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asin(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-0.6339838656391767163187971150641425256114034706732080871830243719859002728749749993086379445432366107,2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asin(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-0.6339838656391767163187971150641425256114034706732080871830243719859002728749749993086379445432366107,-2.305509031243476942041835938133430897329082346127664344272444037895023877157677213805198168856890747)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.asin(new Apfloat(2, 10));
        assertEquals("(2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(2,0), 10 value", new Apcomplex("(1.570796327,-1.316957897)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asin(new Apfloat(-2, 10));
        assertEquals("(-2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(-2,0), 10 value", new Apcomplex("(-1.570796327,1.316957897)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asin(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("(0,2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,2), 10 value", new Apcomplex("(0,1.443635475)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asin(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("(0,-2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,-2), 10 value", new Apcomplex("(0,-1.443635475)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.asin(new Apfloat("8e17", 30));
        assertEquals("(8e17,0), 30 precision", 32, a.precision());
        assertEquals("(8e17,0), 30 value", new Apcomplex("(1.570796326794896619231321691640,-41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asin(new Apfloat("-8e17", 30));
        assertEquals("(-8e17,0), 30 precision", 32, a.precision());
        assertEquals("(-8e17,0), 30 value", new Apcomplex("(-1.570796326794896619231321691640,41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asin(new Apcomplex(new Apfloat(0), new Apfloat("8e17", 30)));
        assertEquals("(0,8e17), 30 precision", 32, a.precision());
        assertEquals("(0,8e17), 30 value", new Apcomplex("(0,41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asin(new Apcomplex(new Apfloat(0), new Apfloat("-8e17", 30)));
        assertEquals("(0,-8e17), 30 precision", 32, a.precision());
        assertEquals("(0,-8e17), 30 value", new Apcomplex("(0,-41.916535303138557865974783215467)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.asin(new Apcomplex("0"));
        assertEquals("0, 100 value", new Apfloat(0), a);

        a = ApcomplexMath.asin(new Apcomplex(new Apfloat("0.5", 30)));
        assertEquals("0.5, 30 value", new Apfloat("0.523598775598298873077107230547"), a, new Apfloat("5e-29"));

        try
        {
            ApcomplexMath.asin(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAtan()
    {
        Apcomplex a = ApcomplexMath.atan(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(1.448306995231464542145280451034113536641512650496960876923784338820230643349283451026750333836707538,0.1589971916799991743647610360070187815733054742350614709569622676518259973409283367912158396025096925)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atan(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(1.448306995231464542145280451034113536641512650496960876923784338820230643349283451026750333836707538,-0.1589971916799991743647610360070187815733054742350614709569622676518259973409283367912158396025096925)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atan(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-1.448306995231464542145280451034113536641512650496960876923784338820230643349283451026750333836707538,0.1589971916799991743647610360070187815733054742350614709569622676518259973409283367912158396025096925)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atan(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-1.448306995231464542145280451034113536641512650496960876923784338820230643349283451026750333836707538,-0.1589971916799991743647610360070187815733054742350614709569622676518259973409283367912158396025096925)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.atan(new Apfloat(2, 10));
        assertEquals("(2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(2,0), 10 value", new Apcomplex("1.107148718"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atan(new Apfloat(-2, 10));
        assertEquals("(-2,0), 10 precision", 10, a.precision(), 1);
        assertEquals("(-2,0), 10 value", new Apcomplex("-1.107148718"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atan(new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("(0,2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,2), 10 value", new Apcomplex("(1.570796327,0.549306144)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atan(new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("(0,-2), 10 precision", 10, a.precision(), 1);
        assertEquals("(0,-2), 10 value", new Apcomplex("(-1.570796327,-0.549306144)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.atan(new Apcomplex("0"));
        assertEquals("0, 100 value", new Apfloat(0), a);

        a = ApcomplexMath.atan(new Apcomplex(new Apfloat("0.5", 30)));
        assertEquals("0.5, 30 value", new Apfloat("0.463647609000806116214256231461"), a, new Apfloat("5e-29"));

        try
        {
            ApcomplexMath.atan(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testCos()
    {
        Apcomplex a = ApcomplexMath.cos(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(-27.03494560307422464769480266827091348467753695567661661019265514673434246483988229429946831870519301,-3.851153334811777536563337123053124569704160846091637003157728595256494186490481089994453362578315815)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.cos(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(-27.03494560307422464769480266827091348467753695567661661019265514673434246483988229429946831870519301,3.851153334811777536563337123053124569704160846091637003157728595256494186490481089994453362578315815)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.cos(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-27.03494560307422464769480266827091348467753695567661661019265514673434246483988229429946831870519301,3.851153334811777536563337123053124569704160846091637003157728595256494186490481089994453362578315815)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.cos(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-27.03494560307422464769480266827091348467753695567661661019265514673434246483988229429946831870519301,-3.851153334811777536563337123053124569704160846091637003157728595256494186490481089994453362578315815)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.cos(new Apcomplex("1.0000"));
        assertEquals("1 value", new Apfloat("0.5403"), a, new Apfloat("5e-5"));
        assertEquals("1 imag value", new Apfloat(0), a.imag());

        a = ApcomplexMath.cos(new Apcomplex(new Apfloat(0)));
        assertEquals("0, 100 value", new Apfloat(1), a);

        try
        {
            ApcomplexMath.cos(new Apcomplex(new Apfloat(1000, 3), new Apfloat("1.5")));
            fail("cos(1000 prec 3) accepted");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK; loss of precision
        }

        try
        {
            ApcomplexMath.cos(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testSin()
    {
        Apcomplex a = ApcomplexMath.sin(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(3.853738037919377321617528940463730667068274946989034956763346803317838585207899050385464301460315524,-27.01681325800393448809754375499215226336386568976518470594798897425063415478434990691671779691472675)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.sin(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(3.853738037919377321617528940463730667068274946989034956763346803317838585207899050385464301460315524,27.01681325800393448809754375499215226336386568976518470594798897425063415478434990691671779691472675)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.sin(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(-3.853738037919377321617528940463730667068274946989034956763346803317838585207899050385464301460315524,-27.01681325800393448809754375499215226336386568976518470594798897425063415478434990691671779691472675)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.sin(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 100, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(-3.853738037919377321617528940463730667068274946989034956763346803317838585207899050385464301460315524,27.01681325800393448809754375499215226336386568976518470594798897425063415478434990691671779691472675)"), a, new Apfloat("5e-97"));

        a = ApcomplexMath.sin(new Apcomplex("(3.00000e-1000,4.00000e-1000)"));
        assertEquals("3e-1000,4e-1000 precision", 6, a.precision());
        assertEquals("3e-1000,4e-1000 value", new Apcomplex("(3.00000e-1000,4.00000e-1000)"), a, new Apfloat("5e-1004"));

        a = ApcomplexMath.sin(new Apcomplex("1.0000"));
        assertEquals("1 value", new Apfloat("0.84147"), a, new Apfloat("5e-5"));
        assertEquals("1 imag value", new Apfloat(0), a.imag());

        a = ApcomplexMath.sin(new Apcomplex(new Apfloat(0)));
        assertEquals("0, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.sin(new Apcomplex(new Apfloat(1000, 3), new Apfloat("1.5")));
            fail("sin(1000 prec 3) accepted");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK; loss of precision
        }

        try
        {
            ApcomplexMath.sin(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testTan()
    {
        Apcomplex a = ApcomplexMath.tan(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 101, a.precision(), 1);
        assertEquals("(3,4), 100 value", new Apcomplex("(-0.0001873462046294784262242556377282181042124242427296606263580802232052224832174311687842725259181727521,0.9993559873814731413916496303201330615648885028135384928319757364498179348866065958722698773248799920)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tan(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 101, a.precision(), 1);
        assertEquals("(3,-4), 100 value", new Apcomplex("(-0.0001873462046294784262242556377282181042124242427296606263580802232052224832174311687842725259181727521,-0.9993559873814731413916496303201330615648885028135384928319757364498179348866065958722698773248799920)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tan(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 101, a.precision(), 1);
        assertEquals("(-3,4), 100 value", new Apcomplex("(0.0001873462046294784262242556377282181042124242427296606263580802232052224832174311687842725259181727521,0.9993559873814731413916496303201330615648885028135384928319757364498179348866065958722698773248799920)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tan(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 101, a.precision(), 1);
        assertEquals("(-3,-4), 100 value", new Apcomplex("(0.0001873462046294784262242556377282181042124242427296606263580802232052224832174311687842725259181727521,-0.9993559873814731413916496303201330615648885028135384928319757364498179348866065958722698773248799920)"), a, new Apfloat("5e-98"));

        a = ApcomplexMath.tan(new Apfloat("3.1415926535897932384626433832795", 24).divide(new Apint(180)));
        assertEquals("1 degree value", new Apfloat("0.0174550649282175857651289"), a, new Apfloat("5e-25"));
        assertEquals("1 degree imag value", new Apfloat(0), a.imag());

        a = ApcomplexMath.tan(new Apcomplex(new Apfloat(0), new Apfloat(5000000, 100)));
        assertEquals("(0,5000000), 100 precision", 4343037, a.precision(), 1);
        assertEquals("(0,5000000), 100 value", new Apcomplex(Apfloat.ZERO, new Apfloat(1).subtract(new Apfloat("3.03387356179746871517892756452203249280217116298171287391802587502345779082540217305405121824e-4342945"))), a, new Apfloat("5e-4343037"));

        a = ApcomplexMath.tan(new Apcomplex(new Apfloat(0), new Apfloat(-5000000, 100)));
        assertEquals("(0,-5000000), 100 precision", 4343037, a.precision(), 1);
        assertEquals("(0,-5000000), 100 value", new Apcomplex(Apfloat.ZERO, new Apfloat(-1).add(new Apfloat("3.03387356179746871517892756452203249280217116298171287391802587502345779082540217305405121824e-4342945"))), a, new Apfloat("5e-4343037"));

        a = ApcomplexMath.tan(new Apcomplex(new Apfloat(0)));
        assertEquals("0, 100 value", new Apfloat(0), a);

        try
        {
            ApcomplexMath.tan(new Apcomplex(new Apfloat(1000, 3), new Apfloat("1.5")));
            fail("tan(1000 prec 3) accepted");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK; loss of precision
        }

        try
        {
            ApcomplexMath.tan(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testCot()
    {
        Apcomplex a = ApcomplexMath.cot(new Apcomplex(new Apfloat(3, 100), new Apfloat(4, 100)));
        assertEquals("(3,4), 100 precision", 103, a.precision());
        assertEquals("(3,4), 100 value", new Apcomplex("(-0.00018758773798365921562850466246423355472564846529309782893964921914630968050082632783622198386659471,-1.00064439247155908009818470784307948938834227700912898634814356679250631676718292100755226328263131)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.cot(new Apcomplex(new Apfloat(3, 100), new Apfloat(-4, 100)));
        assertEquals("(3,-4), 100 precision", 103, a.precision());
        assertEquals("(3,-4), 100 value", new Apcomplex("(-0.00018758773798365921562850466246423355472564846529309782893964921914630968050082632783622198386659471,1.00064439247155908009818470784307948938834227700912898634814356679250631676718292100755226328263131)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.cot(new Apcomplex(new Apfloat(-3, 100), new Apfloat(4, 100)));
        assertEquals("(-3,4), 100 precision", 103, a.precision());
        assertEquals("(-3,4), 100 value", new Apcomplex("(0.00018758773798365921562850466246423355472564846529309782893964921914630968050082632783622198386659471,-1.00064439247155908009818470784307948938834227700912898634814356679250631676718292100755226328263131)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.cot(new Apcomplex(new Apfloat(-3, 100), new Apfloat(-4, 100)));
        assertEquals("(-3,-4), 100 precision", 103, a.precision());
        assertEquals("(-3,-4), 100 value", new Apcomplex("(0.00018758773798365921562850466246423355472564846529309782893964921914630968050082632783622198386659471,1.00064439247155908009818470784307948938834227700912898634814356679250631676718292100755226328263131)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.cot(new Apcomplex(Apfloat.ZERO, new Apfloat(4, 100)));
        assertEquals("(0,4), 100 precision", 104, a.precision());
        assertEquals("(0,4), 100 value", new Apcomplex("(0,-1.000671150401682489912111744434371930958710622745064689809122475628813351918433317813144115811237098917)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.cot(new Apcomplex(Apfloat.ZERO, new Apfloat(-4, 100)));
        assertEquals("(0,-4), 100 precision", 104, a.precision());
        assertEquals("(0,-4), 100 value", new Apcomplex("(0,1.000671150401682489912111744434371930958710622745064689809122475628813351918433317813144115811237098917)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.cot(new Apfloat(3, 100));
        assertEquals("(3,0), 100 precision", 100, a.precision());
        assertEquals("(3,0), 100 value", new Apcomplex("-7.0152525514345334694285513795264765782931033520963538381563324249075850694824874909055796047896063"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.cot(new Apfloat(-3, 100));
        assertEquals("(-3,0), 100 precision", 100, a.precision());
        assertEquals("(-3,0), 100 value", new Apcomplex("7.0152525514345334694285513795264765782931033520963538381563324249075850694824874909055796047896063"), a, new Apfloat("5e-99"));

        try
        {
            ApcomplexMath.cot(new Apcomplex(new Apfloat(0)));
            fail("cot(0) accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK; division by zero
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.cot(new Apcomplex(new Apfloat(1000, 3), new Apfloat("1.5")));
            fail("cot(1000 prec 3) accepted");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK; loss of precision
            assertEquals("Localization key", "imag.lossOfPrecision", lope.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.cot(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testSinc()
    {
        Apcomplex a = ApcomplexMath.sinc(new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("(3,4), 20 precision", 20, a.precision());
        assertEquals("(3,4), 20 value", new Apcomplex("(-3.860241556730304240,-3.858615677027572510)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.sinc(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apint(1), a);

        a = ApcomplexMath.sinc(new Apint(0, 2));
        assertEquals("0 radix 2 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 radix 2 radix", 2, a.radix());
        assertEquals("0 radix 2 value", new Apint(1, 2), a);

        try
        {
            ApcomplexMath.sinc(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testW()
    {
        Apcomplex a = new Apcomplex(new Apfloat(1, 45, 16), new Apfloat(2, 45, 16));
        Apcomplex w = ApcomplexMath.w(a, -1);
        assertEquals("value", new Apcomplex(new Apfloat("-0.731b614b3b95524effd3f81d9be7b8c8e1d21e69264d", 45, 16), new Apfloat("-3.7a03f382c1f5dd2df77921934d2d67941431ed093840", 45, 16)), w, new Apfloat("5", 1, 16).scale(-44));
        assertEquals("radix", 16, w.radix());
        assertEquals("precision", 45, w.precision());

        a = new Apcomplex(new Apfloat(1, 45), new Apfloat(2, 45));
        w = ApcomplexMath.w(a);
        assertEquals("value", new Apcomplex("(0.823771216709230498962714234680902867860235005,0.532928986795441605088201422572330085339330393)"), w, new Apfloat("5e-45"));
        assertEquals("radix", 10, w.radix());
        assertEquals("precision", 45, w.precision());

        try
        {
            ApcomplexMath.w(new Apcomplex(new Apfloat(1)));
            fail("Infinite precision accepted");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK; result would have infinite precision
            assertEquals("Localization key", "w.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testProduct()
    {
        Apcomplex a = ApcomplexMath.product(new Apcomplex("(1,1)"), new Apcomplex("(1,1)"));
        assertEquals("1-1 precision", 1, a.precision());
        assertEquals("1-1 value", new Apcomplex("(0,2)"), a);

        a = ApcomplexMath.product(new Apcomplex(Apfloat.ZERO, new Apfloat(2)), new Apcomplex(new Apfloat(3, 5), new Apfloat(3, 5)), new Apcomplex(new Apfloat(4, 8), new Apfloat(4, 8)));
        assertEquals("MAX-5-8 precision", 5, a.precision());
        assertEquals("MAX-5-8 value", new Apcomplex("-48"), a);

        a = ApcomplexMath.product(Apcomplex.ZERO, new Apcomplex("12345"));
        assertEquals("0 precision", Apcomplex.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.product(new Apint(0, 12));
        assertEquals("0 radix", 12, a.radix());

        a = ApcomplexMath.product(new Apcomplex("-1"),
                                  new Apcomplex("(0,2.50000000000000000000000000000000000000000000000000000000000000000000001)"),
                                  new Apcomplex("(0,2.0000000000000000000000000000000000001)"),
                                  new Apcomplex(new Apfloat(2)));
        assertEquals("Many precision", 1, a.precision());
        assertEquals("Many value", new Apcomplex("10"), a);

        Apcomplex[] x = new Apcomplex[] { new Apcomplex("1000000000000"), new Apcomplex("1") };
        ApcomplexMath.product(x);
        assertEquals("Array product 1 [0]", new Apcomplex("1000000000000"), x[0]);
        assertEquals("Array product 1 [1]", new Apcomplex("1"), x[1]);

        x = new Apcomplex[] { new Apcomplex("1"), new Apcomplex("1000000000000") };
        ApcomplexMath.product(x);
        assertEquals("Array product 2 [0]", new Apcomplex("1"), x[0]);
        assertEquals("Array product 2 [1]", new Apcomplex("1000000000000"), x[1]);

        assertEquals("Empty product", new Apcomplex("1"), ApcomplexMath.product());

        Apcomplex[] numbers = new Apcomplex[100000];    // Length should be divisible by 4 here
        for (int i = 0; i < numbers.length; i++)
        {
            numbers[i] = new Apcomplex(Apfloat.ZERO, new Apfloat(i + 1));
        }
        Apcomplex factorial = ApintMath.factorial(numbers.length);
        assertEquals("Factorial", factorial, ApcomplexMath.product(numbers));

        numbers[0] = new Apcomplex(Apfloat.ZERO, factorial.real());
        assertEquals("Factorial squared", factorial.multiply(factorial), ApcomplexMath.product(numbers));
    }

    public static void testSum()
    {
        Apcomplex a = ApcomplexMath.sum(new Apcomplex(Apfloat.ZERO, new Apfloat(12345000, 5)), new Apcomplex(Apfloat.ZERO, new Apfloat(12345, 5)));
        assertEquals("5-2 precision", 5, a.precision());
        assertEquals("5-2 value", new Apcomplex("(0,12357000)"), a);

        a = ApcomplexMath.sum(new Apcomplex(new Apfloat(12345678, 10)), new Apcomplex(new Apfloat(12345, 5)));
        assertEquals("8-5 precision", 8, a.precision());
        assertEquals("8-5 value", new Apcomplex("12358023"), a);

        a = ApcomplexMath.sum(new Apcomplex("0"), new Apcomplex("12345"));
        assertEquals("0-0 precision", 5, a.precision());
        assertEquals("0-0 value", new Apcomplex("12345"), a);

        a = ApcomplexMath.sum(new Apcomplex("2"));
        assertEquals("2 precision", 1, a.precision());
        assertEquals("2 value", new Apcomplex("2"), a);

        a = ApcomplexMath.sum(new Apcomplex("(0,1)"),
                              new Apcomplex("(0,3333333.33)"),
                              new Apcomplex("(0,2.2)"),
                              new Apcomplex("(0,444444444400000000000000000000000000)"),
                              new Apcomplex("(0,6666.6)"),
                              new Apcomplex("(0,555)"),
                              new Apcomplex(Apfloat.ZERO, new Apfloat(7)));
        assertEquals("Many precision", 36, a.precision());
        assertEquals("Many value", new Apcomplex("(0,444444444400000000000000000003340564)"), a);

        Apcomplex[] x = new Apcomplex[] { new Apcomplex("1000000000000"), new Apcomplex("1") };
        ApcomplexMath.sum(x);
        assertEquals("Array sum 1 [0]", new Apcomplex("1000000000000"), x[0]);
        assertEquals("Array sum 1 [1]", new Apcomplex("1"), x[1]);

        x = new Apcomplex[] { new Apcomplex("1"), new Apcomplex("1000000000000") };
        ApcomplexMath.sum(x);
        assertEquals("Array sum 2 [0]", new Apcomplex("1"), x[0]);
        assertEquals("Array sum 2 [1]", new Apcomplex("1000000000000"), x[1]);

        assertEquals("Empty sum", new Apcomplex("0"), ApcomplexMath.sum());
    }

    public static void testGamma()
    {
        Apcomplex a = ApcomplexMath.gamma(new Apcomplex("0.50000000"));
        assertEquals("0.5 precision", 8, a.precision());
        assertEquals("0.5 value", new Apfloat("1.7724539"), a, new Apfloat("5e-7"));
        a = ApcomplexMath.gamma(new Apcomplex("-0.50000000"));
        assertEquals("-0.5 precision", 8, a.precision());
        assertEquals("-0.5 value", new Apfloat("-3.5449077"), a, new Apfloat("5e-7"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(1, 8, 5)));
        assertEquals("1 precision", 8, a.precision());
        assertEquals("1 radix", 5, a.radix());
        assertEquals("1 value", new Apfloat("1"), a);
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(2, 100, 15)));
        assertEquals("2 precision", 100, a.precision());
        assertEquals("2 radix", 15, a.radix());
        assertEquals("2 value", new Apfloat("1"), a);
        a = ApcomplexMath.gamma(new Apcomplex("3.0000"));
        assertEquals("3 precision", 5, a.precision());
        assertEquals("3 value", new Apfloat("2"), a);
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("1.6", 50, 12)));
        assertEquals("1.5 precision", 50, a.precision());
        assertEquals("1.5 radix", 12, a.radix());
        assertEquals("1.5 value", new Apfloat("0.a77497505445a57663a7a6a27293557aa7636b52055b106267", 50, 12), a, new Apfloat("5e-50", 1, 12));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("1.6", 50, 12), new Apfloat("1.6", 50, 12)));
        assertEquals("(1.5,1.5) precision", 50, a.precision());
        assertEquals("(1.5,1.5) radix", 12, a.radix());
        assertEquals("(1.5,1.5) value", new Apcomplex(new Apfloat("0.421432a040a1238266b59319481b82250a972699b1218016a4", 50, 12), new Apfloat("0.184386517914307662b897756b0100538485b04495282b25ba", 50, 12)), a, new Apfloat("5e-50", 1, 12));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("1.6", 50, 12), new Apfloat("-1.6", 50, 12)));
        assertEquals("(1.5,-1.5) precision", 50, a.precision());
        assertEquals("(1.5,-1.5) radix", 12, a.radix());
        assertEquals("(1.5,-1.5) value", new Apcomplex(new Apfloat("0.421432a040a1238266b59319481b82250a972699b1218016a4", 50, 12), new Apfloat("-0.184386517914307662b897756b0100538485b04495282b25ba", 50, 12)), a, new Apfloat("5e-50", 1, 12));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("10.1", 50), new Apfloat(1, 50)));
        assertEquals("10.1+I precision", 49, a.precision());
        assertEquals("10.1+I radix", 10, a.radix());
        assertEquals("10.1+I value", new Apcomplex("(-275889.24637304345640288294183505994521208628420155,332093.85747733234553448206237389863106703170190430)"), a, new Apfloat("5e-44"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("100.1", 50), new Apfloat(1, 50)));
        assertEquals("100.1+I precision", 48, a.precision());
        assertEquals("100.1+I radix", 10, a.radix());
        assertEquals("100.1+I value", new Apcomplex("(-1.6325249252175791061043773321806465941281038201e155,-1.46196463909803799277895455102943868342521844260e156)"), a, new Apfloat("5e109"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(1, 200), new Apfloat("1000000000000.1", 200)));
        assertEquals("1000000000000.1+I precision", 186, a.precision());
        assertEquals("1000000000000.1+I radix", 10, a.radix());
        assertEquals("1000000000000.1+I value", new Apcomplex("(2.2799397381057012808806414716554222166361918093242073118331397578121585980690443002813637584289628198999964037945275096726070876981676095000509004082444136731667291762706895607184590520e-682188176916,2.56143734228029034694359025317416641643312626363528304218252981145494697876711767159132470544194941716039395729054771162631751713400996765379046059018461097663341902573535496875851156846e-682188176915)"), a, new Apfloat("5e-682188177101"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(1, 40), new Apfloat("1000000000000.1", 40)));
        assertEquals("1000000000000.1+I precision", 26, a.precision());
        assertEquals("1000000000000.1+I radix", 10, a.radix());
        assertEquals("1000000000000.1+I value", new Apcomplex("(2.2799397381057012808806415e-682188176916,2.56143734228029034694359025e-682188176915)"), a, new Apfloat("5e-682188176941"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(1, 133, 2), new Apfloat("1.110100011010100101001010001000000000000000110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011e39", 133, 2)));
        assertEquals("1000000000000.1+I radix 2 precision", 87, a.precision());
        assertEquals("1000000000000.1+I radix 2 radix", 2, a.radix());
        assertEquals("1000000000000.1+I radix 2 value", new Apcomplex(new Apfloat("1.111010101000100100110111110011011000101001000110001000101011000111010000100110001001e-2266180070897", Apfloat.DEFAULT, 2), new Apfloat("1.0101100001110000001011000010100111110010000010101111100000100011110010100011010001110010e-2266180070893", Apfloat.DEFAULT, 2)), a, new Apfloat("1e-2266180070981", 1, 2));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(1, 25, 36), new Apfloat("cre66i9s.3lllllllllllllllm", 25, 36)));
        assertEquals("100000000000.1+I radix 36 precision", 17, a.precision());
        assertEquals("100000000000.1+I radix 36 radix", 36, a.radix());
        assertEquals("100000000000.1+I radix 36 value", ApcomplexMath.scale(new Apcomplex(new Apfloat("0.4w3ncj1ol4pgrcbkl", Apfloat.DEFAULT, 36),new Apfloat("1.iyfv83hi4ul6s26oy", Apfloat.DEFAULT, 36)), -438339061062L), a, ApfloatMath.scale(new Apfloat("h", 1, 36), -438339061078L));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(100, 30), new Apfloat(374, 30)));
        assertEquals("(100,374) precision", 30, a.precision());
        assertEquals("(100,374) radix", 10, a.radix());
        assertEquals("(100,374) value", new Apcomplex("(47.4294943677064514689542753377,-32.7488916473624576880974867017)"), a, new Apfloat("5e-28"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat(1000000000, 30), new Apfloat(14913639641L, 30)));
        assertEquals("(1000000000,14913639641) precision", 30, a.precision());
        assertEquals("(1000000000,14913639641) radix", 10, a.radix());
        assertEquals("(1000000000,14913639641) value", new Apcomplex("(-2.99966240181596582389952917253,-0.39936803730444026987241513690)"), a, new Apfloat("5e-29"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("4825490186121.8", 30), new Apfloat(99000000000000L, 30)));
        assertEquals("(4825490186121.8,99000000000000) precision", 30, a.precision());
        assertEquals("(4825490186121.8,99000000000000) radix", 10, a.radix());
        assertEquals("(4825490186121.8,99000000000000) value", new Apcomplex("(-6.62771164327451839566254131658,5.32978019529137704595692626876)"), a, new Apfloat("5e-29"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("1e-100", 50), new Apfloat("1e-100", 50)));
        assertEquals("1e-100+1e-100i precision", 50, a.precision());
        assertEquals("1e-100+1e-100i radix", 10, a.radix());
        assertEquals("1e-100+1e-100i value", new Apcomplex("(5.000000000000000000000000000000000000000000000000e99,-5.000000000000000000000000000000000000000000000000e99)"), a, new Apfloat("5e51"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("1e-100", 50), new Apfloat("-1e-100", 50)));
        assertEquals("1e-100-1e-100i precision", 50, a.precision());
        assertEquals("1e-100-1e-100i radix", 10, a.radix());
        assertEquals("1e-100-1e-100i value", new Apcomplex("(5.000000000000000000000000000000000000000000000000e99,5.000000000000000000000000000000000000000000000000e99)"), a, new Apfloat("5e51"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("-1e-100", 50), new Apfloat("1e-100", 50)));
        assertEquals("-1e-100+1e-100i precision", 50, a.precision());
        assertEquals("-1e-100+1e-100i radix", 10, a.radix());
        assertEquals("-1e-100+1e-100i value", new Apcomplex("(-5.000000000000000000000000000000000000000000000000e99,-5.000000000000000000000000000000000000000000000000e99)"), a, new Apfloat("5e51"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("-1e-100", 50), new Apfloat("-1e-100", 50)));
        assertEquals("-1e-100-1e-100i precision", 50, a.precision());
        assertEquals("-1e-100-1e-100i radix", 10, a.radix());
        assertEquals("-1e-100-1e-100i value", new Apcomplex("(-5.000000000000000000000000000000000000000000000000e99,5.000000000000000000000000000000000000000000000000e99)"), a, new Apfloat("5e51"));
        a = ApcomplexMath.gamma(new Apfloat("1000000000000", 100));
        assertEquals("1000000000000 precision", 87, a.precision());
        assertEquals("1000000000000 radix", 10, a.radix());
        assertEquals("1000000000000 value", new Apcomplex("1.40366116037375609072013386771345056395992457297880153995116109278764014118526674828156e11565705518091"), a, new Apfloat("5e11565705518005"));
        a = ApcomplexMath.gamma(new Apfloat("12345.12345"));
        assertEquals("12345.12345 precision", 5, a.precision());
        assertEquals("12345.12345 radix", 10, a.radix());
        assertEquals("12345.12345 value", new Apcomplex("8.9252e45146"), a, new Apfloat("5e45142"));
        a = ApcomplexMath.gamma(new Apfloat("-0.9999991"));
        assertEquals("-0.9999991 precision", 1, a.precision());
        assertEquals("-0.9999991 radix", 10, a.radix());
        assertEquals("-0.9999991 value", new Apcomplex("-1e6"), a, new Apfloat("0"));
        a = ApcomplexMath.gamma(new Apfloat("-0.900000"));
        assertEquals("-0.9 precision", 6, a.precision());
        assertEquals("-0.9 radix", 10, a.radix());
        assertEquals("-0.9 value", new Apcomplex("-10.5706"), a, new Apfloat("5e-4"));
        a = ApcomplexMath.gamma(new Apcomplex("(-1.00000000000000000,1.00000000000000000e-5)"));
        assertEquals("-1+1e-5i precision", 14, a.precision());
        assertEquals("-1+1e-5i radix", 10, a.radix());
        assertEquals("-1+1e-5i value", new Apcomplex("(-0.4227843350,99999.999985882)"), a, new Apfloat("5e-9"));

        try
        {
            ApcomplexMath.gamma(new Apcomplex("0"));
            fail("Gamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("-1"));
            fail("Gamma of -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofNegativeInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("(-1.00000,1.00000e-1000)"));
            fail("Gamma of -1 within precision");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofNegativeIntegerWithinPrecision", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("(1e2,1)"));
            fail("Gamma loss of precision");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "lossOfPrecision", lope.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("(0,1e2)"));
            fail("Gamma loss of precision");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "lossOfPrecision", lope.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("1e100"));
            fail("Gamma overflow");
        }
        catch (ApfloatRuntimeException are)
        {
            // OK
            assertEquals("Localization key", "overflow", are.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex(new Apint(1), new Apfloat("4.5", Apfloat.INFINITE)));
            fail("Gamma infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testGammaIncomplete()
    {
        Apcomplex a = ApcomplexMath.gamma(new Apfloat(-4, 10), new Apfloat(-2, 10));
        assertEquals("-4,-2 precision", 10, a.precision());
        assertEquals("-4,-2 value", new Apcomplex("(0.2169049075,-0.1308996939)"), a, new Apfloat("5e-10"));
        a = ApcomplexMath.gamma(new Apfloat(-1, 10), new Apfloat(-2, 10));
        assertEquals("-1,-2 precision", 10, a.precision());
        assertEquals("-1,-2 value", new Apcomplex("(1.259706307,3.141592654)"), a, new Apfloat("5e-9"));
        a = ApcomplexMath.gamma(new Apfloat(0), new Apfloat(-1, 11));
        assertEquals("0,-1 precision", 10, a.precision());
        assertEquals("0,-1 value", new Apcomplex("(-1.895117816,-3.141592654)"), a, new Apfloat("5e-9"));
        a = ApcomplexMath.gamma(new Apfloat(-4, 10), new Apcomplex(Apfloat.ZERO, new Apfloat(-2, 10)));
        assertEquals("-4,-2i precision", 10, a.precision());
        assertEquals("-4,-2i value", new Apcomplex("(-0.01031978444,0.00762842656)"), a, new Apfloat("5e-11"));
        a = ApcomplexMath.gamma(new Apfloat(-4, 10), new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("-4,2i precision", 10, a.precision());
        assertEquals("-4,2i value", new Apcomplex("(-0.01031978444,-0.00762842656)"), a, new Apfloat("5e-11"));
        a = ApcomplexMath.gamma(new Apfloat(-4, 10), new Apcomplex(Apfloat.ZERO, new Apfloat(-200, 10)));
        assertEquals("-4,-200i precision", 8, a.precision());
        assertEquals("-4,-200i value", new Apcomplex("(2.765031767e-12,1.453166391e-12)"), a, new Apfloat("5e-21"));
        a = ApcomplexMath.gamma(new Apcomplex(Apfloat.ZERO, new Apfloat(-4, 10)), new Apcomplex(Apfloat.ZERO, new Apfloat(2, 10)));
        assertEquals("-4i,2i precision", 10, a.precision());
        assertEquals("-4i,2i value", new Apcomplex("(89.37681331,-0.32076166)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.gamma(new Apcomplex("3.50000"), new Apcomplex("0"));
        assertEquals("3.5 precision", 6, a.precision());
        assertEquals("3.5 value", new Apcomplex("3.32335"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.gamma(new Apcomplex("(1.5000000,1.0000000)"), new Apcomplex("(-1.0000000,1.0000000e-2)"));
        assertEquals("1.5+i,-1+0.01i precision", 8, a.precision());
        assertEquals("1.5+i,-1+0.01i value", new Apcomplex("(0.59778962,0.13066077)"), a, new Apfloat("5e-8"));
        a = ApcomplexMath.gamma(new Apcomplex("(1.5000000,1.0000000)"), new Apcomplex("(-1.0000000,-1.0000000e-2)"));
        assertEquals("1.5+i,-1-0.01i precision", 8, a.precision());
        assertEquals("1.5+i,-1-0.01i value", new Apcomplex("(-10.201515,-22.643499)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.gamma(new Apcomplex("(-1.0000000e-2,4.0000000e2)"), new Apcomplex("(1.0000000e-2,1.0000000e2)"));
        assertEquals("-1e-2+4e2i,1e-2+1e2i precision", 7, a.precision());
        assertEquals("-1e-2+4e2i,1e-2+1e2i value", new Apcomplex("(-1.0542844e-274,-1.2073566e-274)"), a, new Apfloat("5e-280"));

        a = ApcomplexMath.gamma(new Apcomplex("(-1.1538262523991663e-1,5.373868295802127e-5)"), new Apcomplex("(-1.773822473482807e1,1.1375203210348511e-1)"));
        assertEquals("-1.1538262523991663e-1+5.373868295802127e-5i,-1.773822473482807e1+1.1375203210348511e-1i precision", 15, a.precision());
        assertEquals("-1.1538262523991663e-1+5.373868295802127e-5i,-1.773822473482807e1+1.1375203210348511e-1i value", new Apcomplex("(-1955553.446208209,989495.924550850)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.gamma(new Apcomplex("(-8.221677442966661e-11,-8.40160119100972e-11)"), new Apcomplex("(1.2025846683194057e-3,9.851413511989293e-9)"));
        assertEquals("-8.221677442966661e-11-8.40160119100972e-11i,1.2025846683194057e-3+9.851413511989293e-9i precision", 17, a.precision());
        assertEquals("-8.221677442966661e-11-8.40160119100972e-11i,1.2025846683194057e-3+9.851413511989293e-9i value", new Apcomplex("(6.14726870827323060,-8.180204838272392707e-6)"), a, new Apfloat("5e-16"));

        a = ApcomplexMath.gamma(new Apcomplex("(5.9140452392587956e-5,8.5750776148049e8)"), new Apcomplex("(4.673198134242025,-1.3140870009190432e-7)"));
        assertEquals("5.9140452392587956e-5+8.5750776148049e8i,4.673198134242025-1.3140870009190432e-7i precision", 14, a.precision());
        assertEquals("5.9140452392587956e-5+8.5750776148049e8i,4.673198134242025-1.3140870009190432e-7i value", new Apcomplex("(-0.32088105037554,0.03770361316879)"), a, new Apfloat("5e-14"));

        a = ApcomplexMath.gamma(new Apcomplex("(-1.078432904072464e-1,2.2318918029265195e-9)"), new Apcomplex("(-1.318051987307835,2.2206695185439e9)"));
        assertEquals("-1.078432904072464e-1+2.2318918029265195e-9i,-1.318051987307835+2.2206695185439e9i precision", 5, a.precision());
        assertEquals("-1.078432904072464e-1+2.2318918029265195e-9i,-1.318051987307835+2.2206695185439e9i value", new Apcomplex("(1.155363210e-10,-1.180636439e-10)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.gamma(new Apcomplex("(-9.608072523703581e1,-3.7643456893059174e-1)"), new Apcomplex("(-1.3814972507571912e2,-3.4538159572099236e-1)"));
        assertEquals("-9.608072523703581e1-3.7643456893059174e-1,-1.3814972507571912e2-3.4538159572099236e-1i precision", 14, a.precision());
        assertEquals("-9.608072523703581e1-3.7643456893059174e-1,-1.3814972507571912e2-3.4538159572099236e-1i value", new Apcomplex("(-1.3024207045775e-149,1.8066865252068e-148)"), a, new Apfloat("5e-161"));

        a = ApcomplexMath.gamma(new Apcomplex("(4.929287290773249e-3,-4.681295287406053e1)"), new Apcomplex("(2.7955773531635903e-6,6.918020068517608e9)"));
        assertEquals("4.929287290773249e-3-4.681295287406053e1i,2.7955773531635903e-6+6.918020068517608e9i precision", 7, a.precision());
        assertEquals("4.929287290773249e-3-4.681295287406053e1i,2.7955773531635903e-6+6.918020068517608e9i value", new Apcomplex("(-9.62645560037940e21,-1.006027591105011e22)"), a, new Apfloat("5e14"));

        a = ApcomplexMath.gamma(new Apcomplex("(-154,-8.66)").precision(10), new Apcomplex("(-48700,-0.0274)").precision(10));
        assertEquals("-154-8.66i,-48700-0.0274i precision 10", 6, a.precision());
        assertEquals("-154-8.66i,-48700-0.0274i value 10", new Apcomplex("(-3.993583e20411,-4.146069e20411)"), a, new Apfloat("5e20406"));
        a = ApcomplexMath.gamma(new Apcomplex("(-154,-8.66)").precision(50), new Apcomplex("(-48700,-0.0274)").precision(50));
        assertEquals("-154-8.66i,-48700-0.0274i precision 50", 46, a.precision());
        assertEquals("-154-8.66i,-48700-0.0274i value 50", new Apcomplex("(-3.993583401859555074273878866836005256257679217e20411,-4.146069249480328790411648959625162586421100204e20411)"), a, new Apfloat("5e20366"));
        a = ApcomplexMath.gamma(new Apcomplex("(-154,-8.66)").precision(100), new Apcomplex("(-48700,-0.0274)").precision(100));
        assertEquals("-154-8.66i,-48700-0.0274i precision 100", 96, a.precision());
        assertEquals("-154-8.66i,-48700-0.0274i value 100", new Apcomplex("(-3.99358340185955507427387886683600525625767921706238693274185708531557493280695373333096470482086e20411,-4.14606924948032879041164895962516258642110020393956205308840983212659862153878019935909589513889e20411)"), a, new Apfloat("5e20316"));

        a = ApcomplexMath.gamma(new Apcomplex("(-1.539926526059491e2,-8.659643233600654)").precision(10), new Apcomplex("(3.651741272548377e1,3.651741272548377e1)").precision(10));
        assertEquals("-1.539926526059491e2-8.659643233600654i,3.651741272548377e1+3.651741272548377e1i precision 10", 7, a.precision());
        assertEquals("-1.539926526059491e2-8.659643233600654i,3.651741272548377e1+3.651741272548377e1i value 10", new Apcomplex("(-1.000387473e-279,2.19340186e-280)"), a, new Apfloat("5e-288"));
        a = ApcomplexMath.gamma(new Apcomplex("(-1.539926526059491e2,-8.659643233600654)").precision(100), new Apcomplex("(3.651741272548377e1,3.651741272548377e1)").precision(100));
        assertEquals("-1.539926526059491e2-8.659643233600654i,3.651741272548377e1+3.651741272548377e1i precision 100", 99, a.precision());
        assertEquals("-1.539926526059491e2-8.659643233600654i,3.651741272548377e1+3.651741272548377e1i value 100", new Apcomplex("(-1.000387472881261786364648259266083073101695881441237876788775418264481632743088708557828811438171176e-279,2.19340185670881734177337416745907040764484275856218117734431994846665774924244282427508784873315962e-280)"), a, new Apfloat("5e-378"));
        a = ApcomplexMath.gamma(new Apcomplex("(-1.539926526059491e2,-8.659643233600654)").precision(150), new Apcomplex("(3.651741272548377e1,3.651741272548377e1)").precision(150));
        assertEquals("-1.539926526059491e2-8.659643233600654i,3.651741272548377e1+3.651741272548377e1i precision 150", 149, a.precision());
        assertEquals("-1.539926526059491e2-8.659643233600654i,3.651741272548377e1+3.651741272548377e1i value 150", new Apcomplex("(-1.00038747288126178636464825926608307310169588144123787678877541826448163274308870855782881143817117680690207698118346329877280924878328777673631757823e-279,2.1934018567088173417733741674590704076448427585621811773443199484666577492424428242750878487331596225808712634666511287059353332666354112564113593836e-280)"), a, new Apfloat("5e-428"));

        a = ApcomplexMath.gamma(new Apcomplex("(-1.539926526059491e2,3.651741272548377e1)"), new Apcomplex("(-1.539926526059491e2,2.053525026457146)"));
        assertEquals("-1.539926526059491e2+3.651741272548377e1i,-1.539926526059491e2+2.053525026457146i precision", 14, a.precision());
        assertEquals("-1.539926526059491e2+3.651741272548377e1i,-1.539926526059491e2+2.053525026457146i value", new Apcomplex("(1.839734790895e-319,1.338102215869e-319)"), a, new Apfloat("5e-330"));

        a = ApcomplexMath.gamma(new Apcomplex("(3.651741272548377e1,6.493816315762113e2)"), new Apcomplex("(-1.539926526059491e2, 6.493816315762113e2)"));
        assertEquals("3.651741272548377e1+6.493816315762113e2i,-1.539926526059491e2+6.493816315762113e2i precision 16", 13, a.precision());
        assertEquals("3.651741272548377e1+6.493816315762113e2i,-1.539926526059491e2+6.493816315762113e2i value 16", new Apcomplex("(2.915334707954e-342,-1.655111718059e-341)"), a, new Apfloat("5e-353"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("3.651741272548377e1", 100), new Apfloat("6.493816315762113e2", 100)), new Apcomplex(new Apfloat("-1.539926526059491e2", 100), new Apfloat("6.493816315762113e2", 100)));
        assertEquals("3.651741272548377e1+6.493816315762113e2i,-1.539926526059491e2+6.493816315762113e2i precision 100", 97, a.precision());
        assertEquals("3.651741272548377e1+6.493816315762113e2i,-1.539926526059491e2+6.493816315762113e2i value 100", new Apcomplex("(2.91533470795462694774511982618601485525980988048575683897915057656824264524933126474133998657486524e-342,-1.655111718059222466900917172705448065052184678587394506208944906007626306997703966539065820047728131e-341)"), a, new Apfloat("5e-438"));

        a = ApcomplexMath.gamma(new Apcomplex("(6.493816315e2,-4.869675251e4)"), new Apcomplex("(2.053525026, -4.869675251e4)"));
        assertEquals("6.493816315762113e2-4.869675251658631e4i,2.053525026457146-4.869675251658631e4i precision 10", 5, a.precision());
        assertEquals("6.493816315762113e2-4.869675251658631e4i,2.053525026457146-4.869675251658631e4i value 10", new Apcomplex("(-3.336774750653543e-30179,-3.429254232216520e-30179)"), a, new Apfloat("5e-30183"));
        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("6.493816315762113e2", 100), new Apfloat("-4.869675251658631e4", 100)), new Apcomplex(new Apfloat("2.053525026457146", 100), new Apfloat("-4.869675251658631e4", 100)));
        assertEquals("6.493816315762113e2-4.869675251658631e4i,2.053525026457146-4.869675251658631e4i precision 100", 95, a.precision());
        assertEquals("6.493816315762113e2-4.869675251658631e4i,2.053525026457146-4.869675251658631e4i value 100", new Apcomplex("(-3.336774750653542780292101143074244789906130563661596634385946198826707896979733558295247049539498194e-30179,-3.429254232216520432738635661723033982576737397069537462221535204624693947897645031930120034934224312e-30179)"), a, new Apfloat("5e-30278"));

        a = ApcomplexMath.gamma(new Apcomplex("(6.493816315762113e2,1.154781984689458e4)"), new Apcomplex("(-8.659643233600654,1.154781984689458e4)"));
        assertEquals("6.493816315762113e2+1.154781984689458e4i,-8.659643233600654+1.154781984689458e4i precision 16", 11, a.precision());
        assertEquals("6.493816315762113e2+1.154781984689458e4i,-8.659643233600654+1.154781984689458e4i value 16", new Apcomplex("(-6.550743789275929e-5242,-1.416983672208689e-5242)"), a, new Apfloat("5e-5257"));

        a = ApcomplexMath.gamma(new Apcomplex(new Apfloat("6.493816315762113e2", 50), new Apfloat("1.154781984689458e4", 50)), new Apcomplex(new Apfloat("-8.659643233600654", 50), new Apfloat("1.154781984689458e4", 50)));
        assertEquals("6.493816315762113e2+1.154781984689458e4i,-8.659643233600654+1.154781984689458e4i precision 50", 45, a.precision());
        assertEquals("6.493816315762113e2+1.154781984689458e4i,-8.659643233600654+1.154781984689458e4i value 50", new Apcomplex("(-6.5507437892759319457546310871131583985239939226551e-5242,-1.4169836722086846119544003377316736599354795064143e-5242)"), a, new Apfloat("5e-5286")); // NOTE some 20 last digits are incorrect

        a = ApcomplexMath.gamma(new Apcomplex("(-1.53992652e2,6.49381631e-3)"), new Apcomplex("(-1.53992652e2,6.49381631e-3)"));
        assertEquals("-1.53992652e2+6.49381631e-3i,-1.53992652e2+6.49381631e-3i precision 9", 6, a.precision());
        assertEquals("-1.53992652e2+6.49381631e-3i,-1.53992652e2+6.49381631e-3i value 9", new Apcomplex("(7.9794e-273,-1.03098e-271)"), a, new Apfloat("5e-276"));
        a = ApcomplexMath.gamma(new Apcomplex("(-1.539926526059491e2,6.493816315762112e-3)"), new Apcomplex("(-1.539926526059491e2,6.493816315762112e-3)"));
        assertEquals("-1.539926526059491e2+6.493816315762112e-3i,-1.539926526059491e2+6.493816315762112e-3i precision 16", 13, a.precision());
        assertEquals("-1.539926526059491e2+6.493816315762112e-3i,-1.539926526059491e2+6.493816315762112e-3i value 16", new Apcomplex("(7.9792063198967e-273,-1.0309779572519e-271)"), a, new Apfloat("5e-283"));

        a = ApcomplexMath.gamma(new Apcomplex("(6.493816315762113e2,-4.869675251658631e4)"), new Apcomplex("(-8.659643233600654,-4.869675251658631e4)"));
        assertEquals("6.493816315762113e2-4.869675251658631e4i,-8.659643233600654-4.869675251658631e4i precision 16", 11, a.precision());
        assertEquals("6.493816315762113e2-4.869675251658631e4i,-8.659643233600654-4.869675251658631e4i value 16", new Apcomplex("(-3.25441737499e-30179,-3.3855297992e-30179)"), a, new Apfloat("5e-30189"));

        a = ApcomplexMath.gamma(new Apcomplex("(6.493816315762113e2,1.154781984689458e4)"), new Apcomplex("(-8.659643233600654,1.154781984689458e4)"));
        assertEquals("6.493816315762113e2+1.154781984689458e4i,-8.659643233600654+1.154781984689458e4i precision 16", 11, a.precision());
        assertEquals("6.493816315762113e2+1.154781984689458e4i,-8.659643233600654+1.154781984689458e4i value 16", new Apcomplex("(-6.550743789275931e-5242,-1.416983672208684e-5242)"), a, new Apfloat("5e-5252"));

        a = ApcomplexMath.gamma(new Apcomplex("(1.154781984689458e4,-1.539926526059491e2)"), new Apcomplex("(1.154781984689458e4,3.651741272548377e1)"));
        assertEquals("1.154781984689458e4-1.539926526059491e2i,1.154781984689458e4+3.651741272548377e1i precision 16", 11, a.precision());
        assertEquals("1.154781984689458e4-1.539926526059491e2i,1.154781984689458e4+3.651741272548377e1i value 16", new Apcomplex("(-8.382175690814767e41895,-2.511119213693562e41895)"), a, new Apfloat("5e41880"));

        a = ApcomplexMath.gamma(new Apcomplex("(100000,0)"), new Apcomplex("(2.00000,3.00000)"));
        assertEquals("100000,2+3i precision", 6, a.precision());
        assertEquals("100000,2+3i", new Apcomplex("(2.824229e456568)"), a, new Apfloat("5e456563"));

        a = ApcomplexMath.gamma(new Apcomplex("(100000.000000,100000.000000)"), new Apcomplex("(2.00000,3.00000)"));
        assertEquals("100000+100000i,2+3i precision", 6, a.precision());
        assertEquals("100000+100000i,2+3i", new Apcomplex("(3.13729e437509,2.911201e437510)"), a, new Apfloat("5e437505"));

        a = ApcomplexMath.gamma(new Apcomplex("(0,100000.00000)"), new Apcomplex("(2.0000000000,3.0000000000)"));
        assertEquals("100000i,2+3i precision", 7, a.precision());
        assertEquals("100000i,2+3i", new Apcomplex("(8.7426106520e-42689,-4.958470896e-42690)"), a, new Apfloat("5e-42695"));

        a = ApcomplexMath.gamma(new Apcomplex("(-100000.000,100000.000)"), new Apcomplex("(2.00000000,3.00000000)"));
        assertEquals("-100000+100000i,2+3i precision", 9, a.precision());
        assertEquals("-100000+100000i,2+3i", new Apcomplex("(8.3872927789e-98387,4.1247684828e-98386)"), a, new Apfloat("5e-98398"));

        a = ApcomplexMath.gamma(new Apcomplex("(-100000.100,0)"), new Apcomplex("(2.00000000,3.00000000)"));
        assertEquals("-100000,2+3i precision", 9, a.precision());
        assertEquals("-100000,2+3i", new Apcomplex("(5.118337676266220e-55704,-6.268428497322141e-55704)"), a, new Apfloat("5e-55712"));

        a = ApcomplexMath.gamma(new Apcomplex("(-100000.000,-100000.000)"), new Apcomplex("(2.00000000,3.00000000)"));
        assertEquals("-100000-100000i,2+3i precision", 9, a.precision());
        assertEquals("-100000-100000i,2+3i", new Apcomplex("(-9.8621266689e-13022,-1.956797639e-13022)"), a, new Apfloat("5e-13030"));

        a = ApcomplexMath.gamma(new Apcomplex("(0,-100000.00000)"), new Apcomplex("(2.0000000000,3.0000000000)"));
        assertEquals("-100000i,2+3i precision", 7, a.precision());
        assertEquals("-100000i,2+3i", new Apcomplex("(1.97199906e42676,6.97215465e42675)"), a, new Apfloat("5e42670"));

        a = ApcomplexMath.gamma(new Apcomplex("(100000.000,-100000.000)"), new Apcomplex("(2.00000000,3.00000000)"));
        assertEquals("100000-100000i,2+3i precision", 3, a.precision());
        assertEquals("100000-100000i,2+3i", new Apcomplex("(3.137289665e437509,-2.91120055e437510)"), a, new Apfloat("5e437507"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(100000.00000,0)"));
        assertEquals("100000,2+3i precision", 6, a.precision());
        assertEquals("100000,2+3i", new Apcomplex("(-3.562361388475777e-43425,6.6669518912609e-43427)"), a, new Apfloat("5e-43430"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(100000.00000,100000.00000)"));
        assertEquals("100000+100000i,2+3i precision", 6, a.precision());
        assertEquals("100000+100000i,2+3i", new Apcomplex("(-1.280065859976790e-43426,4.601110542440815e-43426)"), a, new Apfloat("5e-43426"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(0,100000.00000)"));
        assertEquals("100000i,2+3i precision", 6, a.precision());
        assertEquals("100000i,2+3i", new Apcomplex("(-15.2746,898.226)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(-100000.00000,100000.00000)"));
        assertEquals("-100000+100000i,2+3i precision", 6, a.precision());
        assertEquals("-100000+100000i,2+3i", new Apcomplex("(-3.255952560962579e43431,-9.05726879806356e43430)"), a, new Apfloat("5e43426"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(-100000.00000,0)"));
        assertEquals("-100000,2+3i precision", 6, a.precision());
        assertEquals("-100000,2+3i", new Apcomplex("(2.264542049935799e43430,-4.2516777388445e43428)"), a, new Apfloat("5e43425"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(-100000.00000,-100000.00000)"));
        assertEquals("-100000-100000i,2+3i precision", 6, a.precision());
        assertEquals("-100000-100000i,2+3i", new Apcomplex("(9.25282360923927e43436,-4.568939763307709e43437)"), a, new Apfloat("5e43432"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(0,-100000.00000)"));
        assertEquals("-100000i,2+3i precision", 6, a.precision());
        assertEquals("-100000i,2+3i", new Apcomplex("(-606243,-1.11149e7)"), a, new Apfloat("5e2"));

        a = ApcomplexMath.gamma(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(100000.00000,-100000.00000)"));
        assertEquals("100000-100000i,2+3i precision", 6, a.precision());
        assertEquals("100000-100000i,2+3i", new Apcomplex("(5.210410681496100e-43424,1.055353060233141e-43424)"), a, new Apfloat("5e-43429"));

        a = ApcomplexMath.gamma(new Apfloat("-4.0000000", Apfloat.DEFAULT, 11), new Apfloat("-6.0000000", Apfloat.DEFAULT, 11));
        assertEquals("-4,-6 precision radix 11", 8, a.precision());
        assertEquals("-4,-6 value radix 11", new Apcomplex(new Apfloat("-0.0987840", Apfloat.DEFAULT, 11), new Apfloat("-0.1492559", Apfloat.DEFAULT, 11)), a, new Apfloat("5e-7", Apfloat.DEFAULT, 11));

        a = ApcomplexMath.gamma(new Apfloat("-4.00000000", Apfloat.DEFAULT, 11), new Apfloat("-0.600000000", Apfloat.DEFAULT, 11));
        assertEquals("-4,-0.6 precision radix 11", 8, a.precision());
        assertEquals("-4,-0.6 value radix 11", new Apcomplex(new Apfloat("6.11a99456", Apfloat.DEFAULT, 11), new Apfloat("-0.14925588", Apfloat.DEFAULT, 11)), a, new Apfloat("5e-8", Apfloat.DEFAULT, 11));

        try
        {
            ApcomplexMath.gamma(Apcomplex.ZERO, Apcomplex.ZERO);
            fail("Gamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gammaIncomplete.upperOfNonpositive", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("(1.000e100,1.000)"), new Apcomplex("(1.000e102,1.000)"));
            fail("Overflow");
        }
        catch (OverflowException oe)
        {
            // OK
            assertEquals("Localization key", "overflow", oe.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex(new Apfloat(4)), new Apcomplex(new Apfloat(5)), Apfloat.ZERO);
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gammaIncomplete.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testGammaIncompleteGeneralized()
    {
        Apcomplex a = ApcomplexMath.gamma(new Apcomplex("(-1.0000000e-2,4.0000000e2)"), Apcomplex.ZERO, new Apcomplex("(1.0000000e-2,1.0000000e2)"));
        assertEquals("-1e-2+4e2i,0,1e-2+1e2i precision", 5, a.precision());
        assertEquals("-1e-2+4e2i,0,1e-2+1e2i value", new Apcomplex("(4.3680e-276,1.761e-277)"), a, new Apfloat("5e-280"));
        a = ApcomplexMath.gamma(new Apcomplex("(-1.0000000e-2,4.0000000e2)"), new Apcomplex("(1.0000000e-2,1.0000000e2)"), Apcomplex.ZERO);
        assertEquals("-1e-2+4e2i,1e-2+1e2i,0 precision", 5, a.precision());
        assertEquals("-1e-2+4e2i,1e-2+1e2i,0 value", new Apcomplex("(-4.3680e-276,-1.761e-277)"), a, new Apfloat("5e-280"));
        a = ApcomplexMath.gamma(new Apcomplex("(-1.0000000e-2,4.0000000e2)"), new Apcomplex("(1.0000000e-2,1.0000000e2)"), new Apcomplex("(1.0000000e-2,1.0000000e2)"));
        assertEquals("-1e-2+4e2i,1e-2+1e2i,1e-2+1e2i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1e-2+4e2i,1e-2+1e2i,1e-2+1e2i value", Apcomplex.ZERO, a);
        a = ApcomplexMath.gamma(new Apcomplex("(0,1.0000)"), new Apcomplex("(0,1.0000)"), new Apcomplex("(0,2.0000)"));
        assertEquals("i,i,2i precision", 5, a.precision());
        assertEquals("i,i,2i value", new Apcomplex("(0.06560,-0.12764)"), a, new Apfloat("5e-5"));
        a = ApcomplexMath.gamma(Apcomplex.ZERO, new Apcomplex("(0,1.0000)"), new Apcomplex("(0,2.0000)"));
        assertEquals("0,i,2i precision", 5, a.precision());
        assertEquals("0,i,2i value", new Apcomplex("(0.08558,-0.65933)"), a, new Apfloat("5e-5"));
        a = ApcomplexMath.gamma(Apcomplex.ZERO, new Apcomplex("(1.0000,1.0000)"), new Apcomplex("(2.0000,0)"));
        assertEquals("0,1+i,2 precision", 5, a.precision());
        assertEquals("0,1+i,2 value", new Apcomplex("(-0.04862,-0.17932)"), a, new Apfloat("5e-5"));
        a = ApcomplexMath.gamma(Apcomplex.ZERO, new Apcomplex("(1.0000,1.0000)"), new Apcomplex("(0,2.0000)"));
        assertEquals("0,1+i,2i precision", 5, a.precision());
        assertEquals("0,1+i,2i value", new Apcomplex("(0.42326,-0.21394)"), a, new Apfloat("5e-5"));
        a = ApcomplexMath.gamma(new Apcomplex("(0,1.0000)"), new Apcomplex("(0,1.0000)"), Apcomplex.ZERO);
        assertEquals("i,i,0 precision", 5, a.precision());
        assertEquals("i,i,0 value", new Apcomplex("(0.14013,0.28147)"), a, new Apfloat("5e-5"));

        try
        {
            ApcomplexMath.gamma(Apcomplex.ZERO, Apcomplex.ZERO, Apcomplex.ZERO);
            fail("Gamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("-1"), Apcomplex.ZERO, new Apcomplex("(1,2)"));
            fail("Lower gamma of non-positive integer");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK a is non-positive integer
            assertEquals("Localization key", "gammaIncomplete.lowerOfNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(Apcomplex.ZERO, new Apcomplex("(0,-1)"), Apcomplex.ZERO);
            fail("Lower gamma of non-positive integer");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK a is non-positive integer
            assertEquals("Localization key", "gammaIncomplete.lowerOfNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(Apcomplex.ZERO, Apcomplex.ZERO, new Apcomplex("(0,-1)"));
            fail("Lower gamma of non-positive integer");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK a is non-positive integer
            assertEquals("Localization key", "gammaIncomplete.lowerOfNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(Apcomplex.ZERO, Apcomplex.ZERO, new Apcomplex("(1,-1)"));
            fail("Lower gamma of non-positive integer");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK a is non-positive integer
            assertEquals("Localization key", "gammaIncomplete.lowerOfNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex("(1.00e19,1.00e19)"), new Apcomplex("(1.00e18,1.00e18)"), new Apcomplex("(2.00e19,2.00e19)"));
            fail("Overflow");
        }
        catch (OverflowException oe)
        {
            // OK
            assertEquals("Localization key", "overflow", oe.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.gamma(new Apcomplex(Apfloat.ZERO, new Apfloat(4)), new Apcomplex(Apfloat.ZERO, new Apfloat(5)), new Apcomplex(Apfloat.ZERO, new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gammaIncomplete.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLogGamma()
    {
        Apcomplex a = ApcomplexMath.logGamma(new Apcomplex("(3,4)").precision(30));
        assertEquals("3+4i precision", 29, a.precision());
        assertEquals("3+4i value", new Apcomplex("(-1.75662678460378411053060418162,4.74266443803465792819488940755)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(3,-4)").precision(30));
        assertEquals("3-4i precision", 29, a.precision());
        assertEquals("3-4i value", new Apcomplex("(-1.75662678460378411053060418162,-4.74266443803465792819488940755)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-3,4)").precision(30));
        assertEquals("-3+4i precision", 30, a.precision());
        assertEquals("-3+4i value", new Apcomplex("(-10.5813046757679821776505859518,-5.3256146315280061739958499710)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-3,-4)").precision(30));
        assertEquals("-3-4i precision", 30, a.precision());
        assertEquals("-3-4i value", new Apcomplex("(-10.5813046757679821776505859518,5.3256146315280061739958499710)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(300,4)").precision(30));
        assertEquals("300+4i precision", 30, a.precision());
        assertEquals("300+4i value", new Apcomplex("(1409.17535710394427231445345360,22.80857843613452556017830512)"), a, new Apfloat("5e-26"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-300,-4)").precision(30));
        assertEquals("-300-4i precision", 30, a.precision());
        assertEquals("-300-4i value", new Apcomplex("(-1425.60772200752672992622696153,921.22668142430419691996693265)"), a, new Apfloat("5e-26"));

        a = ApcomplexMath.logGamma(new Apcomplex("(3,400)").precision(30));
        assertEquals("3+400i precision", 30, a.precision());
        assertEquals("3+400i value", new Apcomplex("(-612.42091519215003296376447609,2000.50510137367765558763842034)"), a, new Apfloat("5e-26"));

        a = ApcomplexMath.logGamma(new Apcomplex("(7,-4)").precision(30));
        assertEquals("7-4i precision", 29, a.precision());
        assertEquals("7-4i value", new Apcomplex("(5.4180869718730471169905929840,-7.7181013652048386845411947705)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(3e100000,4e100000)").precision(30));
        assertEquals("3e100000+4e100000i precision", 30, a.precision());
        assertEquals("3e100000+4e100000i value", new Apcomplex("(6.90773647031079001057591524633e100005,9.21039256834922014845392270448e100005)"), a, new Apfloat("5e99975"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-3e100000,4e100000)").precision(30));
        assertEquals("-3e100000+4e100000i precision", 30, a.precision());
        assertEquals("-3e100000+4e100000i value", new Apcomplex("(-6.90786213401693360230545375207e100005,9.21029832056961245465676882518e100005)"), a, new Apfloat("5e99975"));

        a = ApcomplexMath.logGamma(new Apcomplex("(3e-100000,4e-100000)").precision(30));
        assertEquals("3e-100000+4e-100000i precision", 30, a.precision());
        assertEquals("-3e100000+4e100000i value", new Apcomplex("(230256.89986149213430142454470910319,-0.927295218001612232428512462922)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-3e-100000,4e-100000)").precision(30));
        assertEquals("-3e-100000+4e-100000i precision", 30, a.precision());
        assertEquals("-3e-100000+4e-100000i value", new Apcomplex("(230256.89986149213430142454470910319,-2.214297435588181006034130920357)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-3e-8,-4e-8)").precision(6));
        assertEquals("-3e-8-4e-8i precision", 6, a.precision());
        assertEquals("-3e-8-4e-8i value", new Apcomplex("(16.81124,2.214297)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0.001,0.001)").precision(30));
        assertEquals("0.001+0.001i precision", 29, a.precision());
        assertEquals("0.001+0.001i value", new Apcomplex("(6.56060447383755263956515723187,-0.785973734929653434835994646315)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0,0.001)").precision(30));
        assertEquals("0.001i precision", 30, a.precision());
        assertEquals("0.001i value", new Apcomplex("(6.90775445651537420857962686091,-1.571373542059112725090803754152)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-0.001,0.001)").precision(30));
        assertEquals("-0.001+0.001i precision", 29, a.precision());
        assertEquals("-0.001+0.001i value", new Apcomplex("(6.56175890356461150865814111470,-2.356773351592683747807274450833)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0.001,2)").precision(30));
        assertEquals("0.001+2i precision", 29, a.precision());
        assertEquals("0.001+2i value", new Apcomplex("(-2.56851143797407428601007061119,-1.43932944213613926991901894905)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0,2)").precision(30));
        assertEquals("2i precision", 29, a.precision());
        assertEquals("2i value", new Apcomplex("(-2.56922596699087465064722769986,-1.44115001048510830784761423525)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-0.001,2)").precision(30));
        assertEquals("-0.001+2i precision", 29, a.precision());
        assertEquals("-0.001+2i value", new Apcomplex("(-2.56994062107649702287048674102,-1.44297105665961289556329006395)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0.999,2)").precision(30));
        assertEquals("0.999+2i precision", 29, a.precision());
        assertEquals("0.999+2i value", new Apcomplex("(-1.87679331551656733845065045339,0.12832527009361706325136384495)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-0.999,2)").precision(30));
        assertEquals("-0.999+2i precision", 29, a.precision());
        assertEquals("-0.999+2i value", new Apcomplex("(-3.37303045422046060401853555827,-3.47337329793718494112946036370)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-0.5,0.01)").precision(17));
        assertEquals("-0.5,0.1 precision", 17, a.precision());
        assertEquals("-0.5,0.1 value", new Apcomplex("(1.2650654639403971,-3.141227615720128556)"), a, new Apfloat("5e-16"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-0.5)").precision(17));
        assertEquals("-0.5 precision", 17, a.precision());
        assertEquals("-0.5 value", new Apcomplex("(1.2655121234846454,-3.1415926535897932)"), a, new Apfloat("5e-16"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-0.5,-0.01)").precision(17));
        assertEquals("-0.5,-0.01 precision", 17, a.precision());
        assertEquals("-0.5,-0.01 value", new Apcomplex("(1.2650654639403971,3.141227615720128556)"), a, new Apfloat("5e-16"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-1.5,0.01)").precision(17));
        assertEquals("-1.5,0.1 precision", 16, a.precision());
        assertEquals("-1.5,0.1 value", new Apcomplex("(0.8595781341038230,-6.27615370140605357)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-1.5)").precision(17));
        assertEquals("-1.5 precision", 16, a.precision());
        assertEquals("-1.5 value", new Apcomplex("(0.8600470153764810,-6.2831853071795865)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-1.5,-0.01)").precision(17));
        assertEquals("-1.5,-0.01 precision", 16, a.precision());
        assertEquals("-1.5,-0.01 value", new Apcomplex("(0.8595781341038230,6.27615370140605357)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-2.5,0.01)").precision(17));
        assertEquals("-2.5,0.1 precision", 16, a.precision());
        assertEquals("-2.5,0.1 value", new Apcomplex("(-0.0567205977063328,-9.4137463763289753)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-2.5)").precision(17));
        assertEquals("-2.5 precision", 16, a.precision());
        assertEquals("-2.5 value", new Apcomplex("(-0.0562437164976741,-9.4247779607693797)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-2.5,-0.01)").precision(17));
        assertEquals("-2.5,-0.01 precision", 16, a.precision());
        assertEquals("-2.5,-0.01 value", new Apcomplex("(-0.0567205977063328,9.4137463763289753)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.logGamma(new Apcomplex("(1.0,600000.0)"));
        assertEquals("1+600000i precision", 7, a.precision());
        assertEquals("1+600000i value", new Apcomplex("(-942470,7382812)"), a, new Apfloat("5e0"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0,600000)"));
        assertEquals("600000i precision", 6, a.precision());
        assertEquals("600000i value", new Apcomplex("(-942483,7382810)"), a, new Apfloat("5e1"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0,600000.0)"));
        assertEquals("600000.0i precision", 7, a.precision());
        assertEquals("600000.0i value", new Apcomplex("(-942483,7382810)"), a, new Apfloat("5e0"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-1.0,600000.0)"));
        assertEquals("-1+600000i precision", 7, a.precision());
        assertEquals("-1+600000i value", new Apcomplex("(-942497,7382809)"), a, new Apfloat("5e0"));

        a = ApcomplexMath.logGamma(new Apcomplex("(1.00000e600000,0)"));
        assertEquals("1e600000 precision", 6, a.precision());
        assertEquals("1e600000 value", new Apcomplex("(1.38155e600006)"), a, new Apfloat("5e600001"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-1.00000e600000,1)"));
        assertEquals("-1e600000+i precision", 6, a.precision());
        assertEquals("-1e600000+i value", new Apcomplex("(-1.38155e600006,-3.14159e600000)"), a, new Apfloat("5e600001"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-1.00000e600000,-1)"));
        assertEquals("-1e600000-i precision", 6, a.precision());
        assertEquals("-1e600000-i value", new Apcomplex("(-1.38155e600006,-3.14159e600000)"), a, new Apfloat("5e600001"));

        a = ApcomplexMath.logGamma(new Apcomplex("(0,1.00000e600000)"));
        assertEquals("1e600000i precision", 6, a.precision());
        assertEquals("1e600000i value", new Apcomplex("(-1.5708e600000,1.38155e600006)"), a, new Apfloat("5e600001"));

        a = ApcomplexMath.logGamma(new Apcomplex("6.00000"));
        assertEquals("6 precision", 6, a.precision());
        assertEquals("6 value", new Apcomplex("4.78749"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logGamma(new Apcomplex("-4.50000"));
        assertEquals("-4.5 precision", 7, a.precision());
        assertEquals("-4.5 value", new Apcomplex("(-2.81308,-15.70796)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logGamma(new Apcomplex("(-9.71e-2,1.5386)"));
        assertEquals("-9.71e-2+1.5386i precision", 4, a.precision());
        assertEquals("-9.71e-2+1.5386i value", new Apcomplex("(-1.75979,-1.90299)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.logGamma(new Apcomplex("3"));
        assertEquals("3 precision", 1, a.precision(), 1);
        assertEquals("3 value", new Apcomplex("0.7"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.logGamma(new Apcomplex("1").precision(100));
        assertEquals("1 value", new Apcomplex("0"), a);

        a = ApcomplexMath.logGamma(new Apcomplex("2").precision(100));
        assertEquals("2 value", new Apcomplex("0"), a);

        a = ApcomplexMath.logGamma(new Apcomplex(new Apfloat(-5, 20, 9), new Apfloat(-6, 20,9)));
        assertEquals("-5-6i radix precision", 20, a.precision());
        assertEquals("-5-6i radix value", new Apcomplex(new Apfloat("-20.8777170116531164514", 20, 9), new Apfloat("6.1201335747842606317", 20, 9)), a, new Apfloat("5e-18", 1, 9));

        try
        {
            ApcomplexMath.logGamma(Apcomplex.ZERO);
            fail("Log gamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "logGamma.ofZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.logGamma(new Apcomplex("-1"));
            fail("Log gamma of -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "logGamma.ofNegativeInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.logGamma(new Apcomplex(new Apint(3), new Apint(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "logGamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testDigamma()
    {
        Apcomplex a = ApcomplexMath.digamma(new Apcomplex("(3,4)").precision(30));
        assertEquals("3+4i precision", 32, a.precision(), 1);
        assertEquals("3+4i value", new Apcomplex("(1.55035981733341091269899018667062,1.01050220918604445291687052250976)"), a, new Apfloat("5e-31"));

        a = ApcomplexMath.digamma(new Apcomplex("(3,-4)").precision(30));
        assertEquals("3-4i precision", 32, a.precision(), 1);
        assertEquals("3-4i value", new Apcomplex("(1.55035981733341091269899018667062,-1.01050220918604445291687052250976)"), a, new Apfloat("5e-31"));

        a = ApcomplexMath.digamma(new Apcomplex("(-3,4)").precision(30));
        assertEquals("-3+4i precision", 30, a.precision());
        assertEquals("-3+4i value", new Apcomplex("(1.67035981733341091269899018667,2.29109044448016209997569405192)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(new Apcomplex("(-3,-4)").precision(30));
        assertEquals("-3-4i precision", 30, a.precision());
        assertEquals("-3-4i value", new Apcomplex("(1.67035981733341091269899018667,-2.29109044448016209997569405192)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(new Apcomplex("(3000000,4000000)").precision(30));
        assertEquals("3000000+4000000i precision", 30, a.precision());
        assertEquals("3000000+4000000i value", new Apcomplex("(15.4249484103983754120420413946545,0.9272952980016154324285124629296)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.digamma(new Apcomplex("(3000000,-4000000)").precision(30));
        assertEquals("3000000-4000000i precision", 30, a.precision());
        assertEquals("3000000-4000000i value", new Apcomplex("(15.4249484103983754120420413946545,-0.9272952980016154324285124629296)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.digamma(new Apcomplex("(-3000000,4000000)").precision(30));
        assertEquals("-3000000+4000000i precision", 30, a.precision());
        assertEquals("-3000000+4000000i value", new Apcomplex("(15.4249485303983754120420413947,2.2142975155881778060341309203)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.digamma(new Apcomplex("(-3000000,-4000000)").precision(30));
        assertEquals("-3000000-4000000i precision", 30, a.precision());
        assertEquals("-3000000-4000000i value", new Apcomplex("(15.4249485303983754120420413947,-2.2142975155881778060341309203)"), a, new Apfloat("5e-28"));

        a = ApcomplexMath.digamma(new Apcomplex("(0,1e4000000)").precision(30));
        assertEquals("1e4000000i precision", 36, a.precision());
        assertEquals("1e4000000i value", new Apcomplex("(9.21034037197618273607196581873745683e6,1.57079632679489661923132169164)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(new Apcomplex("(0,-1e4000000)").precision(30));
        assertEquals("-1e4000000i precision", 36, a.precision());
        assertEquals("-1e4000000i value", new Apcomplex("(9.21034037197618273607196581873745683e6,-1.57079632679489661923132169164)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(new Apcomplex("(1e4000000,1e4000000)").precision(30));
        assertEquals("1e4000000+1e4000000i precision", 36, a.precision());
        assertEquals("1e4000000+1e4000000i value", new Apcomplex("(9.21034071854977301604462052735351756e6,0.78539816339744830961566084582)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(new Apcomplex("(1e4000000,-1e4000000)").precision(30));
        assertEquals("1e4000000-1e4000000i precision", 36, a.precision());
        assertEquals("1e4000000-1e4000000i value", new Apcomplex("(9.21034071854977301604462052735351756e6,-0.78539816339744830961566084582)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(1e3000000,1e4000000)"), 30));
        assertEquals("1e3000000+1e4000000i precision", 36, a.precision());
        assertEquals("1e3000000+1e4000000i value", new Apcomplex("(9.21034037197618273607196581873745683e6,1.57079632679489661923132169164)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(1e3000000,-1e4000000)"), 30));
        assertEquals("1e3000000-1e4000000i precision", 36, a.precision());
        assertEquals("1e3000000-1e4000000i value", new Apcomplex("(9.21034037197618273607196581873745683e6,-1.57079632679489661923132169164)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(1e4000000,1e3000000)"), 30));
        assertEquals("1e4000000+1e3000000i precision", 36, a.precision());
        assertEquals("1e4000000+1e3000000i value", new Apcomplex("9.21034037197618273607196581873745683e6"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(1e4000000,-1e3000000)"), 30));
        assertEquals("1e4000000-1e3000000i precision", 36, a.precision());
        assertEquals("1e4000000-1e3000000i value", new Apcomplex("9.21034037197618273607196581873745683e6"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(1e-3000,1e-4000)"), 30));
        assertEquals("1e-3000+1e-4000i precision", 30, a.precision());
        assertEquals("1e-3000+1e-4000i value", new Apcomplex("(-1.00000000000000000000000000000e3000,1.00000000000000000000000000000e2000)"), a, new Apfloat("5e2971"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(1e-3000,-1e-4000)"), 30));
        assertEquals("1e-3000-1e-4000i precision", 30, a.precision());
        assertEquals("1e-3000-1e-4000i value", new Apcomplex("(-1.00000000000000000000000000000e3000,-1.00000000000000000000000000000e2000)"), a, new Apfloat("5e2971"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(-1e-3000,1e-4000)"), 30));
        assertEquals("-1e-3000+1e-4000i precision", 30, a.precision());
        assertEquals("-1e-3000+1e-4000i value", new Apcomplex("(1.00000000000000000000000000000e3000,1.00000000000000000000000000000e2000)"), a, new Apfloat("5e2971"));

        a = ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(-1e-3000,-1e-4000)"), 30));
        assertEquals("-1e-3000-1e-4000i precision", 30, a.precision());
        assertEquals("-1e-3000-1e-4000i value", new Apcomplex("(1.00000000000000000000000000000e3000,-1.00000000000000000000000000000e2000)"), a, new Apfloat("5e2971"));

        a = ApcomplexMath.digamma(new Apcomplex(new Apfloat(-3, 30, 11), new Apfloat(-4, 30, 11)));
        assertEquals("-3-4i precision radix 11", 30, a.precision());
        assertEquals("-3-4i value radix 11", new Apcomplex(new Apfloat("1.741281343469756a206022a991993", 30, 11), new Apfloat("-2.32249452a48596236132467355150", 30, 11)), a, new Apfloat("5e-29", 1, 11));

        a = ApcomplexMath.digamma(new Apfloat(6, 30, 10));
        assertEquals("6 precision", 30, a.precision(), 1);
        assertEquals("6 value", new Apcomplex("1.70611766843180047272682124325"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.digamma(new Apfloat("-6.5", 30, 10));
        assertEquals("-6.5 precision", 30, a.precision(), 1);
        assertEquals("-6.5 value", new Apcomplex("1.94675748424608678806929117727"), a, new Apfloat("5e-29"));

        try
        {
            ApcomplexMath.digamma(Apcomplex.ZERO);
            fail("Digamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "digamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.digamma(new Apint(-1));
            fail("Digamma of -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "digamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.digamma(ApfloatHelper.setPrecision(new Apcomplex("(-1e4000000,-1)"), 30));
            fail("Loss of precision in cot()");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "imag.lossOfPrecision", lope.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.digamma(new Apcomplex(Apfloat.ZERO, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "digamma.infinitePrecision", iee.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.digamma(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "digamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testPolygamma()
    {
        Apcomplex a = ApcomplexMath.polygamma(0, new Apcomplex("(3,4)").precision(30));
        assertEquals("0, 3+4i precision", 31, a.precision());
        assertEquals("0, 3+4i value", new Apcomplex("(1.55035981733341091269899018667062,1.01050220918604445291687052250976)"), a, new Apfloat("5e-31"));

        a = ApcomplexMath.polygamma(0, new Apcomplex("(-2,-3)").precision(10));
        assertEquals("0, -2-3i precision", 10, a.precision());
        assertEquals("0, -2-3i value", new Apcomplex("(1.361826864,-2.268232244)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.polygamma(1, new Apcomplex("(3,4)").precision(30));
        assertEquals("1, 3+4i precision", 30, a.precision());
        assertEquals("1, 3+4i value", new Apcomplex("(0.113153113946791703820257508880,-0.179680016184178366603774041063)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.polygamma(1, new Apcomplex("(-2,-3)").precision(10));
        assertEquals("1, -2-3i precision", 10, a.precision());
        assertEquals("1, -2-3i value", new Apcomplex("(-0.1651414829,0.1960040752)"), a, new Apfloat("5e-10"));

        a = ApcomplexMath.polygamma(3, new Apcomplex("(3,4)").precision(30));
        assertEquals("3, 3+4i precision", 30, a.precision());
        assertEquals("3, 3+4i value", new Apcomplex("(-0.0190846939956098231157835648328,-0.0024113608683529464829469139204)"), a, new Apfloat("5e-31"));

        a = ApcomplexMath.polygamma(3, new Apcomplex("(-2,-3)").precision(10));
        assertEquals("3, -2-3i precision", 10, a.precision());
        assertEquals("3, -2-3i value", new Apcomplex("(0.02884298730,0.01752010783)"), a, new Apfloat("5e-11"));

        a = ApcomplexMath.polygamma(2, new Apcomplex("1").precision(6));
        assertEquals("2, 1 precision", 6, a.precision());
        assertEquals("2, 1 value", new Apcomplex("-2.40411"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(1, new Apcomplex("-5003.5"));
        assertEquals("1, -5003.5 precision", 5, a.precision());
        assertEquals("1, -5003.5 value", new Apcomplex("9.8694"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.polygamma(2, new Apcomplex("-5003.5"));
        assertEquals("2, -5003.5 precision", 5, a.precision());
        assertEquals("2, -5003.5 value", new Apcomplex("-3.99361e-8"), a, new Apfloat("5e-12"));

        a = ApcomplexMath.polygamma(3, new Apcomplex("-5003.5"));
        assertEquals("3, -5003.5 precision", 5, a.precision());
        assertEquals("3, -5003.5 value", new Apcomplex("194.818"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("-5003.500000"));
        assertEquals("4, -5003.5 precision", 10, a.precision());
        assertEquals("4, -5003.5 value", new Apcomplex("-9.5693410233651735889e-15"), a, new Apfloat("5e-24"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("-5003.5000000000000000"));
        assertEquals("4, -5003.5 precision", 20, a.precision());
        assertEquals("4, -5003.5 value", new Apcomplex("-9.5693410233651735889e-15"), a, new Apfloat("5e-34"));

        a = ApcomplexMath.polygamma(5, new Apcomplex("-5003.5"));
        assertEquals("5, -5003.5 precision", 5, a.precision());
        assertEquals("5, -5003.5 value", new Apcomplex("15382"), a, new Apfloat("5e0"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("-5003.51"));
        assertEquals("4, -5003.51 precision", 6, a.precision());
        assertEquals("4, -5003.51 value", new Apcomplex("-154.253"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-5003.5,0.000010000)"));
        assertEquals("4, -5003.5+0.000010000i precision", 1, a.precision());
        assertEquals("4, -5003.5+0.000010000i value", new Apcomplex("(-9.5693e-15,0.15382)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-5003.50000,0.0000100000000)"));
        assertEquals("4, -5003.50000+0.0000100000000i precision", 5, a.precision());
        assertEquals("4, -5003.50000+0.0000100000000i value", new Apcomplex("(-9.5693e-15,0.15382)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-5003.50000000000,0.0000100000000000000)"));
        assertEquals("4, -5003.50000000000+0.0000100000000000000i precision", 11, a.precision());
        assertEquals("4, -5003.50000000000+0.0000100000000000000i value", new Apcomplex("(-9.569341023365e-15,0.1538222705419019711488850)"), a, new Apfloat("5e-25"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("5003.5"));
        assertEquals("4, 5003.5 precision", 5, a.precision());
        assertEquals("4, 5003.5 value", new Apcomplex("-9.57699e-15"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.polygamma(600, new Apcomplex("-50.4"));
        assertEquals("600, -50.4 precision", 3, a.precision());
        assertEquals("600, -50.4 value", new Apcomplex("1.8375e1647"), a, new Apfloat("5e1645"));

        a = ApcomplexMath.polygamma(600, new Apcomplex("50.4"));
        assertEquals("600, 50.4 precision", 3, a.precision());
        assertEquals("600, 50.4 value", new Apcomplex("-8.74e384"), a, new Apfloat("5e382"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-1.5000,0.000010000)"));
        assertEquals("4, -1.5000+0.000010000i precision", 2, a.precision());
        assertEquals("4, -1.5000+0.000010000i value", new Apcomplex("(-0.313756,0.153816)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-1.5000,-0.000010000)"));
        assertEquals("4, -1.5000-0.000010000i precision", 2, a.precision());
        assertEquals("4, -1.5000-0.000010000i value", new Apcomplex("(-0.313756,-0.153816)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-1.5000,0.0000010000)"));
        assertEquals("4, -1.5000+0.0000010000i precision",5, a.precision());
        assertEquals("4, -1.5000+0.0000010000i value", new Apcomplex("(-0.313756,0.0153816)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(4, new Apcomplex("(-1.5000,-0.0000010000)"));
        assertEquals("4, -1.5000-0.0000010000i precision",5, a.precision());
        assertEquals("4, -1.5000-0.0000010000i value", new Apcomplex("(-0.313756,-0.0153816)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(-1, new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-1, 3+4i precision", 6, a.precision());
        assertEquals("-1, 3+4i value", new Apcomplex("(-1.75663,4.74266)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(-2, new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-2, 3+4i precision", 6, a.precision());
        assertEquals("-2, 3+4i value", new Apcomplex("(-7.43047,-0.789122)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(-3, new Apcomplex("(3.000000,4.000000)"));
        assertEquals("-3, 3+4i precision", 6, a.precision());
        assertEquals("-3, 3+4i value", new Apcomplex("(0.70938,-6.30055)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(-4, new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-4, 3+4i precision", 6, a.precision());
        assertEquals("-4, 3+4i value", new Apcomplex("(4.89603,5.75728)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(-5, new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-5, 3+4i precision", 6, a.precision());
        assertEquals("-5, 3+4i value", new Apcomplex("(-11.5776,10.0081)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.polygamma(-7, new Apcomplex("(-3.20000,-4.70000)"));
        assertEquals("-7, -3.2-4.7i precision", 6, a.precision());
        assertEquals("-7, -3.2-4.7i value", new Apcomplex("(69.1597,118.979)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.polygamma(-2, Apcomplex.ZERO);;
        assertEquals("-2, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-2, 0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.polygamma(-2, new Apcomplex("-1.00000"));
        assertEquals("-2, -1 precision", 6, a.precision());
        assertEquals("-2, -1 value", new Apcomplex("(-1.91894,3.14159)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polygamma(2, new Apcomplex(new Apfloat(3, 30, 11), new Apfloat(4, 30, 11)));
        assertEquals("2, 3+4i precision radix 11", 30, a.precision());
        assertEquals("2, 3+4i value radix 11", new Apcomplex(new Apfloat("0.023866885496877523831350945a02661", 30, 11), new Apfloat("0.04a32896020596a836741478583250141", 30, 11)), a, new Apfloat("5e-31", 1, 11));

        a = ApcomplexMath.polygamma(2, new Apcomplex(new Apfloat(-3, 30, 11), new Apfloat(-4, 30, 11)));
        assertEquals("2, -3-4i precision radix 11", 30, a.precision());
        assertEquals("2, -3-4i value radix 11", new Apcomplex(new Apfloat("0.0059379999060207591036403634387439", 30, 11), new Apfloat("0.0428884949a3897211182765818663501", 30, 11)), a, new Apfloat("5e-31", 1, 11));

        a = ApcomplexMath.polygamma(-2, new Apcomplex(new Apfloat(-3, 31, 11), new Apfloat(-4, 31, 11)));
        assertEquals("-2, -3-4i precision radix 11", 30, a.precision());
        assertEquals("-2, -3-4i value radix 11", new Apcomplex(new Apfloat("27.180454768698a1264481217a11604", 30, 11), new Apfloat("3.1116947a7840972664272592a0a10", 30, 11)), a, new Apfloat("5e-28", 1, 11));

        a = ApcomplexMath.polygamma(-13, new Apcomplex(new Apfloat(-3, 60, 11), new Apfloat(-4, 60, 11)));
        assertEquals("-13, -3-4i precision radix 11", 60, a.precision());
        assertEquals("-13, -3-4i value radix 11", new Apcomplex(new Apfloat("1.434a51462476983260500a324710178015973a711771a77403a32a60135036a6", 60, 11), new Apfloat("-0.628379556191234485703854251394634462a7a074a97606358091a63249078a", 60, 11)), a, new Apfloat("5e-59", 1, 11));

        try
        {
            ApcomplexMath.polygamma(1, Apcomplex.ZERO);
            fail("Polygamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "polygamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.polygamma(1, new Apint(-1));
            fail("Polygamma of -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "polygamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.polygamma(-1, Apcomplex.ZERO);
            fail("Polygamma -1 of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "polygamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.polygamma(1, new Apcomplex(Apfloat.ZERO, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "zeta.infinitePrecision", iee.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.polygamma(1, new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "zeta.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBarnesG()
    {
        Apcomplex a = ApcomplexMath.barnesG(new Apcomplex("0.50000000"));
        assertEquals("0.5 precision", 8, a.precision());
        assertEquals("0.5 value", new Apfloat("0.60324428"), a, new Apfloat("5e-8"));
        a = ApcomplexMath.barnesG(new Apcomplex("-0.500000000"));
        assertEquals("-0.5 precision", 8, a.precision());
        assertEquals("-0.5 value", new Apfloat("-0.17017207"), a, new Apfloat("5e-8"));
        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat(0, 8, 5)));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 radix", 5, a.radix());
        assertEquals("0 value", new Apfloat(0, 8, 5), a);
        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat(-1, 8, 5)));
        assertEquals("-1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1 radix", 5, a.radix());
        assertEquals("-1 value", new Apfloat(0, 8, 5), a);
        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat(1, 8, 5)));
        assertEquals("1 precision", 8, a.precision());
        assertEquals("1 radix", 5, a.radix());
        assertEquals("1 value", new Apfloat(1, 8, 5), a, new Apfloat("2e-8", 1, 5));
        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat(2, 100, 15)));
        assertEquals("2 precision", 100, a.precision());
        assertEquals("2 radix", 15, a.radix());
        assertEquals("2 value", new Apfloat(1, 100, 15), a,new Apfloat(7, 1, 15).scale(-100));
        a = ApcomplexMath.barnesG(new Apcomplex("3.00000"));
        assertEquals("3 precision", 6, a.precision());
        assertEquals("3 value", new Apfloat(1), a, new Apfloat("5e-5"));
        a = ApcomplexMath.barnesG(new Apcomplex("10.50000"));
        assertEquals("10.5 precision", 5, a.precision());
        assertEquals("10.5 value", new Apfloat("2.2987e18"), a, new Apfloat("5e-14"));
        a = ApcomplexMath.barnesG(new Apcomplex("(2.300000,5.600000)"));
        assertEquals("(2.3,5.6) precision", 5, a.precision());
        assertEquals("(2.3,5.6) value", new Apcomplex("(2.99395e-6,-1.65694e-6)"), a, new Apfloat("5e-10"));
        a = ApcomplexMath.barnesG(new Apcomplex("(12.300000000000000000,-45.600000000000000000)"));
        assertEquals("(12.3,-45.6) precision", 17, a.precision());
        assertEquals("(12.3,-45.6) value", new Apcomplex("(1.6038751856699696e-1289,-1.4566702964503091e-1289)"), a, new Apfloat("5e-1306"));
        a = ApcomplexMath.barnesG(new Apcomplex("(45.600000000000000000,12.300000000000000000)"));
        assertEquals("(45.6,12.3) precision", 17, a.precision());
        assertEquals("(45.6,12.3) value", new Apcomplex("(1.2404253654869028e885,-2.789163740081503e884)"), a, new Apfloat("5e867"));
        a = ApcomplexMath.barnesG(new Apcomplex("(-45.600000000000000000,12.300000000000000000)"));
        assertEquals("(-45.6,12.3) precision", 16, a.precision());
        assertEquals("(-45.6,12.3) value", new Apcomplex("(-5.6302245434406329e1740,-8.4893007300457255e1740)"), a, new Apfloat("5e1724"));

        a = ApcomplexMath.barnesG(new Apint(30));
        assertEquals("30 precision", Apfloat.INFINITE, a.precision());
        assertEquals("30 value", new Apint("24378759692569493001843754884245889709720110123963670883808668267742801150073945462248212671568308430773839473807128215512114800359197934772179842358860234182649345336155492659539815888875032454531949849910359883836215115120785688966546366708482811138722465511411531795422982963200000000000000000000000000000000000000000000000000000000000000000000000000"), a);
        a = ApcomplexMath.barnesG(new Apint(25, 35));
        assertEquals("25 precision", Apfloat.INFINITE, a.precision());
        assertEquals("25 radix", 35, a.radix());
        assertEquals("25 value", new Apint("11kip7fkytm5ja9dv184dog9ugg6bi4ll1fqcw1nu00ow9il1rlalin7tlm3wly1cffmviv9qy0wys28g7fjijjlew973jh0n55jlfdo1luji760p000000000000000000000000000000", 35), a);
        a = ApcomplexMath.barnesG(new Apint(26, 36));
        assertEquals("26 precision", Apfloat.INFINITE, a.precision());
        assertEquals("26 radix", 36, a.radix());
        assertEquals("26 value", new Apint("1xmbv23atp08znokdlfvlz96tsjwr9rcyldl9lktpt9h04fntr9y79053hmz38gp4js8e2vyfy3rn0rkqitq57wfnx5ppn34jhmo000000000000000000000000000000000000000000000000000000000", 36), a);
        a = ApcomplexMath.barnesG(new Apfloat(1000000, 100));
        assertEquals("1000000 precision", 86, a.precision());
        assertEquals("1000000 value", new Apfloat("1.0145655480290378725684376810089100792606395451712942456285894330569570164811886697439e2674273971959"), a, new Apfloat("5e2674273971873"));

        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat("1.6", 50, 12)));
        assertEquals("1.5 precision", 50, a.precision());
        assertEquals("1.5 radix", 12, a.radix());
        assertEquals("1.5 value", new Apfloat("1.09b74988172189564a0a65340788a7655960695071856178a", 50, 12), a, new Apfloat("6e-50", 1, 12));
        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat("1.6", 50, 12), new Apfloat("1.6", 50, 12)));
        assertEquals("(1.5,1.5) precision", 48, a.precision());
        assertEquals("(1.5,1.5) radix", 12, a.radix());
        assertEquals("(1.5,1.5) value", new Apcomplex(new Apfloat("1.068006449b0b4bb1a2239185b395a74a2a8a209b625195042", 50, 12), new Apfloat("-0.b990847b3ba27a23092a292036713862946120970b22228539", 50, 12)), a, new Apfloat("6e-47", 1, 12));
        a = ApcomplexMath.barnesG(new Apcomplex(new Apfloat("-1.6", 50, 12), new Apfloat("-1.6", 50, 12)));
        assertEquals("(-1.5,-1.5) precision", 48, a.precision());
        assertEquals("(-1.5,-1.5) radix", 12, a.radix());
        assertEquals("(-1.5,-1.5) value", new Apcomplex(new Apfloat("-59.07844973188b53033b2532752b72283b3b44ba51809025a44", 50, 12), new Apfloat("-3ab.bbb28ba690454a798499a2baa50b3391a684804a16b789798", 50, 12)), a, new Apfloat("6e-47", 1, 12));

        try
        {
            ApcomplexMath.barnesG(new Apfloat("1826012432"));
            fail("Loss of accuracy");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "lossOfPrecision", lope.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.barnesG(new Apcomplex("1826012431.1"));
            fail("Loss of accuracy");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "lossOfPrecision", lope.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.barnesG(new Apcomplex(new Apfloat("4.5", Apfloat.INFINITE)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "glaisher.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLogBarnesG()
    {
        Apcomplex a = ApcomplexMath.logBarnesG(new Apcomplex("0.500000000"));
        assertEquals("0.5 precision", 8, a.precision());
        assertEquals("0.5 value", new Apfloat("-0.50543305"), a, new Apfloat("5e-8"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("-0.500000000"));
        assertEquals("-0.5 precision", 8, a.precision());
        assertEquals("-0.5 value", new Apcomplex("(-1.7709452,3.1415927)"), a, new Apfloat("5e-7"));
        a = ApcomplexMath.logBarnesG(new Apcomplex(new Apfloat(1, 8, 5)));
        assertEquals("1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("1 radix", 5, a.radix());
        assertEquals("1 value", new Apfloat(0, 8, 5), a);
        a = ApcomplexMath.logBarnesG(new Apcomplex(new Apfloat(2, 100, 15)));
        assertEquals("2 precision", Apfloat.INFINITE, a.precision());
        assertEquals("2 radix", 15, a.radix());
        assertEquals("2 value", new Apfloat(0, 100, 15), a);
        a = ApcomplexMath.logBarnesG(new Apcomplex("3.00000"));
        assertEquals("3 precision", Apfloat.INFINITE, a.precision());
        assertEquals("3 value", new Apfloat(0), a);
        a = ApcomplexMath.logBarnesG(new Apcomplex("4.0000000"));
        assertEquals("4 precision", 6, a.precision());
        assertEquals("4 value", new Apfloat("0.693147"), a, new Apfloat("5e-6"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("9.000"));
        assertEquals("9 precision", 4, a.precision());
        assertEquals("9 value", new Apfloat("25.55"), a, new Apfloat("5e-2"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("(2.3000000000000000000,5.6000000000000000000)"));
        assertEquals("(2.3,5.6) precision", 19, a.precision());
        assertEquals("(2.3,5.6) value", new Apcomplex("(-12.58532330466144013,-13.07184159352336118)"), a, new Apfloat("5e-18"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("(-23.40000000000000000,-56.70000000000000000)"));
        assertEquals("(-23.4,-56.7) precision", 19, a.precision());
        assertEquals("(-23.4,-56.7) value", new Apcomplex("(-722.69949187164653999,6166.18602983642295464)"), a, new Apfloat("5e-15"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("1000000.1"));
        assertEquals("1000000.1 precision", 8, a.precision());
        assertEquals("1000000.1 value", new Apcomplex("6.15774466e12"), a, new Apfloat("5e4"));
        a = ApcomplexMath.logBarnesG(new Apfloat("999999", 70));
        assertEquals("999999 precision", 69, a.precision());
        assertEquals("999999 value", new Apcomplex("6.15773056692403075737116248660514402728615003732433828879731998969726e12"), a, new Apfloat("5e-58"));

        a = ApcomplexMath.logBarnesG(new Apcomplex("10.000000000000000000"));
        assertEquals("10 precision", 20, a.precision());
        assertEquals("10 value", new Apfloat("36.1594676987387574"), a, new Apfloat("5e-18"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("1.00000e100"));
        assertEquals("1e100 precision", 6, a.precision());
        assertEquals("1e100 value", new Apfloat("1.14379e202"), a, new Apfloat("5e197"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("1.00000e1000000000000"));
        assertEquals("1e1000000000000 precision", 6, a.precision());
        assertEquals("1e1000000000000 value", new Apfloat("1.15129e2000000000012"), a, new Apfloat("5e2000000000007"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("1.00000e1000000000000000"));
        assertEquals("1e1000000000000000 precision", 6, a.precision());
        assertEquals("1e1000000000000000 value", new Apfloat("1.15129e2000000000000015"), a, new Apfloat("5e2000000000000010"));
        a = ApcomplexMath.logBarnesG(new Apcomplex("(0,1.00000e10000000000)"));
        assertEquals("1e10000000000i precision", 6, a.precision());
        assertEquals("1e10000000000i value", new Apcomplex("(-1.15129e20000000010,-7.85398e19999999999)"), a, new Apfloat("5e19999999994"));

        a = ApcomplexMath.logBarnesG(new Apcomplex(new Apfloat("1.6", 50, 12)));
        assertEquals("1.5 precision", 48, a.precision());
        assertEquals("1.5 radix", 12, a.radix());
        assertEquals("1.5 value", new Apfloat("0.0977a966aa51b71362585a1056387a57105613567975b33359473", 50, 12), a, new Apfloat("6e-49", 1, 12));
        a = ApcomplexMath.logBarnesG(new Apcomplex(new Apfloat("1.6", 50, 12), new Apfloat("1.6", 50, 12)));
        assertEquals("(1.5,1.5) precision", 47, a.precision());
        assertEquals("(1.5,1.5) radix", 12, a.radix());
        assertEquals("(1.5,1.5) value", new Apcomplex(new Apfloat("0.44201652b040a0b55394209240615544762aa60592417152b350", 50, 12), new Apfloat("-0.90862aa7a449152891b69b40102245a27177b82611413748b23a", 50, 12)), a, new Apfloat("6e-47", 1, 12));
        a = ApcomplexMath.logBarnesG(new Apcomplex(new Apfloat("-1.6", 50, 12), new Apfloat("-1.6", 50, 12)));
        assertEquals("(-1.5,-1.5) precision", 49, a.precision());
        assertEquals("(-1.5,-1.5) radix", 12, a.radix());
        assertEquals("(-1.5,-1.5) value", new Apcomplex(new Apfloat("6.4139b28974baa05683b7785b2aab3a24a72059b2b76112a97449", 50, 12), new Apfloat("-7.b8624a9886b09035067b3a0592671a13876a3652092920603617", 50, 12)), a, new Apfloat("6e-48", 1, 12));

        try
        {
            ApcomplexMath.logBarnesG(new Apcomplex("0"));
            fail("logG of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "logG.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.logBarnesG(new Apcomplex("-1"));
            fail("logG of -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "logG.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.logBarnesG(new Apcomplex(new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBeta()
    {
        Apcomplex a = ApcomplexMath.beta(new Apcomplex("(1,2)").precision(30), new Apcomplex("(3,4)").precision(30));
        assertEquals("1+2i, 3+4i precision", 30, a.precision());
        assertEquals("1+2i, 3+4i value", new Apcomplex("(-0.061274167452252944196162548943,0.197519756150022453064336846144)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.beta(new Apcomplex("3.00000"), new Apcomplex("3.50000"));
        assertEquals("3, 3.5 precision", 6, a.precision());
        assertEquals("3, 3.5 value", new Apcomplex("0.0230880"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.beta(new Apcomplex("3.50000"), new Apcomplex("3.00000"));
        assertEquals("3.5, 3 precision", 6, a.precision());
        assertEquals("3.5, 3 value", new Apcomplex("0.0230880"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.beta(new Apcomplex("3").precision(30), new Apcomplex("-3").precision(30));
        assertEquals("3, -3 precision", 30, a.precision());
        assertEquals("3, -3 value", new Apcomplex("-0.333333333333333333333333333333"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.beta(new Apcomplex("3.5"), new Apcomplex("-3.5"));
        assertEquals("3.5, -3.5 precision", Apfloat.INFINITE, a.precision());
        assertEquals("3.5, -3.5 value", new Apcomplex("0"), a);

        a = ApcomplexMath.beta(new Apcomplex("-0.999999"), new Apcomplex("4.00000"));
        assertEquals("-0.999999, 4 precision", 6, a.precision());
        assertEquals("-0.999999, 4 value", new Apcomplex("-2.99999e6"), a, new Apfloat("5e1"));

        a = ApcomplexMath.beta(new Apcomplex("4.00000"), new Apcomplex("-0.999999"));
        assertEquals("4, -0.999999 precision", 6, a.precision());
        assertEquals("4, -0.999999 value", new Apcomplex("-2.99999e6"), a, new Apfloat("5e1"));

        try
        {
            ApcomplexMath.beta(new Apcomplex("-4"), new Apcomplex("3.5"));
            fail("Beta of -4, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.beta(new Apcomplex("-4"), new Apcomplex("-3"));
            fail("Beta of -4, -3");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "beta.infinite", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.beta(new Apint(4), new Apint(-3));
            fail("Beta of 4, -3");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "beta.infinite", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.beta(new Apint(0), new Apint(1));
            fail("Beta of 0, 1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "beta.infinite", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.beta(new Apint(0), new Apint(0));
            fail("Beta of 0, 0");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "beta.infinite", aae.getLocalizationKey());
        }
    }

    public static void testBetaIncomplete()
    {
        Apcomplex a = ApcomplexMath.beta(new Apcomplex("(1,2)").precision(30), new Apcomplex("(3,4)").precision(30), new Apcomplex("(5,6)").precision(30));
        assertEquals("1+2i, 3+4i, 5+6i precision", 29, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i value", new Apcomplex("(-1720.81983111510859046209114724,-1217.54471001550464664125821887)"), a, new Apfloat("5e-25"));

        a = ApcomplexMath.beta(new Apcomplex("(1,2)").precision(30), new Apcomplex("1").precision(30), new Apcomplex("(5,6)").precision(30));
        assertEquals("1+2i, 1, 5+6i precision", 29, a.precision());
        assertEquals("1+2i, 1, 5+6i value", new Apcomplex("(7146.750742209233540609443877,-50265.400817471882772163196595)"), a, new Apfloat("5e-24"));

        try
        {
            ApcomplexMath.beta(new Apcomplex("1"), new Apcomplex("-4"), new Apcomplex("3.5"));
            fail("Beta of 1, -4, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "betaIncomplete.withNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.beta(new Apcomplex("0"), new Apcomplex("(0,4)"), new Apcomplex("3.5"));
            fail("Beta of 0, 4i, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.beta(new Apcomplex("1"), new Apcomplex("0"), new Apcomplex("3.5"));
            fail("Beta of 1, 0, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "betaIncomplete.withNonpositiveInteger", aae.getLocalizationKey());
        }
    }

    public static void testBetaIncompleteGeneralized()
    {
        Apcomplex a = ApcomplexMath.beta(new Apcomplex("(1,2)").precision(30), new Apcomplex("(3,4)").precision(30), new Apcomplex("(5,6)").precision(30), new Apcomplex("(7,8)").precision(30));
        assertEquals("1+2i, 3+4i, 5+6i, 7+8i precision", 29, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 7+8i value", new Apcomplex("(4.50638342846197639932002079147e10,3.86722680716135531751599616064e10)"), a, new Apfloat("5e-18"));

        a = ApcomplexMath.beta(new Apcomplex("(2.000000,3.000000)"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("1.000000"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("2+3i, 3+4i, 1, 5+6i precision", 6, a.precision());
        assertEquals("2+3i, 3+4i, 1, 5+6i value", new Apcomplex("(1.82681e7,4.14226e7)"), a, new Apfloat("5e2"));

        a = ApcomplexMath.beta(new Apcomplex("2"), new Apcomplex("2"), new Apcomplex("0"), new Apcomplex("3.5"));
        assertEquals("2, 2, 0, 3.5 precision", Apfloat.INFINITE, a.precision());
        assertEquals("2, 2, 0, 3.5 value", new Apcomplex("0"), a);

        try
        {
            ApcomplexMath.beta(new Apcomplex("1"), new Apcomplex("2"), new Apcomplex("-4"), new Apcomplex("3.5"));
            fail("Beta of 1, 2, -4, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "betaIncompleteGeneralized.withNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.beta(new Apcomplex("0"), new Apcomplex("1"), new Apcomplex("(0,4)"), new Apcomplex("3.5"));
            fail("Beta of 0, 1, 4i, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.beta(new Apcomplex("1"), new Apcomplex("0"), new Apcomplex("(0,4)"), new Apcomplex("3.5"));
            fail("Beta of 1, 0, 4i, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.beta(new Apcomplex("1"), new Apcomplex("2"), new Apcomplex("0"), new Apcomplex("3.5"));
            fail("Beta of 1, 2, 0, 3.5");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "betaIncompleteGeneralized.withNonpositiveInteger", aae.getLocalizationKey());
        }
    }

    public static void testPochhammer()
    {
        Apcomplex a = ApcomplexMath.pochhammer(new Apcomplex("(1,2)").precision(30), new Apcomplex("(3,4)").precision(30));
        assertEquals("1+2i, 3+4i precision", 30, a.precision());
        assertEquals("1+2i, 3+4i value", new Apcomplex("(-0.804367351520622246280725889393,0.223073388594934185914414383944)"), a, new Apfloat("5e-30"));

        a = ApcomplexMath.pochhammer(new Apcomplex("0"), new Apcomplex("-1.00"));
        assertEquals("0, -1 precision", 3, a.precision());
        assertEquals("0, -1 value", new Apcomplex("-1.00"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.pochhammer(new Apcomplex("-1.00"), new Apcomplex("0"));
        assertEquals("-1, 0 precision", 3, a.precision());
        assertEquals("-1, 0 value", new Apcomplex("1.00"), a);

        a = ApcomplexMath.pochhammer(new Apcomplex("-1.00"), new Apcomplex("1.00"));
        assertEquals("0, -1 precision", 3, a.precision());
        assertEquals("0, -1 value", new Apcomplex("-1.00"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.pochhammer(new Apcomplex("-1.00"), new Apcomplex("2.00"));
        assertEquals("-1, 2 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, 2 value", new Apcomplex("0"), a);

        a = ApcomplexMath.pochhammer(new Apcomplex("0"), new Apcomplex("1.00"));
        assertEquals("0, 1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 1 value", new Apcomplex("0"), a);

        a = ApcomplexMath.pochhammer(new Apcomplex("-1.00"), new Apcomplex("0.500"));
        assertEquals("-1, 0.5 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, 0.5 value", new Apcomplex("0"), a);

        a = ApcomplexMath.pochhammer(new Apcomplex("3.00"), new Apcomplex("-1.00"));
        assertEquals("3, -1 precision", 3, a.precision());
        assertEquals("3, -1 value", new Apcomplex("0.500"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.pochhammer(new Apcomplex("0"), new Apcomplex("-2.00"));
        assertEquals("0, -2 precision", 3, a.precision());
        assertEquals("0, -2 value", new Apcomplex("0.500"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.pochhammer(new Apcomplex("3.00"), new Apcomplex("(0,2.00)"));
        assertEquals("3, -2i precision", 3, a.precision());
        assertEquals("3, -2i value", new Apcomplex("(-0.211,0.436)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.pochhammer(new Apcomplex("0.12345"), new Apcomplex("12345"));
        assertEquals("0.12345, 12345 precision", 5, a.precision());
        assertEquals("0.12345, 12345 value", new Apcomplex("1.16927e45146"), a, new Apfloat("5e45142"));

        a = ApcomplexMath.pochhammer(new Apcomplex("-0.999999"), new Apcomplex("2.00000"));
        assertEquals("-0.999999, 2 precision", 6, a.precision());
        assertEquals("-0.999999, 2 value", new Apcomplex("-9.99999e-7"), a, new Apfloat("5e-12"));

        a = ApcomplexMath.pochhammer(new Apcomplex("-0.999999"), new Apcomplex("3.50000"));
        assertEquals("-0.999999, 3.5 precision", 6, a.precision());
        assertEquals("-0.999999, 3.5 value", new Apcomplex("-1.32934e-6"), a, new Apfloat("5e-11"));

        a = ApcomplexMath.pochhammer(new Apcomplex("1.00000e-1000000000000000"), new Apcomplex("2.00000"));
        assertEquals("1e-1000000000000000, 2 precision", 6, a.precision());
        assertEquals("1e-1000000000000000, 2 value", new Apcomplex("1.00000e-1000000000000000"), a, new Apfloat("5e-1000000000000005"));

        try
        {
            ApcomplexMath.pochhammer(new Apcomplex("-0.50000"), new Apcomplex("-0.50000"));
            fail("Gamma of -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofNegativeInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.pochhammer(new Apcomplex("0.50000"), new Apcomplex("-0.50000"));
            fail("Gamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.pochhammer(new Apcomplex("1"), new Apcomplex("-1"));
            fail("Gamma of zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.pochhammer(new Apcomplex(new Apint(1), new Apint(2)), new Apcomplex(new Apint(3), new Apint(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBinomial()
    {
        Apcomplex a = ApcomplexMath.binomial(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("(3,4),(5,6) precision", 6, a.precision());
        assertEquals("(3,4),(5,6) value", new Apcomplex("(-3.10924,-1.60449)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.binomial(new Apfloat(0), new Apfloat(0));
        assertEquals("0,0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0,0 value", new Apfloat(1), a);

        a = ApcomplexMath.binomial(new Apfloat(1), new Apfloat(0));
        assertEquals("1,0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("1,0 value", new Apfloat(1), a);

        a = ApcomplexMath.binomial(new Apcomplex("(0,3.20000)"), new Apcomplex("4.00000"));
        assertEquals("3.2i,4 precision", 6, a.precision());
        assertEquals("3.2i,4 value", new Apcomplex("(-0.324267,7.39200)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.binomial(new Apcomplex("(7.20000,1.00000)"), new Apcomplex("(4.20000,1.00000)"));
        assertEquals("7.2+i,4.2+i precision", 6, a.precision());
        assertEquals("7.2+i,4.2+i value", new Apcomplex("(35.5880,18.8867)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.binomial(new Apcomplex("(3.20000,1.00000)"), new Apcomplex("(4.20000,1.00000)"));
        assertEquals("3.2+i,4.2+i precision", Apcomplex.INFINITE, a.precision());
        assertEquals("3.2+i,4.2+i value", new Apcomplex("0"), a);

        a = ApcomplexMath.binomial(new Apcomplex("(0,3.20000)"), new Apcomplex("-4.00000"));
        assertEquals("3.2i,-4 precision", Apcomplex.INFINITE, a.precision());
        assertEquals("3.2i,-4 value", new Apcomplex("0"), a);

        try
        {
            ApcomplexMath.binomial(new Apcomplex("-3.00000"), new Apcomplex("(0,4.00000)"));
            fail("Binomial of -3,4i");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "gamma.ofNegativeInteger", aae.getLocalizationKey());
        }
    }

    public static void testZeta()
    {
        Apcomplex a = ApcomplexMath.zeta(new Apcomplex("(2.00000,3.00000)"));
        assertEquals("2+3i precision", 6, a.precision());
        assertEquals("2+3i value", new Apcomplex("(0.798022,-0.113744)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.zeta(new Apcomplex("(0,3.00000)"));
        assertEquals("0+3i precision", 6, a.precision());
        assertEquals("0+3i value", new Apcomplex("(0.439283,-0.0364719)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.50000,-3.00000)"));
        assertEquals("-1.5-3i precision", 6, a.precision());
        assertEquals("-1.5-3i value", new Apcomplex("(0.201329,-0.0971497)"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,3.00000)"));
        assertEquals("1+3i precision", 6, a.precision());
        assertEquals("1+3i value", new Apcomplex("(0.628852,-0.107476)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.zeta(new Apcomplex("(0.50000,3.00000)"));
        assertEquals("0.5+3i precision", 6, a.precision());
        assertEquals("0.5+3i value", new Apcomplex("(0.532737,-0.0788965)"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.zeta(new Apcomplex("(0.50000,1000.00000)"));
        assertEquals("0.5+1000i precision", 6, a.precision());
        assertEquals("0.5+1000i value", new Apcomplex("(0.356334,0.931998)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,0.00100000)"));
        assertEquals("1+0.001i precision", 6, a.precision());
        assertEquals("1+0.001i value", new Apcomplex("(0.577216,-1000.00)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,3)").precision(100));
        assertEquals("2+3i precision", 100, a.precision());
        assertEquals("2+3i value", new Apcomplex("(0.7980219851462757206222945007248126860252200816083761283248050997826895848039950677534983494423933738,-0.1137443080529385002159133658573150755701378063996650889647244069923585325514128567603037164372547988)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0.5", 100), new Apfloat(1000, 104)));
        assertEquals("0.5+1000i precision 100", 100, a.precision());
        assertEquals("0.5+1000i value 100", new Apcomplex("(0.3563343671943960550744024767110296418750462109065525137341055161422510305547050764059845122070513740,0.9319978312329936651150604327370560741603548016645680162344141200846918466728345537721968349602390048)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0.5", 5), new Apfloat(55000, 10)));
        assertEquals("0.5+10000i precision", 5, a.precision());
        assertEquals("0.5+10000i value", new Apcomplex("(0.33492,0.08418)"), a, new Apfloat("5e-5"));

        /* These tests are quite slow
        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0.5", 100), new Apfloat(55000, 105)));
        assertEquals("0.5+10000i precision", 100, a.precision());
        assertEquals("0.5+10000i value", new Apcomplex("(0.3349197720514120096603674282428742796903831318984995606867247129474952184104423947312465231789576299,0.0841783899417542541667178765548311987703519184678648667055626089534129546322036235064366776146346549)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0.5", 100), new Apfloat(10000, 105)));
        assertEquals("0.5+10000i precision", 100, a.precision());
        assertEquals("0.5+10000i value", new Apcomplex("(-0.3393738026388344575674710779459893805666468101906410889337680247470798756615454924994040171851332603,-0.0370915059732060314743442068130120234022523694433894137028295017082175782077688242563900270774953535)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0.5", 100), new Apfloat(100000, 106)));
        assertEquals("0.5+100000i precision", 101, a.precision());
        assertEquals("0.5+100000i value", new Apcomplex("(1.0730320148577531321140762694920985306591621977677459354641392297498113660694398465432029270776708412,5.7808485443635039842610405578322343742615982357792297214917608074005985960567100284957369179276183025)"), a, new Apfloat("5e-100"));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0.5", 100), new Apfloat(1000000, 108)));
        assertEquals("0.5+1000000i precision", 100, a.precision());
        assertEquals("0.5+1000000i value", new Apcomplex("(0.076089069738227100005564558379927322310798604744722282657978217385062498238818630801746583609816947,2.805102101019298955393836716564940236462506152772803595920107742605247149870834705975457224921619717)"), a, new Apfloat("5e-100"));
        */
        for (int precision = 2; precision < 20; precision++)
        {
            a = ApcomplexMath.zeta(new Apcomplex("(2,3)").precision(precision));
            assertEquals("2+3i precision " + precision, precision, a.precision());
            assertEquals("2+3i value " + precision, new Apcomplex("(0.79802198514627572062,-0.11374430805293850021)").precision(precision), a, new Apfloat("5e-" + precision));
        }

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat(2, 6, 11), new Apfloat(3, 6, 11)));
        assertEquals("2+3i radix 11 precision", 6, a.precision());
        assertEquals("2+3i radix 11 value", new Apcomplex(new Apfloat("0.886193", 6, 11), new Apfloat("-0.128437", 6, 11)), a, new Apfloat("5e-6", 1, 11));

        a = ApcomplexMath.zeta(new Apfloat(-200001, 20));
        assertEquals("-200001 precision", 15, a.precision());
        assertEquals("-200001 value", new Apfloat("-1.5289316181229617526e813718"), a, new Apfloat("5e813704"));

        a = ApcomplexMath.zeta(new Apfloat(-11, 20));
        assertEquals("-11 precision", 19, a.precision());
        assertEquals("-11 value", new Apfloat("0.021092796092796092796"), a, new Apfloat("5e-20"));

        a = ApcomplexMath.zeta(new Apint(-1));
        assertEquals("-1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1 value", new Aprational("-1/12"), a);

        a = ApcomplexMath.zeta(new Apint(-2));
        assertEquals("-2 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-2 value", Apfloat.ZERO, a);

        a = ApcomplexMath.zeta(new Apint(-3));
        assertEquals("-3 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-3 value", new Aprational("1/120"), a);

        a = ApcomplexMath.zeta(new Apint(-4, 11));
        assertEquals("-4 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-4 value", Apfloat.ZERO, a);
        assertEquals("-4 radix", 11, a.radix());

        a = ApcomplexMath.zeta(new Apint(-5, 13));
        assertEquals("-5 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-5 value", new Aprational("-1/165", 13), a);
        assertEquals("-5 radix", 13, a.radix());

        try
        {
            ApcomplexMath.zeta(Apcomplex.ONE);
            fail("Zeta of one");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "zeta.ofOne", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("(0.5,1e1000)"));
            fail("Overflow");
        }
        catch (OverflowException oe)
        {
            // OK
            assertEquals("Localization key", "imag.overflow", oe.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("(0.5,1e100)"));
            fail("Loss of precision");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "imag.lossOfPrecision", lope.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex(Apfloat.ZERO, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "zeta.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testZetaHurwitz()
    {
        Apcomplex a = ApcomplexMath.zeta(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("1+2i,3+4i precision", 6, a.precision());
        assertEquals("1+2i,3+4i value", new Apcomplex("(-0.128334,3.75887)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-1+2i,3+4i precision", 6, a.precision());
        assertEquals("-1+2i,3+4i value", new Apcomplex("(-57.3674,17.7938)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,-2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("1-2i,3+4i precision", 6, a.precision());
        assertEquals("1-2i,3+4i value", new Apcomplex("(-0.00315145,-0.0659678)"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,-2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-1-2i,3+4i precision", 6, a.precision());
        assertEquals("-1-2i,3+4i value", new Apcomplex("(0.370730,0.957515)"), a, new Apfloat("5e-6"));


        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("1+2i,-3+4i precision", 6, a.precision());
        assertEquals("1+2i,-3+4i value", new Apcomplex("(9.3754,47.9189)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,2.00000)"), new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("-1+2i,-3+4i precision", 6, a.precision());
        assertEquals("-1+2i,-3+4i value", new Apcomplex("(423.329,-866.408)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,-2.00000)"), new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("1-2i,-3+4i precision", 6, a.precision());
        assertEquals("1-2i,-3+4i value", new Apcomplex("(0.00104043,-0.00500563)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,-2.00000)"), new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("-1-2i,-3+4i precision", 6, a.precision());
        assertEquals("-1-2i,-3+4i value", new Apcomplex("(-0.0677588,-0.0780479)"), a, new Apfloat("5e-7"));


        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("1+2i,3-4i precision", 6, a.precision());
        assertEquals("1+2i,3-4i value", new Apcomplex("(-0.00315145,0.0659678)"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,2.00000)"), new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("-1+2i,3-4i precision", 6, a.precision());
        assertEquals("-1+2i,3-4i value", new Apcomplex("(0.370730,-0.957515)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,-2.00000)"), new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("1-2i,3-4i precision", 6, a.precision());
        assertEquals("1-2i,3-4i value", new Apcomplex("(-0.128334,-3.75887)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,-2.00000)"), new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("-1-2i,3-4i precision", 6, a.precision());
        assertEquals("-1-2i,3-4i value", new Apcomplex("(-57.3674,-17.7938)"), a, new Apfloat("5e-4"));


        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("1+2i,-3-4i precision", 6, a.precision());
        assertEquals("1+2i,-3-4i value", new Apcomplex("(0.00104043,0.00500563)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,2.00000)"), new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("-1+2i,-3-4i precision", 6, a.precision());
        assertEquals("-1+2i,-3-4i value", new Apcomplex("(-0.0677588,0.0780479)"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.zeta(new Apcomplex("(1.00000,-2.00000)"), new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("1-2i,-3-4i precision", 6, a.precision());
        assertEquals("1-2i,-3-4i value", new Apcomplex("(9.3754,-47.9189)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,-2.00000)"), new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("-1-2i,-3-4i precision", 6, a.precision());
        assertEquals("-1-2i,-3-4i value", new Apcomplex("(423.329,866.408)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.zeta(new Apcomplex("(200,3)").precision(100), new Apcomplex("(4,5)").precision(100));
        assertEquals("200+3i,4+5i precision", 100, a.precision());
        assertEquals("200+3i,4+5i value", new Apcomplex("(-6.510650712253089835100933540605593885423625555766396841030109372143821363398670155866232696777769754e-161,-4.196413709796671831220877888896810470945873889262943538389029106853602203682435123378815438519792110e-161)"), a, new Apfloat("5e-260"));

        a = ApcomplexMath.zeta(new Apcomplex("(-200,3)").precision(100), new Apcomplex("(4,5)").precision(100));
        assertEquals("-200+3i,4+5i precision", 100, a.precision());
        assertEquals("-200+3i,4+5i value", new Apcomplex("(-1.142766776555529743371297901097238001495355117120858842538861484336796660434095964178580019465230251e230,-7.93012330139120590521613115546189973364629076639541502155881731765751317903438879443411307094369442e229)"), a, new Apfloat("5e131"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,300)").precision(100), new Apcomplex("(4,5)").precision(100));
        assertEquals("2+300i,4+5i precision", 100, a.precision());
        assertEquals("2+300i,4+5i value", new Apcomplex("(1.263022208466642119929613734524512143419322652805397208096904557073524855247036414033104354476916940e115,4.97993045496596456851060626340311079427549002991295705149743068485693575066125052846850379420489017e114)"), a, new Apfloat("5e16"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,-300)").precision(100), new Apcomplex("(4,5)").precision(100));
        assertEquals("2-300i,4+5i precision", 100, a.precision());
        assertEquals("2-300i,4+5i value", new Apcomplex("(-1.656175472255496559727564671944616326873344713856337103136980595651959727043476386628834684809146318e-17,-6.681498034417950900886174675379127869732588558333009625497538461825412951655606371987994909561495188e-17)"), a, new Apfloat("5e-116"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,3)").precision(100), new Apcomplex("(400,5)").precision(100));
        assertEquals("2+3i,400+5i precision", 100, a.precision());
        assertEquals("2+3i,400+5i value", new Apcomplex("(0.0007622758908028892841285412120539558133199778951059196976920207815264516538552449013583036172195813640,-0.0003070142863332686417875078833396554514650819941131970534284169324884139279052591800902624774270017371)"), a, new Apfloat("5e-103"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,3)").precision(100), new Apcomplex("(-400,5)").precision(100));
        assertEquals("2+3i,-400+5i precision", 100, a.precision());
        assertEquals("2+3i,-400+5i value", new Apcomplex("(-8.801757372564087615610300337744809871640017567311551657978936640446111619828384618462840131011191894,3.367214239247479438315669736493982562557325268189216328935202322652541577231596038333636652254492929)"), a, new Apfloat("5e-99"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,3)").precision(100), new Apcomplex("(4,500)").precision(100));
        assertEquals("2+3i,4+500i precision", 100, a.precision());
        assertEquals("2+3i,4+500i value", new Apcomplex("(-0.05932655962239436562739499724622952234262807293751692953398064487895538069336256502462076212692751826,-0.03511280488247812166160792282342282860315665135863852252502961596875493374359715802589497563087468930)"), a, new Apfloat("5e-101"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,3)").precision(100), new Apcomplex("(4,-500)").precision(100));
        assertEquals("2+3i,4-500i precision", 100, a.precision());
        assertEquals("2+3i,4-500i value", new Apcomplex("(5.033864599238220394312706546835276797429459490608123122092294078279577716315638351945811941403453475e-6,2.884941945966693002338695967539314988955661994247957452817443910538025152229897547137605972983369419e-6)"), a, new Apfloat("5e-105"));

        a = ApcomplexMath.zeta(new Apcomplex("(-1.00000,2.00000)"), new Apcomplex("-3.00000"));
        assertEquals("-1+2i,-3 precision", 6, a.precision());
        assertEquals("-1+2i,-3 value", new Apcomplex("(210.002,2354.18)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.zeta(new Apcomplex("0"), new Apcomplex("-1.00000"));
        assertEquals("0,-1 precision", 6, a.precision());
        assertEquals("0,-1 value", new Apcomplex("(1.50000)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.zeta(new Apcomplex("0"), new Apcomplex("-2.00000"));
        assertEquals("0,-2 precision", 6, a.precision());
        assertEquals("0,-2 value", new Apcomplex("(2.50000)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.zeta(new Apcomplex("(2,3)"), new Apcomplex("(4,5)"));
        assertEquals("2+3i,4+5i precision", 1, a.precision());
        assertEquals("2+3i,4+5i value", new Apcomplex("(0.2,-0.9)"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.zeta(new Apcomplex("-1.00000000000000000001000000000000000000"), new Apcomplex("(5.8177641733144326503024335907577183960e-3,2.9041784805448350436957228471747086506e-18)"));
        assertEquals("-1.00000000000000000001000000000000000000, 5.8177641733144326503024335907577183960e-3+2.9041784805448350436957228471747086506e-18i precision", 38, a.precision());
        assertEquals("-1.00000000000000000001000000000000000000, 5.8177641733144326503024335907577183960e-3+2.9041784805448350436957228471747086506e-18i value", new Apcomplex("(-0.08044137443666426748877533567221511214,1.43519341475539303437e-18)"), a, new Apfloat("5e-39"));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("-7.5", 18, 9), new Apfloat("-3.2", 18, 9)), new Apcomplex(new Apfloat("-2.3", 18, 9), new Apfloat("-4.6", 18, 9)));
        assertEquals("-7.5-3.2i,-2.3-4.6i radix 9 precision", 18, a.precision());
        assertEquals("-7.5-3.2i,-2.3-4.6i radix 9 value", new Apcomplex(new Apfloat("-4.30042688353112500e8", 18, 9), new Apfloat("1.43812330126776638e8", 18, 9)), a, new Apfloat("5e-8", 1, 9));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("-1", 18, 2)), new Apcomplex(new Apfloat("0", 18, 2)));
        assertEquals("-1,0 radix 2 precision", 18, a.precision());
        assertEquals("-1,0 radix 2 value", new Apcomplex(new Apfloat("-0.00010101010101010101011", 18, 2)), a, new Apfloat("1e-21", 1, 2));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0", 18, 2)), new Apcomplex(new Apfloat("-1", 18, 2)));
        assertEquals("0,-1 radix 2 precision", 18, a.precision());
        assertEquals("0,-1 radix 2 value", new Apcomplex(new Apfloat("1.1", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("-0.1", 18, 2)), new Apcomplex(new Apfloat("-1", 18, 2)));
        assertEquals("-0.1,-1 radix 2 precision", 18, a.precision());
        assertEquals("-0.1,-1 radix 2 value", new Apcomplex(new Apfloat("-0.001101010011100000001", 18, 2), new Apfloat("1", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        a = ApcomplexMath.zeta(new Apcomplex(new Apfloat("0", 18, 2)), new Apcomplex(new Apfloat("0", 18, 2)));
        assertEquals("0,0 radix 2 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0,0 radix 2 value", new Apcomplex(new Apfloat("0.1", Apfloat.INFINITE, 2)), a);

        for (int r = -5; r <= 5; r += 2)
        {
            for (int i = -5; i <= 5; i += 2)
            {
                Apfloat real = new Apfloat(r + 0.5, 10),
                        imag = new Apfloat(i + 0.5, 10);
                a = new Apcomplex(real, imag);
                Apcomplex hurwitz = ApcomplexMath.zeta(a, new Apfloat(1, 10));
                Apcomplex riemann = ApcomplexMath.zeta(a);
                //assertEquals(a + " algorithm precision", riemann.precision(), hurwitz.precision(), 1);
                assertEquals(a + " algorithm value", riemann, hurwitz, new Apfloat("5e" + (hurwitz.scale() - hurwitz.precision())));
            }
        }

        try
        {
            ApcomplexMath.zeta(Apcomplex.ONE, new Apfloat(2.0));
            fail("Zeta of one");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "zeta.ofFirstOne", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("2"), new Apfloat(0));
            fail("Zeta of a 0");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "zeta.ofSecondNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("2"), new Apfloat("-1"));
            fail("Zeta of a -1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "zeta.ofSecondNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("(0,1.00000)"), new Apfloat("0"));
            fail("Zeta of i,0");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "zeta.ofSecondNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("(0,1)"), new Apfloat("-1"));
            fail("Zeta of i,-1");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "zeta.ofSecondNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("(0.5000,1.000e1000)"), new Apcomplex("(2.000,2.000)"));
            fail("Overflow");
        }
        catch (OverflowException oe)
        {
            // OK
            assertEquals("Localization key", "overflow", oe.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex("(0.5,1e100)"), new Apfloat(2.0));
            fail("Loss of precision");
        }
        catch (LossOfPrecisionException lope)
        {
            // OK
            assertEquals("Localization key", "imag.lossOfPrecision", lope.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.zeta(new Apcomplex(Apfloat.ZERO, new Apfloat(4)), new Apfloat(2));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "zeta.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometric0F1()
    {
        Apcomplex a = ApcomplexMath.hypergeometric0F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("1+2i, 3+4i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i value", new Apcomplex("(6.24111,0.025037)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric0F1(new Apcomplex(new Apfloat(2, 12, 36), new Apfloat(3, 12, 36)), new Apcomplex(new Apfloat(4, 12, 36), new Apfloat(5, 12, 36)));
        assertEquals("2+3i, 4+5i radix 36 precision", 12, a.precision());
        assertEquals("2+3i, 4+5i radix 36 radix", 36, a.radix());
        assertEquals("2+3i, 4+5i radix 36 value", new Apcomplex(new Apfloat("4.st9rbd539a0", 12, 36), new Apfloat("0.5oqplurvcpbq", 12, 36)), a, new Apfloat("0.00000000000g", 1, 36));

        // z = 0
        a = ApcomplexMath.hypergeometric0F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("0"));
        assertEquals("1+2i, 0 precision", 6, a.precision());
        assertEquals("1+2i, 0 value", new Apcomplex("1.00000"), a);

        // z very large
        a = ApcomplexMath.hypergeometric0F1(new Apcomplex("(1.00000000,2.00000000)"), new Apcomplex("(300000.000,400000.000)"));
        assertEquals("1+2i, 300000+400000i precision", 5, a.precision());
        assertEquals("1+2i, 300000+400000i value", new Apcomplex("(-8.57044753692138e546,-2.99860981175263e546)"), a, new Apfloat("5e542"));

        a = ApcomplexMath.hypergeometric0F1(new Apcomplex("0.500000"), new Apcomplex("(300000,400000)"));                                       // z very large and b-1/2 is nonpositive integer
        assertEquals("1+2i, 300000+400000i precision", 2, a.precision());
        assertEquals("1+2i, 300000+400000i value", new Apcomplex("(-6.006090911265257e548,-9.26014030743587e548)"), a, new Apfloat("5e547"));

        a = ApcomplexMath.hypergeometric0F1(new Apcomplex(new Apfloat(2, 28, 2), new Apfloat(3, 28, 2)), new Apcomplex(new Apfloat(400000, 28, 2), new Apfloat(500000, 28, 2)));
        assertEquals("2+3i, 400000+500000i radix 2 precision", 11, a.precision());
        assertEquals("2+3i, 400000+500000i radix 2 radix", 2, a.radix());
        assertEquals("2+3i, 400000+500000i radix 2 value", new Apcomplex(new Apfloat("-1.010001101001111001111001110001111100000011001011000e2063", 17, 2), new Apfloat("1.101111010100101100101110011000110100010110010000100e2062", 17, 2)), a, new Apfloat("1e2053", 1, 2));

        a = ApcomplexMath.hypergeometric0F1(new Apcomplex(new Apfloat(2, 27, 2), new Apfloat(3, 27, 2)), new Apcomplex(new Apfloat(-400000, 27, 2), new Apfloat(-500000, 27, 2)));
        assertEquals("2+3i, -400000-500000i radix 2 precision", 10, a.precision());
        assertEquals("2+3i, -400000-500000i radix 2 radix", 2, a.radix());
        assertEquals("2+3i, -400000-500000i radix 2 value", new Apcomplex(new Apfloat("1.011001011111100111e975", 17, 2), new Apfloat("-1.0111010000000101001e975", 17, 2)), a, new Apfloat("1e966", 1, 2));

        // Non converging cases
        try
        {
            ApcomplexMath.hypergeometric0F1(new Apcomplex("-42.00000"), new Apcomplex("(2.00000,3.00000)"));
            fail("-42, 2+3i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric0F1(new Apcomplex("0.00000"), new Apcomplex("0.00000"));
            fail("0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.hypergeometric0F1(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometric1F1()
    {
        Apcomplex a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 3+4i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i value", new Apcomplex("(-8.28601,-9.84438)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric1F1(new Apcomplex(new Apfloat(2, 13, 35), new Apfloat(3, 13, 35)), new Apcomplex(new Apfloat(4, 13, 35), new Apfloat(5, 13, 35)), new Apcomplex(new Apfloat(6, 13, 35), new Apfloat(7, 13, 35)));
        assertEquals("2+3i, 4+5i, 6+7i radix 35 precision", 13, a.precision());
        assertEquals("2+3i, 4+5i, 6+7i radix 35 radix", 35, a.radix());
        assertEquals("2+3i, 4+5i, 6+7i radix 35 value", new Apcomplex(new Apfloat("i.hqetnbmwn38j", 13, 35), new Apfloat("-18.bk1aevn10od1", 13, 35)), a, new Apfloat("0.00000000000f", 1, 35));

        // z = 0
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0"));
        assertEquals("1+2i, 3+4i, 0 precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 0 value", new Apcomplex("1.00000"), a);

        // z negative real part
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(-5.00000,-6.00000)"));
        assertEquals("1+2i, 3+4i, -5-6i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, -5-6i value", new Apcomplex("(-0.1555016,-0.2669975)"), a, new Apfloat("5e-6"));

        // z very large
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.0000000000,2.0000000000)"), new Apcomplex("(3.0000000000,4.0000000000)"), new Apcomplex("(500000.00000,600000.00000)"));
        assertEquals("1+2i, 3+4i, 500000+600000i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 500000+600000i value", new Apcomplex("(1.4855603302940e217136,1.1115533092224e217136)"), a, new Apfloat("5e217131"));

        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.0000000000,2.0000000000)"), new Apcomplex("(3.0000000000,2.0000000000)"), new Apcomplex("(500000.00000,600000.00000)"));
        assertEquals("1+2i, 3+2i, 500000+600000i precision", 6, a.precision());
        assertEquals("1+2i, 3+2i, 500000+600000i value", new Apcomplex("(1.8007619947265998435e217136,-1.337011417934778174e217135)"), a, new Apfloat("5e217131"));

        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(3.0000000,2.0000000)"), new Apcomplex("(1.0000000,2.0000000)"), new Apcomplex("(500.00000,600.00000)"));    // z very large and b - a nonpositive integer
        assertEquals("3+2i, 1+2i, 500+600i precision", 6, a.precision());
        assertEquals("3+2i, 1+2i, 500+600i value", new Apcomplex("(-1.34020e222,2.51189e221)"), a, new Apfloat("5e217"));

        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(3.0000000,2.0000000)"), new Apcomplex("(1.0000000,2.0000001)"), new Apcomplex("(500.00000,600.00000)"));    // z very large and b - a nonpositive near-integer
        assertEquals("3+2i, 1+2.0000001i, 500+600i precision", 6, a.precision());
        assertEquals("3+2i, 1+2.0000001i, 500+600i value", new Apcomplex("(-1.34020e222,2.51190e221)"), a, new Apfloat("5e217"));

        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.0000000,2.0000000)"), new Apcomplex("(2.0000000,2.0000000)"), new Apcomplex("(500.00000,600.00000)"));    // z very large and a - b + 1 nonpositive integer
        assertEquals("1+2i, 2+2i, 500+600i precision", 6, a.precision());
        assertEquals("1+2i, 2+2i, 500+600i value", new Apcomplex("(-3.94194e214,-7.38748e213)"), a, new Apfloat("5e209"));

        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("1.0000000"), new Apcomplex("(2.0000000,3.0000000)"), new Apcomplex("(500.00000,600.00000)"));                // z very large and 1 - a nonpositive integer
        assertEquals("1, 2+3i, 500+600i precision", 6, a.precision());
        assertEquals("1, 2+3i, 500+600i value", new Apcomplex("(-2.97414e214,-7.59031e213)"), a, new Apfloat("5e209"));

        // z pure imaginary
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(0,14.0000)"));
        assertEquals("1+2i, 3+4i, 14i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 14i value", new Apcomplex("(-0.0831361,-0.0482419)"), a, new Apfloat("5e-7"));

        // Polynomial cases
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("0"), new Apcomplex("1.0"), new Apcomplex("1.0"));
        assertEquals("0, 1, 1 precision", 2, a.precision());
        assertEquals("0, 1, 1 value", new Apcomplex("1.0"), a);
 
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("-42.0000000"), new Apcomplex("(3.0000000,4.0000000)"), new Apcomplex("(5.0000000,6.0000000)"));
        assertEquals("-42, 3+4i, 5+6i precision", 2, a.precision());
        assertEquals("-42, 3+4i, 5+6i value", new Apcomplex("(-56.0081,-31.8473)"), a, new Apfloat("5e0"));

        // Reduction to 0F0
        a = ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 1+2i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 1+2i, 5+6i value", new Apcomplex("(142.502,-41.4689)"), a, new Apfloat("5e-4"));
 
        // Non converging cases
        try
        {
            ApcomplexMath.hypergeometric1F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
            fail("1+2i, 0, 5+6i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric1F1(new Apcomplex("1.00000"), new Apcomplex("0"), new Apcomplex("0"));
            fail("1, 0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is indeterminate
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.hypergeometric1F1(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)), new Apcomplex(new Apfloat(7), new Apfloat(8)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometric2F1()
    {
        // T0
        Apcomplex a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("0.100000"));
        assertEquals("1, 2.2, 3.3, 0.1 precision", 6, a.precision());
        assertEquals("1, 2.2, 3.3, 0.1 value", new Apcomplex("1.0720565"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("2.20000"), new Apcomplex("0.000000000100000"), new Apcomplex("0.100000"));
        assertEquals("1.1, 2.2, 0.0000000001, 0.1 precision", 6, a.precision());
        assertEquals("1.1, 2.2, 0.0000000001, 0.1 value", new Apcomplex("3.44671e9"), a, new Apfloat("5e4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("0.0000100000"), new Apcomplex("2.20000"), new Apcomplex("0.000000000100000"), new Apcomplex("0.100000"));
        assertEquals("0.00001, 2.2, 0.0000000001, 0.1 precision", 6, a.precision());
        assertEquals("0.00001, 2.2, 0.0000000001, 0.1 value", new Apcomplex("26086.9"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.00001"), new Apcomplex("2.20000"), new Apcomplex("0.000000000100000"), new Apcomplex("0.100000"));
        assertEquals("-1.00001, 2.2, 0.0000000001, 0.1 precision", 6, a.precision());
        assertEquals("-1.00001, 2.2, 0.0000000001, 0.1 value", new Apcomplex("-2.20002e9"), a, new Apfloat("5e4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.00001"), new Apcomplex("2.20000"), new Apcomplex("-3.00001"), new Apcomplex("0.100000"));
        assertEquals("-1.00001, 2.2, -3.00001, 0.1 precision", 6, a.precision());
        assertEquals("-1.00001, 2.2, -3.00001, 0.1 value", new Apcomplex("1.07365"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-3.00001"), new Apcomplex("2.20000"), new Apcomplex("-1.00001"), new Apcomplex("0.100000"));
        assertEquals("-3.00001, 2.2, -1.00001, 0.1 precision", 5, a.precision());
        assertEquals("-3.00001, 2.2, -1.00001, 0.1 value", new Apcomplex("18164.8"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(0.100000,0.100000)"));
        assertEquals("1+2i, 3+4i, 5+6i, 0.1+0.1i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0.1+0.1i value", new Apcomplex("(0.901921,0.175485)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 6, 7), new Apfloat(2, 6, 7)), new Apcomplex(new Apfloat(3, 6, 7), new Apfloat(4, 6, 7)), new Apcomplex(new Apfloat(5, 6, 7), new Apfloat(6, 6, 7)), new Apcomplex(new Apfloat("0.1", 6, 7), new Apfloat("0.1", 6, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 0.1+0.1i radix 7 precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0.1+0.1i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 0.1+0.1i radix 7 value", new Apcomplex(new Apfloat("0.5631550", 7, 7), new Apfloat("0.1452024", 7, 7)), a, new Apfloat("3e-6", 1, 7));

        // T1
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("-0.500000"));
        assertEquals("1, 2.2, 3.3, -0.5 precision", 6, a.precision());
        assertEquals("1, 2.2, 3.3, -0.5 value", new Apcomplex("0.755818"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("4.30000"), new Apcomplex("5.30000"), new Apcomplex("3.30000"), new Apcomplex("-0.500000"));  // c-a is integer and <= 0 and (c-b is not integer or c-b > 0 or c-a >= c-b)
        assertEquals("4.3, 5.3, 3.3, -0.5 precision", 6, a.precision());
        assertEquals("4.3, 5.3, 3.3, -0.5 value", new Apcomplex("0.054179995"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(0,1.00000)"));
        assertEquals("1+2i, 3+4i, 5+6i, i precision", 5, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, i value", new Apcomplex("(0.277926,0.0318455)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 6, 7), new Apfloat(2, 6, 7)), new Apcomplex(new Apfloat(3, 6, 7), new Apfloat(4, 6, 7)), new Apcomplex(new Apfloat(5, 6, 7), new Apfloat(6, 6, 7)), new Apcomplex(new Apfloat(0, 6, 7), new Apfloat(1, 6, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, i radix 7 precision", 5, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, i radix 7 value", new Apcomplex(new Apfloat("0.1642205", 7, 7), new Apfloat("0.0136314", 7, 7)), a, new Apfloat("3e-6", 1, 7));

        // T2
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));
        assertEquals("1, 2.2, 3.3, 5 precision", 5, a.precision());
        assertEquals("1, 2.2, 3.3, 5 value", new Apcomplex("(-0.527130,-0.228019)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.000000"), new Apcomplex("1.000000"), new Apcomplex("3.300000"), new Apcomplex("5.000000"));    // a = b
        assertEquals("1, 1, 3.3, 5 precision", 6, a.precision());
        assertEquals("1, 1, 3.3, 5 value", new Apcomplex("(0.041932,-1.081246)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("1.00001"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a = b almost
        assertEquals("1, 1.00001, 3.3, 5 precision", 6, a.precision());
        assertEquals("1, 1.00001, 3.3, 5 value", new Apcomplex("(0.041918,-1.081244)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("1.0000000001"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a = b very almost, and rounded is equal
        assertEquals("1, 1.0000000001, 3.3, 5 precision", 6, a.precision());
        assertEquals("1, 1.0000000001, 3.3, 5 value", new Apcomplex("(0.041932,-1.081246)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.000000"), new Apcomplex("2.000000"), new Apcomplex("3.300000"), new Apcomplex("5.000000"));    // a - b is some integer
        assertEquals("1, 2, 3.3, 5 precision", 6, a.precision());
        assertEquals("1, 2, 3.3, 5 value", new Apcomplex("(-0.561372,-0.351405)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.00001"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a - b is almost integer
        assertEquals("1, 2.00001, 3.3, 5 precision", 6, a.precision());
        assertEquals("1, 2.00001, 3.3, 5 value", new Apcomplex("(-0.561371,-0.351398)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("0.0000100000"), new Apcomplex("1.00000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a - b is almost integer, a almost zero
        assertEquals("0.00001, 1, 3.3, 5 precision", 6, a.precision());
        assertEquals("0.00001, 1, 3.3, 5 value", new Apcomplex("(1.00001,-0.0000188043)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("0.0000000000100000"), new Apcomplex("1.00000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a - b is very almost integer, and rounded integer, a almost zero
        assertEquals("0.00000000001, 1, 3.3, 5 precision", 6, a.precision());
        assertEquals("0.00000000001, 1, 3.3, 5 value", new Apcomplex("(1.00001,-0.0000188043)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("0.0000100000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a - b is almost integer, b almost zero
        assertEquals("1, 0.00001, 3.3, 5 precision", 6, a.precision());
        assertEquals("1, 0.00001, 3.3, 5 value", new Apcomplex("(1.00001,-0.0000188043)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("0.000000000100000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a - b is very almost integer, and rounded integer, b almost zero
        assertEquals("1, 0.0000000001, 3.3, 5 precision", 5, a.precision());
        assertEquals("1, 0.0000000001, 3.3, 5 value", new Apcomplex("(1.00001,-0.0000188043)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000000"), new Apcomplex("23456.000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("5.0000000000000000000"));    // a - b is very large integer
        assertEquals("12345, 23456, 3.3, 5 precision", 17, a.precision());
        assertEquals("12345, 23456, 3.3, 5 value", new Apcomplex("(5.2099702663731078027e-4961,7.1709088808283296782e-4961)"), a, new Apfloat("5e-4977"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000001"), new Apcomplex("23456.000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("5.0000000000000000000"));    // a - b is very large almost integer
        assertEquals("12345.000000000000001, 23456, 3.3, 5 precision", 17, a.precision());
        assertEquals("12345.000000000000001, 23456, 3.3, 5 value", new Apcomplex("(5.2099702663731332954e-4961,7.1709088808283173911e-4961)"), a, new Apfloat("5e-4977"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000000"), new Apcomplex("2.0000000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("5.0000000000000000000"));    // a - b is very large integer but different scales
        assertEquals("12345, 2, 3.3, 5 precision", 16, a.precision());
        assertEquals("12345, 2, 3.3, 5 value", new Apcomplex("7.849803042660721e-10"), a, new Apfloat("5e-25"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000000"), new Apcomplex("2.0000000000000000001"), new Apcomplex("3.3000000000000000000"), new Apcomplex("5.0000000000000000000"));    // a - b is very large almost integer but different scales
        assertEquals("12345, 2.0000000000000000001, 3.3, 5 precision", 17, a.precision());
        assertEquals("12345, 2.0000000000000000001, 3.3, 5 value", new Apcomplex("(7.8498030426607211909e-10,-2.4660883570949728023e-28)"), a, new Apfloat("5e-44"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("4.30000"), new Apcomplex("1.00000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // c - a is negative integer
        assertEquals("4.3, 1, 3.3, 5 precision", 5, a.precision());
        assertEquals("4.3, 1, 3.3, 5 value", new Apcomplex("-0.155303"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("1.20000"), new Apcomplex("5.00000"));    // c - b is negative integer
        assertEquals("1, 2.2, 1.2, 5 precision", 5, a.precision());
        assertEquals("1, 2.2, 1.2, 5 value", new Apcomplex("0.0104167"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(5.00000,5.00000)"));
        assertEquals("1+2i, 3+4i, 5+6i, 5+5i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 5+5i value", new Apcomplex("(0.00471924,-0.00269112)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 6, 7), new Apfloat(2, 6, 7)), new Apcomplex(new Apfloat(3, 6, 7), new Apfloat(4, 6, 7)), new Apcomplex(new Apfloat(5, 6, 7), new Apfloat(6, 6, 7)), new Apcomplex(new Apfloat(5, 6, 7), new Apfloat(5, 6, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 5+5i radix 7 precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 5+5i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 5+5i radix 7 value", new Apcomplex(new Apfloat("0.001422133", 7, 7), new Apfloat("-0.0006314153", 7, 7)), a, new Apfloat("3e-8", 1, 7));

        // T3
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("-5.00000"));
        assertEquals("1, 2.2, 3.3, -5 precision", 5, a.precision());
        assertEquals("1, 2.2, 3.3, -5 value", new Apcomplex("0.254205"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("1.00000"), new Apcomplex("3.30000"), new Apcomplex("-5.00000"));    // a = b
        assertEquals("1, 1, 3.3, -5 precision", 5, a.precision());
        assertEquals("1, 1, 3.3, -5 value", new Apcomplex("0.482978"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("1.00001"), new Apcomplex("3.30000"), new Apcomplex("-5.00000"));    // a = b almost
        assertEquals("1, 1.00001, 3.3, -5 precision", 5, a.precision());
        assertEquals("1, 1.00001, 3.3, -5 value", new Apcomplex("0.482975"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.00000"), new Apcomplex("3.30000"), new Apcomplex("-5.00000"));    // a - b is some integer
        assertEquals("1, 2, 3.3, -5 precision", 6, a.precision());
        assertEquals("1, 2, 3.3, -5 value", new Apcomplex("0.278688"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.00001"), new Apcomplex("3.30000"), new Apcomplex("-5.00000"));    // a - b is almost integer
        assertEquals("1, 2.00001, 3.3, -5 precision", 6, a.precision());
        assertEquals("1, 2.00001, 3.3, -5 value", new Apcomplex("0.278687"), a, new Apfloat("5e-6"));

        /* Extreme instability
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000000"), new Apcomplex("23456.000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("-5.0000000000000000000"));    // a - b is very large integer
        assertEquals("12345, 23456, 3.3, -5 precision", 16, a.precision());
        assertEquals("12345, 23456, 3.3, -5 value", new Apcomplex("2.113637302878074e-9709"), a, new Apfloat("5e-9724")); // Could not be verified

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000001"), new Apcomplex("23456.000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("-5.0000000000000000000"));    // a - b is very large almost integer
        assertEquals("12345.000000000000001, 23456, 3.3, -5 precision", 16, a.precision());
        assertEquals("12345.000000000000001, 23456, 3.3, -5 value", new Apcomplex("7.926014599973323e-9710"), a, new Apfloat("5e-9725")); // Could not be verified
        */

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("123.00000000000000000"), new Apcomplex("234.00000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("-5.0000000000000000000"));    // a - b is very large integer
        assertEquals("123, 234, 3.3, -5 precision", 19, a.precision());
        assertEquals("123, 234, 3.3, -5 value", new Apcomplex("-1.6244271268683561270e-145"), a, new Apfloat("5e-163"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("123.00000000000000001"), new Apcomplex("234.00000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("-5.0000000000000000000"));    // a - b is very large almost integer
        assertEquals("123.00000000000000001, 234, 3.3, -5 precision", 19, a.precision());
        assertEquals("123.00000000000000001, 234, 3.3, -5 value", new Apcomplex("-1.6244271268683561596e-145"), a, new Apfloat("5e-163"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000000"), new Apcomplex("2.0000000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("-5.0000000000000000000"));    // a - b is very large integer but different scales
        assertEquals("12345, 2, 3.3, -5 precision", 16, a.precision());
        assertEquals("12345, 2, 3.3, -5 value", new Apcomplex("7.849650398485188e-10"), a, new Apfloat("5e-25"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.000000000000000"), new Apcomplex("2.0000000000000000001"), new Apcomplex("3.3000000000000000000"), new Apcomplex("-5.0000000000000000000"));    // a - b is very large almost integer but different scales
        assertEquals("12345, 2.0000000000000000001, 3.3, -5 precision", 17, a.precision());
        assertEquals("12345, 2.0000000000000000001, 3.3, -5 value", new Apcomplex("7.8496503984851883023e-10"), a, new Apfloat("5e-26"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(-5.00000,-5.00000)"));
        assertEquals("1+2i, 3+4i, 5+6i, -5-5i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, -5-5i value", new Apcomplex("(-0.633637,0.498949)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 6, 7), new Apfloat(2, 6, 7)), new Apcomplex(new Apfloat(3, 6, 7), new Apfloat(4, 6, 7)), new Apcomplex(new Apfloat(5, 6, 7), new Apfloat(6, 6, 7)), new Apcomplex(new Apfloat(-5, 6, 7), new Apfloat(-5, 6, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, -5-5i radix 7 precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, -5-5i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, -5-5i radix 7 value", new Apcomplex(new Apfloat("-0.4302235", 7, 7), new Apfloat("0.33306556", 7, 7)), a, new Apfloat("3e-6", 1, 7));

        // T4
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));
        assertEquals("1, 2.2, 3.3, 0.9 precision", 4, a.precision());
        assertEquals("1, 2.2, 3.3, 0.9 value", new Apcomplex("3.38469"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));   // c = a + b
        assertEquals("1.1, 2.2, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.1, 2.2, 3.3, 0.9 value", new Apcomplex("3.89134"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("2.20001"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));   // c = a + b almost
        assertEquals("1.1, 2.20001, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.1, 2.20001, 3.3, 0.9 value", new Apcomplex("3.89138"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("2.2000000001"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));    // c = a + b very almost, and rounded is equal
        assertEquals("1.1, 2.2000000001, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.1, 2.2000000001, 3.3, 0.9 value", new Apcomplex("3.89134"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("3.20000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));   // c - a - b is some integer
        assertEquals("1.1, 3.2, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.1, 3.2, 3.3, 0.9 value", new Apcomplex("11.1353"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("3.20001"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));   // c - a - b is almost integer
        assertEquals("1.1, 3.20001, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.1, 3.20001, 3.3, 0.9 value", new Apcomplex("11.1354"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("0.0000100000"), new Apcomplex("1.30000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));    // c - a - b is almost integer, a almost zero
        assertEquals("0.00001, 1.3, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("0.00001, 1.3, 3.3, 0.9 value", new Apcomplex("1.00001"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("0.0000000000100000"), new Apcomplex("1.30000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));    // c - a - b is very almost integer, and rounded integer, a almost zero
        assertEquals("0.00000000001, 1.3, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("0.00000000001, 1.3, 3.3, 0.9 value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.30000"), new Apcomplex("0.0000100000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));    // c - a - b is almost integer, b almost zero
        assertEquals("1.3, 0.00001, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.3, 0.00001, 3.3, 0.9 value", new Apcomplex("1.00001"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.30000"), new Apcomplex("0.000000000100000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));    // c - a - b is very almost integer, and rounded integer, b almost zero
        assertEquals("1.3, 0.0000000001, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("1.3, 0.0000000001, 3.3, 0.9 value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("-1.10000"), new Apcomplex("0.0000100000"), new Apcomplex("0.900000"));    // c - a - b is almost integer, c almost zero
        assertEquals("1.1, -1.1, 0.00001, 0.9 precision", 6, a.precision());
        assertEquals("1.1, -1.1, 0.00001, 0.9 value", new Apcomplex("-84213.6"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("-1.10000"), new Apcomplex("0.000000000100000"), new Apcomplex("0.900000"));    // c - a - b is very almost integer, and rounded integer, c almost zero
        assertEquals("1.1, -1.1, 0.0000000001, 0.9 precision", 5, a.precision());
        assertEquals("1.1, -1.1, 0.0000000001, 0.9 value", new Apcomplex("-8.42142e9"), a, new Apfloat("5e4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("0.0000000000100000"), new Apcomplex("-0.0000000000100000"), new Apcomplex("3.00000"), new Apcomplex("0.900000"));    // c - a - b is very almost integer, and rounded integer, a and b both almost zero
        assertEquals("0.00000000001, -0.00000000001, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("0.00000000001, -0.00000000001, 3.3, 0.9 value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));
        
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000000"), new Apcomplex("23456.200000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("0.90000000000000000000"));   // c - a - b is very large integer
        assertEquals("12345.1, 23456.2, 3.3, 0.9 precision", 15, a.precision());
        assertEquals("12345.1, 23456.2, 3.3, 0.9 value", new Apcomplex("2.15122213624475e45435"), a, new Apfloat("5e45421"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000000"), new Apcomplex("23456.200000000000000"), new Apcomplex("3.3000000000000000001"), new Apcomplex("0.90000000000000000000"));   // c - a - b is very large almost integer
        assertEquals("12345.1, 23456.2, 3.3000000000000000001, 0.9 precision", 17, a.precision());
        assertEquals("12345.1, 23456.2, 3.3000000000000000001, 0.9 value", new Apcomplex("2.1512221362447472151e45435"), a, new Apfloat("5e45419"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000000"), new Apcomplex("2.2000000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("0.90000000000000000000"));   // c - a - b is very large integer but different scales
        assertEquals("12345.1, 2.2, 3.3, 0.9 precision", 16, a.precision());
        assertEquals("12345.1, 2.2, 3.3, 0.9 value", new Apcomplex("8.6359944646509259e12339"), a, new Apfloat("5e12324"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000001"), new Apcomplex("2.2000000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("0.90000000000000000000"));   // c - a - b is very large almost integer but different scales
        assertEquals("12345.1, 2.2, 3.3, 0.9 precision", 16, a.precision());
        assertEquals("12345.1, 2.2, 3.3, 0.9 value", new Apcomplex("8.635994464650945e12339"), a, new Apfloat("5e12324"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("4.30000"), new Apcomplex("1.00000"), new Apcomplex("3.30000"), new Apcomplex("0.900000"));    // c - a is negative integer
        assertEquals("4.3, 1, 3.3, 0.9 precision", 6, a.precision());
        assertEquals("4.3, 1, 3.3, 0.9 value", new Apcomplex("37.2727"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(0.800000,-0.200000)"));
        assertEquals("1+2i, 3+4i, 5+6i, 0.8-0.2i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0.8-0.2i value", new Apcomplex("(1.33313,3.65726)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 11, 7), new Apfloat(2, 11, 7)), new Apcomplex(new Apfloat(3, 11, 7), new Apfloat(4, 11, 7)), new Apcomplex(new Apfloat(5, 11, 7), new Apfloat(6, 11, 7)), new Apcomplex(new Apfloat("0.6", 11, 7), new Apfloat("0.2", 11, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 0.6+0.2i radix 7 precision", 11, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0.6+0.2i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 0.6+0.2i radix 7 value", new Apcomplex(new Apfloat("-0.13460121301", 11, 7), new Apfloat("0.42563562524", 11, 7)), a, new Apfloat("3e-11", 1, 7));

        // T5
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("1.10000"));
        assertEquals("1, 2.2, 3.3, 1.1 precision", 4, a.precision());
        assertEquals("1, 2.2, 3.3, 1.1 value", new Apcomplex("(2.412471,-5.13090)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("1.10000"));   // c = a + b
        assertEquals("1.1, 2.2, 3.3, 1.1 precision", 5, a.precision());
        assertEquals("1.1, 2.2, 3.3, 1.1 value", new Apcomplex("(1.76883,-6.38157)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("2.20001"), new Apcomplex("3.30000"), new Apcomplex("1.10000"));   // c = a + b almost
        assertEquals("1.1, 2.20001, 3.3, 1.1 precision", 5, a.precision());
        assertEquals("1.1, 2.20001, 3.3, 1.1 value", new Apcomplex("(1.76876,-6.38164)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.100000"), new Apcomplex("3.200000"), new Apcomplex("3.300000"), new Apcomplex("1.100000"));    // c - a - b is some integer
        assertEquals("1.1, 3.2, 3.3, 1.1 precision", 6, a.precision());
        assertEquals("1.1, 3.2, 3.3, 1.1 value", new Apcomplex("(-11.9673,0.68104)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.10000"), new Apcomplex("3.20001"), new Apcomplex("3.30000"), new Apcomplex("1.10000"));   // c - a - b is almost integer
        assertEquals("1.1, 3.20001, 3.3, 1.1 precision", 6, a.precision());
        assertEquals("1.1, 3.20001, 3.3, 1.1 value", new Apcomplex("(-11.9673,0.681342)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000000"), new Apcomplex("23456.200000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("1.1000000000000000000"));   // c - a - b is very large integer
        assertEquals("12345.1, 23456.2, 3.3, 1.1 precision", 15, a.precision());
        assertEquals("12345.1, 23456.2, 3.3, 1.1 value", new Apcomplex("1.56515678564160e46139"), a, new Apfloat("5e46124"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000000"), new Apcomplex("23456.200000000000000"), new Apcomplex("3.3000000000000000001"), new Apcomplex("1.1000000000000000000"));   // c - a - b is very large almost integer
        assertEquals("12345.1, 23456.2, 3.3000000000000000001, 1.1 precision", 17, a.precision());
        assertEquals("12345.1, 23456.2, 3.3000000000000000001, 1.1 value", new Apcomplex("(1.5651567856416026415e46139,4.9170850594878736391e46120)"), a, new Apfloat("5e46123"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000000"), new Apcomplex("2.2000000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("1.1000000000000000000"));   // c - a - b is very large integer but different scales
        assertEquals("12345.1, 2.2, 3.3, 1.1 precision", 16, a.precision());
        assertEquals("12345.1, 2.2, 3.3, 1.1 value", new Apcomplex("6.925586290556692e12339"), a, new Apfloat("5e12324"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("12345.100000000000001"), new Apcomplex("2.2000000000000000000"), new Apcomplex("3.3000000000000000000"), new Apcomplex("1.1000000000000000000"));   // c - a - b is very large almost integer but different scales
        assertEquals("12345.1, 2.2, 3.3, 1.1 precision", 16, a.precision());
        assertEquals("12345.1, 2.2, 3.3, 1.1 value", new Apcomplex("(6.92558629055670804609685408962018969630924e12339,-2.175737101221514124404378847e12325)"), a, new Apfloat("5e12310"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(2.20000,-1.10000)"));
        assertEquals("1+2i, 3+4i, 5+6i, 2.2-1.1i precision", 3, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 2.2-1.1i value", new Apcomplex("(5.94238,-45.6929)"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 15, 7), new Apfloat(2, 15, 7)), new Apcomplex(new Apfloat(3, 15, 7), new Apfloat(4, 15, 7)), new Apcomplex(new Apfloat(5, 15, 7), new Apfloat(6, 15, 7)), new Apcomplex(new Apfloat("2.2", 15, 7), new Apfloat("1.1", 15, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 2.2+1.1i radix 7 precision", 15, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 2.2+1.1i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 2.2+1.1i radix 7 value", new Apcomplex(new Apfloat("-0.00212125415466401", 15, 7), new Apfloat("0.01231461626540454", 15, 7)), a, new Apfloat("3e-16", 1, 7));

        // AA
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("(0.500000,0.866025)"));
        assertEquals("1, 2.2, 3.3, 0.500000+0.866025i precision", 6, a.precision());
        assertEquals("1, 2.2, 3.3, 0.500000+0.866025i value", new Apcomplex("(0.817034,0.688205)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("-2.00001"), new Apcomplex("(0.500000,0.900000)"));    // c close to even negative integer
        assertEquals("1, 2.2, -2.00001, 0.500000+0.9i precision", 6, a.precision());
        assertEquals("1, 2.2, -2.00001, 0.500000+0.9i value", new Apcomplex("(1058370,-895866)"), a, new Apfloat("5e1"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("(0,0.0000100000)"), new Apcomplex("(0.500000,0.900000)"));    // c small and pure imaginary
        assertEquals("1, 2.2, 0.00001i, 0.500000+0.9i precision", 6, a.precision());
        assertEquals("1, 2.2, 0.00001i, 0.500000+0.9i value", new Apcomplex("(-200190,50025)"), a, new Apfloat("5e0"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(0.600000,-0.700000)"));
        assertEquals("1+2i, 3+4i, 5+6i, 0.6-0.7i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0.6-0.7i value", new Apcomplex("(4.583319,-0.542426)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 17, 7), new Apfloat(2, 17, 7)), new Apcomplex(new Apfloat(3, 17, 7), new Apfloat(4, 17, 7)), new Apcomplex(new Apfloat(5, 17, 7), new Apfloat(6, 17, 7)), new Apcomplex(new Apfloat("0.3", 17, 7), new Apfloat("0.6", 17, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 0.3+0.6i radix 7 precision", 17, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0.3+0.6i radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 0.3+0.6i radix 7 value", new Apcomplex(new Apfloat("0.140136606425645266", 17, 7), new Apfloat("0.11630632042113610", 17, 7)), a, new Apfloat("3e-17", 1, 7));

        // z = 0
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(2,3)"), new Apcomplex("(4,5)"), new Apcomplex("(6,7)"), new Apcomplex("0"));
        assertEquals("(2,3), (4,5), (6,7), 0 precision", 1, a.precision());
        assertEquals("(2,3), (4,5), (6,7), 0 value", new Apcomplex("1"), a);

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 15, 7), new Apfloat(2, 15, 7)), new Apcomplex(new Apfloat(3, 15, 7), new Apfloat(4, 15, 7)), new Apcomplex(new Apfloat(5, 15, 7), new Apfloat(6, 15, 7)), new Apcomplex(new Apfloat(0, 15, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 0 radix 7 precision", 15, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 0 radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 0 radix 7 value", new Apcomplex(new Apfloat("1", 15, 7)), a);

        // z = 1
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.10000"), new Apcomplex("4.40000"), new Apcomplex("3.40000"), new Apcomplex("1.00000"));   // re(a + b - c) < 0
        assertEquals("-1.1, 4.4, 3.4, 1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1.1, 4.4, 3.4, 1 value", new Apcomplex("0"), a);

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("(-1.10000)"), new Apcomplex("(4.40000)"), new Apcomplex("(3.40001)"), new Apcomplex("1.00000")); // re(a + b - c) < 0
        assertEquals("-1.1, 4.4, 3.40001, 1 precision", 6, a.precision());
        assertEquals("-1.1, 4.4, 3.40001, 1 value", new Apcomplex("-0.0000243804"), a, new Apfloat("5e-10"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1, 15, 7), new Apfloat(2, 15, 7)), new Apcomplex(new Apfloat(3, 15, 7), new Apfloat(4, 15, 7)), new Apcomplex(new Apfloat(5, 15, 7), new Apfloat(6, 15, 7)), new Apcomplex(new Apfloat(1, 15, 7)));
        assertEquals("1+2i, 3+4i, 5+6i, 1 radix 7 precision", 15, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i, 1 radix 7 radix", 7, a.radix());
        assertEquals("1+2i, 3+4i, 5+6i, 1 radix 7 value", new Apcomplex(new Apfloat("-3.02122533664322", 15, 7), new Apfloat("-0.450501042623411", 15, 7)), a, new Apfloat("3e-15", 1, 7));

        // Polynomial cases
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("0.100000"));
        assertEquals("-1, 2.2, 3.3, 0.1 precision", 6, a.precision());
        assertEquals("-1, 2.2, 3.3, 0.1 value", new Apcomplex("0.933333"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.00000"), new Apcomplex("2.20000"), new Apcomplex("-2.00000"), new Apcomplex("0.100000"));
        assertEquals("-1, 2.2, -2, 0.1 precision", 6, a.precision());
        assertEquals("-1, 2.2, -2, 0.1 value", new Apcomplex("1.110006"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.00000"), new Apcomplex("2.20000"), new Apcomplex("-2.00000"), new Apcomplex("1.10000"));
        assertEquals("-1, 2.2, -2, 1.1 precision", 6, a.precision());
        assertEquals("-1, 2.2, -2, 1.1 value", new Apcomplex("2.21000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-123456"), new Apcomplex("-234567"), new Apcomplex("3.30000"), new Apcomplex("1.23456"));
        assertEquals("-123456, -234567, 3.3, 1.23456 precision", 2, a.precision());
        assertEquals("-123456, -234567, 3.3, 1.23456 value", new Apcomplex("6.43901e107725"), a, new Apfloat("5e107724"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-2.00000"), new Apcomplex("2.20000"), new Apcomplex("-2.00000"), new Apcomplex("5.00000"));
        assertEquals("-2, 2.2, -2, 5 precision", 6, a.precision());
        assertEquals("-2, 2.2, -2, 5 value", new Apcomplex("100.000"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-1.00000"), new Apcomplex("2.20000"), new Apcomplex("-2.00000"), new Apcomplex("5.00000"));
        assertEquals("-1, 2.2, -2, 5 precision", 6, a.precision());
        assertEquals("-1, 2.2, -2, 5 value", new Apcomplex("6.50000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("-3.00000"), new Apcomplex("-1.00000"), new Apcomplex("-2.00000"), new Apcomplex("1.00000"));
        assertEquals("-3, -1, -2, 1 precision", 6, a.precision());
        assertEquals("-3, -1, -2, 1 value", new Apfloat("-0.500000"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apfloat(-1, 15, 7), new Apcomplex(new Apfloat(3, 15, 7), new Apfloat(4, 15, 7)), new Apcomplex(new Apfloat(5, 15, 7), new Apfloat(6, 15, 7)), new Apcomplex(new Apfloat(1, 15, 7), new Apfloat(2, 15, 7)));
        assertEquals("-1, 3+4i, 5+6i, 1+2i radix 7 precision", 15, a.precision());
        assertEquals("-1, 3+4i, 5+6i, 1+2i radix 7 radix", 7, a.radix());
        assertEquals("-1, 3+4i, 5+6i, 1+2i radix 7 value", new Apcomplex(new Apfloat("0.266124322031330", 15, 7), new Apfloat("-1.211556525164406", 15, 7)), a, new Apfloat("3e-15", 1, 7));

        // Reduction to 1F0
        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("3.30000"), new Apcomplex("1.00000"), new Apcomplex("3.30000"), new Apcomplex("5.00000"));    // a = c
        assertEquals("3.3, 1, 3.3, 5 precision", 6, a.precision());
        assertEquals("3.3, 1, 3.3, 5 value", new Apcomplex("-0.250000"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("2.20000"), new Apcomplex("5.00000"));    // b = c
        assertEquals("1, 2.2, 2.2, 5 precision", 6, a.precision());
        assertEquals("1, 2.2, 2.2, 5 value", new Apcomplex("-0.250000"), a, new Apfloat("5e-6"));

        // Non converging cases
        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex("-3.00000"), new Apcomplex("2.20000"), new Apcomplex("-2.00000"), new Apcomplex("5.00000"));
            fail("-3, 2.2, -2, 5 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex("(-1.10000)"), new Apcomplex("(4.40000)"), new Apcomplex("(3.30000)"), new Apcomplex("1.00000")); // re(a + b - c) = 0
            fail("-1.1, 4.4, 3.3, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex("(-1.10000)"), new Apcomplex("(4.40001)"), new Apcomplex("(3.30000)"), new Apcomplex("1.00000")); // re(a + b - c) > 0
            fail("-1.1, 4.40001, 3.3, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex("(1.00000)"), new Apcomplex("(2.00000)"), new Apcomplex("(1.00000)"), new Apcomplex("1.00000")); // re(a + b - c) > 0 and reduction to 1F0 
            fail("1, 2, 1, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToNegative", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex("1.00000"), new Apcomplex("2.00000"), new Apcomplex("0"), new Apcomplex("0"));
            fail("1, 2, 0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(-3)), new Apcomplex(new Apfloat(-2)), new Apcomplex(new Apfloat(-1)), new Apcomplex(new Apfloat(1)));
            fail("-3, -1, -2, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, division by zero
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.hypergeometric2F1(new Apcomplex(new Apfloat(1), new Apfloat(2)), new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)), new Apcomplex(new Apfloat(7), new Apfloat(8)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometric0F1Regularized()
    {
        Apcomplex a = ApcomplexMath.hypergeometric0F1Regularized(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("1+2i, 3+4i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i value", new Apcomplex("(40.4203,-5.10508)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometric0F1Regularized(new Apcomplex("(-1.00000,-2.00000)"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("-1-2i, 3+4i precision", 6, a.precision());
        assertEquals("-1-2i, 3+4i value", new Apcomplex("(-16.3946,-1.65106)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric0F1Regularized(new Apcomplex("-2.000000"), new Apcomplex("(3.000000,4.000000)"));
        assertEquals("-2, 3+4i precision", 6, a.precision());
        assertEquals("-2, 3+4i value", new Apcomplex("(-39.0633,-21.8202)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric0F1Regularized(new Apcomplex("-0.9999999999998"), new Apcomplex("(3.000000000000,4.000000000000)"));
        assertEquals("-0.9999999999998, 3+4i precision", 12, a.precision());
        assertEquals("-0.9999999999998, 3+4i value", new Apcomplex("(-33.49668360386,7.4495303552)"), a, new Apfloat("5e-11"));

        try
        {
            ApcomplexMath.hypergeometric0F1Regularized(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometric1F1Regularized()
    {
        Apcomplex a = ApcomplexMath.hypergeometric1F1Regularized(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 3+4i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i value", new Apcomplex("(55.548,-49.704)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.hypergeometric1F1Regularized(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("-3.000000"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("1+2i, -3, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, -3, 5+6i value", new Apcomplex("(-153449,880022)"), a, new Apfloat("5e1"));

        try
        {
            ApcomplexMath.hypergeometric1F1Regularized(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)), new Apcomplex(new Apfloat(7), new Apfloat(8)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometric2F1Regularized()
    {
        Apcomplex a = ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("3.30000"), new Apcomplex("0.100000"));
        assertEquals("1, 2.2, 3.3, 0.1 precision", 6, a.precision());
        assertEquals("1, 2.2, 3.3, 0.1 value", new Apcomplex("0.399509"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("-3.00000"), new Apcomplex("0.100000"));
        assertEquals("1, 2.2, -3, 0.1 precision", 6, a.precision());
        assertEquals("1, 2.2, -3, 0.1 value", new Apcomplex("0.0295476"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex("1.00000"), new Apcomplex("2.20000"), new Apcomplex("0"), new Apcomplex("0.100000"));
        assertEquals("1, 2.2, 0, 0.1 precision", 6, a.precision());
        assertEquals("1, 2.2, 0, 0.1 value", new Apcomplex("0.308210"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex("1.00000"), new Apcomplex("2.00000"), new Apcomplex("-3.00000"), new Apcomplex("0.100000"));
        assertEquals("1, 2, -3, 0.1 precision", 6, a.precision());
        assertEquals("1, 2, -3, 0.1 value", new Apcomplex("0.0225801"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex("1.00000"), new Apcomplex("2.00000"), new Apcomplex("-3.00000"), new Apcomplex("7.000000"));
        assertEquals("1, 2, -3, 7 precision", 5, a.precision());
        assertEquals("1, 2, -3, 7 value", new Apcomplex("6.17541"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex("(1.1000000,2.2000000)"), new Apcomplex("(3.4000000,5.6000000)"), new Apcomplex("-7.0000000"), new Apcomplex("(-1.2000000,3.4000000)"));
        assertEquals("1.1+2.2i, 3.4+5.6i, -7, -1.2+3.4i precision", 6, a.precision());
        assertEquals("1.1+2.2i, 3.4+5.6i, -7, -1.2+3.4i value", new Apcomplex("(-8761.55,-55520.5)"), a, new Apfloat("5e-1"));

        try
        {
            ApcomplexMath.hypergeometric2F1Regularized(new Apcomplex(new Apfloat(1), new Apfloat(2)), new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)), new Apcomplex(new Apfloat(7), new Apfloat(8)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHypergeometricU()
    {
        Apcomplex a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 3+4i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 5+6i value", new Apcomplex("(-0.260510,0.792445)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex(new Apfloat(2, 13, 35), new Apfloat(3, 13, 35)), new Apcomplex(new Apfloat(4, 13, 35), new Apfloat(5, 13, 35)), new Apcomplex(new Apfloat(6, 13, 35), new Apfloat(7, 13, 35)));
        assertEquals("2+3i, 4+5i, 6+7i radix 35 precision", 13, a.precision());
        assertEquals("2+3i, 4+5i, 6+7i radix 35 radix", 35, a.radix());
        assertEquals("2+3i, 4+5i, 6+7i radix 35 value", new Apcomplex(new Apfloat("0.1ectwfmqvde25", 13, 35), new Apfloat("-0.6t1hr8o6ew9jd", 13, 35)), a, new Apfloat("0.000000000000f", 1, 35));

        // z = 0
        a = ApcomplexMath.hypergeometricU(new Apcomplex("1.00000"), new Apcomplex("0"), new Apcomplex("0"));
        assertEquals("1, 0, 0 precision", 6, a.precision());
        assertEquals("1, 0, 0 value", new Apcomplex("1.00000"), a);

        a = ApcomplexMath.hypergeometricU(new Apcomplex("2.00000"), new Apcomplex("-3.00000"), new Apcomplex("0"));
        assertEquals("2, -3, 0 precision", 6, a.precision());
        assertEquals("2, -3, 0 value", new Apcomplex("0.0500000"), a);

        // z negative real part
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(-5.00000,-6.00000)"));
        assertEquals("1+2i, 3+4i, -5-6i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, -5-6i value", new Apcomplex("(-0.000890904,-0.000719161)"), a, new Apfloat("6e-9"));

        // z very large
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(500000.0,600000.0)"));
        assertEquals("1+2i, 3+4i, 500000+600000i precision", 3, a.precision());
        assertEquals("1+2i, 3+4i, 500000+600000i value", new Apcomplex("(-7.13250e-6,-1.90930e-6)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,2.000000)"), new Apcomplex("(500000.0,600000.0)"));
        assertEquals("1+2i, 3+2i, 500000+600000i precision", 3, a.precision());
        assertEquals("1+2i, 3+2i, 500000+600000i value", new Apcomplex("(-7.13252e-6,-1.90926e-6)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("(3.000000,2.000000)"), new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(500.0000,600.0000)"));    // z very large and b - a nonpositive integer
        assertEquals("3+2i, 1+2i, 500+600i precision", 6, a.precision());
        assertEquals("3+2i, 1+2i, 500+600i value", new Apcomplex("(-1.16097e-8,2.81084e-9)"), a, new Apfloat("5e-13"));

        // z pure imaginary
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(0,14.0000)"));
        assertEquals("1+2i, 3+4i, 14i precision", 6, a.precision());
        assertEquals("1+2i, 3+4i, 14i value", new Apcomplex("(2.04875,-0.72946)"), a, new Apfloat("5e-5"));

        // Polynomial cases
        a = ApcomplexMath.hypergeometricU(new Apcomplex("0"), new Apcomplex("1.0"), new Apcomplex("1.0"));
        assertEquals("0, 1, 1 precision", 2, a.precision());
        assertEquals("0, 1, 1 value", new Apcomplex("1.0"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("-1.00000"), new Apcomplex("1.50000"), new Apcomplex("0"));
        assertEquals("-1, 1.5, 0 precision", 6, a.precision());
        assertEquals("-1, 1.5, 0 value", new Apcomplex("-1.50000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("-42.00000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-42, 3+4i, 5+6i precision", 6, a.precision());
        assertEquals("-42, 3+4i, 5+6i value", new Apcomplex("(2.80183e55,8.28632e56)"), a, new Apfloat("5e51"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,2.000000)"), new Apcomplex("(500.0000,600.0000)"));    // z very large and a - b + 1 nonpositive integer
        assertEquals("1+2i, 3+2i, 500+600i precision", 6, a.precision());
        assertEquals("1+2i, 3+2i, 500+600i value", new Apcomplex("(-0.000439931,-0.00739112)"), a, new Apfloat("5e-8"));

        // Reduction to 0F0
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 1+2i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 1+2i, 5+6i value", new Apcomplex("(0.194432,0.553089)"), a, new Apfloat("5e-6"));

        // b - a + 1 integer
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(2.00000,2.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 2+2i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 2+2i, 5+6i value", new Apcomplex("(0.200175,0.710710)"), a, new Apfloat("5e-6"));

        // b - a + 1 near-integer
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(1.00000,2.00001)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 1+2.00001i, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 1+2.00001i, 5+6i value", new Apcomplex("(0.194431,0.553089)"), a, new Apfloat("5e-6"));

        // b integer
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 0, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 0, 5+6i value", new Apcomplex("(0.388039,0.370539)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("1.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 1, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 1, 5+6i value", new Apcomplex("(0.451430,0.471959)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hypergeometricU(new Apcomplex("1.00000"), new Apcomplex("-2.00000"), new Apcomplex("-0.100000"));
        assertEquals("1, -2, -0.1 precision", 6, a.precision());
        assertEquals("1, -2, -0.1 value", new Apcomplex("(0.351911,-0.000473772)"), a, new Apfloat("5e-6"));

        // b near-integer
        a = ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("0.999999"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1+2i, 0, 5+6i precision", 6, a.precision());
        assertEquals("1+2i, 0, 5+6i value", new Apcomplex("(0.451430,0.471959)"), a, new Apfloat("5e-6"));

        // Non converging cases
        try
        {
            ApcomplexMath.hypergeometricU(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0"));
            fail("z=0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is indeterminate
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.hypergeometricU(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)), new Apcomplex(new Apfloat(7), new Apfloat(8)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testErf()
    {
        Apcomplex a = ApcomplexMath.erf(new Apcomplex("(3.000000,4.000000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-120.187,-27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erf(new Apcomplex("(3.000000,-4.000000)"));
        assertEquals("3 - 4i precision", 6, a.precision());
        assertEquals("3 - 4i value", new Apcomplex("(-120.187,27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erf(new Apcomplex("(-3.000000,4.000000)"));
        assertEquals("-3 + 4i precision", 6, a.precision());
        assertEquals("-3 + 4i value", new Apcomplex("(120.187,-27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erf(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(120.187,27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erf(new Apcomplex("15").precision(40));
        assertEquals("15 precision", 137, a.precision());
        assertEquals("15 value", new Apcomplex("0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999992787005827548793333434933441307072890066"), a, new Apfloat("5e-137"));

        a = ApcomplexMath.erf(new Apcomplex("-15").precision(40));
        assertEquals("-15 precision", 137, a.precision());
        assertEquals("-15 value", new Apcomplex("-0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999992787005827548793333434933441307072890066"), a, new Apfloat("5e-137"));

        a = ApcomplexMath.erf(new Apcomplex("(0,15)").precision(40));
        assertEquals("15i precision", 38, a.precision());
        assertEquals("15i value", new Apcomplex("(0,1.96138456386738060348167059391082112595e96)"), a, new Apfloat("5e59"));

        a = ApcomplexMath.erf(new Apcomplex("(0,-15)").precision(40));
        assertEquals("-15i precision", 38, a.precision());
        assertEquals("-15i value", new Apcomplex("(0,-1.96138456386738060348167059391082112595e96)"), a, new Apfloat("5e59"));

        a = ApcomplexMath.erf(new Apcomplex("(0.100000,0.150000)"));
        assertEquals("0.1+0.15i precision", 6, a.precision());
        assertEquals("0.1+0.15i value", new Apcomplex("(0.115005,0.168813)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.erf(new Apcomplex("(0,0.150000)"));
        assertEquals("0.15i precision", 6, a.precision());
        assertEquals("0.15i value", new Apcomplex("(0,0.170535)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.erf(new Apcomplex("(0.500000,0.750000)"));
        assertEquals("0.5 + 0.75i precision", 6, a.precision());
        assertEquals("0.5 + 0.75i value", new Apcomplex("(0.835592,0.721707)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.erf(new Apcomplex(new Apfloat(3, 17, 2), new Apfloat(4, 17, 2)));
        assertEquals("3 + 4i radix 2 precision", 13, a.precision());
        assertEquals("3 + 4i radix 2 value", new Apcomplex(new Apfloat("-1111000.00101111111", 13, 2), new Apfloat("-11011.110000000001011", 13, 2)), a, new Apfloat("1e-6", 1, 2));

        a = ApcomplexMath.erf(new Apcomplex(new Apfloat("0.1", 17, 2), new Apfloat("0.11", 17, 2)));
        assertEquals("0.1 + 0.11i radix 2 precision", 17, a.precision());
        assertEquals("0.1 + 0.11i radix 2 value", new Apcomplex(new Apfloat("0.1101010111101001011", 17, 2), new Apfloat("0.101110001100000111", 17, 2)), a, new Apfloat("1e-17", 1, 2));

        a = ApcomplexMath.erf(new Apcomplex("-10007.000000000000000"));
        assertEquals("-10007 precision", 43490286, a.precision());
        assertEquals("-10007 value", new Apint(-1).subtract(new Apcomplex("-1.12953556651e-43490275")), a, new Apfloat("5e-43490264"));

        a = ApcomplexMath.erfFixedPrecision(new Apcomplex("-10007.000000000000000"));
        assertEquals("-10007 fixed precision", 20, a.precision());
        assertEquals("-10007 fixed value", new Apcomplex("-0.99999999999999999999"), a, new Apfloat("5e-20"));

        a = ApcomplexMath.erf(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.erfFixedPrecision(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        try
        {
            ApcomplexMath.erf(new Apcomplex(new Apfloat(3), new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testErfc()
    {
        Apcomplex a = ApcomplexMath.erfc(new Apcomplex("(3.000000,4.000000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(121.187,27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erfc(new Apcomplex("(3.000000,-4.000000)"));
        assertEquals("3 - 4i precision", 6, a.precision());
        assertEquals("3 - 4i value", new Apcomplex("(121.187,-27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erfc(new Apcomplex("(-3.000000,4.000000)"));
        assertEquals("-3 + 4i precision", 6, a.precision());
        assertEquals("-3 + 4i value", new Apcomplex("(-119.187,27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erfc(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(-119.187,-27.7503)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.erfc(new Apcomplex("15").precision(40));
        assertEquals("15 precision", 38, a.precision());
        assertEquals("15 value", new Apcomplex("7.21299417245120666656506655869292710993e-100"), a, new Apfloat("5e-137"));

        a = ApcomplexMath.erfc(new Apcomplex("-15").precision(40));
        assertEquals("-15 precision", 138, a.precision());
        assertEquals("-15 value", new Apcomplex("1.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999278700582754879333343493344130707289007"), a, new Apfloat("5e-137"));

        a = ApcomplexMath.erfc(new Apcomplex("(0,15)").precision(40));
        assertEquals("15i precision", 38, a.precision());
        assertEquals("15i value", new Apcomplex("(0,-1.96138456386738060348167059391082112595e96)"), a, new Apfloat("5e59"));

        a = ApcomplexMath.erfc(new Apcomplex("(0,-15)").precision(40));
        assertEquals("-15i precision", 38, a.precision());
        assertEquals("-15i value", new Apcomplex("(0,1.96138456386738060348167059391082112595e96)"), a, new Apfloat("5e59"));

        a = ApcomplexMath.erfc(new Apcomplex("(0.300000,0.400000)"));
        assertEquals("0.3 + 0.4i precision", 6, a.precision());
        assertEquals("0.3 + 0.4i value", new Apcomplex("(0.617957,-0.431252)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.erfc(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apint(1), a);

        a = ApcomplexMath.erfcFixedPrecision(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apint(1), a);

        a = ApcomplexMath.erfc(new Apcomplex(new Apfloat(3, 17, 2), new Apfloat(4, 17, 2)));
        assertEquals("3 + 4i radix 2 precision", 13, a.precision());
        assertEquals("3 + 4i radix 2 value", new Apcomplex(new Apfloat("1111001.00101111111", 13, 2), new Apfloat("11011.110000000001011", 13, 2)), a, new Apfloat("1e-6", 1, 2));

        try
        {
            ApcomplexMath.erfc(new Apcomplex(new Apfloat(3), new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testErfi()
    {
        Apcomplex a = ApcomplexMath.erfi(new Apcomplex("(3.000000,4.000000)"));
        assertEquals("3 + 4i precision", 10, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-0.0000497203,0.9999106617)"), a, new Apfloat("5e-10"));

        a = ApcomplexMath.erfi(new Apcomplex("15").precision(8));
        assertEquals("15 precision", 6, a.precision());
        assertEquals("15 value", new Apcomplex("1.96138e96"), a, new Apfloat("5e91"));

        a = ApcomplexMath.erfi(new Apcomplex("-15").precision(8));
        assertEquals("-15 precision", 6, a.precision());
        assertEquals("-15 value", new Apcomplex("-1.96138e96"), a, new Apfloat("5e91"));

        a = ApcomplexMath.erfi(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.erfi(new Apcomplex(new Apfloat(3, 17, 2), new Apfloat(4, 17, 2)));
        assertEquals("3 + 4i radix 2 precision", 26, a.precision());
        assertEquals("3 + 4i radix 2 value", new Apcomplex(new Apfloat("-0.00000000000000110100001000101011", 26, 2), new Apfloat("0.111111111111101000100101001", 26, 2)), a, new Apfloat("1e-26", 1, 2));

        try
        {
            ApcomplexMath.erfi(new Apcomplex(new Apfloat(3), new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testDawsonF()
    {
        Apcomplex a = ApcomplexMath.dawsonF(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-880.043,412.164)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.dawsonF(new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(880.043,-412.164)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.dawsonF(new Apcomplex("(1000.000000,-4.000000000)"));
        assertEquals("1000 - 4i precision", 6, a.precision());
        assertEquals("1000 - 4i value", new Apcomplex("(0.000499992,1.99997e-6)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.dawsonF(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apfloat(0), a);

        a = ApcomplexMath.dawsonF(new Apcomplex(new Apfloat(1, 21, 2), new Apfloat(2, 21, 2)));
        assertEquals("1 + 2i radix 2 precision", 20, a.precision());
        assertEquals("1 + 2i radix 2 value", new Apcomplex(new Apfloat("-1101.0110001110010001", 20, 2), new Apfloat("-1011.1101010000100111", 20, 2)), a, new Apfloat("1e-16", 1, 2));

        try
        {
            ApcomplexMath.dawsonF(new Apcomplex(new Apfloat(3), new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testFresnelS()
    {
        Apcomplex a = ApcomplexMath.fresnelS(new Apcomplex("(3.000000,4.000000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(6.09755e14,4.53702e14)"), a, new Apfloat("5e9"));

        a = ApcomplexMath.fresnelS(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(-6.09755e14,-4.53702e14)"), a, new Apfloat("5e9"));

        a = ApcomplexMath.fresnelS(new Apcomplex("(2.000000000000000,1.000000000000000)"));
        assertEquals("2 + 1i precision", 16, a.precision());
        assertEquals("2 + 1i value", new Apcomplex("(-15.5877511044046,-36.7254648839914)"), a, new Apfloat("5e-14"));

        a = ApcomplexMath.fresnelS(new Apcomplex("(10000.0000000000000000000000000,1.00000000000000000000000000000)"));
        assertEquals("10000 + i precision", 22, a.precision());
        assertEquals("10000 + i value", new Apcomplex("(-9.23304009409117412e13634,-9.233334000234768004283e13638)"), a, new Apfloat("5e13617"));

        a = ApcomplexMath.fresnelS(new Apcomplex("(3.00000e-3,4.00000e-3)"));
        assertEquals("3e-3 + 4e-3i precision", 6, a.precision());
        assertEquals("3e-3 + 4e-3i value", new Apcomplex("(-6.12611e-8,2.30383e-8)"), a, new Apfloat("5e-13"));

        a = ApcomplexMath.fresnelS(new Apcomplex("(0,4.00000)"));
        assertEquals("4i precision", 6, a.precision());
        assertEquals("4i value", new Apcomplex("(0,-0.420516)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.fresnelS(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.fresnelS(new Apcomplex(new Apfloat(1, 21, 2), new Apfloat(2, 21, 2)));
        assertEquals("1 + 2i radix 2 precision", 19, a.precision());
        assertEquals("1 + 2i radix 2 value", new Apcomplex(new Apfloat("100100.1011100110111", 19, 2), new Apfloat("1111.100101100111011", 19, 2)), a, new Apfloat("1e-15", 1, 2));

        a = ApcomplexMath.fresnelS(new Apcomplex(new Apfloat("0.1", 21, 2), new Apfloat("0.11", 21, 2)));
        assertEquals("0.5 + 0.75i radix 2 precision", 21, a.precision());
        assertEquals("0.5 + 0.75i radix 2 value", new Apcomplex(new Apfloat("-0.0110100111100100001001", 21, 2), new Apfloat("0.0000101111010110101111011", 21, 2)), a, new Apfloat("1e-22", 1, 2));

        try
        {
            ApcomplexMath.fresnelS(new Apcomplex(new Apfloat(3), new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testFresnelC()
    {
        Apcomplex a = ApcomplexMath.fresnelC(new Apcomplex("(3.000000,4.000000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(4.53702e14,-6.09754e14)"), a, new Apfloat("5e9"));

        a = ApcomplexMath.fresnelC(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(-4.53702e14,6.09754e14)"), a, new Apfloat("5e9"));

        a = ApcomplexMath.fresnelC(new Apcomplex("(2.000000000000000,1.000000000000000)"));
        assertEquals("2 + 1i precision", 16, a.precision());
        assertEquals("2 + 1i value", new Apcomplex("(-36.22568799288165,16.08787137412548)"), a, new Apfloat("5e-14"));

        a = ApcomplexMath.fresnelC(new Apcomplex("(10000.0000000000000000000000000,1.00000000000000000000000000000)"));
        assertEquals("10000 + i precision", 22, a.precision());
        assertEquals("10000 + i value", new Apcomplex("(-9.23333400023476800428e13638,9.2330400940911741e13634)"), a, new Apfloat("5e13617"));

        a = ApcomplexMath.fresnelC(new Apcomplex("(3.00000000000000000000000000000e-3,4.00000000000000000000000000000e-3)"));
        assertEquals("3e-3 + 4e-3i precision", 30, a.precision());
        assertEquals("3e-3 + 4e-3i value", new Apcomplex("(0.00300000000005847740605046524772,0.00400000000076884218289338981714)"), a, new Apfloat("5e-32"));

        a = ApcomplexMath.fresnelC(new Apcomplex("(0,4.00000)"));
        assertEquals("4i precision", 6, a.precision());
        assertEquals("4i value", new Apcomplex("(0,0.498426)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.fresnelC(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.fresnelC(new Apcomplex(new Apfloat(1, 23, 2), new Apfloat(2, 23, 2)));
        assertEquals("1 + 2i radix 2 precision", 20, a.precision());
        assertEquals("1 + 2i radix 2 value", new Apcomplex(new Apfloat("10000.000101100111111", 20, 2), new Apfloat("-100100.00111001110001", 20, 2)), a, new Apfloat("1e-14", 1, 2));

        a = ApcomplexMath.fresnelC(new Apcomplex(new Apfloat("0.1", 21, 2), new Apfloat("0.11", 21, 2)));
        assertEquals("0.5 + 0.75i radix 2 precision", 21, a.precision());
        assertEquals("0.5 + 0.75i radix 2 value", new Apcomplex(new Apfloat("0.0111010111111111010110", 21, 2), new Apfloat("0.111001100101101010101", 21, 2)), a, new Apfloat("1e-21", 1, 2));

        try
        {
            ApcomplexMath.fresnelC(new Apcomplex(new Apfloat(3), new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testExpIntegralE()
    {
        Apcomplex a = ApcomplexMath.expIntegralE(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(0.000432607,-0.000317912)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.expIntegralE(new Apcomplex("(-3.000000,-4.000000)"), new Apcomplex("(-5.000000,-6.000000)"));
        assertEquals("-3 - 4i, -5 - 6i precision", 6, a.precision());
        assertEquals("-3 - 4i, -5 - 6i value", new Apcomplex("(-4.60709,10.3946)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.expIntegralE(new Apcomplex("0.999999"), new Apcomplex("(-5.00000,-6.00000)"));
        assertEquals("0.9999999, -5 - 6i precision", 6, a.precision());
        assertEquals("0.9999999, -5 - 6i value", new Apcomplex("(-5.79814,19.4725)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.expIntegralE(new Apcomplex("(-300.000000000000000,-400.000000000000000)"), new Apcomplex("(-500.000000000000000,-600.000000000000000)"));
        assertEquals("-300 - 400i, -500 - 600i precision", 15, a.precision());
        assertEquals("-300 - 400i, -500 - 600i value", new Apcomplex("(6.46274794850681e213,-8.84938850450089e213)"), a, new Apfloat("5e199"));

        /*
        a = ApcomplexMath.expIntegralE(new Apcomplex("(3.00000e-1000000000000,4.00000e-1000000000000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3e-1000000000000 + 4e-1000000000000i, 5 + 6i precision", 6, a.precision());
        assertEquals("3e-1000000000000 + 4e-1000000000000i, 5 + 6i value", new Apcomplex("(0.000715475,-0.000482033)"), a, new Apfloat("5e-9"));

        a = ApcomplexMath.expIntegralE(new Apcomplex("(3.0000000e-1000000000000,4.0000000e-1000000000000)"), new Apcomplex("(5.0000000e-100,6.0000000e-100)"));
        assertEquals("3e-1000000000000 + 4e-1000000000000i, 5e-1000000000000 + 6e-1000000000000i precision", 6, a.precision());
        assertEquals("3e-1000000000000 + 4e-1000000000000i, 5e-1000000000000 + 6e-1000000000000i value", new Apcomplex("(8.19672e98,-9.83607e98)"), a, new Apfloat("5e93"));
        */

        a = ApcomplexMath.expIntegralE(new Apcomplex("0"), new Apcomplex("-1.00000"));
        assertEquals("0, -1 precision", 6, a.precision());
        assertEquals("0, -1 value", new Apcomplex("-2.71828"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.expIntegralE(new Apcomplex(new Apfloat(3, 17, 2), new Apfloat(-4, 17, 2)), new Apcomplex(new Apfloat(5, 17, 2), new Apfloat(-6, 17, 2)));
        assertEquals("3 - 4i, 5 - 6i precision", 14, a.precision());
        assertEquals("3 - 4i, 5 - 6i radix", 2, a.radix());
        assertEquals("3 - 4i, 5 - 6i value", new Apcomplex(new Apfloat("1.1100010110011111e-12", 17, 2), new Apfloat("1.0100110101011011e-12", 17, 2)), a, new Apfloat("1e-25", 1, 2));

        try
        {
            ApcomplexMath.expIntegralE(new Apcomplex("0"), new Apcomplex("0"));
            fail("0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToNegative", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.expIntegralE(new Apcomplex("(0.9,0.1)"), new Apcomplex("0"));
            fail("0.9+0.1i, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.expIntegralE(new Apcomplex("1"), new Apcomplex("0"));
            fail("1, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.expIntegralE(new Apcomplex("(1,1)"), new Apcomplex("0"));
            fail("1+i, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.expIntegralE(new Apcomplex(Apfloat.ONE, new Apfloat(4)), new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testExpIntegralEi()
    {
        Apcomplex a = ApcomplexMath.expIntegralEi(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-4.15409,4.29442)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.expIntegralEi(new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("3 - 4i precision", 6, a.precision());
        assertEquals("3 - 4i value", new Apcomplex("(-4.15409,-4.29442)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.expIntegralEi(new Apcomplex("3.00000"));
        assertEquals("3 precision", 6, a.precision());
        assertEquals("3 value", new Apcomplex("9.93383"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.expIntegralEi(new Apcomplex("-3.00000"));
        assertEquals("-3 precision", 6, a.precision());
        assertEquals("-3 value", new Apcomplex("-0.0130484"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.expIntegralEi(new Apfloat(5, 17, 2));
        assertEquals("5 precision", 15, a.precision());
        assertEquals("5 radix", 2, a.radix());
        assertEquals("5 value", new Apfloat("101000.00101111011011", 20, 2), a, new Apfloat("1e-9", 1, 2));

        a = ApcomplexMath.expIntegralEi(new Apcomplex(new Apfloat(5, 17, 2), new Apfloat(-6, 17, 2)));
        assertEquals("5 - 6i precision", 15, a.precision());
        assertEquals("5 - 6i radix", 2, a.radix());
        assertEquals("5 - 6i value", new Apcomplex(new Apfloat("101.110011000101", 15, 2), new Apfloat("10000.0101010010", 15, 2)), a, new Apfloat("1e-10", 1, 2));

        try
        {
            ApcomplexMath.expIntegralEi(new Apcomplex("0"));
            fail("0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gammaIncomplete.upperOfNonpositive", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.expIntegralEi(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLogIntegral()
    {
        Apcomplex a = ApcomplexMath.logIntegral(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(3.13438,2.67692)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logIntegral(new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("3 - 4i precision", 6, a.precision());
        assertEquals("3 - 4i value", new Apcomplex("(3.13438,-2.67692)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logIntegral(new Apcomplex("3.000000"));
        assertEquals("3 precision", 6, a.precision());
        assertEquals("3 value", new Apcomplex("2.16359"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logIntegral(new Apcomplex("0.0500000"));
        assertEquals("0.05 precision", 6, a.precision());
        assertEquals("0.05 value", new Apcomplex("-0.0131194"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.logIntegral(new Apcomplex("(0,0.0500000)"));
        assertEquals("0.05i precision", 6, a.precision());
        assertEquals("0.05i value", new Apcomplex("(0.00469234,3.13052)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.logIntegral(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        try
        {
            ApcomplexMath.logIntegral(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "log.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testSinIntegral()
    {
        Apcomplex a = ApcomplexMath.sinIntegral(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(6.74799,-3.49866)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("-3 + 4i precision", 6, a.precision());
        assertEquals("-3 + 4i value", new Apcomplex("(-6.74799,-3.49866)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("(0,4.00000)"));
        assertEquals("4i precision", 6, a.precision());
        assertEquals("4i value", new Apcomplex("(0,9.81732)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("(0,-4.00000)"));
        assertEquals("-4i precision", 6, a.precision());
        assertEquals("-4i value", new Apcomplex("(0,-9.81732)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("(1.68942749162698476714140196393428144026820465592265024961338177758470411763182898030309575361902912e-1,4.569309214501175479576223496730314340966258060071718886889228625514024394623574435856202062672506692e1)"));
        assertEquals("very slow precision", 99, a.precision());
        assertEquals("very slow value", new Apcomplex("(1.2856937320582957355639864773250768352672586514874553088490985837403937331727094287936043615541429e17,7.7136891207689360132104393031156808820367356331758362713399089224432529992357532871154537681039206e17)"), a, new Apfloat("5e-84"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("0.0001").precision(30));
        assertEquals("0.00001 precision", 30, a.precision());
        assertEquals("0.00001 value", new Apcomplex("0.000099999999944444444461111111108"), a, new Apfloat("5e-33"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("(0,0.0001)").precision(30));
        assertEquals("0.00001i precision", 30, a.precision());
        assertEquals("0.00001i value", new Apcomplex("(0,0.000100000000055555555572222222225)"), a, new Apfloat("5e-33"));

        a = ApcomplexMath.sinIntegral(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.sinIntegral(new Apcomplex(new Apfloat(5, 17, 2), new Apfloat(-6, 17, 2)));
        assertEquals("5 - 6i precision", 15, a.precision());
        assertEquals("5 - 6i radix", 2, a.radix());
        assertEquals("5 - 6i value", new Apcomplex(new Apfloat("-10111.00000110110", 15, 2), new Apfloat("1110.00001100100", 15, 2)), a, new Apfloat("1e-10", 1, 2));

        a = ApcomplexMath.sinIntegral(new Apcomplex(new Apfloat("0.1", 17, 2), new Apfloat("0.11", 17, 2)));
        assertEquals("0.5 + 0.75i precision", 17, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.1000101001000101001", 17, 2), new Apfloat("0.101111011011111111", 17, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.sinIntegral(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testCosIntegral()
    {
        Apcomplex a = ApcomplexMath.cosIntegral(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-3.49576,-5.17591)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.cosIntegral(new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("-3 + 4i precision", 6, a.precision());
        assertEquals("-3 + 4i value", new Apcomplex("(-3.49576,8.3175)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.cosIntegral(new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(-3.49576,-8.3175)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.cosIntegral(new Apcomplex("(0,4.00000)"));
        assertEquals("4i precision", 6, a.precision());
        assertEquals("4i value", new Apcomplex("(9.81355,1.5708)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.cosIntegral(new Apcomplex("(0,-4.00000)"));
        assertEquals("-4i precision", 6, a.precision());
        assertEquals("-4i value", new Apcomplex("(9.81355,-1.5708)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.cosIntegral(new Apcomplex("0.0001").precision(30));
        assertEquals("0.00001 precision", 30, a.precision());
        assertEquals("0.00001 value", new Apcomplex("-8.63312470957464987442378706222"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.cosIntegral(new Apcomplex("(0,0.0001)").precision(30));
        assertEquals("0.00001i precision", 30, a.precision());
        assertEquals("0.00001i value", new Apcomplex("(-8.6331247045746498744237870618,1.57079632679489661923132169164)"), a, new Apfloat("5e-29"));

        a = ApcomplexMath.cosIntegral(new Apcomplex(new Apfloat(-5, 17, 2), new Apfloat(-6, 17, 2)));
        assertEquals("-5 - 6i precision", 15, a.precision());
        assertEquals("-5 - 6i radix", 2, a.radix());
        assertEquals("-5 - 6i value", new Apcomplex(new Apfloat("-1110.00001100101011", 15, 2), new Apfloat("10101.011101001011", 15, 2)), a, new Apfloat("1e-10", 1, 2));

        a = ApcomplexMath.cosIntegral(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 17, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.100010111110101110011", 17, 2), new Apfloat("0.11001010010110111000011", 17, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.cosIntegral(new Apcomplex("0"));
            fail("0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "log.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.cosIntegral(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gammaIncomplete.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testSinhIntegral()
    {
        Apcomplex a = ApcomplexMath.sinhIntegral(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-2.07661,2.15160)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("3 - 4i precision", 6, a.precision());
        assertEquals("3 - 4i value", new Apcomplex("(-2.07661,-2.15160)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("-3 + 4i precision", 6, a.precision());
        assertEquals("-3 + 4i value", new Apcomplex("(2.07661,2.15160)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(2.07661,-2.15160)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("4.00000"));
        assertEquals("4 precision", 6, a.precision());
        assertEquals("4 value", new Apcomplex("9.81733"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("-4.00000"));
        assertEquals("-4 precision", 6, a.precision());
        assertEquals("-4 value", new Apcomplex("-9.81733"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("(0,4.00000)"));
        assertEquals("4i precision", 6, a.precision());
        assertEquals("4i value", new Apcomplex("(0,1.75820)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("(0,-4.00000)"));
        assertEquals("-4i precision", 6, a.precision());
        assertEquals("-4i value", new Apcomplex("(0,-1.75820)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sinhIntegral(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        try
        {
            ApcomplexMath.sinhIntegral(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testCoshIntegral()
    {
        Apcomplex a = ApcomplexMath.coshIntegral(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(-2.07748,2.14282)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("(3.00000,-4.00000)"));
        assertEquals("3 - 4i precision", 6, a.precision());
        assertEquals("3 - 4i value", new Apcomplex("(-2.07748,-2.14282)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("(-3.00000,4.00000)"));
        assertEquals("-3 + 4i precision", 6, a.precision());
        assertEquals("-3 + 4i value", new Apcomplex("(-2.07748,0.998776)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("(-3.00000,-4.00000)"));
        assertEquals("-3 - 4i precision", 6, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(-2.07748,-0.998776)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("4.00000"));
        assertEquals("4 precision", 6, a.precision());
        assertEquals("4 value", new Apcomplex("9.81355"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("-4.00000"));
        assertEquals("-4 precision", 6, a.precision());
        assertEquals("-4 value", new Apcomplex("(9.81355,3.14159)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("(0,4.00000)"));
        assertEquals("4i precision", 6, a.precision());
        assertEquals("4i value", new Apcomplex("(-0.140982,1.57080)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.coshIntegral(new Apcomplex("(0,-4.00000)"));
        assertEquals("-4i precision", 6, a.precision());
        assertEquals("-4i value", new Apcomplex("(-0.140982,-1.57080)"), a, new Apfloat("5e-5"));

        try
        {
            ApcomplexMath.coshIntegral(new Apcomplex("0"));
            fail("0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "log.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.coshIntegral(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAiryAi()
    {
        Apcomplex a = ApcomplexMath.airyAi(new Apcomplex("(1.00000,2.00000)"));
        assertEquals("1 + 2i precision", 6, a.precision());
        assertEquals("1 + 2i value", new Apcomplex("(-0.219386,-0.175386)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.airyAi(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 7, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(207.7347,-204.6056)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.airyAi(new Apcomplex("(-300.000000000000,400.000000000000)"));
        assertEquals("-300 + 400i precision", 11, a.precision());
        assertEquals("-300 + 400i value", new Apcomplex("(2.9404090561e3183,2.7090694495e3183)"), a, new Apfloat("5e3173"));

        a = ApcomplexMath.airyAi(new Apcomplex(new Apfloat(-300, 50, 2), new Apfloat(-400, 50, 2)));
        assertEquals("-300 - 400i precision", 37, a.precision());
        assertEquals("-300 - 400i radix", 2, a.radix());
        assertEquals("-300 - 400i value", new Apcomplex(new Apfloat("1.001100010001100111011000010101110010e10575", 37, 2), new Apfloat("-1.000110010001100011001010010000000101e10575", 37, 2)), a, new Apfloat("1e10539", 1, 2));

        a = ApcomplexMath.airyAi(new Apcomplex(new Apfloat("0.1", 17, 2), new Apfloat("0.11", 17, 2)));
        assertEquals("0.5 + 0.75i precision", 17, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.0011000110100010010", 17, 2), new Apfloat("-0.0010110100011100011", 17, 2)), a, new Apfloat("1e-19", 1, 2));

        try
        {
            ApcomplexMath.airyAi(new Apcomplex("0"));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAiryAiPrime()
    {
        Apcomplex a = ApcomplexMath.airyAiPrime(new Apcomplex("(1.00000,2.00000)"));
        assertEquals("1 + 2i precision", 6, a.precision());
        assertEquals("1 + 2i value", new Apcomplex("(0.170445,0.387622)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.airyAiPrime(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 7, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(199.6016,604.6785)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.airyAiPrime(new Apcomplex("(-300.000000000000,400.000000000000)"));
        assertEquals("-300 + 400i precision", 11, a.precision());
        assertEquals("-300 + 400i value", new Apcomplex("(2.477709693e3184,-8.589688662e3184)"), a, new Apfloat("5e3174"));

        a = ApcomplexMath.airyAiPrime(new Apcomplex(new Apfloat("0.1", 19, 2), new Apfloat("0.11", 19, 2)));
        assertEquals("0.5 + 0.75i precision", 19, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("-0.01000000101011010010", 19, 2), new Apfloat("0.00011101011010111011101", 19, 2)), a, new Apfloat("1e-20", 1, 2));

        try
        {
            ApcomplexMath.airyAiPrime(new Apcomplex("0"));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAiryBi()
    {
        Apcomplex a = ApcomplexMath.airyBi(new Apcomplex("(1.00000,2.00000)"));
        assertEquals("1 + 2i precision", 6, a.precision());
        assertEquals("1 + 2i value", new Apcomplex("(0.048822,0.133274)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.airyBi(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 7, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(-204.6057,-207.7345)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.airyBi(new Apcomplex("(300.00000000000,-400.00000000000)"));
        assertEquals("-300 + 400i precision", 11, a.precision());
        assertEquals("-300 + 400i value", new Apcomplex("(1.1097608159e578,-7.994050161e577)"), a, new Apfloat("5e568"));

        a = ApcomplexMath.airyBi(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.110000000000010100", 18, 2), new Apfloat("0.01010101001010100101", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.airyBi(new Apcomplex("0"));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAiryBiPrime()
    {
        Apcomplex a = ApcomplexMath.airyBiPrime(new Apcomplex("(1.00000,2.00000)"));
        assertEquals("1 + 2i precision", 6, a.precision());
        assertEquals("1 + 2i value", new Apcomplex("(-0.857239,0.495506)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.airyBiPrime(new Apcomplex("(-3.000000,-4.000000)"));
        assertEquals("-3 - 4i precision", 7, a.precision());
        assertEquals("-3 - 4i value", new Apcomplex("(604.6789,-199.6012)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.airyBiPrime(new Apcomplex("(300.00000000000,-400.00000000000)"));
        assertEquals("-300 + 400i precision", 11, a.precision());
        assertEquals("-300 + 400i value", new Apcomplex("(1.4200513472e579,-2.7085912602e579)"), a, new Apfloat("5e569"));

        a = ApcomplexMath.airyBiPrime(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.0100000000010011111111", 18, 2), new Apfloat("0.001111010001010101101", 18, 2)), a, new Apfloat("1e-19", 1, 2));

        try
        {
            ApcomplexMath.airyBiPrime(new Apcomplex("0"));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBesselJ()
    {
        Apcomplex a = ApcomplexMath.besselJ(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(0.399827,-0.359635)"), a, new Apfloat("5e-6"));

        try
        {
            ApcomplexMath.besselJ(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBesselI()
    {
        Apcomplex a = ApcomplexMath.besselI(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(-3.54535,-7.37327 )"), a, new Apfloat("5e-5"));

        try
        {
            ApcomplexMath.besselI(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBesselY()
    {
        Apcomplex a = ApcomplexMath.besselY(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(0.357553,0.294736)"), a, new Apfloat("5e-6"));

        try
        {
            ApcomplexMath.besselY(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBesselK()
    {
        Apcomplex a = ApcomplexMath.besselK(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(0.00282215,0.00595941)"), a, new Apfloat("5e-8"));

        try
        {
            ApcomplexMath.besselK(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testStruveH()
    {
        Apcomplex a = ApcomplexMath.struveH(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 5, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(0.190863,1.11273)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.struveH(new Apcomplex(new Apfloat(3, 10, 9), new Apfloat(4, 10, 9)), new Apcomplex(new Apfloat(5, 10, 9), new Apfloat(6, 10, 9)));
        assertEquals("3 + 4i, 5 + 6i radix 9 precision", 9, a.precision());
        assertEquals("3 + 4i, 5 + 6i radix 9 value", new Apcomplex(new Apfloat("0.16412260", 9, 9), new Apfloat("1.10115405", 9 ,9)), a, new Apfloat("5e-8", 1, 9));

        try
        {
            ApcomplexMath.struveH(new Apcomplex("(-1.00000,4.00000)"), new Apcomplex(new Apfloat(0)));
            fail("Division by zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.struveH(new Apcomplex(new Apfloat("-1.00000")), new Apcomplex(new Apfloat(0)));
            fail("Zero to power by zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.struveH(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testStruveL()
    {
        Apcomplex a = ApcomplexMath.struveL(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(-3.26244538,-7.920592)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.struveL(new Apcomplex(new Apfloat(3, 10, 9), new Apfloat(4, 10, 9)), new Apcomplex(new Apfloat(5, 10, 9), new Apfloat(6, 10, 9)));
        assertEquals("3 + 4i, 5 + 6i radix 9 precision", 10, a.precision());
        assertEquals("3 + 4i, 5 + 6i radix 9 value", new Apcomplex(new Apfloat("-3.232281208", 10, 9), new Apfloat("-7.825100357", 10 ,9)), a, new Apfloat("5e-9", 1, 9));

        try
        {
            ApcomplexMath.struveL(new Apcomplex("(-1.00000,4.00000)"), new Apcomplex(new Apfloat(0)));
            fail("Division by zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToNonpositiveReal", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.struveL(new Apcomplex(new Apfloat("-1.00000")), new Apcomplex(new Apfloat(0)));
            fail("Zero to power by zero");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK
            assertEquals("Localization key", "pow.zeroToZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.struveL(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testAngerJ()
    {
        Apcomplex a = ApcomplexMath.angerJ(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 5, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(-2776.4313,-2238.5131)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.angerJ(new Apcomplex(new Apfloat(3, 10, 9), new Apfloat(4, 10, 9)), new Apcomplex(new Apfloat(5, 10, 9), new Apfloat(6, 10, 9)));
        assertEquals("3 + 4i, 5 + 6i radix 9 precision", 9, a.precision());
        assertEquals("3 + 4i, 5 + 6i radix 9 value", new Apcomplex(new Apfloat("-3724.37838", 10, 9), new Apfloat("-3056.45502", 10 ,9)), a, new Apfloat("5e-5", 1, 9));

        try
        {
            ApcomplexMath.angerJ(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testWeberE()
    {
        Apcomplex a = ApcomplexMath.weberE(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 5, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(2237.7155,-2777.0644)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.weberE(new Apcomplex(new Apfloat(3, 10, 9), new Apfloat(4, 10, 9)), new Apcomplex(new Apfloat(5, 10, 9), new Apfloat(6, 10, 9)));
        assertEquals("3 + 4i, 5 + 6i radix 9 precision", 9, a.precision());
        assertEquals("3 + 4i, 5 + 6i radix 9 value", new Apcomplex(new Apfloat("3055.63853", 10, 9), new Apfloat("-3725.05185", 10 ,9)), a, new Apfloat("5e-5", 1, 9));

        try
        {
            ApcomplexMath.weberE(new Apcomplex(new Apfloat(3), new Apfloat(4)), new Apcomplex(new Apfloat(5), new Apfloat(6)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testEllipticK()
    {
        Apcomplex a = ApcomplexMath.ellipticK(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(0.911196,0.631334)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.ellipticK(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("1.10010110101011111", 18, 2), new Apfloat("0.011001001001011001111", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.ellipticK(new Apcomplex("1.00000"));
            fail("1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.ellipticK(new Apcomplex("0"));
            fail("Infinite expansion of pi/2");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.ellipticK(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testEllipticE()
    {
        Apcomplex a = ApcomplexMath.ellipticE(new Apcomplex("(3.00000,4.00000)"));
        assertEquals("3 + 4i precision", 6, a.precision());
        assertEquals("3 + 4i value", new Apcomplex("(1.49955,-1.57788)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.ellipticE(new Apcomplex("(55,66)").precision(80));
        assertEquals("55 + 66i precision", 80, a.precision());
        assertEquals("55 + 66i value", new Apcomplex("(4.0811432805851427433792385864776680345716395379587937142840046535853583006891006,-8.2188557700657038428087644147741544808312164555261128756030008732791464871734558)"), a, new Apfloat("5e-79"));

        a = ApcomplexMath.ellipticE(new Apcomplex("1.00000"));
        assertEquals("1 precision", 6, a.precision());
        assertEquals("1 value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.ellipticE(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("1.0110101111110111101", 18, 2), new Apfloat("-0.010101110110101001", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.ellipticE(new Apcomplex("0"));
            fail("Infinite expansion of pi/2");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.ellipticE(new Apcomplex(Apfloat.ONE, new Apfloat(4)));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHermiteH()
    {
        Apcomplex a = ApcomplexMath.hermiteH(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(53.7166,89.7677)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hermiteH(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0"));
        assertEquals("3 + 4i, 0 precision", 6, a.precision());
        assertEquals("3 + 4i, 0 value", new Apcomplex("(315.806,-267.626)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.hermiteH(new Apcomplex("1.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1, 5 + 6i precision", 6, a.precision());
        assertEquals("1, 5 + 6i value", new Apcomplex("(10.0000,12.0000)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hermiteH(new Apcomplex("2.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("2, 5 + 6i precision", 6, a.precision());
        assertEquals("2, 5 + 6i value", new Apcomplex("(-46.000,240.000)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.hermiteH(new Apcomplex("-1.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, 5 + 6i precision", 6, a.precision());
        assertEquals("-1, 5 + 6i value", new Apcomplex("(0.0414360,-0.0489105)"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.hermiteH(new Apcomplex("-2.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-2, 5 + 6i precision", 6, a.precision());
        assertEquals("-2, 5 + 6i value", new Apcomplex("(-0.000642876,-0.00406325)"), a, new Apfloat("5e-8"));

        a = ApcomplexMath.hermiteH(new Apcomplex("-1.20000"), new Apcomplex("1.90000"));
        assertEquals("-1.2, 1.9 precision", 6, a.precision());
        assertEquals("-1.2, 1.9 value", new Apcomplex("0.175081"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hermiteH(new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, 5 + 6i precision", 6, a.precision());
        assertEquals("0, 5 + 6i value", new Apcomplex("1"), a);

        a = ApcomplexMath.hermiteH(new Apcomplex("0"), new Apcomplex("0"));
        assertEquals("0, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 value", new Apcomplex("1"), a);

        a = ApcomplexMath.hermiteH(new Apcomplex("2.00000"), new Apcomplex("0.7071067811865475"));
        assertEquals("2, 1/sqrt(2) precision", 6, a.precision());
        assertEquals("2, 1/sqrt(2) value", new Apcomplex("0"), a, new Apfloat("5e-16"));

        a = ApcomplexMath.hermiteH(new Apcomplex("3.00000"), new Apcomplex("0"));
        assertEquals("3, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("3, 0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.hermiteH(new Apcomplex("4.00000"), new Apcomplex("0"));
        assertEquals("4, 0 precision", 6, a.precision());
        assertEquals("4, 0 value", new Apcomplex("12.0000"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.hermiteH(new Apcomplex("-3.00000"), new Apcomplex("0"));
        assertEquals("-3, 0 precision", 6, a.precision());
        assertEquals("-3, 0 value", new Apcomplex("0.221557"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.hermiteH(new Apcomplex("-4.00000"), new Apcomplex("0"));
        assertEquals("-4, 0 precision", 6, a.precision());
        assertEquals("-4, 0 value", new Apcomplex("0.0833333"), a, new Apfloat("5e-7"));

        a = ApcomplexMath.hermiteH(new Apcomplex("3.500000000000000"), new Apcomplex("0.2770651806914138"));
        assertEquals("3.5, root precision", 16, a.precision());
        assertEquals("3.5, root value", new Apcomplex("0"), a, new Apfloat("5e-16"));

        a = ApcomplexMath.hermiteH(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("11.10000000101011011", 18, 2), new Apfloat("-10.110001100010111001", 18, 2)), a, new Apfloat("1e-16", 1, 2));

        try
        {
            ApcomplexMath.hermiteH(Apfloat.ONE, new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "gamma.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLaguerreL()
    {
        Apcomplex a = ApcomplexMath.laguerreL(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(-3204.7,13832.4)"), a, new Apfloat("5e-1"));

        a = ApcomplexMath.laguerreL(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("0.101110111001010010", 18, 2), new Apfloat("0.100111010100100101", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.laguerreL(Apfloat.ONE, new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLaguerreLGeneralized()
    {
        Apcomplex a = ApcomplexMath.laguerreL(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i value", new Apcomplex("(21.8186,-11.884)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.laguerreL(new Apcomplex("-1.00000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, 3 + 4i, 5 + 6i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, 3 + 4i, 5 + 6i value", new Apcomplex("0"), a);

        a = ApcomplexMath.laguerreL(new Apcomplex("-1.00000"), new Apcomplex("-2.00000"), new Apcomplex("-1.00000"));
        assertEquals("-1, -2, -1 precision", 6, a.precision());
        assertEquals("-1, -2, -1 value", new Apcomplex("0.183940"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.laguerreL(new Apcomplex(new Apfloat("0.1", 19, 2), new Apfloat("0.11", 19, 2)), new Apcomplex(new Apfloat("-0.1", 19, 2), new Apfloat("-0.11", 19, 2)), new Apcomplex(new Apfloat("0.1", 19, 2), new Apfloat("-0.11", 19, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i value", new Apcomplex(new Apfloat("-0.1001100101100010101", 18, 2), new Apfloat("-1.001000000110101111", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.laguerreL(new Apfloat("-0.5"), new Apfloat("-0.5"), new Apfloat(0));
            fail("Gamma of 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.laguerreL(Apfloat.ONE, new Apfloat(4), new Apfloat(5));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLegendreP()
    {
        Apcomplex a = ApcomplexMath.legendreP(new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(22.7624,16.4401)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.legendreP(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("10.0000100011011000", 18, 2), new Apfloat("-10.0100010011001100", 18, 2)), a, new Apfloat("1e-16", 1, 2));

        try
        {
            ApcomplexMath.legendreP(new Apfloat("0.5"), new Apfloat("-1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.legendreP(Apfloat.ONE, new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "hypergeometric.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLegendrePAssociated()
    {
        Apcomplex a = ApcomplexMath.legendreP(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i value", new Apcomplex("(-2.94024,-11.8168)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.legendreP(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i value", new Apcomplex(new Apfloat("0.11100010110110000111", 18, 2), new Apfloat("-0.0100100111100001101111", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.legendreP(new Apfloat("0.5"), new Apfloat("0.1"), new Apfloat("-1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.legendreP(Apfloat.ONE, new Apfloat(4), new Apfloat(5));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pow.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLegendreQ()
    {
        Apcomplex a = ApcomplexMath.legendreQ(new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(-25.8244,35.7548)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.legendreQ(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("-11.1001110100000101", 18, 2), new Apfloat("-11.00011010110110111", 18, 2)), a, new Apfloat("1e-16", 1, 2));

        try
        {
            ApcomplexMath.legendreQ(new Apfloat("0.5"), new Apfloat("1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.legendreQ(new Apfloat("0.5"), new Apfloat("-1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.legendreQ(Apfloat.ONE, new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLegendreQAssociated()
    {
        Apcomplex a = ApcomplexMath.legendreQ(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i value", new Apcomplex("(-18.6108,4.58924)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.legendreQ(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(3.00000,2.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1 + 2i, 3 + 2i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 2i, 5 + 6i value", new Apcomplex("(2.62864,-3.38769)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.legendreQ(new Apcomplex("(1.00000,2.00000)"), new Apcomplex("(4.00000,2.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1 + 2i, 4 + 2i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 4 + 2i, 5 + 6i value", new Apcomplex("(-6.65987,-26.5379)"), a, new Apfloat("5e-4"));
/*
        a = ApcomplexMath.legendreQ(new Apcomplex("(111.000,222.000)"), new Apcomplex("(333.000,444.000)"), new Apcomplex("(555.000,666.000)"));
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i value", new Apcomplex("(-1.51954e766,6.241444e766)"), a, new Apfloat("5e761"));
*/
        a = ApcomplexMath.legendreQ(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i value", new Apcomplex(new Apfloat("0.0110000011010011101", 18, 2), new Apfloat("-1.0101011110001011011", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.legendreQ(new Apfloat("0.5"), new Apfloat("0.1"), new Apfloat("1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToNegative", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.legendreQ(new Apfloat("0.5"), new Apfloat("0.1"), new Apfloat("-1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "pow.zeroToNegative", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.legendreQ(new Apfloat("0.5"), new Apfloat("-0.1"), new Apfloat("-1"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.legendreQ(new Apfloat("-1"), new Apfloat("-1"), new Apcomplex("(5,6)"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.legendreQ(new Apfloat("-1"), new Apfloat("-2"), new Apcomplex("(5,6)"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gamma.ofNegativeInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.legendreQ(Apfloat.ONE, new Apfloat(4), new Apfloat(5));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testSphericalHarmonicY()
    {
        // Note: Mathematica gives inconsistent results when real part of ϑ is > pi or negative and λ and μ are not integers
        Apcomplex a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(3.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, 3 + 4i, 3 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 3 + 6i, 7 + 8i value", new Apcomplex("(-1.00082e-15,-1.81859e-16)"), a, new Apfloat("5e-20"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(-2.000000,-2.000000)"), new Apcomplex("(5.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, -2 - 2i, 5 + 6i, 7 + 8i precision", Apfloat.INFINITE, a.precision());
        assertEquals("1 + 2i, -2 - 2i, 5 + 6i, 7 + 8i value", new Apcomplex("0"), a);

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(-3.000000,4.000000)"), new Apcomplex("(3.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, -3 + 4i, 3 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("1 + 2i, -3 + 4i, 3 + 6i, 7 + 8i value", new Apcomplex("(8705220,328078)"), a, new Apfloat("5e1"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,-2.000000)"), new Apcomplex("(3.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, 3 - 2i, 3 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 - 2i, 3 + 6i, 7 + 8i value", new Apcomplex("(0.124816,-0.178021 )"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(-3.100000,4.000000)"), new Apcomplex("(3.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, -3.1 + 4i, 3 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("1 + 2i, -3.1 + 4i, 3 + 6i, 7 + 8i value", new Apcomplex("(1.81034e7,-7.51346e6)"), a, new Apfloat("5e2"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("-1.00000"), new Apcomplex("-1.100000"), new Apcomplex("(3.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("-1, -1.1, 3 + 6i, 7 + 8i precision", 5, a.precision());
        assertEquals("-1, -1.1, 3 + 6i, 7 + 8i value", new Apcomplex("(-171.803,535.796)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("-0.500000"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("-0.5, 3 + 4i, 5 + 6i, 7 + 8i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-0.5, 3 + 4i, 5 + 6i, 7 + 8i value", new Apcomplex("0"), a);

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.0000000,2.0000000)"), new Apcomplex("0"), new Apcomplex("(5.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, 0, 5 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("1 + 2i, 0, 5 + 6i, 7 + 8i value", new Apcomplex("(5.60421,4.50366)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("-1.00000"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("-1, 0, 5 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("-1, 0, 5 + 6i, 7 + 8i value", new Apcomplex("(0.282095)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("2.00000"), new Apcomplex("3.00000"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("2, 3, 5 + 6i, 7 + 8i precision", Apfloat.INFINITE, a.precision());
        assertEquals("2, 3, 5 + 6i, 7 + 8i value", new Apcomplex("0"), a);

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("0"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("0, 0, 5 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("0, 0, 5 + 6i, 7 + 8i value", new Apcomplex("(0.282095)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex("1.00000"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("1, 0, 5 + 6i, 7 + 8i precision", 6, a.precision());
        assertEquals("1, 0, 5 + 6i, 7 + 8i value", new Apcomplex("(27.9574,94.5092)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.sphericalHarmonicY(new Apcomplex(new Apfloat("0.1", 19, 2), new Apfloat("0.11", 19, 2)), new Apcomplex(new Apfloat("-0.1", 19, 2), new Apfloat("-0.11", 19, 2)), new Apcomplex(new Apfloat("0.11", 19, 2), new Apfloat("0.111", 19, 2)), new Apcomplex(new Apfloat("-0.11", 19, 2), new Apfloat("-0.111", 19, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.75 + 0.875i, -0.75 - 0.875i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.75 + 0.875i, -0.75 - 0.875i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.75 + 0.875i, -0.75 - 0.875i value", new Apcomplex(new Apfloat("0.000100111111001111110", 18, 2), new Apfloat("1.10011101000100100e-6", 18, 2)), a, new Apfloat("1e-21", 1, 2));

        a = ApcomplexMath.sphericalHarmonicY(new Apfloat("11", 18, 2), new Apfloat("1", 18, 2), new Apcomplex(new Apfloat("0.11", 18, 2), new Apfloat("0.111", 18, 2)), new Apcomplex(new Apfloat("-0.11", 18, 2), new Apfloat("-0.111", 18, 2)));
        assertEquals("3, 1, 0.75 + 0.875i, -0.75 - 0.875i precision", 18, a.precision());
        assertEquals("3, 1, 0.75 + 0.875i, -0.75 - 0.875i radix", 2, a.radix());
        assertEquals("3, 1, 0.75 + 0.875i, -0.75 - 0.875i value", new Apcomplex(new Apfloat("-1.00110101111110011", 18, 2), new Apfloat("110.101001011111111", 18, 2)), a, new Apfloat("1e-15", 1, 2));

        try
        {
            ApcomplexMath.sphericalHarmonicY(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(2.000000,2.000000)"), new Apcomplex("(5.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
            fail("Infinite accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.sphericalHarmonicY(new Apfloat(3.1, Apfloat.INFINITE), new Apfloat(2), new Apfloat(5), new Apfloat(6));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.sphericalHarmonicY(new Apfloat(3), new Apfloat(2), new Apfloat(5), new Apfloat(6));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testChebyshevT()
    {
        Apcomplex a = ApcomplexMath.chebyshevT(new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(27.0758,49.6084)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.chebyshevT(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0"));
        assertEquals("3 + 4i, 0 precision", 6, a.precision());
        assertEquals("3 + 4i, 0 value", new Apcomplex("(0,267.745)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.chebyshevT(new Apcomplex("1.57079632679489661923132169164"), new Apcomplex("-8.38488366986797800727272727273e17"));
        assertEquals("pi/2, -9223372036854775808/11 precision", 29, a.precision());
        assertEquals("pi/2, -9223372036854775808/11 value", new Apcomplex("(4.6726604185343089659638280227e27,-2.06613465832409686981148475189e28)"), a, new Apfloat("5e0"));

        a = ApcomplexMath.chebyshevT(new Apcomplex("0"), new Apcomplex("0"));
        assertEquals("0, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 value", new Apcomplex("1"), a);

        a = ApcomplexMath.chebyshevT(new Apint(0, 9), new Apint(0, 9));
        assertEquals("0, 0 precision radix 9", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 radix radix 9", 9, a.radix());
        assertEquals("0, 0 value radix 9", new Apint(1, 9), a);

        try
        {
            ApcomplexMath.chebyshevT(new Apfloat(3), new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testChebyshevU()
    {
        Apcomplex a = ApcomplexMath.chebyshevU(new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(54.5031,98.9294)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.chebyshevU(new Apcomplex("(2.00000,3.00000)"), new Apcomplex("0"));
        assertEquals("2 + 3i, 0 precision", 6, a.precision());
        assertEquals("2 + 3i, 0 value", new Apcomplex("-55.6634"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.chebyshevU(new Apcomplex("0"), new Apcomplex("0"));
        assertEquals("0, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 value", new Apcomplex("1"), a);

        a = ApcomplexMath.chebyshevU(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("1.00000"));
        assertEquals("3 + 4i, 1 precision", 6, a.precision());
        assertEquals("3 + 4i, 1 value", new Apcomplex("(4.00000,4.00000)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.chebyshevU(new Apcomplex("3.00000"), new Apcomplex("-1.00000"));
        assertEquals("3, -1 precision", 6, a.precision());
        assertEquals("3, -1 value", new Apcomplex("-4.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.chebyshevU(new Apcomplex("4.00000"), new Apcomplex("-1.00000"));
        assertEquals("4, -1 precision", 6, a.precision());
        assertEquals("4, -1 value", new Apcomplex("5.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.chebyshevU(new Apcomplex("0"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("0, 3 + 4i precision", 6, a.precision());
        assertEquals("0, 3 + 4i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.chebyshevU(new Apcomplex(new Apfloat("0.1", 20, 2), new Apfloat("0.11", 20, 2)), new Apcomplex(new Apfloat("-0.1", 20, 2), new Apfloat("-0.11", 20, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 19, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("100.1001100100111011", 19, 2), new Apfloat("-10.111000100101001111", 19, 2)), a, new Apfloat("1e-16", 1, 2));

        a = ApcomplexMath.chebyshevU(new Apint(0, 9), new Apint(0, 9));
        assertEquals("0, 0 precision radix 9", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 radix radix 9", 9, a.radix());
        assertEquals("0, 0 value radix 9", new Apint(1, 9), a);

        try
        {
            ApcomplexMath.chebyshevU(new Apcomplex("(3.000000,4.000000)"), new Apcomplex("-1.000000"));
            fail("3 + 4i, -1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "inverseRoot.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.chebyshevU(new Apfloat(3), new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testGegenbauerCRenormalized()
    {
        Apcomplex a = ApcomplexMath.gegenbauerC(new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(22.3729,3.24175)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("1.01000111000001010", 18, 2), new Apfloat("-111.0000101110111111", 18, 2)), a, new Apfloat("1e-15", 1, 2));

        try
        {
            ApcomplexMath.gegenbauerC(new Apcomplex("0"), new Apcomplex("(5.000000,6.000000)"));
            fail("0, 5 + 6i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.gegenbauerC(new Apfloat(3), new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testGegenbauerC()
    {
        Apcomplex a = ApcomplexMath.gegenbauerC(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"));
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i value", new Apcomplex("(-5.65525,-1.46442)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("142.000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("142, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("142, 3 + 4i, 5 + 6i value", new Apcomplex("(-1.22769e174,3.88388e174)"), a, new Apfloat("5e169"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("141.000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("141, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("141, 3 + 4i, 5 + 6i value", new Apcomplex("(1.45386e173,2.1174e173)"), a, new Apfloat("5e168"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("2.00000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("2, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("2, 3 + 4i, 5 + 6i value", new Apcomplex("(-3275.00,-1100.00)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("1.00000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1, 3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("1, 3 + 4i, 5 + 6i value", new Apcomplex("(-18.0000,76.0000)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("-1.00000"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, 3 + 4i, 5 + 6i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, 3 + 4i, 5 + 6i value", new Apcomplex("0"), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex("-1.00000"), new Apcomplex("0.500000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, 0.5, 5 + 6i precision", 6, a.precision());
        assertEquals("-1, 0.5, 5 + 6i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("-1.00000"), new Apcomplex("-0.500000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, -0.5, 5 + 6i precision", 6, a.precision());
        assertEquals("-1, -0.5, 5 + 6i value", new Apcomplex("(6.00000,-30.0000)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.gegenbauerC(new Apcomplex("-1.00000"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, 0, 5 + 6i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, 0, 5 + 6i value", new Apcomplex("0"), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex("-1.00000"), new Apcomplex("-1.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("-1, -1, 5 + 6i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, -1, 5 + 6i value", new Apcomplex("0"), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex("0"), new Apcomplex("-1.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, -1, 5 + 6i precision", 6, a.precision());
        assertEquals("0, -1, 5 + 6i value", new Apcomplex("1.00000"), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex("0"), new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, 0, 5 + 6i precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0, 5 + 6i value", new Apcomplex("0"), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.5 - 0.75i value", new Apcomplex(new Apfloat("1.0001001011000001011", 18, 2), new Apfloat("-1011.110010001100001", 18, 2)), a, new Apfloat("1e-14", 1, 2));

        a = ApcomplexMath.gegenbauerC(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat(0, 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, 0, 0.5 - 0.75i precision", Apfloat.INFINITE, a.precision());
        assertEquals("0.5 + 0.75i, 0, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, 0, 0.5 - 0.75i value", new Apfloat(0, 18, 2), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex(new Apfloat("0", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0, -0.5 - 0.75i, 0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0, -0.5 - 0.75i, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0, -0.5 - 0.75i, 0.5 - 0.75i value", new Apfloat("1", 18, 2), a);

        a = ApcomplexMath.gegenbauerC(new Apcomplex(new Apfloat("1", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("1, -0.5 - 0.75i, 0.5 - 0.75i precision", 18, a.precision());
        assertEquals("1, -0.5 - 0.75i, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("1, -0.5 - 0.75i, 0.5 - 0.75i value", new Apfloat("-1.101", 18, 2), a, new Apfloat("1e-17", 1, 2));

        a = ApcomplexMath.gegenbauerC(new Apcomplex(new Apfloat("-1", 18, 2)), new Apcomplex(new Apfloat("-1", 18, 2)), new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("-1, -1, 0.5 - 0.75i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, -1, 0.5 - 0.75i radix", 2, a.radix());
        assertEquals("-1, -1, 0.5 - 0.75i value", new Apfloat("0", 18, 2), a);

        try
        {
            ApcomplexMath.gegenbauerC(new Apfloat("0.50"), new Apfloat("-0.25"), new Apfloat(0));
            fail("1/2, -1/4, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.gegenbauerC(new Apfloat(-1), new Apfloat(4), new Apfloat(5));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testJacobiP()
    {
        Apcomplex a = ApcomplexMath.jacobiP(new Apcomplex("(1.000000,2.000000)"), new Apcomplex("(3.000000,4.000000)"), new Apcomplex("(5.000000,6.000000)"), new Apcomplex("(7.000000,8.000000)"));
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i  precision", 6, a.precision());
        assertEquals("1 + 2i, 3 + 4i, 5 + 6i, 7 + 8i value", new Apcomplex("(-7.16216,-0.261529)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.jacobiP(new Apcomplex("0"), new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("0, 3 + 4i, 5 + 6i, 7 + 8i  precision", 6, a.precision());
        assertEquals("0, 3 + 4i, 5 + 6i, 7 + 8i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.jacobiP(new Apfloat("1.00000"), new Apfloat("-0.500000"), new Apfloat("1.00000"), new Apfloat("-1.00000"));
        assertEquals("1, -0.5, 1, -1  precision", 6, a.precision());
        assertEquals("1, -0.5, 1, -1 value", new Apcomplex("-2.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.jacobiP(new Apcomplex("-1.00000"), new Apcomplex("-1.00000"), new Apcomplex("-1.00000"), new Apcomplex("(7.00000,8.00000)"));
        assertEquals("-1, -1, -1, 7 + 8i  precision", 6, a.precision());
        assertEquals("-1, -1, -1, 7 + 8i value", new Apcomplex("(8.00000,-56.0000)"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.jacobiP(new Apcomplex(new Apfloat("0.1", 19, 2), new Apfloat("0.11", 19, 2)), new Apcomplex(new Apfloat("-0.1", 19, 2), new Apfloat("-0.11", 19, 2)), new Apcomplex(new Apfloat("0.11", 19, 2), new Apfloat("0.111", 19, 2)), new Apcomplex(new Apfloat("-0.11", 19, 2), new Apfloat("-0.111", 19, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.75 + 0.875i, -0.75 - 0.875i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.75 + 0.875i, -0.75 - 0.875i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i, 0.75 + 0.875i, -0.75 - 0.875i value", new Apcomplex(new Apfloat("110.110101010011100", 18, 2), new Apfloat("-101.00010011100000011", 18, 2)), a, new Apfloat("1e-15", 1, 2));

        try
        {
            ApcomplexMath.jacobiP(new Apfloat("-0.100000"), new Apfloat("1.00000"), new Apfloat("0"), new Apfloat("-1.00000"));
            fail("-0.1, 1, 0, -1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "hypergeometric.nonconvergence", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.jacobiP(new Apfloat("-0.500000"), new Apfloat("-0.500000"), new Apfloat("1.00000"), new Apfloat("1.00000"));
            fail("-1/2, -1/2, 1, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "gamma.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.jacobiP(new Apfloat(3), new Apfloat(4), new Apfloat(5), new Apfloat(6));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testFibonacci()
    {
        Apcomplex a = ApcomplexMath.fibonacci(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(723.269,975.240)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.fibonacci(new Apcomplex("(333.00000,444.00000)"), new Apcomplex("(5.00000000,6.00000000)"));
        assertEquals("333 + 444i, 5 + 6i precision", 4, a.precision());
        assertEquals("333 + 444i, 5 + 6i value", new Apcomplex("(3.54e472,3.136e473)"), a, new Apfloat("5e470"));

        a = ApcomplexMath.fibonacci(new Apcomplex("0"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("0, 3 + 4i precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 3 + 4i value", new Apcomplex("0"), a);

        a = ApcomplexMath.fibonacci(new Apcomplex("1.00000"), new Apcomplex("(3.00000,4.00000)"));
        assertEquals("1, 3 + 4i precision", 6, a.precision());
        assertEquals("1, 3 + 4i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.fibonacci(new Apcomplex("4.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("4, 5 + 6i precision", 6, a.precision());
        assertEquals("4, 5 + 6i value", new Apcomplex("(-405.000,246.000)"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.fibonacci(new Apcomplex("0"), new Apcomplex("(0,2.00000)"));
        assertEquals("0, 2i precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 2i value", new Apcomplex("0"), a);

        a = ApcomplexMath.fibonacci(new Apcomplex("1.00000"), new Apcomplex("(0,2.00000)"));
        assertEquals("1, 2i precision", 6, a.precision());
        assertEquals("1, 2i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.fibonacci(new Apcomplex("5.00000"), new Apcomplex("(0,2.00000)"));
        assertEquals("5, 2i precision", 6, a.precision());
        assertEquals("5, 2i value", new Apcomplex("5.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.fibonacci(new Apcomplex("3.00000"), new Apcomplex("(0,-2.00000)"));
        assertEquals("3, -2i precision", 6, a.precision());
        assertEquals("3, -2i value", new Apcomplex("-3.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.fibonacci(new Apint(2, 9), new Apcomplex(new Apint(0, 9), new Apint(2, 9)));
        assertEquals("2, 2i precision radix 9", Apfloat.INFINITE, a.precision());
        assertEquals("2, 2i radix radix 9", 9, a.radix());
        assertEquals("2, 2i value radix 9", new Apcomplex(new Apint(0, 9), new Apint(2, 9)), a);

        a = ApcomplexMath.fibonacci(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("-0.000111111111101011111111", 18, 2), new Apfloat("1.11110101100110111", 18, 2)), a, new Apfloat("1e-17", 1, 2));

        try
        {
            ApcomplexMath.fibonacci(new Apfloat("0.500000"), new Apcomplex("(0,2.00000)"));
            fail("1/2, 2i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.fibonacci(new Apfloat("0.500000"), new Apcomplex("(0,-2.00000)"));
            fail("1/2, -2i accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.fibonacci(new Apfloat(3), new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testEulerE()
    {
        Apcomplex a = ApcomplexMath.eulerE(4, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("4, 5 + 6i precision", 6, a.precision());
        assertEquals("4, 5 + 6i value", new Apcomplex("(-2644.00,-1782.00)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.eulerE(20, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("20, 5 + 6i precision", 6, a.precision());
        assertEquals("20, 5 + 6i value", new Apcomplex("(3.01307e17,1.96228e17)"), a, new Apfloat("5e12"));

        a = ApcomplexMath.eulerE(200, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("200, 5 + 6i precision", 6, a.precision());
        assertEquals("200, 5 + 6i value", new Apcomplex("(-1.65486e171,-2.86452e283)"), a, new Apfloat("5e278"));

        a = ApcomplexMath.eulerE(400, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("400, 5 + 6i precision", 6, a.precision());
        assertEquals("400, 5 + 6i value", new Apcomplex("(0,-8.64178e677)"), a, new Apfloat("5e672"));

        /* Very slow
        a = ApcomplexMath.eulerE(2000, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("2000, 5 + 6i precision", 6, a.precision());
        assertEquals("2000, 5 + 6i value", new Apcomplex("(0,-1.62571e4749)"), a, new Apfloat("5e4744"));
        */

        a = ApcomplexMath.eulerE(200, new Apcomplex("(5000.00,6000.00)"));
        assertEquals("200, 5000 + 6000i precision", 6, a.precision());
        assertEquals("200, 5000 + 6000i value", new Apcomplex("(2.571446e778,-2.199798e778)"), a, new Apfloat("5e773"));

        a = ApcomplexMath.eulerE(0, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, 5 + 6i precision", 6, a.precision());
        assertEquals("0, 5 + 6i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.eulerE(0, new Apcomplex("0"));
        assertEquals("0, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 value", new Apcomplex("1"), a);

        a = ApcomplexMath.eulerE(4, new Apcomplex("0"));
        assertEquals("4, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("4, 0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.eulerE(4, new Apcomplex("1.00000"));
        assertEquals("4, 1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("4, 1 value", new Apcomplex("0"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.eulerE(17, new Apcomplex("0"));
        assertEquals("17, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("17, 0 value", new Aprational("-3202291/2"), a);

        a = ApcomplexMath.eulerE(17, new Apcomplex("0"), 6);
        assertEquals("17, 0 precision fixed", 6, a.precision());
        assertEquals("17, 0 value fixed", new Apcomplex("-1601145.5"), a, new Apfloat("5e1"));

        a = ApcomplexMath.eulerE(3, new Apcomplex("-3.00000"));
        assertEquals("3, -3 precision", 6, a.precision());
        assertEquals("3, -3 value", new Apcomplex("-40.2500"), a, new Apfloat("5e-4"));

        a = ApcomplexMath.eulerE(3, new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("3, 0.5 + 0.75i precision", 18, a.precision());
        assertEquals("3, 0.5 + 0.75i radix", 2, a.radix());
        assertEquals("3, 0.5 + 0.75i value", new Apcomplex(new Apfloat("0", 18, 2), new Apfloat("-0.111111", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        a = ApcomplexMath.eulerE(13, new Apint(0, 2));
        assertEquals("13, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("13, 0 radix", 2, a.radix());
        assertEquals("13, 0 value", new Aprational("-1010101010101/10", 2), a);

        try
        {
            ApcomplexMath.eulerE(-1, new Apcomplex("(1,2)"));
            fail("-1, 1+ 2i accepted");
        }
        catch (IllegalArgumentException iae)
        {
            // OK, n < 0
        }

        try
        {
            ApcomplexMath.eulerE(1, new Apfloat(4));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "divide.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testBernoulliB()
    {
        Apcomplex a = ApcomplexMath.bernoulliB(4, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("4, 5 + 6i precision", 6, a.precision());
        assertEquals("4, 5 + 6i value", new Apcomplex("(-2660.03,-1728.00)"), a, new Apfloat("5e-2"));

        a = ApcomplexMath.bernoulliB(20, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("20, 5 + 6i precision", 6, a.precision());
        assertEquals("20, 5 + 6i value", new Apcomplex("(3.41535e17,-1.04603e16)"), a, new Apfloat("5e12"));

        a = ApcomplexMath.bernoulliB(200, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("200, 5 + 6i precision", 6, a.precision());
        assertEquals("200, 5 + 6i value", new Apcomplex("(-4.29963e231,7.90526e172)"), a, new Apfloat("5e278"));

        a = ApcomplexMath.bernoulliB(400, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("400, 5 + 6i precision", 6, a.precision());
        assertEquals("400, 5 + 6i value", new Apcomplex("-8.072036e565"), a, new Apfloat("5e560"));

        a = ApcomplexMath.bernoulliB(400, new Apcomplex("(5000.00,6000.00)"));
        assertEquals("400, 5000 + 6000i precision", 6, a.precision());
        assertEquals("400, 5000 + 6000i value", new Apcomplex("(1.77260e1556,-1.13133e1557)"), a, new Apfloat("5e1552"));

        a = ApcomplexMath.bernoulliB(0, new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, 5 + 6i precision", 6, a.precision());
        assertEquals("0, 5 + 6i value", new Apcomplex("1.00000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.bernoulliB(0, new Apcomplex("0"));
        assertEquals("0, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 value", new Apcomplex("1"), a);

        a = ApcomplexMath.bernoulliB(1, new Apcomplex("0"));
        assertEquals("1, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("1, 0 value", new Aprational("-1/2"), a);

        a = ApcomplexMath.bernoulliB(3, new Apcomplex("0"));
        assertEquals("3, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("3, 0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.bernoulliB(16, new Apcomplex("0"));
        assertEquals("16, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("16, 0 value", new Aprational("-3617/510"), a);

        a = ApcomplexMath.bernoulliB(16, new Apcomplex("0"), 6);
        assertEquals("16, 0 precision fixed", 6, a.precision());
        assertEquals("16, 0 value fixed", new Apcomplex("-7.09216"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.bernoulliB(4, new Apcomplex("-3.00000"));
        assertEquals("4, -3 precision", 6, a.precision());
        assertEquals("4, -3 value", new Apcomplex("143.967"), a, new Apfloat("5e-3"));

        a = ApcomplexMath.bernoulliB(1, new Apcomplex("-2.00000"));
        assertEquals("1, -2 precision", 6, a.precision());
        assertEquals("1, -2 value", new Apcomplex("-2.50000"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.bernoulliB(3, new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("3, 0.5 + 0.75i precision", 18, a.precision());
        assertEquals("3, 0.5 + 0.75i radix", 2, a.radix());
        assertEquals("3, 0.5 + 0.75i value", new Apcomplex(new Apfloat("0", 18, 2), new Apfloat("-0.100111", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        a = ApcomplexMath.bernoulliB(14, new Apint(0, 2));
        assertEquals("14, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("14, 0 radix", 2, a.radix());
        assertEquals("14, 0 value", new Aprational("111/110", 2), a);

        try
        {
            ApcomplexMath.bernoulliB(-1, new Apcomplex("(1,2)"));
            fail("-1, 1+ 2i accepted");
        }
        catch (IllegalArgumentException iae)
        {
            // OK, n < 0
        }

        try
        {
            ApcomplexMath.bernoulliB(1, new Apfloat("1.1", Apfloat.INFINITE));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "inverseRoot.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHarmonicNumber()
    {
        Apcomplex a = ApcomplexMath.harmonicNumber(new Apcomplex("(5.00000,6.00000)"));
        assertEquals("5 + 6i precision", 6, a.precision());
        assertEquals("5 + 6i value", new Apcomplex("(2.67388,0.828222)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.harmonicNumber(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.harmonicNumber(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.110011110100010001", 18, 2), new Apfloat("0.1001111010100111111", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.harmonicNumber(new Apfloat("-1"));
            fail("-1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "digamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.harmonicNumber(new Apfloat("1.1", Apfloat.INFINITE));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "euler.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testHarmonicNumberGeneralized()
    {
        Apcomplex a = ApcomplexMath.harmonicNumber(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(0.994430,0.0502165)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.harmonicNumber(new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, 5 + 6i precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 5 + 6i value", new Apcomplex("0"), a);

        a = ApcomplexMath.harmonicNumber(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0"));
        assertEquals("3 + 4i, 0 precision", 6, a.precision());
        assertEquals("3 + 4i, 0 value", new Apcomplex("(3.00000,4.00000)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.harmonicNumber(new Apcomplex("0"), new Apcomplex("0"));
        assertEquals("0, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0, 0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.harmonicNumber(new Apcomplex("-1.00000"), new Apcomplex("-1.00000"));
        assertEquals("-1, -1 precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, -1 value", new Apcomplex("0"), a);

        a = ApcomplexMath.harmonicNumber(new Apcomplex("-1.00000"), new Apcomplex("(-0.100000,1.00000)"));
        assertEquals("-1, -0.1 + i precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, -0.1 + i value", new Apcomplex("0"), a);

        a = ApcomplexMath.harmonicNumber(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("1"));
        assertEquals("3 + 4i, 1 precision", 6, a.precision());
        assertEquals("3 + 4i, 1 value", new Apcomplex("(2.24758,0.850502)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.harmonicNumber(new Apcomplex(new Apfloat("0.1", 17, 2), new Apfloat("0.11", 17, 2)), new Apcomplex(new Apfloat("-0.1", 17, 2), new Apfloat("-0.11", 17, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("0.0101000011011010011", 18, 2), new Apfloat("0.10000001101100111001", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.harmonicNumber(new Apfloat("-1.00000"), new Apfloat("1.00000"));
            fail("-1, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "digamma.ofNonpositiveInteger", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.harmonicNumber(new Apfloat("-1.00000"), new Apfloat("1.50000"));
            fail("-1, 1.5 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "zeta.ofSecondNonpositiveInteger", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.harmonicNumber(new Apfloat(1), new Apfloat("1.1", Apfloat.INFINITE));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "zeta.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testPolylog()
    {
        Apcomplex a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("3 + 4i, 5 + 6i precision", 6, a.precision());
        assertEquals("3 + 4i, 5 + 6i value", new Apcomplex("(27.2502,30.5992)"), a, new Apfloat("5e-4"));

        /* Very slow
        a = ApcomplexMath.polylog(new Apcomplex("(333.00000,444.00000)"), new Apcomplex("(555.00000,666.00000)"));
        assertEquals("333 + 444i, 555 + 666i precision", 6, a.precision());
        assertEquals("333 + 444i, 555 + 666i value", new Apcomplex("(555.000,666.000)"), a, new Apfloat("5e-3"));
        */

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("2.00000"));
        assertEquals("3 + 4i, 2 precision", 6, a.precision());
        assertEquals("3 + 4i, 2 value", new Apcomplex("(1.64436,0.0209666)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("1.00000"));
        assertEquals("3 + 4i, 1 precision", 6, a.precision());
        assertEquals("3 + 4i, 1 value", new Apcomplex("(0.890555,-0.00807595)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0.500000"));
        assertEquals("3 + 4i, 0.5 precision", 6, a.precision());
        assertEquals("3 + 4i, 0.5 value", new Apcomplex("(0.470416,-0.00634237)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(0.500000,0.100000)"));
        assertEquals("3 + 4i, 0.5 + 0.1i precision", 6, a.precision());
        assertEquals("3 + 4i, 0.5 + 0.1i value", new Apcomplex("(0.472997,0.0818064)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("(0.500000,-0.100000)"));
        assertEquals("3 + 4i, 0.5 - 0.1i precision", 6, a.precision());
        assertEquals("3 + 4i, 0.5 - 0.1i value", new Apcomplex("(0.469938,-0.0948103)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("0"));
        assertEquals("3 + 4i, 0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("3 + 4i, 0 value", new Apcomplex("0"), a);

        a = ApcomplexMath.polylog(new Apcomplex("(3.00000,4.00000)"), new Apcomplex("-0.500000"));
        assertEquals("3 + 4i, -0.5 precision", 6, a.precision());
        assertEquals("3 + 4i, -0.5 value", new Apcomplex("(-0.527181,-0.0150122)"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.polylog(new Apcomplex("4.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("4, 5 + 6i precision", 6, a.precision());
        assertEquals("4, 5 + 6i value", new Apcomplex("(2.35058,7.05471)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polylog(new Apcomplex("1.00000"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("1, 5 + 6i precision", 6, a.precision());
        assertEquals("1, 5 + 6i value", new Apcomplex("(-1.97562,2.15880)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polylog(new Apcomplex("0"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("0, 5 + 6i precision", 6, a.precision());
        assertEquals("0, 5 + 6i value", new Apcomplex("(-1.07692,0.115385)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polylog(new Apcomplex("4.00001"), new Apcomplex("(5.00000,6.00000)"));
        assertEquals("4.00001, 5 + 6i precision", 6, a.precision());
        assertEquals("4.00001, 5 + 6i value", new Apcomplex("(2.35059,7.05471)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.polylog(new Apcomplex("2.000000000000000"), new Apcomplex("(9.993319736282411e-1,3.654595031305655e-2)"));
        assertEquals("2, 9.993319736282411e-1 + 3.654595031305655e-2i precision", 16, a.precision());
        assertEquals("2, 9.993319736282411e-1 + 3.654595031305655e-2i value", new Apcomplex("(1.587849086339557,0.1575108716027421)"), a, new Apfloat("5e-15"));

        a = ApcomplexMath.polylog(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i, -0.5 - 0.75i value", new Apcomplex(new Apfloat("-0.0101111010000111111", 18, 2), new Apfloat("-0.0110110101101011100", 18, 2)), a, new Apfloat("1e-19", 1, 2));

        a = ApcomplexMath.polylog(new Apcomplex(new Apfloat("0", 18, 2), new Apfloat("0", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("0, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("0, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("0, -0.5 - 0.75i value", new Apcomplex(new Apfloat("-0.011101110111011101111", 18, 2), new Apfloat("-0.010001000100010001001", 18, 2)), a, new Apfloat("1e-19", 1, 2));

        a = ApcomplexMath.polylog(new Apcomplex(new Apfloat("1", 18, 2), new Apfloat("0", 18, 2)), new Apcomplex(new Apfloat("-0.1", 18, 2), new Apfloat("-0.11", 18, 2)));
        assertEquals("1, -0.5 - 0.75i precision", 18, a.precision());
        assertEquals("1, -0.5 - 0.75i radix", 2, a.radix());
        assertEquals("1, -0.5 - 0.75i value", new Apcomplex(new Apfloat("-0.100001000101110010", 18, 2), new Apfloat("-0.0111011010110001101", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.polylog(new Apcomplex("(1.00000,4.00000)"), new Apcomplex("1.00000"));
            fail("1 + 4i, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "polylog.infinite", aae.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.polylog(new Apcomplex("(-3.00000,4.00000)"), new Apcomplex("1.00000"));
            fail("-3 + 4i, 1 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "polylog.infinite", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.polylog(new Apfloat(1), new Apfloat("1.1", Apfloat.INFINITE));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testClausenCl()
    {
        Apcomplex a = ApcomplexMath.clausenCl(2, new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("2, (3,4), precision", 20, a.precision());
        assertEquals("2, (3,4), value", new Apcomplex("(0.2857468545510169786,-4.7994024776315696895)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(2, new Apcomplex(new Apfloat(-3, 20), new Apfloat(4, 20)));
        assertEquals("2, (-3,4), precision", 20, a.precision());
        assertEquals("2, (-3,4), value", new Apcomplex("(-0.2857468545510169786,-4.7994024776315696895)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(2, new Apcomplex(new Apfloat(-3, 20), new Apfloat(-4, 20)));
        assertEquals("2, (-3,-4), precision", 20, a.precision());
        assertEquals("2, (-3,-4), value", new Apcomplex("(-0.2857468545510169786,4.7994024776315696895)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(2, new Apcomplex(new Apfloat(3, 20), new Apfloat(-4, 20)));
        assertEquals("2, (3,-4), precision", 20, a.precision());
        assertEquals("2, (3,-4), value", new Apcomplex("(0.2857468545510169786,4.7994024776315696895)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(1, new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("1, (3,4), precision", 20, a.precision());
        assertEquals("1, (3,4), value", new Apcomplex("(-2.0179731370740158536,-0.0682576612005257708)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(3, new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("3, (3,4), precision", 20, a.precision());
        assertEquals("3, (3,4), value", new Apcomplex("(-8.6212452757620584144,-0.6800162650511846837)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(0, new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("0, (3,4), precision", 20, a.precision());
        assertEquals("0, (3,4), value", new Apcomplex("(0.00249344272301786922,-0.48218425142146653425)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenCl(-1, new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("-1, (3,4), precision", 20, a.precision());
        assertEquals("-1, (3,4), value", new Apcomplex("(-0.017504564937732919309,0.002404597625721348784)"), a, new Apfloat("5e-21"));

        a = ApcomplexMath.clausenCl(-2, new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("-2, (3,4), precision", 20, a.precision());
        assertEquals("-2, (3,4), value", new Apcomplex("(0.002231624952129400874,0.016892842534821677192)"), a, new Apfloat("5e-21"));

        a = ApcomplexMath.clausenCl(2, Apfloat.ZERO);
        assertEquals("2, 0, precision", Apfloat.INFINITE, a.precision());
        assertEquals("2, 0, value", Apfloat.ZERO, a);

        a = ApcomplexMath.clausenCl(2, new Apcomplex(new Apfloat(3, 12, 15), new Apfloat(4, 12, 15)));
        assertEquals("2, (3,4) radix 15, precision", 12, a.precision());
        assertEquals("2, (3,4) radix 15, radix", 15, a.radix());
        assertEquals("2, (3,4) radix 15, value", new Apcomplex(new Apfloat("0.4445e03e9ba97d1a", 12, 15),new Apfloat("-4.beceb3ca7cc867b3", 12, 15)), a, new Apfloat("0.00000000007", 1, 15));

        try
        {
            ApcomplexMath.clausenCl(1, Apfloat.ZERO);
            fail("1, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenCl(0, Apfloat.ZERO);
            fail("0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenCl(-1, Apfloat.ZERO);
            fail("-1, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is undefined
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenCl(1, Apfloat.ONE);
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testClausenSl()
    {
        Apcomplex a = ApcomplexMath.clausenSl(2, new Apcomplex(new Apfloat(3, 6), new Apfloat(4, 6)));
        assertEquals("2, (3,4), precision", 6, a.precision());
        assertEquals("2, (3,4), value", new Apcomplex("(-4.81745,-0.283185)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.clausenSl(2, new Apcomplex(new Apfloat(-3, 6), new Apfloat(4, 6)));
        assertEquals("2, (-3,4), precision", 6, a.precision());
        assertEquals("2, (-3,4), value", new Apcomplex("(-4.81745,0.283185)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.clausenSl(2, new Apcomplex(new Apfloat(-3, 6), new Apfloat(-4, 6)));
        assertEquals("2, (-3,-4), precision", 6, a.precision());
        assertEquals("2, (-3,-4), value", new Apcomplex("(-4.81745,-0.283185)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.clausenSl(2, new Apcomplex(new Apfloat(3, 6), new Apfloat(-4, 6)));
        assertEquals("2, (3,-4), precision", 6, a.precision());
        assertEquals("2, (3,-4), value", new Apcomplex("(-4.81745,0.283185)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.clausenSl(1, new Apcomplex(new Apfloat(3, 6), new Apfloat(4, 6)));
        assertEquals("1, (3,4), precision", 6, a.precision());
        assertEquals("1, (3,4), value", new Apcomplex("(0.0707963,-2.00000)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.clausenSl(3, new Apcomplex(new Apfloat(3, 6), new Apfloat(4, 6)));
        assertEquals("3, (3,4), precision", 6, a.precision());
        assertEquals("3, (3,4), value", new Apcomplex("(0.682589,-8.60315)"), a, new Apfloat("5e-5"));

        a = ApcomplexMath.clausenSl(0, new Apcomplex(new Apfloat(3, 6), new Apfloat(4, 6)));
        assertEquals("0, (3,4), precision", 6, a.precision());
        assertEquals("0, (3,4), value", new Apcomplex("-0.500000"), a, new Apfloat("5e-6"));

        a = ApcomplexMath.clausenSl(-1, new Apcomplex(new Apfloat(3, 6), new Apfloat(4, 6)));
        assertEquals("-1, (3,4), precision", Apfloat.INFINITE, a.precision());
        assertEquals("-1, (3,4), value", Apfloat.ZERO, a);

        a = ApcomplexMath.clausenSl(-2, new Apcomplex(new Apfloat(3, 6), new Apfloat(4, 6)));
        assertEquals("-2, (3,4), precision", Apfloat.INFINITE, a.precision());
        assertEquals("-2, (3,4), value", Apfloat.ZERO, a);

        a = ApcomplexMath.clausenSl(3, new Apcomplex("0"));
        assertEquals("3, 0, precision", Apfloat.INFINITE, a.precision());
        assertEquals("3, 0, value", Apfloat.ZERO, a);

        a = ApcomplexMath.clausenSl(2, new Apcomplex(new Apfloat(3, 12, 15), new Apfloat(4, 12, 15)));
        assertEquals("2, (3,4) radix 15, precision", 12, a.precision());
        assertEquals("2, (3,4) radix 15, radix", 15, a.radix());
        assertEquals("2, (3,4) radix 15, value", new Apcomplex(new Apfloat("-4.c3dd9c593e1e", 12, 15),new Apfloat("-0.43ab3c98d958", 12, 15)), a, new Apfloat("0.00000000007", 1, 15));

        try
        {
            ApcomplexMath.clausenSl(1, Apfloat.ZERO);
            fail("1, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenSl(0, Apfloat.ZERO);
            fail("0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenSl(-1, Apfloat.ZERO);
            fail("-1, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is undefined
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenSl(2, Apfloat.ZERO);
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testClausenS()
    {
        Apcomplex a = ApcomplexMath.clausenS(new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)), new Apcomplex(new Apfloat(5, 20), new Apfloat(6, 20)));
        assertEquals("(3,4), (5,6), precision", 19, a.precision());
        assertEquals("(3,4), (5,6), value", new Apcomplex("(261.50343969729421654,-59.32599314486005142)"), a, new Apfloat("5e-18"));

        a = ApcomplexMath.clausenS(new Apcomplex(new Apfloat(-3, 20), new Apfloat(4, 20)), new Apcomplex(new Apfloat(-5, 20), new Apfloat(6, 20)));
        assertEquals("(-3,4), (-5,6), precision", 19, a.precision());
        assertEquals("(-3,4), (-5,6), value", new Apcomplex("(0.4465374037234030926,2.0744134146733077996)"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.clausenS(new Apcomplex(new Apfloat(2, 20), new Apfloat(-3, 20)), new Apcomplex(new Apfloat(4, 20), new Apfloat(-5, 20)));
        assertEquals("(2,-3), (4,-5), precision", 20, a.precision());
        assertEquals("(2,-3), (4,-5), value", new Apcomplex("(32.153141736752359548,-4.856584113608561189)"), a, new Apfloat("5e-18"));

        a = ApcomplexMath.clausenS(new Apcomplex(new Apfloat(2, 20), new Apfloat(3, 20)), Apfloat.ZERO);
        assertEquals("(2,3), 0, precision", Apfloat.INFINITE, a.precision());
        assertEquals("(2,3), 0, value", Apfloat.ZERO, a);

        a = ApcomplexMath.clausenS(new Apcomplex(new Apfloat(1, 12, 15), new Apfloat(2, 12, 15)), new Apcomplex(new Apfloat(3, 12, 15), new Apfloat(4, 12, 15)));
        assertEquals("(1,2), (3,4) radix 15, precision", 12, a.precision());
        assertEquals("(1,2), (3,4) radix 15, radix", 15, a.radix());
        assertEquals("(1,2), (3,4) radix 15, value", new Apcomplex(new Apfloat("4.171e460846e9091b", 12, 15),new Apfloat("1.3b1433b55e383637", 12, 15)), a, new Apfloat("0.00000000007", 1, 15));

        try
        {
            ApcomplexMath.clausenS(new Apcomplex(new Apfloat(1, 20), new Apfloat(2, 20)), Apfloat.ZERO);
            fail("(1,2), 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenS(Apfloat.ZERO, Apfloat.ZERO);
            fail("0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenS(new Apcomplex(new Apfloat(-1, 20), new Apfloat(2, 20)), Apfloat.ZERO);
            fail("(-1,2), 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is undefined
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenS(new Apcomplex(new Apfloat(1), new Apfloat(2)), Apfloat.ONE);
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testClausenC()
    {
        Apcomplex a = ApcomplexMath.clausenC(new Apcomplex(new Apfloat(6, 13), new Apfloat(5, 13)), new Apcomplex(new Apfloat(4, 13), new Apfloat(3, 13)));
        assertEquals("(6,5), (4,3), precision", 13, a.precision());
        assertEquals("(6,5), (4,3), value", new Apcomplex("(-8.6785106871463847083,11.1461120920533052678)"), a, new Apfloat("5e-11"));

        a = ApcomplexMath.clausenC(new Apcomplex(new Apfloat(-6, 12), new Apfloat(5, 12)), new Apcomplex(new Apfloat(-4, 12), new Apfloat(3, 12)));
        assertEquals("(-6,5), (-4,3), precision", 12, a.precision());
        assertEquals("(-6,5), (-4,3), value", new Apcomplex("(18.609012051106803473,47.330157468783126565)"), a, new Apfloat("5e-10"));

        a = ApcomplexMath.clausenC(new Apcomplex(new Apfloat(5, 11), new Apfloat(-4, 11)), new Apcomplex(new Apfloat(3, 11), new Apfloat(-2, 11)));
        assertEquals("(5,-4), (3,-2), precision", 11, a.precision());
        assertEquals("(5,-4), (3,-2), value", new Apcomplex("(-3.9919117682490435618,1.1274795363193261975)"), a, new Apfloat("5e-10"));

        a = ApcomplexMath.clausenC(new Apcomplex(new Apfloat(2, 21), new Apfloat(3, 21)), Apfloat.ZERO);
        assertEquals("(2,3), 0, precision", 21, a.precision());
        assertEquals("(2,3), 0, value", new Apcomplex("(0.798021985146275720622,-0.113744308052938500216)"), a, new Apfloat("5e-21"));

        a = ApcomplexMath.clausenC(new Apcomplex(new Apfloat(4, 13, 15), new Apfloat(3, 13, 15)), new Apcomplex(new Apfloat(2, 13, 15), new Apfloat(1, 13, 15)));
        assertEquals("(4,3), (2,1) radix 15, precision", 13, a.precision());
        assertEquals("(4,3), (2,1) radix 15, radix", 15, a.radix());
        assertEquals("(4,3), (2,1) radix 15, value", new Apcomplex(new Apfloat("-0.74d3e937bab047921", 13, 15),new Apfloat("-1.04ebab6bebedd18a4", 13, 15)), a, new Apfloat("0.000000000007", 1, 15));

        try
        {
            ApcomplexMath.clausenC(new Apcomplex(new Apfloat(1, 20), new Apfloat(2, 20)), Apfloat.ZERO);
            fail("(1,2), 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenC(Apfloat.ZERO, Apfloat.ZERO);
            fail("0, 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenC(new Apcomplex(new Apfloat(-1, 20), new Apfloat(2, 20)), Apfloat.ZERO);
            fail("(-1,2), 0 accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is undefined
            assertEquals("Localization key", "cl.ofZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.clausenC(new Apfloat(3), Apfloat.ZERO);
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "pi.infinitePrecision", iee.getLocalizationKey());
        }
        try
        {
            ApcomplexMath.clausenC(new Apcomplex(new Apfloat(1), new Apfloat(2)), Apfloat.ONE);
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testLogisticSigmoid()
    {
        Apcomplex a = ApcomplexMath.logisticSigmoid(new Apcomplex(new Apfloat(3, 20), new Apfloat(4, 20)));
        assertEquals("(3,4), precision", 19, a.precision());
        assertEquals("(3,4), value", new Apcomplex("(1.032072199588268518,-0.040195507655084086)"), a, new Apfloat("5e-18"));

        a = ApcomplexMath.logisticSigmoid(new Apcomplex(new Apfloat(3000, 19), new Apfloat(4, 19)));
        assertEquals("(3000,4), precision", 19, a.precision());
        assertEquals("(3000,4), value", new Apcomplex("1.000000000000000000"), a, new Apfloat("5e-18"));

        a = ApcomplexMath.logisticSigmoid(new Apcomplex(new Apfloat(-3000, 19), new Apfloat(4, 19)));
        assertEquals("(-3000,4), precision", 16, a.precision());
        assertEquals("(-3000,4), value", new Apcomplex("(-8.54860631834400e-1304,-9.89775832980675e-1304)"), a, new Apfloat("5e-1319"));

        a = ApcomplexMath.logisticSigmoid(new Apcomplex("(1.000000000000000000e-1000000000000000000,1.000000000000000000e-1000000000000000000)"));
        assertEquals("(1e-1000000000000000000,1e-1000000000000000000), precision", 19, a.precision());
        assertEquals("(1e-1000000000000000000,1e-1000000000000000000), value", new Apcomplex("0.5000000000000000000"), a, new Apfloat("5e-19"));

        a = ApcomplexMath.logisticSigmoid(new Apcomplex("0"));
        assertEquals("0 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 value", new Aprational("1/2"), a);

        a = ApcomplexMath.logisticSigmoid(new Apint(0, 9));
        assertEquals("0 radix 9 precision", Apfloat.INFINITE, a.precision());
        assertEquals("0 radix 9 radix", 9, a.radix());
        assertEquals("0 radix 9 value", new Aprational("1/2", 9), a);

        a = ApcomplexMath.logisticSigmoid(new Apcomplex(new Apfloat("0.1", 18, 2), new Apfloat("0.11", 18, 2)));
        assertEquals("0.5 + 0.75i precision", 18, a.precision());
        assertEquals("0.5 + 0.75i radix", 2, a.radix());
        assertEquals("0.5 + 0.75i value", new Apcomplex(new Apfloat("0.1010001111011111101", 18, 2), new Apfloat("0.0010111011101101", 18, 2)), a, new Apfloat("1e-18", 1, 2));

        try
        {
            ApcomplexMath.logisticSigmoid(new Apcomplex(Apfloat.ZERO, ApfloatMath.pi(25)));
            fail("i pi accepted");
        }
        catch (ApfloatArithmeticException aae)
        {
            // OK, result is infinite
            assertEquals("Localization key", "divide.byZero", aae.getLocalizationKey());
        }

        try
        {
            ApcomplexMath.logisticSigmoid(new Apfloat(5));
            fail("Infinite expansion");
        }
        catch (InfiniteExpansionException iee)
        {
            // OK
            assertEquals("Localization key", "exp.infinitePrecision", iee.getLocalizationKey());
        }
    }

    public static void testUlp()
    {
        assertEquals("ulp 0", new Apcomplex("0"), ApcomplexMath.ulp(new Apcomplex("0")));
        Apfloat a = ApcomplexMath.ulp(new Apcomplex(new Apfloat(1)));
        assertEquals("ulp 1", new Apfloat("0"), a);
        assertEquals("ulp 1 precision", Apcomplex.INFINITE, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("1"));
        assertEquals("ulp 1.", new Apfloat("1"), a);
        assertEquals("ulp 1. precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("1.0"));
        assertEquals("ulp 1.0", new Apfloat("0.1"), a);
        assertEquals("ulp 1.0 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("1.1"));
        assertEquals("ulp 1.1", new Apfloat("0.1"), a);
        assertEquals("ulp 1.1 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("0.1"));
        assertEquals("ulp 0.1", new Apfloat("0.1"), a);
        assertEquals("ulp 0.1 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("0.2"));
        assertEquals("ulp 0.2", new Apfloat("0.1"), a);
        assertEquals("ulp 0.2 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("10"));
        assertEquals("ulp 10.", new Apfloat("1"), a);
        assertEquals("ulp 10. precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("1e1"));
        assertEquals("ulp 1e1", new Apfloat("1e1"), a);
        assertEquals("ulp 1e1 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("-1e1"));
        assertEquals("ulp -1e1", new Apfloat("1e1"), a);
        assertEquals("ulp -1e1 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex(Apfloat.ZERO, new Apfloat("1.a", 2, 11)));
        assertEquals("ulp (0, 1.a)", new Apfloat("0.1", 1, 11), a);
        assertEquals("ulp (0, 1.a) precision", 1, a.precision());
        assertEquals("ulp (0, 1.a) radix", 11, a.radix());
        a = ApcomplexMath.ulp(new Apcomplex("1e-9000000000000000000"));
        assertEquals("ulp 1e-9000000000000000000", new Apfloat("1e-9000000000000000000"), a);
        assertEquals("ulp 1e-9000000000000000000 precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex(new Apfloat("1e-9000000000000000000", 9000000000000000000L), new Apfloat("1e-9000000000000000000", 9000000000000000000L)));
        assertEquals("ulp (1e-9000000000000000000.000, 1e-9000000000000000000.000)", new Apfloat(0), a);
        assertEquals("ulp (1e-9000000000000000000.000, 1e-9000000000000000000.000) precision", Apcomplex.INFINITE, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("(1.11,-101.1)"));
        assertEquals("ulp (1.11,-101.1)", new Apfloat("0.1"), a);
        assertEquals("ulp (1.11,-101.1) precision", 1, a.precision());
        a = ApcomplexMath.ulp(new Apcomplex("(-9.9,0.0000011)"));
        assertEquals("ulp (-9.9,0.0000011)", new Apfloat("0.1"), a);
        assertEquals("ulp (-9.9,0.0000011) precision", 1, a.precision());
    }
}
