LevelS C++ support library  3.82
compress_utils.h
Go to the documentation of this file.
1 /*
2  * This file is part of libcxxsupport.
3  *
4  * libcxxsupport is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * libcxxsupport is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with libcxxsupport; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
21  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
22  * (DLR).
23  */
24 
25 /*! \file compress_utils.h
26  * Support for compression of integer arrays.
27  *
28  * Copyright (C) 2013-2015 Max-Planck-Society
29  * \author Martin Reinecke
30  */
31 
32 #ifndef PLANCK_COMPRESS_UTILS_H
33 #define PLANCK_COMPRESS_UTILS_H
34 
35 #include <limits>
36 #include <vector>
37 #include <iterator>
38 
39 #include "datatypes.h"
40 #include "error_handling.h"
41 #include "math_utils.h"
42 
43 class obitstream
44  {
45  private:
46  std::vector<uint8> data;
47  tsize bitpos;
48 
49  template<typename T> void put_internal (const T &val, uint8 bits)
50  {
51  int bitsleft = 8-(bitpos&7);
52  if (bitsleft==8) data.push_back(0);
53  if (bits<=bitsleft) // wbits==bits
54  {
55  data.back() |= ((val&((T(1)<<bits)-1))<<(bitsleft-bits));
56  bitpos+=bits;
57  }
58  else // wbits==bitsleft
59  {
60  data.back() |= ((val>>(bits-bitsleft))&((1<<bitsleft)-1));
61  bitpos+=bitsleft;
62  put_internal(val,bits-bitsleft);
63  }
64  }
65 
66  public:
67  obitstream() : bitpos(0) {}
68 
69  template<typename T> void put (const T &val, uint8 bits)
70  {
71  if (bits==0) return;
72  planck_assert(bits<=(sizeof(T)<<3),"too many bits for this data type");
73 // planck_assert(val-(val&((T(1)<<bits)-1))==0,"value has too many bits");
74  put_internal(val,bits);
75  }
76 
77  const std::vector<uint8> &state() const
78  { return data; }
79  };
80 
81 class ibitstream
82  {
83  private:
84  const std::vector<uint8> data;
85  tsize bitpos;
86 
87  template<typename T> void get_internal (T &val, int bits)
88  {
89  int bitsleft = 8-(bitpos&7);
90  if (bits<=bitsleft)
91  {
92  val |= ((data[bitpos>>3]>>(bitsleft-bits))&((1<<bits)-1));
93  bitpos+=bits;
94  }
95  else
96  {
97  val |= T((data[bitpos>>3])&((1<<bitsleft)-1))<<(bits-bitsleft);
98  bitpos+=bitsleft;
99  get_internal(val,bits-bitsleft);
100  }
101  }
102  public:
103  ibitstream(const std::vector<uint8> &indata) : data(indata), bitpos(0) {}
104 
105  template<typename T> T get (uint8 bits)
106  {
107  if (bits==0) return T(0);
108  planck_assert(bits<=(sizeof(T)<<3),"too many bits for this data type");
109  planck_assert((bitpos+bits)<=8*data.size(),"reading past end of stream");
110  T res=T(0);
111  get_internal(res,bits);
112  return res;
113  }
114  };
115 
116 template<typename T,bool> struct notNegativeHelper__
117  { notNegativeHelper__(const T &) {} };
118 template<typename T> struct notNegativeHelper__<T,true>
119  {
120  notNegativeHelper__(const T &val)
121  { planck_assert(val>=T(0),"numbers must be nonnegative");}
122  };
123 template<typename T> void assertNotNegative(const T &val)
124  { notNegativeHelper__<T,std::numeric_limits<T>::is_signed> dummy(val); }
125 
126 template<typename Iter> void interpol_encode2 (Iter l, Iter r, obitstream &obs,
127  int shift)
128  {
129  if (r-l<=1) return;
130  typedef std::iterator_traits<Iter> traits;
131  typedef typename traits::value_type T;
132 
133  Iter m=l+(r-l)/2;
134  T nval = ((*r-*l)>>shift) - (r-l) + 1;
135  if (nval<=1) return;
136 
137  uint8 nb = 1+ilog2(nval-1);
138  T val = ((*m)>>shift)-(((*l)>>shift)+(m-l));
139  T nshort=(T(1)<<nb)-nval;
140 #if 0
141  // optional rotation
142  T nrot=nval-(nshort>>1);
143  if (val>=nrot)
144  val-=nrot;
145  else
146  val+=(nval-nrot);
147 #endif
148  if (val<nshort)
149  obs.put(val,nb-1);
150  else
151  obs.put(val+nshort,nb);
152  interpol_encode2(l,m,obs,shift);
153  interpol_encode2(m,r,obs,shift);
154  }
155 
156 template<typename Iter> void interpol_encode (Iter l, Iter r, obitstream &obs)
157  {
158  typedef std::iterator_traits<Iter> traits;
159  typedef typename traits::value_type T;
160 
161  if (l==r) // empty range
162  { obs.put(0,8); return; }
163 
164  assertNotNegative(*l);
165 
166  T combo=*l;
167  for (Iter i=l+1; i!=r; ++i)
168  {
169  planck_assert(*i>*(i-1),"numbers not strictly increasing");
170  combo|=*i;
171  }
172  int shift = trailingZeros(combo);
173  T maxnum=(*(r-1))>>shift;
174  if (T(r-l)>maxnum) maxnum=T(r-l);
175  uint8 maxbits=1+ilog2(maxnum);
176  obs.put(maxbits,8);
177  obs.put(shift,8);
178  obs.put(r-l,maxbits);
179  obs.put((*l)>>shift,maxbits);
180  if (r-l==1) return;
181  obs.put((*(r-1))>>shift,maxbits);
182  interpol_encode2(l,r-1,obs,shift);
183  }
184 
185 template<typename Iter> void interpol_decode2 (Iter l, Iter r, ibitstream &ibs,
186  int shift)
187  {
188  if (r-l<=1) return;
189  typedef std::iterator_traits<Iter> traits;
190  typedef typename traits::value_type T;
191 
192  Iter m=l+(r-l)/2;
193  T nval = ((*r-*l)>>shift) - (r-l) + 1;
194  T val=0;
195 
196  if (nval>1)
197  {
198  uint8 nb = 1+ilog2(nval-1);
199  T nshort=(T(1)<<nb)-nval;
200  val=ibs.get<T>(nb-1);
201  if (val>=nshort)
202  val=(val<<1)+ ibs.get<T>(1) - nshort;
203 #if 0
204  // optional rotation
205  T nrot=nval-(nshort>>1);
206  if (val<(nval-nrot))
207  val+=nrot;
208  else
209  val-=(nval-nrot);
210 #endif
211  }
212  *m=*l+(((m-l)+val)<<shift);
213 
214  interpol_decode2(l,m,ibs,shift);
215  interpol_decode2(m,r,ibs,shift);
216  }
217 
218 template<typename T> void interpol_decode (std::vector<T> &v, ibitstream &ibs)
219  {
220  uint8 maxbits=ibs.get<uint8>(8);
221  if (maxbits==0) { v.clear(); return; }
222  int shift = ibs.get<int>(8);
223  v.resize(ibs.get<tsize>(maxbits));
224  v[0]=ibs.get<T>(maxbits)<<shift;
225  if (v.size()==1) return;
226  v[v.size()-1]=ibs.get<T>(maxbits)<<shift;
227  interpol_decode2(v.begin(),v.end()-1,ibs,shift);
228  }
229 
230 #endif
std::size_t tsize
Definition: datatypes.h:116
int ilog2(I arg)
Definition: math_utils.h:125
#define planck_assert(testval, msg)

Generated on Thu Jul 28 2022 17:32:05 for LevelS C++ support library