Schwerdteger describes an interesting “invariant” relationship between any two circles:
where
,
, and
with the circles represented as Hermitian matrices .
The point is, in the end you come up with this single number which represents whether the smaller circle is inside the first, overlapping the first, just touching the first, or outside the first. Here are the cases:
common invariant > 1 : smaller circle contained withing the greater circle

common invariant = 1 : touching from the inside

-1 > common invariant > 1 : overlapping at two points

common invariant = -1 : touching from the outside

common invariant < -1 : completely outside

Here is Racket code used for calculations and plotting:
(require math/array)
(require math/matrix)
(require plot)
(define (circle-to-matrix zC r)
(let ([B (* -1 (conjugate zC))]
[mzC (magnitude zC)])
(matrix [[ 1 B ]
[ (conjugate B) (- (* mzC mzC) (* r r)) ]])))
;; gothic C - 212d
;; delta - 394
(define (invariant ℭ1 ℭ2)
(let* ([Δ1 (matrix-determinant ℭ1)]
[Δ2 (matrix-determinant ℭ2)]
[A1 (array-ref ℭ1 #[0 0])]
[B1 (array-ref ℭ1 #[0 1])]
[C1 (array-ref ℭ1 #[1 0])]
[D1 (array-ref ℭ1 #[1 1])]
[A2 (array-ref ℭ2 #[0 0])]
[B2 (array-ref ℭ2 #[0 1])]
[C2 (array-ref ℭ2 #[1 0])]
[D2 (array-ref ℭ2 #[1 1])]
[Δ12 (* 0.5 (+ (* A1 D2)
(* A2 D1)
(* -1 B1 C2)
(* -1 B2 C1)))])
(/ Δ12 (* (sqrt Δ1) (sqrt Δ2)))))
(define (circle-isoline x y r)
(isoline
(lambda (x_ y_) (sqrt (+ (sqr (- x_ x)) (sqr (- y_ y))))) r))
(define (circles-invariant-plot x1 y1 r1 x2 y2 r2 min max)
(let ([C1 (circle-to-matrix (make-rectangular x1 y1) r1)]
[C2 (circle-to-matrix (make-rectangular x2 y2) r2)])
(plot-file
(list
(circle-isoline x1 y1 r1)
(circle-isoline x2 y2 r2)
(point-label (vector (+ min (* (- max min) 0.1))
(+ min (* (- max min) 0.9)))
(number->string (invariant C1 C2)) #:point-size 0))
"out.png"
#:x-min min
#:x-max max
#:y-min min
#:y-max max
#:width 400
#:height 400)))