import java.util.Objects;

public class Circles {
    private static class Point {
        private final double x, y;

        public Point(Double x, Double y) {
            this.x = x;
            this.y = y;
        }

        public double distanceFrom(Point other) {
            double dx = x - other.x;
            double dy = y - other.y;
            return Math.sqrt(dx * dx + dy * dy);
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) return true;
            if (other == null || getClass() != other.getClass()) return false;
            Point point = (Point) other;
            return x == point.x && y == point.y;
        }

        @Override
        public String toString() {
            return String.format("(%.4f, %.4f)", x, y);
        }
    }

    private static Point[] findCircles(Point p1, Point p2, double r) {
        if (r < 0.0) throw new IllegalArgumentException("the radius can't be negative");
        if (r == 0.0 && p1 != p2) throw new IllegalArgumentException("no circles can ever be drawn");
        if (r == 0.0) return new Point[]{p1, p1};
        if (Objects.equals(p1, p2)) throw new IllegalArgumentException("an infinite number of circles can be drawn");
        double distance = p1.distanceFrom(p2);
        double diameter = 2.0 * r;
        if (distance > diameter) throw new IllegalArgumentException("the points are too far apart to draw a circle");
        Point center = new Point((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0);
        if (distance == diameter) return new Point[]{center, center};
        double mirrorDistance = Math.sqrt(r * r - distance * distance / 4.0);
        double dx = (p2.x - p1.x) * mirrorDistance / distance;
        double dy = (p2.y - p1.y) * mirrorDistance / distance;
        return new Point[]{
            new Point(center.x - dy, center.y + dx),
            new Point(center.x + dy, center.y - dx)
        };
    }

    public static void main(String[] args) {
        Point[] p = new Point[]{
            new Point(0.1234, 0.9876),
            new Point(0.8765, 0.2345),
            new Point(0.0000, 2.0000),
            new Point(0.0000, 0.0000)
        };
        Point[][] points = new Point[][]{
            {p[0], p[1]},
            {p[2], p[3]},
            {p[0], p[0]},
            {p[0], p[1]},
            {p[0], p[0]},
        };
        double[] radii = new double[]{2.0, 1.0, 2.0, 0.5, 0.0};
        for (int i = 0; i < radii.length; ++i) {
            Point p1 = points[i][0];
            Point p2 = points[i][1];
            double r = radii[i];
            System.out.printf("For points %s and %s with radius %f\n", p1, p2, r);
            try {
                Point[] circles = findCircles(p1, p2, r);
                Point c1 = circles[0];
                Point c2 = circles[1];
                if (Objects.equals(c1, c2)) {
                    System.out.printf("there is just one circle with center at %s\n", c1);
                } else {
                    System.out.printf("there are two circles with centers at %s and %s\n", c1, c2);
                }
            } catch (IllegalArgumentException ex) {
                System.out.println(ex.getMessage());
            }
            System.out.println();
        }
    }
}


const hDist = (p1, p2) => Math.hypot(...p1.map((e, i) => e - p2[i])) / 2;
const pAng = (p1, p2) => Math.atan(p1.map((e, i) => e - p2[i]).reduce((p, c) => c / p, 1));
const solveF = (p, r) => t => [r*Math.cos(t) + p[0], r*Math.sin(t) + p[1]];
const diamPoints = (p1, p2) => p1.map((e, i) => e + (p2[i] - e) / 2);

const findC = (...args) => {
  const [p1, p2, s] = args;
  const solve = solveF(p1, s);
  const halfDist = hDist(p1, p2);

  let msg = `p1: ${p1}, p2: ${p2}, r:${s} Result: `;
  switch (Math.sign(s - halfDist)) {
    case 0:
      msg += s ? `Points on diameter. Circle at: ${diamPoints(p1, p2)}` :
        'Radius Zero';
      break;
    case 1:
      if (!halfDist) {
        msg += 'Coincident point. Infinite solutions';
      }
      else {
        let theta = pAng(p1, p2);
        let theta2 = Math.acos(halfDist / s);
        [1, -1].map(e => solve(theta + e * theta2)).forEach(
          e => msg += `Circle at ${e} `);
      }
      break;
    case -1:
      msg += 'No intersection. Points further apart than circle diameter';
      break;
  }
  return msg;
};

[
  [[0.1234, 0.9876], [0.8765, 0.2345], 2.0],
  [[0.0000, 2.0000], [0.0000, 0.0000], 1.0],
  [[0.1234, 0.9876], [0.1234, 0.9876], 2.0],
  [[0.1234, 0.9876], [0.8765, 0.2345], 0.5],
  [[0.1234, 0.9876], [0.1234, 0.9876], 0.0]
].forEach((t,i) => console.log(`Test: ${i}: ${findC(...t)}`));


# circle_centers is defined here as a filter.
# Input should be an array [x1, y1, x2, y2, r] giving the co-ordinates
# of the two points and a radius.
# If there is one solution, the output is the circle center;
# if there are two solutions centered at [x1, y1] and [x2, y2],
# then the output is [x1, y1, x2, y2];
# otherwise an explanatory string is returned.

def circle_centers:
  def sq: .*.;
  def c(x3; y1; y2; r; d): x3 + ((r|sq - ((d/2)|sq)) | sqrt) * (y1-y2)/d;

  .[0] as $x1 | .[1] as $y1 | .[2] as $x2 | .[3] as $y2 | .[4] as $r
  | ((($x2-$x1)|sq) + (($y2-$y1)|sq) | sqrt) as $d
  | (($x1+$x2)/2) as $x3
  | (($y1+$y2)/2) as $y3
  | c($x3; $y1; $y2; $r; $d) as $cx1
  | c($y3; $x2; $x2; $r; $d) as $cy1
  | (- c(-$x3; $y1; $y2; $r; $d)) as $cx2
  | (- c(-$y3; $x2; $x2; $r; $d)) as $cy2
  | if   $d == 0 and $r == 0 then [$x1, $y1]  # special case
    elif $d == 0     then "infinitely many circles can be drawn"
    elif $d >  $r*2  then "points are too far from each other"
    elif  0 >  $r    then "radius is not valid"
    elif ($cx1 and $cy1 and $cx2 and $cy2) | not then "no solution"
    else  [$cx1, $cy1, $cx2, $cy2 ]
    end;


immutable Point{T<:FloatingPoint}
    x::T
    y::T
end

immutable Circle{T<:FloatingPoint}
    c::Point{T}
    r::T
end
Circle{T<:FloatingPoint}(a::Point{T}) = Circle(a, zero(T))

using AffineTransforms

function circlepoints{T<:FloatingPoint}(a::Point{T}, b::Point{T}, r::T)
    cp = Circle{T}[]
    r >= 0 || return (cp, "No Solution, Negative Radius")
    if a == b
        if abs(r) < 2eps(zero(T))
            return (push!(cp, Circle(a)), "Point Solution, Zero Radius")
        else
            return (cp, "Infinite Solutions, Indefinite Center")
        end
    end
    ca = Complex(a.x, a.y)
    cb = Complex(b.x, b.y)
    d = (ca + cb)/2
    tfd = tformtranslate([real(d), imag(d)])
    tfr = tformrotate(angle(cb-ca))
    tfm = tfd*tfr
    u = abs(cb-ca)/2
    r-u > -5eps(r) || return(cp, "No Solution, Radius Too Small")
    if r-u < 5eps(r)
        push!(cp, Circle(apply(Point, tfm*[0.0, 0.0]), r))
        return return (cp, "Single Solution, Degenerate Centers")
    end
    v = sqrt(r^2 - u^2)
    for w in [v, -v]
        push!(cp, Circle(apply(Point, tfm*[0.0, w]), r))
    end
    return (cp, "Two Solutions")
end


F mul_inv(=a, =b)
   V b0 = b
   V x0 = 0
   V x1 = 1
   I b == 1
      R 1
   L a > 1
      V q = a I/ b
      (a, b) = (b, a % b)
      (x0, x1) = (x1 - q * x0, x0)
   I x1 < 0
      x1 += b0
   R x1

F chinese_remainder(n, a)
   V sum = 0
   V prod = product(n)
   L(n_i, a_i) zip(n, a)
      V p = prod I/ n_i
      sum += a_i * mul_inv(p, n_i) * p
   R sum % prod

V n = [3, 5, 7]
V a = [2, 3, 2]
print(chinese_remainder(n, a))


// version 1.1.51

typealias IAE = IllegalArgumentException

class Point(val x: Double, val y: Double) {
    fun distanceFrom(other: Point): Double {
        val dx = x - other.x
        val dy = y - other.y
        return Math.sqrt(dx * dx + dy * dy )
    }

    override fun equals(other: Any?): Boolean {
        if (other == null || other !is Point) return false
        return (x == other.x && y == other.y)
    }

    override fun toString() = "(%.4f, %.4f)".format(x, y)
}

fun findCircles(p1: Point, p2: Point, r: Double): Pair<Point, Point> {
    if (r < 0.0) throw IAE("the radius can't be negative")
    if (r == 0.0 && p1 != p2) throw IAE("no circles can ever be drawn")
    if (r == 0.0) return p1 to p1
    if (p1 == p2) throw IAE("an infinite number of circles can be drawn")
    val distance = p1.distanceFrom(p2)
    val diameter = 2.0 * r
    if (distance > diameter) throw IAE("the points are too far apart to draw a circle")
    val center = Point((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0)
    if (distance == diameter) return center to center
    val mirrorDistance = Math.sqrt(r * r - distance * distance / 4.0)
    val dx =  (p2.x - p1.x) * mirrorDistance / distance
    val dy =  (p2.y - p1.y) * mirrorDistance / distance
    return Point(center.x - dy, center.y + dx) to
           Point(center.x + dy, center.y - dx)
}

fun main(args: Array<String>) {
    val p = arrayOf(
        Point(0.1234, 0.9876),
        Point(0.8765, 0.2345),
        Point(0.0000, 2.0000),
        Point(0.0000, 0.0000)
    )
    val points = arrayOf(
        p[0] to p[1], p[2] to p[3], p[0] to p[0], p[0] to p[1], p[0] to p[0]
    )
    val radii = doubleArrayOf(2.0, 1.0, 2.0, 0.5, 0.0)
    for (i in 0..4) {
        try {
            val (p1, p2) = points[i]
            val r  = radii[i]
            println("For points $p1 and $p2 with radius $r")
            val (c1, c2) = findCircles(p1, p2, r)
            if (c1 == c2)
                println("there is just one circle with center at $c1")
            else
                println("there are two circles with centers at $c1 and $c2")
        }
        catch(ex: IllegalArgumentException) {
            println(ex.message)
        }
        println()
    }
}


*        Chinese remainder theorem 06/09/2015
CHINESE  CSECT
         USING  CHINESE,R12        base addr
         LR     R12,R15
BEGIN    LA     R9,1               m=1
         LA     R6,1               j=1
LOOPJ    C      R6,NN              do j=1 to nn
         BH     ELOOPJ
         LR     R1,R6              j
         SLA    R1,2               j*4
         M      R8,N-4(R1)         m=m*n(j)
         LA     R6,1(R6)           j=j+1
         B      LOOPJ
ELOOPJ   LA     R6,1               x=1
LOOPX    CR     R6,R9              do x=1 to m
         BH     ELOOPX
         LA     R7,1               i=1
LOOPI    C      R7,NN              do i=1 to nn
         BH     ELOOPI
         LR     R1,R7              i
         SLA    R1,2               i*4
         LR     R5,R6              x
         LA     R4,0
         D      R4,N-4(R1)         x//n(i)
         C      R4,A-4(R1)         if x//n(i)^=a(i)
         BNE    ITERX              then iterate x
         LA     R7,1(R7)           i=i+1
         B      LOOPI
ELOOPI   MVC    PG(2),=C'x='
         XDECO  R6,PG+2            edit x
         XPRNT  PG,14              print buffer
         B      RETURN
ITERX    LA     R6,1(R6)           x=x+1
         B      LOOPX
ELOOPX   XPRNT  NOSOL,17           print
RETURN   XR     R15,R15            rc=0
         BR     R14
NN       DC     F'3'
N        DC     F'3',F'5',F'7'
A        DC     F'2',F'3',F'2'
PG       DS     CL80
NOSOL    DC     CL17'no solution found'
         YREGS
         END    CHINESE


INT FUNC MulInv(INT a,b)
  INT b0,x0,x1,q,tmp

  IF b=1 THEN RETURN (1) FI

  b0=b x0=0 x1=1
  WHILE a>1
  DO
    q=a/b

    tmp=b
    b=a MOD b
    a=tmp

    tmp=x0
    x0=x1-q*x0
    x1=tmp
  OD
  IF x1<0 THEN
    x1==+b0
  FI
RETURN (x1)

INT FUNC ChineseRemainder(BYTE ARRAY n,a BYTE len)
  INT prod,sum,p,m
  BYTE i

  prod=1 sum=0
  FOR i=0 TO len-1
  DO
    prod==*n(i)
  OD
  FOR i=0 TO len-1
  DO
    p=prod/n(i)
    m=MulInv(p,n(i))
    sum==+a(i)*m*p
  OD
RETURN (sum MOD prod)

PROC Main()
  BYTE ARRAY n=[3 5 7],a=[2 3 2]
  INT res

  res=ChineseRemainder(n,a,3)
  PrintI(res)
RETURN


with Ada.Text_IO, Mod_Inv;

procedure Chin_Rema is
   N: array(Positive range <>) of Positive := (3, 5, 7);
   A: array(Positive range <>) of Positive := (2, 3, 2);
   Tmp: Positive;
   Prod: Positive := 1;
   Sum: Natural := 0;

begin
   for I in N'Range loop
      Prod := Prod * N(I);
   end loop;

   for I in A'Range loop
      Tmp := Prod / N(I);
      Sum := Sum + A(I) * Mod_Inv.Inverse(Tmp, N(I)) * Tmp;
   end loop;
   Ada.Text_IO.Put_Line(Integer'Image(Sum mod Prod));
end Chin_Rema;


input:  OP1=(x1,y1), OP2=(x2,y2), r
output: OC = OH + HC
  where OH = (OP1+OP2)/2
    and HC = j*|HC|
  where j is the unit vector rotated -90° from P1P2
    and |HC| = √(r^2 - (|P1P2|/2)^2) if exists

{def circleby2points
 {lambda {:x1 :y1 :x2 :y2 :r}
  {if {= :r 0}
   then radius is zero
   else {if {and {= :x1 :x2} {= :y1 :y2}}
   then same points
   else {let { {:r :r}
               {:vx {- :x2 :x1}} {:vy {- :y2 :y1}}                      // v = P1P2
               {:hx {/ {+ :x1 :x2} 2}} {:hy {/ {+ :y1 :y2} 2}} }        // h = OH
        {let { {:r :r} {:vx :vx} {:vy :vy} {:hx :hx} {:hy :hy}          // closure
               {:d {sqrt {+ {* :px :px} {* :py :py}}} } }               // d = |P1P2|
        {if {> :d {* 2 :r}}                                             // d > diam
         then no circle, points are too far apart
         else {if {= :d {* 2 :r}}                                       // d = diam
         then one circle: opposite ends of diameter with centre (:hx,:hy)
         else {let { {:r :r} {:hx :hx} {:hy :hy}                        // closure
                     {:jx {- {/ :vy :d}}} {:jy {/ :vx :d}}              // j unit -90° to P1P2
                     {:d {sqrt {- {* :r :r} {/ {* :d :d} 4}}}} }        // |HC|
              two circles: {br}({+ :hx {* :d :jx}},{+ :hy {* :d :jy}})  // OH + j*|HC|
                           {br}({- :hx {* :d :jx}},{- :hy {* :d :jy}})  // OH - j*|HC|
}}}}}}}}}

{circleby2points -1 0 1 0 0.5}
-> no circle:
points are too far apart

{circleby2points -1 0 1 0 1}
-> one circle:
opposite ends of diameter with centre (0,0)

{circleby2points -1 0 1 0 {sqrt 2}}
-> two circles:
(0,1.0000000000000002)
(0,-1.0000000000000002)

rosetta's task:

{circleby2points 0.1234 0.9876 0.8765 0.2345 2.0}
-> two circles:
(1.8631118016581893,1.974211801658189)
(-0.8632118016581896,-0.7521118016581892)

{circleby2points 0.0000 2.0000 0.0000 0.0000 1.0}
-> one circle: opposite ends of diameter with centre (0,1)

{circleby2points 0.1234 0.9876 0.1234 0.9876 2.0}
-> same points

{circleby2points 0.1234 0.9876 0.8765 0.2345 0.5}
-> no circle, points are too far apart

{circleby2points 0.1234 0.9876 0.1234 0.9876 0.0}
-> radius is zero


mulInv: function [a0, b0][
    [a b x0]: @[a0 b0 0]
    result: 1
    if b = 1 -> return result
    while [a > 1][
        q: a / b
        a: a % b
        tmp: a
        a: b
        b: tmp
        result: result - q * x0
        tmp: x0
        x0: result
        result: tmp
    ]
    if result < 0 -> result: result + b0
    return result
]

chineseRemainder: function [N, A][
    prod: 1
    s: 0

    loop N 'x -> prod: prod * x

    loop.with:'i N 'x [
        p: prod / x
        s: s + (mulInv p x) * p * A\[i]
    ]
    return s % prod
]

print chineseRemainder [3 5 7] [2 3 2]


# Usage: GAWK -f CHINESE_REMAINDER_THEOREM.AWK
BEGIN {
    len = split("3 5 7", n)
    len = split("2 3 2", a)
    printf("%d\n", chineseremainder(n, a, len))
}
function chineseremainder(n, a, len,    p, i, prod, sum) {
    prod = 1
    sum = 0
    for (i = 1; i <= len; i++)
        prod *= n[i]
    for (i = 1; i <= len; i++) {
        p = prod / n[i]
        sum += a[i] * mulinv(p, n[i]) * p
    }
    return sum % prod
}
function mulinv(a, b,    b0, t, q, x0, x1) {
    # returns x where (a * x) % b == 1
    b0 = b
    x0 = 0
    x1 = 1
    if (b == 1)
        return 1
    while (a > 1) {
        q = int(a / b)
        t = b
        b = a % b
        a = t
        t = x0
        x0 = x1 - q * x0
        x1 = t
    }
    if (x1 < 0)
        x1 += b0
    return x1
}


'[RC] Circles of given radius through two points
for i = 1 to 5
    read x1, y1, x2, y2,r
    print i;") ";x1, y1, x2, y2,r
    call twoCircles x1, y1, x2, y2,r
next
end

'p1                p2           r
data 0.1234, 0.9876,    0.8765, 0.2345,    2.0
data 0.0000, 2.0000,    0.0000, 0.0000,    1.0
data 0.1234, 0.9876,    0.1234, 0.9876,    2.0
data 0.1234, 0.9876,    0.8765, 0.2345,    0.5
data 0.1234, 0.9876,    0.1234, 0.9876,    0.0

sub  twoCircles  x1, y1, x2, y2,r

    if x1=x2 and y1=y2 then '2.If the points are coincident
        if r=0 then ' unless r==0.0
            print "It will be a single point (";x1;",";y1;") of radius 0"
            exit sub
        else
            print "There are any number of circles via single point (";x1;",";y1;") of radius ";r
            exit sub
        end if
    end if
    r2 = sqr((x1-x2)^2+(y1-y2)^2)/2 'half distance between points
    if r<r2 then
        print "Points are too far apart (";2*r2;") - there are no circles of radius ";r
        exit sub
    end if

    'else, calculate two centers
    cx=(x1+x2)/2 'middle point
    cy=(y1+y2)/2
    'should move from middle point along perpendicular by dd2
    dd2=sqr(r^2-r2^2)   'perpendicular distance
    dx1=x2-cx   'vector to middle point
    dy1=y2-cy
    dx = 0-dy1/r2*dd2   'perpendicular:
    dy = dx1/r2*dd2     'rotate and scale
    print "(";cx+dy;",";cy+dx;")"   'two points, with (+)
    print "(";cx-dy;",";cy-dx;")"   'and (-)

end sub


#include <stdio.h>

// returns x where (a * x) % b == 1
int mul_inv(int a, int b)
{
	int b0 = b, t, q;
	int x0 = 0, x1 = 1;
	if (b == 1) return 1;
	while (a > 1) {
		q = a / b;
		t = b, b = a % b, a = t;
		t = x0, x0 = x1 - q * x0, x1 = t;
	}
	if (x1 < 0) x1 += b0;
	return x1;
}

int chinese_remainder(int *n, int *a, int len)
{
	int p, i, prod = 1, sum = 0;

	for (i = 0; i < len; i++) prod *= n[i];

	for (i = 0; i < len; i++) {
		p = prod / n[i];
		sum += a[i] * mul_inv(p, n[i]) * p;
	}

	return sum % prod;
}

int main(void)
{
	int n[] = { 3, 5, 7 };
	int a[] = { 2, 3, 2 };

	printf("%d\n", chinese_remainder(n, a, sizeof(n)/sizeof(n[0])));
	return 0;
}


function distance(p1, p2)
    local dx = (p1.x-p2.x)
    local dy = (p1.y-p2.y)
    return math.sqrt(dx*dx + dy*dy)
end

function findCircles(p1, p2, radius)
    local seperation = distance(p1, p2)
    if seperation == 0.0 then
        if radius == 0.0 then
            print("No circles can be drawn through ("..p1.x..", "..p1.y..")")
        else
            print("Infinitely many circles can be drawn through ("..p1.x..", "..p1.y..")")
        end
    elseif seperation == 2*radius then
        local cx = (p1.x+p2.x)/2
        local cy = (p1.y+p2.y)/2
        print("Given points are opposite ends of a diameter of the circle with center ("..cx..", "..cy..") and radius "..radius)
    elseif seperation > 2*radius then
        print("Given points are further away from each other than a diameter of a circle with radius "..radius)
    else
        local mirrorDistance = math.sqrt(math.pow(radius,2) - math.pow(seperation/2,2))
        local dx = p2.x - p1.x
        local dy = p1.y - p2.y
        local ax = (p1.x + p2.x) / 2
        local ay = (p1.y + p2.y) / 2
        local mx = mirrorDistance * dx / seperation
        local my = mirrorDistance * dy / seperation
        c1 = {x=ax+my, y=ay+mx}
        c2 = {x=ax-my, y=ay-mx}

        print("Two circles are possible.")
        print("Circle C1 with center ("..c1.x..", "..c1.y.."), radius "..radius)
        print("Circle C2 with center ("..c2.x..", "..c2.y.."), radius "..radius)
    end
    print()
end

cases = {
    {x=0.1234, y=0.9876},   {x=0.8765, y=0.2345},
    {x=0.0000, y=2.0000},   {x=0.0000, y=0.0000},
    {x=0.1234, y=0.9876},   {x=0.1234, y=0.9876},
    {x=0.1234, y=0.9876},   {x=0.8765, y=0.2345},
    {x=0.1234, y=0.9876},   {x=0.1234, y=0.9876}
}
radii = { 2.0, 1.0, 2.0, 0.5, 0.0 }
for i=1, #radii do
    print("Case "..i)
    findCircles(cases[i*2-1], cases[i*2], radii[i])
end


using System;
using System.Linq;

namespace ChineseRemainderTheorem
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] n = { 3, 5, 7 };
            int[] a = { 2, 3, 2 };

            int result = ChineseRemainderTheorem.Solve(n, a);

            int counter = 0;
            int maxCount = n.Length - 1;
            while (counter <= maxCount)
            {
                Console.WriteLine($"{result} ≡ {a[counter]} (mod {n[counter]})");
                counter++;
            }
        }
    }

    public static class ChineseRemainderTheorem
    {
        public static int Solve(int[] n, int[] a)
        {
            int prod = n.Aggregate(1, (i, j) => i * j);
            int p;
            int sm = 0;
            for (int i = 0; i < n.Length; i++)
            {
                p = prod / n[i];
                sm += a[i] * ModularMultiplicativeInverse(p, n[i]) * p;
            }
            return sm % prod;
        }

        private static int ModularMultiplicativeInverse(int a, int mod)
        {
            int b = a % mod;
            for (int x = 1; x < mod; x++)
            {
                if ((b * x) % mod == 1)
                {
                    return x;
                }
            }
            return 1;
        }
    }
}


drawCircles := proc(x1, y1, x2, y2, r, $)
	local c1, c2, p1, p2;
	use geometry in
		if x1 = x2 and y1 = y2 then
			if r = 0 then
				printf("The circle is a point at [%a, %a].\n", x1, y1);
			else
				printf("The two points are the same. Infinite circles can be drawn.\n");
			end if;
		elif evalf(distance(point(A, x1, y1), point(B, x2, y2))) >r*2 then
				printf("The two points are too far apart. No circles can be drawn.\n");
		else
			circle(P1Cir, [A, r]);#make a circle around the first point
			circle(P2Cir, [B, r]);#make a circle around the second point
			intersection('i', P1Cir, P2Cir);
			#the intersection of the above 2 circles should give you the centers of the two circles you need to draw
			c1 := plottools[circle](coordinates(`if`(type(i, list), i[1], i)), r);#make the first circle
			c2 := plottools[circle](coordinates(`if`(type(i, list), i[2], i)), r);#make the second circle
			plots[display](c1, c2, scaling = constrained);#draw
		end if;
	end use;
end proc:

drawCircles(0.1234, 0.9876, 0.8765, 0.2345, 2.0);
drawCircles(0.0000, 2.0000, 0.0000, 0.0000, 1.0);
drawCircles(0.1234, 0.9876, 0.1234, 0.9876, 2.0);
drawCircles(0.1234, 0.9876, 0.8765, 0.2345, 0.5);
drawCircles(0.1234, 0.9876, 0.1234, 0.9876, 0.0);


Off[Solve::ratnz];
circs::invrad = "The radius is invalid.";
circs::equpts = "The given points (`1`, `2`) are equivalent.";
circs::dist =
  "The given points (`1`, `2`) and (`3`, `4`) are too far apart for \
radius `5`.";
circs[_, _, 0.] := Message[circs::invrad];
circs[{p1x_, p1y_}, {p1x_, p1y_}, _] :=
  Message[circs::equpts, p1x, p1y];
circs[p1 : {p1x_, p1y_}, p2 : {p2x_, p2y_}, r_] /;
  EuclideanDistance[p1, p2] > 2 r :=
 Message[circs::dist, p1x, p1y, p2x, p2y, r];
circs[p1 : {p1x_, p1y_}, p2 : {p2x_, p2y_}, r_] :=
 Values /@
  Solve[Abs[x - p1x]^2 + Abs[y - p1y]^2 ==
    Abs[x - p2x]^2 + Abs[y - p2y]^2 == r^2, {x, y}];


// Requires C++17
#include <iostream>
#include <numeric>
#include <vector>
#include <execution>

template<typename _Ty> _Ty mulInv(_Ty a, _Ty b) {
	_Ty b0 = b;
	_Ty x0 = 0;
	_Ty x1 = 1;

	if (b == 1) {
		return 1;
	}

	while (a > 1) {
		_Ty q = a / b;
		_Ty amb = a % b;
		a = b;
		b = amb;

		_Ty xqx = x1 - q * x0;
		x1 = x0;
		x0 = xqx;
	}

	if (x1 < 0) {
		x1 += b0;
	}

	return x1;
}

template<typename _Ty> _Ty chineseRemainder(std::vector<_Ty> n, std::vector<_Ty> a) {
	_Ty prod = std::reduce(std::execution::seq, n.begin(), n.end(), (_Ty)1, [](_Ty a, _Ty b) { return a * b; });

	_Ty sm = 0;
	for (int i = 0; i < n.size(); i++) {
		_Ty p = prod / n[i];
		sm += a[i] * mulInv(p, n[i]) * p;
	}

	return sm % prod;
}

int main() {
	vector<int> n = { 3, 5, 7 };
	vector<int> a = { 2, 3, 2 };

	cout << chineseRemainder(n,a) << endl;

	return 0;
}


/* define helper function */
vabs(a):= sqrt(a.a);
realp(e):=freeof(%i, e);

/* get a general solution */
sol: block(
  [p1: [x1, y1], p2: [x2, y2], c:  [x0, y0], eq],
  local(r),
  eq: [vabs(p1-c) = r, vabs(p2-c) = r],
  load(to_poly_solve),
  assume(r>0),
  args(to_poly_solve(eq, c, use_grobner = true)))$

/* use general solution for concrete case */
getsol(sol, x1, y1, x2, y2, r):=block([n, lsol],
  if [x1, y1]=[x2, y2] then (
    print("infinity many solutions"),
    return('infmany)),
  lsol: sublist(''sol, 'realp),
  n: length(lsol),
  if n=0 then (
    print("no solutions"),
    [])
  else if n=1 then (
    print("single solution"),
    lsol[1])
  else if [assoc('x0, lsol[1]), assoc('y0, lsol[1])]=[assoc('x0, lsol[2]), assoc('y0, lsol[2])] then (
    print("single solution"),
    lsol[1])
  else (
    print("two solutions"),
    lsol))$

/* [x1, y1, x2, y2, r] */
d[1]: [0.1234, 0.9876,    0.8765, 0.2345,    2];
d[2]: [0.0000, 2.0000,    0.0000, 0.0000,    1];
d[3]: [0,      0,         0,      1,         0.4];
d[4]: [0,      0,         0,      0,         0.4];

apply('getsol, cons(sol, d[1]));
apply('getsol, cons(sol, d[2]));
apply('getsol, cons(sol, d[3]));
apply('getsol, cons(sol, d[4]));


П0	С/П	П1	С/П	П2	С/П	П3	С/П	П4
ИП2	ИП0	-	x^2	ИП3	ИП1	-	x^2	+	КвКор	П5
ИП0	ИП2	+	2	/	П6	ИП1	ИП3	+	2	/	П7
ИП4	x^2	ИП5	2	/	x^2	-	КвКор	ИП5	/	П8
ИП6	ИП1	ИП3	-	ИП8	*	П9	+	ПA
ИП6	ИП9	-	ПC
ИП7	ИП2	ИП0	-	ИП8	*	П9	+	ПB
ИП7	ИП9	-	ПD
ИП5	x#0	97	8	4	ИНВ	С/П
ИП4	2	*	ИП5	-	ПE	x#0	97	ИПB	ИПA	8	5	ИНВ	С/П
ИПE	x>=0	97	8	3	ИНВ	С/П
ИПD	ИПC	ИПB	ИПA	С/П


MODULE Circles;
FROM EXCEPTIONS IMPORT AllocateSource,ExceptionSource,GetMessage,RAISE;
FROM FormatString IMPORT FormatString;
FROM LongMath IMPORT sqrt;
FROM LongStr IMPORT RealToStr;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;

VAR
    TextWinExSrc : ExceptionSource;

TYPE
    Point = RECORD
        x,y : LONGREAL;
    END;
    Pair = RECORD
        a,b : Point;
    END;

PROCEDURE Distance(p1,p2 : Point) : LONGREAL;
VAR dx,dy : LONGREAL;
BEGIN
    dx := p1.x - p2.x;
    dy := p1.y - p2.y;
    RETURN sqrt(dx*dx + dy*dy)
END Distance;

PROCEDURE Equal(p1,p2 : Point) : BOOLEAN;
BEGIN
    RETURN (p1.x=p2.x) AND (p1.y=p2.y)
END Equal;

PROCEDURE WritePoint(p : Point);
VAR buf : ARRAY[0..63] OF CHAR;
BEGIN
    WriteString("(");
    RealToStr(p.x, buf);
    WriteString(buf);
    WriteString(", ");
    RealToStr(p.y, buf);
    WriteString(buf);
    WriteString(")");
END WritePoint;

PROCEDURE FindCircles(p1,p2 : Point; r : LONGREAL) : Pair;
VAR
    distance,diameter,mirrorDistance,dx,dy : LONGREAL;
    center : Point;
BEGIN
    IF r < 0.0 THEN RAISE(TextWinExSrc, 0, "the radius can't be negative") END;
    IF (r = 0.0) AND NOT Equal(p1,p2) THEN RAISE(TextWinExSrc, 0, "No circles can ever be drawn") END;
    IF r = 0.0 THEN RETURN Pair{p1,p1} END;
    IF Equal(p1,p2) THEN RAISE(TextWinExSrc, 0, "an infinite number of circles can be drawn") END;
    distance := Distance(p1,p2);
    diameter := 2.0 * r;
    IF distance > diameter THEN RAISE(TextWinExSrc, 0, "the points are too far apart to draw a circle") END;
    center := Point{(p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0};
    IF distance = diameter THEN RETURN Pair{center, center} END;
    mirrorDistance := sqrt(r * r - distance * distance / 4.0);
    dx := (p2.x - p1.x) * mirrorDistance / distance;
    dy := (p2.y - p1.y) * mirrorDistance / distance;
    RETURN Pair{
        {center.x - dy, center.y + dx},
        {center.x + dy, center.y - dx}
    }
END FindCircles;

PROCEDURE Print(p1,p2 : Point; r : LONGREAL) : BOOLEAN;
VAR
    buf : ARRAY[0..63] OF CHAR;
    result : Pair;
BEGIN
    WriteString("For points ");
    WritePoint(p1);
    WriteString(" and ");
    WritePoint(p2);
    WriteString(" with radius ");
    RealToStr(r, buf);
    WriteString(buf);
    WriteLn;

    result := FindCircles(p1,p2,r);
    IF Equal(result.a, result.b) THEN
        WriteString("there is just one circle with the center at ");
        WritePoint(result.a);
        WriteLn;
    ELSE
        WriteString("there are two circles with centers at ");
        WritePoint(result.a);
        WriteString(" and ");
        WritePoint(result.b);
        WriteLn;
    END;
    WriteLn;
    RETURN TRUE
EXCEPT
    GetMessage(buf);
    WriteString(buf);
    WriteLn;
    WriteLn;
    RETURN FALSE
END Print;

VAR p0,p1,p2,p3 : Point;
BEGIN
    AllocateSource(TextWinExSrc);
    p0 := Point{0.1234,0.9876};
    p1 := Point{0.8765,0.2345};
    p2 := Point{0.0000,2.0000};
    p3 := Point{0.0000,0.0000};

    Print(p0,p1,2.0);
    Print(p2,p3,1.0);
    Print(p0,p0,2.0);
    Print(p0,p1,0.5);
    Print(p0,p0,0.0);

    ReadChar
END Circles.


(ns test-p.core
  (:require [clojure.math.numeric-tower :as math]))

(defn extended-gcd
  "The extended Euclidean algorithm
  Returns a list containing the GCD and the Bézout coefficients
  corresponding to the inputs. "
  [a b]
  (cond (zero? a) [(math/abs b) 0 1]
        (zero? b) [(math/abs a) 1 0]
        :else (loop [s 0
                     s0 1
                     t 1
                     t0 0
                     r (math/abs b)
                     r0 (math/abs a)]
                (if (zero? r)
                  [r0 s0 t0]
                  (let [q (quot r0 r)]
                    (recur (- s0 (* q s)) s
                           (- t0 (* q t)) t
                           (- r0 (* q r)) r))))))

(defn chinese_remainder
  " Main routine to return the chinese remainder "
  [n a]
  (let [prod (apply * n)
        reducer (fn [sum [n_i a_i]]
                  (let [p (quot prod n_i)           ; p = prod / n_i
                        egcd (extended-gcd p n_i)   ; Extended gcd
                        inv_p (second egcd)]        ; Second item is the inverse
                    (+ sum (* a_i inv_p p))))
        sum-prod (reduce reducer 0 (map vector n a))] ; Replaces the Python for loop to sum
                                                      ; (map vector n a) is same as
        ;                                             ; Python's version Zip (n, a)
    (mod sum-prod prod)))                             ; Result line

(def n [3 5 7])
(def a [2 3 2])

(println (chinese_remainder n a))


import math

type
  Point = tuple[x, y: float]
  Circle = tuple[x, y, r: float]

proc circles(p1, p2: Point, r: float): tuple[c1, c2: Circle] =
  if r == 0: raise newException(ValueError,
    "radius of zero")
  if p1 == p2: raise newException(ValueError,
    "coincident points gives infinite number of Circles")

  # delta x, delta y between points
  let (dx, dy) = (p2.x - p1.x, p2.y - p1.y)
  # dist between points
  let q = sqrt(dx*dx + dy*dy)
  if q > 2.0*r: raise newException(ValueError,
    "separation of points > diameter")

  # halfway point
  let p3: Point = ((p1.x+p2.x)/2, (p1.y+p2.y)/2)
  # distance along the mirror line
  let d = sqrt(r*r - (q/2)*(q/2))
  # One answer
  result.c1 = (p3.x - d*dy/q, p3.y + d*dx/q, abs(r))
  # The other answer
  result.c2 = (p3.x + d*dy/q, p3.y - d*dx/q, abs(r))

const tries: seq[tuple[p1, p2: Point, r: float]] =
  @[((0.1234, 0.9876), (0.8765, 0.2345), 2.0),
    ((0.0000, 2.0000), (0.0000, 0.0000), 1.0),
    ((0.1234, 0.9876), (0.1234, 0.9876), 2.0),
    ((0.1234, 0.9876), (0.8765, 0.2345), 0.5),
    ((0.1234, 0.9876), (0.1234, 0.9876), 0.0)]

for p1, p2, r in tries.items:
  echo "Through points:"
  echo "  ", p1
  echo "  ", p2
  echo "  and radius ", r
  echo "You can construct the following circles:"
  try:
    let (c1, c2) = circles(p1, p2, r)
    echo "  ", c1
    echo "  ", c2
  except ValueError:
    echo "  ERROR: ", getCurrentExceptionMsg()
  echo ""


(* Task : Circles of given radius through two points *)

(* Types to make code even more readable *)
type point = float * float
type radius = float
type circle = Circle of radius * point
type circ_output =
    NoSolution
    | OneSolution of circle
    | TwoSolutions of circle * circle
    | InfiniteSolutions
;;

(* Actual function *)
let circles_2points_radius (x1, y1 : point) (x2, y2 : point) (r : radius) =
    let (dx, dy) = (x2 -. x1, y2 -. y1) in
    let dist_sq = dx *. dx +. dy *. dy in
    match dist_sq, r with
    (* Edge case - point circles *)
    | 0., 0. -> OneSolution (Circle (r, (x1, y1)))
    (* Edge case - coinciding points *)
    | 0., _ -> InfiniteSolutions
    | _ ->
        let side_len_sq = r *. r -. dist_sq /. 4. in
        let midp = ((x1 +. x2) *. 0.5, (y1 +. y2) *. 0.5) in
        (* Points are too far apart; same whether r = 0 or not *)
        if side_len_sq < 0. then NoSolution
        (* Points are on diameter *)
        else if side_len_sq = 0. then OneSolution (Circle (r, midp))
        else
            (* A right-angle triangle is made with the radius as hyp, dist/2 as one side *)
            let side_len = sqrt (r *. r -. dist_sq /. 4.) in
            let dist = sqrt dist_sq in
            (*  A 90-deg rotation of a vector (x, y) is obtained by either (y, -x) or (-y, x)
                We need both, so pick one and the other is its negative.
            *)
            let (vx, vy) = (-. dy *. side_len /. dist, dx *. side_len /. dist) in
            let c1 = Circle (r, (fst midp +. vx, snd midp +. vy)) in
            let c2 = Circle (r, (fst midp -. vx, snd midp -. vy)) in
            TwoSolutions (c1, c2)
;;

(* Relevant tests and printing *)
let tests = [
    (0.1234, 0.9876), (0.8765, 0.2345), 2.0;
    (0.0000, 2.0000), (0.0000, 0.0000), 1.0;
    (0.1234, 0.9876), (0.1234, 0.9876), 2.0;
    (0.1234, 0.9876), (0.8765, 0.2345), 0.5;
    (0.1234, 0.9876), (0.1234, 0.9876), 0.0;
] ;;

let format_output (out : circ_output) = match out with
    | NoSolution -> print_endline "No solution"
    | OneSolution (Circle (_, (x, y))) -> Printf.printf "One solution: (%.6f, %.6f)\n" x y
    | TwoSolutions (Circle (_, (x1, y1)), Circle (_, (x2, y2))) ->
        Printf.printf "Two solutions: (%.6f, %.6f) and (%.6f, %.6f)\n" x1 y1 x2 y2
    | InfiniteSolutions -> print_endline "Infinite solutions"
;;

let _ =
    List.iter
    (fun (a, b, c) -> circles_2points_radius a b c |> format_output)
    tests
;;


crt = (n,a) ->
	sum = 0
	prod = n.reduce (a,c) -> a*c
	for [ni,ai] in _.zip n,a
		p = prod // ni
		sum += ai * p * mulInv p,ni
	sum % prod

mulInv = (a,b) ->
	b0 = b
	[x0,x1] = [0,1]
	if b==1 then return 1
	while a > 1
		q = a // b
		[a,b] = [b, a % b]
		[x0,x1] = [x1-q*x0, x0]
	if x1 < 0 then x1 += b0
	x1

print crt [3,5,7], [2,3,2]


(defun chinese-remainder (am)
"Calculates the Chinese Remainder for the given set of integer modulo pairs.
 Note: All the ni and the N must be coprimes."
  (loop :for (a . m) :in am
        :with mtot = (reduce #'* (mapcar #'(lambda(X) (cdr X)) am))
        :with sum  = 0
        :finally (return (mod sum mtot))
        :do
   (incf sum (* a (invmod (/ mtot m) m) (/ mtot m)))))


: circleCenter(x1, y1, x2, y2, r)
| d xmid ymid r1 md |
   x2 x1 - sq  y2 y1 - sq + sqrt -> d
   x1 x2 + 2 / -> xmid
   y1 y2 + 2 / -> ymid
   2 r * -> r1

   d 0.0 == ifTrue: [ "Infinite number of circles" . return ]
   d r1 == ifTrue:  [ System.Out "One circle: (" << xmid << ", " << ymid << ")" << cr return ]
   d r1  > ifTrue:  [ "No circle" . return ]

   r sq d 2 / sq - sqrt ->md

   System.Out "C1 : (" << xmid y1 y2 - md * d / + << ", " << ymid x2 x1 - md * d / + << ")" << cr
   System.Out "C2 : (" << xmid y1 y2 - md * d / - << ", " << ymid x2 x1 - md * d / - << ")" << cr
;


/*REXX pgm finds 2 circles with a specific radius given two (X,Y) points*/
  a.=''
  a.1=0.1234 0.9876 0.8765 0.2345 2
  a.2=0.0000 2.0000 0.0000 0.0000 1
  a.3=0.1234 0.9876 0.1234 0.9876 2
  a.4=0.1234 0.9876 0.8765 0.2345 0.5
  a.5=0.1234 0.9876 0.1234 0.9876 0

  Say '     x1      y1      x2      y2  radius   cir1x   cir1y   cir2x   cir2y'
  Say ' ------  ------  ------  ------  ------  ------  ------  ------  ------'
  Do j=1 By 1 While a.j<>''
    Do k=1 For 4
      w.k=f(word(a.j,k))
      End
    Say w.1 w.2 w.3 w.4 format(word(a.j,5),5,1)  twocircles(a.j)
    End
  Exit

twocircles: Procedure
  Parse Arg px py qx qy r .
  If r=0 Then
    Return ' radius of zero gives no circles.'
  x=(qx-px)/2
  y=(qy-py)/2
  bx=px+x
  by=py+y
  pb=rxCalcsqrt(x**2+y**2)
  If pb=0 Then
    Return ' coincident points give infinite circles'
  If pb>r Then
    Return ' points are too far apart for the given radius'
  cb=rxCalcsqrt(r**2-pb**2)
  x1=y*cb/pb
  y1=x*cb/pb
  Return f(bx-x1) f(by+y1) f(bx+x1) f(by-y1)

f: Return format(arg(1),2,4) /* format a number with 4 dec dig.*/

::requires 'rxMath' library


def extended_gcd(a, b)
    last_remainder, remainder = a.abs, b.abs
    x, last_x = 0, 1

    until remainder == 0
        tmp = remainder
        quotient, remainder = last_remainder.divmod(remainder)
        last_remainder = tmp
        x, last_x = last_x - quotient * x, x
    end

    return last_remainder, last_x * (a < 0 ? -1 : 1)
end

def invmod(e, et)
    g, x = extended_gcd(e, et)
    unless g == 1
        raise "Multiplicative inverse modulo does not exist"
    end
    return x % et
end

def chinese_remainder(mods, remainders)
    max = mods.product
    series = remainders.zip(mods).map { |r, m| r * max * invmod(max // m, m) // m }
    return series.sum % max
end

puts chinese_remainder([3, 5, 7], [2, 3, 2])
puts chinese_remainder([5, 7, 9, 11], [1, 2, 3, 4])


import std.stdio, std.algorithm;

T chineseRemainder(T)(in T[] n, in T[] a) pure nothrow @safe @nogc
in {
    assert(n.length == a.length);
} body {
    static T mulInv(T)(T a, T b) pure nothrow @safe @nogc {
        auto b0 = b;
        T x0 = 0, x1 = 1;
        if (b == 1)
            return T(1);
        while (a > 1) {
            immutable q = a / b;
            immutable amb = a % b;
            a = b;
            b = amb;
            immutable xqx = x1 - q * x0;
            x1 = x0;
            x0 = xqx;
        }
        if (x1 < 0)
            x1 += b0;
        return x1;
    }

    immutable prod = reduce!q{a * b}(T(1), n);

    T p = 1, sm = 0;
    foreach (immutable i, immutable ni; n) {
        p = prod / ni;
        sm += a[i] * mulInv(p, ni) * p;
    }
    return sm % prod;
}

void main() {
    immutable n = [3, 5, 7],
              a = [2, 3, 2];
    chineseRemainder(n, a).writeln;
}


program ChineseRemainderTheorem;

uses
  System.SysUtils, Velthuis.BigIntegers;

function mulInv(a, b: BigInteger): BigInteger;
var
  b0, x0, x1, q, amb, xqx: BigInteger;
begin
  b0 := b;
  x0 := 0;
  x1 := 1;

  if (b = 1) then
    exit(1);

  while (a > 1) do
  begin
    q := a div b;
    amb := a mod b;
    a := b;
    b := amb;
    xqx := x1 - q * x0;
    x1 := x0;
    x0 := xqx;
  end;

  if (x1 < 0) then
    x1 := x1 + b0;

  Result := x1;
end;

function chineseRemainder(n: TArray<BigInteger>; a: TArray<BigInteger>)
  : BigInteger;
var
  i: Integer;
  prod, p, sm: BigInteger;
begin
  prod := 1;

  for i := 0 to High(n) do
    prod := prod * n[i];

  p := 0;
  sm := 0;

  for i := 0 to High(n) do
  begin
    p := prod div n[i];
    sm := sm + a[i] * mulInv(p, n[i]) * p;
  end;
  Result := sm mod prod;
end;

var
  n, a: TArray<BigInteger>;

begin
  n := [3, 5, 7];
  a := [2, 3, 2];

  Writeln(chineseRemainder(n, a).ToString);
end.


func mul_inv a b . x1 .
  b0 = b
  x1 = 1
  if b <> 1
    while a > 1
      q = a div b
      t = b
      b = a mod b
      a = t
      t = x0
      x0 = x1 - q * x0
      x1 = t
    .
    if x1 < 0
      x1 += b0
    .
  .
.
func remainder . n[] a[] r .
  prod = 1
  sum = 0
  for i range len n[]
    prod *= n[i]
  .
  for i range len n[]
    p = prod / n[i]
    call mul_inv p n[i] h
    sum += a[i] * h * p
    r = sum mod prod
  .
.
n[] = [ 3 5 7 ]
a[] = [ 2 3 2 ]
call remainder n[] a[] h
print h


(lib 'math)
math.lib v1.10 ® EchoLisp
Lib: math.lib loaded.

(crt-solve '(2 3 2) '(3 5 7))
   → 23
(crt-solve '(2 3 2) '(7 1005 15))
💥 error: mod[i] must be co-primes : assertion failed : 1005


with javascript_semantics
constant tests = {{0.1234, 0.9876, 0.8765, 0.2345, 2.0},
                  {0.0000, 2.0000, 0.0000, 0.0000, 1.0},
                  {0.1234, 0.9876, 0.1234, 0.9876, 2.0},
                  {0.1234, 0.9876, 0.8765, 0.2345, 0.5},
                  {0.1234, 0.9876, 0.1234, 0.9876, 0.0}}
for i=1 to length(tests) do
    atom {x1,y1,x2,y2,r} = tests[i],
         xd = x2-x1, yd = y1-y2,
         s2 = xd*xd+yd*yd, sep = sqrt(s2),
         xh = (x1+x2)/2, yh = (y1+y2)/2
    string txt
    if sep=0 then
        txt = "same points/"&iff(r=0?"radius is zero":"infinite solutions")
    elsif sep=2*r then
        txt = sprintf("opposite ends of diameter with centre {%.4f,%.4f}",{xh,yh})
    elsif sep>2*r then
        txt = sprintf("too far apart (%.4f > %.4f)",{sep,2*r})
    else
        atom md = sqrt(r*r-s2/4), xs = md*xd/sep, ys = md*yd/sep
        txt = sprintf("{%.4f,%.4f} and {%.4f,%.4f}",{xh+ys,yh+xs,xh-ys,yh-xs})
    end if
    printf(1,"points {%.4f,%.4f}, {%.4f,%.4f} with radius %.1f ==> %s\n",{x1,y1,x2,y2,r,txt})
end for


defmodule Chinese do
  def remainder(mods, remainders) do
    max = Enum.reduce(mods, fn x,acc -> x*acc end)
    Enum.zip(mods, remainders)
    |> Enum.map(fn {m,r} -> Enum.take_every(r..max, m) |> MapSet.new end)
    |> Enum.reduce(fn set,acc -> MapSet.intersection(set, acc) end)
    |> MapSet.to_list
  end
end

IO.inspect Chinese.remainder([3,5,7], [2,3,2])
IO.inspect Chinese.remainder([10,4,9], [11,22,19])
IO.inspect Chinese.remainder([11,12,13], [10,4,12])


-module(crt).
-import(lists, [zip/2, unzip/1, foldl/3, sum/1]).
-export([egcd/2, mod/2, mod_inv/2, chinese_remainder/1]).

egcd(_, 0) -> {1, 0};
egcd(A, B) ->
    {S, T} = egcd(B, A rem B),
    {T, S - (A div B)*T}.

mod_inv(A, B) ->
    {X, Y} = egcd(A, B),
    if
        A*X + B*Y =:= 1 -> X;
        true -> undefined
    end.

mod(A, M) ->
    X = A rem M,
    if
        X < 0 -> X + M;
        true -> X
    end.

calc_inverses([], []) -> [];
calc_inverses([N | Ns], [M | Ms]) ->
    case mod_inv(N, M) of
        undefined -> undefined;
        Inv -> [Inv | calc_inverses(Ns, Ms)]
    end.

chinese_remainder(Congruences) ->
    {Residues, Modulii} = unzip(Congruences),
    ModPI = foldl(fun(A, B) -> A*B end, 1, Modulii),
    CRT_Modulii = [ModPI div M || M <- Modulii],
    case calc_inverses(CRT_Modulii, Modulii) of
        undefined -> undefined;
        Inverses ->
            Solution = sum([A*B || {A,B} <- zip(CRT_Modulii,
                                    [A*B || {A,B} <- zip(Residues, Inverses)])]),
            mod(Solution, ModPI)
    end.


twoci: Proc Options(main);
 Dcl 1 *(5),
      2 m1x Dec Float Init(0.1234,     0,0.1234,0.1234,0.1234),
      2 m1y Dec Float Init(0.9876,     2,0.9876,0.9876,0.9876),
      2 m2x Dec Float Init(0.8765,     0,0.1234,0.8765,0.1234),
      2 m2y Dec Float Init(0.2345,     0,0.9876,0.2345,0.9876),
      2 r   Dec Float Init(     2,     1,     2,0.5   ,     0);
 Dcl i Bin Fixed(31);
 Put Edit('     x1     y1     x2     y2  r '||
          '  cir1x   cir1y   cir2x   cir2y')(Skip,a);
 Put Edit(' ====== ====== ====== ======  = '||
          ' ======  ======  ======  ======')(Skip,a);
 Do i=1 To 5;
   Put Edit(m1x(i),m1y(i),m2x(i),m2y(i),r(i))
           (Skip,4(f(7,4)),f(3));
   Put Edit(twocircles(m1x(i),m1y(i),m2x(i),m2y(i),r(i)))(a);
   End;

 twoCircles: proc(m1x,m1y,m2x,m2y,r) Returns(Char(50) Var);
 Dcl (m1x,m1y,m2x,m2y,r) Dec Float;
 Dcl (cx,cy,bx,by,pb,x,y,x1,y1) Dec Float;
 Dcl res Char(50) Var;
 If r=0 then return(' radius of zero gives no circles.');
 x=(m2x-m1x)/2;
 y=(m2y-m1y)/2;
 bx=m1x+x;
 by=m1y+y;
 pb=sqrt(x**2+y**2);
 cx=(m2x-m1x)/2;
 cy=(m2y-m1y)/2;
 bx=m1x+x;
 by=m1y+y;
 pb=sqrt(x**2+y**2)
 if pb=0 then return(' coincident points give infinite circles');
 if pb>r then return(' points are too far apart for the given radius');
 cb=sqrt(r**2-pb**2);
 x1=y*cb/pb;
 y1=x*cb/pb
 Put String(res) Edit((bx-x1),(by+y1),(bx+x1),(by-y1))(4(f(8,4)));
 Return(res);
 End;
 End;


DataSection
  DataStart:
  Data.d  0.1234, 0.9876,   0.8765, 0.2345,   2.0
  Data.d  0.0000, 2.0000,   0.0000, 0.0000,   1.0
  Data.d  0.1234, 0.9876,   0.1234, 0.9876,   2.0
  Data.d  0.1234, 0.9876,   0.9765, 0.2345,   0.5
  Data.d  0.1234, 0.9876,   0.1234, 0.9876,   0.0
  DataEnd:
EndDataSection
Macro MaxRec : (?DataEnd-?DataStart)/SizeOf(P2r)-1 : EndMacro

Structure Pxy   : x.d         : y.d           : EndStructure
Structure P2r   : p1.Pxy      : p2.Pxy  : r.d : EndStructure
Structure PData : Prec.P2r[5]                 : EndStructure

Procedure.s cCenter(Rec.i)
  If Rec<0 Or Rec>MaxRec : ProcedureReturn "Data set number incorrect." : EndIf
  *myP.PData=?DataStart
  r.d=*myP\Prec[Rec]\r
  If r<=0.0 : ProcedureReturn "Illegal radius." : EndIf
  r2.d=2.0*r
  x1.d=*myP\Prec[Rec]\p1\x : x2.d=*myP\Prec[Rec]\p2\x
  y1.d=*myP\Prec[Rec]\p1\y : y2.d=*myP\Prec[Rec]\p2\y
  d.d=Sqr(Pow(x2-x1,2)+Pow(y2-y1,2))
  If d=0.0 : ProcedureReturn "Identical points, infinite number of circles." : EndIf
  If d>r2  : ProcedureReturn "No circles possible." : EndIf
  z.d=Sqr(Pow(r,2)-Pow(d/2.0,2))
  x3.d =(x1+x2)/2.0     :   y3.d =(y1+y2)/2.0
  cx1.d=x3+z*(y1-y2)/d  :   cy1.d=y3+z*(x2-x1)/d
  cx2.d=x3-z*(y1-y2)/d  :   cy2.d=y3-z*(x2-x1)/d
  If d=r2 : ProcedureReturn "Single circle at ("+StrD(cx1)+","+StrD(cy1)+")" : EndIf
  ProcedureReturn "("+StrD(cx1)+","+StrD(cy1)+") and ("+StrD(cx2)+","+StrD(cy2)+")"
EndProcedure

If OpenConsole("")
  For i=0 To MaxRec : PrintN(cCenter(i)) : Next : Input()
EndIf


let rec sieve cs x N =
    match cs with
    | [] -> Some(x)
    | (a,n)::rest ->
        let arrProgress = Seq.unfold (fun x -> Some(x, x+N)) x
        let firstXmodNequalA = Seq.tryFind (fun x -> a = x % n)
        match firstXmodNequalA (Seq.take n arrProgress) with
        | None -> None
        | Some(x) -> sieve rest x (N*n)

[ [(2,3);(3,5);(2,7)];
  [(10,11); (4,22); (9,19)];
  [(10,11); (4,12); (12,13)] ]
|> List.iter (fun congruences ->
    let cs =
        congruences
        |> List.map (fun (a,n) -> (a % n, n))
        |> List.sortBy (snd>>(~-))
    let an = List.head cs
    match sieve (List.tail cs) (fst an) (snd an) with
    | None    -> printfn "no solution"
    | Some(x) -> printfn "result = %i" x
)


from collections import namedtuple
from math import sqrt

Pt = namedtuple('Pt', 'x, y')
Circle = Cir = namedtuple('Circle', 'x, y, r')

def circles_from_p1p2r(p1, p2, r):
    'Following explanation at http://mathforum.org/library/drmath/view/53027.html'
    if r == 0.0:
        raise ValueError('radius of zero')
    (x1, y1), (x2, y2) = p1, p2
    if p1 == p2:
        raise ValueError('coincident points gives infinite number of Circles')
    # delta x, delta y between points
    dx, dy = x2 - x1, y2 - y1
    # dist between points
    q = sqrt(dx**2 + dy**2)
    if q > 2.0*r:
        raise ValueError('separation of points > diameter')
    # halfway point
    x3, y3 = (x1+x2)/2, (y1+y2)/2
    # distance along the mirror line
    d = sqrt(r**2-(q/2)**2)
    # One answer
    c1 = Cir(x = x3 - d*dy/q,
             y = y3 + d*dx/q,
             r = abs(r))
    # The other answer
    c2 = Cir(x = x3 + d*dy/q,
             y = y3 - d*dx/q,
             r = abs(r))
    return c1, c2

if __name__ == '__main__':
    for p1, p2, r in [(Pt(0.1234, 0.9876), Pt(0.8765, 0.2345), 2.0),
                      (Pt(0.0000, 2.0000), Pt(0.0000, 0.0000), 1.0),
                      (Pt(0.1234, 0.9876), Pt(0.1234, 0.9876), 2.0),
                      (Pt(0.1234, 0.9876), Pt(0.8765, 0.2345), 0.5),
                      (Pt(0.1234, 0.9876), Pt(0.1234, 0.9876), 0.0)]:
        print('Through points:\n  %r,\n  %r\n  and radius %f\nYou can construct the following circles:'
              % (p1, p2, r))
        try:
            print('  %r\n  %r\n' % circles_from_p1p2r(p1, p2, r))
        except ValueError as v:
            print('  ERROR: %s\n' % (v.args[0],))


USING: math.algebra prettyprint ;
{ 2 3 2 } { 3 5 7 } chinese-remainder .


: egcd ( a b -- a b )
    dup 0= IF
        2drop 1 0
    ELSE
        dup -rot /mod               \ -- b r=a%b q=a/b
        -rot recurse                \ -- q (s,t) = egcd(b, r)
        >r swap [email protected] * - r> swap      \ -- t (s - q*t)
    THEN ;

: egcd>gcd  ( a b x y -- n )  \ calculate gcd from egcd
    rot * -rot * + ;

: mod-inv  ( a m -- a' )     \ modular inverse with coprime check
    2dup egcd over >r egcd>gcd r> swap 1 <> -24 and throw ;

: array-product ( adr count -- n )
    1 -rot  cells bounds ?DO  i @ *  cell +LOOP ;

: crt-from-array  ( adr1 adr2 count -- n )
    2dup array-product   locals| M count m[] a[] |
    0  \ result
    count 0 DO
        m[] i cells + @
        dup M swap /
        dup rot mod-inv *
        a[] i cells + @ * +
    LOOP  M mod ;

create crt-residues[]  10 cells allot
create crt-moduli[]    10 cells allot

: crt ( .... n -- n )  \ takes pairs of "n (mod m)" from stack.
    10 min  locals| n |
    n 0 DO
        crt-moduli[] i cells + !
        crt-residues[] i cells + !
    LOOP
    crt-residues[] crt-moduli[] n crt-from-array ;


#include "gcd.bas"
function mul_inv( a as integer, b as integer ) as integer
	if b = 1 then return 1
    for i as integer = 1 to b
        if a*i mod b = 1 then return i
    next i
    return 0
end function

function chinese_remainder(n() as integer, a() as integer) as integer
	dim as integer p, i, prod = 1, sum = 0, ln = ubound(n)
	for p = 0 to ln-1
	    for i = p+1 to ln
	        if gcd(n(i), n(p))>1 then
	            print "N not coprime"
	            end
	        end if
	    next i
	next p
	for i = 0 to ln
	    prod *= n(i)
	next i
	for i = 0 to ln
	    p = prod/n(i)
	    sum += a(i) * mul_inv(p, n(i))*p
	next i
	return sum mod prod
end function

dim as integer n(0 to 2) = { 3, 5, 7 }
dim as integer a(0 to 2) = { 2, 3, 2 }

print chinese_remainder(n(), a())


#lang racket
(require plot/utils)

(define (circle-centers p1 p2 r)
  (when (zero? r) (err "zero radius."))
  (when (equal? p1 p2) (err "the points coinside."))
  ; the midle point
  (define m (v/ (v+ p1 p2) 2))
  ; the vector connecting given points
  (define d (v/ (v- p1 p2) 2))
  ; the distance between the center of the circle and the middle point
  (define ξ (- (sqr r) (vmag^2 d)))
  (when (negative? ξ) (err "given radius is less then the distance between points."))
  ; the unit vector orthogonal to the delta
  (define n (vnormalize (orth d)))
  ; the shift along the direction orthogonal to the delta
  (define x (v* n (sqrt ξ)))
  (values (v+ m x) (v- m x)))

;; error message
(define (err m) (error "Impossible to build a circle:" m))

;; returns a vector which is orthogonal to the geven one
(define orth (match-lambda [(vector x y) (vector y (- x))]))


/** arguments:
       [r, m, d=0]  where r and m are arrays of the remainder terms r and the
               modulus terms m respectively.  These must be of the same length.
    returns
       x, the unique solution mod N where N is the product of all the M terms where x >= d.
*/
ChineseRemainder[r, m, d=0] :=
{
   if length[r] != length[m]
   {
      println["ChineseRemainder:  r and m must be arrays of the same length."]
      return undef
   }

   N = product[m]

   y = new array
   z = new array
   x = 0
   for i = rangeOf[m]
   {
      [email protected] = N / [email protected]
      [email protected] = modInverse[[email protected], [email protected]]
      if [email protected] == undef
      {
         println["ChineseRemainder:  modInverse returned undef for modInverse[" + [email protected] + ", " + [email protected] + "]"]
         return undef
      }

      x = x + [email protected] [email protected] [email protected]
   }

   xp = x mod N
   f = d div N
   r = f * N + xp
   if r < d
      r = r + N

   return r
}

println[ChineseRemainder[[2,3,2],[3,5,7]] ]


import integers.modinv

def crt( congruences ) =
    N = product( n | (_, n) <- congruences )
    sum( a*modinv(N/n, n)*N/n | (a, n) <- congruences ) mod N

println( crt([(2, 3), (3, 5), (2, 7)]) )


package main

import (
    "fmt"
    "math/big"
)

var one = big.NewInt(1)

func crt(a, n []*big.Int) (*big.Int, error) {
    p := new(big.Int).Set(n[0])
    for _, n1 := range n[1:] {
        p.Mul(p, n1)
    }
    var x, q, s, z big.Int
    for i, n1 := range n {
        q.Div(p, n1)
        z.GCD(nil, &s, n1, &q)
        if z.Cmp(one) != 0 {
            return nil, fmt.Errorf("%d not coprime", n1)
        }
        x.Add(&x, s.Mul(a[i], s.Mul(&s, &q)))
    }
    return x.Mod(&x, p), nil
}

func main() {
    n := []*big.Int{
        big.NewInt(3),
        big.NewInt(5),
        big.NewInt(7),
    }
    a := []*big.Int{
        big.NewInt(2),
        big.NewInt(3),
        big.NewInt(2),
    }
    fmt.Println(crt(a, n))
}


/*REXX pgm finds 2 circles with a specific radius given 2 (X1,Y1) and (X2,Y2) ctr points*/
@.=; @.1= 0.1234   0.9876    0.8765    0.2345    2
     @.2= 0        2         0         0         1
     @.3= 0.1234   0.9876    0.1234    0.9876    2
     @.4= 0.1234   0.9876    0.8765    0.2345    0.5
     @.5= 0.1234   0.9876    0.1234    0.9876    0
say '     x1        y1        x2        y2     radius          circle1x  circle1y  circle2x  circle2y'
say '  ════════  ════════  ════════  ════════  ══════          ════════  ════════  ════════  ════════'
       do  j=1  while  @.j\=='';  parse var @.j  p1 p2 p3 p4 r           /*points, radii*/
       say fmt(p1)  fmt(p2)  fmt(p3)  fmt(p4)    center(r/1, 9)    "───► "      2circ(@.j)
       end   /*j*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
2circ: procedure; parse arg px py qx qy r .;     x= (qx-px)/2;          y= (qy-py)/2
                                                bx= px + x;            by= py + y
                                                pb= sqrt(x**2 + y**2)
       if r = 0  then return  'radius of zero yields no circles.'
       if pb==0  then return  'coincident points give infinite circles.'
       if pb >r  then return  'points are too far apart for the specified radius.'
       cb= sqrt(r**2 - pb**2);     x1= y * cb / pb;                       y1= x * cb / pb
                    return  fmt(bx-x1)   fmt(by+y1)   fmt(bx+x1)   fmt(by-y1)
/*──────────────────────────────────────────────────────────────────────────────────────*/
fmt:   arg f;   f= right( format(f, , 4), 9);         _= f  /*format # with 4 dec digits*/
       if pos(.,f)>0 & pos('E',f)=0  then f= strip(f,'T',0) /*strip trailing 0s if .& ¬E*/
       return left( strip(f, 'T', .), length(_) )           /*strip trailing dec point. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt:  procedure; arg x; if x=0  then return 0;  d=digits(); numeric digits;  h=d+6;  m.=9
       numeric form;  parse value format(x,2,1,,0) 'E0'  with  g "E" _ .;  g=g *.5'e'_ % 2
         do j=0  while h>9;      m.j=h;               h=h%2+1;       end  /*j*/
         do k=j+5  to 0  by -1;  numeric digits m.k;  g=(g+x/g)*.5;  end  /*k*/;  return g


class ChineseRemainderTheorem {
    static int chineseRemainder(int[] n, int[] a) {
        int prod = 1
        for (int i = 0; i < n.length; i++) {
            prod *= n[i]
        }

        int p, sm = 0
        for (int i = 0; i < n.length; i++) {
            p = prod.intdiv(n[i])
            sm += a[i] * mulInv(p, n[i]) * p
        }
        return sm % prod
    }

    private static int mulInv(int a, int b) {
        int b0 = b
        int x0 = 0
        int x1 = 1

        if (b == 1) {
            return 1
        }

        while (a > 1) {
            int q = a.intdiv(b)
            int amb = a % b
            a = b
            b = amb
            int xqx = x1 - q * x0
            x1 = x0
            x0 = xqx
        }

        if (x1 < 0) {
            x1 += b0
        }

        return x1
    }

    static void main(String[] args) {
        int[] n = [3, 5, 7]
        int[] a = [2, 3, 2]
        println(chineseRemainder(n, a))
    }
}


Pt     = Struct.new(:x, :y)
Circle = Struct.new(:x, :y, :r)

def circles_from(pt1, pt2, r)
  raise ArgumentError, "Infinite number of circles, points coincide." if pt1 == pt2 && r > 0
  # handle single point and r == 0
  return [Circle.new(pt1.x, pt1.y, r)] if pt1 == pt2 && r == 0
  dx, dy = pt2.x - pt1.x, pt2.y - pt1.y
  # distance between points
  q = Math.hypot(dx, dy)
  # Also catches pt1 != pt2 && r == 0
  raise ArgumentError, "Distance of points > diameter." if q > 2.0*r
  # halfway point
  x3, y3 = (pt1.x + pt2.x)/2.0, (pt1.y + pt2.y)/2.0
  d = (r**2 - (q/2)**2)**0.5
  [Circle.new(x3 - d*dy/q, y3 + d*dx/q, r),
   Circle.new(x3 + d*dy/q, y3 - d*dx/q, r)].uniq
end

# Demo:
ar = [[Pt.new(0.1234, 0.9876), Pt.new(0.8765, 0.2345), 2.0],
      [Pt.new(0.0000, 2.0000), Pt.new(0.0000, 0.0000), 1.0],
      [Pt.new(0.1234, 0.9876), Pt.new(0.1234, 0.9876), 2.0],
      [Pt.new(0.1234, 0.9876), Pt.new(0.8765, 0.2345), 0.5],
      [Pt.new(0.1234, 0.9876), Pt.new(0.1234, 0.9876), 0.0]]

ar.each do |p1, p2, r|
  print "Given points:\n  #{p1.values},\n  #{p2.values}\n  and radius #{r}\n"
  begin
    circles = circles_from(p1, p2, r)
    puts "You can construct the following circles:"
    circles.each{|c| puts "  #{c}"}
  rescue ArgumentError => e
    puts e
  end
  puts
end


import Control.Monad (zipWithM)

egcd :: Int -> Int -> (Int, Int)
egcd _ 0 = (1, 0)
egcd a b = (t, s - q * t)
  where
    (s, t) = egcd b r
    (q, r) = a `quotRem` b

modInv :: Int -> Int -> Either String Int
modInv a b =
  case egcd a b of
    (x, y)
      | a * x + b * y == 1 -> Right x
      | otherwise ->
        Left $ "No modular inverse for " ++ show a ++ " and " ++ show b

chineseRemainder :: [Int] -> [Int] -> Either String Int
chineseRemainder residues modulii =
  zipWithM modInv crtModulii modulii >>=
  (Right . (`mod` modPI) . sum . zipWith (*) crtModulii . zipWith (*) residues)
  where
    modPI = product modulii
    crtModulii = (modPI `div`) <$> modulii

main :: IO ()
main =
  mapM_ (putStrLn . either id show) $
  uncurry chineseRemainder <$>
  [ ([10, 4, 12], [11, 12, 13])
  , ([10, 4, 9], [11, 22, 19])
  , ([2, 3, 2], [3, 5, 7])
  ]


html "
"
html "
No.	x1	y1	x2	y2	r	cir x1	cir y1	cir x2	cir y2
"
for i = 1 to 5
    read x1, y1, x2, y2,r
html "
";i;"	";x1;"	";y1;"	";x2;"	";y2;"	";r;"	"
    gosub [twoCircles]
next
html "
"
end

'p1                p2           r
data 0.1234, 0.9876,    0.8765, 0.2345,    2.0
data 0.0000, 2.0000,    0.0000, 0.0000,    1.0
data 0.1234, 0.9876,    0.1234, 0.9876,    2.0
data 0.1234, 0.9876,    0.8765, 0.2345,    0.5
data 0.1234, 0.9876,    0.1234, 0.9876,    0.0

[twoCircles]

    if x1=x2 and y1=y2 then '2.If the points are coincident
        if r=0 then ' unless r==0.0
            html "It will be a single point (";x1;",";y1;") of radius 0
"
            RETURN
        else
            html "There are any number of circles via single point (";x1;",";y1;") of radius ";r;"
"
            RETURN
        end if
    end if
    r2 = sqr((x1-x2)^2+(y1-y2)^2)/2			'half distance between points
    if r<r2 then
        html "Points are too far apart (";2*r2;") - there are no circles of radius ";r
        RETURN
    end if

    'else, calculate two centers
    cx=(x1+x2)/2 					'middle point
    cy=(y1+y2)/2
    'should move from middle point along perpendicular by dd2
    dd2=sqr(r^2-r2^2)					'perpendicular distance
    dx1=x2-cx   					'vector to middle point
    dy1=y2-cy
    dx = 0-dy1/r2*dd2   				'perpendicular:
    dy = dx1/r2*dd2     				'rotate and scale
    html "";cx+dy;"	";cy+dx;"	"   	'two points, with (+)
    html "";cx-dy;"	";cy-dx;"
" 	'and (-)
RETURN


use std::fmt;

#[derive(Clone,Copy)]
struct Point {
    x: f64,
    y: f64
}

fn distance (p1: Point, p2: Point) -> f64 {
    ((p1.x - p2.x).powi(2) + (p1.y - p2.y).powi(2)).sqrt()
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:.4}, {:.4})", self.x, self.y)
    }
}

fn describe_circle(p1: Point, p2: Point, r: f64) {
    let sep = distance(p1, p2);

    if sep == 0. {
        if r == 0. {
            println!("No circles can be drawn through {}", p1);
        } else {
            println!("Infinitely many circles can be drawn through {}", p1);
        }
    } else if sep == 2.0 * r {
        println!("Given points are opposite ends of a diameter of the circle with center ({:.4},{:.4}) and r {:.4}",
                (p1.x+p2.x) / 2.0, (p1.y+p2.y) / 2.0, r);
    } else if sep > 2.0 * r {
        println!("Given points are farther away from each other than a diameter of a circle with r {:.4}", r);
    } else {
        let mirror_dist = (r.powi(2) - (sep / 2.0).powi(2)).sqrt();

        println!("Two circles are possible.");
        println!("Circle C1 with center ({:.4}, {:.4}), r {:.4} and Circle C2 with center ({:.4}, {:.4}), r {:.4}",
                ((p1.x + p2.x) / 2.0) + mirror_dist * (p1.y-p2.y)/sep, (p1.y+p2.y) / 2.0 + mirror_dist*(p2.x-p1.x)/sep,
                r,
                (p1.x+p2.x) / 2.0 - mirror_dist*(p1.y-p2.y)/sep, (p1.y+p2.y) / 2.0 - mirror_dist*(p2.x-p1.x)/sep, r);
    }
}

fn main() {
    let points: Vec<(Point, Point)> = vec![
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.8765, y: 0.2345 }),
        (Point { x: 0.0000, y: 2.0000 }, Point { x: 0.0000, y: 0.0000 }),
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.1234, y: 0.9876 }),
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.8765, y: 0.2345 }),
        (Point { x: 0.1234, y: 0.9876 }, Point { x: 0.1234, y: 0.9876 })
    ];
    let radii: Vec<f64> = vec![2.0, 1.0, 2.0, 0.5, 0.0];

    for (p, r) in points.into_iter().zip(radii.into_iter()) {
        println!("\nPoints: ({}, {}), Radius: {:.4}", p.0, p.1, r);
        describe_circle(p.0, p.1, r);
    }
}


import org.scalatest.FunSuite
import math._

case class V2(x: Double, y: Double) {
  val distance = hypot(x, y)
  def /(other: V2) = V2((x+other.x) / 2.0, (y+other.y) / 2.0)
  def -(other: V2) = V2(x-other.x,y-other.y)
  override def equals(other: Any) = other match {
    case p: V2 => abs(x-p.x) <  0.0001 && abs(y-p.y) <  0.0001
    case _ => false
  }
  override def toString = f"($x%.4f, $y%.4f)"
}

case class Circle(center: V2, radius: Double)

class PointTest extends FunSuite {
  println("       p1               p2         r    result")
  Seq(
    (V2(0.1234, 0.9876), V2(0.8765, 0.2345), 2.0, Seq(Circle(V2(1.8631, 1.9742), 2.0), Circle(V2(-0.8632, -0.7521), 2.0))),
    (V2(0.0000, 2.0000), V2(0.0000, 0.0000), 1.0, Seq(Circle(V2(0.0, 1.0), 1.0))),
    (V2(0.1234, 0.9876), V2(0.1234, 0.9876), 2.0, "coincident points yields infinite circles"),
    (V2(0.1234, 0.9876), V2(0.8765, 0.2345), 0.5, "radius is less then the distance between points"),
    (V2(0.1234, 0.9876), V2(0.1234, 0.9876), 0.0, "radius of zero yields no circles")
  ) foreach { v =>
    print(s"${v._1} ${v._2}  ${v._3}: ")
    circles(v._1, v._2, v._3) match {
      case Right(list) => println(list mkString ",")
        assert(list === v._4)
      case Left(error) => println(error)
        assert(error === v._4)
    }
  }

  def circles(p1: V2, p2: V2, radius: Double) = if (radius == 0.0) {
      Left("radius of zero yields no circles")
    } else if (p1 == p2) {
      Left("coincident points yields infinite circles")
    } else if (radius * 2 < (p1-p2).distance) {
      Left("radius is less then the distance between points")
    } else {
      Right(circlesThruPoints(p1, p2, radius))
    } ensuring { result =>
      result.isLeft || result.right.get.nonEmpty
    }

  def circlesThruPoints(p1: V2, p2: V2, radius: Double): Seq[Circle] = {
    val diff = p2 - p1
    val d = pow(pow(radius, 2) - pow(diff.distance / 2, 2), 0.5)
    val mid = p1 / p2
    Seq(
      Circle(V2(mid.x - d * diff.y / diff.distance, mid.y + d * diff.x / diff.distance), abs(radius)),
      Circle(V2(mid.x + d * diff.y / diff.distance, mid.y - d * diff.x / diff.distance), abs(radius))).distinct
  }
}


link numbers   # for gcd()

procedure main()
    write(cr([3,5,7],[2,3,2]) | "No solution!")
    write(cr([10,4,9],[11,22,19]) | "No solution!")
end

procedure cr(n,a)
    if 1 ~= gcd(n[i := !*n],a[i]) then fail  # Not pairwise coprime
    (prod := 1, sm := 0)
    every prod *:= !n
    every p := prod/(ni := n[i := !*n]) do sm +:= a[i] * mul_inv(p,ni) * p
    return sm%prod
end

procedure mul_inv(a,b)
    if b = 1 then return 1
    (b0 := b, x0 := 0, x1 := 1)
    while q := (1 < a)/b do {
        (t := a, a := b, b := t%b)
        (t := x0, x0 := x1-q*t, x1 := t)
        }
    return if x1 < 0 then x1+b0 else x1
end


(import (scheme base)
        (scheme inexact)
        (scheme write))

;; c1 and c2 are pairs (x y), r a positive radius
(define (find-circles c1 c2 r)
  (define x-coord car) ; for easier to read coordinate extraction from list
  (define y-coord cadr)
  (define (approx= a b) (< (- a b) 0.000001)) ; equal within tolerance
  (define (avg a b) (/ (+ a b) 2))
  (define (distance pt1 pt2)
    (sqrt (+ (square (- (x-coord pt1) (x-coord pt2)))
             (square (- (y-coord pt1) (y-coord pt2))))))
  (define (equal-points? pt1 pt2)
    (and (approx= (x-coord pt1) (x-coord pt2))
         (approx= (y-coord pt1) (y-coord pt2))))
  (define (delete-duplicate pts) ; assume no more than two points in list
    (if (and (= 2 (length pts))
             (equal-points? (car pts) (cadr pts)))
      (list (car pts)) ; keep the first only
      pts))
  ;
  (let ((d (distance c1 c2)))
    (cond ((equal-points? c1 c2) ; coincident points
           (if (> r 0)
             'infinite   ; r > 0
             (list c1))) ; else r = 0
          ((< (* 2 r) d)
           '()) ; circle cannot reach both points, as too far apart
          ((approx= r 0.0) ; r = 0, no circles, as points differ
           '())
          (else ; find up to two circles meeting c1 and c2
            (let* ((mid-pt (list (avg (x-coord c1) (x-coord c2))
                                 (avg (y-coord c1) (y-coord c2))))
                   (offset (sqrt (- (square r)
                                    (square (* 0.5 d)))))
                   (delta-cx (/ (- (x-coord c1) (x-coord c2)) d))
                   (delta-cy (/ (- (y-coord c1) (y-coord c2)) d)))
              (delete-duplicate
                (list (list (- (x-coord mid-pt) (* offset delta-cx))
                            (+ (y-coord mid-pt) (* offset delta-cy)))
                      (list (+ (x-coord mid-pt) (* offset delta-cx))
                            (- (y-coord mid-pt) (* offset delta-cy))))))))))

;; work through the input examples, outputting results
(for-each
  (lambda (c1 c2 r)
    (let ((result (find-circles c1 c2 r)))
      (display "p1: ") (display c1)
      (display " p2: ") (display c2)
      (display " r: ") (display (number->string r))
      (display " => ")
      (cond ((eq? result 'infinite)
             (display "Infinite number of circles"))
            ((null? result)
             (display "No circles"))
            (else
              (display result)))
      (newline)))
  '((0.1234 0.9876) (0.0000 2.0000) (0.1234 0.9876) (0.1234 0.9876) (0.1234 0.9876))
  '((0.8765 0.2345) (0.0000 0.0000) (0.1234 0.9876) (0.8765 0.2345) (0.1234 0.9876))
  '(2.0 1.0 2.0 0.5 0.0))


import static java.util.Arrays.stream;

public class ChineseRemainderTheorem {

    public static int chineseRemainder(int[] n, int[] a) {

        int prod = stream(n).reduce(1, (i, j) -> i * j);

        int p, sm = 0;
        for (int i = 0; i < n.length; i++) {
            p = prod / n[i];
            sm += a[i] * mulInv(p, n[i]) * p;
        }
        return sm % prod;
    }

    private static int mulInv(int a, int b) {
        int b0 = b;
        int x0 = 0;
        int x1 = 1;

        if (b == 1)
            return 1;

        while (a > 1) {
            int q = a / b;
            int amb = a % b;
            a = b;
            b = amb;
            int xqx = x1 - q * x0;
            x1 = x0;
            x0 = xqx;
        }

        if (x1 < 0)
            x1 += b0;

        return x1;
    }

    public static void main(String[] args) {
        int[] n = {3, 5, 7};
        int[] a = {2, 3, 2};
        System.out.println(chineseRemainder(n, a));
    }
}


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

const type: point is new struct
    var float: x is 0.0;
    var float: y is 0.0;
  end struct;

const func point: point (in float: x, in float: y) is func
  result
    var point: aPoint is point.value;
  begin
    aPoint.x := x;
    aPoint.y := y;
  end func;

const func float: distance (in point: p1, in point: p2) is
  return sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);

const proc: findCircles (in point: p1, in point: p2, in float: radius) is func
  local
    var float: separation is 0.0;
    var float: mirrorDistance is 0.0;
  begin
    separation := distance(p1, p2);
    if separation = 0.0 then
      if radius = 0.0 then
        write("Radius of zero. No circles can be drawn through (");
      else
        write("Infinitely many circles can be drawn through (");
      end if;
      writeln(p1.x digits 4 <& ", " <& p1.y digits 4 <& ")");
    elsif separation = 2.0 * radius then
      writeln("Given points are opposite ends of a diameter of the circle with center (" <&
              (p1.x + p2.x) / 2.0 digits 4 <& ", " <& (p1.y + p2.y) / 2.0 digits 4 <& ") and radius " <&
              radius digits 4);
    elsif separation > 2.0 * radius then
      writeln("Given points are farther away from each other than a diameter of a circle with radius " <&
              radius digits 4);
    else
      mirrorDistance := sqrt(radius ** 2 - (separation / 2.0) ** 2);
      writeln("Two circles are possible.");
      writeln("Circle C1 with center (" <&
              (p1.x + p2.x) / 2.0 + mirrorDistance*(p1.y - p2.y) / separation digits 4 <& ", " <&
              (p1.y + p2.y) / 2.0 + mirrorDistance*(p2.x - p1.x) / separation digits 4 <& "), radius " <&
              radius digits 4);
      writeln("Circle C2 with center (" <&
              (p1.x + p2.x) / 2.0 - mirrorDistance*(p1.y - p2.y) / separation digits 4 <& ", " <&
              (p1.y + p2.y) / 2.0 - mirrorDistance*(p2.x - p1.x) / separation digits 4 <& "), radius " <&
              radius digits 4);
    end if;
  end func;

const proc: main is func
  local
    const array array float: cases is [] (
        [] (0.1234, 0.9876, 0.8765, 0.2345, 2.0),
        [] (0.0000, 2.0000, 0.0000, 0.0000, 1.0),
        [] (0.1234, 0.9876, 0.1234, 0.9876, 2.0),
        [] (0.1234, 0.9876, 0.8765, 0.2345, 0.5),
        [] (0.1234, 0.9876, 0.1234, 0.9876, 0.0));
    var integer: index is 0;
  begin
    for index range 1 to 5 do
      writeln("Case " <& index <& ":");
      findCircles(point(cases[index][1], cases[index][2]),
                  point(cases[index][3], cases[index][4]), cases[index][5]);
    end for;
  end func;


function crt(num, rem) {
  let sum = 0;
  const prod = num.reduce((a, c) => a * c, 1);

  for (let i = 0; i < num.length; i++) {
    const [ni, ri] = [num[i], rem[i]];
    const p = Math.floor(prod / ni);
    sum += ri * p * mulInv(p, ni);
  }
  return sum % prod;
}

function mulInv(a, b) {
  const b0 = b;
  let [x0, x1] = [0, 1];

  if (b === 1) {
    return 1;
  }
  while (a > 1) {
    const q = Math.floor(a / b);
    [a, b] = [b, a % b];
    [x0, x1] = [x1 - q * x0, x0];
  }
  if (x1 < 0) {
    x1 += b0;
  }
  return x1;
}

console.log(crt([3,5,7], [2,3,2]))


real matrix centers(real colvector a, real colvector b, real scalar r) {
	real matrix rot
	real scalar d, u, v
	d = norm(b-a)
	if (r == 0 | d == 0) {
		if (r == 0 & d == 0) {
			return((a,a))
		} else {
			return(J(2, 2, .))
		}
	} else if (d <= 2*r) {
		u = d/(2*r)
		v = sqrt(1-u^2)
		rot = u,-v\v,u
		return((rot*(b-a),rot'*(b-a))*r/d:+a)
	} else {
		return(J(2, 2, .))
	}
}


import Foundation

struct Point: Equatable {
    var x: Double
    var y: Double
}

struct Circle {
  var center: Point
  var radius: Double

  static func circleBetween(
    _ p1: Point,
    _ p2: Point,
    withRadius radius: Double
  ) -> (Circle, Circle?)? {
    func applyPoint(_ p1: Point, _ p2: Point, op: (Double, Double) -> Double) -> Point {
      return Point(x: op(p1.x, p2.x), y: op(p1.y, p2.y))
    }

    func mul2(_ p: Point, mul: Double) -> Point {
      return Point(x: p.x * mul, y: p.y * mul)
    }

    func div2(_ p: Point, div: Double) -> Point {
      return Point(x: p.x / div, y: p.y / div)
    }

    func norm(_ p: Point) -> Point {
      return div2(p, div: (p.x * p.x + p.y * p.y).squareRoot())
    }

    guard radius != 0, p1 != p2 else {
      return nil
    }

    let diameter = 2 * radius
    let pq = applyPoint(p1, p2, op: -)
    let magPQ = (pq.x * pq.x + pq.y * pq.y).squareRoot()

    guard diameter >= magPQ else {
      return nil
    }

    let midpoint = div2(applyPoint(p1, p2, op: +), div: 2)
    let halfPQ = magPQ / 2
    let magMidC = abs(radius * radius - halfPQ * halfPQ).squareRoot()
    let midC = mul2(norm(Point(x: -pq.y, y: pq.x)), mul: magMidC)
    let center1 = applyPoint(midpoint, midC, op: +)
    let center2 = applyPoint(midpoint, midC, op: -)

    if center1 == center2 {
      return (Circle(center: center1, radius: radius), nil)
    } else {
      return (Circle(center: center1, radius: radius), Circle(center: center2, radius: radius))
    }
  }
}

let testCases = [
  (Point(x: 0.1234, y: 0.9876), Point(x: 0.8765, y: 0.2345), 2.0),
  (Point(x: 0.0000, y: 2.0000), Point(x: 0.0000, y: 0.0000), 1.0),
  (Point(x: 0.1234, y: 0.9876), Point(x: 0.1234, y: 0.9876), 2.0),
  (Point(x: 0.1234, y: 0.9876), Point(x: 0.8765, y: 0.2345), 0.5),
  (Point(x: 0.1234, y: 0.9876), Point(x: 0.1234, y: 0.9876), 0.0)
]

for testCase in testCases {
  switch Circle.circleBetween(testCase.0, testCase.1, withRadius: testCase.2) {
  case nil:
    print("No ans")
  case (let circle1, nil)?:
    print("One ans: \(circle1)")
  case (let circle1, let circle2?)?:
    print("Two ans: \(circle1) \(circle2)")
  }
}


# mul_inv(a;b) returns x where (a * x) % b == 1, or else null
def mul_inv(a; b):

  # state: [a, b, x0, x1]
  def iterate:
    .[0] as $a | .[1] as $b
    | if $a > 1 then
        if $b == 0 then null
        else ($a / $b | floor) as $q
           | [$b, ($a % $b), (.[3] - ($q * .[2])), .[2]] | iterate
        end
      else .
      end ;

  if (b == 1) then 1
  else [a,b,0,1] | iterate
       | if . == null then .
         else  .[3] | if . <  0 then . + b else . end
         end
  end;

def chinese_remainder(mods; remainders):
  (reduce mods[] as $i (1; . * $i)) as $prod
  | reduce range(0; mods|length) as $i
      (0;
       ($prod/mods[$i]) as $p
       | mul_inv($p; mods[$i]) as $mi
       | if $mi == null then error("nogo: p=\($p) mods[\($i)]=\(mods[$i])")
         else . + (remainders[$i] * $mi * $p)
         end )
  | . % $prod ;


function chineseremainder(n::Array, a::Array)
    Π = prod(n)
    mod(sum(ai * invmod(Π ÷ ni, ni) * (Π ÷ ni) for (ni, ai) in zip(n, a)), Π)
end

@show chineseremainder([3, 5, 7], [2, 3, 2])


// version 1.1.2

/* returns x where (a * x) % b == 1 */
fun multInv(a: Int, b: Int): Int {
    if (b == 1) return 1
    var aa = a
    var bb = b
    var x0 = 0
    var x1 = 1
    while (aa > 1) {
        val q = aa / bb
        var t = bb
        bb = aa % bb
        aa = t
        t = x0
        x0 = x1 - q * x0
        x1 = t
    }
    if (x1 < 0) x1 += b
    return x1
}

fun chineseRemainder(n: IntArray, a: IntArray): Int {
    val prod = n.fold(1) { acc, i -> acc * i }
    var sum = 0
    for (i in 0 until n.size) {
        val p = prod / n[i]
        sum += a[i] * multInv(p, n[i]) * p
    }
    return sum % prod
}

fun main(args: Array<String>) {
    val n = intArrayOf(3, 5, 7)
    val a = intArrayOf(2, 3, 2)
    println(chineseRemainder(n, a))
}


proc findCircles {p1 p2 r} {
    lassign $p1 x1 y1
    lassign $p2 x2 y2
    # Special case: coincident & zero size
    if {$x1 == $x2 && $y1 == $y2 && $r == 0.0} {
	return [list [list $x1 $y1 0.0]]
    }
    if {$r <= 0.0} {
	error "radius must be positive for sane results"
    }
    if {$x1 == $x2 && $y1 == $y2} {
	error "no sane solution: points are coincident"
    }

    # Calculate distance apart and separation vector
    set dx [expr {$x2 - $x1}]
    set dy [expr {$y2 - $y1}]
    set q [expr {hypot($dx, $dy)}]
    if {$q > 2*$r} {
	error "no solution: points are further apart than required diameter"
    }

    # Calculate midpoint
    set x3 [expr {($x1+$x2)/2.0}]
    set y3 [expr {($y1+$y2)/2.0}]
    # Fractional distance along the mirror line
    set f [expr {($r**2 - ($q/2.0)**2)**0.5 / $q}]
    # The two answers
    set c1 [list [expr {$x3 - $f*$dy}] [expr {$y3 + $f*$dx}] $r]
    set c2 [list [expr {$x3 + $f*$dy}] [expr {$y3 - $f*$dx}] $r]
    return [list $c1 $c2]
}


import std

def extended_gcd(a, b):
    var s = 0
    var old_s = 1
    var t = 1
    var old_t = 0
    var r = b
    var old_r = a

    while r != 0:
        let quotient = old_r / r
        old_r, r = r, old_r - quotient * r
        old_s, s = s, old_s - quotient * s
        old_t, t = t, old_t - quotient * t

    return old_r, old_s, old_t, t, s

def for2(xs, ys, fun): return for xs.length: fun(xs[_], ys[_])

def crt(xs, ys):
    let p = reduce(xs): _a * _b
    var r = 0
    for2(xs,ys) x, y:
        let q = p / x
        let z,s,_t,_qt,_qs = q.extended_gcd(x)
        if z != 1:
            return "ng " + x + " not coprime", 0
        if s < 0: r += y * (s + x) * q
        else:     r += y * s       * q
    return "ok", r % p

def print_crt(xs, ys):
    let msg, res = crt(xs, ys)
    print(msg + " " + res)

print_crt([3,5,7],[2,3,2])
print_crt([11,12,13],[10,4,12])
print_crt([11,22,19],[10,4,9])
print_crt([100,23],[19,0])


-- Taken from https://www.rosettacode.org/wiki/Sum_and_product_of_an_array#Lua
function prodf(a, ...) return a and a * prodf(...) or 1 end
function prodt(t) return prodf(unpack(t)) end

function mulInv(a, b)
    local b0 = b
    local x0 = 0
    local x1 = 1

    if b == 1 then
        return 1
    end

    while a > 1 do
        local q = math.floor(a / b)
        local amb = math.fmod(a, b)
        a = b
        b = amb
        local xqx = x1 - q * x0
        x1 = x0
        x0 = xqx
    end

    if x1 < 0 then
        x1 = x1 + b0
    end

    return x1
end

function chineseRemainder(n, a)
    local prod = prodt(n)

    local p
    local sm = 0
    for i=1,#n do
        p = prod / n[i]
        sm = sm + a[i] * mulInv(p, n[i]) * p
    end

    return math.fmod(sm, prod)
end

n = {3, 5, 7}
a = {2, 3, 2}
io.write(chineseRemainder(n, a))


Public Class CirclesOfGivenRadiusThroughTwoPoints
    Public Shared Sub Main()
        For Each valu In New Double()() {
        New Double() {0.1234, 0.9876, 0.8765, 0.2345, 2},
        New Double() {0.0, 2.0, 0.0, 0.0, 1},
        New Double() {0.1234, 0.9876, 0.1234, 0.9876, 2},
        New Double() {0.1234, 0.9876, 0.8765, 0.2345, 0.5},
        New Double() {0.1234, 0.9876, 0.1234, 0.9876, 0},
        New Double() {0.1234, 0.9876, 0.2345, 0.8765, 0}}
            Dim p = New Point(valu(0), valu(1)), q = New Point(valu(2), valu(3))
            Console.WriteLine($"Points {p} and {q} with radius {valu(4)}:")
            Try
                Console.WriteLine(vbTab & String.Join(" and ", FindCircles(p, q, valu(4))))
            Catch ex As Exception
                Console.WriteLine(vbTab & ex.Message)
            End Try
        Next
        If System.Diagnostics.Debugger.IsAttached Then Console.ReadKey()
    End Sub

    Private Shared Function FindCircles(ByVal p As Point, ByVal q As Point, ByVal rad As Double) As Point()
        If rad < 0 Then Throw New ArgumentException("Negative radius.")
        If rad = 0 Then Throw New InvalidOperationException(If(p = q,
            String.Format("{0} (degenerate circle)", {p}), "No circles."))
        If p = q Then Throw New InvalidOperationException("Infinite number of circles.")
        Dim dist As Double = Point.Distance(p, q), sqDist As Double = dist * dist,
            sqDiam As Double = 4 * rad * rad
        If sqDist > sqDiam Then Throw New InvalidOperationException(
            String.Format("Points are too far apart (by {0}).", sqDist - sqDiam))
        Dim midPoint As Point = New Point((p.X + q.X) / 2, (p.Y + q.Y) / 2)
        If sqDist = sqDiam Then Return {midPoint}
        Dim d As Double = Math.Sqrt(rad * rad - sqDist / 4),
            a As Double = d * (q.X - p.X) / dist, b As Double = d * (q.Y - p.Y) / dist
        Return {New Point(midPoint.X - b, midPoint.Y + a), New Point(midPoint.X + b, midPoint.Y - a)}
    End Function

    Public Structure Point
        Public ReadOnly Property X As Double
        Public ReadOnly Property Y As Double

        Public Sub New(ByVal ix As Double, ByVal iy As Double)
            Me.New() : X = ix : Y = iy
        End Sub

        Public Shared Operator =(ByVal p As Point, ByVal q As Point) As Boolean
            Return p.X = q.X AndAlso p.Y = q.Y
        End Operator

        Public Shared Operator <>(ByVal p As Point, ByVal q As Point) As Boolean
            Return p.X <> q.X OrElse p.Y <> q.Y
        End Operator

        Public Shared Function SquaredDistance(ByVal p As Point, ByVal q As Point) As Double
            Dim dx As Double = q.X - p.X, dy As Double = q.Y - p.Y
            Return dx * dx + dy * dy
        End Function

        Public Shared Function Distance(ByVal p As Point, ByVal q As Point) As Double
            Return Math.Sqrt(SquaredDistance(p, q))
        End Function

        Public Overrides Function ToString() As String
            Return $"({X}, {Y})"
        End Function
    End Structure
End Class


Function ChineseRemainder(n(), a()) {
	Function mul_inv(a, b) {
		if b==1 then =1 : exit
		b0=b
		x1=1 : x0=0
		while a>1
			q=a div b
			t=b : b=a mod b: a=t
			t=x0: x0=x1-q*x0:x1=t
		end while
		if x1<0 then x1+=b0
		=x1
	}
	def p, i, prod=1, sum
	for i=0 to  len(n())-1 {prod*=n(i)}
	for i=0 to  len(a())-1
		p=prod div n(i)
		sum+=a(i)*mul_inv(p, n(i))*p
	next
	=sum mod prod
}
Print ChineseRemainder((3,5,7), (2,3,2))


LOCAL p1 As point, p2 As point, rr As Double
CLOSE DATABASES ALL
SET FIXED ON
SET DECIMALS TO 4
CLEAR
CREATE CURSOR circles (xc1 B(4), yc1 B(4), xc2 B(4), yc2 B(4), rad B(4))
INSERT INTO circles VALUES (0.1234, 0.9876, 0.8765, 0.2345, 2.0)
INSERT INTO circles VALUES (0.0000, 2.0000, 0.0000, 0.0000, 1.0)
INSERT INTO circles VALUES (0.1234, 0.9876, 0.1234, 0.9876, 2.0)
INSERT INTO circles VALUES (0.1234, 0.9876, 0.8765, 0.2345, 0.5)
INSERT INTO circles VALUES (0.1234, 0.9876, 0.1234, 0.9876, 0.0)
GO TOP

p1 = NEWOBJECT("point")
p2 = NEWOBJECT("point")
SCAN
    p1.SetPoints(xc1, yc1)
    p2.SetPoints(xc2, yc2)
    rr = rad
    GetCircles(p1, p2, rr)
    ?
ENDSCAN

SET DECIMALS TO
SET FIXED OFF

PROCEDURE GetCircles(op1 As point, op2 As point, r As Double)
LOCAL ctr As point, half As point, lenhalf As Double, dist As Double, rot As point, c As String
ctr = NEWOBJECT("point")
half = NEWOBJECT("point")
ctr.SetPoints((op1.xc + op2.xc)/2, (op1.yc + op2.yc)/2)
half.SetPoints(op1.xc - ctr.xc, op1.yc - ctr.yc)
lenhalf = half.nLength
PrintPoints(op1, op2, r)
IF r < lenhalf
    ? "Cannot solve for these parameters."
    RETURN
ENDIF
IF lenhalf = 0
    ? "Points are coincident."
    RETURN
ENDIF
dist = SQRT(r^2 - lenhalf^2)/lenhalf
rot = NEWOBJECT("point")
rot.SetPoints(-dist*(op1.yc - ctr.yc) + ctr.xc, dist*(op1.xc - ctr.xc) + ctr.yc)
TEXT TO c TEXTMERGE NOSHOW PRETEXT 3
    Circle 1 (<<rot.xc>>, <<rot.yc>>)
ENDTEXT
? c
rot.SetPoints(-(rot.xc - ctr.xc) + ctr.xc, -((rot.yc - ctr.yc)) + ctr.yc)
TEXT TO c TEXTMERGE NOSHOW PRETEXT 3
    Circle 2 (<<rot.xc>>, <<rot.yc>>)
ENDTEXT
? c
ENDPROC

PROCEDURE PrintPoints(op1 As point, op2 As point, r As Double)
LOCAL lcTxt As String
TEXT TO lcTxt TEXTMERGE NOSHOW PRETEXT 3
    Points (<<op1.xc>>,<<op1.yc>>), (<<op2.xc>>,<<op2.yc>>) Radius <<r>>.
ENDTEXT
? lcTxt
ENDPROC

DEFINE CLASS point As Custom
xc = 0
yc = 0
nLength = 0

PROCEDURE Init
DODEFAULT()
ENDPROC

PROCEDURE SetPoints(tnx As Double, tny As Double)
THIS.xc = tnx
THIS.yc = tny
THIS.nLength = THIS.GetLength()
ENDPROC

FUNCTION GetLength()
RETURN SQRT(THIS.xc*THIS.xc + THIS.yc*THIS.yc)
ENDFUNC

ENDDEFINE


import math

const (
    two  = "two circles."
    r0   = "R==0.0 does not describe circles."
    co   = "coincident points describe an infinite number of circles."
    cor0 = "coincident points with r==0.0 describe a degenerate circle."
    diam = "Points form a diameter and describe only a single circle."
    far  = "Points too far apart to form circles."
)

struct Point {
	x f64
	y f64
}

fn circles(p1 Point, p2 Point, r f64) (Point, Point, string) {
	mut case := ''
	c1, c2 := p1, p2
    if p1 == p2 {
        if r == 0 {
            return p1, p1, cor0
        }
        case = co
        return c1, c2, case
    }
    if r == 0 {
        return p1, p2, r0
    }
    dx := p2.x - p1.x
    dy := p2.y - p1.y
    q := math.hypot(dx, dy)
    if q > 2*r {
        case = far
        return c1, c2, case
    }
    m := Point{(p1.x + p2.x) / 2, (p1.y + p2.y) / 2}
    if q == 2*r {
        return m, m, diam
    }
    d := math.sqrt(r*r - q*q/4)
    ox := d * dx / q
    oy := d * dy / q
    return Point{m.x - oy, m.y + ox}, Point{m.x + oy, m.y - ox}, two
}

struct Cir {
	p1 Point
	p2 Point
	r f64
}
const td = [
    Cir{Point{0.1234, 0.9876}, Point{0.8765, 0.2345}, 2.0},
    Cir{Point{0.0000, 2.0000}, Point{0.0000, 0.0000}, 1.0},
    Cir{Point{0.1234, 0.9876}, Point{0.1234, 0.9876}, 2.0},
    Cir{Point{0.1234, 0.9876}, Point{0.8765, 0.2345}, 0.5},
    Cir{Point{0.1234, 0.9876}, Point{0.1234, 0.9876}, 0.0},
]

fn main() {
    for tc in td {
        println("p1:  $tc.p1")
        println("p2:  $tc.p2")
        println("r:  $tc.r")
        c1, c2, case := circles(tc.p1, tc.p2, tc.r)
        println("   $case")
        match case {
        	cor0, diam{
            	println("   Center:  $c1")
			}
        	two {
				println("   Center 1:  $c1")
				println("   Center 2:  $c2")
			}
			else{}
		}
        println('')
    }
}


import "/math" for Math

var Two  = "Two circles."
var R0   = "R == 0 does not describe circles."
var Co   = "Coincident points describe an infinite number of circles."
var CoR0 = "Coincident points with r == 0 describe a degenerate circle."
var Diam = "Points form a diameter and describe only a single circle."
var Far  = "Points too far apart to form circles."

class Point {
    construct new(x, y) {
        _x = x
        _y = y
    }

    x { _x }
    y { _y }
    ==(p) { _x == p.x && _y == p.y }

    toString { "(%(_x), %(_y))" }
}

var circles = Fn.new { |p1, p2, r|
    var c1 = Point.new(0, 0)
    var c2 = Point.new(0, 0)
    if (p1 == p2) {
        if (r == 0) return [p1, p1, CoR0]
        return [c1, c2, Co]
    }
    if (r == 0) return [p1, p2, R0]
    var dx = p2.x - p1.x
    var dy = p2.y - p1.y
    var q = Math.hypot(dx, dy)
    if (q > 2*r) return [c1, c2, Far]
    var m = Point.new((p1.x + p2.x)/2, (p1.y + p2.y)/2)
    if (q == 2*r) return [m, m, Diam]
    var d = (r*r - q*q/4).sqrt
    var ox = d * dx / q
    var oy = d * dy / q
    return [Point.new(m.x - oy, m.y + ox), Point.new(m.x + oy, m.y - ox), Two]
}

var td = [
    [Point.new(0.1234, 0.9876), Point.new(0.8765, 0.2345), 2.0],
    [Point.new(0.0000, 2.0000), Point.new(0.0000, 0.0000), 1.0],
    [Point.new(0.1234, 0.9876), Point.new(0.1234, 0.9876), 2.0],
    [Point.new(0.1234, 0.9876), Point.new(0.8765, 0.2345), 0.5],
    [Point.new(0.1234, 0.9876), Point.new(0.1234, 0.9876), 0.0]
]
for (tc in td) {
    System.print("p1: %(tc[0])")
    System.print("p2: %(tc[1])")
    System.print("r : %(tc[2])")
    var res = circles.call(tc[0], tc[1], tc[2])
    System.print("    %(res[2])")
    if (res[2] == CoR0 || res[2] == Diam) {
        System.print("    Center: %(res[0])")
    } else if (res[2] == Two) {
        System.print("    Center 1: %(res[0])")
        System.print("    Center 2: %(res[1])")
    }
    System.print()
}


function f = chineseRemainder(r, m)
  s = prod(m) ./ m;
  [~, t] = gcd(s, m);
  f = s .* t * r';


MODULE CRT;
FROM FormatString IMPORT FormatString;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;

PROCEDURE WriteInt(n : INTEGER);
VAR buf : ARRAY[0..15] OF CHAR;
BEGIN
    FormatString("%i", buf, n);
    WriteString(buf)
END WriteInt;

PROCEDURE MulInv(a,b : INTEGER) : INTEGER;
VAR
    b0,x0,x1,q,amb,xqx : INTEGER;
BEGIN
    b0 := b;
    x0 := 0;
    x1 := 1;

    IF b=1 THEN
        RETURN 1
    END;

    WHILE a>1 DO
        q := a DIV b;
        amb := a MOD b;
        a := b;
        b := amb;
        xqx := x1 - q * x0;
        x1 := x0;
        x0 := xqx
    END;

    IF x1<0 THEN
        x1 := x1 + b0
    END;

    RETURN x1
END MulInv;

PROCEDURE ChineseRemainder(n,a : ARRAY OF INTEGER) : INTEGER;
VAR
    i : CARDINAL;
    prod,p,sm : INTEGER;
BEGIN
    prod := n[0];
    FOR i:=1 TO HIGH(n) DO
        prod := prod * n[i]
    END;

    sm := 0;
    FOR i:=0 TO HIGH(n) DO
        p := prod DIV n[i];
        sm := sm + a[i] * MulInv(p, n[i]) * p
    END;

    RETURN sm MOD prod
END ChineseRemainder;

TYPE TA = ARRAY[0..2] OF INTEGER;
VAR n,a : TA;
BEGIN
    n := TA{3, 5, 7};
    a := TA{2, 3, 2};
    WriteInt(ChineseRemainder(n, a));
    WriteLn;

    ReadChar
END CRT.


include c:\cxpl\codes;

proc Circles; real Data; \Show centers of circles, given points P & Q and radius
real Px, Py, Qx, Qy, R, X, Y, X1, Y1, Bx, By, PB, CB;
[Px:= Data(0); Py:= Data(1); Qx:= Data(2); Qy:= Data(3); R:= Data(4);
if R = 0.0 then [Text(0, "Radius = zero gives no circles^M^J"); return];
X:= (Qx-Px)/2.0;  Y:= (Qy-Py)/2.0;
Bx:= Px+X;  By:= Py+Y;
PB:= sqrt(X*X + Y*Y);
if PB = 0.0 then [Text(0, "Coincident points give infinite circles^M^J"); return];
if PB > R   then [Text(0, "Points are too far apart for radius^M^J"); return];
CB:= sqrt(R*R - PB*PB);
X1:= Y*CB/PB; Y1:= X*CB/PB;
RlOut(0, Bx-X1); ChOut(0, ^,); RlOut(0, By+Y1); ChOut(0, 9\tab\);
RlOut(0, Bx+X1); ChOut(0, ^,); RlOut(0, By-Y1); CrLf(0);
];

real Tbl; int I;
[Tbl:=[[0.1234, 0.9876,    0.8765, 0.2345,    2.0],
       [0.0000, 2.0000,    0.0000, 0.0000,    1.0],
       [0.1234, 0.9876,    0.1234, 0.9876,    2.0],
       [0.1234, 0.9876,    0.8765, 0.2345,    0.5],
       [0.1234, 0.9876,    0.1234, 0.9876,    0.0]];
for I:= 0 to 4 do Circles(Tbl(I));
]


sub twoCircles (x1, y1, x2, y2, radio)
	if x1 = x2 and y1 = y2 then //Si los puntos coinciden
		if radio = 0 then       //a no ser que radio=0
			print "Los puntos son los mismos\n"
			return true
		else
			print "Hay cualquier numero de circulos a traves de un solo punto (", x1, ",", y1, ") de radio ", radio : print
			return true
		end if
	end if
	r2 = sqr((x1-x2)^2+(y1-y2)^2) / 2  //distancia media entre puntos
	if radio < r2 then
		print "Los puntos estan demasiado separados (", 2*r2, ") - no hay circulos de radio ", radio : print
		return true
	end if

	//si no, calcular dos centros
	cx = (x1+x2) / 2 //punto medio
	cy = (y1+y2) / 2
	//debe moverse desde el punto medio a lo largo de la perpendicular en dd2
	dd2 = sqr(radio^2 - r2^2)   //distancia perpendicular
	dx1 = x2-cx           //vector al punto medio
	dy1 = y2-cy
	dx = 0-dy1 / r2*dd2   //perpendicular:
	dy = dx1 / r2*dd2     //rotar y escalar
	print " -> Circulo 1 (", cx+dy, ", ", cy+dx, ")"     //dos puntos, con (+)
	print " -> Circulo 2 (", cx-dy, ", ", cy-dx, ")\n"   //y (-)
end sub

for i = 1 to 5
	read x1, y1, x2, y2, radio
	print "Puntos ", "(", x1, ",", y1, "), (", x2, ",", y2, ")", ", Radio ", radio
	twoCircles (x1, y1, x2, y2, radio)
next
end

//p1                p2           radio
data 0.1234, 0.9876,    0.8765, 0.2345,    2.0
data 0.0000, 2.0000,    0.0000, 0.0000,    1.0
data 0.1234, 0.9876,    0.1234, 0.9876,    2.0
data 0.1234, 0.9876,    0.8765, 0.2345,    0.5
data 0.1234, 0.9876,    0.1234, 0.9876,    0.0


proc mulInv(a0, b0: int): int =
  var (a, b, x0) = (a0, b0, 0)
  result = 1
  if b == 1: return
  while a > 1:
    let q = a div b
    a = a mod b
    swap a, b
    result = result - q * x0
    swap x0, result
  if result < 0: result += b0

proc chineseRemainder[T](n, a: T): int =
  var prod = 1
  var sum = 0
  for x in n: prod *= x

  for i in 0..<n.len:
    let p = prod div n[i]
    sum += a[i] * mulInv(p, n[i]) * p

  sum mod prod

echo chineseRemainder([3,5,7], [2,3,2])


exception Modular_inverse
let inverse_mod a = function
  | 1 -> 1
  | b -> let rec inner a b x0 x1 =
           if a <= 1 then x1
           else if  b = 0 then raise Modular_inverse
           else inner b (a mod b) (x1 - (a / b) * x0) x0 in
         let x = inner a b 0 1 in
         if x < 0 then x + b else x

let chinese_remainder_exn congruences =
  let mtot = congruences
             |> List.map (fun (_, x) -> x)
             |> List.fold_left ( *) 1 in
   (List.fold_left (fun acc (r, n) ->
                  acc + r * inverse_mod (mtot / n) n * (mtot / n)
                ) 0 congruences)
             mod mtot

let chinese_remainder congruences =
   try Some (chinese_remainder_exn congruences)
   with modular_inverse -> None


chivec(residues, moduli)={
  my(m=Mod(0,1));
  for(i=1,#residues,
    m=chinese(Mod(residues[i],moduli[i]),m)
  );
  lift(m)
};
chivec([2,3,2], [3,5,7])


// Rosetta Code task "Chinese remainder theorem".
program ChineseRemThm;
uses SysUtils;
type TIntArray = array of integer;

// Defining EXTRA adds optional explanatory code
{$DEFINE EXTRA}

// Return (if possible) a residue res_out that satifies
//   res_out = res1 modulo mod1,  res_out = res2 modulo mod2.
// Return mod_out = LCM( mod1, mod2), or mod_out = 0 if there's no solution.
procedure Solve2( const res1, res2, mod1, mod2 : integer;
                  out res_out, mod_out : integer);
var
  a, c, d, k, m, m1, m2, r, temp : integer;
  p, p_prev : integer;
{$IFDEF EXTRA}
  q, q_prev : integer;
{$ENDIF}
begin
  if (mod1 = 0) or (mod2 = 0) then
    raise SysUtils.Exception.Create( 'Solve2: Modulus cannot be 0');
  m1 := Abs( mod1);
  m2 := Abs( mod2);
  // Extended Euclid's algorithm for HCF( m1, m2), except that only one
  //   of the Bezout coefficients is needed (here p, could have used q)
  c := m1; d := m2;
  p :=0;  p_prev := 1;
{$IFDEF EXTRA}
  q := 1; q_prev := 0;
{$ENDIF}
  a := 0;
  while (d > 0) do begin
    temp := p_prev - a*p;  p_prev := p;  p := temp;
  {$IFDEF EXTRA}
    temp := q_prev - a*q;  q_prev := q;  q := temp;
  {$ENDIF}
    a := c div d;
    temp := c - a*d;  c := d;  d := temp;
  end;
  // Here with c = HCF( m1, m2)
{$IFDEF EXTRA}
  Assert( c = p*m2 + q*m1); // p and q are the Bezout coefficients
{$ENDIF}
  // A soution exists iff c divides (res2 - res1)
  k := (res2 - res1) div c;
  if res2 - res1 <> k*c then begin
    res_out := 0;  mod_out := 0; // indicate that there's no xolution
  end
  else begin
    m := (m1 div c) * m2; // m := LCM( m1, m2)
    r:= res2 - k*p*m2;    // r := a solution modulo m
{$IFDEF EXTRA}
    Assert( r = res1 + k*q*m1); // alternative formula in terms of q
{$ENDIF}
    // Return the solution in the range 0..(m - 1)
    // Don't trust the compiler with a negative argument to mod
    if (r >= 0) then r := r mod m
    else begin
      r := (-r) mod m;
      if (r > 0) then r := m - r;
    end;
    res_out := r;  mod_out := m;
  end;
end;

// Return (if possible) a residue res_out that satifies
//   res_out = res_array[j] modulo mod_array[j], for j = 0..High(res_array).
// Return mod_out = LCM of the moduli, or mod_out = 0 if there's no solution.
procedure SolveMulti( const res_array, mod_array : TIntArray;
                      out res_out, mod_out : integer);
var
  count, k, m, r : integer;
begin
  count := Length( mod_array);
  if count <> Length( res_array) then
    raise SysUtils.Exception.Create( 'Arrays are different sizes')
  else if count = 0 then
    raise SysUtils.Exception.Create( 'Arrays are empty');
  k := 1;
  m := mod_array[0];  r := res_array[0];
  while (k < count) and (m > 0) do begin
    Solve2( r, res_array[k], m, mod_array[k], r, m);
    inc(k);
  end;
  res_out := r;  mod_out := m;
end;

// Cosmetic to turn an integer array into a string for printout.
function ArrayToString( a : TIntArray) : string;
var
  j : integer;
begin
  result := '[';
  for j := 0 to High(a) do begin
    result := result + SysUtils.IntToStr(a[j]);
    if j < High(a) then result := result + ', '
                   else result := result + ']';
  end;
end;

// For the passed-in res_array and mod_array, show the solution
//   found by SolveMulti (above), or state that there's no solution.
procedure ShowSolution( const res_array, mod_array : TIntArray);
var
  mod_out, res_out : integer;
begin
  SolveMulti( res_array, mod_array, res_out, mod_out);
  Write( ArrayToString( res_array) + ' mod '
       + ArrayToString( mod_array) + ' --> ');
  if mod_out = 0 then
    WriteLn( 'No solution')
  else
    WriteLn( SysUtils.Format( '%d mod %d', [res_out, mod_out]));
end;

// Main routine. Examples for Rosetta Code task.
begin
  ShowSolution([2, 3, 2], [3, 5, 7]);
  ShowSolution([3, 5, 7], [2, 3, 2]);
  ShowSolution([10, 4, 12], [11, 12, 13]);
  ShowSolution([1, 2, 3, 4], [5, 7, 9, 11]);
  ShowSolution([11, 22, 19], [10, 4, 9]);
  ShowSolution([2328, 410], [16256, 5418]);
  ShowSolution([19, 0], [100, 23]);
end.


use ntheory qw/chinese/;
say chinese([2,3], [3,5], [2,7]);


function mul_inv(integer a, n)
    if n<0 then n = -n end if
    if a<0 then a = n - mod(-a,n) end if
    integer t = 0,  nt = 1,
            r = n,  nr = a;
    while nr!=0 do
        integer q = floor(r/nr)
        {t, nt} = {nt, t-q*nt}
        {r, nr} = {nr, r-q*nr}
    end while
    if r>1 then return "a is not invertible" end if
    if t<0 then t += n end if
    return t
end function

function chinese_remainder(sequence n, a)
    integer p, prod = 1, tot = 0;
    for i=1 to length(n) do prod *= n[i] end for
    for i=1 to length(n) do
        p = prod / n[i];
        object m = mul_inv(p, n[i])
        if string(m) then return "fail" end if
        tot += a[i] * m * p;
    end for
    return mod(tot,prod)
end function

?chinese_remainder({3,5,7},{2,3,2})
?chinese_remainder({11,12,13},{10,4,12})
?chinese_remainder({11,22,19},{10,4,9})
?chinese_remainder({100,23},{19,0})


(de modinv (A B)
   (let (B0 B  X0 0  X1 1  Q 0  T1 0)
      (while (< 1 A)
         (setq
            Q (/ A B)
            T1 B
            B (% A B)
            A T1
            T1 X0
            X0 (- X1 (* Q X0))
            X1 T1 ) )
      (if (lt0 X1) (+ X1 B0) X1) ) )

(de chinrem (N A)
   (let P (apply * N)
      (%
         (sum
            '((N A)
               (setq T1 (/ P N))
               (* A (modinv T1 N) T1) )
            N
            A )
         P ) ) )

(println
   (chinrem (3 5 7) (2 3 2))
   (chinrem (11 12 13) (10 4 12)) )

(bye)


product(A, B, C) :- C is A*B.

pair(X, Y, X-Y).

egcd(_, 0, 1, 0) :- !.
egcd(A, B, X, Y) :-
    divmod(A, B, Q, R),
    egcd(B, R, S, X),
    Y is S - Q*X.

modinv(A, B, X) :-
    egcd(A, B, X, Y),
    A*X + B*Y =:= 1.

crt_fold(A, M, P, R0, R1) :- % system of equations of (x = a) (mod m); p = M/m
    modinv(P, M, Inv),
    R1 is R0 + A*Inv*P.

crt(Pairs, N) :-
    maplist(pair, As, Ms, Pairs),
    foldl(product, Ms, 1, M),
    maplist(divmod(M), Ms, Ps, _), % p(n) <- M/m(n)
    foldl(crt_fold, As, Ms, Ps, 0, N0),
    N is N0 mod M.