dibio.c revision 1.1 1 1.1 christos /*
2 1.1 christos * Copyright (c) Meta Platforms, Inc. and affiliates.
3 1.1 christos * All rights reserved.
4 1.1 christos *
5 1.1 christos * This source code is licensed under both the BSD-style license (found in the
6 1.1 christos * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 1.1 christos * in the COPYING file in the root directory of this source tree).
8 1.1 christos * You may select, at your option, one of the above-listed licenses.
9 1.1 christos */
10 1.1 christos
11 1.1 christos
12 1.1 christos
13 1.1 christos /* **************************************
14 1.1 christos * Compiler Warnings
15 1.1 christos ****************************************/
16 1.1 christos #ifdef _MSC_VER
17 1.1 christos # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
18 1.1 christos #endif
19 1.1 christos
20 1.1 christos
21 1.1 christos /*-*************************************
22 1.1 christos * Includes
23 1.1 christos ***************************************/
24 1.1 christos #include "platform.h" /* Large Files support */
25 1.1 christos #include "util.h" /* UTIL_getFileSize, UTIL_getTotalFileSize */
26 1.1 christos #include <stdlib.h> /* malloc, free */
27 1.1 christos #include <string.h> /* memset */
28 1.1 christos #include <stdio.h> /* fprintf, fopen, ftello64 */
29 1.1 christos #include <errno.h> /* errno */
30 1.1 christos
31 1.1 christos #include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */
32 1.1 christos #include "../lib/common/debug.h" /* assert */
33 1.1 christos #include "../lib/common/mem.h" /* read */
34 1.1 christos #include "../lib/zstd_errors.h"
35 1.1 christos #include "dibio.h"
36 1.1 christos
37 1.1 christos
38 1.1 christos /*-*************************************
39 1.1 christos * Constants
40 1.1 christos ***************************************/
41 1.1 christos #define KB *(1 <<10)
42 1.1 christos #define MB *(1 <<20)
43 1.1 christos #define GB *(1U<<30)
44 1.1 christos
45 1.1 christos #define SAMPLESIZE_MAX (128 KB)
46 1.1 christos #define MEMMULT 11 /* rough estimation : memory cost to analyze 1 byte of sample */
47 1.1 christos #define COVER_MEMMULT 9 /* rough estimation : memory cost to analyze 1 byte of sample */
48 1.1 christos #define FASTCOVER_MEMMULT 1 /* rough estimation : memory cost to analyze 1 byte of sample */
49 1.1 christos static const size_t g_maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t));
50 1.1 christos
51 1.1 christos #define NOISELENGTH 32
52 1.1 christos #define MAX_SAMPLES_SIZE (2 GB) /* training dataset limited to 2GB */
53 1.1 christos
54 1.1 christos
55 1.1 christos /*-*************************************
56 1.1 christos * Console display
57 1.1 christos ***************************************/
58 1.1 christos #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
59 1.1 christos #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); }
60 1.1 christos
61 1.1 christos static const U64 g_refreshRate = SEC_TO_MICRO / 6;
62 1.1 christos static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER;
63 1.1 christos
64 1.1 christos #define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \
65 1.1 christos if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \
66 1.1 christos { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \
67 1.1 christos if (displayLevel>=4) fflush(stderr); } } }
68 1.1 christos
69 1.1 christos /*-*************************************
70 1.1 christos * Exceptions
71 1.1 christos ***************************************/
72 1.1 christos #ifndef DEBUG
73 1.1 christos # define DEBUG 0
74 1.1 christos #endif
75 1.1 christos #define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
76 1.1 christos #define EXM_THROW(error, ...) \
77 1.1 christos { \
78 1.1 christos DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
79 1.1 christos DISPLAY("Error %i : ", error); \
80 1.1 christos DISPLAY(__VA_ARGS__); \
81 1.1 christos DISPLAY("\n"); \
82 1.1 christos exit(error); \
83 1.1 christos }
84 1.1 christos
85 1.1 christos
86 1.1 christos /* ********************************************************
87 1.1 christos * Helper functions
88 1.1 christos **********************************************************/
89 1.1 christos #undef MIN
90 1.1 christos #define MIN(a,b) ((a) < (b) ? (a) : (b))
91 1.1 christos
92 1.1 christos /**
93 1.1 christos Returns the size of a file.
94 1.1 christos If error returns -1.
95 1.1 christos */
96 1.1 christos static S64 DiB_getFileSize (const char * fileName)
97 1.1 christos {
98 1.1 christos U64 const fileSize = UTIL_getFileSize(fileName);
99 1.1 christos return (fileSize == UTIL_FILESIZE_UNKNOWN) ? -1 : (S64)fileSize;
100 1.1 christos }
101 1.1 christos
102 1.1 christos /* ********************************************************
103 1.1 christos * File related operations
104 1.1 christos **********************************************************/
105 1.1 christos /** DiB_loadFiles() :
106 1.1 christos * load samples from files listed in fileNamesTable into buffer.
107 1.1 christos * works even if buffer is too small to load all samples.
108 1.1 christos * Also provides the size of each sample into sampleSizes table
109 1.1 christos * which must be sized correctly, using DiB_fileStats().
110 1.1 christos * @return : nb of samples effectively loaded into `buffer`
111 1.1 christos * *bufferSizePtr is modified, it provides the amount data loaded within buffer.
112 1.1 christos * sampleSizes is filled with the size of each sample.
113 1.1 christos */
114 1.1 christos static int DiB_loadFiles(
115 1.1 christos void* buffer, size_t* bufferSizePtr,
116 1.1 christos size_t* sampleSizes, int sstSize,
117 1.1 christos const char** fileNamesTable, int nbFiles,
118 1.1 christos size_t targetChunkSize, int displayLevel )
119 1.1 christos {
120 1.1 christos char* const buff = (char*)buffer;
121 1.1 christos size_t totalDataLoaded = 0;
122 1.1 christos int nbSamplesLoaded = 0;
123 1.1 christos int fileIndex = 0;
124 1.1 christos FILE * f = NULL;
125 1.1 christos
126 1.1 christos assert(targetChunkSize <= SAMPLESIZE_MAX);
127 1.1 christos
128 1.1 christos while ( nbSamplesLoaded < sstSize && fileIndex < nbFiles ) {
129 1.1 christos size_t fileDataLoaded;
130 1.1 christos S64 const fileSize = DiB_getFileSize(fileNamesTable[fileIndex]);
131 1.1 christos if (fileSize <= 0) {
132 1.1 christos /* skip if zero-size or file error */
133 1.1 christos ++fileIndex;
134 1.1 christos continue;
135 1.1 christos }
136 1.1 christos
137 1.1 christos f = fopen( fileNamesTable[fileIndex], "rb");
138 1.1 christos if (f == NULL)
139 1.1 christos EXM_THROW(10, "zstd: dictBuilder: %s %s ", fileNamesTable[fileIndex], strerror(errno));
140 1.1 christos DISPLAYUPDATE(2, "Loading %s... \r", fileNamesTable[fileIndex]);
141 1.1 christos
142 1.1 christos /* Load the first chunk of data from the file */
143 1.1 christos fileDataLoaded = targetChunkSize > 0 ?
144 1.1 christos (size_t)MIN(fileSize, (S64)targetChunkSize) :
145 1.1 christos (size_t)MIN(fileSize, SAMPLESIZE_MAX );
146 1.1 christos if (totalDataLoaded + fileDataLoaded > *bufferSizePtr)
147 1.1 christos break;
148 1.1 christos if (fread( buff+totalDataLoaded, 1, fileDataLoaded, f ) != fileDataLoaded)
149 1.1 christos EXM_THROW(11, "Pb reading %s", fileNamesTable[fileIndex]);
150 1.1 christos sampleSizes[nbSamplesLoaded++] = fileDataLoaded;
151 1.1 christos totalDataLoaded += fileDataLoaded;
152 1.1 christos
153 1.1 christos /* If file-chunking is enabled, load the rest of the file as more samples */
154 1.1 christos if (targetChunkSize > 0) {
155 1.1 christos while( (S64)fileDataLoaded < fileSize && nbSamplesLoaded < sstSize ) {
156 1.1 christos size_t const chunkSize = MIN((size_t)(fileSize-fileDataLoaded), targetChunkSize);
157 1.1 christos if (totalDataLoaded + chunkSize > *bufferSizePtr) /* buffer is full */
158 1.1 christos break;
159 1.1 christos
160 1.1 christos if (fread( buff+totalDataLoaded, 1, chunkSize, f ) != chunkSize)
161 1.1 christos EXM_THROW(11, "Pb reading %s", fileNamesTable[fileIndex]);
162 1.1 christos sampleSizes[nbSamplesLoaded++] = chunkSize;
163 1.1 christos totalDataLoaded += chunkSize;
164 1.1 christos fileDataLoaded += chunkSize;
165 1.1 christos }
166 1.1 christos }
167 1.1 christos fileIndex += 1;
168 1.1 christos fclose(f); f = NULL;
169 1.1 christos }
170 1.1 christos if (f != NULL)
171 1.1 christos fclose(f);
172 1.1 christos
173 1.1 christos DISPLAYLEVEL(2, "\r%79s\r", "");
174 1.1 christos DISPLAYLEVEL(4, "Loaded %d KB total training data, %d nb samples \n",
175 1.1 christos (int)(totalDataLoaded / (1 KB)), nbSamplesLoaded );
176 1.1 christos *bufferSizePtr = totalDataLoaded;
177 1.1 christos return nbSamplesLoaded;
178 1.1 christos }
179 1.1 christos
180 1.1 christos #define DiB_rotl32(x,r) ((x << r) | (x >> (32 - r)))
181 1.1 christos static U32 DiB_rand(U32* src)
182 1.1 christos {
183 1.1 christos static const U32 prime1 = 2654435761U;
184 1.1 christos static const U32 prime2 = 2246822519U;
185 1.1 christos U32 rand32 = *src;
186 1.1 christos rand32 *= prime1;
187 1.1 christos rand32 ^= prime2;
188 1.1 christos rand32 = DiB_rotl32(rand32, 13);
189 1.1 christos *src = rand32;
190 1.1 christos return rand32 >> 5;
191 1.1 christos }
192 1.1 christos
193 1.1 christos /* DiB_shuffle() :
194 1.1 christos * shuffle a table of file names in a semi-random way
195 1.1 christos * It improves dictionary quality by reducing "locality" impact, so if sample set is very large,
196 1.1 christos * it will load random elements from it, instead of just the first ones. */
197 1.1 christos static void DiB_shuffle(const char** fileNamesTable, unsigned nbFiles) {
198 1.1 christos U32 seed = 0xFD2FB528;
199 1.1 christos unsigned i;
200 1.1 christos if (nbFiles == 0)
201 1.1 christos return;
202 1.1 christos for (i = nbFiles - 1; i > 0; --i) {
203 1.1 christos unsigned const j = DiB_rand(&seed) % (i + 1);
204 1.1 christos const char* const tmp = fileNamesTable[j];
205 1.1 christos fileNamesTable[j] = fileNamesTable[i];
206 1.1 christos fileNamesTable[i] = tmp;
207 1.1 christos }
208 1.1 christos }
209 1.1 christos
210 1.1 christos
211 1.1 christos /*-********************************************************
212 1.1 christos * Dictionary training functions
213 1.1 christos **********************************************************/
214 1.1 christos static size_t DiB_findMaxMem(unsigned long long requiredMem)
215 1.1 christos {
216 1.1 christos size_t const step = 8 MB;
217 1.1 christos void* testmem = NULL;
218 1.1 christos
219 1.1 christos requiredMem = (((requiredMem >> 23) + 1) << 23);
220 1.1 christos requiredMem += step;
221 1.1 christos if (requiredMem > g_maxMemory) requiredMem = g_maxMemory;
222 1.1 christos
223 1.1 christos while (!testmem) {
224 1.1 christos testmem = malloc((size_t)requiredMem);
225 1.1 christos requiredMem -= step;
226 1.1 christos }
227 1.1 christos
228 1.1 christos free(testmem);
229 1.1 christos return (size_t)requiredMem;
230 1.1 christos }
231 1.1 christos
232 1.1 christos
233 1.1 christos static void DiB_fillNoise(void* buffer, size_t length)
234 1.1 christos {
235 1.1 christos unsigned const prime1 = 2654435761U;
236 1.1 christos unsigned const prime2 = 2246822519U;
237 1.1 christos unsigned acc = prime1;
238 1.1 christos size_t p=0;
239 1.1 christos
240 1.1 christos for (p=0; p<length; p++) {
241 1.1 christos acc *= prime2;
242 1.1 christos ((unsigned char*)buffer)[p] = (unsigned char)(acc >> 21);
243 1.1 christos }
244 1.1 christos }
245 1.1 christos
246 1.1 christos
247 1.1 christos static void DiB_saveDict(const char* dictFileName,
248 1.1 christos const void* buff, size_t buffSize)
249 1.1 christos {
250 1.1 christos FILE* const f = fopen(dictFileName, "wb");
251 1.1 christos if (f==NULL) EXM_THROW(3, "cannot open %s ", dictFileName);
252 1.1 christos
253 1.1 christos { size_t const n = fwrite(buff, 1, buffSize, f);
254 1.1 christos if (n!=buffSize) EXM_THROW(4, "%s : write error", dictFileName) }
255 1.1 christos
256 1.1 christos { size_t const n = (size_t)fclose(f);
257 1.1 christos if (n!=0) EXM_THROW(5, "%s : flush error", dictFileName) }
258 1.1 christos }
259 1.1 christos
260 1.1 christos typedef struct {
261 1.1 christos S64 totalSizeToLoad;
262 1.1 christos int nbSamples;
263 1.1 christos int oneSampleTooLarge;
264 1.1 christos } fileStats;
265 1.1 christos
266 1.1 christos /*! DiB_fileStats() :
267 1.1 christos * Given a list of files, and a chunkSize (0 == no chunk, whole files)
268 1.1 christos * provides the amount of data to be loaded and the resulting nb of samples.
269 1.1 christos * This is useful primarily for allocation purpose => sample buffer, and sample sizes table.
270 1.1 christos */
271 1.1 christos static fileStats DiB_fileStats(const char** fileNamesTable, int nbFiles, size_t chunkSize, int displayLevel)
272 1.1 christos {
273 1.1 christos fileStats fs;
274 1.1 christos int n;
275 1.1 christos memset(&fs, 0, sizeof(fs));
276 1.1 christos
277 1.1 christos /* We assume that if chunking is requested, the chunk size is < SAMPLESIZE_MAX */
278 1.1 christos assert( chunkSize <= SAMPLESIZE_MAX );
279 1.1 christos
280 1.1 christos for (n=0; n<nbFiles; n++) {
281 1.1 christos S64 const fileSize = DiB_getFileSize(fileNamesTable[n]);
282 1.1 christos /* TODO: is there a minimum sample size? What if the file is 1-byte? */
283 1.1 christos if (fileSize == 0) {
284 1.1 christos DISPLAYLEVEL(3, "Sample file '%s' has zero size, skipping...\n", fileNamesTable[n]);
285 1.1 christos continue;
286 1.1 christos }
287 1.1 christos
288 1.1 christos /* the case where we are breaking up files in sample chunks */
289 1.1 christos if (chunkSize > 0) {
290 1.1 christos /* TODO: is there a minimum sample size? Can we have a 1-byte sample? */
291 1.1 christos fs.nbSamples += (int)((fileSize + chunkSize-1) / chunkSize);
292 1.1 christos fs.totalSizeToLoad += fileSize;
293 1.1 christos }
294 1.1 christos else {
295 1.1 christos /* the case where one file is one sample */
296 1.1 christos if (fileSize > SAMPLESIZE_MAX) {
297 1.1 christos /* flag excessively large sample files */
298 1.1 christos fs.oneSampleTooLarge |= (fileSize > 2*SAMPLESIZE_MAX);
299 1.1 christos
300 1.1 christos /* Limit to the first SAMPLESIZE_MAX (128kB) of the file */
301 1.1 christos DISPLAYLEVEL(3, "Sample file '%s' is too large, limiting to %d KB",
302 1.1 christos fileNamesTable[n], SAMPLESIZE_MAX / (1 KB));
303 1.1 christos }
304 1.1 christos fs.nbSamples += 1;
305 1.1 christos fs.totalSizeToLoad += MIN(fileSize, SAMPLESIZE_MAX);
306 1.1 christos }
307 1.1 christos }
308 1.1 christos DISPLAYLEVEL(4, "Found training data %d files, %d KB, %d samples\n", nbFiles, (int)(fs.totalSizeToLoad / (1 KB)), fs.nbSamples);
309 1.1 christos return fs;
310 1.1 christos }
311 1.1 christos
312 1.1 christos int DiB_trainFromFiles(const char* dictFileName, size_t maxDictSize,
313 1.1 christos const char** fileNamesTable, int nbFiles, size_t chunkSize,
314 1.1 christos ZDICT_legacy_params_t* params, ZDICT_cover_params_t* coverParams,
315 1.1 christos ZDICT_fastCover_params_t* fastCoverParams, int optimize, unsigned memLimit)
316 1.1 christos {
317 1.1 christos fileStats fs;
318 1.1 christos size_t* sampleSizes; /* vector of sample sizes. Each sample can be up to SAMPLESIZE_MAX */
319 1.1 christos int nbSamplesLoaded; /* nb of samples effectively loaded in srcBuffer */
320 1.1 christos size_t loadedSize; /* total data loaded in srcBuffer for all samples */
321 1.1 christos void* srcBuffer /* contiguous buffer with training data/samples */;
322 1.1 christos void* const dictBuffer = malloc(maxDictSize);
323 1.1 christos int result = 0;
324 1.1 christos
325 1.1 christos int const displayLevel = params ? params->zParams.notificationLevel :
326 1.1 christos coverParams ? coverParams->zParams.notificationLevel :
327 1.1 christos fastCoverParams ? fastCoverParams->zParams.notificationLevel : 0;
328 1.1 christos
329 1.1 christos /* Shuffle input files before we start assessing how much sample datA to load.
330 1.1 christos The purpose of the shuffle is to pick random samples when the sample
331 1.1 christos set is larger than what we can load in memory. */
332 1.1 christos DISPLAYLEVEL(3, "Shuffling input files\n");
333 1.1 christos DiB_shuffle(fileNamesTable, nbFiles);
334 1.1 christos
335 1.1 christos /* Figure out how much sample data to load with how many samples */
336 1.1 christos fs = DiB_fileStats(fileNamesTable, nbFiles, chunkSize, displayLevel);
337 1.1 christos
338 1.1 christos {
339 1.1 christos int const memMult = params ? MEMMULT :
340 1.1 christos coverParams ? COVER_MEMMULT:
341 1.1 christos FASTCOVER_MEMMULT;
342 1.1 christos size_t const maxMem = DiB_findMaxMem(fs.totalSizeToLoad * memMult) / memMult;
343 1.1 christos /* Limit the size of the training data to the free memory */
344 1.1 christos /* Limit the size of the training data to 2GB */
345 1.1 christos /* TODO: there is opportunity to stop DiB_fileStats() early when the data limit is reached */
346 1.1 christos loadedSize = (size_t)MIN( MIN((S64)maxMem, fs.totalSizeToLoad), MAX_SAMPLES_SIZE );
347 1.1 christos if (memLimit != 0) {
348 1.1 christos DISPLAYLEVEL(2, "! Warning : setting manual memory limit for dictionary training data at %u MB \n",
349 1.1 christos (unsigned)(memLimit / (1 MB)));
350 1.1 christos loadedSize = (size_t)MIN(loadedSize, memLimit);
351 1.1 christos }
352 1.1 christos srcBuffer = malloc(loadedSize+NOISELENGTH);
353 1.1 christos sampleSizes = (size_t*)malloc(fs.nbSamples * sizeof(size_t));
354 1.1 christos }
355 1.1 christos
356 1.1 christos /* Checks */
357 1.1 christos if ((fs.nbSamples && !sampleSizes) || (!srcBuffer) || (!dictBuffer))
358 1.1 christos EXM_THROW(12, "not enough memory for DiB_trainFiles"); /* should not happen */
359 1.1 christos if (fs.oneSampleTooLarge) {
360 1.1 christos DISPLAYLEVEL(2, "! Warning : some sample(s) are very large \n");
361 1.1 christos DISPLAYLEVEL(2, "! Note that dictionary is only useful for small samples. \n");
362 1.1 christos DISPLAYLEVEL(2, "! As a consequence, only the first %u bytes of each sample are loaded \n", SAMPLESIZE_MAX);
363 1.1 christos }
364 1.1 christos if (fs.nbSamples < 5) {
365 1.1 christos DISPLAYLEVEL(2, "! Warning : nb of samples too low for proper processing ! \n");
366 1.1 christos DISPLAYLEVEL(2, "! Please provide _one file per sample_. \n");
367 1.1 christos DISPLAYLEVEL(2, "! Alternatively, split files into fixed-size blocks representative of samples, with -B# \n");
368 1.1 christos EXM_THROW(14, "nb of samples too low"); /* we now clearly forbid this case */
369 1.1 christos }
370 1.1 christos if (fs.totalSizeToLoad < (S64)maxDictSize * 8) {
371 1.1 christos DISPLAYLEVEL(2, "! Warning : data size of samples too small for target dictionary size \n");
372 1.1 christos DISPLAYLEVEL(2, "! Samples should be about 100x larger than target dictionary size \n");
373 1.1 christos }
374 1.1 christos
375 1.1 christos /* init */
376 1.1 christos if ((S64)loadedSize < fs.totalSizeToLoad)
377 1.1 christos DISPLAYLEVEL(1, "Training samples set too large (%u MB); training on %u MB only...\n",
378 1.1 christos (unsigned)(fs.totalSizeToLoad / (1 MB)),
379 1.1 christos (unsigned)(loadedSize / (1 MB)));
380 1.1 christos
381 1.1 christos /* Load input buffer */
382 1.1 christos nbSamplesLoaded = DiB_loadFiles(
383 1.1 christos srcBuffer, &loadedSize, sampleSizes, fs.nbSamples, fileNamesTable,
384 1.1 christos nbFiles, chunkSize, displayLevel);
385 1.1 christos
386 1.1 christos { size_t dictSize = ZSTD_error_GENERIC;
387 1.1 christos if (params) {
388 1.1 christos DiB_fillNoise((char*)srcBuffer + loadedSize, NOISELENGTH); /* guard band, for end of buffer condition */
389 1.1 christos dictSize = ZDICT_trainFromBuffer_legacy(dictBuffer, maxDictSize,
390 1.1 christos srcBuffer, sampleSizes, nbSamplesLoaded,
391 1.1 christos *params);
392 1.1 christos } else if (coverParams) {
393 1.1 christos if (optimize) {
394 1.1 christos dictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, maxDictSize,
395 1.1 christos srcBuffer, sampleSizes, nbSamplesLoaded,
396 1.1 christos coverParams);
397 1.1 christos if (!ZDICT_isError(dictSize)) {
398 1.1 christos unsigned splitPercentage = (unsigned)(coverParams->splitPoint * 100);
399 1.1 christos DISPLAYLEVEL(2, "k=%u\nd=%u\nsteps=%u\nsplit=%u\n", coverParams->k, coverParams->d,
400 1.1 christos coverParams->steps, splitPercentage);
401 1.1 christos }
402 1.1 christos } else {
403 1.1 christos dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, maxDictSize, srcBuffer,
404 1.1 christos sampleSizes, nbSamplesLoaded, *coverParams);
405 1.1 christos }
406 1.1 christos } else if (fastCoverParams != NULL) {
407 1.1 christos if (optimize) {
408 1.1 christos dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, maxDictSize,
409 1.1 christos srcBuffer, sampleSizes, nbSamplesLoaded,
410 1.1 christos fastCoverParams);
411 1.1 christos if (!ZDICT_isError(dictSize)) {
412 1.1 christos unsigned splitPercentage = (unsigned)(fastCoverParams->splitPoint * 100);
413 1.1 christos DISPLAYLEVEL(2, "k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\naccel=%u\n", fastCoverParams->k,
414 1.1 christos fastCoverParams->d, fastCoverParams->f, fastCoverParams->steps, splitPercentage,
415 1.1 christos fastCoverParams->accel);
416 1.1 christos }
417 1.1 christos } else {
418 1.1 christos dictSize = ZDICT_trainFromBuffer_fastCover(dictBuffer, maxDictSize, srcBuffer,
419 1.1 christos sampleSizes, nbSamplesLoaded, *fastCoverParams);
420 1.1 christos }
421 1.1 christos } else {
422 1.1 christos assert(0 /* Impossible */);
423 1.1 christos }
424 1.1 christos if (ZDICT_isError(dictSize)) {
425 1.1 christos DISPLAYLEVEL(1, "dictionary training failed : %s \n", ZDICT_getErrorName(dictSize)); /* should not happen */
426 1.1 christos result = 1;
427 1.1 christos goto _cleanup;
428 1.1 christos }
429 1.1 christos /* save dict */
430 1.1 christos DISPLAYLEVEL(2, "Save dictionary of size %u into file %s \n", (unsigned)dictSize, dictFileName);
431 1.1 christos DiB_saveDict(dictFileName, dictBuffer, dictSize);
432 1.1 christos }
433 1.1 christos
434 1.1 christos /* clean up */
435 1.1 christos _cleanup:
436 1.1 christos free(srcBuffer);
437 1.1 christos free(sampleSizes);
438 1.1 christos free(dictBuffer);
439 1.1 christos return result;
440 1.1 christos }
441