File Formats¶
This section documents the structure of Aion binary data files. The files described in this section can be created using the functions:
and loaded into Aion using the functions:
File Header¶
All binary data files use the same header format described in Table 54.
Offset |
Meaning |
Encoding |
---|---|---|
5 - 0 |
Magic Number |
0x49 0x4E 0x45 0x42 0x49 0x4E (ASCII for “INEBIN”) |
6 |
Reserved |
0x00 |
7 |
Matrix Type |
ASCII: “B”, “Z”, “R”, or “C” representing boolean, integer, real, and complex matrices respectively. |
11 - 8 |
Number Rows |
4-byte little endian unsigned integer |
15 - 12 |
Number Columns |
4-byte little endian unsigned integer |
16 - xx |
Matrix Data |
The application specific matrix data |
Boolean Matrix Data Files¶
Boolean matrices are stored in a packed format with one bit per matrix entry. Entries are written in reading order across rows and then by row.
The zero based bit index into the matrix data can be calculated by:
Where \(i _ { index }\) is the bit index into the matrix data associated with a given matrix entry, \(N _ c\) indicates the number of matrix columns, \(r\) represents the one based row number, and \(c\) represents the one based column number.
The byte offset into the file where a given entry is stored can then be determined by:
The bit offset into the byte is given by:
Bit offset 0 represents the least sigificant bit into each byte, bit offset 7 represents the most significant bit into each byte.
The matrix
would create the following binary file described in Table 55.
Offset |
Contents |
Representing |
Meaning |
---|---|---|---|
0 |
0x49 |
“INEBIN” |
File magic number. |
1 |
0x4E |
||
2 |
0x45 |
||
3 |
0x42 |
||
4 |
0x49 |
||
5 |
0x4E |
||
6 |
0x00 |
Reserved |
|
7 |
0x42 |
“B” |
Indicates a boolean matrix. |
8 |
0x03 |
3 |
Number rows |
9 |
0x00 |
||
10 |
0x00 |
||
11 |
0x00 |
||
12 |
0x05 |
5 |
Number columns |
13 |
0x00 |
||
14 |
0x00 |
||
15 |
0x00 |
||
16 |
0x99 |
10011 001 |
Matrix Data |
17 |
0x21 |
10 00010 0 |
Below is sample code that writes a boolean matrix:
bool writeBooleanMatrix(
const char* filename,
unsigned numberRows,
unsigned numberColumns,
const bool* matrix
) {
bool success = true;
std::ofstream f(filename, std::ios::binary);
if (f) {
unsigned i = 6;
std::uint8_t* buffer = new std::uint8_t[4096];
std::memcpy(buffer, "INEBIN", 6);
buffer[i++] = 0;
buffer[i++] = 'B';
buffer[i++] = static_cast<std::uint8_t>(numberRows );
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 24);
buffer[i++] = static_cast<std::uint8_t>(numberColumns );
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 24);
std::uint8_t mask = 1;
unsigned long rowIndex = 0;
std::uint8_t v = 0;
while (success && rowIndex < numberRows) {
unsigned long columnIndex = 0;
while (success && columnIndex < numberColumns) {
if (matrix[numberColumns * rowIndex + columnIndex]) {
v |= mask;
}
mask <<= 1;
if (mask == 0) {
buffer[i++] = v;
v = 0;
mask = 1;
if (i == 4096) {
f.write(reinterpret_cast<const char*>(buffer), 4096);
success = static_cast<bool>(f);
i = 0;
}
}
++columnIndex;
}
++rowIndex;
}
if (success) {
if (mask != 1 || i != 0) {
if (mask != 1) {
buffer[i++] = v;
}
f.write(reinterpret_cast<const char*>(buffer), i);
success = static_cast<bool>(f);
}
}
if (success) {
f.close();
success = static_cast<bool>(f);
} else {
success = false;
}
delete[] buffer;
} else {
success = false;
}
return success;
}
Integer Matrix Data Files¶
Integer matrices are stores in reading order across rows and then by row. Each entry is stored in signed little-endian format with 8-bytes per entry.
The zero based byte offset into the file where a given row/column entry starts is given by:
The matrix
would create the following binary file described in Table 56.
Offset |
Contents |
Representing |
Meaning |
---|---|---|---|
0 |
0x49 |
“INEBIN” |
File magic number. |
1 |
0x4E |
||
2 |
0x45 |
||
3 |
0x42 |
||
4 |
0x49 |
||
5 |
0x4E |
||
6 |
0x00 |
Reserved |
|
7 |
0x42 |
“Z” |
Indicates an integer matrix. |
8 |
0x02 |
2 |
Number rows |
9 |
0x00 |
||
10 |
0x00 |
||
11 |
0x00 |
||
12 |
0x03 |
3 |
Number columns |
13 |
0x00 |
||
14 |
0x00 |
||
15 |
0x00 |
||
16 |
0x01 |
1 |
Matrix Data |
17 |
0x00 |
||
18 |
0x00 |
||
19 |
0x00 |
||
20 |
0x00 |
||
21 |
0x00 |
||
22 |
0x00 |
||
23 |
0x00 |
||
24 |
0x00 |
65536 |
|
25 |
0x00 |
||
26 |
0x01 |
||
27 |
0x00 |
||
28 |
0x00 |
||
29 |
0x00 |
||
30 |
0x00 |
||
31 |
0x00 |
||
32 |
0x08 |
0x0102030405060708 |
|
33 |
0x07 |
||
34 |
0x06 |
||
35 |
0x05 |
||
36 |
0x04 |
||
37 |
0x03 |
||
38 |
0x02 |
||
39 |
0x01 |
||
40 |
0xFF |
-1 |
|
41 |
0xFF |
||
42 |
0xFF |
||
43 |
0xFF |
||
44 |
0xFF |
||
45 |
0xFF |
||
46 |
0xFF |
||
47 |
0xFF |
||
48 |
0x00 |
-65536 |
|
49 |
0x00 |
||
50 |
0xFF |
||
51 |
0xFF |
||
52 |
0xFF |
||
53 |
0xFF |
||
54 |
0xFF |
||
55 |
0xFF |
||
48 |
0x00 |
\(-2^{62}\) |
|
49 |
0x00 |
||
50 |
0x00 |
||
51 |
0x00 |
||
52 |
0x00 |
||
53 |
0x00 |
||
54 |
0x00 |
||
55 |
0xC0 |
The sample code below writes an integer matrix to a binary file.
bool writeIntegerMatrix(
const char* filename,
unsigned numberRows,
unsigned numberColumns,
const long long* matrix
) {
bool success = true;
std::ofstream f(filename, std::ios::binary);
if (f) {
unsigned i = 6;
std::uint8_t* buffer = new std::uint8_t[4096];
std::memcpy(buffer, "INEBIN", 6);
buffer[i++] = 0;
buffer[i++] = 'Z';
buffer[i++] = static_cast<std::uint8_t>(numberRows );
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 24);
buffer[i++] = static_cast<std::uint8_t>(numberColumns );
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 24);
unsigned long rowIndex = 0;
while (success && rowIndex < numberRows) {
unsigned long columnIndex = 0;
while (columnIndex < numberColumns) {
long long v = matrix[numberColumns * rowIndex + columnIndex];
*reinterpret_cast<std::int64_t*>(buffer + i) = v;
i += sizeof(std::int64_t);
if (i >= 4096) {
f.write(reinterpret_cast<const char*>(buffer), 4096);
success = static_cast<bool>(f);
i = 0;
}
++columnIndex;
}
++rowIndex;
}
if (i != 0) {
f.write(reinterpret_cast<const char*>(buffer), i);
success = static_cast<bool>(f);
}
if (success) {
f.close();
success = static_cast<bool>(f);
}
delete[] buffer;
} else {
success = false;
}
return success;
}
Real Matrix Data Files¶
Real matrices are stores in reading order across rows and then by row. Each entry is stored as double precision values conforming with the IEEE 754-2008 standard as shown in Figure 227.
Where the number value is represented by
The zero based byte offset into the file where a given row/column entry starts is given by:
The matrix
would create the following binary file described in Table 57.
Offset |
Contents |
Representing |
Meaning |
---|---|---|---|
0 |
0x49 |
“INEBIN” |
File magic number. |
1 |
0x4E |
||
2 |
0x45 |
||
3 |
0x42 |
||
4 |
0x49 |
||
5 |
0x4E |
||
6 |
0x00 |
Reserved |
|
7 |
0x42 |
“R” |
Indicates a real matrix. |
8 |
0x02 |
2 |
Number rows |
9 |
0x00 |
||
10 |
0x00 |
||
11 |
0x00 |
||
12 |
0x03 |
3 |
Number columns |
13 |
0x00 |
||
14 |
0x00 |
||
15 |
0x00 |
||
16 |
0x00 |
1 |
Matrix Data |
17 |
0x00 |
||
18 |
0x00 |
||
19 |
0x00 |
||
20 |
0x00 |
||
21 |
0x00 |
||
22 |
0xF0 |
||
23 |
0x3F |
||
24 |
0x00 |
1.5 |
|
25 |
0x00 |
||
26 |
0x00 |
||
27 |
0x00 |
||
28 |
0x00 |
||
29 |
0x00 |
||
30 |
0xF8 |
||
31 |
0x3F |
||
32 |
0x00 |
65536 |
|
33 |
0x00 |
||
34 |
0x00 |
||
35 |
0x00 |
||
36 |
0x00 |
||
37 |
0x00 |
||
38 |
0xF0 |
||
39 |
0x40 |
||
40 |
0x00 |
-1 |
|
41 |
0x00 |
||
42 |
0x00 |
||
43 |
0x00 |
||
44 |
0x00 |
||
45 |
0x00 |
||
46 |
0xF0 |
||
47 |
0xBF |
||
48 |
0x00 |
0.375 |
|
49 |
0x00 |
||
50 |
0x00 |
||
51 |
0x00 |
||
52 |
0x00 |
||
53 |
0x00 |
||
54 |
0xD8 |
||
55 |
0x3F |
||
56 |
0x2D |
0.0002 |
|
57 |
0x43 |
||
58 |
0x1C |
||
59 |
0xEB |
||
60 |
0xE2 |
||
61 |
0x36 |
||
62 |
0x2A |
||
63 |
0x3F |
The sample code below writes a real matrix to a binary file.
bool writeRealMatrix(
const char* filename,
unsigned numberRows,
unsigned numberColumns,
const double* matrix
) {
bool success = true;
std::ofstream f(filename, std::ios::binary);
if (f) {
unsigned i = 6;
std::uint8_t* buffer = new std::uint8_t[4096];
std::memcpy(buffer, "INEBIN", 6);
buffer[i++] = 0;
buffer[i++] = 'R';
buffer[i++] = static_cast<std::uint8_t>(numberRows );
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 24);
buffer[i++] = static_cast<std::uint8_t>(numberColumns );
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 24);
unsigned long rowIndex = 0;
while (success && rowIndex < numberRows) {
unsigned long columnIndex = 0;
while (columnIndex < numberColumns) {
double v = matrix[numberColumns * rowIndex + columnIndex];
*reinterpret_cast<double*>(buffer + i) = v;
i += sizeof(double);
if (i >= 4096) {
f.write(reinterpret_cast<const char*>(buffer), 4096);
success = static_cast<bool>(f);
i = 0;
}
++columnIndex;
}
++rowIndex;
}
if (i != 0) {
f.write(reinterpret_cast<const char*>(buffer), i);
success = static_cast<bool>(f);
}
if (success) {
f.close();
success = static_cast<bool>(f);
}
delete[] buffer;
} else {
success = false;
}
return success;
}
Complex Matrix Data Files¶
Complex matrices are stores in reading order across rows and then by row. Each entry is stored as a pair of double precision values conforming with the IEEE 754-2008 standard as shown in Figure 227.
Real values are placed first in the file, followed by complex values.
The zero based byte offset into the file where a given row/column entry starts is given by:
The matrix
would create the following binary file described in Table 58.
Offset |
Contents |
Representing |
Meaning |
---|---|---|---|
0 |
0x49 |
“INEBIN” |
File magic number. |
1 |
0x4E |
||
2 |
0x45 |
||
3 |
0x42 |
||
4 |
0x49 |
||
5 |
0x4E |
||
6 |
0x00 |
Reserved |
|
7 |
0x42 |
“C” |
Indicates a complex matrix. |
8 |
0x02 |
2 |
Number rows |
9 |
0x00 |
||
10 |
0x00 |
||
11 |
0x00 |
||
12 |
0x03 |
3 |
Number columns |
13 |
0x00 |
||
14 |
0x00 |
||
15 |
0x00 |
||
16 |
0x00 |
1 |
Matrix Data |
17 |
0x00 |
||
18 |
0x00 |
||
19 |
0x00 |
||
20 |
0x00 |
||
21 |
0x00 |
||
22 |
0xF0 |
||
23 |
0x3F |
||
24 |
0x00 |
1.5 |
|
25 |
0x00 |
||
26 |
0x00 |
||
27 |
0x00 |
||
28 |
0x00 |
||
29 |
0x00 |
||
30 |
0xF8 |
||
31 |
0x3F |
||
32 |
0x00 |
0.375 |
|
33 |
0x00 |
||
34 |
0x00 |
||
35 |
0x00 |
||
36 |
0x00 |
||
37 |
0x00 |
||
38 |
0xD8 |
||
39 |
0x3F |
||
40 |
0x00 |
1.75 |
|
41 |
0x00 |
||
42 |
0x00 |
||
43 |
0x00 |
||
44 |
0x00 |
||
45 |
0x00 |
||
46 |
0xFC |
||
47 |
0x3F |
||
48 |
0x00 |
3 |
|
49 |
0x00 |
||
50 |
0x00 |
||
51 |
0x00 |
||
52 |
0x00 |
||
53 |
0x00 |
||
54 |
0x08 |
||
55 |
0x40 |
||
56 |
0x00 |
5 |
|
57 |
0x00 |
||
58 |
0x00 |
||
59 |
0x00 |
||
60 |
0x00 |
||
61 |
0x00 |
||
62 |
0x14 |
||
63 |
0x40 |
||
64 |
0x00 |
6 |
|
65 |
0x00 |
||
66 |
0x00 |
||
67 |
0x00 |
||
68 |
0x00 |
||
69 |
0x00 |
||
70 |
0x18 |
||
71 |
0x40 |
||
72 |
0x00 |
7 |
|
73 |
0x00 |
||
74 |
0x00 |
||
75 |
0x00 |
||
76 |
0x00 |
||
77 |
0x00 |
||
78 |
0x1C |
||
79 |
0x40 |
||
80 |
0x00 |
2 |
|
81 |
0x00 |
||
82 |
0x00 |
||
83 |
0x00 |
||
84 |
0x00 |
||
85 |
0x00 |
||
86 |
0x00 |
||
87 |
0x40 |
||
88 |
0x00 |
0 |
|
89 |
0x00 |
||
90 |
0x00 |
||
91 |
0x00 |
||
92 |
0x00 |
||
93 |
0x00 |
||
94 |
0x00 |
||
95 |
0x00 |
||
96 |
0x00 |
0.9375 |
|
97 |
0x00 |
||
98 |
0x00 |
||
99 |
0x00 |
||
100 |
0x00 |
||
101 |
0x00 |
||
102 |
0xEE |
||
103 |
0x3F |
||
104 |
0x00 |
31 |
|
105 |
0x00 |
||
106 |
0x00 |
||
107 |
0x00 |
||
108 |
0x00 |
||
109 |
0x00 |
||
110 |
0x3F |
||
111 |
0x40 |
The sample code below writes a complex matrix to a binary file.
bool writeComplexMatrix(
const char* filename,
unsigned numberRows,
unsigned numberColumns,
const std::complex<double>* matrix
) {
bool success = true;
std::ofstream f(filename, std::ios::binary);
if (f) {
unsigned i = 6;
std::uint8_t* buffer = new std::uint8_t[4096];
std::memcpy(buffer, "INEBIN", 6);
buffer[i++] = 0;
buffer[i++] = 'C';
buffer[i++] = static_cast<std::uint8_t>(numberRows );
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberRows >> 24);
buffer[i++] = static_cast<std::uint8_t>(numberColumns );
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 8);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 16);
buffer[i++] = static_cast<std::uint8_t>(numberColumns >> 24);
unsigned long rowIndex = 0;
while (success && rowIndex < numberRows) {
unsigned long columnIndex = 0;
while (columnIndex < numberColumns) {
const std::complex<double>& v = matrix[
numberColumns * rowIndex + columnIndex
];
*reinterpret_cast<double*>(buffer + i) = v.real();
i += sizeof(double);
*reinterpret_cast<double*>(buffer + i) = v.imag();
i += sizeof(double);
if (i >= 4096) {
f.write(reinterpret_cast<const char*>(buffer), 4096);
success = static_cast<bool>(f);
i = 0;
}
++columnIndex;
}
++rowIndex;
}
if (i != 0) {
f.write(reinterpret_cast<const char*>(buffer), i);
success = static_cast<bool>(f);
}
if (success) {
f.close();
success = static_cast<bool>(f);
}
delete[] buffer;
} else {
success = false;
}
return success;
}