@@ -15,8 +15,8 @@ namespace Zeiss.PiWeb.Volume.Block;
15
15
16
16
using System ;
17
17
using System . Buffers ;
18
- using System . IO ;
19
18
using System . Runtime . InteropServices ;
19
+ using System . Runtime . Intrinsics ;
20
20
using System . Threading ;
21
21
using System . Threading . Tasks ;
22
22
@@ -41,37 +41,49 @@ internal static void Decode( byte[] data,
41
41
IProgress < VolumeSliceDefinition > ? progress = null ,
42
42
CancellationToken ct = default )
43
43
{
44
- var reader = new BinaryReader ( new MemoryStream ( data ) ) ;
45
- var ( _, sizeX , sizeY , sizeZ , quantization ) = BlockVolumeMetaData . Read ( reader ) ;
44
+ var header = BlockVolumeMetaData . Create ( data ) ;
45
+ var ( _, sizeX , sizeY , sizeZ , quantization ) = header ;
46
46
var ( bcx , bcy , bcz ) = BlockVolume . GetBlockCount ( sizeX , sizeY , sizeZ ) ;
47
47
var blockCount = bcx * bcy ;
48
48
var encodedBlockInfos = new EncodedBlockInfo [ blockCount ] ;
49
+ var position = BlockVolumeMetaData . HeaderLength ;
50
+ var dataSpan = data . AsSpan ( ) ;
51
+
52
+ Quantization . Invert ( quantization ) ;
49
53
50
54
for ( ushort biz = 0 ; biz < bcz ; biz ++ )
51
55
{
52
56
ct . ThrowIfCancellationRequested ( ) ;
53
57
54
- var layerLength = reader . ReadInt32 ( ) ;
58
+ var layerLength = MemoryMarshal . Read < int > ( dataSpan . Slice ( position , sizeof ( int ) ) ) ;
59
+ position += sizeof ( int ) ;
55
60
if ( layerPredicate ? . Invoke ( biz ) is false )
56
61
{
57
- reader . BaseStream . Seek ( layerLength , SeekOrigin . Current ) ;
62
+ position += layerLength ;
58
63
continue ;
59
64
}
60
65
61
- ReadBlockInfos ( reader , blockCount , encodedBlockInfos ) ;
66
+ ReadLayer ( dataSpan , position , blockCount , encodedBlockInfos ) ;
62
67
DecodeLayer ( data , encodedBlockInfos , bcx , bcy , biz , quantization , blockPredicate , blockAction ) ;
63
68
64
69
progress ? . Report ( new VolumeSliceDefinition ( Direction . Z , ( ushort ) ( biz * BlockVolume . N ) ) ) ;
70
+
71
+ position += layerLength ;
65
72
}
66
73
}
67
74
68
- private static void ReadBlockInfos ( BinaryReader reader , int blockCount , EncodedBlockInfo [ ] encodedBlockInfos )
75
+ private static void ReadLayer ( ReadOnlySpan < byte > dataSpan , int position , int blockCount , EncodedBlockInfo [ ] encodedBlockInfos )
69
76
{
70
77
for ( var i = 0 ; i < blockCount ; i ++ )
71
78
{
72
- var encodedBlockInfo = EncodedBlockInfo . Read ( reader ) ;
73
- reader . BaseStream . Seek ( encodedBlockInfo . Info . Length , SeekOrigin . Current ) ;
79
+ var value = MemoryMarshal . Read < ushort > ( dataSpan [ position .. ] ) ;
80
+
81
+ position += sizeof ( ushort ) ;
82
+
83
+ var encodedBlockInfo = new EncodedBlockInfo ( position , BlockInfo . Create ( value ) ) ;
74
84
encodedBlockInfos [ i ] = encodedBlockInfo ;
85
+
86
+ position += encodedBlockInfo . Info . Length ;
75
87
}
76
88
}
77
89
@@ -85,50 +97,71 @@ private static void DecodeLayer(
85
97
BlockPredicate ? blockPredicate ,
86
98
BlockAction blockAction )
87
99
{
88
- Parallel . For ( 0 , blockCountX * blockCountY , ( ) => (
89
- ArrayPool < double > . Shared . Rent ( BlockVolume . N3 ) ,
90
- ArrayPool < double > . Shared . Rent ( BlockVolume . N3 ) ,
91
- ArrayPool < byte > . Shared . Rent ( BlockVolume . N3 )
92
- ) , ( index , _ , buffers ) =>
93
- {
94
- var blockIndexX = index % blockCountX ;
95
- var blockIndexY = index / blockCountX ;
96
- var blockIndex = new BlockIndex ( ( ushort ) blockIndexX , ( ushort ) blockIndexY , blockIndexZ ) ;
100
+ #if DEBUG
101
+ var buffers = new DecodingBuffers ( ) ;
102
+ for ( var index = 0 ; index < blockCountX * blockCountY ; index ++ )
103
+ {
104
+ #else
105
+ Parallel . For ( 0 , blockCountX * blockCountY , ( ) => new DecodingBuffers ( ) , ( index , _ , buffers ) =>
106
+ {
107
+ #endif
108
+ var blockIndexX = index % blockCountX ;
109
+ var blockIndexY = index / blockCountX ;
110
+ var blockIndex = new BlockIndex ( ( ushort ) blockIndexX , ( ushort ) blockIndexY , blockIndexZ ) ;
97
111
98
- if ( blockPredicate ? . Invoke ( blockIndex ) == false )
99
- return buffers ;
112
+ if ( blockPredicate ? . Invoke ( blockIndex ) == false )
113
+ #if DEBUG
114
+ continue ;
115
+ #else
116
+ return buffers ;
117
+ #endif
100
118
101
- var doubleBuffer1 = buffers . Item1 . AsSpan ( 0 , BlockVolume . N3 ) ;
102
- var doubleBuffer2 = buffers . Item2 . AsSpan ( 0 , BlockVolume . N3 ) ;
103
- var byteBuffer = buffers . Item3 . AsSpan ( 0 , BlockVolume . N3 ) ;
104
- var encodedBlockInfo = encodedBlockInfos [ index ] ;
119
+ var inputSpan = buffers . InputBuffer . AsSpan ( 0 , BlockVolume . N3 ) ;
120
+ var outputSpan = buffers . OutputBuffer . AsSpan ( 0 , BlockVolume . N3 ) ;
121
+ var resultSpan = buffers . ResultBuffer . AsSpan ( 0 , BlockVolume . N3 ) ;
122
+ var encodedBlockInfo = encodedBlockInfos [ index ] ;
105
123
106
- //1. Dediscretization
107
- ReadBlock ( encodedBlocks . AsSpan ( ) , encodedBlockInfo , doubleBuffer1 ) ;
124
+ //1. Dediscretization
125
+ ReadBlock ( encodedBlocks . AsSpan ( ) , encodedBlockInfo , inputSpan ) ;
108
126
109
- //2. ZigZag
110
- ZigZag . Reverse ( doubleBuffer1 , doubleBuffer2 ) ;
127
+ //2. ZigZag
128
+ ZigZag . Reverse ( inputSpan , outputSpan ) ;
111
129
112
- //3. Quantization
113
- Quantization . Apply ( quantization . AsSpan ( ) , doubleBuffer2 ) ;
130
+ var nonEmptyVectors = FindNonEmptyVectors ( outputSpan ) ;
114
131
115
- //4. Cosine transform
116
- DiscreteCosineTransform . Transform ( doubleBuffer2 , doubleBuffer1 , true ) ;
132
+ //3. Quantization
133
+ Quantization . Apply ( quantization . AsSpan ( ) , outputSpan ) ;
117
134
118
- //5. Discretization
119
- for ( var i = 0 ; i < BlockVolume . N3 ; i ++ )
120
- byteBuffer [ i ] = ( byte ) Math . Clamp ( doubleBuffer1 [ i ] , byte . MinValue , byte . MaxValue ) ;
135
+ //4. Cosine transform
136
+ DiscreteCosineTransform . Transform ( outputSpan , inputSpan , true , nonEmptyVectors ) ;
121
137
122
- blockAction ( byteBuffer , blockIndex ) ;
138
+ //5. Discretization
139
+ for ( var i = 0 ; i < BlockVolume . N3 ; i ++ )
140
+ resultSpan [ i ] = ( byte ) Math . Clamp ( inputSpan [ i ] , byte . MinValue , byte . MaxValue ) ;
123
141
124
- return buffers ;
125
- } ,
126
- buffers =>
127
- {
128
- ArrayPool < double > . Shared . Return ( buffers . Item1 ) ;
129
- ArrayPool < double > . Shared . Return ( buffers . Item2 ) ;
130
- ArrayPool < byte > . Shared . Return ( buffers . Item3 ) ;
131
- } ) ;
142
+ blockAction ( resultSpan , blockIndex ) ;
143
+ #if DEBUG
144
+ }
145
+
146
+ buffers . Return ( ) ;
147
+ #else
148
+ return buffers ;
149
+ } , buffers => buffers . Return ( ) ) ;
150
+ #endif
151
+ }
152
+
153
+ private static ulong FindNonEmptyVectors ( Span < double > values )
154
+ {
155
+ var vectors = MemoryMarshal . Cast < double , Vector512 < double > > ( values ) ;
156
+ var result = 0UL ;
157
+
158
+ for ( ushort i = 0 ; i < BlockVolume . N2 ; i ++ )
159
+ {
160
+ if ( Vector512 . Sum ( Vector512 . Abs ( vectors [ i ] ) ) > 1e-12 )
161
+ result |= 1UL << i ;
162
+ }
163
+
164
+ return result ;
132
165
}
133
166
134
167
private static void ReadBlock ( ReadOnlySpan < byte > data , EncodedBlockInfo blockInfo , Span < double > result )
@@ -167,24 +200,22 @@ private static void ReadBlock( ReadOnlySpan<byte> data, EncodedBlockInfo blockIn
167
200
168
201
#endregion
169
202
170
- private readonly record struct EncodedBlockInfo ( int StartIndex , BlockInfo Info )
203
+ private readonly struct DecodingBuffers ( )
171
204
{
172
- #region methods
205
+ public double [ ] InputBuffer { get ; } = ArrayPool < double > . Shared . Rent ( BlockVolume . N3 ) ;
206
+ public double [ ] OutputBuffer { get ; } = ArrayPool < double > . Shared . Rent ( BlockVolume . N3 ) ;
207
+ public byte [ ] ResultBuffer { get ; } = ArrayPool < byte > . Shared . Rent ( BlockVolume . N3 ) ;
173
208
174
- /// <summary>
175
- /// Reads the encoded block info from the specified <paramref name="reader"/>
176
- /// </summary>
177
- public static EncodedBlockInfo Read ( BinaryReader reader )
209
+ public void Return ( )
178
210
{
179
- var info = BlockInfo . Read ( reader ) ;
180
- var startIndex = ( int ) reader . BaseStream . Position ;
181
-
182
- return new EncodedBlockInfo ( startIndex , info ) ;
211
+ ArrayPool < double > . Shared . Return ( InputBuffer ) ;
212
+ ArrayPool < double > . Shared . Return ( OutputBuffer ) ;
213
+ ArrayPool < byte > . Shared . Return ( ResultBuffer ) ;
183
214
}
184
-
185
- #endregion
186
215
}
187
216
217
+ private readonly record struct EncodedBlockInfo ( int StartIndex , BlockInfo Info ) ;
218
+
188
219
internal delegate void BlockAction ( ReadOnlySpan < byte > data , BlockIndex index ) ;
189
220
190
221
internal delegate bool BlockPredicate ( BlockIndex index ) ;
0 commit comments