<commit_before>use super::*;
use crate::shapes::{GeoClass, Shape};
use crate::StrError;
use russell_lab::Vector;
use russell_tensor::Tensor2;

/// Defines scalar function (the argument is index of the integration point)
pub type FnScalar = fn(usize) -> f64;

/// Defines vector function (the second argument is index of the integration point)
pub type FnVector = fn(&mut Vector, usize);

/// Defines tensor function (the second argument is index of the integration point)
pub type FnTensor = fn(&mut Tensor2, usize);

impl Shape {
    /// Selects integrations points and weights
    ///
    /// # Options
    ///
    /// ## nip for Lin class
    ///
    /// * `1` -- Legendre points
    /// * `2` -- Legendre points
    /// * `3` -- Legendre points
    /// * `4` -- Legendre points
    /// * `5` -- Legendre points
    ///
    /// ## nip for Tri class
    ///
    /// * `1` -- Internal points
    /// * `3`:
    ///     - `edge` -- Points on edge
    ///     - otherwise, internal points
    /// * `4` -- Internal points
    /// * `12` -- Internal points
    /// * `16` -- Internal points
    ///
    /// ## nip for Qua class
    ///
    /// * `1` -- Legendre points
    /// * `4` -- Legendre points
    /// * `5`:
    ///     - `ws` -- Wilson's "Stable" version with w0=0.004 and wa=0.999 to mimic 4-point rule
    ///     - otherwise, standard Wilson's formula
    /// * `9` -- Legendre points
    /// * `16` -- Legendre points
    ///
    /// ## nip for Tet class
    ///
    /// * `1` -- Internal points
    /// * `4` -- Internal points
    /// * `5` -- Internal points
    /// * `6` -- Internal points
    ///
    /// ## nip for Hex class
    ///
    /// * `6` -- Iron's formula
    /// * `8` -- Legendre points
    /// * `9`:
    ///     - `ws` -- Wilson's "Stable" version
    ///     - otherwise, Wilson's standard formula
    /// * `14` -- Iron's formula
    /// * `27` -- Legendre points
    pub fn select_int_points(&mut self, nip: usize, edge: bool, ws: bool) -> Result<(), StrError> {
        match self.class {
            // Lin
            GeoClass::Lin => match nip {
                1 => self.ip_data = &IP_LIN_LEGENDRE_1,
                2 => self.ip_data = &IP_LIN_LEGENDRE_2,
                3 => self.ip_data = &IP_LIN_LEGENDRE_3,
                4 => self.ip_data = &IP_LIN_LEGENDRE_4,
                5 => self.ip_data = &IP_LIN_LEGENDRE_5,
                _ => return Err("number of integration points is not available for Lin class"),
            },

            // Tri
            GeoClass::Tri => match nip {
                1 => self.ip_data = &IP_TRI_INTERNAL_1,
                3 => {
                    if edge {
                        self.ip_data = &IP_TRI_EDGE_3
                    } else {
                        self.ip_data = &IP_TRI_INTERNAL_3
                    }
                }
                4 => self.ip_data = &IP_TRI_INTERNAL_4,
                12 => self.ip_data = &IP_TRI_INTERNAL_12,
                16 => self.ip_data = &IP_TRI_INTERNAL_16,
                _ => return Err("number of integration points is not available for Tri class"),
            },

            // Qua
            GeoClass::Qua => match nip {
                1 => self.ip_data = &IP_QUA_LEGENDRE_1,
                4 => self.ip_data = &IP_QUA_LEGENDRE_4,
                5 => {
                    if ws {
                        self.ip_data = &IP_QUA_WILSON_STABLE_5
                    } else {
                        self.ip_data = &IP_QUA_WILSON_CORNER_5
                    }
                }
                8 => self.ip_data = &IP_QUA_WILSON_8,
                9 => self.ip_data = &IP_QUA_LEGENDRE_9,
                16 => self.ip_data = &IP_QUA_LEGENDRE_16,
                _ => return Err("number of integration points is not available for Qua class"),
            },

            // Tet
            GeoClass::Tet => match nip {
                1 => self.ip_data = &IP_TET_INTERNAL_1,
                4 => self.ip_data = &IP_TET_INTERNAL_4,
                5 => self.ip_data = &IP_TET_INTERNAL_5,
                6 => self.ip_data = &IP_TET_INTERNAL_6,
                _ => return Err("number of integration points is not available for Tet class"),
            },

            // Hex
            GeoClass::Hex => match nip {
                6 => self.ip_data = &IP_HEX_IRONS_6,
                8 => self.ip_data = &IP_HEX_LEGENDRE_8,
                9 => {
                    if ws {
                        self.ip_data = &IP_HEX_WILSON_STABLE_9
                    } else {
                        self.ip_data = &IP_HEX_WILSON_CORNER_9
                    }
                }
                14 => self.ip_data = &IP_HEX_IRONS_14,
                27 => self.ip_data = &IP_HEX_LEGENDRE_27,
                _ => return Err("number of integration points is not available for Hex class"),
            },
        }
        Ok(())
    }

    /// Performs the Case-A integration
    ///
    /// Case-A, interpolation functions times scalar field:
    ///
    /// ```text
    ///      ⌠    → →     →
    /// aᵐ = │ Nᵐ(x(ξ)) s(x) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// or, for lines in multi-dimensions,
    ///
    /// ```text
    ///      ⌠
    /// aᵐ = │ Nᵐ(ℓ(ξ)) s(ℓ) dℓ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    ///     nip-1    →     →       →
    /// aᵐ ≈  Σ   Nᵐ(ιp) s(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_s` -- s(x(ξ)) or s(ℓ) scalar function, however written as the
    ///             function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `a` -- (npoint) aᵐ scalars; result from the integration
    pub fn integ_case_a(&mut self, a: &mut [f64], fn_s: FnScalar) -> Result<(), StrError> {
        // clear results
        a.fill(0.0);

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate interpolation functions and Jacobian
            self.calc_interp(iota);
            let det_jac = self.calc_jacobian(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                a[m] += self.interp[m] * fn_s(index) * det_jac * weight;
            }
        }
        Ok(())
    }

    /// Performs the Case-B integration
    ///
    /// Case-B, interpolation functions times vector field:
    ///
    /// ```text
    /// →    ⌠    → →   → →
    /// bᵐ = │ Nᵐ(x(ξ)) v(x) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    /// →   nip-1    →   → →       →
    /// bᵐ ≈  Σ   Nᵐ(ιp) v(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_v` -- v(x(ξ)) vector function, however written as the
    ///             function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `b` -- (npoint) bᵐ vectors; result from the integration
    pub fn integ_case_b(&mut self, b: &mut Vec<Vector>, fn_v: FnVector) -> Result<(), StrError> {
        // check
        if b.len() != self.npoint {
            return Err("b.len() must equal npoint");
        }

        // check dims and clear results
        for m in 0..self.npoint {
            if b[m].dim() != self.space_ndim {
                return Err("b[m].dim() must equal space_ndim");
            }
            b[m].fill(0.0);
        }

        // auxiliary vector holding the output of fn_v
        let mut v = Vector::new(self.space_ndim);

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate interpolation functions and Jacobian
            self.calc_interp(iota);
            let det_jac = self.calc_jacobian(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                fn_v(&mut v, index);
                for i in 0..self.space_ndim {
                    b[m][i] += self.interp[m] * v[i] * det_jac * weight;
                }
            }
        }
        Ok(())
    }

    /// Performs the Case-C integration
    ///
    /// Case-C, vector dot gradient:
    ///
    /// ```text
    ///      ⌠ → →    →  → →
    /// cᵐ = │ w(x) · Gᵐ(x(ξ)) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    ///     nip-1 → →     →  →       →
    /// cᵐ ≈  Σ   w(ιp) · Gᵐ(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_w` -- w(x(ξ)) vector function, however written as the
    ///             function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `c` -- (npoint) cᵐ scalars; result from the integration
    pub fn integ_case_c(&mut self, c: &mut [f64], fn_w: FnVector) -> Result<(), StrError> {
        // clear results
        c.fill(0.0);

        // auxiliary vector holding the output of fn_w
        let mut w = Vector::new(self.space_ndim);

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate Jacobian and Gradient
            let det_jac = self.calc_gradient(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                fn_w(&mut w, index);
                let w_dot_grad = self.vec_dot_grad(m, &w);
                c[m] += w_dot_grad * det_jac * weight;
            }
        }
        Ok(())
    }

    /// Performs the Case-D integration
    ///
    /// Case-D, tensor dot gradient:
    ///
    /// ```text
    /// →    ⌠ → →    →  → →   →
    /// dᵐ = │ σ(x) · Gᵐ(x(ξ)) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    /// →   nip-1 → →     →  →       →
    /// dᵐ ≈  Σ   σ(ιp) · Gᵐ(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_sig` -- sig(x(ξ)) tensor function, however written as the
    ///               function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `d` -- (npoint) dᵐ vectors; result from the integration
    pub fn integ_case_d(&mut self, d: &mut Vec<Vector>, fn_sig: FnTensor) -> Result<(), StrError> {
        // check
        if d.len() != self.npoint {
            return Err("b.len() must equal npoint");
        }

        // check dims and clear results
        for m in 0..self.npoint {
            if d[m].dim() != self.space_ndim {
                return Err("d[m].dim() must equal space_ndim");
            }
            d[m].fill(0.0);
        }

        // auxiliary tensor holding the output of fn_sig
        let mut sig = Tensor2::new(true);

        // auxiliary vector equal to σ · G
        let mut sig_dot_grad = vec![0.0; self.space_ndim];

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate Jacobian and Gradient
            let det_jac = self.calc_gradient(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                fn_sig(&mut sig, index);
                self.tensor_dot_grad(&mut sig_dot_grad, m, &sig);
                for i in 0..self.space_ndim {
                    d[m][i] += sig_dot_grad[i] * det_jac * weight;
                }
            }
        }
        Ok(())
    }

    /// Computes vector dot the gradient at point m
    fn vec_dot_grad(&self, m: usize, w: &Vector) -> f64 {
        let mut res = 0.0;
        for i in 0..self.space_ndim {
            res += w[i] * self.gradient[m][i];
        }
        res
    }

    /// Computes tensor dot the gradient at point m
    fn tensor_dot_grad(&self, res: &mut [f64], m: usize, sig: &Tensor2) {
        for i in 0..self.space_ndim {
            res[i] = 0.0;
            for j in 0..self.space_ndim {
                res[i] += sig.get(i, j) * self.gradient[m][j];
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::*;

    // to test if variables are cleared before summation
    const NOISE: f64 = 1234.56;

    #[test]
    fn integ_case_a_works() -> Result<(), StrError> {
        let mut shape = Shape::new(2, 2, 4)?;
        shape.set_point(0, 0, 0.0)?;
        shape.set_point(0, 1, 0.0)?;
        shape.set_point(1, 0, 1.0)?;
        shape.set_point(1, 1, 0.0)?;
        shape.set_point(2, 0, 1.0)?;
        shape.set_point(2, 1, 1.0)?;
        shape.set_point(3, 0, 0.0)?;
        shape.set_point(3, 1, 1.0)?;

        let mut a = vec![NOISE; shape.npoint];

        shape.integ_case_a(&mut a, |_| 0.0)?;

        println!("a = {:?}", a);

        Ok(())
    }
}
<commit_msg>Improve doc<commit_after>use super::*;
use crate::shapes::{GeoClass, Shape};
use crate::StrError;
use russell_lab::Vector;
use russell_tensor::Tensor2;

/// Defines scalar function (the argument is index of the integration point)
pub type FnScalar = fn(usize) -> f64;

/// Defines vector function (the second argument is index of the integration point)
pub type FnVector = fn(&mut Vector, usize);

/// Defines tensor function (the second argument is index of the integration point)
pub type FnTensor = fn(&mut Tensor2, usize);

impl Shape {
    /// Selects integrations points and weights
    ///
    /// # Options
    ///
    /// ## nip for Lin class
    ///
    /// * `1` -- Legendre points
    /// * `2` -- Legendre points
    /// * `3` -- Legendre points
    /// * `4` -- Legendre points
    /// * `5` -- Legendre points
    ///
    /// ## nip for Tri class
    ///
    /// * `1` -- Internal points
    /// * `3`:
    ///     - `edge` -- Points on edge
    ///     - otherwise, internal points
    /// * `4` -- Internal points
    /// * `12` -- Internal points
    /// * `16` -- Internal points
    ///
    /// ## nip for Qua class
    ///
    /// * `1` -- Legendre points
    /// * `4` -- Legendre points
    /// * `5`:
    ///     - `ws` -- Wilson's "Stable" version with w0=0.004 and wa=0.999 to mimic 4-point rule
    ///     - otherwise, standard Wilson's formula
    /// * `9` -- Legendre points
    /// * `16` -- Legendre points
    ///
    /// ## nip for Tet class
    ///
    /// * `1` -- Internal points
    /// * `4` -- Internal points
    /// * `5` -- Internal points
    /// * `6` -- Internal points
    ///
    /// ## nip for Hex class
    ///
    /// * `6` -- Iron's formula
    /// * `8` -- Legendre points
    /// * `9`:
    ///     - `ws` -- Wilson's "Stable" version
    ///     - otherwise, Wilson's standard formula
    /// * `14` -- Iron's formula
    /// * `27` -- Legendre points
    pub fn select_int_points(&mut self, nip: usize, edge: bool, ws: bool) -> Result<(), StrError> {
        match self.class {
            // Lin
            GeoClass::Lin => match nip {
                1 => self.ip_data = &IP_LIN_LEGENDRE_1,
                2 => self.ip_data = &IP_LIN_LEGENDRE_2,
                3 => self.ip_data = &IP_LIN_LEGENDRE_3,
                4 => self.ip_data = &IP_LIN_LEGENDRE_4,
                5 => self.ip_data = &IP_LIN_LEGENDRE_5,
                _ => return Err("number of integration points is not available for Lin class"),
            },

            // Tri
            GeoClass::Tri => match nip {
                1 => self.ip_data = &IP_TRI_INTERNAL_1,
                3 => {
                    if edge {
                        self.ip_data = &IP_TRI_EDGE_3
                    } else {
                        self.ip_data = &IP_TRI_INTERNAL_3
                    }
                }
                4 => self.ip_data = &IP_TRI_INTERNAL_4,
                12 => self.ip_data = &IP_TRI_INTERNAL_12,
                16 => self.ip_data = &IP_TRI_INTERNAL_16,
                _ => return Err("number of integration points is not available for Tri class"),
            },

            // Qua
            GeoClass::Qua => match nip {
                1 => self.ip_data = &IP_QUA_LEGENDRE_1,
                4 => self.ip_data = &IP_QUA_LEGENDRE_4,
                5 => {
                    if ws {
                        self.ip_data = &IP_QUA_WILSON_STABLE_5
                    } else {
                        self.ip_data = &IP_QUA_WILSON_CORNER_5
                    }
                }
                8 => self.ip_data = &IP_QUA_WILSON_8,
                9 => self.ip_data = &IP_QUA_LEGENDRE_9,
                16 => self.ip_data = &IP_QUA_LEGENDRE_16,
                _ => return Err("number of integration points is not available for Qua class"),
            },

            // Tet
            GeoClass::Tet => match nip {
                1 => self.ip_data = &IP_TET_INTERNAL_1,
                4 => self.ip_data = &IP_TET_INTERNAL_4,
                5 => self.ip_data = &IP_TET_INTERNAL_5,
                6 => self.ip_data = &IP_TET_INTERNAL_6,
                _ => return Err("number of integration points is not available for Tet class"),
            },

            // Hex
            GeoClass::Hex => match nip {
                6 => self.ip_data = &IP_HEX_IRONS_6,
                8 => self.ip_data = &IP_HEX_LEGENDRE_8,
                9 => {
                    if ws {
                        self.ip_data = &IP_HEX_WILSON_STABLE_9
                    } else {
                        self.ip_data = &IP_HEX_WILSON_CORNER_9
                    }
                }
                14 => self.ip_data = &IP_HEX_IRONS_14,
                27 => self.ip_data = &IP_HEX_LEGENDRE_27,
                _ => return Err("number of integration points is not available for Hex class"),
            },
        }
        Ok(())
    }

    /// Performs the Case-A integration
    ///
    /// Case-A, interpolation functions times scalar field:
    ///
    /// ```text
    ///      ⌠    → →     →
    /// aᵐ = │ Nᵐ(x(ξ)) s(x) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// or, for lines in multi-dimensions,
    ///
    /// ```text
    ///      ⌠
    /// aᵐ = │ Nᵐ(ℓ(ξ)) s(ℓ) dℓ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    ///     nip-1    →     →       →
    /// aᵐ ≈  Σ   Nᵐ(ιp) s(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_s` -- s(x(ξ)) or s(ℓ) scalar function, however written as the
    ///             function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `a` -- (npoint) aᵐ scalars; result from the integration
    pub fn integ_case_a(&mut self, a: &mut [f64], fn_s: FnScalar) -> Result<(), StrError> {
        // clear results
        a.fill(0.0);

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate interpolation functions and Jacobian
            self.calc_interp(iota);
            let det_jac = self.calc_jacobian(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                a[m] += self.interp[m] * fn_s(index) * det_jac * weight;
            }
        }
        Ok(())
    }

    /// Performs the Case-B integration
    ///
    /// Case-B, interpolation functions times vector field:
    ///
    /// ```text
    /// →    ⌠    → →   → →
    /// bᵐ = │ Nᵐ(x(ξ)) v(x) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    /// →   nip-1    →   → →       →
    /// bᵐ ≈  Σ   Nᵐ(ιp) v(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_v` -- v(x(ξ)) vector function, however written as the
    ///             function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `b` -- (npoint) bᵐ vectors; result from the integration
    pub fn integ_case_b(&mut self, b: &mut Vec<Vector>, fn_v: FnVector) -> Result<(), StrError> {
        // check
        if b.len() != self.npoint {
            return Err("b.len() must equal npoint");
        }

        // check dims and clear results
        for m in 0..self.npoint {
            if b[m].dim() != self.space_ndim {
                return Err("b[m].dim() must equal space_ndim");
            }
            b[m].fill(0.0);
        }

        // auxiliary vector holding the output of fn_v
        let mut v = Vector::new(self.space_ndim);

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate interpolation functions and Jacobian
            self.calc_interp(iota);
            let det_jac = self.calc_jacobian(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                fn_v(&mut v, index);
                for i in 0..self.space_ndim {
                    b[m][i] += self.interp[m] * v[i] * det_jac * weight;
                }
            }
        }
        Ok(())
    }

    /// Performs the Case-C integration
    ///
    /// Case-C, vector dot gradient:
    ///
    /// ```text
    ///      ⌠ → →    →  → →
    /// cᵐ = │ w(x) · Gᵐ(x(ξ)) dΩ
    ///      ⌡
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    ///     nip-1 → →     →  →       →
    /// cᵐ ≈  Σ   w(ιp) · Gᵐ(ιp) |J|(ιp) wp
    ///      p=0
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_w` -- w(x(ξ)) vector function, however written as the
    ///             function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `c` -- (npoint) cᵐ scalars; result from the integration
    pub fn integ_case_c(&mut self, c: &mut [f64], fn_w: FnVector) -> Result<(), StrError> {
        // clear results
        c.fill(0.0);

        // auxiliary vector holding the output of fn_w
        let mut w = Vector::new(self.space_ndim);

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate Jacobian and Gradient
            let det_jac = self.calc_gradient(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                fn_w(&mut w, index);
                let w_dot_grad = self.vec_dot_grad(m, &w);
                c[m] += w_dot_grad * det_jac * weight;
            }
        }
        Ok(())
    }

    /// Performs the Case-D integration
    ///
    /// Case-D, tensor dot gradient:
    ///
    /// ```text
    /// →    ⌠   →    →  → →   →
    /// dᵐ = │ σ(x) · Gᵐ(x(ξ)) dΩ
    ///      ⌡ ▔
    ///      Ω
    /// ```
    ///
    /// The numerical integration is:
    ///
    /// ```text
    /// →   nip-1   →     →  →       →
    /// dᵐ ≈  Σ   σ(ιp) · Gᵐ(ιp) |J|(ιp) wp
    ///      p=0  ▔
    /// ```
    ///
    /// # Input
    ///
    /// * `fn_sig` -- sig(x(ξ)) tensor function, however written as the
    ///               function of the index of the integration point.
    ///
    /// # Output
    ///
    /// * `d` -- (npoint) dᵐ vectors; result from the integration
    pub fn integ_case_d(&mut self, d: &mut Vec<Vector>, fn_sig: FnTensor) -> Result<(), StrError> {
        // check
        if d.len() != self.npoint {
            return Err("b.len() must equal npoint");
        }

        // check dims and clear results
        for m in 0..self.npoint {
            if d[m].dim() != self.space_ndim {
                return Err("d[m].dim() must equal space_ndim");
            }
            d[m].fill(0.0);
        }

        // auxiliary tensor holding the output of fn_sig
        let mut sig = Tensor2::new(true);

        // auxiliary vector equal to σ · G
        let mut sig_dot_grad = vec![0.0; self.space_ndim];

        // loop over integration points
        for index in 0..self.ip_data.len() {
            // ksi coordinates and weight
            let iota = &self.ip_data[index][0..self.geo_ndim];
            let weight = self.ip_data[index][3];

            // calculate Jacobian and Gradient
            let det_jac = self.calc_gradient(iota)?;

            // loop over points and perform summation
            for m in 0..self.npoint {
                fn_sig(&mut sig, index);
                self.tensor_dot_grad(&mut sig_dot_grad, m, &sig);
                for i in 0..self.space_ndim {
                    d[m][i] += sig_dot_grad[i] * det_jac * weight;
                }
            }
        }
        Ok(())
    }

    /// Computes vector dot the gradient at point m
    fn vec_dot_grad(&self, m: usize, w: &Vector) -> f64 {
        let mut res = 0.0;
        for i in 0..self.space_ndim {
            res += w[i] * self.gradient[m][i];
        }
        res
    }

    /// Computes tensor dot the gradient at point m
    fn tensor_dot_grad(&self, res: &mut [f64], m: usize, sig: &Tensor2) {
        for i in 0..self.space_ndim {
            res[i] = 0.0;
            for j in 0..self.space_ndim {
                res[i] += sig.get(i, j) * self.gradient[m][j];
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::*;

    // to test if variables are cleared before summation
    const NOISE: f64 = 1234.56;

    #[test]
    fn integ_case_a_works() -> Result<(), StrError> {
        let mut shape = Shape::new(2, 2, 4)?;
        shape.set_point(0, 0, 0.0)?;
        shape.set_point(0, 1, 0.0)?;
        shape.set_point(1, 0, 1.0)?;
        shape.set_point(1, 1, 0.0)?;
        shape.set_point(2, 0, 1.0)?;
        shape.set_point(2, 1, 1.0)?;
        shape.set_point(3, 0, 0.0)?;
        shape.set_point(3, 1, 1.0)?;

        let mut a = vec![NOISE; shape.npoint];

        shape.integ_case_a(&mut a, |_| 0.0)?;

        println!("a = {:?}", a);

        Ok(())
    }
}
<|endoftext|>


<commit_before>//#![cfg(feature = "ecs")]

extern crate rusoto;

use rusoto::ecs::ECSClient;
use rusoto::credentials::DefaultAWSCredentialsProviderChain;
use rusoto::regions::Region;

#[test]
fn main() {
    let credentials = DefaultAWSCredentialsProviderChain::new();
    let region = Region::UsEast1;
    let mut ecs = ECSClient::new(
        credentials,
        &region
    );
    match ecs.list_clusters(&Default::default()) {
        Ok(clusters) => {
            for arn in clusters.clusterArns.unwrap_or(vec![]) {
                println!("arn -> {:?}", arn);
            }
        },
        Err(err) => {
            println!("Error listing container instances {:#?}", err);
        }
    }
}
<commit_msg>put ecs test behind a feature flag<commit_after>#![cfg(feature = "ecs")]

extern crate rusoto;

use rusoto::ecs::ECSClient;
use rusoto::credentials::DefaultAWSCredentialsProviderChain;
use rusoto::regions::Region;

#[test]
fn main() {
    let credentials = DefaultAWSCredentialsProviderChain::new();
    let region = Region::UsEast1;
    let mut ecs = ECSClient::new(
        credentials,
        &region
    );
    match ecs.list_clusters(&Default::default()) {
        Ok(clusters) => {
            for arn in clusters.clusterArns.unwrap_or(vec![]) {
                println!("arn -> {:?}", arn);
            }
        },
        Err(err) => {
            println!("Error listing container instances {:#?}", err);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(globs,macro_rules,phase)]

#[phase(plugin,link)]
extern crate nom;

use nom::{IResult,Producer,FileProducer,ProducerState,Mapper,Mapper2,line_ending,not_line_ending};
use nom::IResult::*;

use std::str;
use std::fmt::Show;

fn empty_result(i:&[u8]) -> IResult<&[u8], ()> { Done(i,()) }
tag!(semicolon ";".as_bytes());
o!(comment<&[u8], ()> semicolon not_line_ending line_ending ~ empty_result ~);
tag!(lsb "[".as_bytes());
tag!(rsb "]".as_bytes());
fn not_rsb(input:&[u8]) -> IResult<&[u8], &[u8]> {
  for idx in range(0, input.len()) {
    if input[idx] == ']' as u8 {
      return Done(input.slice_from(idx), input.slice(0, idx))
    }
  }
  Done("".as_bytes(), input)
}
o!(category<&[u8], &[u8]> lsb ~ not_rsb ~ rsb line_ending);

#[test]
fn parse_comment_test() {
  let ini_file = ";comment
[category]
parameter=value
key = value2

[other]
number = 1234
str = a b cc dd ; comment";

  let ini_without_comment = "[category]
parameter=value
key = value2

[other]
number = 1234
str = a b cc dd ; comment";

  let res = Done((), ini_file.as_bytes()).flat_map(comment);
  println!("{}", res);
  match res {
    IResult::Done(i, o) => println!("i: {} | o: {}", str::from_utf8(i), o),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_comment.as_bytes(), ()));
}

#[test]
fn parse_category_test() {
  let ini_file = "[category]
parameter=value
key = value2";

  let ini_without_category = "parameter=value
key = value2";

  let res = Done((), ini_file.as_bytes()).flat_map(category);
  println!("{}", res);
  match res {
    IResult::Done(i, o) => println!("i: {} | o: {}", str::from_utf8(i), str::from_utf8(o)),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_category.as_bytes(), "category".as_bytes()));
}

<commit_msg>parse key/value in INI files<commit_after>#![feature(globs,macro_rules,phase)]

#[phase(plugin,link)]
extern crate nom;

use nom::{IResult,Producer,FileProducer,ProducerState,Mapper,Mapper2,line_ending,not_line_ending};
use nom::IResult::*;

use std::str;
use std::fmt::Show;

fn empty_result(i:&[u8]) -> IResult<&[u8], ()> { Done(i,()) }
tag!(semicolon ";".as_bytes());
o!(comment_body<&[u8],&[u8]> semicolon ~ not_line_ending ~ );
o!(comment<&[u8], ()> comment_body line_ending ~ empty_result ~);
opt!(opt_comment<&[u8],&[u8]> comment_body);

tag!(lsb "[".as_bytes());
tag!(rsb "]".as_bytes());
fn not_rsb(input:&[u8]) -> IResult<&[u8], &[u8]> {
  for idx in range(0, input.len()) {
    if input[idx] == ']' as u8 {
      return Done(input.slice_from(idx), input.slice(0, idx))
    }
  }
  Done("".as_bytes(), input)
}
o!(category<&[u8], &[u8]> lsb ~ not_rsb ~ rsb line_ending);

tag!(equal "=".as_bytes());
fn not_equal(input:&[u8]) -> IResult<&[u8], &[u8]> {
  for idx in range(0, input.len()) {
    if input[idx] == '=' as u8 {
      return Done(input.slice_from(idx), input.slice(0, idx))
    }
  }
  Done("".as_bytes(), input)
}

fn not_line_ending_or_semicolon(input:&[u8]) -> IResult<&[u8], &[u8]> {
  for idx in range(0, input.len()) {
    if input[idx] == '\n' as u8 || input[idx] == ';' as u8 {
      return Done(input.slice_from(idx), input.slice(0, idx))
    }
  }
  Done("".as_bytes(), input)
}

opt!(opt_line_ending<&[u8],&[u8]> line_ending);
//o!(parameter<&[u8],&[u8]> ~ not_equal ~ equal);
o!(value<&[u8],&[u8]> equal ~ not_line_ending_or_semicolon ~ opt_comment  opt_line_ending); // opt_comment line_ending);
chain!(key_value<&[u8],(&[u8],&[u8])>, ||{(key, val)},  key: not_equal, val: value,);

#[test]
fn parse_comment_test() {
  let ini_file = ";comment
[category]
parameter=value
key = value2

[other]
number = 1234
str = a b cc dd ; comment";

  let ini_without_comment = "[category]
parameter=value
key = value2

[other]
number = 1234
str = a b cc dd ; comment";

  let res = Done((), ini_file.as_bytes()).flat_map(comment);
  println!("{}", res);
  match res {
    IResult::Done(i, o) => println!("i: {} | o: {}", str::from_utf8(i), o),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_comment.as_bytes(), ()));
}

#[test]
fn parse_category_test() {
  let ini_file = "[category]
parameter=value
key = value2";

  let ini_without_category = "parameter=value
key = value2";

  let res = Done((), ini_file.as_bytes()).flat_map(category);
  println!("{}", res);
  match res {
    IResult::Done(i, o) => println!("i: {} | o: {}", str::from_utf8(i), str::from_utf8(o)),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_category.as_bytes(), "category".as_bytes()));
}

#[test]
fn parse_key_value_test() {
  let ini_file = "parameter=value
key = value2";

  let ini_without_key_value = "key = value2";

  let res = Done((), ini_file.as_bytes()).flat_map(key_value);
  println!("{}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({},{})", str::from_utf8(i), str::from_utf8(o1), str::from_utf8(o2)),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_key_value.as_bytes(), ("parameter".as_bytes(), "value".as_bytes())));
}

#[test]
fn parse_key_value_with_space_test() {
  let ini_file = "parameter = value
key = value2";

  let ini_without_key_value = "key = value2";

  let res = Done((), ini_file.as_bytes()).flat_map(key_value);
  println!("{}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({},{})", str::from_utf8(i), str::from_utf8(o1), str::from_utf8(o2)),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_key_value.as_bytes(), ("parameter".as_bytes(), "value".as_bytes())));
}

#[test]
fn parse_key_value_with_comment_test() {
  let ini_file = "parameter=value;abc
key = value2";

  let ini_without_key_value = "key = value2";

  let res = Done((), ini_file.as_bytes()).flat_map(key_value);
  println!("{}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({},{})", str::from_utf8(i), str::from_utf8(o1), str::from_utf8(o2)),
    _ => println!("error")
  }

  assert_eq!(res, Done(ini_without_key_value.as_bytes(), ("parameter".as_bytes(), "value".as_bytes())));
}
<|endoftext|>


<commit_before>extern crate natural_constants;

#[test]
fn test_math() {
    use natural_constants::math::*;

    println!("{}", golden_ratio)
}

#[test]
fn test_conversion() {
    use natural_constants::conversion::*;

    let mass_in_g = 50_000.0; // 50 kg
    assert_eq!(to_kilo(mass_in_g), 50.0);
    assert_eq!(from_kilo(50.0), mass_in_g);

    let energy_in_j = 125_000_000.0; // 125 MJoule
    assert_eq!(to_mega(energy_in_j), 125.0);
    assert_eq!(from_mega(125.0), energy_in_j);

    let file_size_in_bytes1 = 73_000_000_000.0; // 74 gigabytes (not gibibytes)
    assert_eq!(to_giga(file_size_in_bytes1), 73.0);
    assert_eq!(from_giga(73.0), file_size_in_bytes);

    let file_size_in_bytes2 = 312_000_000_000_000.0; // 312 terabytes (not tebibytes)
    assert_eq!(to_terra(file_size_in_bytes2), 312.0);
    assert_eq!(from_terra(312.0), file_size_in_bytes2);

    assert_eq!(kilo_to_mega(), );
    assert_eq!(mega_to_kilo(), )
}
<commit_msg>fix test case<commit_after>extern crate natural_constants;

#[test]
fn test_math() {
    use natural_constants::math::*;

    println!("{}", golden_ratio)
}

#[test]
fn test_conversion() {
    use natural_constants::conversion::*;

    let mass_in_g = 50_000.0; // 50 kg
    assert_eq!(to_kilo(mass_in_g), 50.0);
    assert_eq!(from_kilo(50.0), mass_in_g);

    let energy_in_j = 125_000_000.0; // 125 MJoule
    assert_eq!(to_mega(energy_in_j), 125.0);
    assert_eq!(from_mega(125.0), energy_in_j);

    let file_size_in_bytes1 = 73_000_000_000.0; // 74 gigabytes (not gibibytes)
    assert_eq!(to_giga(file_size_in_bytes1), 73.0);
    assert_eq!(from_giga(73.0), file_size_in_bytes1);

    let file_size_in_bytes2 = 312_000_000_000_000.0; // 312 terabytes (not tebibytes)
    assert_eq!(to_terra(file_size_in_bytes2), 312.0);
    assert_eq!(from_terra(312.0), file_size_in_bytes2);

    let force_in_kn = 780.23; // kilo newton
    assert_eq!(kilo_to_mega(force_in_kn), 0.78023);
    assert_eq!(mega_to_kilo(0.78023), force_in_kn);
}
<|endoftext|>


<commit_before>extern crate trustines;

mod memory {
    use trustines::memory::Memory;
    #[test]
    fn write() {
        let mut m = Memory::new();
        m.write(0, &[0,1,2]);
        assert_eq!(0,m.read8(0).unwrap());
        assert_eq!(1,m.read8(1).unwrap());
        assert_eq!(2,m.read8(2).unwrap());
        m.write(1, &[3]);
        assert_eq!(0,m.read8(0).unwrap());
        assert_eq!(3,m.read8(1).unwrap());
        assert_eq!(2,m.read8(2).unwrap());
    }

    #[test]
    fn read8_basic() {
        let mut m = Memory::new();
        m.write(0,&[5,10]);
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn write8_basic() {
        let mut m = Memory::new();
        m.write8(0,5);
        assert_eq!(5,m.mem[0]);

        m.write8(1,10);
        assert_eq!(5,m.mem[0]);
        assert_eq!(10,m.mem[1]);
    }

    #[test]
    fn read16_basic() {
        let mut m = Memory::new();
        m.write(0,&[2,1,0]);
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(1,m.read16(1).unwrap());
    }
    #[test]
    fn write16_basic() {
        let mut m = Memory::new();
        m.write16(0,258);
        assert_eq!(2,m.mem[0]);
        assert_eq!(1,m.mem[1]);
    }
    #[test]
    fn readwrite8() {
        let mut m = Memory::new();
        m.write8(0,5);
        m.write8(1,10);
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn readwrite16() {
        let mut m = Memory::new();
        m.write16(0,258);
        m.write16(2,300);
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(300,m.read16(2).unwrap());
    }
}

mod address_mode {
    use trustines::cpu;
    use trustines::memory::Memory;

    fn build_executor() -> cpu::CpuExecutor {
        let opcode_info = cpu::opcode::load_from_file("resources/opcodes.csv").unwrap();
        return cpu::CpuExecutor::new(opcode_info.0);
    }
    fn build_memory(instr:u8,ops: &[u8]) -> Memory {
        return Memory::new();
    }

    // NOTE: the opcodes specified in build_memory are not being exucuted, so the
    //       opcode class (ADC, ASL, BRK, etc) don't actually matter.  What matters
    //       is the addressing mode (Absolute, AbsoluteX, ZeroPage, etc)
    //

    #[test]
    fn absolute() {
        let exec = build_executor();
        let mut m = build_memory(0x6D,&[]); //0x6D = ADC Absolute
    }
    #[test]
    fn absolute_x() {
        let exec = build_executor();
        let mut m = build_memory(0x7D,&[]); // 0x7D = ADC AbsoluteX
    }
    #[test]
    fn absolute_y() {
        let exec = build_executor();
        let mut m = build_memory(0x79,&[]);// 0x79 = ADC AbsoluteY
    }
    #[test]
    fn accumulator() {
        let exec = build_executor();
        let mut m = build_memory(0x0A,&[]);// 0x0A = ASL Accumulator
    }
    #[test]
    fn immediate() {
        let exec = build_executor();
        let mut m = build_memory(0x69,&[]);// 0x69 = ADC Immediate
    }
    #[test]
    fn implied() {
        let exec = build_executor();
        let mut m = build_memory(0x00,&[]);// 0x00 = BRK Implied
    }
    #[test]
    fn indirect() {
        let exec = build_executor();
        let mut m = build_memory(0x6C,&[]);// 0x6C = JMP Indirect
    }
    #[test]
    fn indexed_indirect() {
        let exec = build_executor();
        let mut m = build_memory(0x61,&[]);// 0x61 = ADC IndexedIndirect
    }
    #[test]
    fn indirect_indexed() {
        let exec = build_executor();
        let mut m = build_memory(0x71,&[]);// 0x71 = ADC IndirectIndexed
    }
    #[test]
    fn relative() {
        let exec = build_executor();
        let mut m = build_memory(0x90,&[]);// 0x90 = BCC IndirectIndexed
    }
    #[test]
    fn zeropage() {
        let exec = build_executor();
        let mut m = build_memory(0x65,&[]);// 0x65 = ADC IndirectIndexed
    }
    #[test]
    fn zeropage_x() {
        let exec = build_executor();
        let mut m = build_memory(0x75,&[]);// 0x75 = ADC IndirectIndexed
    }
    #[test]
    fn zeropage_y() {
        let exec = build_executor();
        let mut m = build_memory(0xB6,&[]);// 0xB6 = LDX IndirectIndexed
    }
}

<commit_msg>build_memory util function now takes index to place operands.<commit_after>extern crate trustines;

mod memory {
    use trustines::memory::Memory;
    #[test]
    fn write() {
        let mut m = Memory::new();
        m.write(0, &[0,1,2]);
        assert_eq!(0,m.read8(0).unwrap());
        assert_eq!(1,m.read8(1).unwrap());
        assert_eq!(2,m.read8(2).unwrap());
        m.write(1, &[3]);
        assert_eq!(0,m.read8(0).unwrap());
        assert_eq!(3,m.read8(1).unwrap());
        assert_eq!(2,m.read8(2).unwrap());
    }

    #[test]
    fn read8_basic() {
        let mut m = Memory::new();
        m.write(0,&[5,10]);
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn write8_basic() {
        let mut m = Memory::new();
        m.write8(0,5);
        assert_eq!(5,m.mem[0]);

        m.write8(1,10);
        assert_eq!(5,m.mem[0]);
        assert_eq!(10,m.mem[1]);
    }

    #[test]
    fn read16_basic() {
        let mut m = Memory::new();
        m.write(0,&[2,1,0]);
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(1,m.read16(1).unwrap());
    }
    #[test]
    fn write16_basic() {
        let mut m = Memory::new();
        m.write16(0,258);
        assert_eq!(2,m.mem[0]);
        assert_eq!(1,m.mem[1]);
    }
    #[test]
    fn readwrite8() {
        let mut m = Memory::new();
        m.write8(0,5);
        m.write8(1,10);
        assert_eq!(5,m.read8(0).unwrap());
        assert_eq!(10,m.read8(1).unwrap());
    }
    #[test]
    fn readwrite16() {
        let mut m = Memory::new();
        m.write16(0,258);
        m.write16(2,300);
        assert_eq!(258,m.read16(0).unwrap());
        assert_eq!(300,m.read16(2).unwrap());
    }
}

mod address_mode {
    use trustines::cpu;
    use trustines::memory::Memory;

    fn build_executor() -> cpu::CpuExecutor {
        let opcode_info = cpu::opcode::load_from_file("resources/opcodes.csv").unwrap();
        return cpu::CpuExecutor::new(opcode_info.0);
    }
    fn build_memory(instr:u8,index:usize, ops: &[u8]) -> Memory {
        let mut m = Memory::new();
        if ops.len() > 0 {
            m.write(index,ops);
        }
        return m;
    }

    // NOTE: the opcodes specified in build_memory are not being exucuted, so the
    //       opcode class (ADC, ASL, BRK, etc) don't actually matter.  What matters
    //       is the addressing mode (Absolute, AbsoluteX, ZeroPage, etc)
    //

    #[test]
    fn absolute() {
        let exec = build_executor();
        let mut m = build_memory(0x6D,0, &[]); //0x6D = ADC Absolute
    }
    #[test]
    fn absolute_x() {
        let exec = build_executor();
        let mut m = build_memory(0x7D,0, &[]); // 0x7D = ADC AbsoluteX
    }
    #[test]
    fn absolute_y() {
        let exec = build_executor();
        let mut m = build_memory(0x79,0, &[]);// 0x79 = ADC AbsoluteY
    }
    #[test]
    fn accumulator() {
        let exec = build_executor();
        let mut m = build_memory(0x0A,0, &[]);// 0x0A = ASL Accumulator
    }
    #[test]
    fn immediate() {
        let exec = build_executor();
        let mut m = build_memory(0x69,0, &[]);// 0x69 = ADC Immediate
    }
    #[test]
    fn implied() {
        let exec = build_executor();
        let mut m = build_memory(0x00,0, &[]);// 0x00 = BRK Implied
    }
    #[test]
    fn indirect() {
        let exec = build_executor();
        let mut m = build_memory(0x6C,0, &[]);// 0x6C = JMP Indirect
    }
    #[test]
    fn indexed_indirect() {
        let exec = build_executor();
        let mut m = build_memory(0x61,0, &[]);// 0x61 = ADC IndexedIndirect
    }
    #[test]
    fn indirect_indexed() {
        let exec = build_executor();
        let mut m = build_memory(0x71,0, &[]);// 0x71 = ADC IndirectIndexed
    }
    #[test]
    fn relative() {
        let exec = build_executor();
        let mut m = build_memory(0x90,0, &[]);// 0x90 = BCC IndirectIndexed
    }
    #[test]
    fn zeropage() {
        let exec = build_executor();
        let mut m = build_memory(0x65,0, &[]);// 0x65 = ADC IndirectIndexed
    }
    #[test]
    fn zeropage_x() {
        let exec = build_executor();
        let mut m = build_memory(0x75,0, &[]);// 0x75 = ADC IndirectIndexed
    }
    #[test]
    fn zeropage_y() {
        let exec = build_executor();
        let mut m = build_memory(0xB6,0, &[]);// 0xB6 = LDX IndirectIndexed
    }
}

<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use std::str::from_utf8;
use std::collections::HashMap;

use rustc_serialize::json;
use curl::http;

use super::{Service, RegisterService, TtlHealthCheck};

/// Agent can be used to query the Agent endpoints
pub struct Agent{
    endpoint: String,
}

/// AgentMember represents a cluster member known to the agent
#[derive(RustcDecodable, RustcEncodable)]
pub struct AgentMember {
	Name: String,
	Addr: String,
	Port: u16,
	Tags: HashMap<String, String>,
	Status: usize,
	ProtocolMin: u8,
	ProtocolMax: u8,
	ProtocolCur: u8,
	DelegateMin: u8,
	DelegateMax: u8,
	DelegateCur: u8
}

impl Agent {

    pub fn new(address: &str) -> Agent {
        Agent{endpoint: format!("{}/v1/agent", address)}
    }

    pub fn services(&self) -> HashMap<String, Service> {
        let url = format!("{}/services", self.endpoint);
        let resp = http::handle().get(url).exec().unwrap();
        let result = from_utf8(resp.get_body()).unwrap();
        json::decode(result).unwrap()
    }

    pub fn members(&self) -> Vec<AgentMember> {
        let url = format!("{}/members", self.endpoint);
        let resp = http::handle().get(url).exec().unwrap();
        let result = from_utf8(resp.get_body()).unwrap();
        json::decode(result).unwrap()
    }

    pub fn register(&self, service: RegisterService) {
        let url = format!("{}/service/register", self.endpoint);
        let json_str = json::encode(&service).unwrap();
        let resp = http::handle()
            .put(url, &json_str)
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Consul: Error registering a service!");
        }
    }

    pub fn register_ttl_check(&self, health_check: TtlHealthCheck) {
        let url = format!("{}/check/register", self.endpoint);
        let json_str = json::encode(&health_check).unwrap();
        let resp = http::handle()
            .put(url, &json_str)
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Consul: Error registering a health check!");
        }
    }

    pub fn check_pass(&self, service_id: String) {
        let url = format!("{}/check/pass/{}", self.endpoint, service_id);
        let resp = http::handle().get(url).exec().unwrap();
    }

}
<commit_msg>Get name of self<commit_after>#![allow(non_snake_case)]

use std::str::from_utf8;
use std::collections::HashMap;

use rustc_serialize::json;
use curl::http;

use super::{Service, RegisterService, TtlHealthCheck};

/// Agent can be used to query the Agent endpoints
pub struct Agent{
    endpoint: String,
}

/// AgentMember represents a cluster member known to the agent
#[derive(RustcDecodable, RustcEncodable)]
pub struct AgentMember {
	Name: String,
	Addr: String,
	Port: u16,
	Tags: HashMap<String, String>,
	Status: usize,
	ProtocolMin: u8,
	ProtocolMax: u8,
	ProtocolCur: u8,
	DelegateMin: u8,
	DelegateMax: u8,
	DelegateCur: u8
}

impl Agent {

    pub fn new(address: &str) -> Agent {
        Agent{endpoint: format!("{}/v1/agent", address)}
    }

    pub fn services(&self) -> HashMap<String, Service> {
        let url = format!("{}/services", self.endpoint);
        let resp = http::handle().get(url).exec().unwrap();
        let result = from_utf8(resp.get_body()).unwrap();
        json::decode(result).unwrap()
    }

    pub fn members(&self) -> Vec<AgentMember> {
        let url = format!("{}/members", self.endpoint);
        let resp = http::handle().get(url).exec().unwrap();
        let result = from_utf8(resp.get_body()).unwrap();
        json::decode(result).unwrap()
    }

    pub fn register(&self, service: RegisterService) {
        let url = format!("{}/service/register", self.endpoint);
        let json_str = json::encode(&service).unwrap();
        let resp = http::handle()
            .put(url, &json_str)
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Consul: Error registering a service!");
        }
    }

    pub fn register_ttl_check(&self, health_check: TtlHealthCheck) {
        let url = format!("{}/check/register", self.endpoint);
        let json_str = json::encode(&health_check).unwrap();
        let resp = http::handle()
            .put(url, &json_str)
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Consul: Error registering a health check!");
        }
    }

    pub fn check_pass(&self, service_id: String) {
        let url = format!("{}/check/pass/{}", self.endpoint, service_id);
        let resp = http::handle().get(url).exec().unwrap();
    }

    pub fn get_self_name(&self) -> String {
        let url = format!("{}/self", self.endpoint);
        let resp = http::handle().get(url).exec().unwrap();
        let result = from_utf8(resp.get_body()).unwrap();
        let json_data = match json::Json::from_str(result) {
            Ok(value) => value,
            Err(err) => panic!("consul: Could not convert to json: {:?}", result)
        };
        super::get_string(&json_data, &["Config", "NodeName"])
    }

}
<|endoftext|>


<commit_before>// * This file is part of the uutils coreutils package.
// *
// * (c) 2020 nicoo <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

use smallvec::SmallVec;
use std::cell::RefCell;
use std::fmt;

use crate::numeric::{Arithmetic, Montgomery};
use crate::{miller_rabin, rho, table};

type Exponent = u8;

#[derive(Clone, Debug)]
struct Decomposition(SmallVec<[(u64, Exponent); NUM_FACTORS_INLINE]>);

// spell-checker:ignore (names) Erdős–Kac * Erdős Kac
// The number of factors to inline directly into a `Decomposition` object.
// As a consequence of the Erdős–Kac theorem, the average number of prime factors
// of integers < 10²⁵ ≃ 2⁸³ is 4, so we can use a slightly higher value.
const NUM_FACTORS_INLINE: usize = 5;

impl Decomposition {
    fn one() -> Decomposition {
        Decomposition(SmallVec::new())
    }

    fn add(&mut self, factor: u64, exp: Exponent) {
        debug_assert!(exp > 0);

        if let Some((_, e)) = self.0.iter_mut().find(|(f, _)| *f == factor) {
            *e += exp;
        } else {
            self.0.push((factor, exp))
        }
    }

    #[cfg(test)]
    fn product(&self) -> u64 {
        self.0
            .iter()
            .fold(1, |acc, (p, exp)| acc * p.pow(*exp as u32))
    }

    fn get(&self, p: u64) -> Option<&(u64, u8)> {
        self.0.iter().find(|(q, _)| *q == p)
    }
}

impl PartialEq for Decomposition {
    fn eq(&self, other: &Decomposition) -> bool {
        for p in &self.0 {
            if other.get(p.0) != Some(p) {
                return false;
            }
        }

        for p in &other.0 {
            if self.get(p.0) != Some(p) {
                return false;
            }
        }

        true
    }
}
impl Eq for Decomposition {}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors(RefCell<Decomposition>);

impl Factors {
    pub fn one() -> Factors {
        Factors(RefCell::new(Decomposition::one()))
    }

    pub fn add(&mut self, prime: u64, exp: Exponent) {
        debug_assert!(miller_rabin::is_prime(prime));
        self.0.borrow_mut().add(prime, exp)
    }

    pub fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }

    #[cfg(test)]
    fn product(&self) -> u64 {
        self.0.borrow().product()
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let v = &mut (self.0).borrow_mut().0;
        v.sort_unstable();

        for (p, exp) in v.iter() {
            for _ in 0..*exp {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn _factor<A: Arithmetic + miller_rabin::Basis>(num: u64, f: Factors) -> Factors {
    use miller_rabin::Result::*;

    // Shadow the name, so the recursion automatically goes from “Big” arithmetic to small.
    let _factor = |n, f| {
        if n < (1 << 32) {
            _factor::<Montgomery<u32>>(n, f)
        } else {
            _factor::<A>(n, f)
        }
    };

    if num == 1 {
        return f;
    }

    let n = A::new(num);
    let divisor = match miller_rabin::test::<A>(n) {
        Prime => {
            #[cfg(feature = "coz")]
            coz::progress!("factor found");
            let mut r = f;
            r.push(num);
            return r;
        }

        Composite(d) => d,
        Pseudoprime => rho::find_divisor::<A>(n),
    };

    let f = _factor(divisor, f);
    _factor(num / divisor, f)
}

pub fn factor(mut n: u64) -> Factors {
    #[cfg(feature = "coz")]
    coz::begin!("factorization");
    let mut factors = Factors::one();

    if n < 2 {
        return factors;
    }

    let n_zeros = n.trailing_zeros();
    if n_zeros > 0 {
        factors.add(2, n_zeros as Exponent);
        n >>= n_zeros;
    }

    if n == 1 {
        #[cfg(feature = "coz")]
        coz::end!("factorization");
        return factors;
    }

    table::factor(&mut n, &mut factors);

    #[allow(clippy::let_and_return)]
    let r = if n < (1 << 32) {
        _factor::<Montgomery<u32>>(n, factors)
    } else {
        _factor::<Montgomery<u64>>(n, factors)
    };

    #[cfg(feature = "coz")]
    coz::end!("factorization");

    r
}

#[cfg(test)]
mod tests {
    use super::{factor, Decomposition, Exponent, Factors};
    use quickcheck::quickcheck;
    use smallvec::smallvec;
    use std::cell::RefCell;

    #[test]
    fn factor_2044854919485649() {
        let f = Factors(RefCell::new(Decomposition(smallvec![
            (503, 1),
            (2423, 1),
            (40961, 2)
        ])));
        assert_eq!(factor(f.product()), f);
    }

    #[test]
    fn factor_recombines_small() {
        assert!((1..10_000)
            .map(|i| 2 * i + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_overflowing() {
        assert!((0..250)
            .map(|i| 2 * i + 2u64.pow(32) + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_strong_pseudoprime() {
        // This is a strong pseudoprime (wrt. miller_rabin::BASIS)
        //  and triggered a bug in rho::factor's code path handling
        //  miller_rabbin::Result::Composite
        let pseudoprime = 17179869183;
        for _ in 0..20 {
            // Repeat the test 20 times, as it only fails some fraction
            // of the time.
            assert!(factor(pseudoprime).product() == pseudoprime);
        }
    }

    quickcheck! {
        fn factor_recombines(i: u64) -> bool {
            i == 0 || factor(i).product() == i
        }

        fn recombines_factors(f: Factors) -> () {
            assert_eq!(factor(f.product()), f);
        }

        fn exponentiate_factors(f: Factors, e: Exponent) -> () {
            if e == 0 { return; }
            if let Some(fe) = f.product().checked_pow(e.into()) {
                assert_eq!(factor(fe), f ^ e);
            }
        }
    }
}

#[cfg(test)]
use rand::{
    distributions::{Distribution, Standard},
    Rng,
};
#[cfg(test)]
impl Distribution<Factors> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Factors {
        let mut f = Factors::one();
        let mut g = 1u64;
        let mut n = u64::MAX;

        // spell-checker:ignore (names) Adam Kalai * Kalai's
        // Adam Kalai's algorithm for generating uniformly-distributed
        // integers and their factorization.
        //
        // See Generating Random Factored Numbers, Easily, J. Cryptology (2003)
        'attempt: loop {
            while n > 1 {
                n = rng.gen_range(1..n);
                if miller_rabin::is_prime(n) {
                    if let Some(h) = g.checked_mul(n) {
                        f.push(n);
                        g = h;
                    } else {
                        // We are overflowing u64, retry
                        continue 'attempt;
                    }
                }
            }

            return f;
        }
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Factors {
    fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
        g.gen()
    }
}

#[cfg(test)]
impl std::ops::BitXor<Exponent> for Factors {
    type Output = Self;

    fn bitxor(self, rhs: Exponent) -> Factors {
        debug_assert_ne!(rhs, 0);
        let mut r = Factors::one();
        for (p, e) in self.0.borrow().0.iter() {
            r.add(*p, rhs * e);
        }

        debug_assert_eq!(r.product(), self.product().pow(rhs.into()));
        r
    }
}
<commit_msg>factor: tests: update Arbitrary impl for Factors<commit_after>// * This file is part of the uutils coreutils package.
// *
// * (c) 2020 nicoo <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

use smallvec::SmallVec;
use std::cell::RefCell;
use std::fmt;

use crate::numeric::{Arithmetic, Montgomery};
use crate::{miller_rabin, rho, table};

type Exponent = u8;

#[derive(Clone, Debug)]
struct Decomposition(SmallVec<[(u64, Exponent); NUM_FACTORS_INLINE]>);

// spell-checker:ignore (names) Erdős–Kac * Erdős Kac
// The number of factors to inline directly into a `Decomposition` object.
// As a consequence of the Erdős–Kac theorem, the average number of prime factors
// of integers < 10²⁵ ≃ 2⁸³ is 4, so we can use a slightly higher value.
const NUM_FACTORS_INLINE: usize = 5;

impl Decomposition {
    fn one() -> Decomposition {
        Decomposition(SmallVec::new())
    }

    fn add(&mut self, factor: u64, exp: Exponent) {
        debug_assert!(exp > 0);

        if let Some((_, e)) = self.0.iter_mut().find(|(f, _)| *f == factor) {
            *e += exp;
        } else {
            self.0.push((factor, exp))
        }
    }

    #[cfg(test)]
    fn product(&self) -> u64 {
        self.0
            .iter()
            .fold(1, |acc, (p, exp)| acc * p.pow(*exp as u32))
    }

    fn get(&self, p: u64) -> Option<&(u64, u8)> {
        self.0.iter().find(|(q, _)| *q == p)
    }
}

impl PartialEq for Decomposition {
    fn eq(&self, other: &Decomposition) -> bool {
        for p in &self.0 {
            if other.get(p.0) != Some(p) {
                return false;
            }
        }

        for p in &other.0 {
            if self.get(p.0) != Some(p) {
                return false;
            }
        }

        true
    }
}
impl Eq for Decomposition {}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors(RefCell<Decomposition>);

impl Factors {
    pub fn one() -> Factors {
        Factors(RefCell::new(Decomposition::one()))
    }

    pub fn add(&mut self, prime: u64, exp: Exponent) {
        debug_assert!(miller_rabin::is_prime(prime));
        self.0.borrow_mut().add(prime, exp)
    }

    pub fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }

    #[cfg(test)]
    fn product(&self) -> u64 {
        self.0.borrow().product()
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let v = &mut (self.0).borrow_mut().0;
        v.sort_unstable();

        for (p, exp) in v.iter() {
            for _ in 0..*exp {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn _factor<A: Arithmetic + miller_rabin::Basis>(num: u64, f: Factors) -> Factors {
    use miller_rabin::Result::*;

    // Shadow the name, so the recursion automatically goes from “Big” arithmetic to small.
    let _factor = |n, f| {
        if n < (1 << 32) {
            _factor::<Montgomery<u32>>(n, f)
        } else {
            _factor::<A>(n, f)
        }
    };

    if num == 1 {
        return f;
    }

    let n = A::new(num);
    let divisor = match miller_rabin::test::<A>(n) {
        Prime => {
            #[cfg(feature = "coz")]
            coz::progress!("factor found");
            let mut r = f;
            r.push(num);
            return r;
        }

        Composite(d) => d,
        Pseudoprime => rho::find_divisor::<A>(n),
    };

    let f = _factor(divisor, f);
    _factor(num / divisor, f)
}

pub fn factor(mut n: u64) -> Factors {
    #[cfg(feature = "coz")]
    coz::begin!("factorization");
    let mut factors = Factors::one();

    if n < 2 {
        return factors;
    }

    let n_zeros = n.trailing_zeros();
    if n_zeros > 0 {
        factors.add(2, n_zeros as Exponent);
        n >>= n_zeros;
    }

    if n == 1 {
        #[cfg(feature = "coz")]
        coz::end!("factorization");
        return factors;
    }

    table::factor(&mut n, &mut factors);

    #[allow(clippy::let_and_return)]
    let r = if n < (1 << 32) {
        _factor::<Montgomery<u32>>(n, factors)
    } else {
        _factor::<Montgomery<u64>>(n, factors)
    };

    #[cfg(feature = "coz")]
    coz::end!("factorization");

    r
}

#[cfg(test)]
mod tests {
    use super::{factor, Decomposition, Exponent, Factors};
    use quickcheck::quickcheck;
    use smallvec::smallvec;
    use std::cell::RefCell;

    #[test]
    fn factor_2044854919485649() {
        let f = Factors(RefCell::new(Decomposition(smallvec![
            (503, 1),
            (2423, 1),
            (40961, 2)
        ])));
        assert_eq!(factor(f.product()), f);
    }

    #[test]
    fn factor_recombines_small() {
        assert!((1..10_000)
            .map(|i| 2 * i + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_overflowing() {
        assert!((0..250)
            .map(|i| 2 * i + 2u64.pow(32) + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_strong_pseudoprime() {
        // This is a strong pseudoprime (wrt. miller_rabin::BASIS)
        //  and triggered a bug in rho::factor's code path handling
        //  miller_rabbin::Result::Composite
        let pseudoprime = 17179869183;
        for _ in 0..20 {
            // Repeat the test 20 times, as it only fails some fraction
            // of the time.
            assert!(factor(pseudoprime).product() == pseudoprime);
        }
    }

    quickcheck! {
        fn factor_recombines(i: u64) -> bool {
            i == 0 || factor(i).product() == i
        }

        fn recombines_factors(f: Factors) -> () {
            assert_eq!(factor(f.product()), f);
        }

        fn exponentiate_factors(f: Factors, e: Exponent) -> () {
            if e == 0 { return; }
            if let Some(fe) = f.product().checked_pow(e.into()) {
                assert_eq!(factor(fe), f ^ e);
            }
        }
    }
}

#[cfg(test)]
use rand::{
    distributions::{Distribution, Standard},
    Rng,
};
#[cfg(test)]
impl Distribution<Factors> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Factors {
        let mut f = Factors::one();
        let mut g = 1u64;
        let mut n = u64::MAX;

        // spell-checker:ignore (names) Adam Kalai * Kalai's
        // Adam Kalai's algorithm for generating uniformly-distributed
        // integers and their factorization.
        //
        // See Generating Random Factored Numbers, Easily, J. Cryptology (2003)
        'attempt: loop {
            while n > 1 {
                n = rng.gen_range(1..n);
                if miller_rabin::is_prime(n) {
                    if let Some(h) = g.checked_mul(n) {
                        f.push(n);
                        g = h;
                    } else {
                        // We are overflowing u64, retry
                        continue 'attempt;
                    }
                }
            }

            return f;
        }
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Factors {
    fn arbitrary(g: &mut quickcheck::Gen) -> Self {
        factor(u64::arbitrary(g))
    }
}

#[cfg(test)]
impl std::ops::BitXor<Exponent> for Factors {
    type Output = Self;

    fn bitxor(self, rhs: Exponent) -> Factors {
        debug_assert_ne!(rhs, 0);
        let mut r = Factors::one();
        for (p, e) in self.0.borrow().0.iter() {
            r.add(*p, rhs * e);
        }

        debug_assert_eq!(r.product(), self.product().pow(rhs.into()));
        r
    }
}
<|endoftext|>


<commit_before>// Copyright (C) ~ Roy Ivy III <rivy.dev@gmail.com>; MIT license

extern crate proc_macro;

//## rust proc-macro background info
//* ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
//* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>

//## proc_dbg macro
//* used to help debug the compile-time proc_macro code

#[cfg(feature = "debug")]
macro_rules! proc_dbg {
    ($x:expr) => {
        dbg!($x)
    };
}
#[cfg(not(feature = "debug"))]
macro_rules! proc_dbg {
    ($x:expr) => {};
}

//## main!()

// main!( EXPR )
// generates a `main()` function for utilities within the uutils group
// EXPR == syn::Expr::Lit::String | syn::Expr::Path::Ident ~ EXPR contains the lexical path to the utility `uumain()` function
//* NOTE: EXPR is ultimately expected to be a multi-segment lexical path (eg, `crate::func`); so, if a single segment path is provided, a trailing "::uumain" is automatically added
//* for more generic use (and future use of "eager" macros), EXPR may be in either STRING or IDENT form

struct Tokens {
    expr: syn::Expr,
}

impl syn::parse::Parse for Tokens {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Tokens {
            expr: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
    proc_dbg!(&expr);

    const ARG_PANIC_TEXT: &str =
        "expected ident lexical path (or a literal string version) to 'uumain()' as argument";

    // match EXPR as a string literal or an ident path, o/w panic!()
    let mut expr = match expr {
        syn::Expr::Lit(expr_lit) => match expr_lit.lit {
            syn::Lit::Str(ref lit_str) => lit_str.parse::<syn::ExprPath>().unwrap(),
            _ => panic!("{}", ARG_PANIC_TEXT),
        },
        syn::Expr::Path(expr_path) => expr_path,
        _ => panic!("{}", ARG_PANIC_TEXT),
    };
    proc_dbg!(&expr);

    // for a single segment ExprPath argument, add trailing '::uumain' segment
    if expr.path.segments.len() < 2 {
        expr = syn::parse_quote!( #expr::uumain );
    };
    proc_dbg!(&expr);

    let f = quote::quote! { #expr(uucore::args_os()) };
    proc_dbg!(&f);

    // generate a uutils utility `main()` function, tailored for the calling utility
    let result = quote::quote! {
        fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = #f; // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
    proc_macro::TokenStream::from(result)
}
<commit_msg>uucore_procs: add temporary proc macro gen_uumain for standardized error handling<commit_after>// Copyright (C) ~ Roy Ivy III <rivy.dev@gmail.com>; MIT license

extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{self, parse_macro_input, ItemFn};

//## rust proc-macro background info
//* ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
//* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>

//## proc_dbg macro
//* used to help debug the compile-time proc_macro code

#[cfg(feature = "debug")]
macro_rules! proc_dbg {
    ($x:expr) => {
        dbg!($x)
    };
}
#[cfg(not(feature = "debug"))]
macro_rules! proc_dbg {
    ($x:expr) => {};
}

//## main!()

// main!( EXPR )
// generates a `main()` function for utilities within the uutils group
// EXPR == syn::Expr::Lit::String | syn::Expr::Path::Ident ~ EXPR contains the lexical path to the utility `uumain()` function
//* NOTE: EXPR is ultimately expected to be a multi-segment lexical path (eg, `crate::func`); so, if a single segment path is provided, a trailing "::uumain" is automatically added
//* for more generic use (and future use of "eager" macros), EXPR may be in either STRING or IDENT form

struct Tokens {
    expr: syn::Expr,
}

impl syn::parse::Parse for Tokens {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Tokens {
            expr: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn main(stream: TokenStream) -> TokenStream {
    let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
    proc_dbg!(&expr);

    const ARG_PANIC_TEXT: &str =
        "expected ident lexical path (or a literal string version) to 'uumain()' as argument";

    // match EXPR as a string literal or an ident path, o/w panic!()
    let mut expr = match expr {
        syn::Expr::Lit(expr_lit) => match expr_lit.lit {
            syn::Lit::Str(ref lit_str) => lit_str.parse::<syn::ExprPath>().unwrap(),
            _ => panic!("{}", ARG_PANIC_TEXT),
        },
        syn::Expr::Path(expr_path) => expr_path,
        _ => panic!("{}", ARG_PANIC_TEXT),
    };
    proc_dbg!(&expr);

    // for a single segment ExprPath argument, add trailing '::uumain' segment
    if expr.path.segments.len() < 2 {
        expr = syn::parse_quote!( #expr::uumain );
    };
    proc_dbg!(&expr);

    let f = quote::quote! { #expr(uucore::args_os()) };
    proc_dbg!(&f);

    // generate a uutils utility `main()` function, tailored for the calling utility
    let result = quote::quote! {
        fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = #f; // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
    TokenStream::from(result)
}

#[proc_macro_attribute]
pub fn gen_uumain(_args: TokenStream, stream: TokenStream) -> TokenStream {
    let mut ast = parse_macro_input!(stream as ItemFn);

    // Change the name of the function to "uumain_result" to prevent name-conflicts
    ast.sig.ident = Ident::new("uumain_result", Span::call_site());

    let new = quote!(
        pub fn uumain(args: impl uucore::Args) -> i32 {
            #ast
            let result = uumain_result(args);
            match result {
                Ok(()) => uucore::error::get_exit_code(),
                Err(e) => {
                    let s = format!("{}", e);
                    if s != "" {
                        show_error!("{}", s);
                    }
                    e.code()
                }
            }
        }
    );

    TokenStream::from(new)
}
<|endoftext|>


<commit_before>use std::hash;
use std::hash::Hash;
use std::int::MAX;
use std::num::Int;
use std::result::Result;

// The idea of a "balanced fixed-point" computation is to do two
// things simultaneously:
//
// (1) compute the fixed-point value of a function by running an
// (abstracted) iterative algorithm.
//
// (2) structure the evaluation of this algorithm as a balanced binary
// tree of Adapton thunks, where each thunk in the tree stores an
// intermediate state of the algorithm.
//
// The second goal is motivated by Adapton's need for a shallow
// call-graph.  If one were to write a loop naively, the call-graph
// may not be shallow.  By using this fixed-point combinator in place
// of a while loop (or some tail-recursive loop), we can guarantee
// (probabilistically) that the call-graph is shallow.

trait FpFn {
    // Fixed-point Function.
    //
    /// The Self type need not be stateful at all.
    ///
    /// Instead, a FpFn exposes its state (abstractly) to the loop
    /// that contains it.  There are two parts:
    //
    ///  - The loop iteration's current state (type `St`)
    //
    ///  - Any "meta-state" needed to explore the space of states
    ///  (type `Sys`).  This meta state may consist of nothing, or it
    ///  may consist of queues, stacks, and/or sets of
    ///  previously-visited states.
    //
    /// Our fixed-point loop below needs a way of hashing the "current
    /// state" (type `St`).  It builds a binary tree of stepped states
    /// (type `St_stepped`).

    type St : Hash ;
    type St_stepped ;
    type Sys ;
    fn step (self:& Self, st:Self::St, sys:Self::Sys) -> (Self::St_stepped, Self::Sys) ;
    fn next (self:& Self, sys:Self::Sys) -> Result<(Self::St, Self::Sys), Self::Sys> ;
}

trait BinTree<T> {
    // Our fixed-point loop builds a balanced binary tree of stepped states.
    type Tree;
    fn leaf(self:& Self) -> Self::Tree;
    fn bin(self:& Self, left:Self::Tree, T, right:Self::Tree) -> Self::Tree;
}

trait FpLp<F:FpFn, BT:BinTree<F::St_stepped>> {
    // Our fixed-point loop.  It uses a hashing and probabilistic
    // reasoning to build a balanced binary tree of stepped states.
    //
    // Key assumption: Each state (of type `F::St`) has a distinct hash.
    fn work_tree (self:&Self, f:&F, bt:&BT,
                  left:BT::Tree, left_lev:int,
                  sys:F::Sys, parent_lev:int) -> (F::Sys, BT::Tree)
    {
        let nxt = f.next(sys) ;
        match nxt {
            Err(sys) => (sys, left),
            Ok((st,sys)) => {
                let st_lev = Int::trailing_zeros(hash::hash(&st)) as int ;
                if left_lev <= st_lev &&
                    st_lev  <= parent_lev
                {
                    let (st, sys) = f.step(st, sys) ;
                    let (sys,right) = self.work_tree (f, bt, bt.leaf(), -1, sys, st_lev );
                    let tree = bt.bin(left,st,right) ;
                    let (sys,tree) = self.work_tree (f, bt, tree, st_lev, sys, parent_lev );
                    (sys,tree)
                }
                else {
                    (sys,left)
                }
            }
        }
    }
    fn compute (self:&Self, f:&F, bt:&BT, sys:F::Sys) -> (F::Sys,BT::Tree) {
        self.work_tree (f, bt, bt.leaf(), -1, sys, MAX )
    }
}
<commit_msg>extensible balfp recursion via traits<commit_after>use std::hash;
use std::hash::Hash;
use std::int::MAX;
use std::num::Int;
use std::result::Result;

// The idea of a "balanced fixed-point" computation is to do two
// things simultaneously:
//
// (1) compute the fixed-point value of a function by running an
// (abstracted) iterative algorithm.
//
// (2) structure the evaluation of this algorithm as a balanced binary
// tree of Adapton thunks, where each thunk in the tree stores an
// intermediate state of the algorithm.
//
// The second goal is motivated by Adapton's need for a shallow
// call-graph.  If one were to write a loop naively, the call-graph
// may not be shallow.  By using this fixed-point combinator in place
// of a while loop (or some tail-recursive loop), we can guarantee
// (probabilistically) that the call-graph is shallow.

trait FpFn {
    // Fixed-point Function.
    //
    /// The Self type need not be stateful at all.
    ///
    /// Instead, a FpFn exposes its state (abstractly) to the loop
    /// that contains it.  There are two parts:
    //
    ///  - The loop iteration's current state (type `St`)
    //
    ///  - Any "meta-state" needed to explore the space of states
    ///  (type `Sys`).  This meta state may consist of nothing, or it
    ///  may consist of queues, stacks, and/or sets of
    ///  previously-visited states.
    //
    /// Our fixed-point loop below needs a way of hashing the "current
    /// state" (type `St`).  It builds a binary tree of stepped states
    /// (type `St_stepped`).

    type St : Hash ;
    type St_stepped ;
    type Sys ;
    fn step (self:& Self, st:Self::St, sys:Self::Sys) -> (Self::St_stepped, Self::Sys) ;
    fn next (self:& Self, sys:Self::Sys) -> Result<(Self::St, Self::Sys), Self::Sys> ;
}

trait BinTree<T> {
    // Our fixed-point loop builds a balanced binary tree of stepped states.
    type Tree;
    fn leaf(self:& Self) -> Self::Tree;
    fn bin(self:& Self, left:Self::Tree, T, right:Self::Tree) -> Self::Tree;
}

trait FpLp<F:FpFn, BT:BinTree<F::St_stepped>> {

    // We leave this abstract here.
    // It can either be a simple wrapper around work_tree, or
    // something that uses memoization.
    fn work_recur (self:&Self, f:&F, bt:&BT,
                  left:BT::Tree, left_lev:int,
                  sys:F::Sys, parent_lev:int) -> (F::Sys, BT::Tree) ;

    // Our fixed-point loop.  It uses a hashing and probabilistic
    // reasoning to build a balanced binary tree of stepped states.
    //
    // Key assumption: Each state (of type `F::St`) has a distinct hash.
    fn work_tree (self:&Self, f:&F, bt:&BT,
                  left:BT::Tree, left_lev:int,
                  sys:F::Sys, parent_lev:int) -> (F::Sys, BT::Tree)
    {
        let nxt = f.next(sys) ;
        match nxt {
            Err(sys) => (sys, left),
            Ok((st,sys)) => {
                let st_lev = Int::trailing_zeros(hash::hash(&st)) as int ;
                if left_lev <= st_lev &&
                    st_lev  <= parent_lev
                {
                    let (st, sys) = f.step(st, sys) ;
                    let (sys,right) = self.work_recur (f, bt, bt.leaf(), -1, sys, st_lev );
                    let tree = bt.bin(left,st,right) ;
                    let (sys,tree) = self.work_recur (f, bt, tree, st_lev, sys, parent_lev );
                    (sys,tree)
                }
                else {
                    (sys,left)
                }
            }
        }
    }
    fn compute (self:&Self, f:&F, bt:&BT, sys:F::Sys) -> (F::Sys,BT::Tree) {
        self.work_recur (f, bt, bt.leaf(), -1, sys, MAX )
    }
}

impl<F:FpFn, BT:BinTree<F::St_stepped>> FpLp<F,BT> for () {
    fn work_recur (self:&Self, f:&F, bt:&BT,
                   left:BT::Tree, left_lev:int,
                   sys:F::Sys, parent_lev:int) -> (F::Sys, BT::Tree) {
        self.work_tree (f, bt, left, left_lev, sys, parent_lev )
    }
}
<|endoftext|>


<commit_before>extern crate wayland;

extern crate libc;

use std::ptr;

const WIDTH: i32 = 300;
const HEIGHT: i32 = 200;
const STRIDE: i32 = WIDTH * 4;
const PIXELS: i32 = WIDTH * HEIGHT;
const SIZE: i32 = PIXELS * 4;

#[link(name = "rt")]
extern {} // So we can link to shm_open and shm_unlink

struct ShmFd {
    fd: i32,
    ptr: *mut libc::c_void
}

impl ShmFd {
    pub fn new() -> ShmFd {
        unsafe {
            let fd = libc::funcs::posix88::mman::shm_open(
                "/eyl-hello-world".to_c_str().as_ptr(),
                libc::O_CREAT | libc::O_RDWR,
                libc::S_IRUSR | libc::S_IWUSR
            );
            assert!(fd >= 0);
            assert!(libc::ftruncate(fd, SIZE as i64) != -1);
            let ptr = libc::mmap(ptr::null_mut(), SIZE as u64,
                                 libc::PROT_WRITE | libc::PROT_READ, 1, fd, 0);
            assert!(ptr != libc::MAP_FAILED);
            for i in range(0, PIXELS) {
                let p: *mut u32 = (ptr as *mut u32).offset(i as int);
                if i % 2 == 0 {
                    std::ptr::write(&mut *p, 0x00FF00FF);
                }
                else {
                    std::ptr::write(&mut *p, 0x00000000);
                }
            }
            ShmFd { fd: fd, ptr: ptr }
        }
    }
    pub fn fd(&self) -> i32 {
        self.fd
    }
}

impl Drop for ShmFd {
    fn drop(&mut self) {
        unsafe {
            libc::munmap(self.ptr, SIZE as u64);
            libc::funcs::posix88::mman::shm_unlink(
                "/eyl-hello-world".to_c_str().as_ptr()
            );
        }
    }
}

fn main() {
    let mut display = wayland::Display::new();
    let mut registry = wayland::Registry::new(&mut display);
    let shm_fd = ShmFd::new();
    let mut pool = registry.shm().create_pool(shm_fd.fd(), SIZE);
    let mut surface = registry.compositor().create_surface();
    let mut buffer = pool.create_buffer(
        0, WIDTH, HEIGHT, STRIDE, wayland::raw::WL_SHM_FORMAT_ARGB8888
    );
    surface.attach(&mut buffer, 0, 0);
    let mut shell_surface = registry.shell().get_shell_surface(&mut surface);
    shell_surface.set_toplevel();
    surface.commit();
    loop {
        display.dispatch();
    }
}
<commit_msg>Make the box transparent and black<commit_after>extern crate wayland;

extern crate libc;

use std::ptr;

const WIDTH: i32 = 300;
const HEIGHT: i32 = 200;
const STRIDE: i32 = WIDTH * 4;
const PIXELS: i32 = WIDTH * HEIGHT;
const SIZE: i32 = PIXELS * 4;

#[link(name = "rt")]
extern {} // So we can link to shm_open and shm_unlink

struct ShmFd {
    fd: i32,
    ptr: *mut libc::c_void
}

impl ShmFd {
    pub fn new() -> ShmFd {
        unsafe {
            let fd = libc::funcs::posix88::mman::shm_open(
                "/eyl-hello-world".to_c_str().as_ptr(),
                libc::O_CREAT | libc::O_RDWR,
                libc::S_IRUSR | libc::S_IWUSR
            );
            assert!(fd >= 0);
            assert!(libc::ftruncate(fd, SIZE as i64) != -1);
            let ptr = libc::mmap(ptr::null_mut(), SIZE as u64,
                                 libc::PROT_WRITE | libc::PROT_READ, 1, fd, 0);
            assert!(ptr != libc::MAP_FAILED);
            for i in range(0, PIXELS) {
                let p: *mut u32 = (ptr as *mut u32).offset(i as int);
                std::ptr::write(&mut *p, 0x80000000);
            }
            ShmFd { fd: fd, ptr: ptr }
        }
    }
    pub fn fd(&self) -> i32 {
        self.fd
    }
}

impl Drop for ShmFd {
    fn drop(&mut self) {
        unsafe {
            libc::munmap(self.ptr, SIZE as u64);
            libc::funcs::posix88::mman::shm_unlink(
                "/eyl-hello-world".to_c_str().as_ptr()
            );
        }
    }
}

fn main() {
    let mut display = wayland::Display::new();
    let mut registry = wayland::Registry::new(&mut display);
    let shm_fd = ShmFd::new();
    let mut pool = registry.shm().create_pool(shm_fd.fd(), SIZE);
    let mut surface = registry.compositor().create_surface();
    let mut buffer = pool.create_buffer(
        0, WIDTH, HEIGHT, STRIDE, wayland::raw::WL_SHM_FORMAT_ARGB8888
    );
    surface.attach(&mut buffer, 0, 0);
    let mut shell_surface = registry.shell().get_shell_surface(&mut surface);
    shell_surface.set_toplevel();
    surface.commit();
    loop {
        display.dispatch();
    }
}
<|endoftext|>


<commit_before>use cmake;

fn main() {
    #[cfg(feature = "no_bssl")]
    return;

    let bssl_dir = std::env::var("QUICHE_BSSL_PATH").unwrap_or_else(|_| {
        cmake::Config::new("deps/boringssl")
            .cflag("-fPIC")
            .build_target("bssl")
            .build()
            .display()
            .to_string()
    });

    let crypto_dir = format!("{}/build/crypto", bssl_dir);
    println!("cargo:rustc-link-search=native={}", crypto_dir);
    println!("cargo:rustc-link-lib=static=crypto");

    let ssl_dir = format!("{}/build/ssl", bssl_dir);
    println!("cargo:rustc-link-search=native={}", ssl_dir);
    println!("cargo:rustc-link-lib=static=ssl");
}
<commit_msg>build: add workaround for cmake on Windows<commit_after>use cmake;

/// Generate the platform-specific output path for lib
///
/// MSVC generator on Windows place static libs in a target sub-folder,
/// so adjust library location based on platform and build target.
/// See issue: https://github.com/alexcrichton/cmake-rs/issues/18
fn platform_output_path(lib: &str) -> String {
    if cfg!(windows) {
        if cfg!(debug_assertions) {
            return format!("{}/Debug", lib);
        } else {
            return format!("{}/RelWithDebInfo", lib);
        }
    } else {
        return format!("{}", lib);
    };
}

fn main() {
    #[cfg(feature = "no_bssl")]
    return;

    let bssl_dir = std::env::var("QUICHE_BSSL_PATH").unwrap_or_else(|_| {
        cmake::Config::new("deps/boringssl")
            .cflag("-fPIC")
            .build_target("bssl")
            .build()
            .display()
            .to_string()
    });

    let crypto_dir =
        format!("{}/build/{}", bssl_dir, platform_output_path("crypto"));
    println!("cargo:rustc-link-search=native={}", crypto_dir);
    println!("cargo:rustc-link-lib=static=crypto");

    let ssl_dir = format!("{}/build/{}", bssl_dir, platform_output_path("ssl"));
    println!("cargo:rustc-link-search=native={}", ssl_dir);
    println!("cargo:rustc-link-lib=static=ssl");
}
<|endoftext|>