libzstd_rs_sys/lib/compress/
zstd_preSplit.rs1use core::ptr;
2
3use libc::size_t;
4
5use crate::lib::common::mem::MEM_read16;
6use crate::lib::compress::hist::HIST_add;
7
8#[repr(C)]
9pub struct Fingerprint {
10 pub events: [core::ffi::c_uint; 1024],
11 pub nbEvents: size_t,
12}
13#[repr(C)]
14pub struct FPStats {
15 pub pastEvents: Fingerprint,
16 pub newEvents: Fingerprint,
17}
18pub type RecordEvents_f =
19 Option<unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> ()>;
20pub const THRESHOLD_PENALTY_RATE: core::ffi::c_int = 16;
21pub const THRESHOLD_BASE: core::ffi::c_int = THRESHOLD_PENALTY_RATE - 2;
22pub const THRESHOLD_PENALTY: core::ffi::c_int = 3;
23pub const HASHLENGTH: core::ffi::c_int = 2;
24pub const HASHLOG_MAX: core::ffi::c_int = 10;
25pub const HASHTABLESIZE: core::ffi::c_int = (1) << HASHLOG_MAX;
26pub const KNUTH: core::ffi::c_uint = 0x9e3779b9;
27#[inline(always)]
28unsafe fn hash2(p: *const core::ffi::c_void, hashLog: core::ffi::c_uint) -> core::ffi::c_uint {
29 if hashLog == 8 {
30 return *(p as *const u8).offset(0) as u32;
31 }
32 (MEM_read16(p) as u32).wrapping_mul(KNUTH) >> (32 as core::ffi::c_uint).wrapping_sub(hashLog)
33}
34unsafe fn initStats(fpstats: *mut FPStats) {
35 ptr::write_bytes(fpstats as *mut u8, 0, ::core::mem::size_of::<FPStats>());
36}
37#[inline(always)]
38unsafe fn addEvents_generic(
39 fp: *mut Fingerprint,
40 src: *const core::ffi::c_void,
41 srcSize: size_t,
42 samplingRate: size_t,
43 hashLog: core::ffi::c_uint,
44) {
45 let p = src as *const core::ffi::c_char;
46 let limit = srcSize.wrapping_sub(HASHLENGTH as size_t).wrapping_add(1);
47 let mut n: size_t = 0;
48 n = 0;
49 while n < limit {
50 let fresh0 = &mut (*((*fp).events)
51 .as_mut_ptr()
52 .offset(hash2(p.add(n) as *const core::ffi::c_void, hashLog) as isize));
53 *fresh0 = (*fresh0).wrapping_add(1);
54 n = n.wrapping_add(samplingRate);
55 }
56 (*fp).nbEvents = ((*fp).nbEvents).wrapping_add(limit / samplingRate);
57}
58#[inline(always)]
59unsafe fn recordFingerprint_generic(
60 fp: *mut Fingerprint,
61 src: *const core::ffi::c_void,
62 srcSize: size_t,
63 samplingRate: size_t,
64 hashLog: core::ffi::c_uint,
65) {
66 ptr::write_bytes(
67 fp as *mut u8,
68 0,
69 ::core::mem::size_of::<core::ffi::c_uint>() << hashLog,
70 );
71 (*fp).nbEvents = 0;
72 addEvents_generic(fp, src, srcSize, samplingRate, hashLog);
73}
74unsafe fn ZSTD_recordFingerprint_1(
75 fp: *mut Fingerprint,
76 src: *const core::ffi::c_void,
77 srcSize: size_t,
78) {
79 recordFingerprint_generic(fp, src, srcSize, 1, 10);
80}
81unsafe fn ZSTD_recordFingerprint_5(
82 fp: *mut Fingerprint,
83 src: *const core::ffi::c_void,
84 srcSize: size_t,
85) {
86 recordFingerprint_generic(fp, src, srcSize, 5, 10);
87}
88unsafe fn ZSTD_recordFingerprint_11(
89 fp: *mut Fingerprint,
90 src: *const core::ffi::c_void,
91 srcSize: size_t,
92) {
93 recordFingerprint_generic(fp, src, srcSize, 11, 9);
94}
95unsafe fn ZSTD_recordFingerprint_43(
96 fp: *mut Fingerprint,
97 src: *const core::ffi::c_void,
98 srcSize: size_t,
99) {
100 recordFingerprint_generic(fp, src, srcSize, 43, 8);
101}
102unsafe fn abs64(s64: i64) -> u64 {
103 (if s64 < 0 { -s64 } else { s64 }) as u64
104}
105unsafe fn fpDistance(
106 fp1: *const Fingerprint,
107 fp2: *const Fingerprint,
108 hashLog: core::ffi::c_uint,
109) -> u64 {
110 let mut distance = 0u64;
111 let mut n: size_t = 0;
112 n = 0;
113 while n < (1) << hashLog {
114 distance = distance.wrapping_add(abs64(
115 *((*fp1).events).as_ptr().add(n) as i64 * (*fp2).nbEvents as i64
116 - *((*fp2).events).as_ptr().add(n) as i64 * (*fp1).nbEvents as i64,
117 ));
118 n = n.wrapping_add(1);
119 }
120 distance
121}
122unsafe fn compareFingerprints(
123 ref_0: *const Fingerprint,
124 newfp: *const Fingerprint,
125 penalty: core::ffi::c_int,
126 hashLog: core::ffi::c_uint,
127) -> core::ffi::c_int {
128 let p50 = (*ref_0).nbEvents * (*newfp).nbEvents;
129 let deviation = fpDistance(ref_0, newfp, hashLog);
130 let threshold = p50 as u64 * (THRESHOLD_BASE + penalty) as u64 / THRESHOLD_PENALTY_RATE as u64;
131 (deviation >= threshold) as core::ffi::c_int
132}
133unsafe fn mergeEvents(acc: *mut Fingerprint, newfp: *const Fingerprint) {
134 let mut n: size_t = 0;
135 n = 0;
136 while n < HASHTABLESIZE as size_t {
137 let fresh1 = &mut (*((*acc).events).as_mut_ptr().add(n));
138 *fresh1 = (*fresh1).wrapping_add(*((*newfp).events).as_ptr().add(n));
139 n = n.wrapping_add(1);
140 }
141 (*acc).nbEvents = ((*acc).nbEvents).wrapping_add((*newfp).nbEvents);
142}
143unsafe fn flushEvents(fpstats: *mut FPStats) {
144 let mut n: size_t = 0;
145 n = 0;
146 while n < HASHTABLESIZE as size_t {
147 *((*fpstats).pastEvents.events).as_mut_ptr().add(n) =
148 *((*fpstats).newEvents.events).as_mut_ptr().add(n);
149 n = n.wrapping_add(1);
150 }
151 (*fpstats).pastEvents.nbEvents = (*fpstats).newEvents.nbEvents;
152 ptr::write_bytes(
153 &mut (*fpstats).newEvents as *mut Fingerprint as *mut u8,
154 0,
155 ::core::mem::size_of::<Fingerprint>(),
156 );
157}
158unsafe fn removeEvents(acc: *mut Fingerprint, slice: *const Fingerprint) {
159 let mut n: size_t = 0;
160 n = 0;
161 while n < HASHTABLESIZE as size_t {
162 let fresh2 = &mut (*((*acc).events).as_mut_ptr().add(n));
163 *fresh2 = (*fresh2).wrapping_sub(*((*slice).events).as_ptr().add(n));
164 n = n.wrapping_add(1);
165 }
166 (*acc).nbEvents = ((*acc).nbEvents).wrapping_sub((*slice).nbEvents);
167}
168pub const CHUNKSIZE: core::ffi::c_int = (8) << 10;
169unsafe fn ZSTD_splitBlock_byChunks(
170 blockStart: *const core::ffi::c_void,
171 blockSize: size_t,
172 level: core::ffi::c_int,
173 workspace: *mut core::ffi::c_void,
174 wkspSize: size_t,
175) -> size_t {
176 static records_fs: [RecordEvents_f; 4] = [
177 Some(
178 ZSTD_recordFingerprint_43
179 as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
180 ),
181 Some(
182 ZSTD_recordFingerprint_11
183 as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
184 ),
185 Some(
186 ZSTD_recordFingerprint_5
187 as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
188 ),
189 Some(
190 ZSTD_recordFingerprint_1
191 as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
192 ),
193 ];
194 static hashParams: [core::ffi::c_uint; 4] = [8, 9, 10, 10];
195 let record_f: RecordEvents_f = *records_fs.as_ptr().offset(level as isize);
196 let fpstats = workspace as *mut FPStats;
197 let p = blockStart as *const core::ffi::c_char;
198 let mut penalty = THRESHOLD_PENALTY;
199 let mut pos = 0;
200 initStats(fpstats);
201 record_f.unwrap_unchecked()(
202 &mut (*fpstats).pastEvents,
203 p as *const core::ffi::c_void,
204 CHUNKSIZE as size_t,
205 );
206 pos = CHUNKSIZE as size_t;
207 while pos <= blockSize.wrapping_sub(CHUNKSIZE as size_t) {
208 record_f.unwrap_unchecked()(
209 &mut (*fpstats).newEvents,
210 p.add(pos) as *const core::ffi::c_void,
211 CHUNKSIZE as size_t,
212 );
213 if compareFingerprints(
214 &(*fpstats).pastEvents,
215 &(*fpstats).newEvents,
216 penalty,
217 *hashParams.as_ptr().offset(level as isize),
218 ) != 0
219 {
220 return pos;
221 } else {
222 mergeEvents(&mut (*fpstats).pastEvents, &(*fpstats).newEvents);
223 if penalty > 0 {
224 penalty -= 1;
225 }
226 }
227 pos = pos.wrapping_add(CHUNKSIZE as size_t);
228 }
229 blockSize
230}
231unsafe fn ZSTD_splitBlock_fromBorders(
232 blockStart: *const core::ffi::c_void,
233 blockSize: size_t,
234 workspace: *mut core::ffi::c_void,
235 wkspSize: size_t,
236) -> size_t {
237 let fpstats = workspace as *mut FPStats;
238 let middleEvents = (workspace as *mut core::ffi::c_char).offset(
239 (512 as core::ffi::c_ulong)
240 .wrapping_mul(::core::mem::size_of::<core::ffi::c_uint>() as core::ffi::c_ulong)
241 as isize,
242 ) as *mut core::ffi::c_void as *mut Fingerprint;
243 initStats(fpstats);
244 HIST_add(
245 ((*fpstats).pastEvents.events).as_mut_ptr(),
246 blockStart,
247 SEGMENT_SIZE as size_t,
248 );
249 HIST_add(
250 ((*fpstats).newEvents.events).as_mut_ptr(),
251 (blockStart as *const core::ffi::c_char)
252 .add(blockSize)
253 .offset(-(SEGMENT_SIZE as isize)) as *const core::ffi::c_void,
254 SEGMENT_SIZE as size_t,
255 );
256 (*fpstats).newEvents.nbEvents = SEGMENT_SIZE as size_t;
257 (*fpstats).pastEvents.nbEvents = (*fpstats).newEvents.nbEvents;
258 if compareFingerprints(&(*fpstats).pastEvents, &(*fpstats).newEvents, 0, 8) == 0 {
259 return blockSize;
260 }
261 HIST_add(
262 ((*middleEvents).events).as_mut_ptr(),
263 (blockStart as *const core::ffi::c_char)
264 .add(blockSize / 2)
265 .offset(-((SEGMENT_SIZE / 2) as isize)) as *const core::ffi::c_void,
266 SEGMENT_SIZE as size_t,
267 );
268 (*middleEvents).nbEvents = SEGMENT_SIZE as size_t;
269 let distFromBegin = fpDistance(&(*fpstats).pastEvents, middleEvents, 8);
270 let distFromEnd = fpDistance(&(*fpstats).newEvents, middleEvents, 8);
271 let minDistance = (SEGMENT_SIZE * SEGMENT_SIZE / 3) as u64;
272 if abs64(distFromBegin as i64 - distFromEnd as i64) < minDistance {
273 return (64 * ((1) << 10)) as size_t;
274 }
275 (if distFromBegin > distFromEnd {
276 32 * ((1) << 10)
277 } else {
278 96 * ((1) << 10)
279 }) as size_t
280}
281pub const SEGMENT_SIZE: core::ffi::c_int = 512;
282pub unsafe fn ZSTD_splitBlock(
283 blockStart: *const core::ffi::c_void,
284 blockSize: size_t,
285 level: core::ffi::c_int,
286 workspace: *mut core::ffi::c_void,
287 wkspSize: size_t,
288) -> size_t {
289 if level == 0 {
290 return ZSTD_splitBlock_fromBorders(blockStart, blockSize, workspace, wkspSize);
291 }
292 ZSTD_splitBlock_byChunks(blockStart, blockSize, level - 1, workspace, wkspSize)
293}