11use crate :: algebra:: { BaseField , Elem , Int , Polynomial , Vector } ;
2- use array:: ArraySize ;
3- use module_lattice:: EncodingSize ;
4- use module_lattice:: { Field , Truncate } ;
2+ use module_lattice:: {
3+ ArraySize , EncodingSize , Field , FixedWidthInt , FixedWidthPolynomial , FixedWidthVector ,
4+ Truncate ,
5+ } ;
56
67// A convenience trait to allow us to associate some constants with a typenum
78pub ( crate ) trait CompressionFactor : EncodingSize {
@@ -22,68 +23,75 @@ where
2223 const DIV_MUL : u64 = ( 1 << T :: DIV_SHIFT ) / BaseField :: QLL ;
2324}
2425
25- // Traits for objects that allow compression / decompression
26- pub ( crate ) trait Compress {
27- fn compress < D : CompressionFactor > ( & mut self ) -> & Self ;
28- fn decompress < D : CompressionFactor > ( & mut self ) -> & Self ;
26+ /// Compress a prime-field representation into its `Z_{2^D}` fixed-width form.
27+ pub ( crate ) trait Compress < D : CompressionFactor > {
28+ type Output ;
29+ fn compress ( self ) -> Self :: Output ;
2930}
3031
31- impl Compress for Elem {
32+ /// Decompress a `Z_{2^D}` fixed-width representation back into the prime field.
33+ pub ( crate ) trait Decompress < D : CompressionFactor > {
34+ type Output ;
35+ fn decompress ( self ) -> Self :: Output ;
36+ }
37+
38+ impl < D : CompressionFactor > Compress < D > for Elem {
39+ type Output = FixedWidthInt < BaseField , D > ;
40+
3241 // Equation 4.5: Compress_d(x) = round((2^d / q) x)
3342 //
3443 // Here and in decompression, we leverage the following facts:
3544 //
3645 // round(a / b) = floor((a + b/2) / b)
3746 // a / q ~= (a * x) >> s where x >> s ~= 1/q
38- fn compress < D : CompressionFactor > ( & mut self ) -> & Self {
47+ fn compress ( self ) -> FixedWidthInt < BaseField , D > {
3948 const Q_HALF : u64 = ( BaseField :: QLL + 1 ) >> 1 ;
4049 let x = u64:: from ( self . 0 ) ;
4150 let y = ( ( ( x << D :: USIZE ) + Q_HALF ) * D :: DIV_MUL ) >> D :: DIV_SHIFT ;
42- self . 0 = u16:: truncate ( y) & D :: MASK ;
43- self
51+ FixedWidthInt :: new ( u16:: truncate ( y) & D :: MASK )
4452 }
53+ }
54+
55+ impl < D : CompressionFactor > Decompress < D > for FixedWidthInt < BaseField , D > {
56+ type Output = Elem ;
4557
4658 // Equation 4.6: Decompress_d(x) = round((q / 2^d) x)
47- fn decompress < D : CompressionFactor > ( & mut self ) -> & Self {
48- let x = u32:: from ( self . 0 ) ;
59+ fn decompress ( self ) -> Elem {
60+ let x = u32:: from ( self . value ( ) ) ;
4961 let y = ( ( x * BaseField :: QL ) + D :: POW2_HALF ) >> D :: USIZE ;
50- self . 0 = Truncate :: truncate ( y) ;
51- self
62+ Elem :: new ( Truncate :: truncate ( y) )
5263 }
5364}
54- impl Compress for Polynomial {
55- fn compress < D : CompressionFactor > ( & mut self ) -> & Self {
56- for x in & mut self . 0 {
57- x. compress :: < D > ( ) ;
58- }
5965
60- self
66+ impl < D : CompressionFactor > Compress < D > for Polynomial {
67+ type Output = FixedWidthPolynomial < BaseField , D > ;
68+
69+ fn compress ( self ) -> FixedWidthPolynomial < BaseField , D > {
70+ FixedWidthPolynomial :: new ( self . 0 . into_iter ( ) . map ( Compress :: < D > :: compress) . collect ( ) )
6171 }
72+ }
6273
63- fn decompress < D : CompressionFactor > ( & mut self ) -> & Self {
64- for x in & mut self . 0 {
65- x. decompress :: < D > ( ) ;
66- }
74+ impl < D : CompressionFactor > Decompress < D > for FixedWidthPolynomial < BaseField , D > {
75+ type Output = Polynomial ;
6776
68- self
77+ fn decompress ( self ) -> Polynomial {
78+ Polynomial :: new ( self . 0 . into_iter ( ) . map ( Decompress :: < D > :: decompress) . collect ( ) )
6979 }
7080}
7181
72- impl < K : ArraySize > Compress for Vector < K > {
73- fn compress < D : CompressionFactor > ( & mut self ) -> & Self {
74- for x in & mut self . 0 {
75- x. compress :: < D > ( ) ;
76- }
82+ impl < K : ArraySize , D : CompressionFactor > Compress < D > for Vector < K > {
83+ type Output = FixedWidthVector < BaseField , K , D > ;
7784
78- self
85+ fn compress ( self ) -> FixedWidthVector < BaseField , K , D > {
86+ FixedWidthVector :: new ( self . 0 . into_iter ( ) . map ( Compress :: < D > :: compress) . collect ( ) )
7987 }
88+ }
8089
81- fn decompress < D : CompressionFactor > ( & mut self ) -> & Self {
82- for x in & mut self . 0 {
83- x. decompress :: < D > ( ) ;
84- }
90+ impl < K : ArraySize , D : CompressionFactor > Decompress < D > for FixedWidthVector < BaseField , K , D > {
91+ type Output = Vector < K > ;
8592
86- self
93+ fn decompress ( self ) -> Vector < K > {
94+ Vector :: new ( self . 0 . into_iter ( ) . map ( Decompress :: < D > :: decompress) . collect ( ) )
8795 }
8896}
8997
@@ -111,11 +119,10 @@ pub(crate) mod tests {
111119 let error_threshold = i32:: from ( Ratio :: new ( BaseField :: Q , 1 << D :: USIZE ) . to_integer ( ) ) ;
112120
113121 for x in 0 ..BaseField :: Q {
114- let mut y = Elem :: new ( x) ;
115- y. compress :: < D > ( ) ;
116- y. decompress :: < D > ( ) ;
122+ let compressed = Compress :: < D > :: compress ( Elem :: new ( x) ) ;
123+ let decompressed = Decompress :: < D > :: decompress ( compressed) ;
117124
118- let mut error = i32:: from ( y . 0 ) - i32:: from ( x) + QI32 ;
125+ let mut error = i32:: from ( decompressed . 0 ) - i32:: from ( x) + QI32 ;
119126 if error > ( QI32 - 1 ) / 2 {
120127 error -= QI32 ;
121128 }
@@ -131,19 +138,17 @@ pub(crate) mod tests {
131138
132139 fn decompression_compression_equality < D : CompressionFactor > ( ) {
133140 for x in 0 ..( 1 << D :: USIZE ) {
134- let mut y = Elem :: new ( x) ;
135- y. decompress :: < D > ( ) ;
136- y. compress :: < D > ( ) ;
141+ let decompressed = Decompress :: < D > :: decompress ( FixedWidthInt :: < BaseField , D > :: new ( x) ) ;
142+ let recompressed = Compress :: < D > :: compress ( decompressed) ;
137143
138- assert_eq ! ( y . 0 , x, "failed for x: {}, D: {}" , x, D :: USIZE ) ;
144+ assert_eq ! ( recompressed . value ( ) , x, "failed for x: {}, D: {}" , x, D :: USIZE ) ;
139145 }
140146 }
141147
142148 fn decompress_KAT < D : CompressionFactor > ( ) {
143149 for y in 0 ..( 1 << D :: USIZE ) {
144150 let x_expected = rational_decompress :: < D > ( y) ;
145- let mut x_actual = Elem :: new ( y) ;
146- x_actual. decompress :: < D > ( ) ;
151+ let x_actual = Decompress :: < D > :: decompress ( FixedWidthInt :: < BaseField , D > :: new ( y) ) ;
147152
148153 assert_eq ! ( x_expected, x_actual. 0 ) ;
149154 }
@@ -152,10 +157,9 @@ pub(crate) mod tests {
152157 fn compress_KAT < D : CompressionFactor > ( ) {
153158 for x in 0 ..BaseField :: Q {
154159 let y_expected = rational_compress :: < D > ( x) ;
155- let mut y_actual = Elem :: new ( x) ;
156- y_actual. compress :: < D > ( ) ;
160+ let y_actual = Compress :: < D > :: compress ( Elem :: new ( x) ) ;
157161
158- assert_eq ! ( y_expected, y_actual. 0 , "for x: {}, D: {}" , x, D :: USIZE ) ;
162+ assert_eq ! ( y_expected, y_actual. value ( ) , "for x: {}, D: {}" , x, D :: USIZE ) ;
159163 }
160164 }
161165
0 commit comments