(ns rosettacode.arithmetic.cmplx
  (:require [clojure.algo.generic.arithmetic :as ga])
  (:import [java.lang Number]))

(defrecord Complex [^Number r ^Number i]
  Object
  (toString [{:keys [r i]}]
    (apply str
      (cond
        (zero? r) [(if (= i 1) "" i) "i"]
        (zero? i) [r]
        :else     [r (if (neg? i) "-" "+") i "i"]))))

(defmethod ga/+ [Complex Complex]
  [x y] (map->Complex (merge-with + x y)))

(defmethod ga/+ [Complex Number] ; reals become y + 0i
  [{:keys [r i]} y] (->Complex (+ r y) i))

(defmethod ga/- Complex
  [x] (->> x vals (map -) (apply ->Complex)))

(defmethod ga/* [Complex Complex]
  [x y] (map->Complex (merge-with * x y)))

(defmethod ga/* [Complex Number]
  [{:keys [r i]} y] (->Complex (* r y) (* i y)))

(ga/defmethod* ga / Complex
  [x] (->> x vals (map /) (apply ->Complex)))

(defn conj [^Complex {:keys [r i]}]
  (->Complex r (- i)))

(defn inv [^Complex {:keys [r i]}]
  (let [m (+ (* r r) (* i i))]
    (->Complex (/ r m) (- (/ i m)))))


      $SET SOURCEFORMAT "FREE"
$SET ILUSING "System"
$SET ILUSING "System.Numerics"
class-id Prog.
method-id. Main static.
procedure division.
    declare num as type Complex = type Complex::ImaginaryOne()
    declare results as type Complex occurs any
    set content of results to ((num + num), (num * num), (- num), (1 / num), type Complex::Conjugate(num))
    perform varying result as type Complex thru results
        display result
    end-perform
end method.
end class.


# create an immutable Complex type
class Complex
  constructor: (@r=0, @i=0) ->
    @magnitude = @r*@r + @i*@i

  plus: (c2) ->
    new Complex(
      @r + c2.r,
      @i + c2.i
    )

  times: (c2) ->
    new Complex(
      @r*c2.r - @i*c2.i,
      @r*c2.i + @i*c2.r
    )

  negation: ->
    new Complex(
      -1 * @r,
      -1 * @i
    )

  inverse: ->
    throw Error "no inverse" if @magnitude is 0
    new Complex(
      @r / @magnitude,
      -1 * @i / @magnitude
    )

  toString: ->
    return "#{@r}" if @i == 0
    return "#{@i}i" if @r == 0
    if @i > 0
      "#{@r} + #{@i}i"
    else
      "#{@r} - #{-1 * @i}i"

# test
do ->
  a = new Complex(5, 3)
  b = new Complex(4, -3)

  sum = a.plus b
  console.log "(#{a}) + (#{b}) = #{sum}"

  product = a.times b
  console.log "(#{a}) * (#{b}) = #{product}"

  negation = b.negation()
  console.log "-1 * (#{b}) = #{negation}"

  diff = a.plus negation
  console.log "(#{a}) - (#{b}) = #{diff}"

  inverse = b.inverse()
  console.log "1 / (#{b}) = #{inverse}"

  quotient = product.times inverse
  console.log "(#{product}) / (#{b}) = #{quotient}"


MODULE Complex;
IMPORT StdLog;
TYPE
        Complex* = POINTER TO ComplexDesc;
        ComplexDesc = RECORD
                r-,i-: REAL;
        END;

VAR
        r,x,y: Complex;

PROCEDURE New(x,y: REAL): Complex;
VAR
        r: Complex;
BEGIN
        NEW(r);r.r := x;r.i := y;
        RETURN r
END New;

PROCEDURE (x: Complex) Add*(y: Complex): Complex,NEW;
BEGIN
        RETURN New(x.r + y.r,x.i + y.i)
END Add;

PROCEDURE ( x: Complex) Sub*( y: Complex): Complex, NEW;
BEGIN
        RETURN New(x.r - y.r,x.i - y.i)
END Sub;

PROCEDURE ( x: Complex) Mul*( y: Complex): Complex, NEW;
BEGIN
        RETURN New(x.r*y.r - x.i*y.i,x.r*y.i + x.i*y.r)
END Mul;

PROCEDURE ( x: Complex) Div*( y: Complex): Complex, NEW;
VAR
        d: REAL;
BEGIN
        d := y.r * y.r + y.i * y.i;
        RETURN New((x.r*y.r + x.i*y.i)/d,(x.i*y.r - x.r*y.i)/d)
END Div;

(* Reciprocal *)
PROCEDURE (x: Complex) Rec*(): Complex,NEW;
VAR
        d: REAL;
BEGIN
        d := x.r * x.r + x.i * x.i;
        RETURN New(x.r/d,(-1.0 * x.i)/d);
END Rec;

(* Conjugate *)
PROCEDURE (x: Complex) Con*(): Complex,NEW;
BEGIN
        RETURN New(x.r, (-1.0) * x.i);
END Con;

PROCEDURE (x: Complex) Out(),NEW;
BEGIN
	   StdLog.String("Complex(");
	   StdLog.Real(x.r);StdLog.String(',');StdLog.Real(x.i);
	   StdLog.String("i );")
END Out;

PROCEDURE Do*;
BEGIN
        x := New(1.5,3);
        y := New(1.0,1.0);

        StdLog.String("x: ");x.Out();StdLog.Ln;
        StdLog.String("y: ");y.Out();StdLog.Ln;
        r := x.Add(y);
        StdLog.String("x + y: ");r.Out();StdLog.Ln;
        r := x.Sub(y);
        StdLog.String("x - y: ");r.Out();StdLog.Ln;
        r := x.Mul(y);
        StdLog.String("x * y: ");r.Out();StdLog.Ln;
        r := x.Div(y);
        StdLog.String("x / y: ");r.Out();StdLog.Ln;
        r := y.Rec();
        StdLog.String("1 / y: ");r.Out();StdLog.Ln;
        r := x.Con();
        StdLog.String("x': ");r.Out();StdLog.Ln;
END Do;

END Complex.


import std.stdio, std.complex;

void main() {
    auto x = complex(1, 1); // complex of doubles on default
    auto y = complex(3.14159, 1.2);

    writeln(x + y);   // addition
    writeln(x * y);   // multiplication
    writeln(1.0 / x); // inversion
    writeln(-x);      // negation
}


class complex {

  num real=0;
  num imag=0;

  complex(num r,num i){
    this.real=r;
    this.imag=i;
  }

  complex add(complex b){
    return new complex(this.real + b.real, this.imag + b.imag);
  }

  complex mult(complex b){
    //FOIL of (a+bi)(c+di) with i*i = -1
    return new complex(this.real * b.real - this.imag * b.imag, this.real * b.imag + this.imag * b.real);
  }

  complex inv(){
    //1/(a+bi) * (a-bi)/(a-bi) = 1/(a+bi) but it's more workable
    num denom = real * real + imag * imag;
    double r =real/denom;
    double i= -imag/denom;
    return new complex( r,-i);
  }

  complex neg(){
    return new complex(-real, -imag);
  }

  complex conj(){
    return new complex(real, -imag);
  }

String toString(){
  return    this.real.toString()+' + '+ this.imag.toString()+'*i';
}
}
void main() {
  var cl= new complex(1,2);
  var cl2= new complex(3,-1);
  print(cl.toString());
  print(cl2.toString());
  print(cl.inv().toString());
  print(cl2.mult(cl).toString());

}


program Arithmetic_Complex;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.VarCmplx;

var
  a, b: Variant;

begin
  a := VarComplexCreate(5, 3);
  b := VarComplexCreate(0.5, 6.0);

  writeln(format('(%s) + (%s) = %s',[a,b, a+b]));

  writeln(format('(%s) * (%s) = %s',[a,b, a*b]));

  writeln(format('-(%s) = %s',[a,- a]));

  writeln(format('1/(%s) = %s',[a,1/a]));

  writeln(format('conj(%s) = %s',[a,VarComplexConjugate(a)]));

  Readln;
end.


defmodule Complex do
  import Kernel, except: [abs: 1, div: 2]

  defstruct real: 0, imag: 0

  def new(real, imag) do
    %__MODULE__{real: real, imag: imag}
  end

  def add(a, b) do
    {a, b} = convert(a, b)
    new(a.real + b.real, a.imag + b.imag)
  end

  def sub(a, b) do
    {a, b} = convert(a, b)
    new(a.real - b.real, a.imag - b.imag)
  end

  def mul(a, b) do
    {a, b} = convert(a, b)
    new(a.real*b.real - a.imag*b.imag, a.imag*b.real + a.real*b.imag)
  end

  def div(a, b) do
    {a, b} = convert(a, b)
    divisor = abs2(b)
    new((a.real*b.real + a.imag*b.imag) / divisor,
        (a.imag*b.real - a.real*b.imag) / divisor)
  end

  def neg(a) do
    a = convert(a)
    new(-a.real, -a.imag)
  end

  def inv(a) do
    a = convert(a)
    divisor = abs2(a)
    new(a.real / divisor, -a.imag / divisor)
  end

  def conj(a) do
    a = convert(a)
    new(a.real, -a.imag)
  end

  def abs(a) do
    :math.sqrt(abs2(a))
  end

  defp abs2(a) do
    a = convert(a)
    a.real*a.real + a.imag*a.imag
  end

  defp convert(a) when is_number(a), do: new(a, 0)
  defp convert(%__MODULE__{} = a), do: a

  defp convert(a, b), do: {convert(a), convert(b)}

  def task do
    a = new(1, 3)
    b = new(5, 2)
    IO.puts "a = #{a}"
    IO.puts "b = #{b}"
    IO.puts "add(a,b): #{add(a, b)}"
    IO.puts "sub(a,b): #{sub(a, b)}"
    IO.puts "mul(a,b): #{mul(a, b)}"
    IO.puts "div(a,b): #{div(a, b)}"
    IO.puts "div(b,a): #{div(b, a)}"
    IO.puts "neg(a)  : #{neg(a)}"
    IO.puts "inv(a)  : #{inv(a)}"
    IO.puts "conj(a) : #{conj(a)}"
  end
end

defimpl String.Chars, for: Complex do
  def to_string(%Complex{real: real, imag: imag}) do
    if imag >= 0, do: "#{real}+#{imag}j",
                else: "#{real}#{imag}j"
  end
end

Complex.task


%% Task: Complex Arithmetic
%% Author: Abhay Jain

-module(complex_number).
-export([calculate/0]).

-record(complex, {real, img}).

calculate() ->
    A = #complex{real=1, img=3},
    B = #complex{real=5, img=2},

    Sum = add (A, B),
    print (Sum),

    Product = multiply (A, B),
    print (Product),

    Negation = negation (A),
    print (Negation),

    Inversion = inverse (A),
    print (Inversion),

    Conjugate = conjugate (A),
    print (Conjugate).

add (A, B) ->
    RealPart = A#complex.real + B#complex.real,
    ImgPart = A#complex.img + B#complex.img,
    #complex{real=RealPart, img=ImgPart}.

multiply (A, B) ->
    RealPart = (A#complex.real * B#complex.real) - (A#complex.img * B#complex.img),
    ImgPart = (A#complex.real * B#complex.img) + (B#complex.real * A#complex.img),
    #complex{real=RealPart, img=ImgPart}.

negation (A) ->
    #complex{real=-A#complex.real, img=-A#complex.img}.

inverse (A) ->
    C = conjugate (A),
    Mod = (A#complex.real * A#complex.real) + (A#complex.img * A#complex.img),
    RealPart = C#complex.real / Mod,
    ImgPart = C#complex.img / Mod,
    #complex{real=RealPart, img=ImgPart}.

conjugate (A) ->
    RealPart = A#complex.real,
    ImgPart = -A#complex.img,
    #complex{real=RealPart, img=ImgPart}.

print (A) ->
    if A#complex.img < 0 ->
        io:format("Ans = ~p~pi~n", [A#complex.real, A#complex.img]);
       true ->
        io:format("Ans = ~p+~pi~n", [A#complex.real, A#complex.img])
    end.


PROGRAM COMPLEX_ARITH

TYPE COMPLEX=(REAL#,IMAG#)

DIM X:COMPLEX,Y:COMPLEX,Z:COMPLEX

!
! complex arithmetic routines
!
DIM A:COMPLEX,B:COMPLEX,C:COMPLEX

PROCEDURE ADD(A.,B.->C.)
    C.REAL#=A.REAL#+B.REAL#
    C.IMAG#=A.IMAG#+B.IMAG#
END PROCEDURE

PROCEDURE INV(A.->B.)
  LOCAL DENOM#
    DENOM#=A.REAL#^2+A.IMAG#^2
    B.REAL#=A.REAL#/DENOM#
    B.IMAG#=-A.IMAG#/DENOM#
END PROCEDURE

PROCEDURE MULT(A.,B.->C.)
    C.REAL#=A.REAL#*B.REAL#-A.IMAG#*B.IMAG#
    C.IMAG#=A.REAL#*B.IMAG#+A.IMAG#*B.REAL#
END PROCEDURE

PROCEDURE NEG(A.->B.)
    B.REAL#=-A.REAL#
    B.IMAG#=-A.IMAG#
END PROCEDURE

BEGIN
    PRINT(CHR$(12);) !CLS
    X.REAL#=1
    X.IMAG#=1
    Y.REAL#=2
    Y.IMAG#=2
    ADD(X.,Y.->Z.)
    PRINT(Z.REAL#;" + ";Z.IMAG#;"i")
    MULT(X.,Y.->Z.)
    PRINT(Z.REAL#;" + ";Z.IMAG#;"i")
    INV(X.->Z.)
    PRINT(Z.REAL#;" + ";Z.IMAG#;"i")
    NEG(X.->Z.)
    PRINT(Z.REAL#;" + ";Z.IMAG#;"i")
END PROGRAM


constant REAL = 1, IMAG = 2
type complex(sequence s)
    return length(s) = 2 and atom(s[REAL]) and atom(s[IMAG])
end type

function add(complex a, complex b)
    return a + b
end function

function mult(complex a, complex b)
    return {a[REAL] * b[REAL] - a[IMAG] * b[IMAG],
        a[REAL] * b[IMAG] + a[IMAG] * b[REAL]}
end function

function inv(complex a)
    atom denom
    denom = a[REAL] * a[REAL] + a[IMAG] * a[IMAG]
    return {a[REAL] / denom, -a[IMAG] / denom}
end function

function neg(complex a)
    return -a
end function

function scomplex(complex a)
    sequence s
    if a[REAL] != 0 then
        s = sprintf("%g",a)
    else
        s = {}
    end if

    if a[IMAG] != 0 then
        if a[IMAG] = 1 then
            s &= "+i"
        elsif a[IMAG] = -1 then
            s &= "-i"
        else
            s &= sprintf("%+gi",a[IMAG])
        end if
    end if

    if length(s) = 0 then
        return "0"
    else
        return s
    end if
end function

complex a, b
a = { 1.0,     1.0 }
b = { 3.14159, 1.2 }
printf(1,"a = %s\n",{scomplex(a)})
printf(1,"b = %s\n",{scomplex(b)})
printf(1,"a+b = %s\n",{scomplex(add(a,b))})
printf(1,"a*b = %s\n",{scomplex(mult(a,b))})
printf(1,"1/a = %s\n",{scomplex(inv(a))})
printf(1,"-a = %s\n",{scomplex(neg(a))})


USING: combinators kernel math math.functions prettyprint ;

C{ 1 2 } C{ 0.9 -2.78 } {
    [ + . ]             ! addition
    [ - . ]             ! subtraction
    [ * . ]             ! multiplication
    [ / . ]             ! division
    [ ^ . ]             ! power
} 2cleave

C{ 1 2 } {
    [ neg . ]           ! negation
    [ recip . ]         ! multiplicative inverse
    [ conjugate . ]     ! complex conjugate
    [ sin . ]           ! sine
    [ log . ]           ! natural logarithm
    [ sqrt . ]          ! square root
} cleave


S" fsl-util.fs" REQUIRED
S" complex.fs" REQUIRED

zvariable x
zvariable y
1e 1e   x z!
pi 1.2e y z!

x [email protected] y [email protected] z+ z.
x [email protected] y [email protected] z* z.
1e 0e zconstant 1+0i
1+0i x [email protected] z/ z.
x [email protected] znegate z.


program cdemo
    complex :: a = (5,3), b = (0.5, 6.0)      ! complex initializer
    complex :: absum, abprod, aneg, ainv

    absum  = a + b
    abprod = a * b
    aneg   = -a
    ainv   = 1.0 / a
end program cdemo


' FB 1.05.0 Win64

Type Complex
  As Double real, imag
  Declare Constructor(real As Double, imag As Double)
  Declare Function invert() As Complex
  Declare Function conjugate() As Complex
  Declare Operator cast() As String
End Type

Constructor Complex(real As Double, imag As Double)
  This.real = real
  This.imag = imag
End Constructor

Function Complex.invert() As Complex
  Dim denom As Double = real * real + imag * imag
  Return Complex(real / denom, -imag / denom)
End Function

Function Complex.conjugate() As Complex
  Return Complex(real, -imag)
End Function

Operator Complex.Cast() As String
  If imag >= 0 Then
    Return Str(real) + "+" + Str(imag) + "j"
  End If
  Return Str(real) + Str(imag) + "j"
End Operator

Operator - (c As Complex) As Complex
  Return Complex(-c.real, -c.imag)
End Operator

Operator + (c1 As Complex, c2 As Complex) As Complex
  Return Complex(c1.real + c2.real, c1.imag + c2.imag)
End Operator

Operator - (c1 As Complex, c2 As Complex) As Complex
  Return c1 + (-c2)
End Operator

Operator * (c1 As Complex, c2 As Complex) As Complex
  Return Complex(c1.real * c2.real - c1.imag * c2.imag, c1.real * c2.imag + c2.real * c1.imag)
End Operator

Operator / (c1 As Complex, c2 As Complex) As Complex
  Return c1 * c2.invert
End Operator

Var x = Complex(1, 3)
Var y = Complex(5, 2)
Print "x     = "; x
Print "y     = "; y
Print "x + y = "; x + y
Print "x - y = "; x - y
Print "x * y = "; x * y
Print "x / y = "; x / y
Print "-x    = "; -x
Print "1 / x = "; x.invert
Print "x*    = "; x.conjugate
Print
Print "Press any key to quit"
Sleep


Program ComplexDemo;

uses
  ucomplex;

var
  a, b, absum, abprod, aneg, ainv, acong: complex;

function complex(const re, im: real): ucomplex.complex; overload;
  begin
    complex.re := re;
    complex.im := im;
  end;

begin
  a      := complex(5, 3);
  b      := complex(0.5, 6.0);
  absum  := a + b;
  writeln ('(5 + i3) + (0.5 + i6.0): ', absum.re:3:1, ' + i', absum.im:3:1);
  abprod := a * b;
  writeln ('(5 + i3) * (0.5 + i6.0): ', abprod.re:5:1, ' + i', abprod.im:4:1);
  aneg   := -a;
  writeln ('-(5 + i3): ', aneg.re:3:1, ' + i', aneg.im:3:1);
  ainv   := 1.0 / a;
  writeln ('1/(5 + i3): ', ainv.re:3:1, ' + i', ainv.im:3:1);
  acong  := cong(a);
  writeln ('conj(5 + i3): ', acong.re:3:1, ' + i', acong.im:3:1);
end.


add[x,y] := x + y
multiply[x,y] := x * y
negate[x] := -x
invert[x] := 1/x  // Could also use inv[x] or recip[x]
conjugate[x] := Re[x] - Im[x] i

a = 3 + 2.5i
b = 7.3 - 10i
println["$a + $b = " + add[a,b]]
println["$a * $b = " + multiply[a,b]]
println["-$a = " + negate[a]]
println["1/$a = " + invert[a]]
println["conjugate[$a] = " + conjugate[a]]


type complex = (f64,f64)

fun complexAdd((a,b): complex) ((c,d): complex): complex =
  (a + c,
   b + d)

fun complexMult((a,b): complex) ((c,d): complex): complex =
 (a*c - b * d,
  a*d + b * c)

fun complexInv((r,i): complex): complex =
  let denom = r*r + i * i
  in (r / denom,
      -i / denom)

fun complexNeg((r,i): complex): complex =
  (-r, -i)

fun complexConj((r,i): complex): complex =
  (r, -i)

fun main (o: int) (a: complex) (b: complex): complex =
  if      o == 0 then complexAdd a b
  else if o == 1 then complexMult a b
  else if o == 2 then complexInv a
  else if o == 3 then complexNeg a
  else                complexConj a


# GAP knows gaussian integers, gaussian rationals (i.e. Q[i]), and cyclotomic fields. Here are some examples.
# E(n) is an nth primitive root of 1
i := Sqrt(-1);
# E(4)
(3 + 2*i)*(5 - 7*i);
# 29-11*E(4)
1/i;
# -E(4)
Sqrt(-3);
# E(3)-E(3)^2

i in GaussianIntegers;
# true
i/2 in GaussianIntegers;
# false
i/2 in GaussianRationals;
# true
Sqrt(-3) in Cyclotomics;
# true


package main

import (
    "fmt"
    "math/cmplx"
)

func main() {
    a := 1 + 1i
    b := 3.14159 + 1.25i
    fmt.Println("a:      ", a)
    fmt.Println("b:      ", b)
    fmt.Println("a + b:  ", a+b)
    fmt.Println("a * b:  ", a*b)
    fmt.Println("-a:     ", -a)
    fmt.Println("1 / a:  ", 1/a)
    fmt.Println("a̅:      ", cmplx.Conj(a))
}


class Complex {
    final Number real, imag

    static final Complex i = [0,1] as Complex

    Complex(Number r, Number i = 0) { (real, imag) = [r, i] }

    Complex(Map that) { (real, imag) = [that.real ?: 0, that.imag ?: 0] }

    Complex plus (Complex c) { [real + c.real, imag + c.imag] as Complex }
    Complex plus (Number n) { [real + n, imag] as Complex }

    Complex minus (Complex c) { [real - c.real, imag - c.imag] as Complex }
    Complex minus (Number n) { [real - n, imag] as Complex }

    Complex multiply (Complex c) { [real*c.real - imag*c.imag , imag*c.real + real*c.imag] as Complex }
    Complex multiply (Number n) { [real*n , imag*n] as Complex }

    Complex div (Complex c) { this * c.recip() }
    Complex div (Number n) { this * (1/n) }

    Complex negative () { [-real, -imag] as Complex }

    /** the complex conjugate of this complex number. Overloads the bitwise complement (~) operator. */
    Complex bitwiseNegate () { [real, -imag] as Complex }

    /** the magnitude of this complex number. */
    // could also use Math.sqrt( (this * (~this)).real )
    Number getAbs() { Math.sqrt( real*real + imag*imag ) }
    /** the magnitude of this complex number. */
    Number abs() { this.abs }

    /** the reciprocal of this complex number. */
    Complex getRecip() { (~this) / (ρ**2) }
    /** the reciprocal of this complex number. */
    Complex recip() { this.recip }

    /** derived polar angle θ (theta) for polar form. Normalized to 0 ≤ θ < 2π. */
    Number getTheta() {
        def θ = Math.atan2(imag,real)
        θ = θ < 0 ? θ + 2 * Math.PI : θ
    }
    /** derived polar angle θ (theta) for polar form. Normalized to 0 ≤ θ < 2π. */
    Number getΘ() { this.theta } // this is greek uppercase theta

    /** derived polar magnitude ρ (rho) for polar form. */
    Number getRho() { this.abs }
    /** derived polar magnitude ρ (rho) for polar form. */
    Number getΡ() { this.abs } // this is greek uppercase rho, not roman P

    /** Runs Euler's polar-to-Cartesian complex conversion,
     * converting [ρ, θ] inputs into a [real, imag]-based complex number */
    static Complex fromPolar(Number ρ, Number θ) {
        [ρ * Math.cos(θ), ρ * Math.sin(θ)] as Complex
    }

    /** Creates new complex with same magnitude ρ, but different angle θ */
    Complex withTheta(Number θ) { fromPolar(this.rho, θ) }
    /** Creates new complex with same magnitude ρ, but different angle θ */
    Complex withΘ(Number θ) { fromPolar(this.rho, θ) }

    /** Creates new complex with same angle θ, but different magnitude ρ */
    Complex withRho(Number ρ) { fromPolar(ρ, this.θ) }
    /** Creates new complex with same angle θ, but different magnitude ρ */
    Complex withΡ(Number ρ) { fromPolar(ρ, this.θ) } // this is greek uppercase rho, not roman P

    static Complex exp(Complex c) { fromPolar(Math.exp(c.real), c.imag) }

    static Complex log(Complex c) { [Math.log(c.rho), c.theta] as Complex }

    Complex power(Complex c) {
        def zero = [0] as Complex
        (this == zero && c != zero)  \
                ?  zero  \
                :  c == 1  \
                        ?  this  \
                        :  exp( log(this) * c )
    }

    Complex power(Number n) { this ** ([n, 0] as Complex) }

    boolean equals(that) {
        that != null && (that instanceof Complex \
                                ? [this.real, this.imag] == [that.real, that.imag] \
                                : that instanceof Number && [this.real, this.imag] == [that, 0])
    }

    int hashCode() { [real, imag].hashCode() }

    String toString() {
        def realPart = "${real}"
        def imagPart = imag.abs() == 1 ? "i" : "${imag.abs()}i"
        real == 0 && imag == 0 \
                ? "0" \
                : real == 0 \
                        ? (imag > 0 ? '' : "-")  + imagPart \
                        : imag == 0 \
                                ? realPart \
                                : realPart + (imag > 0 ? " + " : " - ")  + imagPart
    }
}


use fmt;
use math::complex::{c128,addc128,mulc128,divc128,negc128,conjc128};

export fn main() void = {
	let x: c128 = (1.0, 1.0);
	let y: c128 = (3.14159265, 1.2);

	// addition
	let (re, im) = addc128(x, y);
	fmt::printfln("{} + {}i", re, im)!;
	// multiplication
	let (re, im) = mulc128(x, y);
	fmt::printfln("{} + {}i", re, im)!;
	// inversion
	let (re, im) = divc128((1.0, 0.0), x);
	fmt::printfln("{} + {}i", re, im)!;
	// negation
	let (re, im) = negc128(x);
	fmt::printfln("{} + {}i", re, im)!;
	// conjugate
	let (re, im) = conjc128(x);
	fmt::printfln("{} + {}i", re, im)!;
};


import Data.Complex

main = do
  let a = 1.0 :+ 2.0    -- complex number 1+2i
  let b = 4             -- complex number 4+0i
  -- 'b' is inferred to be complex because it's used in
  -- arithmetic with 'a' below.
  putStrLn $ "Add:      " ++ show (a + b)
  putStrLn $ "Subtract: " ++ show (a - b)
  putStrLn $ "Multiply: " ++ show (a * b)
  putStrLn $ "Divide:   " ++ show (a / b)
  putStrLn $ "Negate:   " ++ show (-a)
  putStrLn $ "Inverse:  " ++ show (recip a)
  putStrLn $ "Conjugate:" ++ show (conjugate a)


procedure main()

SetupComplex()
a := complex(1,2)
b := complex(3,4)

c := complex(&pi,1.5)
d := complex(1)
e := complex(,1)

every v := !"abcde" do write(v," := ",cpxstr(variable(v)))

write("a+b := ", cpxstr(cpxadd(a,b)))
write("a-b := ", cpxstr(cpxsub(a,b)))
write("a*b := ", cpxstr(cpxmul(a,b)))
write("a/b := ", cpxstr(cpxdiv(a,b)))
write("neg(a) := ", cpxstr(cpxneg(a)))
write("inv(a) := ", cpxstr(cpxinv(a)))
write("conj(a) := ", cpxstr(cpxconj(a)))
write("abs(a) := ", cpxabs(a))
write("neg(1) := ", cpxstr(cpxneg(1)))
end


   x=: 1j1
   y=: 3.14159j1.2
   x+y            NB. addition
4.14159j2.2
   x*y            NB. multiplication
1.94159j4.34159
   %x             NB. inversion
0.5j_0.5
   -x             NB. negation
_1j_1
   +x             NB. (complex) conjugation
1j_1


public class Complex {
    public final double real;
    public final double imag;

    public Complex() {
        this(0, 0);
    }

    public Complex(double r, double i) {
        real = r;
        imag = i;
    }

    public Complex add(Complex b) {
        return new Complex(this.real + b.real, this.imag + b.imag);
    }

    public Complex mult(Complex b) {
        // FOIL of (a+bi)(c+di) with i*i = -1
        return new Complex(this.real * b.real - this.imag * b.imag,
                this.real * b.imag + this.imag * b.real);
    }

    public Complex inv() {
        // 1/(a+bi) * (a-bi)/(a-bi) = 1/(a+bi) but it's more workable
        double denom = real * real + imag * imag;
        return new Complex(real / denom, -imag / denom);
    }

    public Complex neg() {
        return new Complex(-real, -imag);
    }

    public Complex conj() {
        return new Complex(real, -imag);
    }

    @Override
    public String toString() {
        return real + " + " + imag + " * i";
    }

    public static void main(String[] args) {
        Complex a = new Complex(Math.PI, -5); //just some numbers
        Complex b = new Complex(-1, 2.5);
        System.out.println(a.neg());
        System.out.println(a.add(b));
        System.out.println(a.inv());
        System.out.println(a.mult(b));
        System.out.println(a.conj());
    }
}


function Complex(r, i) {
	this.r = r;
	this.i = i;
}

Complex.add = function() {
	var num = arguments[0];

	for(var i = 1, ilim = arguments.length; i < ilim; i += 1){
		num.r += arguments[i].r;
		num.i += arguments[i].i;
	}

	return num;
}

Complex.multiply = function() {
	var num = arguments[0];

	for(var i = 1, ilim = arguments.length; i < ilim; i += 1){
		num.r = (num.r * arguments[i].r) - (num.i * arguments[i].i);
		num.i = (num.i * arguments[i].r) - (num.r * arguments[i].i);
	}

	return num;
}

Complex.negate = function (z) {
	return new Complex(-1*z.r, -1*z.i);
}

Complex.invert = function(z) {
	var denom = Math.pow(z.r,2) + Math.pow(z.i,2);
	return new Complex(z.r/denom, -1*z.i/denom);
}

Complex.conjugate = function(z) {
	return new Complex(z.r, -1*z.i);
}

// BONUSES!

Complex.prototype.toString = function() {
	return this.r === 0 && this.i === 0
          ? "0"
          : (this.r !== 0 ? this.r : "")
          + ((this.r !== 0 || this.i < 0) && this.i !== 0
              ? (this.i > 0 ? "+" : "-")
              : "" ) + ( this.i !== 0 ? Math.abs(this.i) + "i" : "" );
}

Complex.prototype.getMod = function() {
	return Math.sqrt( Math.pow(this.r,2) , Math.pow(this.i,2) )
}


def real(z): if (z|type) == "number" then z else z[0] end;

def imag(z): if (z|type) == "number" then 0 else z[1] end;

def plus(x; y):
    if (x|type) == "number" then
       if  (y|type) == "number" then [ x+y, 0 ]
       else [ x + y[0], y[1]]
       end
    elif (y|type) == "number" then plus(y;x)
    else [ x[0] + y[0], x[1] + y[1] ]
    end;

def multiply(x; y):
    if (x|type) == "number" then
       if  (y|type) == "number" then [ x*y, 0 ]
       else [x * y[0], x * y[1]]
       end
    elif (y|type) == "number" then multiply(y;x)
    else [ x[0] * y[0] - x[1] * y[1],
           x[0] * y[1] + x[1] * y[0]]
    end;

def multiply: reduce .[] as $x (1; multiply(.; $x));

def negate(x): multiply(-1; x);

def minus(x; y): plus(x; multiply(-1; y));

def conjugate(z):
  if (z|type) == "number" then [z, 0]
  else  [z[0], -(z[1]) ]
  end;

def invert(z):
  if (z|type) == "number" then [1/z, 0]
  else
    ( (z[0] * z[0]) + (z[1] * z[1]) ) as $d
   # use "0 + ." to convert -0 back to 0
    | [ z[0]/$d, (0 + -(z[1]) / $d)]
  end;

def divide(x;y): multiply(x; invert(y));

def exp(z):
  def expi(x): [ (x|cos), (x|sin) ];
  if (z|type) == "number" then z|exp
  elif z[0] == 0 then expi(z[1])  # for efficiency
  else multiply( (z[0]|exp); expi(z[1]) )
  end ;

def test(x;y):
  "x =      \( x )",
  "y =      \( y )",
  "x+y:     \( plus(x;y))",
  "x*y:     \( multiply(x;y))",
  "-x:      \( negate(x))",
  "1/x:     \( invert(x))",
  "conj(x): \( conjugate(x))",
  "(x/y)*y: \( multiply( divide(x;y) ; y) )",
  "e^iπ:    \( exp( [0, 4 * (1|atan)  ] ) )"
;

test( [1,1]; [0,1] )


class Complex(private val real: Double, private val imag: Double) {
    operator fun plus(other: Complex) = Complex(real + other.real, imag + other.imag)

    operator fun times(other: Complex) = Complex(
        real * other.real - imag * other.imag,
        real * other.imag + imag * other.real
    )

    fun inv(): Complex {
        val denom = real * real + imag * imag
        return Complex(real / denom, -imag / denom)
    }

    operator fun unaryMinus() = Complex(-real, -imag)

    operator fun minus(other: Complex) = this + (-other)

    operator fun div(other: Complex) = this * other.inv()

    fun conj() = Complex(real, -imag)

    override fun toString() =
        if (imag >= 0.0) "$real + ${imag}i"
        else "$real - ${-imag}i"
}

fun main(args: Array<String>) {
    val x = Complex(1.0, 3.0)
    val y = Complex(5.0, 2.0)
    println("x     =  $x")
    println("y     =  $y")
    println("x + y =  ${x + y}")
    println("x - y =  ${x - y}")
    println("x * y =  ${x * y}")
    println("x / y =  ${x / y}")
    println("-x    =  ${-x}")
    println("1 / x =  ${x.inv()}")
    println("x*    =  ${x.conj()}")
}


mainwin 50 10

print " Adding"
call cprint cadd$(   complex$( 1, 1), complex$( 3.14159265, 1.2))
print " Multiplying"
call cprint cmulti$( complex$( 1, 1), complex$( 3.14159265, 1.2))
print " Inverting"
call cprint cinv$(   complex$( 1, 1))
print " Negating"
call cprint cneg$(   complex$( 1, 1))

end

sub cprint cx$
    print "( "; word$( cx$, 1); " + i *"; word$( cx$, 2); ")"
end sub

function complex$( a , bj )
''complex number string-object constructor
  complex$ = str$( a ) ; " " ; str$( bj )
end function

function cadd$( a$ , b$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  br = val( word$( b$ , 1 ) )
  bi = val( word$( b$ , 2 ) )
  cadd$ = complex$( ar + br , ai + bi )
end function

function cmulti$( a$ , b$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  br = val( word$( b$ , 1 ) )
  bi = val( word$( b$ , 2 ) )
  cmulti$ = complex$( ar * br - ai * bi _
                    , ar * bi + ai * br )
end function

function cneg$( a$)
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  cneg$ =complex$( 0 -ar, 0 -ai)
end function

function cinv$( a$)
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  D =ar^2 +ai^2
  cinv$ =complex$( ar /D , 0 -ai /D )
end function


--defines addition, subtraction, negation, multiplication, division, conjugation, norms, and a conversion to strgs.
complex = setmetatable({
__add = function(u, v) return complex(u.real + v.real, u.imag + v.imag) end,
__sub = function(u, v) return complex(u.real - v.real, u.imag - v.imag) end,
__mul = function(u, v) return complex(u.real * v.real - u.imag * v.imag, u.real * v.imag + u.imag * v.real) end,
__div = function(u, v) return u * complex(v.real / v.norm, -v.imag / v.norm) end,
__unm = function(u) return complex(-u.real, -u.imag) end,
__concat = function(u, v)
    if type(u) == "table" then return u.real .. " + " .. u.imag .. "i" .. v
	elseif type(u) == "string" or type(u) == "number" then return u .. v.real .. " + " .. v.imag .. "i"
	end end,
__index = function(u, index)
  local operations = {
    norm = function(u) return u.real ^ 2 + u.imag ^ 2 end,
    conj = function(u) return complex(u.real, -u.imag) end,
  }
  return operations[index] and operations[index](u)
end,
__newindex = function() error() end
}, {
__call = function(z, realpart, imagpart) return setmetatable({real = realpart, imag = imagpart}, complex) end
} )

local i, j = complex(2, 3), complex(1, 1)

print(i .. " + " .. j .. " = " .. (i+j))
print(i .. " - " .. j .. " = " .. (i-j))
print(i .. " * " .. j .. " = " .. (i*j))
print(i .. " / " .. j .. " = " .. (i/j))
print("|" .. i .. "| = " .. math.sqrt(i.norm))
print(i .. "* = " .. i.conj)


ПA	С/П	ПB	С/П	ПC	С/П	ПD	С/П	ИПC	x^2
ИПD	x^2	+	П3	ИПA	ИПC	*	ИПB	ИПD	*
+	ИП3	/	П1	ИПB	ИПC	*	ИПA	ИПD	*
-	ИП3	/	П2	ИП1	С/П	ИПA	ИПC	*	ИПB
ИПD	*	-	П1	ИПB	ИПC	*	ИПA	ИПD	*
+	П2	ИП1	С/П	ИПB	ИПD	+	П2	ИПA	ИПC
+	ИП1	С/П	ИПB	ИПD	-	П2	ИПA	ИПC	-
П1	С/П


MODULE complex;

IMPORT  InOut;

TYPE    Complex         = RECORD   R, Im    : REAL    END;

VAR     z               : ARRAY [0..3] OF Complex;

PROCEDURE ShowComplex (str  : ARRAY OF CHAR;  p  : Complex);

BEGIN
  InOut.WriteString (str);              InOut.WriteString (" = ");
  InOut.WriteReal (p.R, 6, 2);
  IF  p.Im >= 0.0  THEN  InOut.WriteString (" + ")  ELSE  InOut.WriteString (" - ")  END;
  InOut.WriteReal (ABS (p.Im), 6, 2);   InOut.WriteString (" i ");
  InOut.WriteLn;                        InOut.WriteBf
END ShowComplex;

PROCEDURE AddComplex (x1, x2 : Complex; VAR x3  : Complex);

BEGIN
  x3.R  := x1.R  + x2.R;
  x3.Im := x1.Im + x2.Im
END AddComplex;

PROCEDURE SubComplex (x1, x2 : Complex; VAR x3  : Complex);

BEGIN
  x3.R := x1.R - x2.R;
  x3.Im := x1.Im - x2.Im
END SubComplex;

PROCEDURE MulComplex (x1, x2  : Complex; VAR x3  : Complex);

BEGIN
  x3.R := x1.R * x2.R - x1.Im * x2.Im;
  x3.Im := x1.R * x2.Im + x1.Im * x2.R
END MulComplex;

PROCEDURE InvComplex (x1 : Complex; VAR x2  : Complex);

BEGIN
  x2.R := x1.R / (x1.R * x1.R + x1.Im * x1.Im);
  x2.Im := -1.0 * x1.Im / (x1.R * x1.R + x1.Im * x1.Im)
END InvComplex;

PROCEDURE NegComplex (x1 : Complex; VAR x2  : Complex);

BEGIN
  x2.R := - x1.R;       x2.Im := - x1.Im
END NegComplex;

BEGIN
  InOut.WriteString ("Enter two complex numbers : ");
  InOut.WriteBf;
  InOut.ReadReal (z[0].R);              InOut.ReadReal (z[0].Im);
  InOut.ReadReal (z[1].R);              InOut.ReadReal (z[1].Im);
  ShowComplex ("z1", z[0]);             ShowComplex ("z2", z[1]);
  InOut.WriteLn;
  AddComplex (z[0], z[1], z[2]);        ShowComplex ("z1 + z2", z[2]);
  SubComplex (z[0], z[1], z[2]);        ShowComplex ("z1 - z2", z[2]);
  MulComplex (z[0], z[1], z[2]);        ShowComplex ("z1 * z2", z[2]);
  InvComplex (z[0], z[2]);              ShowComplex ("1  / z1", z[2]);
  NegComplex (z[0], z[2]);              ShowComplex ("   - z1", z[2]);
  InOut.WriteLn
END complex.


import math

class Complex
        declare real
        declare imag

        def Complex()
                real = 0.0
                imag = 0.0
        end

        def Complex(r, i)
                real = double(r)
                imag = double(i)
        end

        def operator-(b)
                return new(Complex, this.real - b.real, this.imag - b.imag)
        end

        def operator+(b)
                return new(Complex, this.real + b.real, this.imag + b.imag)
        end

        def operator*(b)
                // FOIL of (a+bi)(c+di) with i*i = -1
                return new(Complex, this.real * b.real - this.imag * b.imag,\
                         this.real * b.imag + this.imag * b.real)
        end

        def inv()
                // 1/(a+bi) * (a-bi)/(a-bi) = 1/(a+bi) but it's more workable
                denom = this.real * this.real + this.imag * this.imag
                return new(Complex, real/denom, -imag/denom)
        end

        def neg()
                return new(Complex, -this.real, -this.imag)
        end

        def conj()
                return new(Complex, this.real, -this.imag)
        end

        def toString()
                return this.real + " + " + this.imag + " * i"
        end
end

a = new(Complex, math.pi, -5)
b = new(Complex, -1, 2.5)
println a.neg()
println a + b
println a.inv()
println a * b
println a.conj()


using System;
using System.Console;
using System.Numerics;
using System.Numerics.Complex;

module RCComplex
{
    PrettyPrint(this c : Complex) : string
    {
        mutable sign = '+';
        when (c.Imaginary < 0) sign = '-';
        $"$(c.Real) $sign $(Math.Abs(c.Imaginary))i"
    }

    Main() : void
    {
        def complex1 = Complex(1.0, 1.0);
        def complex2 = Complex(3.14159, 1.2);

        WriteLine(Add(complex1, complex2).PrettyPrint());
        WriteLine(Multiply(complex1, complex2).PrettyPrint());
        WriteLine(Negate(complex2).PrettyPrint());
        WriteLine(Reciprocal(complex2).PrettyPrint());
        WriteLine(Conjugate(complex2).PrettyPrint());
    }
}


MODULE Complex;
IMPORT Files,Out;
TYPE
        Complex* = POINTER TO ComplexDesc;
        ComplexDesc = RECORD
                r-,i-: REAL;
        END;

PROCEDURE (CONST x: Complex) Add*(CONST y: Complex): Complex;
BEGIN
        RETURN New(x.r + y.r,x.i + y.i)
END Add;

PROCEDURE (CONST x: Complex) Sub*(CONST y: Complex): Complex;
BEGIN
        RETURN New(x.r - y.r,x.i - y.i)
END Sub;

PROCEDURE (CONST x: Complex) Mul*(CONST y: Complex): Complex;
BEGIN
        RETURN New(x.r*y.r - x.i*y.i,x.r*y.i + x.i*y.r)
END Mul;

PROCEDURE (CONST x: Complex) Div*(CONST y: Complex): Complex;
VAR
        d: REAL;
BEGIN
        d := y.r * y.r + y.i * y.i;
        RETURN New((x.r*y.r + x.i*y.i)/d,(x.i*y.r - x.r*y.i)/d)
END Div;

(* Reciprocal *)
PROCEDURE (CONST x: Complex) Rec*(): Complex;
VAR
        d: REAL;
BEGIN
        d := x.r * x.r + y.i * y.i;
        RETURN New(x.r/d,(-1.0 * x.i)/d);
END Rec;

(* Conjugate *)
PROCEDURE (x: Complex) Con*(): Complex;
BEGIN
        RETURN New(x.r, (-1.0) * x.i);
END Con;

PROCEDURE (x: Complex) Out(out : Files.File);
BEGIN
        Files.WriteString(out,"(");
        Files.WriteReal(out,x.r);
        Files.WriteString(out,",");
        Files.WriteReal(out,x.i);
        Files.WriteString(out,"i)")
END Out;

PROCEDURE New(x,y: REAL): Complex;
VAR
        r: Complex;
BEGIN
        NEW(r);r.r := x;r.i := y;
        RETURN r
END New;

VAR
        r,x,y: Complex;
BEGIN
        x := New(1.5,3);
        y := New(1.0,1.0);

        Out.String("x: ");x.Out(Files.stdout);Out.Ln;
        Out.String("y: ");y.Out(Files.stdout);Out.Ln;
        r := x.Add(y);
        Out.String("x + y: ");r.Out(Files.stdout);Out.Ln;
        r := x.Sub(y);
        Out.String("x - y: ");r.Out(Files.stdout);Out.Ln;
        r := x.Mul(y);
        Out.String("x * y: ");r.Out(Files.stdout);Out.Ln;
        r := x.Div(y);
        Out.String("x / y: ");r.Out(Files.stdout);Out.Ln;
        r := y.Rec();
        Out.String("1 / y: ");r.Out(Files.stdout);Out.Ln;
        r := x.Con();
        Out.String("x': ");r.Out(Files.stdout);Out.Ln;

END Complex.


open Complex

let print_complex z =
  Printf.printf "%f + %f i\n" z.re z.im

let () =
  let a = { re = 1.0; im = 1.0 }
  and b = { re = 3.14159; im = 1.25 } in
  print_complex (add a b);
  print_complex (mul a b);
  print_complex (inv a);
  print_complex (neg a);
  print_complex (conj a)


Object Class new: Complex(re, im)

Complex method: re  @re ;
Complex method: im  @im ;

Complex method: initialize   := im := re ;
Complex method: <<  '(' <<c @re << ',' <<c @im << ')' <<c  ;

0 1 Complex new const: I

Complex method: ==(c -- b )
    c re @re == c im @im == and ;

Complex method: norm -- f
    @re sq @im sq + sqrt ;

Complex method: conj -- c
    @re @im neg Complex new ;

Complex method: +(c -- d )
    c re @re +  c im @im + Complex new ;

Complex method: -(c -- d )
    c re @re -  c im @im - Complex new ;

Complex method: *(c -- d)
    c re @re * c im @im * -  c re @im * @re c im * + Complex new ;

Complex method: inv
| n |
   @re sq @im sq + >float ->n
   @re n /   @im neg n / Complex new
;

Complex method: /( c -- d )
   c self inv * ;

Integer method: >complex  self 0 Complex new ;
Float   method: >complex  self 0 Complex new ;


(define A 0+1i) ; manually entered numbers
(define B 1+0i)

(print (+ A B))
; <== 1+i

(print (- A B))
; <== -1+i

(print (* A B))
; <== 0+i

(print (/ A B))
; <== 0+i

(define C (complex 2/7 -3)) ; functional way

(print "real part of " C " is " (car C))
; <== real part of 2/7-3i is 2/7

(print "imaginary part of " C " is " (cdr C))
; <== imaginary part of 2/7-3i is -3


c1 = .complex~new(1, 2)
c2 = .complex~new(3, 4)
r = 7

say "c1           =" c1
say "c2           =" c2
say "r            =" r
say "-c1          =" (-c1)
say "c1 + r       =" c1 + r
say "c1 + c2      =" c1 + c2
say "c1 - r       =" c1 - r
say "c1 - c2      =" c1 - c2
say "c1 * r       =" c1 * r
say "c1 * c2      =" c1 * c2
say "inv(c1)      =" c1~inv
say "conj(c1)     =" c1~conjugate
say "c1 / r       =" c1 / r
say "c1 / c2      =" c1 / c2
say "c1 == c1     =" (c1 == c1)
say "c1 == c2     =" (c1 == c2)

::class complex
::method init
  expose r i
  use strict arg r, i = 0

-- complex instances are immutable, so these are
-- read only attributes
::attribute r GET
::attribute i GET

::method negative
  expose r i
  return self~class~new(-r, -i)

::method add
  expose r i
  use strict arg other
  if other~isa(.complex) then
     return self~class~new(r + other~r, i + other~i)
  else return self~class~new(r + other, i)

::method subtract
  expose r i
  use strict arg other
  if other~isa(.complex) then
     return self~class~new(r - other~r, i - other~i)
  else return self~class~new(r - other, i)

::method times
  expose r i
  use strict arg other
  if other~isa(.complex) then
     return self~class~new(r * other~r - i * other~i, r * other~i + i * other~r)
  else return self~class~new(r * other, i * other)

::method inv
  expose r i
  denom = r * r + i * i
  return self~class~new(r/denom,-i/denom)

::method conjugate
  expose r i
  return self~class~new(r, -i)

::method divide
  use strict arg other
  -- this is easier if everything is a complex number
  if \other~isA(.complex) then other = .complex~new(other)
  -- division is multiplication with the inversion
  return self * other~inv

::method "=="
  expose r i
  use strict arg other

  if \other~isa(.complex) then return .false
  -- Note:  these are numeric comparisons, so we're using the "="
  -- method so those are handled correctly
  return r = other~r & i = other~i

::method "\=="
  use strict arg other
  return \self~"\=="(other)

::method "="
  -- this is equivalent of "=="
  forward message("==")

::method "\="
  -- this is equivalent of "\=="
  forward message("\==")

::method "<>"
  -- this is equivalent of "\=="
  forward message("\==")

::method "><"
  -- this is equivalent of "\=="
  forward message("\==")

-- some operator overrides -- these only work if the left-hand-side of the
-- subexpression is a quaternion
::method "*"
  forward message("TIMES")

::method "/"
  forward message("DIVIDE")

::method "-"
  -- need to check if this is a prefix minus or a subtract
  if arg() == 0 then
      forward message("NEGATIVE")
  else
      forward message("SUBTRACT")

::method "+"
  -- need to check if this is a prefix plus or an addition
  if arg() == 0 then
      return self  -- we can return this copy since it is immutable
  else
      forward message("ADD")

::method string
  expose r i
  return r self~formatnumber(i)"i"

::method formatnumber private
  use arg value
  if value > 0 then return "+" value
  else return "-" value~abs

-- override hashcode for collection class hash uses
::method hashCode
  expose r i
  return r~hashcode~bitxor(i~hashcode)


'COMPLEX OPERATIONS
'=================

type tcomplex double x,y

class Complex
'============

  has tcomplex
  static sys i,pp
  static tcomplex accum[32]

def operands
  tcomplex*a,*b
  @[email protected]+i
  if pp then
    @[email protected]+sizeof accum
    pp=0
  else
    @[email protected]
  end if
end def

method "load"()
  operands
  a.x=b.x
  a.y=b.y
end method

method "push"()
  i+=sizeof accum
end method

method "pop"()
  pp=1
  i-=sizeof accum
end method

method "="()
  operands
  b.x=a.x
  b.y=a.y
end method

method "+"()
  operands
  a.x+=b.x
  a.y+=b.y
end method

method "-"()
  operands
  a.x-=b.x
  a.y-=b.y
end method

method "*"()
  operands
  double d
  d=a.x
  a.x = a.x * b.x - a.y * b.y
  a.y = a.y * b.x + d   * b.y
end method

method "/"()
  operands
  double d,v
  v=1/(b.x * b.x + b.y * b.y)
  d=a.x
  a.x = (a.x * b.x + a.y * b.y) * v
  a.y = (a.y * b.x - d   * b.y) * v
end method

method power(double n)
  operands
  'Using DeMoivre theorem
  double r,an,mg
  r = hypot(b.x,b.y)
  mg = r^n
  if b.x=0 then
    ay=.5*pi
    if b.y<0 then ay=-ay
  else
    an = atan(b.y,b.x)
  end if
  an  *= n
  a.x  = mg * cos(an)
  a.y  = mg * sin(an)
end method

method show() as string
  return str(x,14) ", " str(y,14)
end method

end class

'#recordof complexop

'====
'TEST
'====

complex z1,z2,z3,z4,z5

'ENTER VALUES

z1 <=  0, 0
z2 <=  2, 1
z3 <= -2, 1
z4 <=  2, 4
z5 <=  1, 1

'EVALUATE COMPLEX EXPRESSIONS

z1 =  z2 * z3
print "Z1 = "+z1.show 'RESULT  -5.0, 0

z1 = z3+(z2.power(2))
print "Z1 = "+z1.show  'RESULT  1.0, 5.0

z1 = z5/z4
print "Z1 = "+z1.show  'RESULT 0.3, 0.1

z1 = z5/z1
print "Z1 = "+z1.show  'RESULT 2.0, 4.0

z1 = z2/z4
print "Z1 = "+z1.show  'RESULT  -0.4, -0.3

z1 = z1*z4
print "Z1 = "+z1.show  'RESULT  2.0, 1.0


add(a,b)=a+b;
mult(a,b)=a*b;
neg(a)=-a;
inv(a)=1/a;


program complexDemo(output);

const
	{ I experienced some hiccups with -1.0 using GPC (GNU Pascal Compiler) }
	negativeOne = -1.0;

type
	line = string(80);

{ as per task requirements wrap arithmetic operations into separate functions }
function sum(protected x, y: complex): complex;
begin
	sum := x + y
end;

function product(protected x, y: complex): complex;
begin
	product := x * y
end;

function negative(protected x: complex): complex;
begin
	negative := -x
end;

function inverse(protected x: complex): complex;
begin
	inverse := x ** negativeOne
end;

{ only this function is not covered by Extended Pascal, ISO 10206 }
function conjugation(protected x: complex): complex;
begin
	conjugation := cmplx(re(x), im(x) * negativeOne)
end;

{ --- test suite ------------------------------------------------------------- }
function asString(protected x: complex): line;
const
	totalWidth = 5;
	fractionDigits = 2;
var
	result: line;
begin
	writeStr(result, '(', re(x):totalWidth:fractionDigits, ', ',
		im(x):totalWidth:fractionDigits, ')');
	asString := result
end;

{ === MAIN =================================================================== }
var
	x: complex;
	{ for demonstration purposes: how to initialize complex variables }
	y: complex value cmplx(1.0, 4.0);
	z: complex value polar(exp(1.0), 3.14159265358979);
begin
	x := cmplx(-3, 2);

	writeLn(asString(x), ' + ', asString(y), ' = ', asString(sum(x, y)));
	writeLn(asString(x), ' * ', asString(z), ' = ', asString(product(x, z)));

	writeLn;

	writeLn('               −', asString(z), '  = ', asString(negative(z)));
	writeLn('        inverse(', asString(z), ') = ', asString(inverse(z)));
	writeLn('    conjugation(', asString(y), ') = ', asString(conjugation(y)));
end.


use Math::Complex;
my $a = 1 + 1*i;
my $b = 3.14159 + 1.25*i;

print "$_\n" foreach
    $a + $b,    # addition
    $a * $b,    # multiplication
    -$a,        # negation
    1 / $a,     # multiplicative inverse
    ~$a;        # complex conjugate


-- demo\rosetta\ArithComplex.exw
with javascript_semantics
include complex.e
complex a = complex_new(1,1),  -- (or just {1,1})
        b = complex_new(3.14159,1.25),
        c = complex_new(1,0),
        d = complex_new(0,1)
printf(1,"a = %s\n",{complex_sprint(a)})
printf(1,"b = %s\n",{complex_sprint(b)})
printf(1,"c = %s\n",{complex_sprint(c)})
printf(1,"d = %s\n",{complex_sprint(d)})
printf(1,"a+b = %s\n",{complex_sprint(complex_add(a,b))})
printf(1,"a*b = %s\n",{complex_sprint(complex_mul(a,b))})
printf(1,"1/a = %s\n",{complex_sprint(complex_inv(a))})
printf(1,"c/a = %s\n",{complex_sprint(complex_div(c,a))})
printf(1,"c-a = %s\n",{complex_sprint(complex_sub(c,a))})
printf(1,"d-a = %s\n",{complex_sprint(complex_sub(d,a))})
printf(1,"-a = %s\n",{complex_sprint(complex_neg(a))})
printf(1,"conj a = %s\n",{complex_sprint(complex_conjugate(a))})


(load "@lib/math.l")

(de addComplex (A B)
   (cons
      (+ (car A) (car B))        # Real
      (+ (cdr A) (cdr B)) ) )    # Imag

(de mulComplex (A B)
   (cons
      (-
         (*/ (car A) (car B) 1.0)
         (*/ (cdr A) (cdr B) 1.0) )
      (+
         (*/ (car A) (cdr B) 1.0)
         (*/ (cdr A) (car B) 1.0) ) ) )

(de invComplex (A)
   (let Denom
      (+
         (*/ (car A) (car A) 1.0)
         (*/ (cdr A) (cdr A) 1.0) )
      (cons
         (*/ (car A) 1.0 Denom)
         (- (*/ (cdr A) 1.0 Denom)) ) ) )

(de negComplex (A)
   (cons (- (car A)) (- (cdr A))) )

(de fmtComplex (A)
   (pack
      (round (car A) (dec *Scl))
      (and (gt0 (cdr A)) "+")
      (round (cdr A) (dec *Scl))
      "i" ) )

(let (A (1.0 . 1.0)  B (cons pi 1.2))
   (prinl "A = " (fmtComplex A))
   (prinl "B = " (fmtComplex B))
   (prinl "A+B = " (fmtComplex (addComplex A B)))
   (prinl "A*B = " (fmtComplex (mulComplex A B)))
   (prinl "1/A = " (fmtComplex (invComplex A)))
   (prinl "-A = " (fmtComplex (negComplex A))) )


/* PL/I complex numbers may be integer or floating-point.  */
/* In this example, the variables are floating-pint.       */
/* For integer variables, change 'float' to 'fixed binary' */

declare (a, b) complex float;
a = 2+5i;
b = 7-6i;

put skip list (a+b);
put skip list (a - b);
put skip list (a*b);
put skip list (a/b);
put skip list (a**b);
put skip list (1/a);
put skip list (conjg(a)); /* gives the conjugate of 'a'. */

/* Functions exist for extracting the real and imaginary parts */
/* of a complex number. */

/* As well, trigonometric functions may be used with complex  */
/* numbers, such as SIN, COS, TAN, ATAN, and so on.           */


%Adding two complex numbers
/addcomp{
/x exch def
/y exch def
/z [0 0] def
z 0 x 0 get y 0 get add put
z 1 x 1 get y 1 get add put
z pstack
}def

%Subtracting one complex number from another
/subcomp{
/x exch def
/y exch def
/z [0 0] def
z 0 x 0 get y 0 get sub put
z 1 x 1 get y 1 get sub put
z pstack
}def

%Multiplying two complex numbers
/mulcomp{
/x exch def
/y exch def
/z [0 0] def
z 0 x 0 get y 0 get mul x 1 get y 1 get mul sub  put
z 1 x 1 get y 0 get mul x 0 get y 1 get mul add put
z pstack
}def

%Negating a complex number
/negcomp{
/x exch def
/z [0 0] def
z 0 x 0 get neg put
z 1 x 1 get neg put
z pstack
}def

%Inverting a complex number
/invcomp{
/x exch def
/z [0 0] def
z 0 x 0 get x 0 get 2 exp x 1 get 2 exp add div put
z 0 x 1 get neg x 0 get 2 exp x 1 get 2 exp add div put
z pstack
}def


class Complex {
  [Double]$x
  [Double]$y
  Complex() {
      $this.x = 0
      $this.y = 0
  }
  Complex([Double]$x, [Double]$y) {
      $this.x = $x
      $this.y = $y
  }
  [Double]abs2() {return $this.x*$this.x + $this.y*$this.y}
  [Double]abs() {return [math]::sqrt($this.abs2())}
  static [Complex]add([Complex]$m,[Complex]$n) {return [Complex]::new($m.x+$n.x, $m.y+$n.y)}
  static [Complex]mul([Complex]$m,[Complex]$n) {return [Complex]::new($m.x*$n.x - $m.y*$n.y, $m.x*$n.y + $n.x*$m.y)}
  [Complex]mul([Double]$k) {return [Complex]::new($k*$this.x, $k*$this.y)}
  [Complex]negate() {return $this.mul(-1)}
  [Complex]conjugate() {return [Complex]::new($this.x, -$this.y)}
  [Complex]inverse() {return $this.conjugate().mul(1/$this.abs2())}
  [String]show() {
    if(0 -ge $this.y) {
        return "$($this.x)+$($this.y)i"
    } else {
        return "$($this.x)$($this.y)i"
    }
  }
  static [String]show([Complex]$other) {
    return $other.show()
  }
}
$m = [complex]::new(3, 4)
$n = [complex]::new(7, 6)
"`$m: $($m.show())"
"`$n: $($n.show())"
"`$m + `$n: $([complex]::show([complex]::add($m,$n)))"
"`$m * `$n: $([complex]::show([complex]::mul($m,$n)))"
"negate `$m: $($m.negate().show())"
"1/`$m: $([complex]::show($m.inverse()))"
"conjugate `$m: $([complex]::show($m.conjugate()))"


Structure Complex
  real.d
  imag.d
EndStructure

Procedure Add_Complex(*A.Complex, *B.Complex)
  Protected *R.Complex=AllocateMemory(SizeOf(Complex))
  If *R
    *R\real=*A\real+*B\real
    *R\imag=*A\imag+*B\imag
  EndIf
  ProcedureReturn *R
EndProcedure

Procedure Inv_Complex(*A.Complex)
  Protected *R.Complex=AllocateMemory(SizeOf(Complex)), denom.d
  If *R
    denom  = *A\real * *A\real + *A\imag * *A\imag
    *R\real= *A\real / denom
    *R\imag=-*A\imag / denom
  EndIf
  ProcedureReturn *R
EndProcedure

Procedure Mul_Complex(*A.Complex, *B.Complex)
  Protected *R.Complex=AllocateMemory(SizeOf(Complex))
  If *R
    *R\real=*A\real * *B\real - *A\imag * *B\imag
    *R\imag=*A\real * *B\imag + *A\imag * *B\real
  EndIf
  ProcedureReturn *R
EndProcedure

Procedure Neg_Complex(*A.Complex)
  Protected *R.Complex=AllocateMemory(SizeOf(Complex))
  If *R
    *R\real=-*A\real
    *R\imag=-*A\imag
  EndIf
  ProcedureReturn *R
EndProcedure

Procedure ShowAndFree(Header$, *Complex.Complex)
  If *Complex
    Protected.d i=*Complex\imag, r=*Complex\real
    Print(LSet(Header$,7))
    Print("= "+StrD(r,3))
    If i>=0:  Print(" + ")
    Else:     Print(" - ")
    EndIf
    PrintN(StrD(Abs(i),3)+"i")
    FreeMemory(*Complex)
  EndIf
EndProcedure

If OpenConsole()
  Define.Complex a, b, *c
  a\real=1.0: a\imag=1.0
  b\real=#PI: b\imag=1.2
  *c=Add_Complex(a,b):  ShowAndFree("a+b",    *c)
  *c=Mul_Complex(a,b):  ShowAndFree("a*b",    *c)
  *c=Inv_Complex(a):    ShowAndFree("Inv(a)", *c)
  *c=Neg_Complex(a):    ShowAndFree("-a",     *c)
  Print(#CRLF$+"Press ENTER to exit"):Input()
EndIf


#lang racket

(define a 3+4i)
(define b 8+0i)

(+ a b)       ; addition
(- a b)       ; subtraction
(/ a b)       ; division
(* a b)       ; multiplication
(- a)         ; negation
(/ 1 a)       ; reciprocal
(conjugate a) ; conjugation


my $a = 1 + i;
my $b = pi + 1.25i;

.say for $a + $b, $a * $b, -$a, 1 / $a, $a.conj;
.say for $a.abs, $a.sqrt, $a.re, $a.im;


#include "gmp.h"

void agm (const mpf_t in1, const mpf_t in2, mpf_t out1, mpf_t out2) {
	mpf_add (out1, in1, in2);
	mpf_div_ui (out1, out1, 2);
	mpf_mul (out2, in1, in2);
	mpf_sqrt (out2, out2);
}

int main (void) {
	mpf_set_default_prec (300000);
	mpf_t x0, y0, resA, resB, Z, var;

	mpf_init_set_ui (x0, 1);
	mpf_init_set_d (y0, 0.5);
	mpf_sqrt (y0, y0);
	mpf_init (resA);
	mpf_init (resB);
	mpf_init_set_d (Z, 0.25);
	mpf_init (var);

	int n = 1;
        int i;
	for(i=0; i<8; i++){
		agm(x0, y0, resA, resB);
		mpf_sub(var, resA, x0);
		mpf_mul(var, var, var);
		mpf_mul_ui(var, var, n);
		mpf_sub(Z, Z, var);
		n += n;
		agm(resA, resB, x0, y0);
		mpf_sub(var, x0, resA);
		mpf_mul(var, var, var);
		mpf_mul_ui(var, var, n);
		mpf_sub(Z, Z, var);
		n += n;
	}
	mpf_mul(x0, x0, x0);
	mpf_div(x0, x0, Z);
	gmp_printf ("%.100000Ff\n", x0);
	return 0;
}


/*REXX program  demonstrates how to support some  math functions  for  complex numbers. */
x = '(5,3i)'                                     /*define  X    ─── can use  I i J or j */
y = "( .5,  6j)"                                 /*define  Y         "   "   " " "  " " */

say '      addition:   '        x        " + "         y         ' = '          Cadd(x, y)
say '   subtraction:   '        x        " - "         y         ' = '          Csub(x, y)
say 'multiplication:   '        x        " * "         y         ' = '          Cmul(x, y)
say '      division:   '        x        " ÷ "         y         ' = '          Cdiv(x, y)
say '       inverse:   '        x        "                         = "          Cinv(x, y)
say '  conjugate of:   '        x        "                         = "          Conj(x, y)
say '   negation of:   '        x        "                         = "          Cneg(x, y)
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
Conj: procedure; parse arg a ',' b,c ',' d;   call C#;    return C$(  a      ,  -b    )
Cadd: procedure; parse arg a ',' b,c ',' d;   call C#;    return C$(  a+c    ,   b+d  )
Csub: procedure; parse arg a ',' b,c ',' d;   call C#;    return C$(  a-c    ,   b-d  )
Cmul: procedure; parse arg a ',' b,c ',' d;   call C#;    return C$( ac-bd   ,   bc+ad)
Cdiv: procedure; parse arg a ',' b,c ',' d;   call C#;    return C$((ac+bd)/s,  (bc-ad)/s)
Cinv: return  Cdiv(1,  arg(1))
Cneg: return  Cmul(arg(1), -1)
C_:   return  word(translate(arg(1), , '{[(JjIi)]}')  0,  1)                /*get # or 0*/
C#:   a=C_(a); b=C_(b); c=C_(c); d=C_(d); ac=a*c; ad=a*d; bc=b*c; bd=b*d;s=c*c+d*d; return
C$:   parse arg r,c;    _='['r;   if c\=0  then _=_","c'j';   return _"]"   /*uses  j   */


using System;
using System.Numerics;

class AgmPie
{
    static BigInteger IntSqRoot(BigInteger valu, BigInteger guess)
    {
        BigInteger term; do {
            term = valu / guess; if (BigInteger.Abs(term - guess) <= 1) break;
            guess += term; guess >>= 1;
        } while (true); return guess;
    }

    static BigInteger ISR(BigInteger term, BigInteger guess)
    {
        BigInteger valu = term * guess; do {
            if (BigInteger.Abs(term - guess) <= 1) break;
            guess += term; guess >>= 1; term = valu / guess;
        } while (true); return guess;
    }

    static BigInteger CalcAGM(BigInteger lam, BigInteger gm, ref BigInteger z,
                              BigInteger ep)
    {
        BigInteger am, zi; ulong n = 1; do {
            am = (lam + gm) >> 1; gm = ISR(lam, gm);
            BigInteger v = am - lam; if ((zi = v * v * n) < ep) break;
            z -= zi; n <<= 1; lam = am;
        } while (true); return am;
    }

    static BigInteger BIP(int exp, ulong man = 1)
    {
        BigInteger rv = BigInteger.Pow(10, exp); return man == 1 ? rv : man * rv;
    }

    static void Main(string[] args)
    {
        int d = 25000;
        if (args.Length > 0)
        {
            int.TryParse(args[0], out d);
            if (d < 1 || d > 999999) d = 25000;
        }
        DateTime st = DateTime.Now;
        BigInteger am = BIP(d),
          gm = IntSqRoot(BIP(d + d - 1, 5),
                             BIP(d - 15, (ulong)(Math.Sqrt(0.5) * 1e+15))),
          z = BIP(d + d - 2, 25),
          agm = CalcAGM(am, gm, ref z, BIP(d + 1)),
          pi = agm * agm * BIP(d - 2) / z;
        Console.WriteLine("Computation time: {0:0.0000} seconds ",
                             (DateTime.Now - st).TotalMilliseconds / 1000);
        string s = pi.ToString();
        Console.WriteLine("{0}.{1}", s[0], s.Substring(1));
        if (System.Diagnostics.Debugger.IsAttached) Console.ReadKey();
    }
}


F agm(a0, g0, tolerance = 1e-10)
   V an = (a0 + g0) / 2.0
   V gn = sqrt(a0 * g0)
   L abs(an - gn) > tolerance
      (an, gn) = ((an + gn) / 2.0, sqrt(an * gn))
   R an

print(agm(1, 1 / sqrt(2)))


# Four ways to write complex numbers:
a = Complex(1, 1)       # 1. call Kernel#Complex
i = Complex::I          # 2. use Complex::I
b = 3.14159 + 1.25 * i
c = '1/2+3/4i'.to_c     # 3. Use the .to_c method from String, result ((1/2)+(3/4)*i)
c =  1.0/2+3/4i         # (0.5-(3/4)*i)

# Operations:
puts a + b              # addition
puts a * b              # multiplication
puts -a                 # negation
puts 1.quo a            # multiplicative inverse
puts a.conjugate        # complex conjugate
puts a.conj             # alias for complex conjugate


#include <gmpxx.h>
#include <chrono>

using namespace std;
using namespace chrono;

void agm(mpf_class& rop1, mpf_class& rop2, const mpf_class& op1,
        const mpf_class& op2)
{
    rop1 = (op1 + op2) / 2;
    rop2 = op1 * op2;
    mpf_sqrt(rop2.get_mpf_t(), rop2.get_mpf_t());
}

int main(void)
{
    auto st = steady_clock::now();
    mpf_set_default_prec(300000);
    mpf_class x0, y0, resA, resB, Z;

    x0 = 1;
    y0 = 0.5;
    Z  = 0.25;
    mpf_sqrt(y0.get_mpf_t(), y0.get_mpf_t());

    int n = 1;
    for (int i = 0; i < 8; i++) {
        agm(resA, resB, x0, y0);
        Z -= n * (resA - x0) * (resA - x0);
        n *= 2;

        agm(x0, y0, resA, resB);
        Z -= n * (x0 - resA) * (x0 - resA);
        n *= 2;
    }

    x0 = x0 * x0 / Z;
    printf("Took %f ms for computation.\n", duration<double>(steady_clock::now() - st).count() * 1000.0);
    st = steady_clock::now();
    gmp_printf ("%.89412Ff\n", x0.get_mpf_t());
    printf("Took %f ms for output.\n", duration<double>(steady_clock::now() - st).count() * 1000.0);
    return 0;
}


(ns async-example.core
  (:use [criterium.core])
  (:gen-class))

; Java Arbitray Precision Library
(import '(org.apfloat Apfloat ApfloatMath))

(def precision 8192)

; Define big constants (i.e. 1, 2, 4, 0.5, .25, 1/sqrt(2))
(def one (Apfloat. 1M precision))
(def two (Apfloat. 2M precision))
(def four (Apfloat. 4M precision))
(def half (Apfloat. 0.5M precision))
(def quarter (Apfloat. 0.25M precision))
(def isqrt2 (.divide one  (ApfloatMath/pow two half)))

(defn compute-pi [iterations]
    (loop [i 0, n one, [a g] [one isqrt2], z quarter]
        (if (> i iterations)
          (.divide (.multiply a a) z)
          (let [x [(.multiply (.add a g) half) (ApfloatMath/pow (.multiply a g) half)]
                v (.subtract (first x) a)]
            (recur (inc i) (.add n n) x (.subtract z (.multiply (.multiply v v) n)))))))

(doseq [q (partition-all 200 (str (compute-pi 18)))]
    (println (apply str q)))


AGM      CSECT
         USING  AGM,R13
SAVEAREA B      STM-SAVEAREA(R15)
         DC     17F'0'
         DC     CL8'AGM'
STM      STM    R14,R12,12(R13)
         ST     R13,4(R15)
         ST     R15,8(R13)
         LR     R13,R15
         ZAP    A,K                a=1
         ZAP    PWL8,K
         MP     PWL8,K
         DP     PWL8,=P'2'
         ZAP    PWL8,PWL8(7)
         BAL    R14,SQRT
         ZAP    G,PWL8             g=sqrt(1/2)
WHILE1   EQU    *                  while a!=g
         ZAP    PWL8,A
         SP     PWL8,G
         CP     PWL8,=P'0'         (a-g)!=0
         BE     EWHILE1
         ZAP    PWL8,A
         AP     PWL8,G
         DP     PWL8,=P'2'
         ZAP    AN,PWL8(7)         an=(a+g)/2
         ZAP    PWL8,A
         MP     PWL8,G
         BAL    R14,SQRT
         ZAP    G,PWL8             g=sqrt(a*g)
         ZAP    A,AN               a=an
         B      WHILE1
EWHILE1  EQU    *
         ZAP    PWL8,A
         UNPK   ZWL16,PWL8
         MVC    CWL16,ZWL16
         OI     CWL16+15,X'F0'
         MVI    CWL16,C'+'
         CP     PWL8,=P'0'
         BNM    *+8
         MVI    CWL16,C'-'
         MVC    CWL80+0(15),CWL16
         MVC    CWL80+9(1),=C'.'   /k  (15-6=9)
         XPRNT  CWL80,80           display a
         L      R13,4(0,R13)
         LM     R14,R12,12(R13)
         XR     R15,R15
         BR     R14
         DS     0F
K        DC     PL8'1000000'       10^6
A        DS     PL8
G        DS     PL8
AN       DS     PL8
* ****** SQRT   *******************
SQRT     CNOP   0,4                function sqrt(x)
         ZAP    X,PWL8
         ZAP    X0,=P'0'           x0=0
         ZAP    X1,=P'1'           x1=1
WHILE2   EQU    *                  while x0!=x1
         ZAP    PWL8,X0
         SP     PWL8,X1
         CP     PWL8,=P'0'         (x0-x1)!=0
         BE     EWHILE2
         ZAP    X0,X1              x0=x1
         ZAP    PWL16,X
         DP     PWL16,X1
         ZAP    XW,PWL16(8)        xw=x/x1
         ZAP    PWL8,X1
         AP     PWL8,XW
         DP     PWL8,=P'2'
         ZAP    PWL8,PWL8(7)
         ZAP    X2,PWL8            x2=(x1+xw)/2
         ZAP    X1,X2              x1=x2
         B      WHILE2
EWHILE2  EQU    *
         ZAP    PWL8,X1            return x1
         BR     R14
         DS     0F
X        DS     PL8
X0       DS     PL8
X1       DS     PL8
X2       DS     PL8
XW       DS     PL8
* end SQRT
PWL8     DC     PL8'0'
PWL16    DC     PL16'0'
CWL80    DC     CL80' '
CWL16    DS     CL16
ZWL16    DS     ZL16
         LTORG
         YREGS
         END    AGM


: epsilon  1.0e-12 ;

with: n

: iter  \ n1 n2 -- n1 n2
    2dup * sqrt >r + 2 / r> ;

: agn  \ n1 n2 -- n
    repeat  iter  2dup epsilon ~= not while!  drop ;

"agn(1, 1/sqrt(2)) = " .  1  1 2 sqrt /  agn  "%.10f" s:strfmt . cr

;with
bye


INCLUDE "H6:REALMATH.ACT"

PROC Agm(REAL POINTER a0,g0,result)
  REAL a,g,prevA,tmp,r2

  RealAssign(a0,a)
  RealAssign(g0,g)
  IntToReal(2,r2)
  DO
    RealAssign(a,prevA)
    RealAdd(a,g,tmp)
    RealDiv(tmp,r2,a)
    RealMult(prevA,g,tmp)
    Sqrt(tmp,g)
    IF RealGreaterOrEqual(a,prevA) THEN
      EXIT
    FI
  OD
  RealAssign(a,result)
RETURN

PROC Main()
  REAL r1,r2,tmp,g,res

  Put(125) PutE() ;clear screen

  MathInit()
  IntToReal(1,r1)
  IntToReal(2,r2)
  Sqrt(r2,tmp)
  RealDiv(r1,tmp,g)
  Agm(r1,g,res)

  Print("agm(") PrintR(r1)
  Print(",") PrintR(g)
  Print(")=") PrintRE(res)
RETURN


extern crate num;
use num::complex::Complex;

fn main() {
    // two valid forms of definition
    let a = Complex {re:-4.0, im: 5.0};
    let b = Complex::new(1.0, 1.0);

    println!("   a    = {}", a);
    println!("   b    = {}", b);
    println!(" a + b  = {}", a + b);
    println!(" a * b  = {}", a * b);
    println!(" 1 / a  = {}", a.inv());
    println!("  -a    = {}", -a);
    println!("conj(a) = {}", a.conj());
}


package org.rosettacode

package object ArithmeticComplex {
  val i = Complex(0, 1)

  implicit def fromDouble(d: Double) = Complex(d)
  implicit def fromInt(i: Int) = Complex(i.toDouble)
}

package ArithmeticComplex {
  case class Complex(real: Double = 0.0, imag: Double = 0.0) {
    def this(s: String) =
      this("[\\d.]+(?!i)".r findFirstIn s getOrElse "0" toDouble,
           "[\\d.]+(?=i)".r findFirstIn s getOrElse "0" toDouble)

    def +(b: Complex) = Complex(real + b.real, imag + b.imag)
    def -(b: Complex) = Complex(real - b.real, imag - b.imag)
    def *(b: Complex) = Complex(real * b.real - imag * b.imag, real * b.imag + imag * b.real)
    def inverse = {
      val denom = real * real + imag * imag
      Complex(real / denom, -imag / denom)
    }
    def /(b: Complex) = this * b.inverse
    def unary_- = Complex(-real, -imag)
    lazy val abs = math.hypot(real, imag)
    override def toString = real + " + " + imag + "i"

    def i = { require(imag == 0.0); Complex(imag = real) }
  }

  object Complex {
    def apply(s: String) = new Complex(s)
    def fromPolar(rho:Double, theta:Double) = Complex(rho*math.cos(theta), rho*math.sin(theta))
  }
}


(load "bf.fasl")

;;(setf mma::bigfloat-bin-prec 1000)

(let ((A (mma:bigfloat-convert 1.0d0))
      (N (mma:bigfloat-convert 1.0d0))
      (Z (mma:bigfloat-convert 0.25d0))
      (G (mma:bigfloat-/ (mma:bigfloat-convert 1.0d0)
			 (mma:bigfloat-sqrt (mma:bigfloat-convert 2.0d0)))))
  (loop repeat 18 do
       (let* ((X1  (mma:bigfloat-* (mma:bigfloat-+ A G) (mma:bigfloat-convert 0.5d0)))
	      (X2 (mma:bigfloat-sqrt (mma:bigfloat-* A G)))
	      (V (mma:bigfloat-- X1 A)))
	 (setf Z (mma:bigfloat-- Z  (mma:bigfloat-* (mma:bigfloat-/ (mma:bigfloat-* V V) (mma:bigfloat-convert 1.0d0)) N) ))
	 (setf N (mma:bigfloat-+ N N))
	 (setf A X1)
	 (setf G X2)))
  (mma:bigfloat-/ (mma:bigfloat-* A A) Z))


import std.bigint;
import std.conv;
import std.math;
import std.stdio;

BigInt IntSqRoot(BigInt value, BigInt guess) {
    BigInt term;
    do {
        term = value / guess;
        auto temp = term - guess;
        if (temp < 0) {
            temp = -temp;
        }
        if (temp <= 1) {
            break;
        }
        guess += term;
        guess >>= 1;
        term = value / guess;
    } while (true);
    return guess;
}

BigInt ISR(BigInt term, BigInt guess) {
    BigInt value = term * guess;
    do {
        auto temp = term - guess;
        if (temp < 0) {
            temp = -temp;
        }
        if (temp <= 1) {
            break;
        }
        guess += term;
        guess >>= 1;
        term = value / guess;
    } while (true);
    return guess;
}

BigInt CalcAGM(BigInt lam, BigInt gm, ref BigInt z, BigInt ep) {
    BigInt am, zi;
    ulong n = 1;
    do {
        am = (lam + gm) >> 1;
        gm = ISR(lam, gm);
        BigInt v = am - lam;
        if ((zi = v * v * n) < ep) {
            break;
        }
        z -= zi;
        n <<= 1;
        lam = am;
    } while(true);
    return am;
}

BigInt BIP(int exp, ulong man = 1) {
    BigInt rv = BigInt(10) ^^ exp;
    return man == 1 ? rv : man * rv;
}

void main() {
    int d = 25000;
    // ignore setting d from commandline for now
    BigInt am = BIP(d);
    BigInt gm = IntSqRoot(BIP(d + d - 1, 5), BIP(d - 15, cast(ulong)(sqrt(0.5) * 1e15)));
    BigInt z = BIP(d + d - 2, 25);
    BigInt agm = CalcAGM(am, gm, z, BIP(d + 1));
    BigInt pi = agm * agm * BIP(d - 2) / z;

    string piStr = to!string(pi);
    writeln(piStr[0], '.', piStr[1..$]);
}


with Ada.Text_IO, Ada.Numerics.Generic_Elementary_Functions;

procedure Arith_Geom_Mean is

   type Num is digits 18; -- the largest value gnat/gcc allows
   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;
         -- Num'Epsilon denotes the relative error when performing arithmetic over Num
      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;


BEGIN
   PROC agm = (LONG REAL x, y) LONG REAL :
   BEGIN
      IF x < LONG 0.0 OR y < LONG 0.0 THEN -LONG 1.0
      ELIF x + y = LONG 0.0 THEN LONG 0.0		CO Edge cases CO
      ELSE
	 LONG REAL a := x, g := y;
	 LONG REAL epsilon := a + g;
	 LONG REAL next a := (a + g) / LONG 2.0, next g := long sqrt (a * g);
	 LONG REAL next epsilon := ABS (a - g);
	 WHILE next epsilon < epsilon
	 DO
	    print ((epsilon, "   ", next epsilon, newline));
	    epsilon := next epsilon;
	    a := next a; g := next g;
	    next a := (a + g) / LONG 2.0; next g := long sqrt (a * g);
	    next epsilon := ABS (a - g)
	 OD;
	 a
      FI
   END;
   printf (($l(-35,33)l$, agm (LONG 1.0, LONG 1.0 / long sqrt (LONG 2.0))))
END


(define a 1+i)
(define b 3.14159+1.25i)

(define c (+ a b))
(define c (* a b))
(define c (/ 1 a))
(define c (- a))


$ include "seed7_05.s7i";
  include "float.s7i";
  include "complex.s7i";

const proc: main is func
  local
    var complex: a is complex(1.0, 1.0);
    var complex: b is complex(3.14159, 1.2);
  begin
    writeln("a=" <& a digits 5);
    writeln("b=" <& b digits 5);
    # addition
    writeln("a+b=" <& a + b digits 5);
    # multiplication
    writeln("a*b=" <& a * b digits 5);
    # inversion
    writeln("1/a=" <& complex(1.0) / a digits 5);
    # negation
    writeln("-a=" <& -a digits 5);
  end func;


program Calculate_Pi;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Velthuis.BigIntegers,
  System.Diagnostics;

function IntSqRoot(value, guess: BigInteger): BigInteger;
var
  term: BigInteger;
begin
  while True do
  begin
    term := value div guess;
    if (BigInteger.Abs(term - guess) <= 1) then
      break;
    guess := (guess + term) shr 1;
  end;
  Result := guess;
end;

function ISR(term, guess: BigInteger): BigInteger;
var
  value: BigInteger;
begin
  value := term * guess;
  while (True) do
  begin
    if (BigInteger.Abs(term - guess) <= 1) then
      break;
    guess := (guess + term) shr 1;
    term := value div guess;
  end;
  Result := guess;
end;

function CalcAGM(lam, gm: BigInteger; var z: BigInteger; ep: BigInteger): BigInteger;
var
  am, zi, v: BigInteger;
  n: UInt32;
begin
  n := 1;
  while True do
  begin
    am := (lam + gm) shr 1;
    gm := ISR(lam, gm);
    v := am - lam;
    zi := v * v * n;
    if (zi < ep) then
      break;
    z := z - zi;
    n := n shl 1;
    lam := am;
  end;
  Result := am;
end;

function BIP(exp: Integer; man: UInt32 = 1): BigInteger;
begin
  Result := man * BigInteger.Pow(10, exp);
end;

function Compress(val: string; size: Integer): string;
begin
  result := val.Remove(size, val.Length - size * 2).Insert(size, '...');
end;

const
  DEFAULT_DIGITS = 25000;

var
  d: Integer;
  am, gm, z, agm, pi: BigInteger;
  StopWatch: TStopwatch;
  s: string;

begin
  StopWatch := TStopwatch.Create;

  d := DEFAULT_DIGITS;
  if (ParamCount > 0) then
  begin
    d := StrToIntDef(ParamStr(1), d);

    if ((d < 1) or (d > 999999)) then
      d := DEFAULT_DIGITS;
  end;

  StopWatch.Start;

  am := BIP(d);

  gm := IntSqRoot(BIP(d + d - 1, 5), BIP(d - 15, Trunc(Sqrt(0.5) * 1e+15)));

  z := BIP(d + d - 2, 25);
  agm := CalcAGM(am, gm, z, BIP(d + 1));

  pi := (agm * agm * BIP(d - 2)) div z;
  s := pi.ToString.Insert(1, '.');

  StopWatch.Stop;
  Writeln(Format('Computation time: %.3f seconds ', [StopWatch.ElapsedMilliseconds
    / 1000]));

  Writeln(Compress(s, 20));
  readln;
end.


-- ARITHMETIC GEOMETRIC MEAN -------------------------------------------------

property tolerance : 1.0E-5

-- agm :: Num a => a -> a -> a
on agm(a, g)
    script withinTolerance
        on |λ|(m)
            tell m to ((its an) - (its gn)) < tolerance
        end |λ|
    end script

    script nextRefinement
        on |λ|(m)
            tell m
                set {an, gn} to {its an, its gn}
                {an:(an + gn) / 2, gn:(an * gn) ^ 0.5}
            end tell
        end |λ|
    end script

    an of |until|(withinTolerance, ¬
        nextRefinement, {an:(a + g) / 2, gn:(a * g) ^ 0.5})
end agm

-- TEST ----------------------------------------------------------------------
on run

    agm(1, 1 / (2 ^ 0.5))

    --> 0.847213084835

end run

-- GENERIC FUNCTIONS ---------------------------------------------------------

-- until :: (a -> Bool) -> (a -> a) -> a -> a
on |until|(p, f, x)
    set mp to mReturn(p)
    set v to x
    tell mReturn(f)
        repeat until mp's |λ|(v)
            set v to |λ|(v)
        end repeat
    end tell
    return v
end |until|

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn


var a = 1:1                 # Complex(1, 1)
var b = 3.14159:1.25        # Complex(3.14159, 1.25)

[   a + b,                  # addition
    a * b,                  # multiplication
    -a,                     # negation
    a.inv,                  # multiplicative inverse
    a.conj,                 # complex conjugate
    a.abs,                  # abs
    a.sqrt,                 # sqrt
    b.re,                   # real
    b.im,                   # imaginary
].each { |c| say c }


[| a b |
  a: 1 + 1 i.
  b: Pi + 1.2 i.
  print: a + b.
  print: a * b.
  print: a / b.
  print: a reciprocal.
  print: a conjugated.
  print: a abs.
  print: a negated.
].


-module(pi).
-export([agmPi/1, agmPiBody/5]).

agmPi(Loops) ->
    % Tail recursive function that produces pi from the Arithmetic Geometric Mean method
    A = 1,
    B = 1/math:sqrt(2),
    J = 1,
    Running_divisor = 0.25,
    A_n_plus_one = 0.5*(A+B),
    B_n_plus_one = math:sqrt(A*B),
    Step_difference = A_n_plus_one - A,
    agmPiBody(Loops-1, Running_divisor-(math:pow(Step_difference, 2)*J), A_n_plus_one, B_n_plus_one, J+J).

agmPiBody(0, Running_divisor, A, _, _) ->
    math:pow(A, 2)/Running_divisor;
agmPiBody(Loops, Running_divisor, A, B, J) ->
    A_n_plus_one = 0.5*(A+B),
    B_n_plus_one = math:sqrt(A*B),
    Step_difference = A_n_plus_one - A,
    agmPiBody(Loops-1, Running_divisor-(math:pow(Step_difference, 2)*J), A_n_plus_one, B_n_plus_one, J+J).


package main

import (
    "fmt"
    "math/big"
)

func main() {
    one := big.NewFloat(1)
    two := big.NewFloat(2)
    four := big.NewFloat(4)
    prec := uint(768) // say

    a := big.NewFloat(1).SetPrec(prec)
    g := new(big.Float).SetPrec(prec)

    // temporary variables
    t := new(big.Float).SetPrec(prec)
    u := new(big.Float).SetPrec(prec)

    g.Quo(a, t.Sqrt(two))
    sum := new(big.Float)
    pow := big.NewFloat(2)

    for a.Cmp(g) != 0 {
        t.Add(a, g)
        t.Quo(t, two)
        g.Sqrt(u.Mul(a, g))
        a.Set(t)
        pow.Mul(pow, two)
        t.Sub(t.Mul(a, a), u.Mul(g, g))
        sum.Add(sum, t.Mul(t, pow))
    }

    t.Mul(a, a)
    t.Mul(t, four)
    pi := t.Quo(t, u.Sub(one, sum))
    fmt.Println(pi)
}


agm(a, g, tolerance=1.0e-15){
	While abs(a-g) > tolerance
	{
		an := .5 * (a + g)
		g  := sqrt(a*g)
		a  := an
	}
	return a
}
SetFormat, FloatFast, 0.15
MsgBox % agm(1, 1/sqrt(2))


#!/usr/bin/awk -f
BEGIN {
	printf "%.16g\n", agm(1.0,sqrt(0.5))
}
function agm(a,g) {
	while (1) {
		a0=a
		a=(a0+g)/2
		g=sqrt(a0*g)
		if (abs(a0-a) < abs(a)*1e-15) break
	}
	return a
}
function abs(x) {
	return (x<0 ? -x : x)
}


PackageLoader fileInPackage: 'Complex'.
|a b|
a := 1 + 1 i.
b := 3.14159 + 1.2 i.
(a + b) displayNl.
(a * b) displayNl.
(a / b) displayNl.
a reciprocal displayNl.
a conjugate displayNl.
a abs displayNl.
a real displayNl.
a imaginary displayNl.
a negated displayNl.


' complex numbers are native for "smart BASIC"
A=1+2i
B=3-5i

' all math operations and functions work with complex numbers
C=A*B
PRINT SQR(-4)

' example of solving quadratic equation with complex roots
' x^2+2x+5=0
a=1 ! b=2 ! c=5
x1=(-b+SQR(b^2-4*a*c))/(2*a)
x2=(-b-SQR(b^2-4*a*c))/(2*a)
PRINT x1,x2

' gives output
-1+2i    -1-2i


import java.math.MathContext

class CalculatePi {
    private static final MathContext con1024 = new MathContext(1024)
    private static final BigDecimal bigTwo = new BigDecimal(2)
    private static final BigDecimal bigFour = new BigDecimal(4)

    private static BigDecimal bigSqrt(BigDecimal bd, MathContext con) {
        BigDecimal x0 = BigDecimal.ZERO
        BigDecimal x1 = BigDecimal.valueOf(Math.sqrt(bd.doubleValue()))
        while (!Objects.equals(x0, x1)) {
            x0 = x1
            x1 = (bd.divide(x0, con) + x0).divide(bigTwo, con)
        }
        return x1
    }

    static void main(String[] args) {
        BigDecimal a = BigDecimal.ONE
        BigDecimal g = a.divide(bigSqrt(bigTwo, con1024), con1024)
        BigDecimal t
        BigDecimal sum = BigDecimal.ZERO
        BigDecimal pow = bigTwo
        while (!Objects.equals(a, g)) {
            t = (a + g).divide(bigTwo, con1024)
            g = bigSqrt(a * g, con1024)
            a = t
            pow = pow * bigTwo
            sum = sum + (a * a - g * g) * pow
        }
        BigDecimal pi = (bigFour * (a * a)).divide(BigDecimal.ONE - sum, con1024)
        System.out.println(pi)
    }
}


import Prelude hiding (pi)
import Data.Number.MPFR hiding (sqrt, pi, div)
import Data.Number.MPFR.Instances.Near ()

-- A generous overshoot of the number of bits needed for a
-- given number of digits.
digitBits :: (Integral a, Num a) => a -> a
digitBits n = (n + 1) `div` 2 * 8

-- Calculate pi accurate to a given number of digits.
pi :: Integer -> MPFR
pi digits =
  let eps = fromString ("1e-" ++ show digits)
            (fromInteger $ digitBits digits) 0
      two = fromInt Near (getPrec eps) 2
      twoi = 2 :: Int
      twoI = 2 :: Integer
      pis a g s n =
        let aB = (a + g) / two
            gB = sqrt (a * g)
            aB2 = aB ^^ twoi
            sB = s + (two ^^ n) * (aB2 - gB ^^ twoi)
            num = 4 * aB2
            den = 1 - sB
        in (num / den) : pis aB gB sB (n + 1)
      puntil f (a:b:xs) = if f a b then b else puntil f (b:xs)
  in puntil (\a b -> abs (a - b) < eps)
     $ pis one (one / sqrt two) zero twoI

main :: IO ()
main = do
  -- The last decimal is rounded.
  putStrLn $ toString 1000 $ pi 1000


PRINT AGM(1, 1 / SQR(2))
END

FUNCTION AGM (a, g)
    DO
        ta = (a + g) / 2
        g = SQR(a * g)
        SWAP a, ta
    LOOP UNTIL a = ta

    AGM = a
END FUNCTION


/* Calculate the arithmethic-geometric mean of two positive
 * numbers x and y.
 * Result will have d digits after the decimal point.
 */
define m(x, y, d) {
    auto a, g, o

    o = scale
    scale = d
    d = 1 / 10 ^ d

    a = (x + y) / 2
    g = sqrt(x * y)
    while ((a - g) > d) {
        x = (a + g) / 2
        g = sqrt(a * g)
        a = x
    }

    scale = o
    return(a)
}

scale = 20
m(1, 1 / sqrt(2), 20)


AGM ← {
    (|𝕨-𝕩) ≤ 1e¯15? 𝕨;
    (0.5×𝕨+𝕩) 𝕊 √𝕨×𝕩
}

1 AGM 1÷√2


*       # Define complex datatype
        data('complex(r,i)')

*       # Addition
        define('addx(x1,x2)a,b,c,d') :(addx_end)
addx    a = r(x1); b = i(x1); c = r(x2); d = i(x2)
        addx = complex(a + c, b + d) :(return)
addx_end

*       # Multiplication
        define('multx(x1,x2)a,b,c,d') :(multx_end)
multx   a = r(x1); b = i(x1); c = r(x2); d = i(x2)
        multx = complex(a * c - b * d, b * c + a * d) :(return)
multx_end

*       # Negation
        define('negx(x)') :(negx_end)
negx    negx = complex(-r(x), -i(x)) :(return)
negx_end

*       # Inverse
        define('invx(x)d') :(invx_end)
invx    d = (r(x) * r(x)) + (i(x) * i(x))
        invx = complex(1.0 * r(x) / d, 1.0 * -i(x) / d) :(return)
invx_end

*       # Print compex number: a+bi / a-bi
        define('printx(x)sign') :(printx_end)
printx  sign = ge(i(x),0) '+'
        printx = r(x) sign i(x) 'i' :(return)
printx_end

*       # Test and display
        a = complex(1,1)
        b = complex(3.14159, 1.2)
        output = printx( addx(a,b) )
        output = printx( multx(a,b) )
        output = printx( negx(a) ) ', ' printx( negx(b) )
        output = printx( invx(a) ) ', ' printx( invx(b) )
end


(* Signature for complex numbers *)
signature COMPLEX = sig
 type num

 val complex : real * real -> num

 val negative : num -> num
 val plus : num -> num -> num
 val minus : num -> num -> num
 val times : num -> num -> num
 val invert : num -> num
 val print_number : num -> unit
end;

(* Actual implementation *)
structure Complex :> COMPLEX = struct
  type num = real * real

  fun complex (a, b) = (a, b)

  fun negative (a, b) = (Real.~a, Real.~b)
  fun plus (a1, b1) (a2, b2) = (Real.+ (a1, a2), Real.+(b1, b2))
  fun minus i1 i2 = plus i1 (negative i2)
  fun times (a1, b1) (a2, b2)= (Real.*(a1, a2) - Real.*(b1, b2), Real.*(a1, b2) + Real.*(a2, b1))
  fun invert (a, b) =
    let
      val denom = a * a + b * b
    in
      (a / denom, ~b / denom)
    end

  fun print_number (a, b) =
    print (Real.toString(a) ^ " + " ^ Real.toString(b) ^ "i\n")
end;

val i1 = Complex.complex(1.0,2.0); (* 1 + 2i *)
val i2 = Complex.complex(3.0,4.0); (* 3 + 4i *)

Complex.print_number(Complex.negative(i1)); (* -1 - 2i *)
Complex.print_number(Complex.plus i1 i2); (* 4 + 6i *)
Complex.print_number(Complex.minus i2 i1); (* 2 + 2i *)
Complex.print_number(Complex.times i1 i2); (* -5 + 10i *)
Complex.print_number(Complex.invert i1); (* 1/5 - 2i/5 *)


import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Objects;

public class Calculate_Pi {
    private static final MathContext con1024 = new MathContext(1024);
    private static final BigDecimal bigTwo = new BigDecimal(2);
    private static final BigDecimal bigFour = new BigDecimal(4);

    private static BigDecimal bigSqrt(BigDecimal bd, MathContext con) {
        BigDecimal x0 = BigDecimal.ZERO;
        BigDecimal x1 = BigDecimal.valueOf(Math.sqrt(bd.doubleValue()));
        while (!Objects.equals(x0, x1)) {
            x0 = x1;
            x1 = bd.divide(x0, con).add(x0).divide(bigTwo, con);
        }
        return x1;
    }

    public static void main(String[] args) {
        BigDecimal a = BigDecimal.ONE;
        BigDecimal g = a.divide(bigSqrt(bigTwo, con1024), con1024);
        BigDecimal t;
        BigDecimal sum = BigDecimal.ZERO;
        BigDecimal pow = bigTwo;
        while (!Objects.equals(a, g)) {
            t = a.add(g).divide(bigTwo, con1024);
            g = bigSqrt(a.multiply(g), con1024);
            a = t;
            pow = pow.multiply(bigTwo);
            sum = sum.add(a.multiply(a).subtract(g.multiply(g)).multiply(pow));
        }
        BigDecimal pi = bigFour.multiply(a.multiply(a)).divide(BigDecimal.ONE.subtract(sum), con1024);
        System.out.println(pi);
    }
}


#include<math.h>
#include<stdio.h>
#include<stdlib.h>

double agm( double a, double g ) {
   /* arithmetic-geometric mean */
   double iota = 1.0E-16;
   double a1, g1;

   if( a*g < 0.0 ) {
      printf( "arithmetic-geometric mean undefined when x*y<0\n" );
      exit(1);
   }

   while( fabs(a-g)>iota ) {
      a1 = (a + g) / 2.0;
      g1 = sqrt(a * g);

      a = a1;
      g = g1;
   }

   return a;
}

int main( void ) {
   double x, y;
   printf( "Enter two numbers: " );
   scanf( "%lf%lf", &x, &y );
   printf( "The arithmetic-geometric mean is %lf\n", agm(x, y) );
   return 0;
}


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));
            }
        }
    }
}


public struct Complex {

    public let real : Double
    public let imaginary : Double

    public init(real inReal:Double, imaginary inImaginary:Double) {
        real = inReal
        imaginary = inImaginary
    }

    public static var i : Complex = Complex(real:0, imaginary: 1)
    public static var zero : Complex = Complex(real: 0, imaginary: 0)

    public var negate : Complex {
        return Complex(real: -real, imaginary: -imaginary)
    }

    public var invert : Complex {
        let d = (real*real + imaginary*imaginary)
        return Complex(real: real/d, imaginary: -imaginary/d)
    }

    public var conjugate : Complex {
        return Complex(real: real, imaginary: -imaginary)
    }

}
public func + (left: Complex, right: Complex) -> Complex {

    return Complex(real: left.real+right.real, imaginary: left.imaginary+right.imaginary)
}
public func * (left: Complex, right: Complex) -> Complex {

    return Complex(real: left.real*right.real - left.imaginary*right.imaginary,
        imaginary: left.real*right.imaginary+left.imaginary*right.real)
}
public prefix func - (right:Complex) -> Complex {
    return right.negate
}

// Checking equality is almost necessary for a struct of this type  to be useful
extension Complex : Equatable {}
public func == (left:Complex, right:Complex) -> Bool {
    return left.real == right.real && left.imaginary == right.imaginary
}


# include "rational";  # a reminder

def pi(precision):
  (precision | (. + log) | ceil) as $digits
  | def sq: . as $in | rmult($in; $in) | rround($digits);
  {an: r(1;1),
   bn: (r(1;2) | rsqrt($digits)),
   tn: r(1;4),
   pn: 1 }
  | until (.pn > $digits;
      .an as $prevAn
      | .an = (rmult(radd(.bn; .an); r(1;2)) | rround($digits) )
      | .bn = ([.bn, $prevAn] | rmult | rsqrt($digits) )
      | .tn = rminus(.tn; rmult(rminus($prevAn; .an)|sq; .pn))
      | .pn *= 2
      )
   | rdiv( radd(.an; .bn)|sq; rmult(.tn; 4))
   | r_to_decimal(precision);

pi(500)


using Printf

agm1step(x, y) = (x + y) / 2, sqrt(x * y)

function approxπstep(x, y, z, n::Integer)
    a, g = agm1step(x, y)
    k = n + 1
    s = z + 2 ^ (k + 1) * (a ^ 2 - g ^ 2)
    return a, g, s, k
end

approxπ(a, g, s) = 4a ^ 2 / (1 - s)

function testmakepi()
	setprecision(512)
	a, g, s, k = BigFloat(1.0), 1 / √BigFloat(2.0), BigFloat(0.0), 0
	oldπ = BigFloat(0.0)
	println("Approximating π using ", precision(BigFloat), "-bit floats.")
	println("   k     Error  Result")
	for i in 1:100
		a, g, s, k = approxπstep(a, g, s, k)
		estπ = approxπ(a, g, s)
		if abs(estπ - oldπ) < 2eps(estπ) break end
		oldπ = estπ
		err = abs(π - estπ)
		@printf("%4d%10.1e%68.60e\n", i, err, estπ)
	end
end

testmakepi()


import java.math.BigDecimal
import java.math.MathContext

val con1024 = MathContext(1024)
val bigTwo  = BigDecimal(2)
val bigFour = bigTwo * bigTwo

fun bigSqrt(bd: BigDecimal, con: MathContext): BigDecimal {
    var x0 = BigDecimal.ZERO
    var x1 = BigDecimal.valueOf(Math.sqrt(bd.toDouble()))
    while (x0 != x1) {
        x0 = x1
        x1 = bd.divide(x0, con).add(x0).divide(bigTwo, con)
    }
    return x1
}

fun main(args: Array<String>) {
    var a = BigDecimal.ONE
    var g = a.divide(bigSqrt(bigTwo, con1024), con1024)
    var t : BigDecimal
    var sum = BigDecimal.ZERO
    var pow = bigTwo
    while (a != g) {
        t = (a + g).divide(bigTwo, con1024)
        g = bigSqrt(a * g, con1024)
        a = t
        pow *= bigTwo
        sum += (a * a - g * g) * pow
    }
    val pi = (bigFour * a * a).divide(BigDecimal.ONE - sum, con1024)
    println(pi)
}


#include<bits/stdc++.h>
using namespace std;
#define _cin	ios_base::sync_with_stdio(0);	cin.tie(0);
#define rep(a, b)	for(ll i =a;i<=b;++i)

double agm(double a, double g)		//ARITHMETIC GEOMETRIC MEAN
{	double epsilon = 1.0E-16,a1,g1;
	if(a*g<0.0)
	{	cout<<"Couldn't find arithmetic-geometric mean of these numbers\n";
		exit(1);
	}
	while(fabs(a-g)>epsilon)
	{	a1 = (a+g)/2.0;
		g1 = sqrt(a*g);
		a = a1;
		g = g1;
	}
	return a;
}

int main()
{	_cin;    //fast input-output
	double x, y;
	cout<<"Enter X and Y: ";	//Enter two numbers
	cin>>x>>y;
	cout<<"\nThe Arithmetic-Geometric Mean of "<<x<<" and "<<y<<" is "<<agm(x, y);
return 0;
}


(ns agmcompute
  (:gen-class))

; Java Arbitray Precision Library
(import '(org.apfloat Apfloat ApfloatMath))

(def precision 70)
(def one (Apfloat. 1M precision))
(def two (Apfloat. 2M precision))
(def half (Apfloat. 0.5M precision))
(def isqrt2 (.divide one  (ApfloatMath/pow two half)))
(def TOLERANCE (Apfloat. 0.000000M precision))

(defn agm [a g]
  " Simple AGM Loop calculation "
       (let [THRESH 1e-65                 ; done when error less than threshold or we exceed max loops
             MAX-LOOPS 1000000]
        (loop [[an gn] [a g], cnt 0]
            (if (or (< (ApfloatMath/abs (.subtract an gn)) THRESH)
                    (> cnt MAX-LOOPS))
              an
              (recur [(.multiply (.add an gn) half) (ApfloatMath/pow (.multiply an gn) half)]
                     (inc cnt))))))

(println  (agm one isqrt2))


package require math::complexnumbers
namespace import math::complexnumbers::*

set a [complex 1 1]
set b [complex 3.14159 1.2]
puts [tostring [+ $a $b]] ;# ==> 4.14159+2.2i
puts [tostring [* $a $b]] ;# ==> 1.94159+4.34159i
puts [tostring [pow $a [complex -1 0]]] ;# ==> 0.5-0.4999999999999999i
puts [tostring [- $a]] ;# ==> -1.0-i


3	П0	1	П1	П4	2	КвКор	1/x	П2	1
^	4	/	П3	ИП3	ИП1	ИП2	+	2	/
П5	ИП1	-	x^2	ИП4	*	-	П3	ИП1	ИП2
*	КвКор	П2	ИП5	П1	КИП4	L0	14	ИП1	x^2
ИП3	/	С/П


from math import sqrt
import times

import bignum

#---------------------------------------------------------------------------------------------------

func sqrt(value, guess: Int): Int =
  result = guess
  while true:
    let term = value div result
    if abs(term - result) <= 1:
      break
    result = (result + term) shr 1

#---------------------------------------------------------------------------------------------------

func isr(term, guess: Int): Int =
  var term = term
  result = guess
  let value = term * result
  while true:
    if abs(term - result) <= 1:
      break
    result = (result + term) shr 1
    term = value div result

#---------------------------------------------------------------------------------------------------

func calcAGM(lam, gm: Int; z: var Int; ep: Int): Int =
  var am: Int
  var lam = lam
  var gm = gm
  var n = 1
  while true:
    am = (lam + gm) shr 1
    gm = isr(lam, gm)
    let v = am - lam
    let zi = v * v * n
    if zi < ep:
      break
    dec z, zi
    inc n, n
    lam = am
  result = am

#---------------------------------------------------------------------------------------------------

func bip(exp: int; man = 1): Int {.inline.} = man * pow(10, culong(exp))

#---------------------------------------------------------------------------------------------------

func compress(str: string; size: int): string =
  if str.len <= 2 * size: str
  else: str[0..<size] & "..." & str[^size..^1]

#———————————————————————————————————————————————————————————————————————————————————————————————————

import os
import parseutils
import strutils

const DefaultDigits = 25_000

var d = DefaultDigits
if paramCount() > 0:
  if paramStr(1).parseInt(d) > 0:
    if d notin 1..999_999:
      d = DefaultDigits

let t0 = getTime()

let am = bip(d)
let gm = sqrt(bip(d + d - 1, 5), bip(d - 15, int(sqrt(0.5) * 1e15)))
var z = bip(d + d - 2, 25)
let agm = calcAGM(am, gm, z, bip(d + 1))
let pi = agm * agm * bip(d - 2) div z

var piStr = $pi
piStr.insert(".", 1)

let dt = (getTime() - t0).inMicroseconds.float
let timestr = if dt > 1_000_000:
                (dt / 1e6).formatFloat(ffDecimal, 2) & " s"
              elif dt > 1000:
                $(dt / 1e3).toInt & " ms"
              else:
                $dt.toInt & " µs"
echo "Computed ", d, " digits in ", timeStr

echo "π = ", compress(piStr, 20), "..."


let limit = 10000 and n = 2800
let x = Array.make (n+1) 2000

let rec g j sum =
  if j < 1 then sum else
    let sum = sum * j + limit * x.(j) in
    x.(j) <- sum mod (j * 2 - 1);
    g (j - 1) (sum / (j * 2 - 1))

let rec f i carry =
  if i = 0 then () else
    let sum = g i 0 in
    Printf.printf "%04d" (carry + sum / limit);
    f (i - 14) (sum mod limit)

let () =
  f n 0;
  print_newline()


IDENTIFICATION DIVISION.
PROGRAM-ID. ARITHMETIC-GEOMETRIC-MEAN-PROG.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  AGM-VARS.
    05 A       PIC 9V9(16).
    05 A-ZERO  PIC 9V9(16).
    05 G       PIC 9V9(16).
    05 DIFF    PIC 9V9(16) VALUE 1.
* Initialize DIFF with a non-zero value, otherwise AGM-PARAGRAPH
* is never performed at all.
PROCEDURE DIVISION.
TEST-PARAGRAPH.
    MOVE    1 TO A.
    COMPUTE G = 1 / FUNCTION SQRT(2).
* The program will run with the test values. If you would rather
* calculate the AGM of numbers input at the console, comment out
* TEST-PARAGRAPH and un-comment-out INPUT-A-AND-G-PARAGRAPH.
* INPUT-A-AND-G-PARAGRAPH.
*     DISPLAY 'Enter two numbers.'
*     ACCEPT  A.
*     ACCEPT  G.
CONTROL-PARAGRAPH.
    PERFORM AGM-PARAGRAPH UNTIL DIFF IS LESS THAN 0.000000000000001.
    DISPLAY A.
    STOP RUN.
AGM-PARAGRAPH.
    MOVE     A TO A-ZERO.
    COMPUTE  A = (A-ZERO + G) / 2.
    MULTIPLY A-ZERO BY G GIVING G.
    COMPUTE  G = FUNCTION SQRT(G).
    SUBTRACT A FROM G GIVING DIFF.
    COMPUTE  DIFF = FUNCTION ABS(DIFF).


(defun agm (a0 g0 &optional (tolerance 1d-8))
  (loop for a = a0 then (* (+ a g) 5d-1)
     and g = g0 then (sqrt (* a g))
     until (< (abs (- a g)) tolerance)
     finally (return a)))


typeset -T Complex_t=(
    float real=0
    float imag=0

    function to_s {
        print -- "${_.real} + ${_.imag} i"
    }

    function dup {
        nameref other=$1
        _=( real=${other.real} imag=${other.imag} )
    }

    function add {
        typeset varname
        for varname; do
            nameref other=$varname
            (( _.real += other.real ))
            (( _.imag += other.imag ))
        done
    }

    function negate {
        (( _.real *= -1 ))
        (( _.imag *= -1 ))
    }

    function conjugate {
        (( _.imag *= -1 ))
    }

    function multiply {
        typeset varname
        for varname; do
            nameref other=$varname
            float a=${_.real} b=${_.imag} c=${other.real} d=${other.imag}
            (( _.real = a*c - b*d ))
            (( _.imag = b*c + a*d ))
        done
    }

    function inverse {
        if (( _.real == 0 && _.imag == 0 )); then
            print -u2 "division by zero"
            return 1
        fi
        float denom=$(( _.real*_.real + _.imag*_.imag ))
        (( _.real = _.real / denom ))
        (( _.imag = -1 * _.imag / denom ))
    }
)

Complex_t a=(real=1 imag=1)
a.to_s        # 1 + 1 i

Complex_t b=(real=3.14159 imag=1.2)
b.to_s        # 3.14159 + 1.2 i

Complex_t c
c.add a b
c.to_s        # 4.14159 + 2.2 i

c.negate
c.to_s        # -4.14159 + -2.2 i

c.conjugate
c.to_s        # -4.14159 + 2.2 i

c.dup a
c.multiply b
c.to_s        # 1.94159 + 4.34159 i

Complex_t d=(real=2 imag=1)
d.inverse
d.to_s        # 0.4 + -0.2 i


use Math::BigFloat try => "GMP,Pari";

my $digits = shift || 100;   # Get number of digits from command line
print agm_pi($digits), "\n";

sub agm_pi {
  my $digits = shift;
  my $acc = $digits + 8;
  my $HALF = Math::BigFloat->new("0.5");
  my ($an, $bn, $tn, $pn) = (Math::BigFloat->bone, $HALF->copy->bsqrt($acc),
                             $HALF->copy->bmul($HALF), Math::BigFloat->bone);
  while ($pn < $acc) {
    my $prev_an = $an->copy;
    $an->badd($bn)->bmul($HALF, $acc);
    $bn->bmul($prev_an)->bsqrt($acc);
    $prev_an->bsub($an);
    $tn->bsub($pn * $prev_an * $prev_an);
    $pn->badd($pn);
  }
  $an->badd($bn);
  $an->bmul($an,$acc)->bdiv(4*$tn, $digits);
  return $an;
}


import std.stdio, std.math, std.meta, std.typecons;

real agm(real a, real g, in int bitPrecision=60) pure nothrow @nogc @safe {
    do {
        //{a, g} = {(a + g) / 2.0, sqrt(a * g)};
        AliasSeq!(a, g) = tuple((a + g) / 2.0, sqrt(a * g));
    } while (feqrel(a, g) < bitPrecision);
    return a;
}

void main() @safe {
    writefln("%0.19f", agm(1, 1 / sqrt(2.0)));
}


program geometric_mean;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

function Fabs(value: Double): Double;
begin
  Result := value;
  if Result < 0 then
    Result := -Result;
end;

function agm(a, g: Double):Double;
var
  iota, a1, g1: Double;
begin
  iota := 1.0E-16;
  if a * g < 0.0 then
  begin
    Writeln('arithmetic-geometric mean undefined when x*y<0');
    exit(1);
  end;

  while Fabs(a - g) > iota do
  begin
    a1 := (a + g) / 2.0;
    g1 := sqrt(a * g);
    a := a1;
    g := g1;
  end;
  Exit(a);
end;

var
  x, y: Double;

begin
  Write('Enter two numbers:');
  Readln(x, y);
  writeln(format('The arithmetic-geometric mean is  %.6f', [agm(x, y)]));
  readln;
end.


u = 3.785e+00-1.969e+00i
v = 9.545e-01-3.305e+00j

#cast %jL

examples =

<
   complex..add (u,v),
   complex..mul (u,v),
   complex..sub (0.,u),
   complex..div (1.,v)>