%mathpiper,def="ArithmeticGeometricMean"

/// coded by Serge Winitzki. See essays documentation for algorithms.

//////////////////////////////////////////////////
/// Numerical method: AGM sequence
//////////////////////////////////////////////////

/// compute the AGM sequence up to a given precision
ArithmeticGeometricMean(a, b, eps) :=
[
    Check(IsPositiveReal(a) And IsPositiveReal(b), "Argument", "The first two arguments must be positive real numbers.");
    
    Check(IsPositiveInteger(eps), "Argument", "The precision argument must be a positive integer.");
    
    a := N(a, eps);
    
    b := N(b, eps);
    
	Local(a1, b1);
	
	If(InVerboseMode(), Echo("ArithmeticGeometricMean: Info: at prec. ", BuiltinPrecisionGet()));
	
	// AGM main loop
	While(Abs(a-b)>=eps)
	[
		a1 := DivideN(a+b, 2);
		b1 := SqrtN(MultiplyN(a, b));	// avoid Sqrt() which uses N() inside it
		a := a1;
		b := b1;
	];
	
	DivideN(a+b, 2);
];
//UnFence(ArithmeticGeometricMean, 3);

%/mathpiper

    %output,preserve="false"
      Result: True
.   %/output





%mathpiper_docs,name="ArithmeticGeometricMean",categories="User Functions;Special Functions"
*CMD ArithmeticGeometricMean --- calculate the arithmetic geometric mean of two positive real numbers
*CALL
	ArithmeticGeometricMean(a,b,precision)

*PARMS
{a} -- a positive real number
{b} -- a positive real number
{precision} -- a positive integer which specifies the precision to use during the calculation

*DESC
Computes the arithmetic geometric mean of two positive real numbers.

*E.G.
In> ArithmeticGeometricMean(6,24,10)
Result: 13.5

%/mathpiper_docs

    %output,preserve="false"
      
.   %/output

