Task: Arithmetic-geometric mean



C#: namespace RosettaCode.ArithmeticGeometricMean
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    internal static class Program
    {
        private static double ArithmeticGeometricMean(double number,
                                                      double otherNumber,
                                                      IEqualityComparer<double>
                                                          comparer)
        {
            return comparer.Equals(number, otherNumber)
                       ? number
                       : ArithmeticGeometricMean(
                           ArithmeticMean(number, otherNumber),
                           GeometricMean(number, otherNumber), comparer);
        }

        private static double ArithmeticMean(double number, double otherNumber)
        {
            return 0.5 * (number + otherNumber);
        }

        private static double GeometricMean(double number, double otherNumber)
        {
            return Math.Sqrt(number * otherNumber);
        }

        private static void Main()
        {
            Console.WriteLine(
                ArithmeticGeometricMean(1, 0.5 * Math.Sqrt(2),
                                        new RelativeDifferenceComparer(1e-5)).
                    ToString(CultureInfo.InvariantCulture));
        }

        private class RelativeDifferenceComparer : IEqualityComparer<double>
        {
            private readonly double _maximumRelativeDifference;

            internal RelativeDifferenceComparer(double maximumRelativeDifference)
            {
                _maximumRelativeDifference = maximumRelativeDifference;
            }

            public bool Equals(double number, double otherNumber)
            {
                return RelativeDifference(number, otherNumber) <=
                       _maximumRelativeDifference;
            }

            public int GetHashCode(double number)
            {
                return number.GetHashCode();
            }

            private static double RelativeDifference(double number,
                                                     double otherNumber)
            {
                return AbsoluteDifference(number, otherNumber) /
                       Norm(number, otherNumber);
            }

            private static double AbsoluteDifference(double number,
                                                     double otherNumber)
            {
                return Math.Abs(number - otherNumber);
            }

            private static double Norm(double number, double otherNumber)
            {
                return 0.5 * (Math.Abs(number) + Math.Abs(otherNumber));
            }
        }
    }
}









Ada: with Ada.Text_IO, Ada.Numerics.Generic_Elementary_Functions;

procedure Arith_Geom_Mean is

   type Num is digits 18; 
   package N_IO is new Ada.Text_IO.Float_IO(Num);
   package Math is new Ada.Numerics.Generic_Elementary_Functions(Num);

   function AGM(A, G: Num) return Num is
      Old_G: Num;
      New_G: Num := G;
      New_A: Num := A;
   begin
      loop
         Old_G := New_G;
         New_G := Math.Sqrt(New_A*New_G);
         New_A := (Old_G + New_A) * 0.5;
         exit when (New_A - New_G) <= Num'Epsilon;
         
      end loop;
      return New_G;
   end AGM;

begin
   N_IO.Put(AGM(1.0, 1.0/Math.Sqrt(2.0)), Fore => 1, Aft => 17, Exp => 0);
end Arith_Geom_Mean;