1313// limitations under the License.
1414
1515use crate :: {
16- hash:: { hash_f64, hash_to_u64} ,
16+ hash:: hash_f64,
17+ imag,
18+ instruction:: MemoryReference ,
1719 parser:: { lex, parse_expression, ParseError } ,
1820 program:: { disallow_leftover, ParseProgramError } ,
19- { imag , instruction :: MemoryReference , real} ,
21+ real,
2022} ;
2123use lexical:: { format, to_string_with_options, WriteFloatOptions } ;
2224use nom_locate:: LocatedSpan ;
@@ -53,13 +55,13 @@ pub enum Expression {
5355 Address ( MemoryReference ) ,
5456 FunctionCall ( FunctionCallExpression ) ,
5557 Infix ( InfixExpression ) ,
56- Number ( num_complex :: Complex64 ) ,
58+ Number ( Complex64 ) ,
5759 PiConstant ,
5860 Prefix ( PrefixExpression ) ,
5961 Variable ( String ) ,
6062}
6163
62- #[ derive( Clone , Debug ) ]
64+ #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
6365pub struct FunctionCallExpression {
6466 pub function : ExpressionFunction ,
6567 pub expression : Box < Expression > ,
@@ -74,7 +76,7 @@ impl FunctionCallExpression {
7476 }
7577}
7678
77- #[ derive( Clone , Debug ) ]
79+ #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
7880pub struct InfixExpression {
7981 pub left : Box < Expression > ,
8082 pub operator : InfixOperator ,
@@ -91,7 +93,7 @@ impl InfixExpression {
9193 }
9294}
9395
94- #[ derive( Clone , Debug ) ]
96+ #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
9597pub struct PrefixExpression {
9698 pub operator : PrefixOperator ,
9799 pub expression : Box < Expression > ,
@@ -106,50 +108,52 @@ impl PrefixExpression {
106108 }
107109}
108110
111+ impl PartialEq for Expression {
112+ // Implemented by hand since we can't derive with f64s hidden inside.
113+ fn eq ( & self , other : & Self ) -> bool {
114+ match ( self , other) {
115+ ( Self :: Address ( left) , Self :: Address ( right) ) => left == right,
116+ ( Self :: Infix ( left) , Self :: Infix ( right) ) => left == right,
117+ ( Self :: Number ( left) , Self :: Number ( right) ) => left == right,
118+ ( Self :: Prefix ( left) , Self :: Prefix ( right) ) => left == right,
119+ ( Self :: FunctionCall ( left) , Self :: FunctionCall ( right) ) => left == right,
120+ ( Self :: Variable ( left) , Self :: Variable ( right) ) => left == right,
121+ ( Self :: PiConstant , Self :: PiConstant ) => true ,
122+ _ => false ,
123+ }
124+ }
125+ }
126+
127+ // Implemented by hand since we can't derive with f64s hidden inside.
128+ impl Eq for Expression { }
129+
109130impl Hash for Expression {
110131 // Implemented by hand since we can't derive with f64s hidden inside.
111- // Also to understand when things should be the same, like with commutativity (`1 + 2 == 2 + 1`).
112- // See https://github.com/rigetti/quil-rust/issues/27
113132 fn hash < H : Hasher > ( & self , state : & mut H ) {
114- use std:: cmp:: { max_by_key, min_by_key} ;
115- use Expression :: * ;
116133 match self {
117- Address ( m) => {
134+ Expression :: Address ( m) => {
118135 "Address" . hash ( state) ;
119136 m. hash ( state) ;
120137 }
121- FunctionCall ( FunctionCallExpression {
138+ Expression :: FunctionCall ( FunctionCallExpression {
122139 function,
123140 expression,
124141 } ) => {
125142 "FunctionCall" . hash ( state) ;
126143 function. hash ( state) ;
127144 expression. hash ( state) ;
128145 }
129- Infix ( InfixExpression {
146+ Expression :: Infix ( InfixExpression {
130147 left,
131148 operator,
132149 right,
133150 } ) => {
134151 "Infix" . hash ( state) ;
135152 operator. hash ( state) ;
136- match operator {
137- InfixOperator :: Plus | InfixOperator :: Star => {
138- // commutative, so put left & right in decreasing order by hash value
139- let ( a, b) = (
140- min_by_key ( & left, & right, hash_to_u64) ,
141- max_by_key ( & left, & right, hash_to_u64) ,
142- ) ;
143- a. hash ( state) ;
144- b. hash ( state) ;
145- }
146- _ => {
147- left. hash ( state) ;
148- right. hash ( state) ;
149- }
150- }
153+ left. hash ( state) ;
154+ right. hash ( state) ;
151155 }
152- Number ( n) => {
156+ Expression :: Number ( n) => {
153157 "Number" . hash ( state) ;
154158 // Skip zero values (akin to `format_complex`).
155159 // Also, since f64 isn't hashable, use the u64 binary representation.
@@ -161,31 +165,22 @@ impl Hash for Expression {
161165 hash_f64 ( n. im , state)
162166 }
163167 }
164- PiConstant => {
168+ Expression :: PiConstant => {
165169 "PiConstant" . hash ( state) ;
166170 }
167- Prefix ( p) => {
171+ Expression :: Prefix ( p) => {
168172 "Prefix" . hash ( state) ;
169173 p. operator . hash ( state) ;
170174 p. expression . hash ( state) ;
171175 }
172- Variable ( v) => {
176+ Expression :: Variable ( v) => {
173177 "Variable" . hash ( state) ;
174178 v. hash ( state) ;
175179 }
176180 }
177181 }
178182}
179183
180- impl PartialEq for Expression {
181- // Partial equality by hash value
182- fn eq ( & self , other : & Self ) -> bool {
183- hash_to_u64 ( self ) == hash_to_u64 ( other)
184- }
185- }
186-
187- impl Eq for Expression { }
188-
189184macro_rules! impl_expr_op {
190185 ( $name: ident, $name_assign: ident, $function: ident, $function_assign: ident, $operator: ident) => {
191186 impl $name for Expression {
@@ -215,11 +210,7 @@ impl_expr_op!(Mul, MulAssign, mul, mul_assign, Star);
215210impl_expr_op ! ( Div , DivAssign , div, div_assign, Slash ) ;
216211
217212/// Compute the result of an infix expression where both operands are complex.
218- fn calculate_infix (
219- left : & num_complex:: Complex64 ,
220- operator : & InfixOperator ,
221- right : & num_complex:: Complex64 ,
222- ) -> num_complex:: Complex64 {
213+ fn calculate_infix ( left : & Complex64 , operator : & InfixOperator , right : & Complex64 ) -> Complex64 {
223214 use InfixOperator :: * ;
224215 match operator {
225216 Caret => left. powc ( * right) ,
@@ -231,10 +222,7 @@ fn calculate_infix(
231222}
232223
233224/// Compute the result of a Quil-defined expression function where the operand is complex.
234- fn calculate_function (
235- function : & ExpressionFunction ,
236- argument : & num_complex:: Complex64 ,
237- ) -> num_complex:: Complex64 {
225+ fn calculate_function ( function : & ExpressionFunction , argument : & Complex64 ) -> Complex64 {
238226 use ExpressionFunction :: * ;
239227 match function {
240228 Sine => argument. sin ( ) ,
@@ -323,9 +311,9 @@ impl Expression {
323311 /// ```
324312 pub fn evaluate (
325313 & self ,
326- variables : & HashMap < String , num_complex :: Complex64 > ,
314+ variables : & HashMap < String , Complex64 > ,
327315 memory_references : & HashMap < & str , Vec < f64 > > ,
328- ) -> Result < num_complex :: Complex64 , EvaluationError > {
316+ ) -> Result < Complex64 , EvaluationError > {
329317 use Expression :: * ;
330318
331319 match self {
@@ -660,18 +648,11 @@ impl fmt::Display for InfixOperator {
660648
661649#[ cfg( test) ]
662650mod tests {
663- use std:: collections:: { hash_map:: DefaultHasher , HashSet } ;
664-
665- use num_complex:: Complex64 ;
666- use proptest:: prelude:: * ;
667-
668- use crate :: {
669- expression:: { EvaluationError , Expression , ExpressionFunction } ,
670- real,
671- reserved:: ReservedToken ,
672- } ;
673-
674651 use super :: * ;
652+ use crate :: hash:: hash_to_u64;
653+ use crate :: reserved:: ReservedToken ;
654+ use proptest:: prelude:: * ;
655+ use std:: collections:: HashSet ;
675656
676657 #[ test]
677658 fn simplify_and_evaluate ( ) {
@@ -862,21 +843,6 @@ mod tests {
862843 prop_assert_ne!( & first, & differing) ;
863844 }
864845
865- #[ test]
866- fn eq_commutative( a in any:: <f64 >( ) , b in any:: <f64 >( ) ) {
867- let first = Expression :: Infix ( InfixExpression {
868- left: Box :: new( Expression :: Number ( real!( a) ) ) ,
869- operator: InfixOperator :: Plus ,
870- right: Box :: new( Expression :: Number ( real!( b) ) ) ,
871- } ) ;
872- let second = Expression :: Infix ( InfixExpression {
873- left: Box :: new( Expression :: Number ( real!( b) ) ) ,
874- operator: InfixOperator :: Plus ,
875- right: Box :: new( Expression :: Number ( real!( a) ) ) ,
876- } ) ;
877- prop_assert_eq!( first, second) ;
878- }
879-
880846 #[ test]
881847 fn hash( a in any:: <f64 >( ) , b in any:: <f64 >( ) ) {
882848 let first = Expression :: Infix ( InfixExpression {
@@ -892,36 +858,9 @@ mod tests {
892858 assert!( !set. contains( & differing) )
893859 }
894860
895- #[ test]
896- fn hash_commutative( a in any:: <f64 >( ) , b in any:: <f64 >( ) ) {
897- let first = Expression :: Infix ( InfixExpression {
898- left: Box :: new( Expression :: Number ( real!( a) ) ) ,
899- operator: InfixOperator :: Plus ,
900- right: Box :: new( Expression :: Number ( real!( b) ) ) ,
901- } ) ;
902- let second = Expression :: Infix ( InfixExpression {
903- left: Box :: new( Expression :: Number ( real!( b) ) ) ,
904- operator: InfixOperator :: Plus ,
905- right: Box :: new( Expression :: Number ( real!( a) ) ) ,
906- } ) ;
907- let mut set = HashSet :: new( ) ;
908- set. insert( first) ;
909- assert!( set. contains( & second) ) ;
910- }
911-
912861 #[ test]
913862 fn eq_iff_hash_eq( x in arb_expr( ) , y in arb_expr( ) ) {
914- let h_x = {
915- let mut s = DefaultHasher :: new( ) ;
916- x. hash( & mut s) ;
917- s. finish( )
918- } ;
919- let h_y = {
920- let mut s = DefaultHasher :: new( ) ;
921- y. hash( & mut s) ;
922- s. finish( )
923- } ;
924- prop_assert_eq!( x == y, h_x == h_y) ;
863+ prop_assert_eq!( x == y, hash_to_u64( & x) == hash_to_u64( & y) ) ;
925864 }
926865
927866 #[ test]
0 commit comments