cgmath/
structure.rs

1// Copyright 2016 The CGMath Developers. For a full listing of the authors,
2// refer to the Cargo.toml file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Generic algebraic structures
17
18use num_traits::{cast, Float};
19use std::cmp;
20use std::iter;
21use std::ops::*;
22
23use approx;
24
25use angle::Rad;
26use num::{BaseFloat, BaseNum};
27
28pub use num_traits::{Bounded, One, Zero};
29
30/// An array containing elements of type `Element`
31pub trait Array
32where
33    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
34    Self: Index<usize, Output = <Self as Array>::Element>,
35    Self: IndexMut<usize, Output = <Self as Array>::Element>,
36{
37    type Element: Copy;
38
39    /// Get the number of elements in the array type
40    ///
41    /// ```rust
42    /// use cgmath::prelude::*;
43    /// use cgmath::Vector3;
44    ///
45    /// assert_eq!(Vector3::<f32>::len(), 3);
46    /// ```
47    fn len() -> usize;
48
49    /// Construct a vector from a single value, replicating it.
50    ///
51    /// ```rust
52    /// use cgmath::prelude::*;
53    /// use cgmath::Vector3;
54    ///
55    /// assert_eq!(Vector3::from_value(1),
56    ///            Vector3::new(1, 1, 1));
57    /// ```
58    fn from_value(value: Self::Element) -> Self;
59
60    /// Get the pointer to the first element of the array.
61    #[inline]
62    fn as_ptr(&self) -> *const Self::Element {
63        &self[0]
64    }
65
66    /// Get a mutable pointer to the first element of the array.
67    #[inline]
68    fn as_mut_ptr(&mut self) -> *mut Self::Element {
69        &mut self[0]
70    }
71
72    /// Swap the elements at indices `i` and `j` in-place.
73    #[inline]
74    fn swap_elements(&mut self, i: usize, j: usize) {
75        use std::ptr;
76
77        // Yeah, ok borrow checker – I know what I'm doing here
78        unsafe { ptr::swap(&mut self[i], &mut self[j]) };
79    }
80
81    /// The sum of the elements of the array.
82    fn sum(self) -> Self::Element
83    where
84        Self::Element: Add<Output = <Self as Array>::Element>;
85
86    /// The product of the elements of the array.
87    fn product(self) -> Self::Element
88    where
89        Self::Element: Mul<Output = <Self as Array>::Element>;
90
91    /// Whether all elements of the array are finite
92    fn is_finite(&self) -> bool
93    where
94        Self::Element: Float;
95}
96
97/// Element-wise arithmetic operations. These are supplied for pragmatic
98/// reasons, but will usually fall outside of traditional algebraic properties.
99pub trait ElementWise<Rhs = Self> {
100    fn add_element_wise(self, rhs: Rhs) -> Self;
101    fn sub_element_wise(self, rhs: Rhs) -> Self;
102    fn mul_element_wise(self, rhs: Rhs) -> Self;
103    fn div_element_wise(self, rhs: Rhs) -> Self;
104    fn rem_element_wise(self, rhs: Rhs) -> Self;
105
106    fn add_assign_element_wise(&mut self, rhs: Rhs);
107    fn sub_assign_element_wise(&mut self, rhs: Rhs);
108    fn mul_assign_element_wise(&mut self, rhs: Rhs);
109    fn div_assign_element_wise(&mut self, rhs: Rhs);
110    fn rem_assign_element_wise(&mut self, rhs: Rhs);
111}
112
113/// Vectors that can be [added](http://mathworld.wolfram.com/VectorAddition.html)
114/// together and [multiplied](https://en.wikipedia.org/wiki/Scalar_multiplication)
115/// by scalars.
116///
117/// Examples include vectors, matrices, and quaternions.
118///
119/// # Required operators
120///
121/// ## Vector addition
122///
123/// Vectors can be added, subtracted, or negated via the following traits:
124///
125/// - `Add<Output = Self>`
126/// - `Sub<Output = Self>`
127/// - `Neg<Output = Self>`
128///
129/// ```rust
130/// use cgmath::Vector3;
131///
132/// let velocity0 = Vector3::new(1, 2, 0);
133/// let velocity1 = Vector3::new(1, 1, 0);
134///
135/// let total_velocity = velocity0 + velocity1;
136/// let velocity_diff = velocity1 - velocity0;
137/// let reversed_velocity0 = -velocity0;
138/// ```
139///
140/// Vector spaces are also required to implement the additive identity trait,
141/// `Zero`. Adding this to another vector should have no effect:
142///
143/// ```rust
144/// use cgmath::prelude::*;
145/// use cgmath::Vector2;
146///
147/// let v = Vector2::new(1, 2);
148/// assert_eq!(v + Vector2::zero(), v);
149/// ```
150///
151/// ## Scalar multiplication
152///
153/// Vectors can be multiplied or divided by their associated scalars via the
154/// following traits:
155///
156/// - `Mul<Self::Scalar, Output = Self>`
157/// - `Div<Self::Scalar, Output = Self>`
158/// - `Rem<Self::Scalar, Output = Self>`
159///
160/// ```rust
161/// use cgmath::Vector2;
162///
163/// let translation = Vector2::new(3.0, 4.0);
164/// let scale_factor = 2.0;
165///
166/// let upscaled_translation = translation * scale_factor;
167/// let downscaled_translation = translation / scale_factor;
168/// ```
169pub trait VectorSpace: Copy + Clone
170where
171    Self: Zero,
172
173    Self: Add<Self, Output = Self>,
174    Self: Sub<Self, Output = Self>,
175    Self: iter::Sum<Self>,
176
177    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
178    Self: Mul<<Self as VectorSpace>::Scalar, Output = Self>,
179    Self: Div<<Self as VectorSpace>::Scalar, Output = Self>,
180    Self: Rem<<Self as VectorSpace>::Scalar, Output = Self>,
181{
182    /// The associated scalar.
183    type Scalar: BaseNum;
184
185    /// Returns the result of linearly interpolating the vector
186    /// towards `other` by the specified amount.
187    #[inline]
188    fn lerp(self, other: Self, amount: Self::Scalar) -> Self {
189        self + ((other - self) * amount)
190    }
191}
192
193/// A type with a distance function between values.
194///
195/// Examples are vectors, points, and quaternions.
196pub trait MetricSpace: Sized {
197    /// The metric to be returned by the `distance` function.
198    type Metric;
199
200    /// Returns the squared distance.
201    ///
202    /// This does not perform an expensive square root operation like in
203    /// `MetricSpace::distance` method, and so can be used to compare distances
204    /// more efficiently.
205    fn distance2(self, other: Self) -> Self::Metric;
206
207    /// The distance between two values.
208    fn distance(self, other: Self) -> Self::Metric
209    where
210        Self::Metric: Float,
211    {
212        Float::sqrt(Self::distance2(self, other))
213    }
214}
215
216/// Vectors that also have a [dot](https://en.wikipedia.org/wiki/Dot_product)
217/// (or [inner](https://en.wikipedia.org/wiki/Inner_product_space)) product.
218///
219/// The dot product allows for the definition of other useful operations, like
220/// finding the magnitude of a vector or normalizing it.
221///
222/// Examples include vectors and quaternions.
223pub trait InnerSpace: VectorSpace
224where
225    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
226    Self: MetricSpace<Metric = <Self as VectorSpace>::Scalar>,
227{
228    /// Vector dot (or inner) product.
229    fn dot(self, other: Self) -> Self::Scalar;
230
231    /// Returns `true` if the vector is perpendicular (at right angles) to the
232    /// other vector.
233    fn is_perpendicular(self, other: Self) -> bool
234    where
235        Self::Scalar: approx::UlpsEq,
236    {
237        ulps_eq!(Self::dot(self, other), &Self::Scalar::zero())
238    }
239
240    /// Returns the squared magnitude.
241    ///
242    /// This does not perform an expensive square root operation like in
243    /// `InnerSpace::magnitude` method, and so can be used to compare magnitudes
244    /// more efficiently.
245    #[inline]
246    fn magnitude2(self) -> Self::Scalar {
247        Self::dot(self, self)
248    }
249
250    /// Returns the angle between two vectors in radians.
251    fn angle(self, other: Self) -> Rad<Self::Scalar>
252    where
253        Self::Scalar: BaseFloat,
254    {
255        Rad::acos(Self::dot(self, other) / (self.magnitude() * other.magnitude()))
256    }
257
258    /// Returns the
259    /// [vector projection](https://en.wikipedia.org/wiki/Vector_projection)
260    /// of the current inner space projected onto the supplied argument.
261    #[inline]
262    fn project_on(self, other: Self) -> Self {
263        other * (self.dot(other) / other.magnitude2())
264    }
265
266    /// The distance from the tail to the tip of the vector.
267    #[inline]
268    fn magnitude(self) -> Self::Scalar
269    where
270        Self::Scalar: Float,
271    {
272        Float::sqrt(self.magnitude2())
273    }
274
275    /// Returns a vector with the same direction, but with a magnitude of `1`.
276    #[inline]
277    fn normalize(self) -> Self
278    where
279        Self::Scalar: Float,
280    {
281        self.normalize_to(Self::Scalar::one())
282    }
283
284    /// Returns a vector with the same direction and a given magnitude.
285    #[inline]
286    fn normalize_to(self, magnitude: Self::Scalar) -> Self
287    where
288        Self::Scalar: Float,
289    {
290        self * (magnitude / self.magnitude())
291    }
292}
293
294/// Points in a [Euclidean space](https://en.wikipedia.org/wiki/Euclidean_space)
295/// with an associated space of displacement vectors.
296///
297/// # Point-Vector distinction
298///
299/// `cgmath` distinguishes between points and vectors in the following way:
300///
301/// - Points are _locations_ relative to an origin
302/// - Vectors are _displacements_ between those points
303///
304/// For example, to find the midpoint between two points, you can write the
305/// following:
306///
307/// ```rust
308/// use cgmath::Point3;
309///
310/// let p0 = Point3::new(1.0, 2.0, 3.0);
311/// let p1 = Point3::new(-3.0, 1.0, 2.0);
312/// let midpoint: Point3<f32> = p0 + (p1 - p0) * 0.5;
313/// ```
314///
315/// Breaking the expression up, and adding explicit types makes it clearer
316/// to see what is going on:
317///
318/// ```rust
319/// # use cgmath::{Point3, Vector3};
320/// #
321/// # let p0 = Point3::new(1.0, 2.0, 3.0);
322/// # let p1 = Point3::new(-3.0, 1.0, 2.0);
323/// #
324/// let dv: Vector3<f32> = p1 - p0;
325/// let half_dv: Vector3<f32> = dv * 0.5;
326/// let midpoint: Point3<f32> = p0 + half_dv;
327/// ```
328///
329/// ## Converting between points and vectors
330///
331/// Points can be converted to and from displacement vectors using the
332/// `EuclideanSpace::{from_vec, to_vec}` methods. Note that under the hood these
333/// are implemented as inlined a type conversion, so should not have any
334/// performance implications.
335///
336/// ## References
337///
338/// - [CGAL 4.7 - 2D and 3D Linear Geometry Kernel: 3.1 Points and Vectors](http://doc.cgal.org/latest/Kernel_23/index.html#Kernel_23PointsandVectors)
339/// - [What is the difference between a point and a vector](http://math.stackexchange.com/q/645827)
340///
341pub trait EuclideanSpace: Copy + Clone
342where
343    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
344    Self: Array<Element = <Self as EuclideanSpace>::Scalar>,
345
346    Self: Add<<Self as EuclideanSpace>::Diff, Output = Self>,
347    Self: Sub<<Self as EuclideanSpace>::Diff, Output = Self>,
348    Self: Sub<Self, Output = <Self as EuclideanSpace>::Diff>,
349
350    Self: Mul<<Self as EuclideanSpace>::Scalar, Output = Self>,
351    Self: Div<<Self as EuclideanSpace>::Scalar, Output = Self>,
352    Self: Rem<<Self as EuclideanSpace>::Scalar, Output = Self>,
353{
354    /// The associated scalar over which the space is defined.
355    ///
356    /// Due to the equality constraints demanded by `Self::Diff`, this is effectively just an
357    /// alias to `Self::Diff::Scalar`.
358    type Scalar: BaseNum;
359
360    /// The associated space of displacement vectors.
361    type Diff: VectorSpace<Scalar = Self::Scalar>;
362
363    /// The point at the origin of the Euclidean space.
364    fn origin() -> Self;
365
366    /// Convert a displacement vector to a point.
367    ///
368    /// This can be considered equivalent to the addition of the displacement
369    /// vector `v` to to `Self::origin()`.
370    fn from_vec(v: Self::Diff) -> Self;
371
372    /// Convert a point to a displacement vector.
373    ///
374    /// This can be seen as equivalent to the displacement vector from
375    /// `Self::origin()` to `self`.
376    fn to_vec(self) -> Self::Diff;
377
378    /// Returns the middle point between two other points.
379    ///
380    /// ```rust
381    /// use cgmath::prelude::*;
382    /// use cgmath::Point3;
383    ///
384    /// let p = Point3::midpoint(
385    ///     Point3::new(1.0, 2.0, 3.0),
386    ///     Point3::new(3.0, 1.0, 2.0),
387    /// );
388    /// ```
389    #[inline]
390    fn midpoint(self, other: Self) -> Self {
391        self + (other - self) / cast(2).unwrap()
392    }
393
394    /// Returns the average position of all points in the slice.
395    ///
396    /// ```rust
397    /// use cgmath::prelude::*;
398    /// use cgmath::Point2;
399    ///
400    /// let triangle = [
401    ///     Point2::new(1.0, 1.0),
402    ///     Point2::new(2.0, 3.0),
403    ///     Point2::new(3.0, 1.0),
404    /// ];
405    ///
406    /// let centroid = Point2::centroid(&triangle);
407    /// ```
408    #[inline]
409    fn centroid(points: &[Self]) -> Self {
410        let total_displacement = points
411            .iter()
412            .fold(Self::Diff::zero(), |acc, p| acc + p.to_vec());
413
414        Self::from_vec(total_displacement / cast(points.len()).unwrap())
415    }
416
417    /// This is a weird one, but its useful for plane calculations.
418    fn dot(self, v: Self::Diff) -> Self::Scalar;
419}
420
421/// A column-major matrix of arbitrary dimensions.
422///
423/// Because this is constrained to the `VectorSpace` trait, this means that
424/// following operators are required to be implemented:
425///
426/// Matrix addition:
427///
428/// - `Add<Output = Self>`
429/// - `Sub<Output = Self>`
430/// - `Neg<Output = Self>`
431///
432/// Scalar multiplication:
433///
434/// - `Mul<Self::Scalar, Output = Self>`
435/// - `Div<Self::Scalar, Output = Self>`
436/// - `Rem<Self::Scalar, Output = Self>`
437///
438/// Note that matrix multiplication is not required for implementors of this
439/// trait. This is due to the complexities of implementing these operators with
440/// Rust's current type system. For the multiplication of square matrices,
441/// see `SquareMatrix`.
442pub trait Matrix: VectorSpace
443where
444    Self::Scalar: Float,
445
446    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
447    Self: Index<usize, Output = <Self as Matrix>::Column>,
448    Self: IndexMut<usize, Output = <Self as Matrix>::Column>,
449{
450    /// The row vector of the matrix.
451    type Row: VectorSpace<Scalar = Self::Scalar> + Array<Element = Self::Scalar>;
452
453    /// The column vector of the matrix.
454    type Column: VectorSpace<Scalar = Self::Scalar> + Array<Element = Self::Scalar>;
455
456    /// The result of transposing the matrix
457    type Transpose: Matrix<Scalar = Self::Scalar, Row = Self::Column, Column = Self::Row>;
458
459    /// Get the pointer to the first element of the array.
460    #[inline]
461    fn as_ptr(&self) -> *const Self::Scalar {
462        &self[0][0]
463    }
464
465    /// Get a mutable pointer to the first element of the array.
466    #[inline]
467    fn as_mut_ptr(&mut self) -> *mut Self::Scalar {
468        &mut self[0][0]
469    }
470
471    /// Replace a column in the array.
472    #[inline]
473    fn replace_col(&mut self, c: usize, src: Self::Column) -> Self::Column {
474        use std::mem;
475
476        mem::replace(&mut self[c], src)
477    }
478
479    /// Get a row from this matrix by-value.
480    fn row(&self, r: usize) -> Self::Row;
481
482    /// Swap two rows of this array.
483    fn swap_rows(&mut self, a: usize, b: usize);
484    /// Swap two columns of this array.
485    fn swap_columns(&mut self, a: usize, b: usize);
486    /// Swap the values at index `a` and `b`
487    fn swap_elements(&mut self, a: (usize, usize), b: (usize, usize));
488
489    /// Transpose this matrix, returning a new matrix.
490    fn transpose(&self) -> Self::Transpose;
491}
492
493/// A column-major major matrix where the rows and column vectors are of the same dimensions.
494pub trait SquareMatrix
495where
496    Self::Scalar: Float,
497
498    Self: One,
499    Self: iter::Product<Self>,
500
501    Self: Matrix<
502        // FIXME: Can be cleaned up once equality constraints in where clauses are implemented
503        Column = <Self as SquareMatrix>::ColumnRow,
504        Row = <Self as SquareMatrix>::ColumnRow,
505        Transpose = Self,
506    >,
507    Self: Mul<<Self as SquareMatrix>::ColumnRow, Output = <Self as SquareMatrix>::ColumnRow>,
508    Self: Mul<Self, Output = Self>,
509{
510    // FIXME: Will not be needed once equality constraints in where clauses are implemented
511    /// The row/column vector of the matrix.
512    ///
513    /// This is used to constrain the column and rows to be of the same type in lieu of equality
514    /// constraints being implemented for `where` clauses. Once those are added, this type will
515    /// likely go away.
516    type ColumnRow: VectorSpace<Scalar = Self::Scalar> + Array<Element = Self::Scalar>;
517
518    /// Create a new diagonal matrix using the supplied value.
519    fn from_value(value: Self::Scalar) -> Self;
520    /// Create a matrix from a non-uniform scale
521    fn from_diagonal(diagonal: Self::ColumnRow) -> Self;
522
523    /// The [identity matrix]. Multiplying this matrix with another should have
524    /// no effect.
525    ///
526    /// Note that this is exactly the same as `One::one`. The term 'identity
527    /// matrix' is more common though, so we provide this method as an
528    /// alternative.
529    ///
530    /// [identity matrix]: https://en.wikipedia.org/wiki/Identity_matrix
531    #[inline]
532    fn identity() -> Self {
533        Self::one()
534    }
535
536    /// Transpose this matrix in-place.
537    fn transpose_self(&mut self);
538    /// Take the determinant of this matrix.
539    fn determinant(&self) -> Self::Scalar;
540
541    /// Return a vector containing the diagonal of this matrix.
542    fn diagonal(&self) -> Self::ColumnRow;
543
544    /// Return the trace of this matrix. That is, the sum of the diagonal.
545    #[inline]
546    fn trace(&self) -> Self::Scalar {
547        self.diagonal().sum()
548    }
549
550    /// Invert this matrix, returning a new matrix. `m.mul_m(m.invert())` is
551    /// the identity matrix. Returns `None` if this matrix is not invertible
552    /// (has a determinant of zero).
553    fn invert(&self) -> Option<Self>;
554
555    /// Test if this matrix is invertible.
556    #[inline]
557    fn is_invertible(&self) -> bool
558    where
559        Self::Scalar: approx::UlpsEq,
560    {
561        ulps_ne!(self.determinant(), &Self::Scalar::zero())
562    }
563
564    /// Test if this matrix is the identity matrix. That is, it is diagonal
565    /// and every element in the diagonal is one.
566    #[inline]
567    fn is_identity(&self) -> bool
568    where
569        Self: approx::UlpsEq,
570    {
571        ulps_eq!(self, &Self::identity())
572    }
573
574    /// Test if this is a diagonal matrix. That is, every element outside of
575    /// the diagonal is 0.
576    fn is_diagonal(&self) -> bool;
577
578    /// Test if this matrix is symmetric. That is, it is equal to its
579    /// transpose.
580    fn is_symmetric(&self) -> bool;
581}
582
583/// Angles and their associated trigonometric functions.
584///
585/// Typed angles allow for the writing of self-documenting code that makes it
586/// clear when semantic violations have occured - for example, adding degrees to
587/// radians, or adding a number to an angle.
588///
589pub trait Angle
590where
591    Self: Copy + Clone,
592    Self: PartialEq + cmp::PartialOrd,
593    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
594    Self: approx::AbsDiffEq<Epsilon = <Self as Angle>::Unitless>,
595    Self: approx::RelativeEq<Epsilon = <Self as Angle>::Unitless>,
596    Self: approx::UlpsEq<Epsilon = <Self as Angle>::Unitless>,
597
598    Self: Zero,
599
600    Self: Neg<Output = Self>,
601    Self: Add<Self, Output = Self>,
602    Self: Sub<Self, Output = Self>,
603    Self: Rem<Self, Output = Self>,
604    Self: Mul<<Self as Angle>::Unitless, Output = Self>,
605    Self: Div<Self, Output = <Self as Angle>::Unitless>,
606    Self: Div<<Self as Angle>::Unitless, Output = Self>,
607
608    Self: iter::Sum,
609{
610    type Unitless: BaseFloat;
611
612    /// Return the angle, normalized to the range `[0, full_turn)`.
613    #[inline]
614    fn normalize(self) -> Self {
615        let rem = self % Self::full_turn();
616        if rem < Self::zero() {
617            rem + Self::full_turn()
618        } else {
619            rem
620        }
621    }
622
623    /// Return the angle, normalized to the range `[-turn_div_2, turn_div_2)`.
624    #[inline]
625    fn normalize_signed(self) -> Self {
626        let rem = self.normalize();
627        if Self::turn_div_2() < rem {
628            rem - Self::full_turn()
629        } else {
630            rem
631        }
632    }
633
634    /// Return the angle rotated by half a turn.
635    #[inline]
636    fn opposite(self) -> Self {
637        Self::normalize(self + Self::turn_div_2())
638    }
639
640    /// Returns the interior bisector of the two angles.
641    #[inline]
642    fn bisect(self, other: Self) -> Self {
643        let half = cast(0.5f64).unwrap();
644        Self::normalize((self - other) * half + self)
645    }
646
647    /// A full rotation.
648    fn full_turn() -> Self;
649
650    /// Half of a full rotation.
651    #[inline]
652    fn turn_div_2() -> Self {
653        let factor: Self::Unitless = cast(2).unwrap();
654        Self::full_turn() / factor
655    }
656
657    /// A third of a full rotation.
658    #[inline]
659    fn turn_div_3() -> Self {
660        let factor: Self::Unitless = cast(3).unwrap();
661        Self::full_turn() / factor
662    }
663
664    /// A quarter of a full rotation.
665    #[inline]
666    fn turn_div_4() -> Self {
667        let factor: Self::Unitless = cast(4).unwrap();
668        Self::full_turn() / factor
669    }
670
671    /// A sixth of a full rotation.
672    #[inline]
673    fn turn_div_6() -> Self {
674        let factor: Self::Unitless = cast(6).unwrap();
675        Self::full_turn() / factor
676    }
677
678    /// Compute the sine of the angle, returning a unitless ratio.
679    ///
680    /// ```rust
681    /// use cgmath::prelude::*;
682    /// use cgmath::Rad;
683    ///
684    /// let angle = Rad(35.0);
685    /// let ratio: f32 = Rad::sin(angle);
686    /// ```
687    fn sin(self) -> Self::Unitless;
688
689    /// Compute the cosine of the angle, returning a unitless ratio.
690    ///
691    /// ```rust
692    /// use cgmath::prelude::*;
693    /// use cgmath::Rad;
694    ///
695    /// let angle = Rad(35.0);
696    /// let ratio: f32 = Rad::cos(angle);
697    /// ```
698    fn cos(self) -> Self::Unitless;
699
700    /// Compute the tangent of the angle, returning a unitless ratio.
701    ///
702    /// ```rust
703    /// use cgmath::prelude::*;
704    /// use cgmath::Rad;
705    ///
706    /// let angle = Rad(35.0);
707    /// let ratio: f32 = Rad::tan(angle);
708    /// ```
709    fn tan(self) -> Self::Unitless;
710
711    /// Compute the sine and cosine of the angle, returning the result as a
712    /// pair.
713    ///
714    /// This does not have any performance benefits, but calculating both the
715    /// sine and cosine of a single angle is a common operation.
716    ///
717    /// ```rust
718    /// use cgmath::prelude::*;
719    /// use cgmath::Rad;
720    ///
721    /// let angle = Rad(35.0);
722    /// let (s, c) = Rad::sin_cos(angle);
723    /// ```
724    fn sin_cos(self) -> (Self::Unitless, Self::Unitless);
725
726    /// Compute the cosecant of the angle.
727    ///
728    /// This is the same as computing the reciprocal of `Self::sin`.
729    ///
730    /// ```rust
731    /// use cgmath::prelude::*;
732    /// use cgmath::Rad;
733    ///
734    /// let angle = Rad(35.0);
735    /// let ratio: f32 = Rad::csc(angle);
736    /// ```
737    #[inline]
738    fn csc(self) -> Self::Unitless {
739        Self::sin(self).recip()
740    }
741
742    /// Compute the cotangent of the angle.
743    ///
744    /// This is the same as computing the reciprocal of `Self::tan`.
745    ///
746    /// ```rust
747    /// use cgmath::prelude::*;
748    /// use cgmath::Rad;
749    ///
750    /// let angle = Rad(35.0);
751    /// let ratio: f32 = Rad::cot(angle);
752    /// ```
753    #[inline]
754    fn cot(self) -> Self::Unitless {
755        Self::tan(self).recip()
756    }
757
758    /// Compute the secant of the angle.
759    ///
760    /// This is the same as computing the reciprocal of `Self::cos`.
761    ///
762    /// ```rust
763    /// use cgmath::prelude::*;
764    /// use cgmath::Rad;
765    ///
766    /// let angle = Rad(35.0);
767    /// let ratio: f32 = Rad::sec(angle);
768    /// ```
769    #[inline]
770    fn sec(self) -> Self::Unitless {
771        Self::cos(self).recip()
772    }
773
774    /// Compute the arcsine of the ratio, returning the resulting angle.
775    ///
776    /// ```rust
777    /// use cgmath::prelude::*;
778    /// use cgmath::Rad;
779    ///
780    /// let angle: Rad<f32> = Rad::asin(0.5);
781    /// ```
782    fn asin(ratio: Self::Unitless) -> Self;
783
784    /// Compute the arccosine of the ratio, returning the resulting angle.
785    ///
786    /// ```rust
787    /// use cgmath::prelude::*;
788    /// use cgmath::Rad;
789    ///
790    /// let angle: Rad<f32> = Rad::acos(0.5);
791    /// ```
792    fn acos(ratio: Self::Unitless) -> Self;
793
794    /// Compute the arctangent of the ratio, returning the resulting angle.
795    ///
796    /// ```rust
797    /// use cgmath::prelude::*;
798    /// use cgmath::Rad;
799    ///
800    /// let angle: Rad<f32> = Rad::atan(0.5);
801    /// ```
802    fn atan(ratio: Self::Unitless) -> Self;
803
804    fn atan2(a: Self::Unitless, b: Self::Unitless) -> Self;
805}