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,86 +108,77 @@ 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+ Self :: Address ( m) => {
118135 "Address" . hash ( state) ;
119136 m. hash ( state) ;
120137 }
121- FunctionCall ( FunctionCallExpression {
138+ Self :: FunctionCall ( FunctionCallExpression {
122139 function,
123140 expression,
124141 } ) => {
125142 "FunctionCall" . hash ( state) ;
126143 function. hash ( state) ;
127144 expression. hash ( state) ;
128145 }
129- Infix ( InfixExpression {
146+ Self :: 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+ Self :: Number ( n) => {
153157 "Number" . hash ( state) ;
154158 // Skip zero values (akin to `format_complex`).
155- // Also, since f64 isn't hashable, use the u64 binary representation.
156- // The docs claim this is rather portable: https://doc.rust-lang.org/std/primitive.f64.html#method.to_bits
157159 if n. re . abs ( ) > 0f64 {
158160 hash_f64 ( n. re , state)
159161 }
160162 if n. im . abs ( ) > 0f64 {
161163 hash_f64 ( n. im , state)
162164 }
163165 }
164- PiConstant => {
166+ Self :: PiConstant => {
165167 "PiConstant" . hash ( state) ;
166168 }
167- Prefix ( p) => {
169+ Self :: Prefix ( p) => {
168170 "Prefix" . hash ( state) ;
169171 p. operator . hash ( state) ;
170172 p. expression . hash ( state) ;
171173 }
172- Variable ( v) => {
174+ Self :: Variable ( v) => {
173175 "Variable" . hash ( state) ;
174176 v. hash ( state) ;
175177 }
176178 }
177179 }
178180}
179181
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-
189182macro_rules! impl_expr_op {
190183 ( $name: ident, $name_assign: ident, $function: ident, $function_assign: ident, $operator: ident) => {
191184 impl $name for Expression {
@@ -215,11 +208,7 @@ impl_expr_op!(Mul, MulAssign, mul, mul_assign, Star);
215208impl_expr_op ! ( Div , DivAssign , div, div_assign, Slash ) ;
216209
217210/// 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 {
211+ fn calculate_infix ( left : & Complex64 , operator : & InfixOperator , right : & Complex64 ) -> Complex64 {
223212 use InfixOperator :: * ;
224213 match operator {
225214 Caret => left. powc ( * right) ,
@@ -231,10 +220,7 @@ fn calculate_infix(
231220}
232221
233222/// 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 {
223+ fn calculate_function ( function : & ExpressionFunction , argument : & Complex64 ) -> Complex64 {
238224 use ExpressionFunction :: * ;
239225 match function {
240226 Sine => argument. sin ( ) ,
@@ -323,9 +309,9 @@ impl Expression {
323309 /// ```
324310 pub fn evaluate (
325311 & self ,
326- variables : & HashMap < String , num_complex :: Complex64 > ,
312+ variables : & HashMap < String , Complex64 > ,
327313 memory_references : & HashMap < & str , Vec < f64 > > ,
328- ) -> Result < num_complex :: Complex64 , EvaluationError > {
314+ ) -> Result < Complex64 , EvaluationError > {
329315 use Expression :: * ;
330316
331317 match self {
@@ -660,18 +646,11 @@ impl fmt::Display for InfixOperator {
660646
661647#[ cfg( test) ]
662648mod 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-
674649 use super :: * ;
650+ use crate :: hash:: hash_to_u64;
651+ use crate :: reserved:: ReservedToken ;
652+ use proptest:: prelude:: * ;
653+ use std:: collections:: HashSet ;
675654
676655 #[ test]
677656 fn simplify_and_evaluate ( ) {
@@ -862,21 +841,6 @@ mod tests {
862841 prop_assert_ne!( & first, & differing) ;
863842 }
864843
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-
880844 #[ test]
881845 fn hash( a in any:: <f64 >( ) , b in any:: <f64 >( ) ) {
882846 let first = Expression :: Infix ( InfixExpression {
@@ -892,36 +856,9 @@ mod tests {
892856 assert!( !set. contains( & differing) )
893857 }
894858
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-
912859 #[ test]
913860 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) ;
861+ prop_assert_eq!( x == y, hash_to_u64( & x) == hash_to_u64( & y) ) ;
925862 }
926863
927864 #[ test]
0 commit comments