pbrt 0.1.5

Rust implementation of https://pbrt.org/
Documentation
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Types and utilities for dealing with 2D and 3D, integer and float data types.
use std::fmt;
use std::ops::Add;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Sub;

use crate::float;
use crate::Float;

mod bounds;
pub use crate::core::geometry::bounds::Bounds2;
pub use crate::core::geometry::bounds::Bounds2f;
pub use crate::core::geometry::bounds::Bounds2i;
pub use crate::core::geometry::bounds::Bounds3;
pub use crate::core::geometry::bounds::Bounds3f;
pub use crate::core::geometry::bounds::Bounds3i;

mod normal;
pub use crate::core::geometry::normal::Normal3;
pub use crate::core::geometry::normal::Normal3f;

mod point;
pub use crate::core::geometry::point::Point2;
pub use crate::core::geometry::point::Point2f;
pub use crate::core::geometry::point::Point2i;
pub use crate::core::geometry::point::Point3;
pub use crate::core::geometry::point::Point3f;
pub use crate::core::geometry::point::Point3i;

mod vector;
pub use crate::core::geometry::vector::Vector2;
pub use crate::core::geometry::vector::Vector2f;
pub use crate::core::geometry::vector::Vector2i;
pub use crate::core::geometry::vector::Vector3f;
pub use crate::core::geometry::vector::Vector3i;

/// Trait for ensuring methods present on only `{float}` or `{integer}` types have appropriate
/// implementations as necessary for this crate.
pub trait Number
where
    Self: std::marker::Sized
        + Copy
        + fmt::Display
        + std::cmp::PartialOrd
        + Add<Output = Self>
        + Div<Output = Self>
        + Mul<Output = Self>
        + Sub<Output = Self>,
{
    /// Returns true if this value is NaN.
    /// # Examples
    /// ```
    /// use pbrt::core::geometry::Number;
    /// use pbrt::float::NAN;
    /// use pbrt::Float;
    ///
    /// let i: isize = 1;
    /// let f1: Float = 1.;
    /// let f2 = NAN;
    /// assert_eq!(Number::is_nan(f1), false);
    /// assert_eq!(Number::is_nan(f2), true);
    /// assert_eq!(Number::is_nan(i), false);
    /// ```
    fn is_nan(self) -> bool;

    /// Returns the smallest value this type can hold.
    ///
    /// # Examples
    /// ```
    /// use pbrt::core::geometry::Number;
    /// use pbrt::Float;
    ///
    /// #[cfg(not(feature = "float-as-double"))]
    /// assert_eq!(<Float as Number>::min_value(), -3.4028235e+38);
    /// #[cfg(feature = "float-as-double")]
    /// assert_eq!(<Float as Number>::min_value(), -1.7976931348623157e+308);
    /// assert_eq!(<isize as Number>::min_value(), -9223372036854775808);
    /// ```
    fn min_value() -> Self;

    /// Returns the largest value this type can hold.
    ///
    /// # Examples
    /// ```
    /// use pbrt::core::geometry::Number;
    /// use pbrt::Float;
    ///
    /// #[cfg(not(feature = "float-as-double"))]
    /// assert_eq!(<Float as Number>::max_value(), 3.4028235e+38);
    /// #[cfg(feature = "float-as-double")]
    /// assert_eq!(<Float as Number>::max_value(), 1.7976931348623157e+308);
    /// assert_eq!(<isize as Number>::max_value(), 9223372036854775807);
    /// ```
    fn max_value() -> Self;

    /// Returns the maximum of self or other.  No special care is taken for NaN and infinity.
    ///
    /// # Examples
    /// ```
    /// use pbrt::core::geometry::Number;
    /// use pbrt::Float;
    ///
    /// let x: Float = 1.;
    /// let y: Float = 2.;
    ///
    /// assert_eq!(Number::max(x, y), y);
    /// assert_eq!(Number::max(x, y), y);
    ///
    /// let a: isize = 1;
    /// let b: isize = 2;
    ///
    /// assert_eq!(Number::max(a, b), b);
    /// assert_eq!(Number::max(a, b), b);
    ///
    /// fn bigger<T>(m: T, n: T) -> T
    /// where
    ///     T: Number,
    /// {
    ///     m.max(n)
    /// }
    /// assert_eq!(bigger(a, b), b)
    /// ```
    fn max(self, other: Self) -> Self;

    /// Returns the minimum of self or other.  No special care is taken for NaN and infinity.
    ///
    /// # Examples
    /// ```
    /// use pbrt::core::geometry::Number;
    /// use pbrt::Float;
    ///
    /// let x: Float = 1.;
    /// let y: Float = 2.;
    ///
    /// assert_eq!(Number::min(x, y), x);
    /// assert_eq!(Number::min(x, y), x);
    ///
    /// let a: isize = 1;
    /// let b: isize = 2;
    ///
    /// assert_eq!(Number::min(a, b), a);
    /// assert_eq!(Number::min(a, b), a);
    ///
    /// fn smaller<T>(m: T, n: T) -> T
    /// where
    ///     T: Number,
    /// {
    ///     m.min(n)
    /// }
    /// assert_eq!(smaller(a, b), a)
    /// ```
    fn min(self, other: Self) -> Self;
}

impl Number for Float {
    fn is_nan(self) -> bool {
        self.is_nan()
    }
    fn min_value() -> Self {
        float::MIN
    }
    fn max_value() -> Self {
        float::MAX
    }
    fn max(self, other: Self) -> Self {
        if self > other {
            self
        } else {
            other
        }
    }
    fn min(self, other: Self) -> Self {
        if self < other {
            self
        } else {
            other
        }
    }
}

impl Number for isize {
    fn is_nan(self) -> bool {
        false
    }
    fn min_value() -> Self {
        std::isize::MIN
    }
    fn max_value() -> Self {
        std::isize::MAX
    }
    fn max(self, other: Self) -> Self {
        if self > other {
            self
        } else {
            other
        }
    }
    fn min(self, other: Self) -> Self {
        if self < other {
            self
        } else {
            other
        }
    }
}