Mantid
Loading...
Searching...
No Matches
byte_rel_comp.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7/*
8C
9C Compression of 32bit integer data into byte-relative format
10C
11C Each integer is stored relative to the previous value in byte form.The first
12C is relative to zero. This allows for numbers to be within + or - 127 of
13C the previous value. Where a 32bit integer cannot be expressed in this way a
14C special byte code is used (-128) and the full 32bit integer stored elsewhere.
15C The final space used is (NIN-1)/4 +1 + NEXTRA longwords, where NEXTRA is the
16C number of extra longwords used in giving absolute values.
17C
18*/
19#include <iostream>
20#include <stdexcept>
21
22#include "byte_rel_comp.h"
23
24#define LARGE_NUMBER 1073741824
25
26#define FAILURE 1
27#define SUCCESS 0
28
29// We aren't going to EVER change this code - so let's ignore the warnings.
30#if defined(__GNUC__) && !(defined(__INTEL_COMPILER))
31#pragma GCC diagnostic ignored "-Wconversion"
32#elif defined(_WIN32)
33#pragma warning(disable : 4100)
34#endif
35
36int byte_rel_comp(const int *data_in, int n_in, char *data_out, int max_out, int &n_out) {
37 int i, icurrent, irel;
38 union {
39 int i;
40 char c[4];
41 } byte_pack;
42 if (n_in <= 0) {
43 throw std::runtime_error("byte rel comp error: nin <= 0");
44 }
45 if (max_out <= n_in) {
46 throw std::runtime_error("byte rel comp error: nin <= 0");
47 }
48 n_out = 0;
49 icurrent = 0;
50 for (i = 0; i < n_in; i++) {
51
52 // Trap out ridiculously large numbers. They could cause problems in
53 // subtraction,
54 // so force them to be stored absolutely
55 if ((data_in[i] > LARGE_NUMBER) || (data_in[i] < -LARGE_NUMBER) || (icurrent > LARGE_NUMBER) ||
56 (icurrent < -LARGE_NUMBER)) {
57 irel = 128; // Force absolute mode
58 } else {
59 irel = data_in[i] - icurrent; // Calc relative offset
60 }
61 // If small put it in a byte
62 if ((irel <= 127) && (irel >= -127)) {
63 if (n_out > max_out) {
64 throw std::runtime_error("byte rel comp error: nin <= 0");
65 }
66 data_out[n_out] = irel; // Pack relative byte
67 n_out++;
68 } else {
69 // Otherwise put marker in byte followed by packed 32bit integer
70 if (n_out + 4 >= max_out) {
71 throw std::runtime_error("byte rel comp error: nin <= 0");
72 }
73 data_out[n_out] = -128; // pack marker
74 byte_pack.i = data_in[i];
75 data_out[n_out + 1] = byte_pack.c[0];
76 data_out[n_out + 2] = byte_pack.c[1];
77 data_out[n_out + 3] = byte_pack.c[2];
78 data_out[n_out + 4] = byte_pack.c[3];
79 n_out += 5;
80 }
81 icurrent = data_in[i];
82 }
83 return SUCCESS;
84}
85
86/*
87C
88C Expansion of byte-relative format into 32bit format
89C
90C Each integer is stored relative to the previous value in byte form.The first
91C is relative to zero. This allows for numbers to be within + or - 127 of
92C the previous value. Where a 32bit integer cannot be expressed in this way a
93C special byte code is used (-128) and the full 32bit integer stored elsewhere.
94C The final space used is (NIN-1)/4 +1 + NEXTRA longwords, where NEXTRA is the
95C number of extra longwords used in giving absolute values.
96C
97C
98C Type definitions
99C Passed parameters
100 INTEGER NIN
101 BYTE INDATA(NIN)
102C Array of NIN compressed bytes
103 INTEGER NFROM
104C pass back data from this 32bit word onwards
105C
106 INTEGER NOUT
107C Number of 32bit words expected
108 INTEGER OUTDATA(NOUT)
109C outgoing expanded data
110 INTEGER ISTATUS
111C Status return
112C =1 no problems!
113C =3 NOUT .lt.NIN/5
114C =2 NIN .le.0
115C =4 NOUT .gt.NIN
116C =6 number of channels lt NOUT
117*/
118// n_from is zero based
119int byte_rel_expn(const char *data_in, int n_in, int n_from, int *data_out, int n_out) {
120 int i, j;
121 union {
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 throw std::runtime_error("byte rel comp error: nin <= 0");
128 }
129 if (n_out + n_from > n_in) {
130 throw std::runtime_error("byte rel comp error: nin <= 0");
131 }
132 // Set initial absolute value to zero and channel counter to zero
133 byte_pack.i = 0;
134 j = 0;
135 // Loop over all expected 32bit integers
136 for (i = 0; i < n_from + n_out; i++) {
137 if (j >= n_in) {
138 throw std::runtime_error("byte rel comp error: nin <= 0");
139 }
140 // if number is contained in a byte
141 if (data_in[j] != -128) {
142 // add in offset to base
143 byte_pack.i += data_in[j];
144 j++;
145 } else {
146 // Else skip marker and pick up new absolute value
147 // check there are enough bytes
148 if (j + 4 >= n_in) {
149 throw std::runtime_error("byte rel comp error: nin <= 0");
150 }
151 // unpack 4 bytes
152 byte_pack.c[0] = data_in[j + 1];
153 byte_pack.c[1] = data_in[j + 2];
154 byte_pack.c[2] = data_in[j + 3];
155 byte_pack.c[3] = data_in[j + 4];
156 // CALL VAX_TO_LOCAL_INTS(ITEMP, 1)
157 j += 5;
158 }
159 // update current value
160 if (i >= n_from) {
161 data_out[i - n_from] = byte_pack.i;
162 }
163 }
164
165 // expansion OK, but excessive number of bytes given to the routine
166 if (n_out < n_in / 5) {
167 std::cerr << "byte rel expn: excessive bytes\n";
168 }
169 return SUCCESS;
170}
int byte_rel_expn(const char *data_in, int n_in, int n_from, int *data_out, int n_out)
#define LARGE_NUMBER
#define SUCCESS
int byte_rel_comp(const int *data_in, int n_in, char *data_out, int max_out, int &n_out)