From 73e172484c0ac982265c1d210723feaa3999eed6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:12:18 +0200 Subject: [PATCH 01/11] Add tick marks around code items in docs --- src/constants.rs | 10 +++++----- src/curve.rs | 14 +++++++------- src/field.rs | 26 ++++++++++++++------------ 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 9ff4d4d..c0e6cc2 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -70,7 +70,7 @@ pub const SQRT_M1: FieldElement = FieldElement([ pub const SQRT_M1: FieldElement = FieldElement([1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133]); /// Precomputed value of the other square root of -1 (mod p), -/// i.e., MSQRT_M1 = -SQRT_M1. +/// i.e., `MSQRT_M1 = -SQRT_M1`. #[cfg(not(feature="radix_51"))] pub const MSQRT_M1: FieldElement = FieldElement([ 32595792, 7943725, -9377950, -3500415, -12389472, @@ -92,7 +92,7 @@ pub const A: FieldElement = FieldElement([ #[cfg(feature="radix_51")] pub const A: FieldElement = FieldElement([486662, 0, 0, 0, 0]); -/// SQRT_MINUS_A is sqrt(-486662) +/// `SQRT_MINUS_A` is sqrt(-486662) // XXX I think that this was used in Adam's code for his elligator // implementation, but that should maybe be using sqrt(-486664) // instead...? - hdevalence @@ -103,7 +103,7 @@ pub const SQRT_MINUS_A: FieldElement = FieldElement([ // sqrtMinusA #[cfg(feature="radix_51")] pub const SQRT_MINUS_A: FieldElement = FieldElement([557817479725543, 1643290402203250, 16226468853936, 1304118542701054, 1985241807451647]); -/// SQRT_MINUS_APLUS2 is sqrt(-486664) +/// `SQRT_MINUS_APLUS2` is sqrt(-486664) #[cfg(not(feature="radix_51"))] pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ -12222970, -8312128, -11511410, 9067497, -15300785, @@ -111,7 +111,7 @@ pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([ #[cfg(feature="radix_51")] pub const SQRT_MINUS_APLUS2: FieldElement = FieldElement([1693982333959686, 608509411481997, 2235573344831311, 947681270984193, 266558006233600]); -/// SQRT_MINUS_HALF is sqrt(-1/2) +/// `SQRT_MINUS_HALF` is sqrt(-1/2) #[cfg(not(feature="radix_51"))] pub const SQRT_MINUS_HALF: FieldElement = FieldElement([ // sqrtMinusHalf -17256545, 3971863, 28865457, -1750208, 27359696, @@ -119,7 +119,7 @@ pub const SQRT_MINUS_HALF: FieldElement = FieldElement([ // sqrtMinusHalf #[cfg(feature="radix_51")] pub const SQRT_MINUS_HALF: FieldElement = FieldElement([266547196637087, 2134345371906993, 1135042577398223, 67298593331632, 743161882051057]); -/// HALF_Q_MINUS_1_BYTES is (2^255-20)/2 expressed in little endian form. +/// `HALF_Q_MINUS_1_BYTES` is (2^255-20)/2 expressed in little endian form. pub const HALF_Q_MINUS_1_BYTES: [u8; 32] = [ // halfQMinus1Bytes 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/src/curve.rs b/src/curve.rs index aefecac..7638da1 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -59,15 +59,15 @@ //! implementation for [Ed25519](https://ed25519.cr.yp.to/ed25519-20110926.pdf), //! we use several different models for curve points: //! -//! * CompletedPoint: points in ๐—ฃ^1 x ๐—ฃ^1; -//! * ExtendedPoint: points in ๐—ฃ^3; -//! * ProjectivePoint: points in ๐—ฃ^2. +//! * `CompletedPoint`: points in ๐—ฃ^1 x ๐—ฃ^1; +//! * `ExtendedPoint`: points in ๐—ฃ^3; +//! * `ProjectivePoint`: points in ๐—ฃ^2. //! //! Finally, to accelerate additions, we use two cached point formats, //! one for the affine model and one for the ๐—ฃ^3 model: //! -//! * AffineNielsPoint: `(y+x, y-x, 2dxy)` -//! * ProjectiveNielsPoint: `(Y+X, Y-X, Z, 2dXY)` +//! * `AffineNielsPoint`: `(y+x, y-x, 2dxy)` +//! * `ProjectiveNielsPoint`: `(Y+X, Y-X, Z, 2dXY)` //! //! [1]: https://moderncrypto.org/mail-archive/curves/2016/000807.html @@ -103,7 +103,7 @@ use std::boxed::Box; /// determined by the `y`-coordinate and the sign of `x`, marshalled /// into a 32-byte array. /// -/// The first 255 bits of a CompressedEdwardsY represent the +/// The first 255 bits of a `CompressedEdwardsY` represent the /// y-coordinate. The high bit of the 32nd byte gives the sign of `x`. #[derive(Copy, Clone, Eq, PartialEq)] pub struct CompressedEdwardsY(pub [u8; 32]); @@ -303,7 +303,7 @@ pub struct ProjectivePoint { Z: FieldElement, } -/// A CompletedPoint is a point ((X:Z), (Y:T)) in ๐—ฃยน(๐”ฝโ‚š)ร—๐—ฃยน(๐”ฝโ‚š). +/// A `CompletedPoint` is a point ((X:Z), (Y:T)) in ๐—ฃยน(๐”ฝโ‚š)ร—๐—ฃยน(๐”ฝโ‚š). /// A point (x,y) in the affine model corresponds to ((x:1),(y:1)). #[derive(Copy, Clone)] pub struct CompletedPoint { diff --git a/src/field.rs b/src/field.rs index 78dcc9b..8a6373c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -41,25 +41,27 @@ use constants; #[cfg(feature="radix_51")] pub type Limb = u64; -/// FieldElement represents an element of the field GF(2^255 - 19). An element -/// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -/// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -/// context. +/// A `FieldElement` represents an element of the field GF(2^255 - 19). +/// +/// With the `radix_51` feature, a `FieldElement` is represented in +/// radix 2^51 as five `u64`s; the coefficients are allowed to grow up +/// to 2^54 between reductions mod `p`. #[cfg(feature="radix_51")] #[derive(Copy, Clone)] pub struct FieldElement(pub [u64; 5]); -/// FieldElements are represented as an array of ten "Limbs", which are radix -/// 25.5, that is, each Limb of a FieldElement alternates between being -/// represented as a factor of 2^25 or 2^26 more than the last corresponding -/// integer. +/// Without the `radix51` feature enabled, `FieldElements` are represented +/// in radix 2^25.5 as ten `i32`s. #[cfg(not(feature="radix_51"))] pub type Limb = i32; -/// FieldElement represents an element of the field GF(2^255 - 19). An element -/// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -/// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -/// context. +/// A `FieldElement` represents an element of the field GF(2^255 - 19). +/// +/// With the `radix_51` feature, a `FieldElement` is represented in +/// radix 2^25.5 as ten `i32`s, so that an element t, entries +/// t[0],...,t[9], represents the integer t[0]+2^26 t[1]+2^51 +/// t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] +/// vary depending on context. #[cfg(not(feature="radix_51"))] #[derive(Copy, Clone)] pub struct FieldElement(pub [i32; 10]); From e74bf8e78932f7eeabfecbe7a2b7fa8c8524d9e3 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:14:19 +0200 Subject: [PATCH 02/11] Remove unnecessary if statement --- src/curve.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 7638da1..b2206d3 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -947,13 +947,7 @@ impl ExtendedPoint { /// /// True if it is of small order; false otherwise. pub fn is_small_order(&self) -> bool { - let p8: ExtendedPoint = self.mult_by_pow_2(3); - - if p8.is_identity() { - return true; - } else { - return false; - } + self.mult_by_cofactor().is_identity() } } From b3041f2adcb7497ffcc38a6098ba1fa3e22a5d55 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:17:20 +0200 Subject: [PATCH 03/11] Remove unnecessary if statements --- src/curve.rs | 8 +------- src/scalar.rs | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index b2206d3..ff82477 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -470,13 +470,7 @@ pub trait IsIdentity { /// constructor. impl IsIdentity for T where T: CTEq + Identity { fn is_identity(&self) -> bool { - let identity: T = T::identity(); - - if self.ct_eq(&identity) == 1u8 { - return true; - } else { - return false; - } + self.ct_eq(&T::identity()) == 1u8 } } diff --git a/src/scalar.rs b/src/scalar.rs index f7808e3..5d6a5ec 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -72,13 +72,7 @@ impl PartialEq for Scalar { /// /// True if they are equal, and false otherwise. fn eq(&self, other: &Self) -> bool { - let equal: u8 = arrays_equal_ct(&self.0, &other.0); - - if equal == 1u8 { - return true; - } else { - return false; - } + arrays_equal_ct(&self.0, &other.0) == 1u8 } } From c8e7e22ddfe92d31f21ec8d2ffeb28d793f422be Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:28:01 +0200 Subject: [PATCH 04/11] Remove unnecessary returns --- src/field.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field.rs b/src/field.rs index 8a6373c..2545d02 100644 --- a/src/field.rs +++ b/src/field.rs @@ -86,7 +86,7 @@ impl PartialEq for FieldElement { for i in 0..32 { are_equal &= self_bytes[i] == other_bytes[i]; } - return are_equal; + are_equal } } @@ -923,7 +923,7 @@ impl FieldElement { for b in &bytes { x |= *b; } - return byte_is_nonzero(x); + byte_is_nonzero(x) } #[cfg(not(feature="radix_51"))] From 7f4b96150deed0be4598d3e7ec660e55bee0786f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:36:05 +0200 Subject: [PATCH 05/11] Remove explicit lifetimes --- src/curve.rs | 2 +- src/field.rs | 10 ++++------ src/scalar.rs | 22 +++++++++------------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index ff82477..872d4d3 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -116,7 +116,7 @@ impl Debug for CompressedEdwardsY { impl CompressedEdwardsY { /// View this `CompressedEdwardsY` as an array of bytes. - pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] { + pub fn as_bytes(&self) -> &[u8; 32] { &self.0 } diff --git a/src/field.rs b/src/field.rs index 2545d02..1495d17 100644 --- a/src/field.rs +++ b/src/field.rs @@ -110,16 +110,14 @@ impl Debug for FieldElement { impl Index for FieldElement { type Output = Limb; - fn index<'a>(&'a self, _index: usize) -> &'a Limb { - let ret: &'a Limb = &(self.0[_index]); - ret + fn index(&self, _index: usize) -> &Limb { + &(self.0[_index]) } } impl IndexMut for FieldElement { - fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Limb { - let ret: &'a mut Limb = &mut(self.0[_index]); - ret + fn index_mut(&mut self, _index: usize) -> &mut Limb { + &mut(self.0[_index]) } } diff --git a/src/scalar.rs b/src/scalar.rs index 5d6a5ec..8606913 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -90,16 +90,14 @@ impl CTEq for Scalar { impl Index for Scalar { type Output = u8; - fn index<'a>(&'a self, _index: usize) -> &'a u8 { - let ret: &'a u8 = &(self.0[_index]); - ret + fn index(&self, _index: usize) -> &u8 { + &(self.0[_index]) } } impl IndexMut for Scalar { - fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut u8 { - let ret: &'a mut u8 = &mut(self.0[_index]); - ret + fn index_mut(&mut self, _index: usize) -> &mut u8 { + &mut(self.0[_index]) } } @@ -194,7 +192,7 @@ impl Scalar { } /// View this `Scalar` as a sequence of bytes. - pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + pub fn as_bytes(&self) -> &[u8;32] { &self.0 } @@ -381,16 +379,14 @@ pub struct UnpackedScalar(pub [i64; 12]); impl Index for UnpackedScalar { type Output = i64; - fn index<'a>(&'a self, _index: usize) -> &'a i64 { - let ret: &'a i64 = &(self.0[_index]); - ret + fn index(&self, _index: usize) -> &i64 { + &(self.0[_index]) } } impl IndexMut for UnpackedScalar { - fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut i64 { - let ret: &'a mut i64 = &mut(self.0[_index]); - ret + fn index_mut(&mut self, _index: usize) -> &mut i64 { + &mut(self.0[_index]) } } From 3705346afa90be6daa47ffee707f1480f69b0889 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:39:45 +0200 Subject: [PATCH 06/11] Remove unnecessary returns --- src/curve.rs | 3 +-- src/field.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/curve.rs b/src/curve.rs index 872d4d3..0cf6890 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -927,8 +927,7 @@ impl ExtendedPoint { r = s.double(); s = r.to_projective(); } // Unroll last iteration so we can go directly to_extended() - r = s.double(); - return r.to_extended(); + s.double().to_extended() } /// Determine if this point is of small order. diff --git a/src/field.rs b/src/field.rs index 1495d17..4c2d333 100644 --- a/src/field.rs +++ b/src/field.rs @@ -907,7 +907,7 @@ impl FieldElement { /// /// If zero, return `1u8`. Otherwise, return `0u8`. pub fn is_zero(&self) -> u8 { - return 1u8 & (!self.is_nonzero()); + 1u8 & (!self.is_nonzero()) } /// Determine if this `FieldElement` is non-zero. From 162dfc83312042d09dc794292d24e38f22b7ee0b Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:45:34 +0200 Subject: [PATCH 07/11] Remove clones on Copy types --- src/field.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/field.rs b/src/field.rs index 4c2d333..bb0333c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -132,7 +132,7 @@ impl<'b> AddAssign<&'b FieldElement> for FieldElement { impl<'a, 'b> Add<&'b FieldElement> for &'a FieldElement { type Output = FieldElement; fn add(self, _rhs: &'b FieldElement) -> FieldElement { - let mut output = self.clone(); + let mut output = *self; output += _rhs; output } @@ -158,7 +158,7 @@ impl<'a, 'b> Sub<&'b FieldElement> for &'a FieldElement { type Output = FieldElement; #[cfg(not(feature="radix_51"))] fn sub(self, _rhs: &'b FieldElement) -> FieldElement { - let mut output = self.clone(); + let mut output = *self; output -= _rhs; output } @@ -326,7 +326,7 @@ impl<'a, 'b> Mul<&'b FieldElement> for &'a FieldElement { impl<'a> Neg for &'a FieldElement { type Output = FieldElement; fn neg(self) -> FieldElement { - let mut output = self.clone(); + let mut output = *self; output.negate(); output } @@ -656,7 +656,7 @@ impl FieldElement { // so floor(2^-255 * (h + 19 * 2^-25 * h9 + 2^-1)) = q. // let mut carry = [0i32; 10]; - let mut h = self.clone(); + let mut h: [i32; 10] = self.0; let mut q:i32 = (19*h[9] + (1 << 24)) >> 25; q = (h[0] + q) >> 26; @@ -1352,7 +1352,7 @@ mod test { #[test] fn from_bytes_highbit_is_ignored() { - let mut cleared_bytes = B_BYTES.clone(); + let mut cleared_bytes = B_BYTES; cleared_bytes[31] &= 127u8; let with_highbit_set = FieldElement::from_bytes(&B_BYTES); let without_highbit_set = FieldElement::from_bytes(&cleared_bytes); From e00cd114d716e0be60dfa2c52e294e8d93456060 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sun, 2 Apr 2017 23:46:01 +0200 Subject: [PATCH 08/11] Have radix 25.5 reduce() consume its argument --- src/field.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/field.rs b/src/field.rs index bb0333c..b4dd2d4 100644 --- a/src/field.rs +++ b/src/field.rs @@ -319,7 +319,7 @@ impl<'a, 'b> Mul<&'b FieldElement> for &'a FieldElement { let h8 = f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19; let h9 = f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0; - FieldElement::reduce(&[h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) + FieldElement::reduce([h0, h1, h2, h3, h4, h5, h6, h7, h8, h9]) } } @@ -455,9 +455,8 @@ impl FieldElement { FieldElement(limbs) } #[cfg(not(feature="radix_51"))] - fn reduce(input: &[i64;10]) -> FieldElement { //FeCombine + fn reduce(mut h: [i64; 10]) -> FieldElement { //FeCombine let mut c = [0i64;10]; - let mut h = input.clone(); /* |h[0]| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) @@ -581,7 +580,7 @@ impl FieldElement { h[8] = load3(&data[26..]) << 4; h[9] = (load3(&data[29..]) & 8388607) << 2; - FieldElement::reduce(&h) + FieldElement::reduce(h) } /// Parse a `FieldElement` from 32 bytes. #[cfg(feature="radix_51")] @@ -1028,12 +1027,12 @@ impl FieldElement { /// * |h[i]| bounded by 1.1*2^25, 1.1*2^24, 1.1*2^25, 1.1*2^24, etc. #[cfg(not(feature="radix_51"))] pub fn square(&self) -> FieldElement { - FieldElement::reduce(&self.square_inner()) + FieldElement::reduce(self.square_inner()) } /// Compute `self^2`. #[cfg(feature="radix_51")] pub fn square(&self) -> FieldElement { - FieldElement::reduce( self.square_inner()) + FieldElement::reduce(self.square_inner()) } /// Square this field element and multiply the result by 2. @@ -1058,7 +1057,7 @@ impl FieldElement { for i in 0..self.0.len() { coeffs[i] += coeffs[i]; } - FieldElement::reduce(&coeffs) + FieldElement::reduce(coeffs) } /// Compute `2 * self^2`. #[cfg(feature="radix_51")] From 57c96616b9469941d9f6075c93762e9dcecf576f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 25 Apr 2017 14:50:59 -0700 Subject: [PATCH 09/11] Remove unused import --- src/field.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/field.rs b/src/field.rs index b4dd2d4..6b5a167 100644 --- a/src/field.rs +++ b/src/field.rs @@ -15,7 +15,6 @@ //! Based on Adam Langley's curve25519-donna and (Golang) ed25519 //! implementations. -use core::clone::Clone; use core::fmt::Debug; use core::ops::{Add, AddAssign}; use core::ops::{Sub, SubAssign}; From cb656bafa7fd0c826b556b6a350f5dd0eb1464a6 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 25 Apr 2017 15:08:56 -0700 Subject: [PATCH 10/11] Delete bytes_equal_less_than This function is unused and untested. It's also incorrect, since the loop 32..0 iterates over an empty range. Remove it for now; if we need it later, it still lives in the history. --- src/field.rs | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/field.rs b/src/field.rs index 6b5a167..7e4a99c 100644 --- a/src/field.rs +++ b/src/field.rs @@ -828,32 +828,6 @@ impl FieldElement { return s } - /// XXX clarify documentation - /// Determine if this field element, represented as a byte array, - /// is less than or equal to another field element represented as - /// a byte array. - /// - /// # Returns - /// - /// Returns `1u8` if `self.to_bytes() <= other.to_bytes()`, and `0u8` otherwise. - pub fn bytes_equal_less_than(&self, other: &[u8; 32]) -> u8 { // feBytesLess - // XXX cleanup - let mut equal_so_far: i32 = -1i32; - let mut greater: i32 = 0i32; - - let this: [u8; 32] = self.to_bytes(); - - for i in 32 .. 0 { - let x: i32 = this[i-1] as i32; - let y: i32 = other[i-1] as i32; - - greater = (!equal_so_far & greater) | (equal_so_far & ((x - y) >> 31)); - equal_so_far = equal_so_far & (((x ^ y) - 1) >> 31); - } - - (!equal_so_far & 1 & greater) as u8 - } - /// Determine if this `FieldElement` is negative, in the sense /// used in the ed25519 paper: `x` is negative if the low bit is /// set. From 60ad000609782fbfc1d65462add18e7d13c43358 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 25 Apr 2017 15:56:36 -0700 Subject: [PATCH 11/11] Remove redundant & --- src/curve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/curve.rs b/src/curve.rs index 0cf6890..1a1e4d8 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -232,7 +232,7 @@ impl CompressedMontgomeryU { /// Montgomery `v` corresponding to this `u`. pub fn to_montgomery_v(u: &FieldElement) -> (u8, FieldElement) { let one: FieldElement = FieldElement::one(); - let v_squared: FieldElement = u * &(&(&u.square() + &(&(&constants::A * u) + &one))); + let v_squared: FieldElement = u * &(&u.square() + &(&(&constants::A * u) + &one)); let (okay, v_inv) = v_squared.invsqrt(); let v = &v_inv * &v_squared;