#!/usr/bin/ruby

# https://rosettacode.org/wiki/Arithmetic-geometric_mean

func agm0(a0, g0) {
    var (a1, g1);
    do {
        a1 = float(a0+g0 / 2);
        g1 = sqrt(a0 * g0);
        a0 = (a1+g1 /2);
        g0 = sqrt(a1 * g1);
    } while (a0 != a1);
    return a0;
}

func agm1(a, g) {
    loop {
        given (var ag = [float(a+g / 2), sqrt(a*g)]) {
            when (a, g) { return a }
            default     { (a, g) = ag... }
        }
    }
}

func agm2(a, g) {
    loop {
        var ag = [float(a+g / 2), sqrt(a*g)];
        ag == [a,g]  ? return(a) : ((a, g) = ag...);
    }
}

const sqrt2 = sqrt(2);
const test = [agm0(1, 1/sqrt2)]*2;

assert_eq([agm1(1, 1/sqrt2), agm2(1, 1/sqrt2)], test);

say "AG: #{test[0]}";