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 , Truncate ,
4+ } ;
55
66// A convenience trait to allow us to associate some constants with a typenum
77pub ( crate ) trait CompressionFactor : EncodingSize {
@@ -22,68 +22,85 @@ where
2222 const DIV_MUL : u64 = ( 1 << T :: DIV_SHIFT ) / BaseField :: QLL ;
2323}
2424
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 ;
25+ /// Compress a prime-field representation into its `Z_{2^D}` fixed-width form.
26+ pub ( crate ) trait Compress < D : CompressionFactor > {
27+ type Output ;
28+ fn compress ( self ) -> Self :: Output ;
2929}
3030
31- impl Compress for Elem {
31+ /// Decompress a `Z_{2^D}` fixed-width representation back into the prime field.
32+ pub ( crate ) trait Decompress < D : CompressionFactor > {
33+ type Output ;
34+ fn decompress ( self ) -> Self :: Output ;
35+ }
36+
37+ impl < D : CompressionFactor > Compress < D > for Elem {
38+ type Output = FixedWidthInt < BaseField , D > ;
39+
3240 // Equation 4.5: Compress_d(x) = round((2^d / q) x)
3341 //
3442 // Here and in decompression, we leverage the following facts:
3543 //
3644 // round(a / b) = floor((a + b/2) / b)
3745 // a / q ~= (a * x) >> s where x >> s ~= 1/q
38- fn compress < D : CompressionFactor > ( & mut self ) -> & Self {
46+ fn compress ( self ) -> FixedWidthInt < BaseField , D > {
3947 const Q_HALF : u64 = ( BaseField :: QLL + 1 ) >> 1 ;
4048 let x = u64:: from ( self . 0 ) ;
4149 let y = ( ( ( x << D :: USIZE ) + Q_HALF ) * D :: DIV_MUL ) >> D :: DIV_SHIFT ;
42- self . 0 = u16:: truncate ( y) & D :: MASK ;
43- self
50+ FixedWidthInt :: new ( u16:: truncate ( y) & D :: MASK )
4451 }
52+ }
53+
54+ impl < D : CompressionFactor > Decompress < D > for FixedWidthInt < BaseField , D > {
55+ type Output = Elem ;
4556
4657 // 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 ) ;
58+ fn decompress ( self ) -> Elem {
59+ let x = u32:: from ( self . value ( ) ) ;
4960 let y = ( ( x * BaseField :: QL ) + D :: POW2_HALF ) >> D :: USIZE ;
50- self . 0 = Truncate :: truncate ( y) ;
51- self
61+ Elem :: new ( Truncate :: truncate ( y) )
5262 }
5363}
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- }
5964
60- self
65+ impl < D : CompressionFactor > Compress < D > for Polynomial {
66+ type Output = FixedWidthPolynomial < BaseField , D > ;
67+
68+ fn compress ( self ) -> FixedWidthPolynomial < BaseField , D > {
69+ FixedWidthPolynomial :: new ( self . 0 . into_iter ( ) . map ( Compress :: < D > :: compress) . collect ( ) )
6170 }
71+ }
6272
63- fn decompress < D : CompressionFactor > ( & mut self ) -> & Self {
64- for x in & mut self . 0 {
65- x. decompress :: < D > ( ) ;
66- }
73+ impl < D : CompressionFactor > Decompress < D > for FixedWidthPolynomial < BaseField , D > {
74+ type Output = Polynomial ;
6775
68- self
76+ fn decompress ( self ) -> Polynomial {
77+ Polynomial :: new (
78+ self . 0
79+ . into_iter ( )
80+ . map ( Decompress :: < D > :: decompress)
81+ . collect ( ) ,
82+ )
6983 }
7084}
7185
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- }
86+ impl < K : ArraySize , D : CompressionFactor > Compress < D > for Vector < K > {
87+ type Output = FixedWidthVector < BaseField , K , D > ;
7788
78- self
89+ fn compress ( self ) -> FixedWidthVector < BaseField , K , D > {
90+ FixedWidthVector :: new ( self . 0 . into_iter ( ) . map ( Compress :: < D > :: compress) . collect ( ) )
7991 }
92+ }
8093
81- fn decompress < D : CompressionFactor > ( & mut self ) -> & Self {
82- for x in & mut self . 0 {
83- x. decompress :: < D > ( ) ;
84- }
94+ impl < K : ArraySize , D : CompressionFactor > Decompress < D > for FixedWidthVector < BaseField , K , D > {
95+ type Output = Vector < K > ;
8596
86- self
97+ fn decompress ( self ) -> Vector < K > {
98+ Vector :: new (
99+ self . 0
100+ . into_iter ( )
101+ . map ( Decompress :: < D > :: decompress)
102+ . collect ( ) ,
103+ )
87104 }
88105}
89106
@@ -111,11 +128,10 @@ pub(crate) mod tests {
111128 let error_threshold = i32:: from ( Ratio :: new ( BaseField :: Q , 1 << D :: USIZE ) . to_integer ( ) ) ;
112129
113130 for x in 0 ..BaseField :: Q {
114- let mut y = Elem :: new ( x) ;
115- y. compress :: < D > ( ) ;
116- y. decompress :: < D > ( ) ;
131+ let compressed = Compress :: < D > :: compress ( Elem :: new ( x) ) ;
132+ let decompressed = Decompress :: < D > :: decompress ( compressed) ;
117133
118- let mut error = i32:: from ( y . 0 ) - i32:: from ( x) + QI32 ;
134+ let mut error = i32:: from ( decompressed . 0 ) - i32:: from ( x) + QI32 ;
119135 if error > ( QI32 - 1 ) / 2 {
120136 error -= QI32 ;
121137 }
@@ -131,19 +147,23 @@ pub(crate) mod tests {
131147
132148 fn decompression_compression_equality < D : CompressionFactor > ( ) {
133149 for x in 0 ..( 1 << D :: USIZE ) {
134- let mut y = Elem :: new ( x) ;
135- y. decompress :: < D > ( ) ;
136- y. compress :: < D > ( ) ;
137-
138- assert_eq ! ( y. 0 , x, "failed for x: {}, D: {}" , x, D :: USIZE ) ;
150+ let decompressed = Decompress :: < D > :: decompress ( FixedWidthInt :: < BaseField , D > :: new ( x) ) ;
151+ let recompressed = Compress :: < D > :: compress ( decompressed) ;
152+
153+ assert_eq ! (
154+ recompressed. value( ) ,
155+ x,
156+ "failed for x: {}, D: {}" ,
157+ x,
158+ D :: USIZE
159+ ) ;
139160 }
140161 }
141162
142163 fn decompress_KAT < D : CompressionFactor > ( ) {
143164 for y in 0 ..( 1 << D :: USIZE ) {
144165 let x_expected = rational_decompress :: < D > ( y) ;
145- let mut x_actual = Elem :: new ( y) ;
146- x_actual. decompress :: < D > ( ) ;
166+ let x_actual = Decompress :: < D > :: decompress ( FixedWidthInt :: < BaseField , D > :: new ( y) ) ;
147167
148168 assert_eq ! ( x_expected, x_actual. 0 ) ;
149169 }
@@ -152,10 +172,15 @@ pub(crate) mod tests {
152172 fn compress_KAT < D : CompressionFactor > ( ) {
153173 for x in 0 ..BaseField :: Q {
154174 let y_expected = rational_compress :: < D > ( x) ;
155- let mut y_actual = Elem :: new ( x) ;
156- y_actual. compress :: < D > ( ) ;
175+ let y_actual = Compress :: < D > :: compress ( Elem :: new ( x) ) ;
157176
158- assert_eq ! ( y_expected, y_actual. 0 , "for x: {}, D: {}" , x, D :: USIZE ) ;
177+ assert_eq ! (
178+ y_expected,
179+ y_actual. value( ) ,
180+ "for x: {}, D: {}" ,
181+ x,
182+ D :: USIZE
183+ ) ;
159184 }
160185 }
161186
0 commit comments