continuedfractions.rational_points#

class continuedfractions.rational_points.Dim2RationalCoordinates(x: Rational, y: Rational)[source]#

A simple tuple subtype for a sequence of two rational coordinates representing a point in \(\mathbb{Q}^2\).

Attributes

x

The x-coordinate.

y

The y-coordinate.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.continuedfraction import ContinuedFraction as CF
>>> c = Dim2RationalCoordinates(F(1, 2), F(3, 4))
>>> c
Dim2RationalCoordinates(1/2, 3/4)
>>> c.x
Fraction(1, 2)
>>> c.y
Fraction(3, 4)
property x: Rational#

The x-coordinate.

Returns:
numbers.Rational

The \(x\)-coordinate.

Examples

>>> Dim2RationalCoordinates(1, Fraction(3, 4)).x
1
>>> Dim2RationalCoordinates(Fraction(1, 2), Fraction(3, 4)).x
Fraction(1, 2)
>>> Dim2RationalCoordinates(ContinuedFraction(1, 2), Fraction(3, 4)).x
ContinuedFraction(1, 2)
Type:

numbers.Rational

property y: Rational#

The y-coordinate.

Returns:
numbers.Rational

The \(y\)-coordinate.

Examples

>>> Dim2RationalCoordinates(Fraction(1, 2), 3).y
3
>>> Dim2RationalCoordinates(Fraction(1, 2), Fraction(3, 4)).y
Fraction(3, 4)
>>> Dim2RationalCoordinates(Fraction(1, 2), ContinuedFraction(3, 4)).y
ContinuedFraction(3, 4)
Type:

numbers.Rational

class continuedfractions.rational_points.Dim3RationalCoordinates(x: Rational, y: Rational, z: Rational)[source]#

A simple tuple subtype for a sequence of three rational coordinates representing a point in \(\mathbb{Q}^3\).

Attributes

x

The x-coordinate.

y

The y-coordinate.

z

The z-coordinate.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.continuedfraction import ContinuedFraction as CF
>>> c = Dim3RationalCoordinates(1, F(-2, 3), CF(4, 5))
>>> c
Dim3RationalCoordinates(1, -2/3, 4/5)
>>> c.x
1
>>> c.y
Fraction(-2, 3)
>>> c.z
ContinuedFraction(4, 5)
property x: Rational#

The x-coordinate.

Returns:
numbers.Rational

The \(x\)-coordinate.

Examples

>>> Dim3RationalCoordinates(1, Fraction(2, 3), ContinuedFraction(3, 4)).x
1
>>> Dim3RationalCoordinates(Fraction(1, 2), 3, ContinuedFraction(4, 5)).x
Fraction(1, 2)
>>> Dim3RationalCoordinates(ContinuedFraction(1, 2), Fraction(3, 4), 5).x
ContinuedFraction(1, 2)
Type:

numbers.Rational

property y: Rational#

The y-coordinate.

Returns:
numbers.Rational

The \(y\)-coordinate.

Examples

>>> Dim3RationalCoordinates(Fraction(1, 2), 3, ContinuedFraction(4, 5)).y
3
>>> Dim3RationalCoordinates(1, Fraction(2, 3), ContinuedFraction(4, 5)).y
Fraction(2, 3)
>>> Dim3RationalCoordinates(1, ContinuedFraction(2, 3), Fraction(4, 5)).y
ContinuedFraction(2, 3)
Type:

numbers.Rational

property z: Rational#

The z-coordinate.

Returns:
numbers.Rational

The \(z\)-coordinate.

Examples

>>> Dim3RationalCoordinates(Fraction(1, 2), ContinuedFraction(3, 4), 5).z
5
>>> Dim3RationalCoordinates(1, ContinuedFraction(2, 3), Fraction(4, 5)).z
Fraction(4, 5)
>>> Dim3RationalCoordinates(1, Fraction(2, 3), ContinuedFraction(4, 5)).z
ContinuedFraction(4, 5)
Type:

numbers.Rational

class continuedfractions.rational_points.HomogeneousCoordinates(x: Rational, y: Rational, z: Rational)[source]#

A class to represent homogeneous coordinates for rational points in projective space \(\mathbb{P}^2(\mathbb{Q})\).

Methods

to_rational_point()

RationalPoint : Returns a new rational point from this sequence of homogeneous coordinates.

Examples

>>> from fractions import Fraction as F
>>> h = HomogeneousCoordinates(3, 4, 5)
>>> h = h.scale(F(1, 5))
>>> h
HomogeneousCoordinates(3/5, 4/5, 1)
>>> h.to_rational_point()
RationalPoint(3/5, 4/5)
to_rational_point() RationalPoint[source]#

RationalPoint : Returns a new rational point from this sequence of homogeneous coordinates.

Returns:
RationalPoint

A new rational point from this sequence of homogeneous coordinates.

Examples

>>> HomogeneousCoordinates(3, 4, 5).to_rational_point()
RationalPoint(3/5, 4/5)
class continuedfractions.rational_points.RationalPoint(x: int | Fraction | ContinuedFraction, y: int | Fraction | ContinuedFraction)[source]#

A simple class for representing and operating on rational points as points in the \(xy\)-plane.

These are points in \(\mathbb{R}^2\) whose coordinates are rational i.e. elements of \(\mathbb{Q}\), and thus are points of \(\mathbb{Q}^2\).

The points form an abelian group under component-wise addition, and form a closed set under scalar left-multiplication by rational numbers. The scalar left-multiplication is distributive over sums of rational points.

This implemention of rational points is based essentially on a custom implementation RationalTuple of tuple, with exactly two rational-valued members: in Python this means the arguments must be instances of Rational, which includes values of type:

Internally, the rational coordinates of the point are stored as ContinuedFraction objects.

Attributes

coordinates

The pair of (rational) coordinates of the rational point.

height

The height of the rational point in the projective space \(\mathbb{P}^2\).

homogeneous_coordinates

A unique sequence of integer-valued homogeneous coordinates in \(\mathbb{P}^2\) for this rational point.

log_height

The natural logarithm of the height of the rational point as defined above.

norm

The Euclidean norm of a rational point in the plane.

norm_squared

The square of the Euclidean (\(\ell_2\)) norm of a rational point in the plane.

rectilinear_norm

The rectilinear (\(\ell_1\) or taxicab) norm of the rational point.

Methods

angle(*[, other, as_degrees])

Decimal: The radian (or degree) angle between this rational point, as a position vector in \(\mathbb{Q}^2\), and either another rational point or the positive \(x\)-axis.

collinear_with(*rational_points)

bool : Tests whether this rational point is collinear with one or more rational points.

collinear_with_origin(*rational_points)

bool : Tests whether this rational point is collinear with one or more rational points and the origin \((0, 0)\).

det(other, /)

ContinuedFraction : The determinant of the \(2 \times 2\) matrix formed by the position vectors in \(\mathbb{Q}^2\) of this rational point and another.

distance(other, /)

Decimal : The Euclidean distance between this point and another rational point.

distance_squared(other, /)

ContinuedFraction : The square of the Euclidean distance between this point and another rational point in the plane.

dot(other, /)

ContinuedFraction : The dot product of two rational points as position vectors in \(\mathbb{Q}^2\).

gradient(*[, other])

ContinuedFraction : Computes the gradient (slope) of the line passing through this rational point and either the origin \((0, 0)\) (default) or another point`.

is_integral_lattice_point()

bool : Whether the rational point is an integral lattice point, i.e. has integer coordinates.

orthogonal()

RationalPoint : Returns a rational point whose position vector is orthogonal to that of the original point.

permute()

RationalPoint : Returns a new rational point by swapping the original coordinates.

perpendicular_distance(other, /)

Decimal : The perpendicular distance between this rational point and another.

rectilinear_distance(other, /)

ContinuedFraction : The rectilinear (\(\ell_1\) or taxicab) distance between this rational point and another.

reflect(axis)

RationalPoint : Returns a new rational point obtained by reflecting the original in the \(x\)- or \(y\)-axis.

sum(*rational_points)

RationalPoint : The sum of a variable number of rational points.

translate(*[, x_by, y_by])

RationalPoint : Returns a new rational point obtained by translating the original in the \(x\)- and/or \(y\)-coordinates by rational scalars.

zero()

RationalPoint : The zero rational point.

Examples

>>> RationalPoint(Fraction(3, 5), Fraction(4, 5))
RationalPoint(3/5, 4/5)
>>> RationalPoint(3, ContinuedFraction(4, 5))
RationalPoint(3, 4/5)
>>> RationalPoint(Fraction(3, 5), ContinuedFraction(4))
RationalPoint(3/5, 4)
>>> RationalPoint(-3, 4)
RationalPoint(-3, 4)
>>> RationalPoint(2, .5)
Traceback (most recent call last):
...
ValueError: A `RationalPoint` object must be specified as a pair of rational numbers `r` and `s`, each of type either integer (`int`), or fraction (`Fraction` or `ContinuedFraction`).
classmethod zero() RationalPoint[source]#

RationalPoint : The zero rational point.

Returns:
RationalPoint

The zero rational point.

Examples

>>> RationalPoint.zero()
RationalPoint(0, 0)
classmethod sum(*rational_points: RationalPoint) RationalPoint[source]#

RationalPoint : The sum of a variable number of rational points.

This is designed as a helper method for rational point summation because the built-in sum() function only works for RationalPoint instances if the start value is set to RP(0, 0), which many users may not be aware of.

Parameters:
rational_pointstyping.Iterable

A variable number of RationalPoint instances to add.

Returns:
RationalPoint

The sum of the rational points.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP.sum(RP(-1, 1), RP(1, -1))
RationalPoint(0, 0)
>>> RP.sum(RP(1, 1), RP(2, 1), RP(3, 1))
RationalPoint(6, 3)
>>> RP.sum(RP(0, 0), RP(1, F(-1, 2)), RP(F(3, 5), F(4, 5)), RP(F(5, 12), 6))
RationalPoint(121/60, 63/10)
property coordinates: Dim2RationalCoordinates#

The pair of (rational) coordinates of the rational point.

Returns:
tuple

The pair of coordinates of the rational point as a tuple of ContinuedFraction instances.

Examples

>>> P = RationalPoint(Fraction(1, 2), Fraction(-3, 4))
>>> P.coordinates
Dim2RationalCoordinates(1/2, -3/4)
Type:

Dim2RationalCoordinates

gradient(*, other: RationalPoint = None) ContinuedFraction[source]#

ContinuedFraction : Computes the gradient (slope) of the line passing through this rational point and either the origin \((0, 0)\) (default) or another point`.

If no second rational point is provided the gradient of this rational point is computed with respect to the origin \((0, 0)\): if this rational point has a zero \(x\)-coordinate, i.e. falls on the \(y\)-axis, then a None value will be returned, to indicate that the result is undefined.

If another rational point \(P' = (x', y')\) (as represented by other) is provided then the gradient is computed as:

\[\frac{y' - y}{x' - x}, \hskip{3em} x' \neq x\]

where \(P = (x, y)\) is this rational point (as represented by self).

If no non-zero second rational point is provided the gradient is computed with respect to the origin:

\[\frac{y}{x}, \hskip{3em} x \neq 0\]

As the gradient of a vertical line is infinite (or undefined) the method raises a ValueError, which occurs whenver the second rational point is vertical with respect to this point, i.e. the two points have the same \(x\)-coordinate.

Parameters:
otherRationalPoint, default=None

An optional second rational point with respect to which the gradient is computed.

Returns:
ContinuedFraction

The gradient (slope) of the line connecting this rational point and either the origin \((0, 0)\) (default) or another point.

Raises:
ValueError

If other is not a rational point or the point it represents is vertical with respect to this rational point.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(1, 1).gradient()
ContinuedFraction(1, 1)
>>> RP(1, 1).gradient(other=RP(2, 1))
ContinuedFraction(0, 1)
>>> RP(0, 1).gradient(other=RP(1, 0))
ContinuedFraction(-1, 1)
>>> RP(0, 1).gradient()
>>> RP(1, 1).gradient(other=RP(1, 2))
Traceback (most recent call last):
...
ValueError: If a second rational point is provided, it must be a `RationalPoint` instance, and non-vertical with respect to this point.
collinear_with(*rational_points: RationalPoint) bool[source]#

bool : Tests whether this rational point is collinear with one or more rational points.

The collinearity test for three points \(P_1 = (x_1, y_1)\), \(P_2 = (x_2, y_2)\), and \(P_3 = (x_3, y_3)\) uses the gradient method:

\[\frac{y_2 - y_1}{x_2 - x_1} = \frac{y_3 - y_2}{x_3 - x_2}, \hskip{3em} x_2 \neq x_1; x_3 \neq x_2\]

which can be rearranged as the equation:

\[(y_3 - y_2)(x_2 - x_1) - (y_2 - y_1)(x_3 - x_2) = 0\]

Note that the other rational points do not need to be given in any particular order.

Parameters:
rational_pointsRationalPoint

One or more rational points to test for collinearity with this point.

Returns:
bool

Whether this point is collinear with the given rational points.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(1, 1).collinear_with(RP(2, 2), RP(F(-1, 2), F(-1, 2)))
True
>>> RP(1, 1).collinear_with(RP(2, 2), RP(F(-1, 2), F(-1, 2)), RP(-3, -3))
True
>>> RP(1, 1).collinear_with(RP(-2, -2), RP(F(1, 2), F(1, 2)), RP(1, 2))
False
>>> RP(1, 1).collinear_with(RP(F(-1, 2), F(-1, 2)))
True
>>> RP(1, 1).collinear_with(RP(2, 1))
True
collinear_with_origin(*rational_points: RationalPoint) bool[source]#

bool : Tests whether this rational point is collinear with one or more rational points and the origin \((0, 0)\).

This is to allow easier checking of collinearity of points falling on a line passing through the origin.

Note that the other rational points do not need to be given in any particular order.

Parameters:
rational_pointsRationalPoint

One or more rational points to test for collinearity with this point and the origin \((0, 0)\)

Returns:
bool

Whether this point is collinear with the given rational points and the origin \((0, 0)\).

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(1, 1).collinear_with_origin(RP(2, 2), RP(F(-1, 2), F(-1, 2)))
True
>>> RP(1, 1).collinear_with_origin(RP(2, 2), RP(F(-1, 2), F(1, 2)))
False
>>> RP(1, 0).collinear_with_origin(RP(-1, 0), RP(F(1, 2), F(1, 2)))
False
>>> RP(1, 0).collinear_with_origin(RP(-1, 0), RP(F(1, 2), 0))
True
angle(*, other: RationalPoint = None, as_degrees: bool = False) Decimal[source]#

Decimal: The radian (or degree) angle between this rational point, as a position vector in \(\mathbb{Q}^2\), and either another rational point or the positive \(x\)-axis.

If another rational point \(P'\) (as represented by other) is provided, the computed angle is that between the position vector of this rational point \(P = (x, y)\) (as represented by self) and the other, as given by:

\[\alpha = \text{arccos}\left( \frac{P \cdot P'}{\|P\|\|P'\|} \right)\]

If no other rational point is provided the computed angle is that between the position vector of this rational point and the positive \(x\)-axis, as given by:

\[\alpha = \text{atan2}\left(\frac{y}{x}\right)\]

where \(\text{atan2}\) refers to the \(\text{arctan}\) extension that uses both \(x\)- and \(y\)-coordinates of a plane point \(P = (x, y)\), as implemented by math.atan2(). For reference any standard book on trigonometry or plane geometry should contain a definition.

The optional as_degrees boolean can be used to return the angle in degrees.

Parameters:
as_degreesbool, default=False

Whether to return the angle in degrees.

Returns:
decimal.Decimal

The angle between this rational point, as a position vector in \(\mathbb{Q}^2\), and either another rational point, if provided, or the positive \(x\)-axis.

Examples

>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(1, 0).angle()
Decimal('0')
>>> RP(1, 0).angle(as_degrees=True)
Decimal('0')
>>> RP(1, 1).angle()
Decimal('0.78539816339744827899949086713604629039764404296875')
>>> RP(1, 1).angle(as_degrees=True)
Decimal('45')
>>> RP(1, 1).angle(other=RP(0, 1))
Decimal('0.78539816339744827899949086713604629039764404296875')
>>> RP(1, 1).angle(other=RP(0, 1), as_degrees=True)
Decimal('45')
orthogonal() RationalPoint[source]#

RationalPoint : Returns a rational point whose position vector is orthogonal to that of the original point.

This is described by the linear transformation:

\[\begin{split}\begin{bmatrix}0 & -1 \\1 & 0 \end{bmatrix} \begin{bmatrix}\frac{a}{c} \\\frac{b}{d}\end{bmatrix} = \begin{bmatrix} -\frac{b}{d} \\ \frac{a}{c} \end{bmatrix}\end{split}\]

for points \(P = \left(\frac{a}{c}, \frac{b}{d}\right) \in \mathbb{Q}^2\), and has the property that \(P \cdot P^{\perp} = P^{\perp} \cdot P = 0\) where \(\perp\) is the orthogonality relation..

Returns:
RationalPoint

The “orthogonal” of the rational point as defined above.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(F(1, 2), F(3, 4)).orthogonal()
RationalPoint(-3/4, 1/2)
>>> RP(1, -2).orthogonal()
RationalPoint(2, 1)
>>> RP(1, -2).orthogonal().dot(RP(1, -2))
ContinuedFraction(0, 1)
permute() RationalPoint[source]#

RationalPoint : Returns a new rational point by swapping the original coordinates.

This is described by the linear transformation:

\[\begin{split}\begin{bmatrix}0 & 1 \\1 & 0 \end{bmatrix} \begin{bmatrix}\frac{a}{c} \\\frac{b}{d}\end{bmatrix} = \begin{bmatrix} \frac{b}{d} \\ \frac{a}{c} \end{bmatrix}\end{split}\]

for points \(P = \left(\frac{a}{c}, \frac{b}{d}\right) \in \mathbb{Q}^2\).

Returns:
RationalPoint

The permuted rational point with the original coordinates swapped.

Examples

>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(1, 2).permute()
RationalPoint(2, 1)
translate(*, x_by: int | Fraction | ContinuedFraction = 0, y_by: int | Fraction | ContinuedFraction = 0) RationalPoint[source]#

RationalPoint : Returns a new rational point obtained by translating the original in the \(x\)- and/or \(y\)-coordinates by rational scalars.

An affine transformation which implements the mapping:

\[\left(\left(\frac{a}{c},\frac{b}{d}\right), \lambda, \mu\right) \longmapsto \left(\frac{a}{c} + \lambda, \frac{b}{d} + \mu\right)\]

for rational points \(\left(\frac{a}{c}, \frac{b}{d}\right) \in \mathbb{Q}^2\) and rational scalars \(\lambda, \mu \in \mathbb{Q}\).

This will not be a linear transformation as the origin \((0, 0)\) of \(\mathbb{Q}^2\) wil be moved for any non-zero scalars.

Parameters:
x_byint or Fraction or ContinuedFraction, default=0

The optional parameter for translating the \(x\)-coordinate, with a default value of \(0\). Must be a rational value.

y_byint or Fraction or ContinuedFraction, default=0

The optional parameter for translating the \(y\)-coordinate, with a default value of \(0\). Must be a rational value.

Returns:
RationalPoint

A new rational point translated from the original using the given coordinate translation parameters.

Raises:
ValueError

If the coordinate translation parameters are not of the expected type.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> P = RP(F(1, 2), F(-3, 4)); P
RationalPoint(1/2, -3/4)
>>> P.translate(x_by=F(-1, 4), y_by=2)
RationalPoint(1/4, 5/4)
>>> P.translate(x_by=-.5)
Traceback (most recent call last):
...
ValueError: The coordinate translation parameters must be of type `int`, `fractions.Fraction` or `ContinuedFraction`.
reflect(axis: Literal['x', 'y']) RationalPoint[source]#

RationalPoint : Returns a new rational point obtained by reflecting the original in the \(x\)- or \(y\)-axis.

Implements linear transformations given by the mappings:

\[\left(\frac{a}{c}, \frac{b}{d} \right) \longmapsto \left(\frac{a}{c}, -\frac{b}{d}\right)\]

for reflection in the \(x\)-axis, and:

\[\left(\frac{a}{c}, \frac{b}{d} \right) \longmapsto \left(-\frac{a}{c}, \frac{b}{d}\right)\]

for reflection in the \(y\)-axis, with matrices \(\begin{bmatrix}1 & 0\\0 & -1\end{bmatrix}\), and \(\begin{bmatrix}-1 & 0\\0 & 1\end{bmatrix}\) respectively.

Parameters:
axisstr

The axis of reflection: should be a string literal which is either "x" or "y".

Returns:
RationalPoint

A new rational point reflected from the original in the given axis.

Raises:
ValueError

If the axis is invalid or incorrectly specified.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> P = RP(1, 1)
>>> P.reflect(axis='x')
RationalPoint(1, -1)
>>> P.reflect(axis='y')
RationalPoint(-1, 1)
>>> P.reflect(axis="X")
Traceback (most recent call last):
...
ValueError: The axis of reflection must be a string literal which is either "x" or "y".
dot(other: RationalPoint, /) ContinuedFraction[source]#

ContinuedFraction : The dot product of two rational points as position vectors in \(\mathbb{Q}^2\).

If \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\) and \(P' = \left( \frac{a'}{c'}, \frac{b'}{d'} \right)\) are two rational points in the plane their dot product \(P \cdot P'\) is the rational number:

\[\begin{split}\begin{align} P \cdot P' &= \frac{aa'}{cc'} + \frac{bb'}{dd'} \\ &= \frac{aa'dd' + bb'cc'}{cc'dd'} \end{align}\end{split}\]

This value is returned as a ContinuedFraction object because this is the standard representation of rational numbers in this package.

Returns:
ContinuedFraction

The standard Euclidean dot product for two rational points in the plane.

Examples

>>> P = RationalPoint(Fraction(1, 2), Fraction(3, 4))
>>> Q = RationalPoint(Fraction(1, 3), Fraction(2, 5))
>>> P.dot(Q)
ContinuedFraction(7, 15)
>>> P.dot(2)
Traceback (most recent call last):
...
ValueError: The dot product is only defined between `RationalPoint` instances.
>>> P.dot(RationalPoint(0, 0))
ContinuedFraction(0, 1)
>>> P.dot(RationalPoint(1, 1))
ContinuedFraction(5, 4)
det(other: RationalPoint, /) ContinuedFraction[source]#

ContinuedFraction : The determinant of the \(2 \times 2\) matrix formed by the position vectors in \(\mathbb{Q}^2\) of this rational point and another.

Computes the (rational) determinant:

\[\begin{split}\begin{vmatrix}\frac{a}{c} & \frac{a'}{c'}\\\frac{b}{d} & \frac{b'}{d'}\end{vmatrix} = \frac{ab'}{cd'} - \frac{a'b}{c'd} = \frac{ab'c'd - a'bcd'}{cc'dd'}\end{split}\]

of the matrix formed by the position vectors of two plane rational points \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\) and \(P' = \left( \frac{a'}{c'}, \frac{b'}{d'} \right)\), where \(P\) is represented by self and \(P'\) by other.

Geometrically, the quantity represents the signed area of the plane parallelogram formed by the position vectors of \(P\) and \(P'\) and the vector sum \(P + P'\), where the sign is positive or negative depending on whether \(\frac{bc}{ad} < \frac{b'c'}{a'd'}\) or \(\frac{bc}{ad} > \frac{b'c'}{a'd'}\) respectively, where \(\frac{bc}{ad}\) and \(\frac{b'c'}{a'd'}\) are the gradients of the lines passing through the origin \((0, 0)\) and \(P\) and \(P'\) respectively. The quantity is zero when these lines are collinear, i.e. when \(P\) and \(P'\) fall on a single line passing through \((0, 0)\).

Returns:
ContinuedFraction

The determinant of the \(2 \times 2\) matrix formed by the position vector of this rational point and another, as described above.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.rational_points import RationalPoint as RP
>>> P, Q, R = RP(F(3, 5), F(4, 5)), RP(1, 1), RP(F(5, 4), 2); P, Q, R
(RationalPoint(3/5, 4/5), RationalPoint(1, 1), RationalPoint(5/4, 2))
>>> P.det(Q)
ContinuedFraction(-1, 5)
>>> P.det(R)
ContinuedFraction(1, 5)
>>> Q.det(R)
ContinuedFraction(3, 4)
>>> P.det(P)
ContinuedFraction(0, 1)
property norm_squared: ContinuedFraction#

The square of the Euclidean (\(\ell_2\)) norm of a rational point in the plane.

The Euclidean (\(\ell_2\)) norm squared \(\|P\|_{2}^2\) of a rational point \(P = \left(\frac{a}{c}, \frac{b}{d} \right)\) in the plane, which is the dot product \(P \cdot P\) of \(P\) with itself:

\[\begin{split}\begin{align} \|P\|_{2}^2 = P \cdot P &= \frac{a^2}{c^2} + \frac{b^2}{d^2} \\ &= \frac{a^2d^2 + b^2c^2}{c^2d^2} \end{align}\end{split}\]

and is also a rational number.

Returns:
ContinuedFraction

The Euclidean norm squared of the rational point.

Examples

>>> RationalPoint(1, 1).norm_squared
ContinuedFraction(2, 1)
>>> RationalPoint(Fraction(1, 2), Fraction(3, 5)).norm_squared
ContinuedFraction(61, 100)
>>> RationalPoint(0, 0).norm_squared
ContinuedFraction(0, 1)
Type:

ContinuedFraction

property norm: Decimal#

The Euclidean norm of a rational point in the plane.

The Euclidean norm \(\|P\|_2\) of a rational point \(P = \left(\frac{a}{c}, \frac{b}{d} \right)\), as given by:

\[\begin{split}\begin{align} \|P\|_2 = \sqrt{P \cdot P} &= \sqrt{\frac{a^2}{c^2} + \frac{b^2}{d^2}} \\ &= \sqrt{\frac{a^2d^2 + b^2c^2}{c^2d^2}} \end{align}\end{split}\]
Returns:
decimal.Decimal

The Euclidean norm of the rational point.

Examples

>>> RationalPoint(1, 1).norm
Decimal('1.414213562373095048801688724')
>>> RationalPoint(Fraction(1, 2), Fraction(3, 5)).norm
Decimal('0.7810249675906654394129722736')
>>> RationalPoint(0, 0).norm
Decimal('0')
>>> RationalPoint(Fraction(3, 5), Fraction(4, 5)).norm
Decimal('1')
Type:

Decimal

distance_squared(other: RationalPoint, /) ContinuedFraction[source]#

ContinuedFraction : The square of the Euclidean distance between this point and another rational point in the plane.

If \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\) and \(P' = \left( \frac{a'}{c'}, \frac{b'}{d'} \right)\) are two rational points in the plane the square of their Euclidean distance \(\|P - P'\|_{2}^2\) is the non-negative rational number:

\[\begin{split}\begin{align} \|P - P'\|^2 &= \left( \frac{a}{c} - \frac{a'}{c'} \right)^2 + \left( \frac{b}{d} - \frac{b'}{d'} \right)^2 \\ &= \left( \frac{ac' - a'c}{cc'} \right)^2 + \left( \frac{bd' - b'd}{dd'} \right)^2 \\ &= \frac{\left(ac' - a'c\right)^2d^2d'^2 + \left(bd' - b'd\right)^2c^2c'^2}{c^2c'^2d^2d'^2} \end{align}\end{split}\]

where \(\|P - P'\|_{2}^2 = 0\) if and only if \(P = P'\).

The Euclidean distance \(\|P - P'\|_2\) is simply the square root of this quantity, but will in general not be a rational number unless \(\left( \frac{ac' - a'c}{cc'} \right)^2 + \left( \frac{bd' - b'd}{dd'} \right)^2\) is a square of a rational number.

Returns:
ContinuedFraction

The square of the Euclidean distance between this point and another rational point in the plane.

Examples

>>> P = RationalPoint(Fraction(3, 5), Fraction(4, 5))
>>> P
RationalPoint(3/5, 4/5)
>>> P.distance_squared(RationalPoint(0, 0))
ContinuedFraction(1, 1)
>>> P.distance_squared(RationalPoint(1, 1))
ContinuedFraction(1, 5)
>>> RationalPoint(0, 0).distance_squared(RationalPoint(1, 1))
ContinuedFraction(2, 1)
distance(other: RationalPoint, /) Decimal[source]#

Decimal : The Euclidean distance between this point and another rational point.

For rational points \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\) and \(P' = \left( \frac{a'}{c'}, \frac{b'}{d'} \right)\) this is the square root \(\sqrt{\|P - P'\|_{2}^2}\) of the distance squared \(\|P - P'\|_{2}^2\) as defined above.

And of course \(\|P - P'\|_{2} = 0\) if and only if \(P = P'\).

Returns:
decimal.Decimal

The Euclidean distance between this point and another rational point in the plane.

Examples

>>> P = RationalPoint(Fraction(3, 5), Fraction(4, 5))
>>> P
RationalPoint(3/5, 4/5)
>>> P.distance(RationalPoint(0, 0))
Decimal('1')
>>> P.distance_squared(RationalPoint(1, 1))
ContinuedFraction(1, 5)
>>> RationalPoint(0, 0).distance(RationalPoint(1, 1))
Decimal('1.414213562373095048801688724')
perpendicular_distance(other: RationalPoint, /) Decimal[source]#

Decimal : The perpendicular distance between this rational point and another.

Given a non-zero rational point \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\), the line \(\ell_{OP}\) passing through the origin \((0, 0)\) and \(P\), and another rational point \(P' = \left( \frac{a'}{c'}, \frac{b'}{d'} \right)\), the perpendicular distance \(d^{\perp}\left(P, P'\right)'\) between \(P\) and \(P'\) is defined here as the length \(d^{\perp}\left(P, P'\right)\) of the line segment connecting \(P'\) and \(\ell_{OP}\), perpendicular to the latter, as given by:

\[d^{\perp}\left(P, P'\right) = \frac{\lvert\text{det}(P, P')\rvert}{\|P\|_2}\]

where \(\text{det}(P, P')\) is the determinant of \(P\) and \(P'\) as described in det().

Returns:
decimal.Decimal

The perpendicular distance between this rational point and another as defined above.

Examples

>>> from continuedfractions.rational_points import RationalPoint as RP
>>> RP(1, 0).perpendicular_distance(RP(0, 1))
Decimal('1')
>>> RP(0, 1).perpendicular_distance(RP(1, 0))
Decimal('1')
>>> RP(1, 0).perpendicular_distance(RP(1, 0))
Decimal('0')
>>> RP(1, 0).perpendicular_distance(RP(-1, 0))
Decimal('0')
>>> RP(0, 0).perpendicular_distance(RP(1, 0))
Traceback (most recent call last):
...
ValueError: The perpendicular distance is defined only between two `RationalPoint` instances, the first of which must be non-zero, i.e. different from `RationalPoint(0, 0)`.
>>> RP(1, 0).perpendicular_distance(1)
Traceback (most recent call last):
...
ValueError: The perpendicular distance is defined only between two `RationalPoint` instances, the first of which must be non-zero, i.e. different from `RationalPoint(0, 0)`.
is_integral_lattice_point() bool[source]#

bool : Whether the rational point is an integral lattice point, i.e. has integer coordinates.

Returns:
bool

Whether the coordinates correspond to integers. Coordinates in fractional form \(\frac{a}{1}\) where the numerator \(a\) is an integer are treated as integers.

Examples

>>> RationalPoint(1, 2).is_integral_lattice_point()
True
>>> RationalPoint(Fraction(1, 2), 2).is_integral_lattice_point()
False
property rectilinear_norm: ContinuedFraction#

The rectilinear (\(\ell_1\) or taxicab) norm of the rational point.

The rectilinear (\(\ell_1\) or taxicab) norm \(\|r\|_1\) of a rational point \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\) is given by:

\[\|P\|_1 = \lvert\frac{a}{c}\rvert + \lvert\frac{b}{d}\rvert\]

The rectilinear norm of a rational point is a non-negative rational number, hence the property produces ContinuedFraction objects, as this is the standard representation of rationals in this package.

To get the decimal value use the as_decimal method.

Returns:
ContinuedFraction

The rectilinear norm of the rational point, which is always a non-negative rational number.

Examples

>>> RationalPoint(Fraction(-1, 2), Fraction(3, 4)).rectilinear_norm
ContinuedFraction(5, 4)
>>> RationalPoint(Fraction(1, 2), Fraction(-3, 4)).rectilinear_norm
ContinuedFraction(5, 4)
>>> RationalPoint(Fraction(1, 2), Fraction(3, 4)).rectilinear_norm
ContinuedFraction(5, 4)
Type:

ContinuedFraction

rectilinear_distance(other: RationalPoint, /) ContinuedFraction[source]#

ContinuedFraction : The rectilinear (\(\ell_1\) or taxicab) distance between this rational point and another.

If \(P = \left( \frac{a}{c}, \frac{b}{d} \right)\) and \(P' = \left( \frac{a'}{c'}, \frac{b'}{d'} \right)\) are two rational points in the plane their rectilinear distance \(\|P - P'\|_1\) is the non-negative rational number:

\[\begin{split}\begin{align} \|P - P'\|_1 &= \lvert \frac{a}{c} - \frac{a'}{c'} \rvert + \lvert \frac{b}{d} - \frac{b'}{d'} \rvert \\ &= \lvert \frac{ac' - a'c}{cc'} \rvert + \lvert \frac{bd' - b'd}{dd'} \rvert \end{align}\end{split}\]

where \(\|P - P'\| = 0\) if and only if \(P = P'\).

Returns:
decimal.Decimal

The rectilinear distance between this point and another rational point in the plane.

Examples

>>> RationalPoint(Fraction(3, 5), Fraction(4, 5)).rectilinear_distance(RationalPoint(1, 1))
ContinuedFraction(3, 5)
>>> RationalPoint(0, 0).rectilinear_distance(RationalPoint(1, 1))
ContinuedFraction(2, 1)
property homogeneous_coordinates: HomogeneousCoordinates#

A unique sequence of integer-valued homogeneous coordinates in \(\mathbb{P}^2\) for this rational point.

For a rational point \(P = \left(\frac{a}{c},\frac{b}{d}\right)\) the triple \(\left(\lambda \frac{a}{c}, \lambda \frac{b}{d}, \lambda\right) = \left(a \frac{\lambda}{c}, b \frac{\lambda}{d}, \lambda\right)\), where \(\lambda = \text{lcm}(c, d) > 0\), represents a unique representative sequence of homogeneous coordinates for \(P\) in \(\mathbb{P}^2\) such that \(\left(a \frac{\lambda}{c}, b \frac{\lambda}{d}, \lambda\right)\) are all integers (not all zero) and \(\text{gcd}\left(a \frac{\lambda}{c}, b \frac{\lambda}{d}, \lambda\right) = 1\).

Returns:
HomogeneousCoordinates

A tuple of “minimal” integer-valued homogeneous coordinates in for this rational point in projective space \(\mathbb{P}^2\).

Examples

>>> from fractions import Fraction as F
>>> RationalPoint(0, 0).homogeneous_coordinates
HomogeneousCoordinates(0, 0, 1)
>>> RationalPoint(F(1, 2), F(3, 4)).homogeneous_coordinates
HomogeneousCoordinates(2, 3, 4)
>>> RationalPoint(F(1, 2), F(2, 3)).homogeneous_coordinates
HomogeneousCoordinates(3, 4, 6)
>>> RationalPoint(-1, 1).homogeneous_coordinates
HomogeneousCoordinates(-1, 1, 1)
>>> RationalPoint(1, 1).homogeneous_coordinates
HomogeneousCoordinates(1, 1, 1)
Type:

HomogeneousCoordinates

property height: int#

The height of the rational point in the projective space \(\mathbb{P}^2\).

The height \(H\left(\frac{a}{c},\frac{b}{d}\right)\) of a rational point \(P = \left(\frac{a}{c},\frac{b}{d}\right)\) as given by:

\[\text{max}\left(|a|\lvert \frac{\lambda}{c} \rvert, |b|\lvert \frac{\lambda}{d} \rvert, \lambda \right)\]

where \(\lambda = \text{lcm}(c, d) > 0\), and \(\left(\lambda \frac{a}{c}, \lambda \frac{b}{d}, \lambda\right) = \left(a \frac{\lambda}{c}, b \frac{\lambda}{d}, \lambda\right)\) is a unique sequence of integer-valued homogeneous coordinates \(\left(\lambda \frac{a}{c}, \lambda \frac{b}{d}, \lambda\right) = \left(a \frac{\lambda}{c}, b \frac{\lambda}{d}, \lambda\right)\) of \(P\) in \(\mathbb{P}^2\).

Returns:
int

The height of this rational point as defined above.

Examples

>>> from fractions import Fraction as F
>>> RationalPoint(0, 0).height
1
>>> RationalPoint(1, 1).height
1
>>> RationalPoint(-1, 1).height
1
>>> RationalPoint(F(3, 5), F(4, 5)).height
5
>>> RationalPoint(F(1, 2), F(3, 5)).height
10
Type:

int

property log_height: Decimal#

The natural logarithm of the height of the rational point as defined above.

The (natural) logarithm of the height of a rational point \(P = \left(\frac{a}{c},\frac{b}{d}\right)\) as given by:

\[\text{log}\left(H\left(\frac{a}{c}, \frac{b}{d}\right)\right) = \text{log}\left(\text{max}\left(|a|\lvert \frac{\lambda}{c} \rvert, |b|\lvert \frac{\lambda}{d} \rvert, \lambda \right)\right)\]

where \(\lambda = \text{lcm}(c, d) > 0\) and \(\left(\lambda \frac{a}{c}, \lambda \frac{b}{d}, \lambda\right) = \left(a \frac{\lambda}{c}, b \frac{\lambda}{d}, \lambda\right)\) is a unique sequence of integer-valued homogeneous coordinates for \(P\) in \(\mathbb{P}^2\), as defined above.

Returns:
decimal.Decimal

The (natural) logarithm of the height of this rational point in \(\mathbb{P}^2\) as defined above.

Examples

>>> from fractions import Fraction as F
>>> RationalPoint(0, 0).log_height
Decimal('0')
>>> RationalPoint(1, 1).log_height
Decimal('0')
>>> RationalPoint(-1, 1).log_height
Decimal('0')
>>> RationalPoint(F(3, 5), F(4, 5)).log_height
Decimal('1.6094379124341002817999424223671667277812957763671875')
>>> RationalPoint(F(1, 2), F(3, 5)).log_height
Decimal('2.30258509299404590109361379290930926799774169921875')
Type:

Decimal

__add__(other: RationalPoint) RationalPoint[source]#

RationalPoint : Component-wise addition for two rational points.

Implements component-wise addition of two rational points:

\[\left(\frac{a}{c}, \frac{b}{d}\right) + \left(\frac{a'}{c'}, \frac{b'}{d'}\right) = \left(\frac{ac' + a'c}{cc'}, \frac{bd' + b'd}{dd'}\right)\]

The second operand as represented by other must be an instance of RationalPoint.

__sub__(other: RationalPoint) RationalPoint[source]#

RationalPoint : Component-wise subtraction for two rational points.

Implements component-wise subtraction of two rational points:

\[\left(\frac{a}{c}, \frac{b}{d}\right) - \left(\frac{a'}{c'}, \frac{b'}{d'}\right) = \left(\frac{ac' - a'c}{cc'}, \frac{bd' - b'd}{dd'}\right)\]

The second operand as represented by other must be an instance of RationalPoint.

__neg__() RationalPoint[source]#

RationalPoint : Component-wise negation for a rational point.

Implements component-wise negation for a rational point:

\[-\left(\frac{a}{c}, \frac{b}{d}\right) = \left(-\frac{a}{c}, -\frac{b}{d}\right)\]
__mul__(other: Any) None[source]#

Does not support component-wise right-multiplication by a scalar to respect notational convention.

__rmul__(other: int | Fraction | ContinuedFraction) RationalPoint[source]#

RationalPoint : Component-wise scalar left-multiplication of a rational number by an integer or rational number.

Implements component-wise left-multiplication of a rational point with a rational scalar \(\lambda\):

\[\lambda \left(\frac{a}{c}, \frac{b}{d}\right) = \left(\lambda \frac{a}{c}, \lambda \frac{b}{d}\right), \hspace{1em} \lambda \in \mathbb{Q}\]

The implementation is in terms of __rmul__, because conventionally scalar multiples of a vectors in vector spaces (or subspaces) such as \(\mathbb{R}^n\) are written in left-multiplication style.

The second operand must be a rational number scalar as given by an instance of int, Fraction, or ContinuedFraction.

__truediv__(other: int | Fraction | ContinuedFraction)[source]#

RationalPoint : Component-wise division by a non-zero rational scalar.

Implements component-wise division of a rational point by a non-zero rational scalar \(\lambda\):

\[\left(\frac{a}{c}, \frac{b}{d}\right) \div \lambda = \frac{1}{\lambda}\cdot \left(\frac{a}{c}, \frac{b}{d} \right) = \left(\frac{a}{\lambda c}, \frac{b}{\lambda d} \right), \hspace{1em} \lambda \in \mathbb{Q}\setminus \{0\}\]

by scaling the point by \(\frac{1}{\lambda}\).

__abs__() Decimal[source]#

Decimal : The absolute value of the rational point as the standard Euclidean norm.

For points in \(\mathbb{R}^n\) the notion of absolute value and Euclidean norm coincide.

Returns:
decimal.Decimal

The absolute value of the rational point as the standard Euclidean norm.

Examples

>>> abs(RationalPoint(0, 0))
Decimal('0')
>>> abs(RationalPoint(Fraction(3, 5), Fraction(4, 5)))
Decimal('1')
>>> abs(RationalPoint(1, 1))
Decimal('1.414213562373095048801688724')
class continuedfractions.rational_points.RationalTuple(*args: Rational)[source]#

A rational-valued tuple consisting of one or more numbers.Rational values.

The class serves as a generic base for other custom rational-valued tuple types defined in this library:

It does not contain any mathematical structure. That is left to the other custom types listed above.

Methods

scale(scalar)

numbers.Rational : A new scaled instance of the rational tuple by a rational scalar.

Examples

>>> from fractions import Fraction as F
>>> from continuedfractions.continuedfraction import ContinuedFraction as CF
>>> RationalTuple(F(1, 2), CF(3, 4))
RationalTuple(1/2, 3/4)
scale(scalar: Rational) RationalTuple[source]#

numbers.Rational : A new scaled instance of the rational tuple by a rational scalar.

Parameters:
scalarnumbers.Rational

The (rational) scalar with which to scale the rational tuple.

Returns:
RationalTuple

The scaled rational tuple.

Examples

>>> RationalTuple(1, Fraction(-2, 3), ContinuedFraction(4, 5)).scale(15)
RationalTuple(15, -10, 12)
>>> RationalTuple(1, Fraction(-2, 3), ContinuedFraction(4, 5)).scale(Fraction(1, 2))
RationalTuple(1/2, -1/3, 2/5)
>>> RationalTuple(1, Fraction(-2, 3), ContinuedFraction(4, 5)).scale(ContinuedFraction(-5, 6))
RationalTuple(-5/6, 5/9, -2/3)