1 static void _t2(rev_fwd_xform, Int, DIMS)(Int* p);
2 
3 /* private functions ------------------------------------------------------- */
4 
5 /* reversible forward lifting transform of 4-vector */
6 static void
_t1(rev_fwd_lift,Int)7 _t1(rev_fwd_lift, Int)(Int* p, uint s)
8 {
9   Int x, y, z, w;
10   x = *p; p += s;
11   y = *p; p += s;
12   z = *p; p += s;
13   w = *p; p += s;
14 
15   /*
16   ** high-order Lorenzo transform
17   ** ( 1  0  0  0) (x)
18   ** (-1  1  0  0) (y)
19   ** ( 1 -2  1  0) (z)
20   ** (-1  3 -3  1) (w)
21   */
22   w -= z; z -= y; y -= x;
23   w -= z; z -= y;
24   w -= z;
25 
26   p -= s; *p = w;
27   p -= s; *p = z;
28   p -= s; *p = y;
29   p -= s; *p = x;
30 }
31 
32 /* return precision required to encode block reversibly */
33 static uint
_t1(rev_precision,UInt)34 _t1(rev_precision, UInt)(const UInt* block, uint n)
35 {
36   uint p = 0;
37   uint s;
38   /* compute bitwise OR of all values */
39   UInt m = 0;
40   while (n--)
41     m |= *block++;
42   /* count trailing zeros via binary search */
43   for (s = CHAR_BIT * (uint)sizeof(UInt); m; s /= 2)
44     if ((UInt)(m << (s - 1))) {
45       m <<= s - 1;
46       m <<= 1;
47       p += s;
48     }
49   return p;
50 }
51 
52 /* encode block of integers using reversible algorithm */
53 static uint
_t2(rev_encode_block,Int,DIMS)54 _t2(rev_encode_block, Int, DIMS)(bitstream* stream, int minbits, int maxbits, int maxprec, Int* iblock)
55 {
56   int bits = PBITS;
57   int prec;
58   cache_align_(UInt ublock[BLOCK_SIZE]);
59   /* perform decorrelating transform */
60   _t2(rev_fwd_xform, Int, DIMS)(iblock);
61   /* reorder signed coefficients and convert to unsigned integer */
62   _t1(fwd_order, Int)(ublock, iblock, PERM, BLOCK_SIZE);
63   /* determine and encode number of significant bits */
64   prec = _t1(rev_precision, UInt)(ublock, BLOCK_SIZE);
65   prec = MIN(prec, maxprec);
66   prec = MAX(prec, 1);
67   stream_write_bits(stream, prec - 1, PBITS);
68   /* encode integer coefficients */
69   if (BLOCK_SIZE <= 64)
70     bits += _t1(encode_ints, UInt)(stream, maxbits - bits, prec, ublock, BLOCK_SIZE);
71   else
72     bits += _t1(encode_many_ints, UInt)(stream, maxbits - bits, prec, ublock, BLOCK_SIZE);
73   /* write at least minbits bits by padding with zeros */
74   if (bits < minbits) {
75     stream_pad(stream, minbits - bits);
76     bits = minbits;
77   }
78   return bits;
79 }
80