GSE++ library: reading and writing GSE waveforms
gsexx_cm6.cc
Go to the documentation of this file.
1 
39 #define TF_GSEXX_CM6_CC_VERSION \
40  "TF_GSEXX_CM6_CC V1.1 "
41 #define TF_GSEXX_CM6_CC_CVSID \
42  "$Id$"
43 
44 #include <gsexx.h>
45 #include "gsexx_TDAT2.h"
46 #include <cmath>
47 
48 namespace GSE2 {
49 namespace waveform {
50 
60 namespace CM6 {
61 
63 
77 std::string encode(const intT& invalue)
78 {
79  // string variable to store return value
80  std::string retval;
81 
82 // The original version of the core of this function was coded by Stefan
83 // Stange. The code (compress_6b) can be found in gse_functions.c in his
84 // library. Here is the original comment by Stefan Stange:
85 /*********************************************************************
86  Function: compress_6b
87  This routine computes the 6Byte encoding of integer data according
88  GSE2.0 based on cmprs6.f in CODECO by Urs Kradolfer. Again, here we
89  can cope with consecutive chunks of a data series.
90  Input is the data series (integer) and the # of samples. The character
91  representation of the data is successively stored to the dynamic
92  character buffer written by Andreas Greve.
93  Attention: Clipping is at 2**27 - 1 although it looks like 2**28 -1
94  in the FORTRAN-Code.
95 
96  St. Stange, 28.4.1998
97 *********************************************************************/
98 
99  // copy of value to be manipulated
100  intT value=invalue;
101  // this defines the value to character mapping
102  char achar[] =
103  " +-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
104 
105  // some powers of 2
106  // 2**5 2**10 2**15 2**20 2**25 2**27
107  long expo_2[] = { 0, 32, 1024, 32768, 1048576, 33554432, 134217728 };
108 
109  // some powers of 2 minus 1
110  // -1 + 2**5 2**10 2**15 2**20 2**25
111  long expo_2m1_o[] = { 01, 037, 01777, 077777, 03777777, 0177777777 };
112 
113  // internal values
114  int nflag;
115  int mflag = 32;
116  long jc;
117  int case_expo;
118 
119  nflag = 1;
120  // convert sign
121  if (value < 0 )
122  { nflag += 16; value = -value; }
123 
124  // clip at 2**27 -1
125  // value = (value >= expo_2[6]) ? expo_2[6] - 1 : value;
126  // the original code clipped at 2**27 -1
127  // we consider a number that large to be illegal
128  if (value >= expo_2[6])
129  {
130  std::cerr << "ERROR (CM6::encode): "
131  << "sample value exceeds largest value which can be handled\n"
132  << "Error is triggered by absolute value being ";
133  std::cerr.setf(std::ios_base::hex,std::ios_base::basefield);
134  std::cerr << "0x0" << value << ">=" << "0x0" << expo_2[6] << std::endl;
135  std::cerr << "The input value passed to the encoder is "
136  << "0x0" << invalue << std::endl;
137  throw Terror("ERROR (CM6::encode): illegal value");
138  }
139 
140  // compute the exponent base 2
141  std::frexp (double(value), &case_expo);
142  // and reduce by integer division
143  case_expo = case_expo/5;
144 
145  // check value
146  if (case_expo > 5 || case_expo < 0)
147  {
148  std::cerr << "ERROR (CM6::encode): exponent is "
149  << case_expo << std::endl;
150  std::cerr << "ERROR (CM6::encode): sample value is is "
151  << invalue << std::endl;
152  throw Terror("ERROR (CM6::encode): illegal exponent");
153  }
154 
155  for ( ; case_expo > 0; case_expo--)
156  {
157  // create one character per turn
158  jc = value/expo_2[case_expo] + nflag + mflag;
159  /*if (jc > 64 || jc < 1) return jc;*/
160  retval+=achar[jc];
161  value = value & expo_2m1_o[case_expo];
162  nflag = 1;
163  }
164 
165  // one character to go
166  jc = value + nflag;
167  retval+=achar[jc];
168 
169  return(retval);
170 }
171 
172 /*----------------------------------------------------------------------*/
173 
175 
191 intT decode(std::istream& is)
192 {
193 // The original version of the core of this function was coded by Stefan
194 // Stange. The code (decomp_6b) can be found in gse_functions.c in his
195 // library. Here is the original comment by Stefan Stange:
196 
197 /*********************************************************************
198 * Function: decomp_6b
199 * This routine evolves the data series from the 6Byte encoding according
200 * GSE2.0 based on dcomp6.f in CODECO by Urs Kradolfer.
201 * Input is the character representation (meaning the file pointer to it),
202 * the number of samples to be expected and the pointer to the data.
203 * Output is the data series in LONG (has to be allocated elsewhere!).
204 * The GSE file must be opened and positioned to or before the "DAT2" line.
205 * Returns actual # of samples or -1 as error code.
206 * Calls no other routines.
207 * St. Stange, 1.10.1998 , verified for PC-byte-sex 11.4.2001
208 *********************************************************************/
209  static int ichar[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
210  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,3,4,5,6,7,
211  8,9,10,11,0,0,0,0,0,0,0,12,13,14,15,16,17,18,19,20,21,22,
212  23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,0,0,0,0,0,0,
213  38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,
214  57,58,59,60,61,62,63,0,0,0,0,0,0},/*1 more than in FORTRAN*/
215  isign=020, ioflow=040, mask1=017, mask2=037, m127=0177;
216 
217  int k, inn, jsign=0, joflow=0;
218  char inchar; // character just read from stream
219  intT retval; // decoded samples
220 
221  // read next
222  is.get(inchar);
223  while (inchar == '\n') { is.get(inchar); }
224  if (isspace(inchar))
225  throw Terror("ERROR (CM6::decode): illegal whitespace");
226  if (is.eof())
227  throw Terror("ERROR (CM6::decode): illegal end of file");
228 
229  /* get ascii code of input character, strip off any higher bits
230  (don't know whether it does what it says) and get number representation */
231 
232  k = int(int(inchar) & m127);
233  inn = ichar[k];
234 
235  jsign = (inn & isign); /* get sign bit */
236  joflow = (inn & ioflow); /* get continuation bit if any */
237  retval = (long)(inn & mask1); /* remove dispensable bits and store */
238 
239  while (joflow != 0) /* loop over other bytes in sample */
240  {
241  retval <<= 5; /* multiply with 32 for next byte */
242 
243  // read next
244  is.get(inchar);
245  while (inchar == '\n') { is.get(inchar); }
246  if (isspace(inchar))
247  throw Terror("ERROR (CM6::decode): illegal whitespace");
248  if (is.eof())
249  throw Terror("ERROR (CM6::decode): illegal end of file");
250 
251  /* now the same procedure as above */
252  k = int(int(inchar) & m127);
253  inn = ichar[k];
254  joflow = (inn & ioflow); /* get continuation bit if any */
255  retval = retval + intT(inn & mask2); /* remove bits and store */
256 
257  } /* finish up sample if there is no further continuation bit */
258 
259  if (jsign != 0) retval = -retval; /* evaluate sign bit */
260 
261  return(retval);
262 } // decode
263 
264 } // namespace CM6
265 
266 } // namespace waveform
267 } // namespace GSE2
268 
269 /* ----- END OF gsexx_cm6.cc ----- */
GSE++ library: read and write GSE waveform data (prototypes).
int intT
All GSE2 waveform data is based on 4 byte integers.
Definition: gsexx.h:89
std::string encode(const intT &invalue)
CM6 subformat encoding function.
Definition: gsexx_cm6.cc:77
All stuff defined by the GSE2 standard.
helper function prototypes for TDAT2 (prototypes)
Base class for all exceptions in this module.
Definition: gsexx.h:68
intT decode(std::istream &is)
CM6 subformat decoding function.
Definition: gsexx_cm6.cc:191