Project Alice
Loading...
Searching...
No Matches
fse.h
Go to the documentation of this file.
1/* ******************************************************************
2 * FSE : Finite State Entropy codec
3 * Public Prototypes declaration
4 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 *
6 * You can contact the author at :
7 * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
8 *
9 * This source code is licensed under both the BSD-style license (found in the
10 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11 * in the COPYING file in the root directory of this source tree).
12 * You may select, at your option, one of the above-listed licenses.
13****************************************************************** */
14
15#if defined (__cplusplus)
16extern "C" {
17#endif
18
19#ifndef FSE_H
20#define FSE_H
21
22
23/*-*****************************************
24* Dependencies
25******************************************/
26#include "zstd_deps.h" /* size_t, ptrdiff_t */
27
28
29/*-*****************************************
30* FSE_PUBLIC_API : control library symbols visibility
31******************************************/
32#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
33# define FSE_PUBLIC_API __attribute__ ((visibility ("default")))
34#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
35# define FSE_PUBLIC_API __declspec(dllexport)
36#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
37# define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
38#else
39# define FSE_PUBLIC_API
40#endif
41
42/*------ Version ------*/
43#define FSE_VERSION_MAJOR 0
44#define FSE_VERSION_MINOR 9
45#define FSE_VERSION_RELEASE 0
46
47#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
48#define FSE_QUOTE(str) #str
49#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
50#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
51
52#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)
53FSE_PUBLIC_API unsigned FSE_versionNumber(void);
56/*-*****************************************
57* Tool functions
58******************************************/
59FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
60
61/* Error Management */
62FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
63FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */
64
65
66/*-*****************************************
67* FSE detailed API
68******************************************/
87/* *** COMPRESSION *** */
88
93FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
94
106FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
107 const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);
108
112FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
113
118FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
119 const short* normalizedCounter,
120 unsigned maxSymbolValue, unsigned tableLog);
121
124typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
125
129FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
130
136FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);
137
182/* *** DECOMPRESSION *** */
183
189FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
190 unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
191 const void* rBuffer, size_t rBuffSize);
192
196FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
197 unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
198 const void* rBuffer, size_t rBuffSize, int bmi2);
199
200typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
201
230#endif /* FSE_H */
231
232
233#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
234#define FSE_H_FSE_STATIC_LINKING_ONLY
235
236/* *** Dependency *** */
237#include "bitstream.h"
238
239
240/* *****************************************
241* Static allocation
242*******************************************/
243/* FSE buffer bounds */
244#define FSE_NCOUNTBOUND 512
245#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
246#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
247
248/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
249#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))
250#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog)))
251
252/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
253#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
254#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))
255
256
257/* *****************************************
258 * FSE advanced API
259 ***************************************** */
260
261unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
264size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
267/* FSE_buildCTable_wksp() :
268 * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
269 * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
270 * See FSE_buildCTable_wksp() for breakdown of workspace usage.
271 */
272#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)
273#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
274size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
275
276#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)
277#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))
278FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
281#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + 1 + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
282#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
283size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
287typedef enum {
288 FSE_repeat_none,
289 FSE_repeat_check,
290 FSE_repeat_valid
291 } FSE_repeat;
292
293/* *****************************************
294* FSE symbol compression API
295*******************************************/
300typedef struct {
301 ptrdiff_t value;
302 const void* stateTable;
303 const void* symbolTT;
304 unsigned stateLog;
305} FSE_CState_t;
306
307static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);
308
309static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);
310
311static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);
312
357/* *****************************************
358* FSE symbol decompression API
359*******************************************/
360typedef struct {
361 size_t state;
362 const void* table; /* precise table may vary, depending on U16 */
363} FSE_DState_t;
364
365
366static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
367
368static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
369
370static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
371
422/* *****************************************
423* FSE unsafe API
424*******************************************/
425static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
426/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
427
428
429/* *****************************************
430* Implementation of inlined functions
431*******************************************/
432typedef struct {
433 int deltaFindState;
434 U32 deltaNbBits;
435} FSE_symbolCompressionTransform; /* total 8 bytes */
436
437MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
438{
439 const void* ptr = ct;
440 const U16* u16ptr = (const U16*) ptr;
441 const U32 tableLog = MEM_read16(ptr);
442 statePtr->value = (ptrdiff_t)1<<tableLog;
443 statePtr->stateTable = u16ptr+2;
444 statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);
445 statePtr->stateLog = tableLog;
446}
447
448
452MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)
453{
454 FSE_initCState(statePtr, ct);
455 { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
456 const U16* stateTable = (const U16*)(statePtr->stateTable);
457 U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
458 statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
459 statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
460 }
461}
462
463MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)
464{
465 FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
466 const U16* const stateTable = (const U16*)(statePtr->stateTable);
467 U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
468 BIT_addBits(bitC, (size_t)statePtr->value, nbBitsOut);
469 statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
470}
471
472MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
473{
474 BIT_addBits(bitC, (size_t)statePtr->value, statePtr->stateLog);
475 BIT_flushBits(bitC);
476}
477
478
479/* FSE_getMaxNbBits() :
480 * Approximate maximum cost of a symbol, in bits.
481 * Fractional get rounded up (i.e. a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)
482 * note 1 : assume symbolValue is valid (<= maxSymbolValue)
483 * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
484MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)
485{
486 const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
487 return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;
488}
489
490/* FSE_bitCost() :
491 * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)
492 * note 1 : assume symbolValue is valid (<= maxSymbolValue)
493 * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
494MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)
495{
496 const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
497 U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;
498 U32 const threshold = (minNbBits+1) << 16;
499 assert(tableLog < 16);
500 assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */
501 { U32 const tableSize = 1 << tableLog;
502 U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);
503 U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */
504 U32 const bitMultiplier = 1 << accuracyLog;
505 assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);
506 assert(normalizedDeltaFromThreshold <= bitMultiplier);
507 return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;
508 }
509}
510
511
512/* ====== Decompression ====== */
513
514typedef struct {
515 U16 tableLog;
516 U16 fastMode;
517} FSE_DTableHeader; /* sizeof U32 */
518
519typedef struct
520{
521 unsigned short newState;
522 unsigned char symbol;
523 unsigned char nbBits;
524} FSE_decode_t; /* size == U32 */
525
526MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
527{
528 const void* ptr = dt;
529 const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
530 DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
531 BIT_reloadDStream(bitD);
532 DStatePtr->table = dt + 1;
533}
534
535MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)
536{
537 FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
538 return DInfo.symbol;
539}
540
541MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
542{
543 FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
544 U32 const nbBits = DInfo.nbBits;
545 size_t const lowBits = BIT_readBits(bitD, nbBits);
546 DStatePtr->state = DInfo.newState + lowBits;
547}
548
549MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
550{
551 FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
552 U32 const nbBits = DInfo.nbBits;
553 BYTE const symbol = DInfo.symbol;
554 size_t const lowBits = BIT_readBits(bitD, nbBits);
555
556 DStatePtr->state = DInfo.newState + lowBits;
557 return symbol;
558}
559
562MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
563{
564 FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
565 U32 const nbBits = DInfo.nbBits;
566 BYTE const symbol = DInfo.symbol;
567 size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
568
569 DStatePtr->state = DInfo.newState + lowBits;
570 return symbol;
571}
572
573MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
574{
575 return DStatePtr->state == 0;
576}
577
578
579
580#ifndef FSE_COMMONDEFS_ONLY
581
582/* **************************************************************
583* Tuning parameters
584****************************************************************/
590#ifndef FSE_MAX_MEMORY_USAGE
591# define FSE_MAX_MEMORY_USAGE 14
592#endif
593#ifndef FSE_DEFAULT_MEMORY_USAGE
594# define FSE_DEFAULT_MEMORY_USAGE 13
595#endif
596#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)
597# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE"
598#endif
599
603#ifndef FSE_MAX_SYMBOL_VALUE
604# define FSE_MAX_SYMBOL_VALUE 255
605#endif
606
607/* **************************************************************
608* template functions type & suffix
609****************************************************************/
610#define FSE_FUNCTION_TYPE BYTE
611#define FSE_FUNCTION_EXTENSION
612#define FSE_DECODE_TYPE FSE_decode_t
613
614
615#endif /* !FSE_COMMONDEFS_ONLY */
616
617
618/* ***************************************************************
619* Constants
620*****************************************************************/
621#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2)
622#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
623#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
624#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
625#define FSE_MIN_TABLELOG 5
626
627#define FSE_TABLELOG_ABSOLUTE_MAX 15
628#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
629# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
630#endif
631
632#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
633
634
635#endif /* FSE_STATIC_LINKING_ONLY */
636
637
638#if defined (__cplusplus)
639}
640#endif
MEM_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, unsigned nbBits)
Definition: bitstream.h:361
MEM_STATIC void BIT_flushBits(BIT_CStream_t *bitC)
Definition: bitstream.h:220
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, unsigned nbBits)
Definition: bitstream.h:370
MEM_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
Definition: bitstream.h:179
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD)
Definition: bitstream.h:411
#define MEM_STATIC
Definition: compiler.h:103
#define assert(condition)
Definition: debug.h:74
FSE_PUBLIC_API size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSymbolValuePtr, unsigned *tableLogPtr, const void *rBuffer, size_t rBuffSize)
FSE_PUBLIC_API size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
Definition: fse_compress.c:330
FSE_PUBLIC_API const char * FSE_getErrorName(size_t code)
unsigned FSE_CTable
Definition: fse.h:124
FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short *normalizedCounter, unsigned *maxSymbolValuePtr, unsigned *tableLogPtr, const void *rBuffer, size_t rBuffSize, int bmi2)
FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
FSE_PUBLIC_API size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, const unsigned *count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount)
Definition: fse_compress.c:465
FSE_PUBLIC_API unsigned FSE_versionNumber(void)
FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
Definition: fse_compress.c:223
FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)
Definition: fse_compress.c:371
FSE_PUBLIC_API size_t FSE_compressBound(size_t size)
Definition: fse_compress.c:623
unsigned FSE_DTable
Definition: fse.h:200
FSE_PUBLIC_API size_t FSE_compress_usingCTable(void *dst, size_t dstCapacity, const void *src, size_t srcSize, const FSE_CTable *ct)
Definition: fse_compress.c:610
#define FSE_PUBLIC_API
Definition: fse.h:39
size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workSpace, size_t wkspSize)
Definition: fse_compress.c:68
unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)
Definition: fse_compress.c:357
size_t FSE_buildCTable_rle(FSE_CTable *ct, BYTE symbolValue)
Definition: fse_compress.c:528
#define FSE_isError
size_t FSE_decompress_wksp_bmi2(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workSpace, size_t wkspSize, int bmi2)
size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workSpace, size_t wkspSize)
MEM_STATIC U16 MEM_read16(const void *memPtr)
Definition: mem.h:197
unsigned char BYTE
Definition: mem.h:58
unsigned int U32
Definition: mem.h:69
unsigned short U16
Definition: mem.h:64
Definition: table.hpp:10