ICP  1
byte_rel_comp.cpp
Go to the documentation of this file.
1 /*
2 C
3 C Compression of 32bit integer data into byte-relative format
4 C
5 C Each integer is stored relative to the previous value in byte form.The first
6 C is relative to zero. This allows for numbers to be within + or - 127 of
7 C the previous value. Where a 32bit integer cannot be expressed in this way a
8 C special byte code is used (-128) and the full 32bit integer stored elsewhere.
9 C The final space used is (NIN-1)/4 +1 + NEXTRA longwords, where NEXTRA is the
10 C number of extra longwords used in giving absolute values.
11 C
12 */
13 #include "stdafx.h"
14 #include "DAEstatus.h"
15 #include "isisvme_types.h"
16 #include "byte_rel_comp.h"
17 
18 #define LARGE_NUMBER 1073741824
19 
20 int byte_rel_comp(int* data_in, int n_in, char* data_out, int max_out, int& n_out, DAEstatus& status)
21 {
22  int i, icurrent, irel;
23  union
24  {
25  int i;
26  char c[4];
27  } byte_pack;
28  if (n_in <= 0)
29  {
30  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: nin <= 0");
31  return DAEstatus::Failure;
32  }
33  if (max_out <= n_in)
34  {
35  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: nin <= 0");
36  return DAEstatus::Failure;
37  }
38  n_out = 0;
39  icurrent = 0;
40  for(i=0; i<n_in; i++)
41  {
42 
43 // Trap out ridiculously large numbers. They could cause problems in subtraction,
44 // so force them to be stored absolutely
45  if ( (data_in[i] > LARGE_NUMBER) || (data_in[i] < -LARGE_NUMBER) || (icurrent > LARGE_NUMBER) || (icurrent < -LARGE_NUMBER) )
46  {
47  irel = 128; // Force absolute mode
48  }
49  else
50  {
51  irel = data_in[i] - icurrent; // Calc relative offset
52  }
53 // If small put it in a byte
54  if ( (irel <= 127) && (irel >= -127) )
55  {
56  if (n_out >= max_out){
57  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: n_out >= max_out");
58  return DAEstatus::Failure;
59  }
60  data_out[n_out] = static_cast<char>(irel); // Pack relative byte
61  n_out++;
62  }
63  else
64  {
65 // Otherwise put marker in byte followed by packed 32bit integer
66  if ((n_out + 5) >= max_out)
67  {
68  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: n_out + 5 >= max_out");
69  return DAEstatus::Failure;
70  }
71  data_out[n_out] = -128; // pack marker
72  byte_pack.i = data_in[i];
73  data_out[n_out+1] = byte_pack.c[0];
74  data_out[n_out+2] = byte_pack.c[1];
75  data_out[n_out+3] = byte_pack.c[2];
76  data_out[n_out+4] = byte_pack.c[3];
77  n_out += 5;
78  }
79  icurrent = data_in[i];
80  }
81  return DAEstatus::Success;
82 }
83 
84 /*
85 C
86 C Expansion of byte-relative format into 32bit format
87 C
88 C Each integer is stored relative to the previous value in byte form.The first
89 C is relative to zero. This allows for numbers to be within + or - 127 of
90 C the previous value. Where a 32bit integer cannot be expressed in this way a
91 C special byte code is used (-128) and the full 32bit integer stored elsewhere.
92 C The final space used is (NIN-1)/4 +1 + NEXTRA longwords, where NEXTRA is the
93 C number of extra longwords used in giving absolute values.
94 C
95 C
96 C Type definitions
97 C Passed parameters
98  INTEGER NIN
99  BYTE INDATA(NIN)
100 C Array of NIN compressed bytes
101  INTEGER NFROM
102 C pass back data from this 32bit word onwards
103 C
104  INTEGER NOUT
105 C Number of 32bit words expected
106  INTEGER OUTDATA(NOUT)
107 C outgoing expanded data
108  INTEGER ISTATUS
109 C Status return
110 C =1 no problems!
111 C =3 NOUT .lt.NIN/5
112 C =2 NIN .le.0
113 C =4 NOUT .gt.NIN
114 C =6 number of channels lt NOUT
115 */
116 //n_from is zero based
117 int byte_rel_expn(char* data_in, int n_in, int n_from, int* data_out, int n_out, DAEstatus& status)
118 {
119  int i, j;
120  union
121  {
122  int i;
123  char c[4];
124  } byte_pack;
125 // First check no slip-ups in the input parameters
126  if (n_in <= 0)
127  {
128  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: nin <= 0");
129  return DAEstatus::Failure;
130  }
131  if (n_out + n_from > n_in)
132  {
133  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: nin <= 0");
134  return DAEstatus::Failure;
135  }
136 // Set initial absolute value to zero and channel counter to zero
137  byte_pack.i = 0;
138  j = 0;
139 // Loop over all expected 32bit integers
140  for(i=0; i< n_from + n_out; i++)
141  {
142  if (j >= n_in)
143  {
144  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: nin <= 0");
145  return DAEstatus::Failure;
146  }
147 // if number is contained in a byte
148  if (data_in[j] != -128)
149  {
150 // add in offset to base
151  byte_pack.i += data_in[j];
152  j++;
153  }
154  else
155  {
156 // Else skip marker and pick up new absolute value
157 // check there are enough bytes
158  if (j+4 >= n_in)
159  {
160  status.add(FAC_DAE, SEV_ERROR, ERRTYPE_OUTOFMEM, "byte rel comp error: nin <= 0");
161  return DAEstatus::Failure;
162  }
163 // unpack 4 bytes
164  byte_pack.c[0] = data_in[j+1];
165  byte_pack.c[1] = data_in[j+2];
166  byte_pack.c[2] = data_in[j+3];
167  byte_pack.c[3] = data_in[j+4];
168 // CALL VAX_TO_LOCAL_INTS(ITEMP, 1)
169  j += 5;
170  }
171 // update current value
172  if (i >= n_from)
173  {
174  data_out[i-n_from] = byte_pack.i;
175  }
176  }
177 
178 // expansion OK, but excessive number of bytes given to the routine
179  if (n_out < n_in / 5)
180  {
181  status.addInfo(FAC_DAE, "byte rel expn: excessive bytes");
182  }
183  return DAEstatus::Success;
184 }
185 
#define LARGE_NUMBER
#define FAC_DAE
#define ERRTYPE_OUTOFMEM
int byte_rel_comp(int *data_in, int n_in, char *data_out, int max_out, int &n_out, DAEstatus &status)
static const int Failure
Definition: DAEstatus.h:141
int add(DAEstatus &dstatus, bool clear)
Definition: DAEstatus.cpp:131
static const int Success
Definition: DAEstatus.h:140
int byte_rel_expn(char *data_in, int n_in, int n_from, int *data_out, int n_out, DAEstatus &status)
#define SEV_ERROR
int addInfo(int facility, const std::string &text)
Definition: DAEstatus.cpp:86