From a8d53959c6b3efd31d8726a612725253ab2c1441 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 11 Feb 2022 11:48:22 +0100
Subject: [PATCH 01/46] change build environment form make to meson

---
 Makefile                      |   50 -
 doc/doxygen/Doxyfile          | 2658 ++++++++++++++++++++++++++++++++
 doc/doxygen/Doxyfile.in       | 2660 +++++++++++++++++++++++++++++++++
 doc/doxygen/DoxygenLayout.xml |  194 +++
 doc/doxygen/bootstrap.min.css |    6 +
 doc/doxygen/bootstrap.min.js  |    7 +
 doc/doxygen/customdoxygen.css |  306 ++++
 doc/doxygen/doxy-boot.js      |  121 ++
 doc/doxygen/footer.html       |   26 +
 doc/doxygen/header.html       |   47 +
 doc/doxygen/meson.build       |   38 +
 include/meson.build           |   13 +
 meson.build                   |   27 +
 meson_options.txt             |    2 +
 test/cmp_icu/meson.build      |   14 +
 test/cmp_icu/test_cmp_icu.c   |  128 ++
 test/cmp_tool/Makefile        |   25 -
 test/cmp_tool/meson.build     |    4 +
 test/meson.build              |   33 +
 19 files changed, 6284 insertions(+), 75 deletions(-)
 delete mode 100644 Makefile
 create mode 100644 doc/doxygen/Doxyfile
 create mode 100644 doc/doxygen/Doxyfile.in
 create mode 100644 doc/doxygen/DoxygenLayout.xml
 create mode 100644 doc/doxygen/bootstrap.min.css
 create mode 100644 doc/doxygen/bootstrap.min.js
 create mode 100644 doc/doxygen/customdoxygen.css
 create mode 100644 doc/doxygen/doxy-boot.js
 create mode 100644 doc/doxygen/footer.html
 create mode 100644 doc/doxygen/header.html
 create mode 100644 doc/doxygen/meson.build
 create mode 100644 include/meson.build
 create mode 100644 meson.build
 create mode 100644 meson_options.txt
 create mode 100644 test/cmp_icu/meson.build
 create mode 100644 test/cmp_icu/test_cmp_icu.c
 delete mode 100644 test/cmp_tool/Makefile
 create mode 100644 test/cmp_tool/meson.build
 create mode 100644 test/meson.build

diff --git a/Makefile b/Makefile
deleted file mode 100644
index 6038a87..0000000
--- a/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-CC               = gcc
-SOURCEDIR	       = lib
-INCLUDEDIR       = include
-BUILDDIR         = ./
-CFLAGS          := -Wall -Wextra -std=gnu99 -mno-ms-bitfields -pedantic -Wshadow \
-		    -Wunreachable-code #-Wdocumentation #-Wsign-conversion
-RELCFLAGS       := -O2 # Release flags
-DBCFLAGS        := -O0 -g3 -fsanitize=address -fsanitize=undefined #debug flags
-COVFLAGS        := -fprofile-arcs -ftest-coverage #coverage flags
-CPPFLAGS        := -I $(INCLUDEDIR)
-LDFLAGS         := -lm
-SOURCES         := cmp_tool.c \
-		    $(SOURCEDIR)/rmap.c \
-		    $(SOURCEDIR)/rdcu_ctrl.c \
-		    $(SOURCEDIR)/rdcu_cmd.c \
-		    $(SOURCEDIR)/rdcu_rmap.c \
-		    $(SOURCEDIR)/cmp_support.c \
-		    $(SOURCEDIR)/cmp_data_types.c \
-		    $(SOURCEDIR)/cmp_rdcu.c \
-		    $(SOURCEDIR)/cmp_icu.c \
-		    $(SOURCEDIR)/decmp.c \
-		    $(SOURCEDIR)/rdcu_pkt_to_file.c \
-		    $(SOURCEDIR)/cmp_guess.c \
-		    $(SOURCEDIR)/cmp_io.c \
-		    $(SOURCEDIR)/cmp_entity.c
-TARGET          := cmp_tool
-
-DEBUG?=1
-ifeq  "$(shell expr $(DEBUG) \> 1)" "1"
-	    CFLAGS += -DDEBUGLEVEL=$(DEBUG)
-else
-	    CFLAGS += -DDEBUGLEVEL=1
-endif
-
-
-all: $(SOURCES)
-	$(CC) $(CPPFLAGS) $(CFLAGS) $(RELCFLAGS) $^ -o $(TARGET) $(LDFLAGS)
-
-debug: $(SOURCES)
-	$(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $^ -o $(TARGET) $(LDFLAGS)
-
-integration: $(SOURCES)
-	$(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $(COVFLAGS) $^ -o $(TARGET) $(LDFLAGS)
-	pytest test/cmp_tool/cmp_tool_integration_test.py
-	lcov --rc lcov_branch_coverage=1 --capture --directory ./ --output-file coverage.info
-	genhtml --rc lcov_branch_coverage=1 --branch-coverage coverage.info --output-directory out
-#firefox out/index.html
-
-clean:
-	rm -rf $(TARGET) *.gcno *.gcda coverage.info out
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
new file mode 100644
index 0000000..5bcc6da
--- /dev/null
+++ b/doc/doxygen/Doxyfile
@@ -0,0 +1,2658 @@
+# Doxyfile 1.9.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "PLATO cmp_tool"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = 0.09 #TODO
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "PLATO Compression/Decompression Tool"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = YES
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS   = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE        = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    = "/bin/sh -c 'git log --pretty=\"format:%ci, author:%aN <%aE>, commit:%h\" -1 \"${1}\" || echo no git'"
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = YES
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR          = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = ../
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.l \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.pyw \
+                         *.f90 \
+                         *.f95 \
+                         *.f03 \
+                         *.f08 \
+                         *.f18 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# ANamespace::AClass, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            = header.html
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            = footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  = customdoxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL         =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR           = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS       = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE      =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION        = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7-latest/tex.html
+# #tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP        = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = ../include
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
+# The default value is: YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = YES
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH    = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = YES
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
+DOT_CLEANUP            = YES
diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in
new file mode 100644
index 0000000..f4fba51
--- /dev/null
+++ b/doc/doxygen/Doxyfile.in
@@ -0,0 +1,2660 @@
+# Doxyfile 1.9.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "PLATO cmp_tool"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = @VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "PLATO Compression/Decompression Tool"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = YES
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS   = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 1
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE        = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    = "/bin/sh -c 'git log --pretty=\"format:%ci, author:%aN <%aE>, commit:%h\" -1 \"${1}\" || echo no git'"
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            = @SRCDIR@/doc/DoxygenLayout.xml
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR          = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = @SRCDIR@
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.l \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.pyw \
+                         *.f90 \
+                         *.f95 \
+                         *.f03 \
+                         *.f08 \
+                         *.f18 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                = @BUILDDIR@
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# ANamespace::AClass, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             = images #TODO
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            = @SRCDIR@/doc/header.html
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            = @SRCDIR@/doc/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  = @SRCDIR@/doc/customdoxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       = @SRCDIR@/doc/bootstrap.min.css \
+                         @SRCDIR@/doc/bootstrap.min.js \
+                         @SRCDIR@/doc/doxy-boot.js
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL         =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR           = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS       = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE      =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION        = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7-latest/tex.html
+# #tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP        = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = @SRCDIR@/include @BUILDDIR@/include
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = @HAVE_DOT@
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
+# The default value is: YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = YES
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH    = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = YES
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
+DOT_CLEANUP            = YES
diff --git a/doc/doxygen/DoxygenLayout.xml b/doc/doxygen/DoxygenLayout.xml
new file mode 100644
index 0000000..7479687
--- /dev/null
+++ b/doc/doxygen/DoxygenLayout.xml
@@ -0,0 +1,194 @@
+<doxygenlayout version="1.0">
+  <!-- Generated by doxygen 1.8.11 -->
+  <!-- Navigation index tabs for HTML output -->
+  <navindex>
+    <tab type="mainpage" visible="yes" title=""/>
+    <tab type="pages" visible="yes" title="" intro=""/>
+    <tab type="modules" visible="yes" title="" intro=""/>
+    <tab type="namespaces" visible="yes" title="">
+      <tab type="namespacelist" visible="yes" title="" intro=""/>
+      <tab type="namespacemembers" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="classes" visible="yes" title="">
+      <tab type="classlist" visible="yes" title="" intro=""/>
+      <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> 
+      <tab type="hierarchy" visible="yes" title="" intro=""/>
+      <tab type="classmembers" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="files" visible="yes" title="">
+      <tab type="filelist" visible="yes" title="" intro=""/>
+      <tab type="globals" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="examples" visible="yes" title="" intro=""/>  
+  </navindex>
+
+  <!-- Layout definition for a class page -->
+  <class>
+    <briefdescription visible="yes"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <inheritancegraph visible="$CLASS_GRAPH"/>
+    <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+    <detaileddescription title=""/>
+    <memberdecl>
+      <nestedclasses visible="yes" title=""/>
+      <publictypes title=""/>
+      <services title=""/>
+      <interfaces title=""/>
+      <publicslots title=""/>
+      <signals title=""/>
+      <publicmethods title=""/>
+      <publicstaticmethods title=""/>
+      <publicattributes title=""/>
+      <publicstaticattributes title=""/>
+      <protectedtypes title=""/>
+      <protectedslots title=""/>
+      <protectedmethods title=""/>
+      <protectedstaticmethods title=""/>
+      <protectedattributes title=""/>
+      <protectedstaticattributes title=""/>
+      <packagetypes title=""/>
+      <packagemethods title=""/>
+      <packagestaticmethods title=""/>
+      <packageattributes title=""/>
+      <packagestaticattributes title=""/>
+      <properties title=""/>
+      <events title=""/>
+      <privatetypes title=""/>
+      <privateslots title=""/>
+      <privatemethods title=""/>
+      <privatestaticmethods title=""/>
+      <privateattributes title=""/>
+      <privatestaticattributes title=""/>
+      <friends title=""/>
+      <related title="" subtitle=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <memberdef>
+      <inlineclasses title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <services title=""/>
+      <interfaces title=""/>
+      <constructors title=""/>
+      <functions title=""/>
+      <related title=""/>
+      <variables title=""/>
+      <properties title=""/>
+      <events title=""/>
+    </memberdef>
+    <allmemberslink visible="yes"/>
+    <usedfiles visible="$SHOW_USED_FILES"/>
+    <authorsection visible="yes"/>
+  </class>
+
+  <!-- Layout definition for a namespace page -->
+  <namespace>
+    <briefdescription visible="yes"/>
+    <detaileddescription title=""/>
+    <memberdecl>
+      <nestednamespaces visible="yes" title=""/>
+      <constantgroups visible="yes" title=""/>
+      <classes visible="yes" title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <memberdef>
+      <inlineclasses title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection visible="yes"/>
+  </namespace>
+
+  <!-- Layout definition for a file page -->
+  <file>
+    <briefdescription visible="yes"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <includegraph visible="$INCLUDE_GRAPH"/>
+    <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+    <sourcelink visible="yes"/>
+    <detaileddescription title=""/>
+    <memberdecl>
+      <classes visible="yes" title=""/>
+      <namespaces visible="yes" title=""/>
+      <constantgroups visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <memberdef>
+      <inlineclasses title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection/>
+  </file>
+
+  <!-- Layout definition for a group page -->
+  <group>
+    <briefdescription visible="yes"/>
+    <groupgraph visible="$GROUP_GRAPHS"/>
+    <detaileddescription title=""/>
+    <memberdecl>
+      <nestedgroups visible="yes" title=""/>
+      <dirs visible="yes" title=""/>
+      <files visible="yes" title=""/>
+      <namespaces visible="yes" title=""/>
+      <classes visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <signals title=""/>
+      <publicslots title=""/>
+      <protectedslots title=""/>
+      <privateslots title=""/>
+      <events title=""/>
+      <properties title=""/>
+      <friends title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <memberdef>
+      <pagedocs/>
+      <inlineclasses title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <signals title=""/>
+      <publicslots title=""/>
+      <protectedslots title=""/>
+      <privateslots title=""/>
+      <events title=""/>
+      <properties title=""/>
+      <friends title=""/>
+    </memberdef>
+    <authorsection visible="yes"/>
+  </group>
+
+  <!-- Layout definition for a directory page -->
+  <directory>
+    <briefdescription visible="yes"/>
+    <directorygraph visible="yes"/>
+    <memberdecl>
+      <dirs visible="yes"/>
+      <files visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+  </directory>
+</doxygenlayout>
diff --git a/doc/doxygen/bootstrap.min.css b/doc/doxygen/bootstrap.min.css
new file mode 100644
index 0000000..4cf729e
--- /dev/null
+++ b/doc/doxygen/bootstrap.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/doc/doxygen/bootstrap.min.js b/doc/doxygen/bootstrap.min.js
new file mode 100644
index 0000000..e79c065
--- /dev/null
+++ b/doc/doxygen/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>2)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.6",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.6",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.6",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.6",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.6",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);return this.$element.trigger(g),g.isDefaultPrevented()?void 0:(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=d?{top:0,left:0}:b.offset(),g={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},h=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,g,h,f)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");
+d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.6",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
\ No newline at end of file
diff --git a/doc/doxygen/customdoxygen.css b/doc/doxygen/customdoxygen.css
new file mode 100644
index 0000000..6a32ca7
--- /dev/null
+++ b/doc/doxygen/customdoxygen.css
@@ -0,0 +1,306 @@
+/*
+h1, .h1, h2, .h2, h3, .h3{
+    font-weight: 200 !important;
+}
+*/
+
+h1,.h1 {
+  font-size: 24px;
+}
+
+h2,.h2 {
+  font-size: 20px;
+}
+
+h3,.h3 {
+  font-size: 16px;
+}
+
+h4,.h4 {
+  font-size: 14px;
+}
+
+h5,.h5 {
+  font-size: 12px;
+}
+
+h6,.h6 {
+  font-size: 10px;
+}
+
+
+
+#navrow1, #navrow2, #navrow3, #navrow4, #navrow5{
+    border-bottom: 1px solid #706d6e;
+}
+
+.adjust-right {
+margin-left: 30px !important;
+font-size: 1.15em !important;
+}
+.navbar{
+ border: 0px solid #222 !important;
+}
+
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html,
+body {
+    height: 100%;
+    /* The html and body elements cannot have any padding or margin. */
+}
+
+img {
+max-width:100%;
+max-height:100%;
+}
+
+/* Wrapper for page content to push down footer */
+#wrap {
+    min-height: 100%;
+    height: auto;
+    /* Negative indent footer by its height */
+    margin: 0 auto -60px;
+    /* Pad bottom by footer height */
+    padding: 0 0 60px;
+}
+
+/* Set the fixed height of the footer here */
+#footer {
+    font-size: 0.9em;
+    padding: 8px 0px;
+    background-color: #f5f5f5;
+}
+
+.footer-row {
+    line-height: 44px;
+}
+
+#footer > .container {
+    padding-left: 15px;
+    padding-right: 15px;
+}
+
+.footer-follow-icon {
+    margin-left: 3px;
+    text-decoration: none !important;
+}
+
+.footer-follow-icon img {
+    width: 20px;
+}
+
+.footer-link {
+    padding-top: 5px;
+    display: inline-block;
+    color: #999999;
+    text-decoration: none;
+}
+
+.footer-copyright {
+    text-align: center;
+}
+
+
+@media (min-width: 992px) {
+    .footer-row {
+        text-align: left;
+    }
+
+    .footer-icons {
+        text-align: right;
+    }
+}
+@media (max-width: 991px) {
+    .footer-row {
+        text-align: center;
+    }
+
+    .footer-icons {
+        text-align: center;
+    }
+}
+
+/* DOXYGEN Code Styles
+----------------------------------- */
+
+	
+div.ingroups {
+    font-size: 16pt;
+    width: 50%;
+    text-align: left;
+    padding-top: 10px;
+}
+
+a.qindex {
+    font-size:  8pt;
+}
+
+a.qindexHL {
+    font-size:  9pt;
+    font-weight: bold;
+    background-color: #9CAFD4;
+    color: #ffffff;
+    border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+    color: #ffffff;
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+    color: #4665A2;
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+    color: #4665A2;
+}
+
+/* @end */
+
+dl.el {
+    margin-left: -1cm;
+}
+
+pre.fragment {
+    border: 1px solid #C4CFE5;
+    background-color: #FBFCFD;
+    padding: 4px 6px;
+    margin: 4px 8px 4px 2px;
+    overflow: auto;
+    word-wrap: break-word;
+    font-size:  8pt;
+    line-height: 125%;
+    font-family: monospace, fixed;
+}
+
+div.navtab {
+    text-align: left;
+    padding-left: 5px;
+    margin-right: 5px;
+}
+
+div.fragment {
+    padding: 4px 6px;
+    margin: 4px 8px 4px 2px;
+    border: 1px solid #C4CFE5;
+}
+
+div.line {
+    font-family: monospace, fixed;
+    font-size: 13px;
+    min-height: 13px;
+    line-height: 1.0;
+    text-wrap: unrestricted;
+    white-space: -moz-pre-wrap; /* Moz */
+    white-space: -pre-wrap;     /* Opera 4-6 */
+    white-space: -o-pre-wrap;   /* Opera 7 */
+    white-space: pre-wrap;      /* CSS3  */
+    word-wrap: break-word;      /* IE 5.5+ */
+    text-indent: -53px;
+    padding-left: 53px;
+    padding-bottom: 0px;
+    margin: 0px;
+    -webkit-transition-property: background-color, box-shadow;
+    -webkit-transition-duration: 0.5s;
+    -moz-transition-property: background-color, box-shadow;
+    -moz-transition-duration: 0.5s;
+    -ms-transition-property: background-color, box-shadow;
+    -ms-transition-duration: 0.5s;
+    -o-transition-property: background-color, box-shadow;
+    -o-transition-duration: 0.5s;
+    transition-property: background-color, box-shadow;
+    transition-duration: 0.5s;
+}
+
+div.line.glow {
+    background-color: cyan;
+    box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+    padding-right: 4px;
+    text-align: right;
+    border-right: 2px solid #0F0;
+    background-color: #E8E8E8;
+    white-space: pre;
+}
+span.lineno a {
+    background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+    background-color: #C8C8C8;
+}
+
+div.groupHeader {
+    margin-left: 16px;
+    margin-top: 12px;
+    font-weight: bold;
+}
+
+div.groupText {
+    margin-left: 16px;
+    font-style: italic;
+}
+
+.caption {
+	font-weight: bold;
+	padding-top: 10px;
+	padding-bottom: 20px;
+}
+/* @group Code Colorization */
+
+span.keyword {
+    color: #008000
+}
+
+span.keywordtype {
+    color: #604020
+}
+
+span.keywordflow {
+    color: #e08000
+}
+
+span.comment {
+    color: #800000
+}
+
+span.preprocessor {
+    color: #806020
+}
+
+span.stringliteral {
+    color: #002080
+}
+
+span.charliteral {
+    color: #008080
+}
+
+span.vhdldigit {
+    color: #ff00ff
+}
+
+span.vhdlchar {
+    color: #000000
+}
+
+span.vhdlkeyword {
+    color: #700070
+}
+
+span.vhdllogic {
+    color: #ff0000
+}
+
+blockquote {
+    background-color: #F7F8FB;
+    border-left: 2px solid #9CAFD4;
+    margin: 0 24px 0 4px;
+    padding: 0 12px 0 16px;
+}
+
diff --git a/doc/doxygen/doxy-boot.js b/doc/doxygen/doxy-boot.js
new file mode 100644
index 0000000..f045d16
--- /dev/null
+++ b/doc/doxygen/doxy-boot.js
@@ -0,0 +1,121 @@
+$( document ).ready(function() {
+
+    $("div.headertitle").addClass("page-header");
+    $("div.title").addClass("h1");
+
+    $('li > a[href="index.html"] > span').before("<i class='fa fa-cog'></i> ");
+    $('li > a[href="index.html"] > span').text("CHEOPS IBSW");
+    $('li > a[href="modules.html"] > span').before("<i class='fa fa-square'></i> ");
+    $('li > a[href="namespaces.html"] > span').before("<i class='fa fa-bars'></i> ");
+    $('li > a[href="annotated.html"] > span').before("<i class='fa fa-list-ul'></i> ");
+    $('li > a[href="classes.html"] > span').before("<i class='fa fa-book'></i> ");
+    $('li > a[href="inherits.html"] > span').before("<i class='fa fa-sitemap'></i> ");
+    $('li > a[href="functions.html"] > span').before("<i class='fa fa-list'></i> ");
+    $('li > a[href="functions_func.html"] > span').before("<i class='fa fa-list'></i> ");
+    $('li > a[href="functions_vars.html"] > span').before("<i class='fa fa-list'></i> ");
+    $('li > a[href="functions_enum.html"] > span').before("<i class='fa fa-list'></i> ");
+    $('li > a[href="functions_eval.html"] > span').before("<i class='fa fa-list'></i> ");
+    $('img[src="ftv2ns.png"]').replaceWith('<span class="label label-danger">N</span> ');
+    $('img[src="ftv2cl.png"]').replaceWith('<span class="label label-danger">C</span> ');
+
+    $("ul.tablist").addClass("nav nav-pills nav-justified");
+    $("ul.tablist").css("margin-top", "0.5em");
+    $("ul.tablist").css("margin-bottom", "0.5em");
+    $("li.current").addClass("active");
+    $("iframe").attr("scrolling", "yes");
+
+    $("#nav-path > ul").addClass("breadcrumb");
+
+    $("table.params").addClass("table");
+    $("div.ingroups").wrapInner("<small></small>");
+    $("div.levels").css("margin", "0.5em");
+    $("div.levels > span").addClass("btn btn-default btn-xs");
+    $("div.levels > span").css("margin-right", "0.25em");
+
+    $("table.directory").addClass("table table-striped");
+    $("div.summary > a").addClass("btn btn-default btn-xs");
+    $("table.fieldtable").addClass("table");
+    $(".fragment").addClass("well");
+    $(".memitem").addClass("panel panel-default");
+    $(".memproto").addClass("panel-heading");
+    $(".memdoc").addClass("panel-body");
+    $("span.mlabel").addClass("label label-info");
+
+    $("table.memberdecls").addClass("table");
+    $("[class^=memitem]").addClass("active");
+
+    $("div.ah").addClass("btn btn-default");
+    $("span.mlabels").addClass("pull-right");
+    $("table.mlabels").css("width", "100%")
+    $("td.mlabels-right").addClass("pull-right");
+
+    $("div.ttc").addClass("panel panel-primary");
+    $("div.ttname").addClass("panel-heading");
+    $("div.ttname a").css("color", 'white');
+    $("div.ttdef,div.ttdoc,div.ttdeci").addClass("panel-body");
+
+    $('#MSearchBox').parent().remove();
+
+    $('div.fragment.well div.line:first').css('margin-top', '15px');
+    $('div.fragment.well div.line:last').css('margin-bottom', '15px');
+	
+	$('table.doxtable').removeClass('doxtable').addClass('table table-striped table-bordered').each(function(){
+		$(this).prepend('<thead></thead>');
+		$(this).find('tbody > tr:first').prependTo($(this).find('thead'));
+		
+		$(this).find('td > span.success').parent().addClass('success');
+		$(this).find('td > span.warning').parent().addClass('warning');
+		$(this).find('td > span.danger').parent().addClass('danger');
+	});
+	
+	
+
+    if($('div.fragment.well div.ttc').length > 0)
+    {
+        $('div.fragment.well div.line:first').parent().removeClass('fragment well');
+    }
+
+    $('table.memberdecls').find('.memItemRight').each(function(){
+        $(this).contents().appendTo($(this).siblings('.memItemLeft'));
+        $(this).siblings('.memItemLeft').attr('align', 'left');
+    });
+	
+	function getOriginalWidthOfImg(img_element) {
+		var t = new Image();
+		t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src;
+		return t.width;
+	}
+	
+	$('div.dyncontent').find('img').each(function(){
+		if(getOriginalWidthOfImg($(this)[0]) > $('#content>div.container').width())
+			$(this).css('width', '100%');
+	});
+	
+	$(".memitem").removeClass('memitem');
+    $(".memproto").removeClass('memproto');
+    $(".memdoc").removeClass('memdoc');
+	$("span.mlabel").removeClass('mlabel');
+	$("table.memberdecls").removeClass('memberdecls');
+    $("[class^=memitem]").removeClass('memitem');
+    $("span.mlabels").removeClass('mlabels');
+    $("table.mlabels").removeClass('mlabels');
+    $("td.mlabels-right").removeClass('mlabels-right');
+	$(".navpath").removeClass('navpath');
+	$("li.navelem").removeClass('navelem');
+	$("a.el").removeClass('el');
+	$("div.ah").removeClass('ah');
+	$("div.header").removeClass("header");
+	
+	$('.mdescLeft').each(function(){
+		if($(this).html()=="&nbsp;") {
+			$(this).siblings('.mdescRight').attr('colspan', 2);
+			$(this).remove();
+		}
+	});
+	$('td.memItemLeft').each(function(){
+		if($(this).siblings('.memItemRight').html()=="") {
+			$(this).attr('colspan', 2);
+			$(this).siblings('.memItemRight').remove();
+		}
+	});
+});
diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html
new file mode 100644
index 0000000..f2fa204
--- /dev/null
+++ b/doc/doxygen/footer.html
@@ -0,0 +1,26 @@
+<!-- HTML footer for doxygen 1.8.8-->
+<!-- start footer part -->
+<!--BEGIN GENERATE_TREEVIEW-->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    $navpath
+    <li class="footer">$generatedby
+    <a href="http://www.doxygen.org/index.html">
+    <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
+  </ul>
+</div>
+<!--END GENERATE_TREEVIEW-->
+</div>
+</div>
+</div>
+</div>
+</div>
+<!--BEGIN !GENERATE_TREEVIEW-->
+<hr class="footer"/><address class="footer"><small>
+$generatedby &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
+</a> $doxygenversion
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+</body>
+</html>
diff --git a/doc/doxygen/header.html b/doc/doxygen/header.html
new file mode 100644
index 0000000..d4b85eb
--- /dev/null
+++ b/doc/doxygen/header.html
@@ -0,0 +1,47 @@
+<!-- HTML header for doxygen 1.8.8-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <!-- For Mobile Devices -->
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+
+        <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+        <meta name="generator" content="Doxygen $doxygenversion"/>
+
+        <script type="text/javascript" src="jquery.js"></script>
+
+        <!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+        <!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+        <!--<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>-->
+        <script type="text/javascript" src="$relpath^dynsections.js"></script>
+        $treeview
+        $search
+        $mathjax
+        <link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+
+	<link rel="stylesheet" href="$relpath^bootstrap.min.css">
+
+	$extrastylesheet
+
+        <script src="$relpath^bootstrap.min.js"></script>
+        <script type="text/javascript" src="$relpath^doxy-boot.js"></script>
+    </head>
+    <body>
+
+        <nav class="navbar navbar-default" role="navigation">
+            <div class="container">
+                <div class="navbar-header">
+			<a class="navbar-brand">
+				<img alt="Logo" align="left" style="margin-right: 1em;" src=$projectlogo/>
+				$projectname $projectnumber</a>
+                </div>
+            </div>
+        </nav>
+        <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+            <div class="content" id="content">
+                <div class="container">
+                    <div class="row">
+                        <div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
+                            <div style="margin-bottom: 15px;">
+<!-- end header part -->
diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build
new file mode 100644
index 0000000..b500bac
--- /dev/null
+++ b/doc/doxygen/meson.build
@@ -0,0 +1,38 @@
+doc_layout_files = files([
+  'DoxygenLayout.xml',
+  'bootstrap.min.css',
+  'customdoxygen.css',
+  'bootstrap.min.js',
+  'doxy-boot.js',
+  'header.html',
+  'footer.html'
+])
+
+doxygen = find_program('doxygen', required : false)
+
+#Build a Doxyfile based on Doxyfile.in
+cdata_doc = configuration_data()
+cdata_doc.set('VERSION', meson.project_version())
+cdata_doc.set('SRCDIR', meson.project_source_root())
+cdata_doc.set('BUILDDIR', meson.project_build_root())
+if find_program('dot', required : false).found()
+  cdata_doc.set('HAVE_DOT', 'YES')
+else
+  cdata_doc.set('HAVE_DOT', 'NO')
+endif
+
+doxy_file = configure_file(
+  input : 'Doxyfile.in',
+  output : 'Doxyfile',
+  configuration : cdata_doc,
+  install : false,
+)
+
+custom_target('doc',
+  input : doxy_file,
+  output : 'html',
+  depend_files : [doc_layout_files, main, cmplib_sources],
+  command : [doxygen, '@INPUT@'],
+  build_by_default : false,
+  console : true,
+)
diff --git a/include/meson.build b/include/meson.build
new file mode 100644
index 0000000..d5946c8
--- /dev/null
+++ b/include/meson.build
@@ -0,0 +1,13 @@
+# generate the configuration file
+cdata = configuration_data()
+cdata.set_quoted('PROGRAM_NAME', 'cmp_tool')
+cdata.set_quoted('VERSION_STR', meson.project_version())
+if get_option('argument_input_mode')
+  cdata.set('ARGUMENT_INPUT_MODE', '')
+endif
+
+configure_file(
+  output : 'cmp_tool-config.h',
+  configuration : cdata)
+
+incdir = include_directories('.')
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..59f2c05
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,27 @@
+project('cmp_tool', 'c',
+  version : '0.09',
+  license : 'GPL-2.0',
+  default_options : ['warning_level=3', 'c_std=gnu99']
+)
+
+if host_machine.system() == 'windows' and cc.get_id() == 'gcc'
+  # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)),
+  # you need to add -mno-ms-bitfields to make it work as expected.
+  # See: https://wintermade.it/blog/posts/__attribute__packed-on-windows-is-ignored-with-mingw.html
+  add_project_arguments('-mno-ms-bitfields', language : 'c')
+endif
+
+subdir('include')
+subdir('lib')
+
+main = files('cmp_tool.c')
+
+cmp_tool = executable('cmp_tool',
+  sources : main,
+  include_directories : incdir,
+  link_with : cmp_lib,
+  install : 'true'
+)
+
+subdir('test')
+subdir('doc/doxygen')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..fe8670e
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,2 @@
+option('argument_input_mode', type : 'boolean', value : false,
+  description : 'If set, the data file is set with the first argument and the model file with the second one')
diff --git a/test/cmp_icu/meson.build b/test/cmp_icu/meson.build
new file mode 100644
index 0000000..80c3e27
--- /dev/null
+++ b/test/cmp_icu/meson.build
@@ -0,0 +1,14 @@
+test_cmp_icu_files = files ([
+  'test_cmp_icu.c'
+])
+
+test_cmp_icu = executable('test_cmp_icu',
+   test_cmp_icu_files,
+   include_directories : incdir,
+   link_with : cmp_lib,
+   # c_args : ['-DMAIN']
+   dependencies : cunit_dep,
+   build_by_default : false
+)
+
+test('cmp_icu unit test', test_cmp_icu)
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
new file mode 100644
index 0000000..8bf30d6
--- /dev/null
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -0,0 +1,128 @@
+/*
+ *  Simple example of a CUnit unit test.
+ *
+ *  This program (crudely) demonstrates a very simple "black box"
+ *  test of the standard library functions fprintf() and fread().
+ *  It uses suite initialization and cleanup functions to open
+ *  and close a common temporary file used by the test functions.
+ *  The test functions then write to and read from the temporary
+ *  file in the course of testing the library functions.
+ *
+ *  The 2 test functions are added to a single CUnit suite, and
+ *  then run using the CUnit Basic interface.  The output of the
+ *  program (on CUnit version 2.0-2) is:
+ *
+ *           CUnit : A Unit testing framework for C.
+ *           http://cunit.sourceforge.net/
+ *
+ *       Suite: Suite_1
+ *         Test: test of fprintf() ... passed
+ *         Test: test of fread() ... passed
+ *
+ *       --Run Summary: Type      Total     Ran  Passed  Failed
+ *                      suites        1       1     n/a       0
+ *                      tests         2       2       2       0
+ *                      asserts       5       5       5       0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "CUnit/Basic.h"
+
+/* Pointer to the file used by the tests. */
+static FILE* temp_file = NULL;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int init_suite1(void)
+{
+	if (NULL == (temp_file = fopen("temp.txt", "w+"))) {
+		return -1;
+	}
+	else {
+		return 0;
+	}
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int clean_suite1(void)
+{
+	if (0 != fclose(temp_file)) {
+		return -1;
+	}
+	else {
+		temp_file = NULL;
+		return 0;
+	}
+}
+
+/* Simple test of fprintf().
+ * Writes test data to the temporary file and checks
+ * whether the expected number of bytes were written.
+ */
+void testFPRINTF(void)
+{
+	int i1 = 10;
+
+	if (NULL != temp_file) {
+		CU_ASSERT(0 == fprintf(temp_file, ""));
+		CU_ASSERT(2 == fprintf(temp_file, "Q\n"));
+		CU_ASSERT(7 == fprintf(temp_file, "i1 = %d", i1));
+	}
+}
+
+/* Simple test of fread().
+ * Reads the data previously written by testFPRINTF()
+ * and checks whether the expected characters are present.
+ * Must be run after testFPRINTF().
+ */
+void testFREAD(void)
+{
+	unsigned char buffer[20];
+
+	if (NULL != temp_file) {
+		rewind(temp_file);
+		CU_ASSERT(9 == fread(buffer, sizeof(unsigned char), 20, temp_file));
+		CU_ASSERT(0 == strncmp(buffer, "Q\ni1 = 10", 9));
+	}
+}
+
+/* The main() function for setting up and running the tests.
+ * Returns a CUE_SUCCESS on successful running, another
+ * CUnit error code on failure.
+ */
+int main()
+{
+	CU_pSuite pSuite = NULL;
+
+	/* initialize the CUnit test registry */
+	if (CUE_SUCCESS != CU_initialize_registry())
+		return CU_get_error();
+
+	/* add a suite to the registry */
+	pSuite = CU_add_suite("Suite_1", init_suite1, clean_suite1);
+	if (NULL == pSuite) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	/* add the tests to the suite */
+	/* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */
+	if ((NULL == CU_add_test(pSuite, "test of fprintf()", testFPRINTF)) ||
+	    (NULL == CU_add_test(pSuite, "test of fread()", testFREAD)))
+	{
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	/* Run all tests using the CUnit Basic interface */
+	CU_basic_set_mode(CU_BRM_VERBOSE);
+	CU_basic_run_tests();
+	CU_cleanup_registry();
+	return CU_get_error();
+}
diff --git a/test/cmp_tool/Makefile b/test/cmp_tool/Makefile
deleted file mode 100644
index 543ea13..0000000
--- a/test/cmp_tool/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-CC               = gcc
-SOURCEDIR	 =
-INCLUDES         = -I../../include
-PATH            +=
-CFLAGS          := -O0 -W -Wall -Wextra -std=gnu99 -Werror -pedantic -g3\
-		-fprofile-arcs -ftest-coverage
-CPPFLAGS        := -D__MAIN__ $(INCLUDES) -I$(SOURCEDIR)
-LDFLAGS         := -lcunit
-SOURCES         := $(wildcard *.c) ../../lib/cmp_tool_lib.c ../../lib/cmp_guess.c\
-		../../lib/cmp_support.c ../../lib/cmp_icu.c ../../lib/cmp_data_types.c
-OBJECTS         := $(patsubst %.c, $(BUILDDIR)/%.o, $(subst $(SOURCEDIR)/,, $(SOURCES)))
-TARGET          := test_cmp_tool
-
-
-all: $(SOURCES)
-	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ -o $(TARGET)
-
-coverage: all
-	./$(TARGET)
-	lcov --rc lcov_branch_coverage=1 --capture --directory ./ --output-file coverage.info
-	genhtml --rc lcov_branch_coverage=1 --branch-coverage coverage.info --output-directory out
-	#firefox out/index.html
-
-clean:
-	rm -r $(TARGET) *.gcno *.gcda coverage.info out/ tmp_stderr.log
diff --git a/test/cmp_tool/meson.build b/test/cmp_tool/meson.build
new file mode 100644
index 0000000..b60e2cf
--- /dev/null
+++ b/test/cmp_tool/meson.build
@@ -0,0 +1,4 @@
+int_test_file = files('cmp_tool_integration_test.py')
+
+pytest = find_program('pytest', required : false)
+test('Integration Test', pytest, args : ['--color=yes', '-vvv', int_test_file])
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..14a5f0c
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,33 @@
+# add checkpatch syntax-check target
+checkpatch = find_program('checkpatch.pl', 'checkpatch', required : false)
+checkpatch_args = [
+  '--no-tree', '-f',
+  '--show-types',
+  '--color=always',
+  '--ignore', 'SPDX_LICENSE_TAG,PREFER_DEFINED_ATTRIBUTE_MACRO,EMBEDDED_FILENAME,BLOCK_COMMENT_STYLE,EMBEDDED_FUNCTION_NAME',
+]
+run_target('syntax-check',
+ command : [checkpatch, checkpatch_args, main, cmplib_sources])
+
+# add cppcheck inspector target
+cppcheck = find_program('cppcheck', required : false)
+cppcheck_args = [
+  main, cmplib_sources,
+  '--clang',
+  '--cppcheck-build-dir='+meson.current_build_dir(),
+  '-I', 'include',
+  '--std=c89',
+  '--addon=misra.py',
+  '--bug-hunting',
+  '--enable=all',
+  '--inconclusive'
+]
+run_target('inspector',
+  command : [cppcheck, cppcheck_args]
+)
+
+cunit_dep = dependency('cunit')
+
+subdir('cmp_tool')
+subdir('cmp_icu')
+
-- 
GitLab


From 07a0445dde048930cf8a2c80eb8c981b4e9d59a3 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 11 Feb 2022 12:24:15 +0100
Subject: [PATCH 02/46] adapt code to cmp_tool-config.h file

---
 cmp_tool.c                                 | 23 +++++++++++-----------
 include/cmp_io.h                           |  1 -
 include/meson.build                        |  2 +-
 lib/cmp_io.c                               |  9 +++++----
 test/cmp_tool/cmp_tool_integration_test.py | 11 +++++------
 5 files changed, 22 insertions(+), 24 deletions(-)
 mode change 100644 => 100755 test/cmp_tool/cmp_tool_integration_test.py

diff --git a/cmp_tool.c b/cmp_tool.c
index fd8401f..90aa1df 100755
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -25,16 +25,15 @@
 #include <getopt.h>
 #include <time.h>
 
-#include "include/cmp_io.h"
-#include "include/cmp_icu.h"
-#include "include/decmp.h"
-#include "include/cmp_guess.h"
-#include "include/cmp_entity.h"
-#include "include/rdcu_pkt_to_file.h"
+#include "cmp_tool-config.h"
+#include "cmp_io.h"
+#include "cmp_icu.h"
+#include "decmp.h"
+#include "cmp_guess.h"
+#include "cmp_entity.h"
+#include "rdcu_pkt_to_file.h"
 
 
-#define VERSION "0.08"
-
 #define BUFFER_LENGTH_DEF_FAKTOR 2
 
 
@@ -190,7 +189,7 @@ int main(int argc, char **argv)
 			verbose_en = 1;
 			break;
 		case 'V': /* --version */
-			printf("%s version %s\n", PROGRAM_NAME, VERSION);
+			printf("%s version %s\n", PROGRAM_NAME, CMP_TOOL_VERSION);
 			exit(EXIT_SUCCESS);
 			break;
 		case DIFF_CFG_OPTION:
@@ -273,9 +272,9 @@ int main(int argc, char **argv)
 
 	printf("#########################################################\n");
 	printf("### PLATO Compression/Decompression Tool Version %s ###\n",
-	       VERSION);
+	       CMP_TOOL_VERSION);
 	printf("#########################################################\n");
-	if (!strcmp(VERSION, "0.07") || !strcmp(VERSION, "0.08"))
+	if (!strcmp(CMP_TOOL_VERSION, "0.07") || !strcmp(CMP_TOOL_VERSION, "0.08"))
 		printf("Info: Note that the behaviour of the cmp_tool has changed. From now on, the compressed data will be preceded by a header by default. The old behaviour can be achieved with the --no_header option.\n\n");
 
 	if (!data_file_name) {
@@ -629,7 +628,7 @@ static int add_cmp_ent_hdr(struct cmp_cfg *cfg, struct cmp_info *info,
 		cmp_bit_to_4byte(info->cmp_size));
 
 	ent = (struct cmp_entity *)cfg->icu_output_buf;
-	s = cmp_ent_build(ent, data_type, cmp_tool_gen_version_id(VERSION),
+	s = cmp_ent_build(ent, data_type, cmp_tool_gen_version_id(CMP_TOOL_VERSION),
 			  start_time, cmp_ent_create_timestamp(NULL), model_id,
 			  model_counter, info, cfg);
 	if (!s) {
diff --git a/include/cmp_io.h b/include/cmp_io.h
index 77dce35..179d59f 100644
--- a/include/cmp_io.h
+++ b/include/cmp_io.h
@@ -20,7 +20,6 @@
 #include "cmp_support.h"
 #include "cmp_entity.h"
 
-#define PROGRAM_NAME "cmp_tool"
 #define MAX_CONFIG_LINE 256
 
 #define DEFAULT_OUTPUT_PREFIX "OUTPUT"
diff --git a/include/meson.build b/include/meson.build
index d5946c8..491eef5 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -1,7 +1,7 @@
 # generate the configuration file
 cdata = configuration_data()
 cdata.set_quoted('PROGRAM_NAME', 'cmp_tool')
-cdata.set_quoted('VERSION_STR', meson.project_version())
+cdata.set_quoted('CMP_TOOL_VERSION', meson.project_version())
 if get_option('argument_input_mode')
   cdata.set('ARGUMENT_INPUT_MODE', '')
 endif
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 9f7fd72..9dc9ba1 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -24,10 +24,11 @@
 #include <ctype.h>
 #include <sys/stat.h>
 
-#include "../include/cmp_io.h"
-#include "../include/cmp_support.h"
-#include "../include/rdcu_cmd.h"
-#include "../include/byteorder.h"
+#include "cmp_tool-config.h"
+#include "cmp_io.h"
+#include "cmp_support.h"
+#include "rdcu_cmd.h"
+#include "byteorder.h"
 
 
 /**
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
old mode 100644
new mode 100755
index f5a022b..72d32c4
--- a/test/cmp_tool/cmp_tool_integration_test.py
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+import pytest
 import subprocess
 import shlex
 import sys
@@ -213,10 +215,7 @@ CMP_START_STR = \
 """#########################################################
 ### PLATO Compression/Decompression Tool Version %s ###
 #########################################################
-Info: Note that the behaviour of the cmp_tool has changed. From now on, the compressed data will be preceded by a header by default. The old behaviour can be achieved with the --no_header option.
-
 """ % (VERSION)
-print(CMP_START_STR)
 
 CMP_START_STR_CMP = CMP_START_STR + "## Starting the compression ##\n"
 CMP_START_STR_DECMP = CMP_START_STR + "## Starting the decompression ##\n"
@@ -277,8 +276,8 @@ def test_print_diff_cfg():
     args = ['--diff_cfg', '--diff_cfg -a', '--diff_cfg --rdcu_par']
     for i, arg in enumerate(args):
         returncode, stdout, stderr = call_cmp_tool(arg)
-        assert(returncode == EXIT_SUCCESS)
         assert(stderr == "")
+        assert(returncode == EXIT_SUCCESS)
 
         cfg = parse_key_value(stdout)
         assert(cfg['cmp_mode'] == '2')
@@ -368,8 +367,8 @@ def test_compression_diff():
         # generate test configuration
         with open(cfg_file_name, 'w', encoding='utf-8') as f:
             returncode, stdout, stderr = call_cmp_tool("--diff_cfg")
-            assert(returncode == EXIT_SUCCESS)
             assert(stderr == "")
+            assert(returncode == EXIT_SUCCESS)
             f.write(stdout)
 
         add_args = [" --no_header", ""]
@@ -379,8 +378,8 @@ def test_compression_diff():
                 " -c "+cfg_file_name+" -d "+data_file_name + " -o "+output_prefix+add_arg)
 
             # check compression results
-            assert(returncode == EXIT_SUCCESS)
             assert(stderr == "")
+            assert(returncode == EXIT_SUCCESS)
             assert(stdout == CMP_START_STR_CMP +
                    "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
                    "Importing data file %s ... \n" % (data_file_name) +
-- 
GitLab


From e76a8a58149c0b3a4aa8488347da2fe8b648d3c2 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 11 Feb 2022 12:29:57 +0100
Subject: [PATCH 03/46] add missing build file

---
 lib/meson.build | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 lib/meson.build

diff --git a/lib/meson.build b/lib/meson.build
new file mode 100644
index 0000000..02487b0
--- /dev/null
+++ b/lib/meson.build
@@ -0,0 +1,21 @@
+cmplib_sources = files([
+  'cmp_data_types.c',
+  'cmp_icu.c',
+  'cmp_support.c',
+  'rdcu_ctrl.c',
+  'rmap.c',
+  'cmp_entity.c',
+  'cmp_io.c',
+  'decmp.c',
+  'rdcu_pkt_to_file.c',
+  'cmp_guess.c',
+  'cmp_rdcu.c',
+  'rdcu_cmd.c',
+  'rdcu_rmap.c'
+])
+
+cmp_lib = static_library('cmp_lib',
+  sources : cmplib_sources,
+  include_directories : incdir,
+  c_args : ['-DDEBUGLEVEL=1']
+)
-- 
GitLab


From 672b918108bbcb9f4f0083f614af5ff72150d15e Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 11 Feb 2022 12:45:52 +0100
Subject: [PATCH 04/46] make test dependencies optional

---
 test/meson.build | 56 +++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/test/meson.build b/test/meson.build
index 14a5f0c..617df9c 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,33 +1,39 @@
 # add checkpatch syntax-check target
 checkpatch = find_program('checkpatch.pl', 'checkpatch', required : false)
-checkpatch_args = [
-  '--no-tree', '-f',
-  '--show-types',
-  '--color=always',
-  '--ignore', 'SPDX_LICENSE_TAG,PREFER_DEFINED_ATTRIBUTE_MACRO,EMBEDDED_FILENAME,BLOCK_COMMENT_STYLE,EMBEDDED_FUNCTION_NAME',
-]
-run_target('syntax-check',
- command : [checkpatch, checkpatch_args, main, cmplib_sources])
+if checkpatch.found()
+  checkpatch_args = [
+    '--no-tree', '-f',
+    '--show-types',
+    '--color=always',
+    '--ignore', 'SPDX_LICENSE_TAG,PREFER_DEFINED_ATTRIBUTE_MACRO,EMBEDDED_FILENAME,BLOCK_COMMENT_STYLE,EMBEDDED_FUNCTION_NAME',
+  ]
+  run_target('syntax-check',
+   command : [checkpatch, checkpatch_args, main, cmplib_sources])
+endif
 
 # add cppcheck inspector target
 cppcheck = find_program('cppcheck', required : false)
-cppcheck_args = [
-  main, cmplib_sources,
-  '--clang',
-  '--cppcheck-build-dir='+meson.current_build_dir(),
-  '-I', 'include',
-  '--std=c89',
-  '--addon=misra.py',
-  '--bug-hunting',
-  '--enable=all',
-  '--inconclusive'
-]
-run_target('inspector',
-  command : [cppcheck, cppcheck_args]
-)
-
-cunit_dep = dependency('cunit')
+if cppcheck.found()
+  cppcheck_args = [
+    main, cmplib_sources,
+    '--clang',
+    '--cppcheck-build-dir='+meson.current_build_dir(),
+    '-I', 'include',
+    '--std=c89',
+    '--addon=misra.py',
+    '--bug-hunting',
+    '--enable=all',
+    '--inconclusive'
+  ]
+  run_target('inspector',
+    command : [cppcheck, cppcheck_args]
+  )
+endif
 
 subdir('cmp_tool')
-subdir('cmp_icu')
+
+cunit_dep = dependency('cunit')
+if cunit_dep.found()
+  subdir('cmp_icu')
+endif
 
-- 
GitLab


From b62f5556350c8d40e9bad7a659b3d41cfffe4ce2 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 11 Feb 2022 09:55:40 -0500
Subject: [PATCH 05/46] make doxygen to required

---
 doc/doxygen/meson.build | 37 ++++++++++++++++++++-----------------
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build
index b500bac..e3062e3 100644
--- a/doc/doxygen/meson.build
+++ b/doc/doxygen/meson.build
@@ -8,31 +8,34 @@ doc_layout_files = files([
   'footer.html'
 ])
 
-doxygen = find_program('doxygen', required : false)
 
 #Build a Doxyfile based on Doxyfile.in
 cdata_doc = configuration_data()
 cdata_doc.set('VERSION', meson.project_version())
-cdata_doc.set('SRCDIR', meson.project_source_root())
-cdata_doc.set('BUILDDIR', meson.project_build_root())
+cdata_doc.set('SRCDIR', meson.source_root())
+cdata_doc.set('BUILDDIR', meson.build_root())
 if find_program('dot', required : false).found()
   cdata_doc.set('HAVE_DOT', 'YES')
 else
   cdata_doc.set('HAVE_DOT', 'NO')
 endif
 
-doxy_file = configure_file(
-  input : 'Doxyfile.in',
-  output : 'Doxyfile',
-  configuration : cdata_doc,
-  install : false,
-)
+doxygen = find_program('doxygen', required : false)
+
+if doxygen.found()
+  doxy_file = configure_file(
+    input : 'Doxyfile.in',
+    output : 'Doxyfile',
+    configuration : cdata_doc,
+    install : false,
+  )
 
-custom_target('doc',
-  input : doxy_file,
-  output : 'html',
-  depend_files : [doc_layout_files, main, cmplib_sources],
-  command : [doxygen, '@INPUT@'],
-  build_by_default : false,
-  console : true,
-)
+  custom_target('doc',
+    input : doxy_file,
+    output : 'html',
+    depend_files : [doc_layout_files, main, cmplib_sources],
+    command : [doxygen, '@INPUT@'],
+    build_by_default : false,
+    console : true,
+  )
+endif
-- 
GitLab


From edee18eab3fc153a5d658a1ccd987eb0de343bee Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 14 Feb 2022 10:53:15 +0000
Subject: [PATCH 06/46] adopt build sytem to windows

---
 lib/meson.build                            |  3 ++-
 meson.build                                |  3 ++-
 test/cmp_tool/cmp_tool_integration_test.py | 11 +++++++++--
 test/meson.build                           |  2 +-
 4 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/lib/meson.build b/lib/meson.build
index 02487b0..21f72ad 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -17,5 +17,6 @@ cmplib_sources = files([
 cmp_lib = static_library('cmp_lib',
   sources : cmplib_sources,
   include_directories : incdir,
-  c_args : ['-DDEBUGLEVEL=1']
+  c_args : ['-DDEBUGLEVEL=1'], 
+  install : 'true' # linking under windows mingw only works if this is set
 )
diff --git a/meson.build b/meson.build
index 59f2c05..295699f 100644
--- a/meson.build
+++ b/meson.build
@@ -4,11 +4,12 @@ project('cmp_tool', 'c',
   default_options : ['warning_level=3', 'c_std=gnu99']
 )
 
-if host_machine.system() == 'windows' and cc.get_id() == 'gcc'
+if host_machine.system() == 'windows' and meson.get_compiler('c').get_id() == 'gcc'
   # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)),
   # you need to add -mno-ms-bitfields to make it work as expected.
   # See: https://wintermade.it/blog/posts/__attribute__packed-on-windows-is-ignored-with-mingw.html
   add_project_arguments('-mno-ms-bitfields', language : 'c')
+  add_global_link_arguments('-static', language: 'c')
 endif
 
 subdir('include')
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
index 72d32c4..9804d41 100755
--- a/test/cmp_tool/cmp_tool_integration_test.py
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -1136,6 +1136,11 @@ def test_model_fiel_erros():
                          "longlonglonglonglonglonglonglonglonglonglonglonglong"
                          "longlonglonglonglonglonglonglonglonglonglonglonglong"
                          "longlonglonglonglonglonglonglonglonglong")
+        if sys.platform == 'win32' or sys.platform == 'cygwin':
+          output_prefix = ("longlonglonglonglonglonglonglonglonglonglonglonglong"
+                           "longlonglonglonglonglonglonglonglonglonglonglonglong"
+                           "longlonglonglonglonglonglonglonglonglonglonglonglong"
+                           "longlonglonglonglonglonglonglonglonglonglong")
         returncode, stdout, stderr = call_cmp_tool(
             " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix)
         assert(returncode == EXIT_FAILURE)
@@ -1147,8 +1152,10 @@ def test_model_fiel_erros():
                "Compress data ... DONE\n" +
                "Write compressed data to file %s.cmp ... DONE\n" %(output_prefix) +
                "Write updated model to file %s_upmodel.dat ... FAILED\n" %(output_prefix))
-        assert(stderr == "cmp_tool: %s_upmodel.dat: File name too long\n" % (output_prefix))
-        #
+        if sys.platform == 'win32' or sys.platform == 'cygwin':
+          assert(stderr == "cmp_tool: %s_upmodel.dat: No such file or directory\n" % (output_prefix))
+        else:
+          assert(stderr == "cmp_tool: %s_upmodel.dat: File name too long\n" % (output_prefix))
 
     finally:
         del_file(data_file_name)
diff --git a/test/meson.build b/test/meson.build
index 617df9c..ea06655 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -32,7 +32,7 @@ endif
 
 subdir('cmp_tool')
 
-cunit_dep = dependency('cunit')
+cunit_dep = dependency('cunit', required : false)
 if cunit_dep.found()
   subdir('cmp_icu')
 endif
-- 
GitLab


From 6be4781a9432b662c470ec3f7c96871191bd1325 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 14 Feb 2022 17:01:29 +0100
Subject: [PATCH 07/46] add more verbose build messages

---
 meson.build               | 1 +
 test/cmp_tool/meson.build | 6 +++++-
 test/meson.build          | 4 +++-
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/meson.build b/meson.build
index 295699f..d1fac6d 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,6 @@
 project('cmp_tool', 'c',
   version : '0.09',
+  meson_version : '>= 0.50',
   license : 'GPL-2.0',
   default_options : ['warning_level=3', 'c_std=gnu99']
 )
diff --git a/test/cmp_tool/meson.build b/test/cmp_tool/meson.build
index b60e2cf..25b47e2 100644
--- a/test/cmp_tool/meson.build
+++ b/test/cmp_tool/meson.build
@@ -1,4 +1,8 @@
 int_test_file = files('cmp_tool_integration_test.py')
 
 pytest = find_program('pytest', required : false)
-test('Integration Test', pytest, args : ['--color=yes', '-vvv', int_test_file])
+if pytest.found()
+  test('Integration Test', pytest, args : ['--color=yes', '-vvv', int_test_file])
+else
+  message('Pytest framework not found! Skipping integration tests.')
+endif
diff --git a/test/meson.build b/test/meson.build
index ea06655..c3a6afb 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -20,7 +20,7 @@ if cppcheck.found()
     '--cppcheck-build-dir='+meson.current_build_dir(),
     '-I', 'include',
     '--std=c89',
-    '--addon=misra.py',
+    # '--addon=misra.py',
     '--bug-hunting',
     '--enable=all',
     '--inconclusive'
@@ -35,5 +35,7 @@ subdir('cmp_tool')
 cunit_dep = dependency('cunit', required : false)
 if cunit_dep.found()
   subdir('cmp_icu')
+else
+  message('C Unit Testing Framework not found! Skipping unit tests.')
 endif
 
-- 
GitLab


From 56eb00208b7b9358b0f9258e4e51914846b51acf Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 14 Feb 2022 17:38:39 +0100
Subject: [PATCH 08/46] integration test depends on cmp_tool executable

---
 test/cmp_tool/meson.build | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/test/cmp_tool/meson.build b/test/cmp_tool/meson.build
index 25b47e2..7b5b382 100644
--- a/test/cmp_tool/meson.build
+++ b/test/cmp_tool/meson.build
@@ -2,7 +2,11 @@ int_test_file = files('cmp_tool_integration_test.py')
 
 pytest = find_program('pytest', required : false)
 if pytest.found()
-  test('Integration Test', pytest, args : ['--color=yes', '-vvv', int_test_file])
+  test('Integration Test',
+    pytest,
+    args : ['--color=yes', '-vvv', int_test_file]
+    depends: cmp_lib,
+    workdir: messon.build_root())
 else
   message('Pytest framework not found! Skipping integration tests.')
 endif
-- 
GitLab


From 575745ae0efa77e7ccd36681950256a753f30692 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 14 Feb 2022 12:08:39 -0500
Subject: [PATCH 09/46] fix erros

---
 meson.build               | 2 +-
 test/cmp_tool/meson.build | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/meson.build b/meson.build
index d1fac6d..300fa64 100644
--- a/meson.build
+++ b/meson.build
@@ -18,7 +18,7 @@ subdir('lib')
 
 main = files('cmp_tool.c')
 
-cmp_tool = executable('cmp_tool',
+cmp_tool_exe = executable('cmp_tool',
   sources : main,
   include_directories : incdir,
   link_with : cmp_lib,
diff --git a/test/cmp_tool/meson.build b/test/cmp_tool/meson.build
index 7b5b382..be04bb7 100644
--- a/test/cmp_tool/meson.build
+++ b/test/cmp_tool/meson.build
@@ -4,9 +4,9 @@ pytest = find_program('pytest', required : false)
 if pytest.found()
   test('Integration Test',
     pytest,
-    args : ['--color=yes', '-vvv', int_test_file]
-    depends: cmp_lib,
-    workdir: messon.build_root())
+    args : ['--color=yes', '-vvv', int_test_file],
+    depends : cmp_tool_exe,
+    workdir : meson.project_build_root())
 else
   message('Pytest framework not found! Skipping integration tests.')
 endif
-- 
GitLab


From 543bfe5ebf539a765446aacd2dac3e18a0151033 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 14 Feb 2022 18:24:11 +0100
Subject: [PATCH 10/46] remove deprecated features

---
 doc/doxygen/meson.build | 4 ++--
 meson.build             | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build
index e3062e3..33a3495 100644
--- a/doc/doxygen/meson.build
+++ b/doc/doxygen/meson.build
@@ -12,8 +12,8 @@ doc_layout_files = files([
 #Build a Doxyfile based on Doxyfile.in
 cdata_doc = configuration_data()
 cdata_doc.set('VERSION', meson.project_version())
-cdata_doc.set('SRCDIR', meson.source_root())
-cdata_doc.set('BUILDDIR', meson.build_root())
+cdata_doc.set('SRCDIR', meson.project_source_root())
+cdata_doc.set('BUILDDIR', meson.project_build_root())
 if find_program('dot', required : false).found()
   cdata_doc.set('HAVE_DOT', 'YES')
 else
diff --git a/meson.build b/meson.build
index 300fa64..d300c11 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
 project('cmp_tool', 'c',
   version : '0.09',
-  meson_version : '>= 0.50',
+  meson_version : '>= 0.56',
   license : 'GPL-2.0',
   default_options : ['warning_level=3', 'c_std=gnu99']
 )
-- 
GitLab


From 3b656c6a6df27fcc55f748068cf575645d68931f Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 17 Feb 2022 16:18:00 +0100
Subject: [PATCH 11/46] Add build documentation

---
 INSTALL.md | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 README.md  |   4 +-
 2 files changed, 138 insertions(+), 2 deletions(-)
 create mode 100644 INSTALL.md

diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..3653d0a
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,136 @@
+## Installation Instructions
+
+### Install git and python 3.6+
+
+If you're on Linux, you probably already have these. On macOS and Windows, you can use the
+[official Python installer](https://www.python.org/downloads/).
+
+### Install meson and ninja
+
+Meson 0.56 or newer is required.
+
+You can get meson through the Python package manager or using:
+
+```pip3 install meson```
+
+Check if meson is included in your PATH.
+
+You should get `ninja` using your [package manager](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages) or download the [official
+release](https://github.com/ninja-build/ninja/releases) and put the `ninja`
+binary in your PATH.
+
+### Get the Source Code
+
+We use the version control system git to get a copy of the source code.
+
+```
+git clone https://gitlab.phaidra.org/loidoltd15/cmp_tool.git  
+cd cmp_tool
+```
+
+### Build the cmp_tool for Debugging
+
+You can build the cmp_tool running:
+
+```
+meson builddir
+```
+
+This will automatically create the `builddir` directory and build **everything** **inside** it.
+
+```
+cd builddir
+meson compile
+```
+
+Now you should find the cmp_tool executable in the folder.
+
+### Release Build
+
+If you want to build an optimized release build run:
+
+```
+meson build_relase_dir --buildtype=release
+cd build_relase_dir
+meson compile
+```
+
+You find the build executable in the `build_relase_dir` directory
+
+### Cross-compiling to native Windows
+
+To build the cmp_tool you can use the [Mingw-w64](https://www.mingw-w64.org).
+Unfortunately, the cmp_tool does not support the Microsoft MSVC compiler. But with the Mingw-w64 GCC compiler, we can compile the cmp_tool for Windows. For this, you need the [Mingw-w64 tool chain](https://www.mingw-w64.org/downloads/). This also works on Linux and macOS. To compile for Windows, do this:
+
+```
+meson setup buiddir_win --cross-file=mingw-w64-64.txt
+cd buiddir_win
+meson compile
+```
+
+## Tests
+### External dependencies
+
+To run the unit tests you need the [c unit testing framework](https://sourceforge.net/projects/cunit/).  
+To run the integration tests you need the [pytest](https://docs.pytest.org/en/7.0.x/index.html) framework. The easiest way to install pytest is with `pip3`:
+
+```
+pip3 install pytest
+```
+### Run tests
+First, cd in the build directory:
+
+```
+cd <name of the build directory>
+```
+
+You can easily run the test of all the components:
+
+```
+meson test
+```
+
+To list all available tests:
+
+```
+meson test --list
+```
+
+Meson also supports running the tests under GDB. Just doing this:
+
+```
+meson test --gdb <testname>
+```
+
+### Producing a coverage report
+
+First, configure the build with this command.
+
+```
+cd <name of the build directory>
+meson configure -Db_coverage=true
+```
+
+Then issue the following commands.
+
+```
+meson test
+ninja coverage-html
+```
+
+The coverage report can be found in the `meson-logs/coveragereport` subdirectory.
+
+## Documentation 
+### External dependencies
+To generate the documentation you need the [Doxygen](https://www.doxygen.nl/index.html) program.
+Optional you can install the "dot" tool from [graphviz](http://www.graphviz.org/) to generate more advanced diagrams and graphs.  
+
+### Generate Documentation
+
+To generate the documentation you need to run:
+
+```
+cd <name of the build directory>
+meson compile doc
+```
+
diff --git a/README.md b/README.md
index 325a24c..cad1887 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 If you find a bug or have a feature request please file an [issue][1] or send
 me an [email][2].  
-Compiled executables can be found [here][3].
+Compiled executables can be found [here][3]. The building instructions can be found [here](INSTALL.md).
 
 ## Usage
 
@@ -86,7 +86,7 @@ You can find the user manual [here](doc).
 A simple example to show how the compression tool works.
 Instructions on how to perform compression without headers can be found [here](how_to_no_header.md).
 
-0. Download the [tool][3] or run `make` to build the tool
+0. Download the [tool][3] or [build the tool](INSTALL.md) yourself
 
 1. Create a configuration file
 * Create a cfg directory  
-- 
GitLab


From 52eaa596ee44d319f1a78d8019f21d5e6ff6b4d6 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 17 Feb 2022 16:50:36 +0100
Subject: [PATCH 12/46] move doxygen in a dir

---
 doc/doxygen/Doxyfile.in | 14 +++++++-------
 doc/doxygen/meson.build |  1 +
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in
index f4fba51..08f1e39 100644
--- a/doc/doxygen/Doxyfile.in
+++ b/doc/doxygen/Doxyfile.in
@@ -772,7 +772,7 @@ FILE_VERSION_FILTER    = "/bin/sh -c 'git log --pretty=\"format:%ci, author:%aN
 # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
 # tag is left empty.
 
-LAYOUT_FILE            = @SRCDIR@/doc/DoxygenLayout.xml
+LAYOUT_FILE            = @DOXYDIR@/DoxygenLayout.xml
 
 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
 # the reference definitions. This must be a list of .bib files. The .bib
@@ -1221,7 +1221,7 @@ HTML_FILE_EXTENSION    = .html
 # of the possible markers and block names see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_HEADER            = @SRCDIR@/doc/header.html
+HTML_HEADER            = @DOXYDIR@/header.html
 
 # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
 # generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1231,7 +1231,7 @@ HTML_HEADER            = @SRCDIR@/doc/header.html
 # that doxygen normally uses.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_FOOTER            = @SRCDIR@/doc/footer.html
+HTML_FOOTER            = @DOXYDIR@/footer.html
 
 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
 # sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1256,7 +1256,7 @@ HTML_STYLESHEET        =
 # list). For an example see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_EXTRA_STYLESHEET  = @SRCDIR@/doc/customdoxygen.css
+HTML_EXTRA_STYLESHEET  = @DOXYDIR@/customdoxygen.css
 
 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the HTML output directory. Note
@@ -1266,9 +1266,9 @@ HTML_EXTRA_STYLESHEET  = @SRCDIR@/doc/customdoxygen.css
 # files will be copied as-is; there are no commands or markers available.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_EXTRA_FILES       = @SRCDIR@/doc/bootstrap.min.css \
-                         @SRCDIR@/doc/bootstrap.min.js \
-                         @SRCDIR@/doc/doxy-boot.js
+HTML_EXTRA_FILES       = @DOXYDIR@/bootstrap.min.css \
+                         @DOXYDIR@/bootstrap.min.js \
+                         @DOXYDIR@/doxy-boot.js
 
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
 # will adjust the colors in the style sheet and background images according to
diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build
index 33a3495..f7facf3 100644
--- a/doc/doxygen/meson.build
+++ b/doc/doxygen/meson.build
@@ -13,6 +13,7 @@ doc_layout_files = files([
 cdata_doc = configuration_data()
 cdata_doc.set('VERSION', meson.project_version())
 cdata_doc.set('SRCDIR', meson.project_source_root())
+cdata_doc.set('DOXYDIR', meson.current_source_dir())
 cdata_doc.set('BUILDDIR', meson.project_build_root())
 if find_program('dot', required : false).found()
   cdata_doc.set('HAVE_DOT', 'YES')
-- 
GitLab


From 8b9c39d5eba57a028486b2ddec920f14ec9da608 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 17 Feb 2022 16:52:46 +0100
Subject: [PATCH 13/46] add cross file

---
 mingw-w64-64.txt | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 mingw-w64-64.txt

diff --git a/mingw-w64-64.txt b/mingw-w64-64.txt
new file mode 100644
index 0000000..773be92
--- /dev/null
+++ b/mingw-w64-64.txt
@@ -0,0 +1,24 @@
+[binaries]
+c = 'x86_64-w64-mingw32-gcc'
+cpp = 'x86_64-w64-mingw32-g++'
+objc = 'x86_64-w64-mingw32-gcc'
+ar = 'x86_64-w64-mingw32-ar'
+strip = 'x86_64-w64-mingw32-strip'
+pkgconfig = 'x86_64-w64-mingw32-pkg-config'
+windres = 'x86_64-w64-mingw32-windres'
+exe_wrapper = 'wine64'
+cmake = 'cmake'
+
+[host_machine]
+system = 'windows'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
+
+[cmake]
+
+CMAKE_BUILD_WITH_INSTALL_RPATH     = 'ON'
+CMAKE_FIND_ROOT_PATH_MODE_PROGRAM  = 'NEVER'
+CMAKE_FIND_ROOT_PATH_MODE_LIBRARY  = 'ONLY'
+CMAKE_FIND_ROOT_PATH_MODE_INCLUDE  = 'ONLY'
+CMAKE_FIND_ROOT_PATH_MODE_PACKAGE  = 'ONLY'
-- 
GitLab


From bcf9c653a9740bd7d3ae095978458b291d43e536 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 1 Feb 2022 15:33:17 +0100
Subject: [PATCH 14/46] Adding the possibility to import non-imagette data

---
 cmp_tool.c               |   9 +--
 include/cmp_data_types.h |  42 +++++++----
 include/cmp_io.h         |  12 ++--
 include/cmp_support.h    |   1 +
 lib/cmp_data_types.c     | 146 +++++++++++++++++++++++++++++++++++++++
 lib/cmp_io.c             |   1 +
 lib/cmp_support.c        |  39 ++++++++++-
 7 files changed, 225 insertions(+), 25 deletions(-)

diff --git a/cmp_tool.c b/cmp_tool.c
index 90aa1df..e3b2716 100755
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -32,6 +32,7 @@
 #include "cmp_guess.h"
 #include "cmp_entity.h"
 #include "rdcu_pkt_to_file.h"
+#include "cmp_data_types.h"
 
 
 #define BUFFER_LENGTH_DEF_FAKTOR 2
@@ -189,7 +190,7 @@ int main(int argc, char **argv)
 			verbose_en = 1;
 			break;
 		case 'V': /* --version */
-			printf("%s version %s\n", PROGRAM_NAME, CMP_TOOL_VERSION);
+			printf("%s version %s\n", PROGRAM_NAME, VERSION);
 			exit(EXIT_SUCCESS);
 			break;
 		case DIFF_CFG_OPTION:
@@ -272,9 +273,9 @@ int main(int argc, char **argv)
 
 	printf("#########################################################\n");
 	printf("### PLATO Compression/Decompression Tool Version %s ###\n",
-	       CMP_TOOL_VERSION);
+	       VERSION);
 	printf("#########################################################\n");
-	if (!strcmp(CMP_TOOL_VERSION, "0.07") || !strcmp(CMP_TOOL_VERSION, "0.08"))
+	if (!strcmp(VERSION, "0.07") || !strcmp(VERSION, "0.08"))
 		printf("Info: Note that the behaviour of the cmp_tool has changed. From now on, the compressed data will be preceded by a header by default. The old behaviour can be achieved with the --no_header option.\n\n");
 
 	if (!data_file_name) {
@@ -628,7 +629,7 @@ static int add_cmp_ent_hdr(struct cmp_cfg *cfg, struct cmp_info *info,
 		cmp_bit_to_4byte(info->cmp_size));
 
 	ent = (struct cmp_entity *)cfg->icu_output_buf;
-	s = cmp_ent_build(ent, data_type, cmp_tool_gen_version_id(CMP_TOOL_VERSION),
+	s = cmp_ent_build(ent, data_type, cmp_tool_gen_version_id(VERSION),
 			  start_time, cmp_ent_create_timestamp(NULL), model_id,
 			  model_counter, info, cfg);
 	if (!s) {
diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 345c0ae..2ec635e 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -33,6 +33,8 @@
 
 #include <stdint.h>
 
+#include "compiler.h"
+
 #define MODE_RAW_S_FX           100
 #define MODE_MODEL_ZERO_S_FX	101
 #define MODE_DIFF_ZERO_S_FX	102
@@ -90,11 +92,25 @@ int lossy_rounding_32(uint32_t *data_buf, unsigned int samples, unsigned int
 int de_lossy_rounding_32(uint32_t *data_buf, uint32_t samples_used, uint32_t
 			 round_used);
 
-/* @see PLATO-LESIA-PL-RP-0031 Issue: 1.9 (N-DPU->ICU data rate) */
-struct __attribute__((packed)) S_FX {
+void cmp_input_big_to_cpu_endiannessy(void *data, u_int32_t data_size_byte,
+				      uint32_t cmp_mode);
+
+/* @see for packed definition: PLATO-LESIA-PL-RP-0031 Issue: 1.9 (N-DPU->ICU data rate) */
+#define N_DPU_ICU_MULTI_ENTRY_HDR_SIZE 12
+
+struct n_dpu_icu_multi_entry_hdr {
+	uint64_t ncxx_timestamp:48;
+	uint16_t ncxx_configuration_id;
+	uint16_t ncxx_collection_id;
+	uint16_t ncxx_collection_length;
+} __attribute__((packed));
+compile_time_assert(sizeof(struct n_dpu_icu_multi_entry_hdr) == N_DPU_ICU_MULTI_ENTRY_HDR_SIZE, N_DPU_ICU_MULTI_ENTRY_HDR_SIZE_IS_NOT_CORRECT);
+
+
+struct S_FX {
 	uint8_t EXPOSURE_FLAGS;
 	uint32_t FX;
-};
+} __attribute__((packed));
 
 struct S_FX sub_S_FX(struct S_FX a, struct S_FX b);
 struct S_FX add_S_FX(struct S_FX a, struct S_FX b);
@@ -110,7 +126,7 @@ struct S_FX_EFX {
 	uint8_t EXPOSURE_FLAGS;
 	uint32_t FX;
 	uint32_t EFX;
-}__attribute__((packed));
+} __attribute__((packed));
 
 struct S_FX_EFX sub_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b);
 struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b);
@@ -127,7 +143,7 @@ struct S_FX_NCOB {
 	uint32_t FX;
 	uint32_t NCOB_X;
 	uint32_t NCOB_Y;
-}__attribute__((packed));
+} __attribute__((packed));
 
 struct S_FX_NCOB sub_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b);
 struct S_FX_NCOB add_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b);
@@ -135,9 +151,9 @@ int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
 			     unsigned int round);
 int de_lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int
 				samples_used, unsigned int round_used);
-struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf, struct
-					S_FX_NCOB model_buf, unsigned int
-					model_value);
+struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf,
+					struct S_FX_NCOB model_buf,
+					unsigned int model_value);
 
 
 struct S_FX_EFX_NCOB_ECOB {
@@ -148,7 +164,7 @@ struct S_FX_EFX_NCOB_ECOB {
 	uint32_t EFX;
 	uint32_t ECOB_X;
 	uint32_t ECOB_Y;
-}__attribute__((packed));
+} __attribute__((packed));
 
 struct S_FX_EFX_NCOB_ECOB sub_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
 						 struct S_FX_EFX_NCOB_ECOB b);
@@ -162,20 +178,20 @@ int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
 
 struct F_FX {
 	uint32_t FX;
-}__attribute__((packed));
+} __attribute__((packed));
 
 
 struct F_FX_EFX {
 	uint32_t FX;
 	uint32_t EFX;
-}__attribute__((packed));
+} __attribute__((packed));
 
 
 struct F_FX_NCOB {
 	uint32_t FX;
 	uint32_t NCOB_X;
 	uint32_t NCOB_Y;
-}__attribute__((packed));
+} __attribute__((packed));
 
 
 struct F_FX_EFX_NCOB_ECOB {
@@ -185,6 +201,6 @@ struct F_FX_EFX_NCOB_ECOB {
 	uint32_t EFX;
 	uint32_t ECOB_X;
 	uint32_t ECOB_Y;
-}__attribute__((packed));
+} __attribute__((packed));
 
 #endif /* CMP_DATA_TYPE_H */
diff --git a/include/cmp_io.h b/include/cmp_io.h
index 179d59f..39cfe59 100644
--- a/include/cmp_io.h
+++ b/include/cmp_io.h
@@ -31,14 +31,12 @@ void print_help(const char *program_name);
 int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en);
 int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en);
 
-ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word,
-		   int verbose_en);
-ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples,
-		    int verbose_en);
-ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
-		    int verbose_en);
+ssize_t read_file_data(const char *file_name, unsigned int cmp_mode, void *buf,
+		       uint32_t buf_size, int verbose_en);
 ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
-			   uint32_t ent_size, int verbose_en);
+			     uint32_t ent_size, int verbose_en);
+ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_size,
+		    int verbose_en);
 
 uint32_t cmp_tool_gen_version_id(const char *version);
 
diff --git a/include/cmp_support.h b/include/cmp_support.h
index 0c1c90f..cfe4bbd 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -179,6 +179,7 @@ uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode);
 uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode);
 
 size_t size_of_a_sample(unsigned int cmp_mode);
+int cmp_input_size_to_samples(unsigned int size, unsigned int cmp_mode);
 unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit);
 unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode);
 
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 1df363c..cf8c08c 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -20,6 +20,7 @@
 #include "../include/cmp_data_types.h"
 #include "../include/cmp_support.h"
 #include "../include/cmp_debug.h"
+#include "../include/byteorder.h"
 
 
 /**
@@ -96,6 +97,15 @@ int de_lossy_rounding_16(uint16_t *data_buf, uint32_t samples_used, uint32_t
 }
 
 
+static void be_to_cpus_16(uint16_t *a, uint32_t samples)
+{
+	size_t i;
+
+	for (i = 0; i < samples; ++i)
+		be16_to_cpus(&a[i]);
+}
+
+
 /**
  * @brief rounding down the least significant digits of a uint32_t data buffer
  *
@@ -261,6 +271,15 @@ struct S_FX cal_up_model_S_FX(struct S_FX data_buf, struct S_FX model_buf,
 }
 
 
+void be_to_cpus_S_FX(struct S_FX *a, uint32_t samples)
+{
+	size_t i;
+
+	for (i = 0; i < samples; ++i)
+		a[i].FX = be32_to_cpu(a[i].FX);
+}
+
+
 struct S_FX_EFX sub_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
 {
 	struct S_FX_EFX result;
@@ -371,6 +390,17 @@ struct S_FX_EFX cal_up_model_S_FX_EFX(struct S_FX_EFX data_buf, struct S_FX_EFX
 }
 
 
+void be_to_cpus_S_FX_EFX(struct S_FX_EFX *a, uint32_t samples)
+{
+	size_t i;
+
+	for (i = 0; i < samples; ++i) {
+		a[i].FX = be32_to_cpu(a[i].FX);
+		a[i].EFX = be32_to_cpu(a[i].EFX);
+	}
+}
+
+
 struct S_FX_NCOB sub_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b)
 {
 	struct S_FX_NCOB result;
@@ -490,6 +520,18 @@ struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf, struct S_FX_N
 }
 
 
+void be_to_cpus_S_FX_NCOB(struct S_FX_NCOB *a, uint32_t samples)
+{
+	size_t i;
+
+	for (i = 0; i < samples; ++i) {
+		a[i].FX = be32_to_cpu(a[i].FX);
+		a[i].NCOB_X = be32_to_cpu(a[i].NCOB_X);
+		a[i].NCOB_Y = be32_to_cpu(a[i].NCOB_Y);
+	}
+}
+
+
 struct S_FX_EFX_NCOB_ECOB sub_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
 						 struct S_FX_EFX_NCOB_ECOB b)
 {
@@ -638,3 +680,107 @@ struct S_FX_EFX_NCOB_ECOB cal_up_model_S_FX_EFX_NCOB_ECOB
 
 	return result;
 }
+
+
+void be_to_cpus_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *a, uint32_t samples)
+{
+	size_t i;
+
+	for (i = 0; i < samples; ++i) {
+		a[i].FX = be32_to_cpu(a[i].FX);
+		a[i].NCOB_X = be32_to_cpu(a[i].NCOB_X);
+		a[i].NCOB_Y = be32_to_cpu(a[i].NCOB_Y);
+		a[i].EFX = be32_to_cpu(a[i].EFX);
+		a[i].ECOB_X = be32_to_cpu(a[i].ECOB_X);
+		a[i].ECOB_Y = be32_to_cpu(a[i].ECOB_Y);
+	}
+}
+
+
+/**
+ * @brief swap the endianness of science products form big endian to the cpu
+ *	endianness in place
+ *
+ * @param  data		pointer to a data sample
+ * @param  cmp_mode	compression mode
+ */
+
+void cmp_input_big_to_cpu_endiannessy(void *data, u_int32_t data_size_byte,
+				      uint32_t cmp_mode)
+{
+	int samples = cmp_input_size_to_samples(data_size_byte, cmp_mode);
+
+	if (!data)
+		return;
+
+	if (samples < 0) {
+		debug_print("Error: Can not convert data size in samples.\n");
+		return;
+	}
+
+	if (!rdcu_supported_mode_is_used(cmp_mode))
+		data = (uint8_t *)data + N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+
+	switch (cmp_mode) {
+	case MODE_RAW:
+	case MODE_MODEL_ZERO:
+	case MODE_MODEL_MULTI:
+	case MODE_DIFF_ZERO:
+	case MODE_DIFF_MULTI:
+		be_to_cpus_16(data, samples);
+		break;
+	case MODE_RAW_S_FX:
+	case MODE_MODEL_ZERO_S_FX:
+	case MODE_MODEL_MULTI_S_FX:
+	case MODE_DIFF_ZERO_S_FX:
+	case MODE_DIFF_MULTI_S_FX:
+		be_to_cpus_S_FX(data, samples);
+		break;
+	case MODE_MODEL_ZERO_S_FX_EFX:
+	case MODE_MODEL_MULTI_S_FX_EFX:
+	case MODE_DIFF_ZERO_S_FX_EFX:
+	case MODE_DIFF_MULTI_S_FX_EFX:
+		be_to_cpus_S_FX_EFX(data, samples);
+		break;
+	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
+	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
+	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
+	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
+		be_to_cpus_S_FX_EFX_NCOB_ECOB(data, samples);
+		break;
+	case MODE_MODEL_ZERO_F_FX:
+	case MODE_MODEL_MULTI_F_FX:
+	case MODE_DIFF_ZERO_F_FX:
+	case MODE_DIFF_MULTI_F_FX:
+		/* be_to_cpus_F_FX(data, samples); */
+		/* break; */
+	case MODE_MODEL_ZERO_F_FX_EFX:
+	case MODE_MODEL_MULTI_F_FX_EFX:
+	case MODE_DIFF_ZERO_F_FX_EFX:
+	case MODE_DIFF_MULTI_F_FX_EFX:
+		/* be_to_cpus_F_FX_EFX(data, samples); */
+		/* break; */
+	case MODE_MODEL_ZERO_F_FX_NCOB:
+	case MODE_MODEL_MULTI_F_FX_NCOB:
+	case MODE_DIFF_ZERO_F_FX_NCOB:
+	case MODE_DIFF_MULTI_F_FX_NCOB:
+		/* be_to_cpus_F_FX_NCOB(data, samples); */
+		/* break; */
+	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
+	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
+	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
+	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
+		/* be_to_cpus_F_FX_EFX_NCOB_ECOB(data, samples); */
+		/* break; */
+	case MODE_RAW_32:
+	case MODE_MODEL_ZERO_32:
+	case MODE_MODEL_MULTI_32:
+	case MODE_DIFF_ZERO_32:
+	case MODE_DIFF_MULTI_32:
+		/* be32_to_cpus(data); */
+		/* break; */
+	default:
+		debug_print("Error: Compression mode not supported.\n");
+		break;
+	}
+}
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 9dc9ba1..7c00d56 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -29,6 +29,7 @@
 #include "cmp_support.h"
 #include "rdcu_cmd.h"
 #include "byteorder.h"
+#include "cmp_data_types.h"
 
 
 /**
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index a945971..93db7b6 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -558,6 +558,36 @@ size_t size_of_a_sample(unsigned int cmp_mode)
 }
 
 
+/**
+ * @brief calculates the number of samples for a given data size for the
+ *	different compression modes
+ *
+ * @param size		size of the data me
+ * @param cmp_mode	compression mode
+ *
+ * @returns the number samples for the given compression mode; negative on error
+ */
+
+int cmp_input_size_to_samples(unsigned int size, unsigned int cmp_mode)
+{
+	unsigned int samples_size = size_of_a_sample(cmp_mode);
+
+	if (!samples_size)
+		return -1;
+
+	if (!rdcu_supported_mode_is_used(cmp_mode)) {
+		if (size < N_DPU_ICU_MULTI_ENTRY_HDR_SIZE)
+			return -1;
+		size -= N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+	}
+
+	if (size % samples_size)
+		return -1;
+
+	return size/samples_size;
+}
+
+
 /**
  * @brief calculate the need bytes to hold a bitstream
  *
@@ -579,12 +609,19 @@ unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
  * @param samples number of data samples
  * @param cmp_mode used compression mode
  *
+ * @note for non RDCU modes the N_DPU ICU multi entry header size is added
+ *
  * @returns the size in bytes to store the data sample
  */
 
 unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode)
 {
-	return samples * size_of_a_sample(cmp_mode);
+	unsigned int s = samples * size_of_a_sample(cmp_mode);
+
+	if (!rdcu_supported_mode_is_used(cmp_mode))
+		s += N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+
+	return s;
 }
 
 
-- 
GitLab


From 9ca41d9cd7f9301b096121ff63c0aea1fefcf24e Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Wed, 2 Feb 2022 10:24:13 +0100
Subject: [PATCH 15/46] correct documentation

---
 lib/cmp_entity.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index 84f784d..99aa3bd 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -1640,7 +1640,6 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
  * @param data_buf	pointer where the destination data buffer where the
  *	compressed data is copied to (can be NULL)
  * @param data_buf_size	size of the destination data buffer
- * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the compressed data; negative on error
  *
-- 
GitLab


From 95a779ee529b28d0c71384a4c2f38c85c62cce10 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 15 Mar 2022 20:14:27 +0100
Subject: [PATCH 16/46] Refactor put_n_bits()

---
 lib/cmp_icu_new.c                  | 165 ++++++++++
 subprojects/unity.wrap             |   8 +
 test/cmp_icu/test_cmp_icu_new.c    | 373 +++++++++++++++++++++
 test/tools/generate_test_runner.rb | 512 +++++++++++++++++++++++++++++
 test/tools/meson.build             |   6 +
 test/tools/run_test.erb            |  37 +++
 test/tools/type_sanitizer.rb       |   6 +
 7 files changed, 1107 insertions(+)
 create mode 100644 lib/cmp_icu_new.c
 create mode 100644 subprojects/unity.wrap
 create mode 100644 test/cmp_icu/test_cmp_icu_new.c
 create mode 100755 test/tools/generate_test_runner.rb
 create mode 100644 test/tools/meson.build
 create mode 100644 test/tools/run_test.erb
 create mode 100644 test/tools/type_sanitizer.rb

diff --git a/lib/cmp_icu_new.c b/lib/cmp_icu_new.c
new file mode 100644
index 0000000..e6f6752
--- /dev/null
+++ b/lib/cmp_icu_new.c
@@ -0,0 +1,165 @@
+/**
+ * @file   icu_cmp.c
+ * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
+ * @date   2020
+ *
+ * @copyright GPLv2
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * @brief software compression library
+ * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
+ */
+
+
+#include <stdint.h>
+
+#include "cmp_debug.h"
+
+
+/* return code if the bitstream buffer is too small to store the whole bitstream */
+#define CMP_ERROR_SAMLL_BUF -2
+
+
+/**
+ * @brief put the value of up to 32 bits into a bitstream accessed as 32-bit
+ *	RAM in big-endian
+ *
+ * @param value		the value to put
+ * @param n_bits	number of bits to put in the bitstream
+ * @param bit_offset	bit index where the bits will be put, seen from the very
+ *			beginning of the bitstream
+ * @param bitstream_adr	this is the pointer to the beginning of the bitstream
+ *			(can be NULL)
+ * @param max_bit_len	maximum length of the bitstream in bits; is ignored if
+ *			bitstream_adr is NULL
+ *
+ * @returns length in bits of the generated bitstream on success; returns
+ *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
+ *          the bitstream buffer is too small to put the value in the bitstream
+ * @note a value with more bits set as the n_bits parameter is considered as an
+ *	erroneous input.
+ */
+
+static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
+			uint32_t *bitstream_adr, unsigned int max_bit_len)
+{
+	uint32_t *local_adr;
+	uint32_t mask;
+	unsigned int shiftRight, shiftLeft, bitsLeft, bitsRight;
+	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
+
+	/* leave in case of erroneous input */
+	if (bit_offset < 0)
+		return -1;
+
+	if (n_bits == 0)
+		return 0;
+
+	if (n_bits > 32)
+		return -1;
+
+	/* (M) is the n_bits parameter large enough to cover all value bits; the
+	 * calculations can be re-used in the unsegmented code, so we have no overhead
+	 */
+	shiftRight = 32 - n_bits;
+	mask = 0xFFFFFFFFU >> shiftRight;
+	if (value & ~mask) {
+		debug_print("Error: Not all set bits in the put value are added to the bitstream. Check value n_bits parameter combination.\n");
+		return -1;
+	}
+
+	/* Do we need to write data to the bitstream? */
+	if (!bitstream_adr)
+		return stream_len;
+
+	/* Check if bitstream buffer is large enough */
+	if ((unsigned int)stream_len > max_bit_len) {
+		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
+		return CMP_ERROR_SAMLL_BUF;
+	}
+
+	/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
+	local_adr = bitstream_adr + (bit_offset >> 5);
+	bitsLeft = bit_offset & 0x1F;
+
+	/* Calculate the bitsRight for the unsegmented case. If bitsRight is
+	 * negative we need to split the value over two words
+	 */
+	bitsRight = shiftRight - bitsLeft;
+
+	if ((int)bitsRight >= 0) {
+		/*         UNSEGMENTED
+		 *
+		 *|-----------|XXXXX|----------------|
+		 *   bitsLeft    n       bitsRight
+		 *
+		 *  -> to get the mask:
+		 *  shiftRight = bitsLeft + bitsRight = 32 - n
+		 *  shiftLeft = bitsRight = 32 - n - bitsLeft = shiftRight - bitsLeft
+		 */
+
+		shiftLeft = bitsRight;
+
+		/* generate the mask, the bits for the values will be true
+		 * shiftRight = 32 - n_bits; see (M) above!
+		 * mask = (0XFFFFFFFF >> shiftRight) << shiftLeft; see (M) above!
+		 */
+		mask <<= shiftLeft;
+		value <<= shiftLeft;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value */
+		*(local_adr) |= value;
+
+	} else {
+		/*                             SEGMENTED
+		 *
+		 *|-----------------------------|XXX| |XX|------------------------------|
+		 *          bitsLeft              n1   n2          bitsRight
+		 *
+		 *  -> to get the mask part 1:
+		 *  shiftRight = bitsLeft
+		 *  n1 = n - (bitsLeft + n - 32) = 32 - bitsLeft
+		 *
+		 *  -> to get the mask part 2:
+		 *  n2 = bitsLeft + n - 32 = -(32 - n - bitsLeft) = -(bitsRight_UNSEGMENTED)
+		 *  shiftLeft = 32 - n2 = 32 - (bitsLeft + n - 32) = 64 - bitsLeft - n
+		 *
+		 */
+
+		unsigned int n2 = -bitsRight;
+
+		/* part 1: */
+		shiftRight = bitsLeft;
+		mask = 0XFFFFFFFFU >> shiftRight;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value part 1 */
+		*(local_adr) |= (value >> n2);
+
+		/* part 2: */
+		/* adjust address */
+		local_adr += 1;
+		shiftLeft = 32 - n2;
+		mask = 0XFFFFFFFFU << shiftLeft;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value part 2 */
+		*(local_adr) |= (value << shiftLeft);
+	}
+	return stream_len;
+}
+
diff --git a/subprojects/unity.wrap b/subprojects/unity.wrap
new file mode 100644
index 0000000..8cc4883
--- /dev/null
+++ b/subprojects/unity.wrap
@@ -0,0 +1,8 @@
+[wrap-file]
+directory = Unity-2.5.2
+source_url = https://github.com/ThrowTheSwitch/Unity/archive/refs/tags/v2.5.2.tar.gz
+source_filename = Unity-2.5.2.tar.gz
+source_hash = 3786de6c8f389be3894feae4f7d8680a02e70ed4dbcce36109c8f8646da2671a
+
+[provide]
+unity = unity_dep
diff --git a/test/cmp_icu/test_cmp_icu_new.c b/test/cmp_icu/test_cmp_icu_new.c
new file mode 100644
index 0000000..6e57615
--- /dev/null
+++ b/test/cmp_icu/test_cmp_icu_new.c
@@ -0,0 +1,373 @@
+#include <string.h>
+
+#include "unity.h"
+
+/* this is a hack to test static functions */
+#include "../lib/cmp_icu_new.c"
+
+
+
+/**
+ * @test put_n_bits32
+ */
+
+#define SDP_PB_N 3
+
+
+static void init_PB32_arrays(uint32_t *z, uint32_t *o)
+{
+	uint32_t i;
+
+	/* init testarray with all 0 and all 1 */
+	for (i = 0; i < SDP_PB_N; i++) {
+		z[i] = 0;
+		o[i] = 0xffffffff;
+	}
+}
+
+
+void test_put_n_bits32(void)
+{
+	uint32_t v, n;
+	int o, rval; /* return value */
+	uint32_t testarray0[SDP_PB_N];
+	uint32_t testarray1[SDP_PB_N];
+	const uint32_t l = sizeof(testarray0) * CHAR_BIT;
+
+	/* hereafter, the value is v,
+	 * the number of bits to write is n,
+	 * the offset of the bit is o,
+	 * the max length the bitstream in bits is l
+	 */
+
+	init_PB32_arrays(testarray0, testarray1);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/*** n=0 ***/
+
+	/* do not write, left border */
+	v = 0; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/* TODO: not a valid test */
+	v = 0xffffffff; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/* do not write, right border */
+	v = 0; n = 0; o = 31;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/* TODO: not a valid test */
+	/* test value = 0xffffffff; N = 0 */
+	v = 0xffffffff; n = 0; o = 31;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/*** n=1 ***/
+
+	/* left border, write 0 */
+	v = 0; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray1[0] == 0x7fffffff);
+
+	/* left border, write 1 */
+	v = 1; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray0[0] == 0x80000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/* left border, write 32 */
+	v = 0xf0f0abcd; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 2 bits */
+	v = 3; n = 2; o = 29;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 31);
+	TEST_ASSERT(testarray0[0] == 0x6);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT_EQUAL_INT(rval, 31);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/*** n=5, unsegmented ***/
+
+	/* left border, write 0 */
+	v = 0; n = 5; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT(testarray1[0] == 0x07ffffff);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* left border, write 11111 */
+	v = 0x1f; n = 5; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray0[0] == 0xf8000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 0 */
+	v = 0; n = 5; o = 7;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray1[0] == 0xfe0fffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 11111 */
+	v = 0x1f; n = 5; o = 7;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray0[0] == 0x01f00000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* right, write 0 */
+	v = 0; n = 5; o = 91;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffe0);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* right, write 11111 */
+	v = 0x1f; n = 5; o = 91;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0x0000001f);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write 0 */
+	v = 0; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0x00000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0x00000000);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write -1 */
+	v = 0xffffffff; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* SEGMENTED cases */
+	/* 5 bit, write 0 */
+	v = 0; n = 5; o = 62;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xfffffffc);
+	TEST_ASSERT(testarray1[2] == 0x1fffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 5 bit, write 1f */
+	v = 0x1f; n = 5; o = 62;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 3);
+	TEST_ASSERT(testarray0[2] == 0xe0000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write 0 */
+	v = 0; n = 32; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray0[0] == 0x00000000);
+	TEST_ASSERT(testarray0[1] == 0x00000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray1[0] == 0x80000000);
+	TEST_ASSERT(testarray1[1] == 0x7fffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write -1 */
+	v = 0xffffffff; n = 32; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray0[0] == 0x7fffffff);
+	TEST_ASSERT(testarray0[1] == 0x80000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* test NULL buffer */
+	v = 0; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 0);
+
+	v = 0; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 1);
+
+	v = 0; n = 5; o = 31;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 36);
+
+	v = 0; n = 2; o = 95;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
+
+	/* error cases */
+	/* n too large */
+	v = 0x0; n = 33; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
+
+	/* value larger than n allows */
+	v = 0x7f; n = 6; o = 10;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+
+	/* try to put too much in the bitstream */
+	v = 0x1; n = 1; o = 96;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+
+	/* this should work */
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(97, rval);
+
+	/* offset lager than max_bit_len */
+	v = 0x0; n = 32; o = INT32_MAX;
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT(rval < 0);
+
+	/* negative offset */
+	v = 0x0; n = 0; o = -1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+}
diff --git a/test/tools/generate_test_runner.rb b/test/tools/generate_test_runner.rb
new file mode 100755
index 0000000..1c0ec34
--- /dev/null
+++ b/test/tools/generate_test_runner.rb
@@ -0,0 +1,512 @@
+#!/usr/bin/env ruby
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class UnityTestRunnerGenerator
+  def initialize(options = nil)
+    @options = UnityTestRunnerGenerator.default_options
+    case options
+    when NilClass
+      @options
+    when String
+      @options.merge!(UnityTestRunnerGenerator.grab_config(options))
+    when Hash
+      # Check if some of these have been specified
+      @options[:has_setup] = !options[:setup_name].nil?
+      @options[:has_teardown] = !options[:teardown_name].nil?
+      @options[:has_suite_setup] = !options[:suite_setup].nil?
+      @options[:has_suite_teardown] = !options[:suite_teardown].nil?
+      @options.merge!(options)
+    else
+      raise 'If you specify arguments, it should be a filename or a hash of options'
+    end
+    require_relative 'type_sanitizer'
+  end
+
+  def self.default_options
+    {
+      includes: [],
+      defines: [],
+      plugins: [],
+      framework: :unity,
+      test_prefix: 'test|spec|should',
+      mock_prefix: 'Mock',
+      mock_suffix: '',
+      setup_name: 'setUp',
+      teardown_name: 'tearDown',
+      test_reset_name: 'resetTest',
+      test_verify_name: 'verifyTest',
+      main_name: 'main', # set to :auto to automatically generate each time
+      main_export_decl: '',
+      cmdline_args: false,
+      omit_begin_end: false,
+      use_param_tests: false,
+      include_extensions: '(?:hpp|hh|H|h)',
+      source_extensions: '(?:cpp|cc|ino|C|c)'
+    }
+  end
+
+  def self.grab_config(config_file)
+    options = default_options
+    unless config_file.nil? || config_file.empty?
+      require 'yaml'
+      yaml_guts = YAML.load_file(config_file)
+      options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
+      raise "No :unity or :cmock section found in #{config_file}" unless options
+    end
+    options
+  end
+
+  def run(input_file, output_file, options = nil)
+    @options.merge!(options) unless options.nil?
+
+    # pull required data from source file
+    source = File.read(input_file)
+    source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
+    tests = find_tests(source)
+    headers = find_includes(source)
+    testfile_includes = (headers[:local] + headers[:system])
+    used_mocks = find_mocks(testfile_includes)
+    testfile_includes = (testfile_includes - used_mocks)
+    testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
+    find_setup_and_teardown(source)
+
+    # build runner file
+    generate(input_file, output_file, tests, used_mocks, testfile_includes)
+
+    # determine which files were used to return them
+    all_files_used = [input_file, output_file]
+    all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty?
+    all_files_used += @options[:includes] unless @options[:includes].empty?
+    all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
+    all_files_used.uniq
+  end
+
+  def generate(input_file, output_file, tests, used_mocks, testfile_includes)
+    File.open(output_file, 'w') do |output|
+      create_header(output, used_mocks, testfile_includes)
+      create_externs(output, tests, used_mocks)
+      create_mock_management(output, used_mocks)
+      create_setup(output)
+      create_teardown(output)
+      create_suite_setup(output)
+      create_suite_teardown(output)
+      create_reset(output)
+      create_run_test(output) unless tests.empty?
+      create_args_wrappers(output, tests)
+      create_main(output, input_file, tests, used_mocks)
+    end
+
+    return unless @options[:header_file] && !@options[:header_file].empty?
+
+    File.open(@options[:header_file], 'w') do |output|
+      create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
+    end
+  end
+
+  def find_tests(source)
+    tests_and_line_numbers = []
+
+    # contains characters which will be substituted from within strings, doing
+    # this prevents these characters from interfering with scrubbers
+    # @ is not a valid C character, so there should be no clashes with files genuinely containing these markers
+    substring_subs = { '{' => '@co@', '}' => '@cc@', ';' => '@ss@', '/' => '@fs@' }
+    substring_re = Regexp.union(substring_subs.keys)
+    substring_unsubs = substring_subs.invert                   # the inverse map will be used to fix the strings afterwords
+    substring_unsubs['@quote@'] = '\\"'
+    substring_unsubs['@apos@'] = '\\\''
+    substring_unre = Regexp.union(substring_unsubs.keys)
+    source_scrubbed = source.clone
+    source_scrubbed = source_scrubbed.gsub(/\\"/, '@quote@')   # hide escaped quotes to allow capture of the full string/char
+    source_scrubbed = source_scrubbed.gsub(/\\'/, '@apos@')    # hide escaped apostrophes to allow capture of the full string/char
+    source_scrubbed = source_scrubbed.gsub(/("[^"\n]*")|('[^'\n]*')/) { |s| s.gsub(substring_re, substring_subs) } # temporarily hide problematic characters within strings
+    source_scrubbed = source_scrubbed.gsub(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '')  # remove line comments that comment out the start of blocks
+    source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '')                     # remove block comments
+    source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '')                          # remove line comments (all that remain)
+    lines = source_scrubbed.split(/(^\s*\#.*$) | (;|\{|\}) /x)                     # Treat preprocessor directives as a logical line. Match ;, {, and } as end of lines
+                           .map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed
+
+    lines.each_with_index do |line, _index|
+      # find tests
+      next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m
+
+      arguments = Regexp.last_match(1)
+      name = Regexp.last_match(2)
+      call = Regexp.last_match(3)
+      params = Regexp.last_match(4)
+      args = nil
+
+      if @options[:use_param_tests] && !arguments.empty?
+        args = []
+        arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] }
+
+        arguments.scan(/\s*TEST_RANGE\s*\((.*)\)\s*$/).flatten.each do |range_str|
+          args += range_str.scan(/\[(-?\d+.?\d*), *(-?\d+.?\d*), *(-?\d+.?\d*)\]/).map do |arg_values_str|
+            arg_values_str.map do |arg_value_str|
+              arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i
+            end
+          end.map do |arg_values|
+            (arg_values[0]..arg_values[1]).step(arg_values[2]).to_a
+          end.reduce do |result, arg_range_expanded|
+            result.product(arg_range_expanded)
+          end.map do |arg_combinations|
+            arg_combinations.flatten.join(', ')
+          end
+        end
+      end
+
+      tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 }
+    end
+
+    tests_and_line_numbers.uniq! { |v| v[:test] }
+
+    # determine line numbers and create tests to run
+    source_lines = source.split("\n")
+    source_index = 0
+    tests_and_line_numbers.size.times do |i|
+      source_lines[source_index..-1].each_with_index do |line, index|
+        next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
+
+        source_index += index
+        tests_and_line_numbers[i][:line_number] = source_index + 1
+        break
+      end
+    end
+
+    tests_and_line_numbers
+  end
+
+  def find_includes(source)
+    # remove comments (block and line, in three steps to ensure correct precedence)
+    source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '')  # remove line comments that comment out the start of blocks
+    source.gsub!(/\/\*.*?\*\//m, '')                     # remove block comments
+    source.gsub!(/\/\/.*$/, '')                          # remove line comments (all that remain)
+
+    # parse out includes
+    includes = {
+      local: source.scan(/^\s*#include\s+\"\s*(.+\.#{@options[:include_extensions]})\s*\"/).flatten,
+      system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
+      linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+\.#{@options[:source_extensions]})\s*\"/).flatten
+    }
+    includes
+  end
+
+  def find_mocks(includes)
+    mock_headers = []
+    includes.each do |include_path|
+      include_file = File.basename(include_path)
+      mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}\.h$/i
+    end
+    mock_headers
+  end
+
+  def find_setup_and_teardown(source)
+    @options[:has_setup] = source =~ /void\s+#{@options[:setup_name]}\s*\(/
+    @options[:has_teardown] = source =~ /void\s+#{@options[:teardown_name]}\s*\(/
+    @options[:has_suite_setup] ||= (source =~ /void\s+suiteSetUp\s*\(/)
+    @options[:has_suite_teardown] ||= (source =~ /int\s+suiteTearDown\s*\(int\s+([a-zA-Z0-9_])+\s*\)/)
+  end
+
+  def create_header(output, mocks, testfile_includes = [])
+    output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+    output.puts("\n/*=======Automagically Detected Files To Include=====*/")
+    output.puts("#include \"#{@options[:framework]}.h\"")
+    output.puts('#include "cmock.h"') unless mocks.empty?
+    if @options[:defines] && !@options[:defines].empty?
+      @options[:defines].each { |d| output.puts("#ifndef #{d}\n#define #{d}\n#endif /* #{d} */") }
+    end
+    if @options[:header_file] && !@options[:header_file].empty?
+      output.puts("#include \"#{File.basename(@options[:header_file])}\"")
+    else
+      @options[:includes].flatten.uniq.compact.each do |inc|
+        output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
+      end
+      testfile_includes.each do |inc|
+        output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
+      end
+    end
+    mocks.each do |mock|
+      output.puts("#include \"#{mock}\"")
+    end
+    output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
+
+    return unless @options[:enforce_strict_ordering]
+
+    output.puts('')
+    output.puts('int GlobalExpectCount;')
+    output.puts('int GlobalVerifyOrder;')
+    output.puts('char* GlobalOrderError;')
+  end
+
+  def create_externs(output, tests, _mocks)
+    output.puts("\n/*=======External Functions This Runner Calls=====*/")
+    output.puts("extern void #{@options[:setup_name]}(void);")
+    output.puts("extern void #{@options[:teardown_name]}(void);")
+    output.puts("\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif") if @options[:externc]
+    tests.each do |test|
+      output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
+    end
+    output.puts("#ifdef __cplusplus\n}\n#endif") if @options[:externc]
+    output.puts('')
+  end
+
+  def create_mock_management(output, mock_headers)
+    output.puts("\n/*=======Mock Management=====*/")
+    output.puts('static void CMock_Init(void)')
+    output.puts('{')
+
+    if @options[:enforce_strict_ordering]
+      output.puts('  GlobalExpectCount = 0;')
+      output.puts('  GlobalVerifyOrder = 0;')
+      output.puts('  GlobalOrderError = NULL;')
+    end
+
+    mocks = mock_headers.map { |mock| File.basename(mock, '.*') }
+    mocks.each do |mock|
+      mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+      output.puts("  #{mock_clean}_Init();")
+    end
+    output.puts("}\n")
+
+    output.puts('static void CMock_Verify(void)')
+    output.puts('{')
+    mocks.each do |mock|
+      mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+      output.puts("  #{mock_clean}_Verify();")
+    end
+    output.puts("}\n")
+
+    output.puts('static void CMock_Destroy(void)')
+    output.puts('{')
+    mocks.each do |mock|
+      mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+      output.puts("  #{mock_clean}_Destroy();")
+    end
+    output.puts("}\n")
+  end
+
+  def create_setup(output)
+    return if @options[:has_setup]
+
+    output.puts("\n/*=======Setup (stub)=====*/")
+    output.puts("void #{@options[:setup_name]}(void) {}")
+  end
+
+  def create_teardown(output)
+    return if @options[:has_teardown]
+
+    output.puts("\n/*=======Teardown (stub)=====*/")
+    output.puts("void #{@options[:teardown_name]}(void) {}")
+  end
+
+  def create_suite_setup(output)
+    return if @options[:suite_setup].nil?
+
+    output.puts("\n/*=======Suite Setup=====*/")
+    output.puts('void suiteSetUp(void)')
+    output.puts('{')
+    output.puts(@options[:suite_setup])
+    output.puts('}')
+  end
+
+  def create_suite_teardown(output)
+    return if @options[:suite_teardown].nil?
+
+    output.puts("\n/*=======Suite Teardown=====*/")
+    output.puts('int suiteTearDown(int num_failures)')
+    output.puts('{')
+    output.puts(@options[:suite_teardown])
+    output.puts('}')
+  end
+
+  def create_reset(output)
+    output.puts("\n/*=======Test Reset Options=====*/")
+    output.puts("void #{@options[:test_reset_name]}(void);")
+    output.puts("void #{@options[:test_reset_name]}(void)")
+    output.puts('{')
+    output.puts("  #{@options[:teardown_name]}();")
+    output.puts('  CMock_Verify();')
+    output.puts('  CMock_Destroy();')
+    output.puts('  CMock_Init();')
+    output.puts("  #{@options[:setup_name]}();")
+    output.puts('}')
+    output.puts("void #{@options[:test_verify_name]}(void);")
+    output.puts("void #{@options[:test_verify_name]}(void)")
+    output.puts('{')
+    output.puts('  CMock_Verify();')
+    output.puts('}')
+  end
+
+  def create_run_test(output)
+    require 'erb'
+    template = ERB.new(File.read(File.join(__dir__, 'run_test.erb')), nil, '<>')
+    output.puts("\n" + template.result(binding))
+  end
+
+  def create_args_wrappers(output, tests)
+    return unless @options[:use_param_tests]
+
+    output.puts("\n/*=======Parameterized Test Wrappers=====*/")
+    tests.each do |test|
+      next if test[:args].nil? || test[:args].empty?
+
+      test[:args].each.with_index(1) do |args, idx|
+        output.puts("static void runner_args#{idx}_#{test[:test]}(void)")
+        output.puts('{')
+        output.puts("    #{test[:test]}(#{args});")
+        output.puts("}\n")
+      end
+    end
+  end
+
+  def create_main(output, filename, tests, used_mocks)
+    output.puts("\n/*=======MAIN=====*/")
+    main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s
+    if @options[:cmdline_args]
+      if main_name != 'main'
+        output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);")
+      end
+      output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
+      output.puts('{')
+      output.puts('  int parse_status = UnityParseOptions(argc, argv);')
+      output.puts('  if (parse_status != 0)')
+      output.puts('  {')
+      output.puts('    if (parse_status < 0)')
+      output.puts('    {')
+      output.puts("      UnityPrint(\"#{filename.gsub('.c', '')}.\");")
+      output.puts('      UNITY_PRINT_EOL();')
+      tests.each do |test|
+        if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty?
+          output.puts("      UnityPrint(\"  #{test[:test]}\");")
+          output.puts('      UNITY_PRINT_EOL();')
+        else
+          test[:args].each do |args|
+            output.puts("      UnityPrint(\"  #{test[:test]}(#{args})\");")
+            output.puts('      UNITY_PRINT_EOL();')
+          end
+        end
+      end
+      output.puts('      return 0;')
+      output.puts('    }')
+      output.puts('    return parse_status;')
+      output.puts('  }')
+    else
+      main_return = @options[:omit_begin_end] ? 'void' : 'int'
+      if main_name != 'main'
+        output.puts("#{@options[:main_export_decl]} #{main_return} #{main_name}(void);")
+      end
+      output.puts("#{main_return} #{main_name}(void)")
+      output.puts('{')
+    end
+    output.puts('  suiteSetUp();') if @options[:has_suite_setup]
+    if @options[:omit_begin_end]
+      output.puts("  UnitySetTestFile(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
+    else
+      output.puts("  UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
+    end
+    tests.each do |test|
+      if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty?
+        output.puts("  run_test(#{test[:test]}, \"#{test[:test]}\", #{test[:line_number]});")
+      else
+        test[:args].each.with_index(1) do |args, idx|
+          wrapper = "runner_args#{idx}_#{test[:test]}"
+          testname = "#{test[:test]}(#{args})".dump
+          output.puts("  run_test(#{wrapper}, #{testname}, #{test[:line_number]});")
+        end
+      end
+    end
+    output.puts
+    output.puts('  CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
+    if @options[:has_suite_teardown]
+      if @options[:omit_begin_end]
+        output.puts('  (void) suite_teardown(0);')
+      else
+        output.puts('  return suiteTearDown(UnityEnd());')
+      end
+    else
+      output.puts('  return UnityEnd();') unless @options[:omit_begin_end]
+    end
+    output.puts('}')
+  end
+
+  def create_h_file(output, filename, tests, testfile_includes, used_mocks)
+    filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase
+    output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+    output.puts("#ifndef _#{filename}")
+    output.puts("#define _#{filename}\n\n")
+    output.puts("#include \"#{@options[:framework]}.h\"")
+    output.puts('#include "cmock.h"') unless used_mocks.empty?
+    @options[:includes].flatten.uniq.compact.each do |inc|
+      output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
+    end
+    testfile_includes.each do |inc|
+      output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
+    end
+    output.puts "\n"
+    tests.each do |test|
+      if test[:params].nil? || test[:params].empty?
+        output.puts("void #{test[:test]}(void);")
+      else
+        output.puts("void #{test[:test]}(#{test[:params]});")
+      end
+    end
+    output.puts("#endif\n\n")
+  end
+end
+
+if $0 == __FILE__
+  options = { includes: [] }
+
+  # parse out all the options first (these will all be removed as we go)
+  ARGV.reject! do |arg|
+    case arg
+    when '-cexception'
+      options[:plugins] = [:cexception]
+      true
+    when /\.*\.ya?ml$/
+      options = UnityTestRunnerGenerator.grab_config(arg)
+      true
+    when /--(\w+)=\"?(.*)\"?/
+      options[Regexp.last_match(1).to_sym] = Regexp.last_match(2)
+      true
+    when /\.*\.(?:hpp|hh|H|h)$/
+      options[:includes] << arg
+      true
+    else false
+    end
+  end
+
+  # make sure there is at least one parameter left (the input file)
+  unless ARGV[0]
+    puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
+          "\n  input_test_file         - this is the C file you want to create a runner for",
+          '  output                  - this is the name of the runner file to generate',
+          '                            defaults to (input_test_file)_Runner',
+          '  files:',
+          '    *.yml / *.yaml        - loads configuration from here in :unity or :cmock',
+          '    *.h                   - header files are added as #includes in runner',
+          '  options:',
+          '    -cexception           - include cexception support',
+          '    -externc              - add extern "C" for cpp support',
+          '    --setup_name=""       - redefine setUp func name to something else',
+          '    --teardown_name=""    - redefine tearDown func name to something else',
+          '    --main_name=""        - redefine main func name to something else',
+          '    --test_prefix=""      - redefine test prefix from default test|spec|should',
+          '    --test_reset_name=""  - redefine resetTest func name to something else',
+          '    --test_verify_name="" - redefine verifyTest func name to something else',
+          '    --suite_setup=""      - code to execute for setup of entire suite',
+          '    --suite_teardown=""   - code to execute for teardown of entire suite',
+          '    --use_param_tests=1   - enable parameterized tests (disabled by default)',
+          '    --omit_begin_end=1    - omit calls to UnityBegin and UnityEnd (disabled by default)',
+          '    --header_file=""      - path/name of test header file to generate too'].join("\n")
+    exit 1
+  end
+
+  # create the default test runner name if not specified
+  ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1]
+
+  UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
+end
diff --git a/test/tools/meson.build b/test/tools/meson.build
new file mode 100644
index 0000000..7e9b122
--- /dev/null
+++ b/test/tools/meson.build
@@ -0,0 +1,6 @@
+generate_test_runner = find_program('generate_test_runner.rb')
+test_runner_generator = generator(
+  generate_test_runner,
+  output: ['@BASENAME@_Runner.c'],
+  arguments: ['@INPUT@', '@OUTPUT@']
+)
diff --git a/test/tools/run_test.erb b/test/tools/run_test.erb
new file mode 100644
index 0000000..f91b566
--- /dev/null
+++ b/test/tools/run_test.erb
@@ -0,0 +1,37 @@
+/*=======Test Runner Used To Run Each Test=====*/
+static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num)
+{
+    Unity.CurrentTestName = name;
+    Unity.CurrentTestLineNumber = line_num;
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+    if (!UnityTestMatches())
+        return;
+#endif
+    Unity.NumberOfTests++;
+    UNITY_CLR_DETAILS();
+    UNITY_EXEC_TIME_START();
+    CMock_Init();
+    if (TEST_PROTECT())
+    {
+<% if @options[:plugins].include?(:cexception) %>
+        CEXCEPTION_T e;
+        Try {
+            <%= @options[:setup_name] %>();
+            func();
+        } Catch(e) {
+            TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!");
+        }
+<% else %>
+        <%= @options[:setup_name] %>();
+        func();
+<% end %>
+    }
+    if (TEST_PROTECT())
+    {
+        <%= @options[:teardown_name] %>();
+        CMock_Verify();
+    }
+    CMock_Destroy();
+    UNITY_EXEC_TIME_STOP();
+    UnityConcludeTest();
+}
diff --git a/test/tools/type_sanitizer.rb b/test/tools/type_sanitizer.rb
new file mode 100644
index 0000000..dafb882
--- /dev/null
+++ b/test/tools/type_sanitizer.rb
@@ -0,0 +1,6 @@
+module TypeSanitizer
+  def self.sanitize_c_identifier(unsanitized)
+    # convert filename to valid C identifier by replacing invalid chars with '_'
+    unsanitized.gsub(/[-\/\\\.\,\s]/, '_')
+  end
+end
-- 
GitLab


From cea4951ac19c2fc80d334756930967b33bd795c0 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 17 Mar 2022 17:49:43 +0100
Subject: [PATCH 17/46] refactor & test Rice and Golomb Encoder

---
 test/meson.build | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/test/meson.build b/test/meson.build
index c3a6afb..b843e00 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -30,12 +30,14 @@ if cppcheck.found()
   )
 endif
 
+subdir('tools')
+
 subdir('cmp_tool')
 
 cunit_dep = dependency('cunit', required : false)
-if cunit_dep.found()
-  subdir('cmp_icu')
-else
-  message('C Unit Testing Framework not found! Skipping unit tests.')
-endif
 
+unity_dep = dependency('unity', fallback : ['unity', 'unity_dep'])
+# unity_proj = subproject('unity')
+# unity_dep = unity_proj.get_variable('unity_dep')
+
+subdir('cmp_icu')
-- 
GitLab


From b402a986eb161d17413a29e7d276a97da490ed02 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 22 Mar 2022 16:28:07 +0100
Subject: [PATCH 18/46] refactor and test for encode_value_zero

---
 lib/cmp_icu_new.c               | 299 +++++++++++++++++++-
 test/cmp_icu/test_cmp_icu_new.c | 469 ++++++++++++++++++++++++++++++--
 2 files changed, 735 insertions(+), 33 deletions(-)

diff --git a/lib/cmp_icu_new.c b/lib/cmp_icu_new.c
index e6f6752..f4bec36 100644
--- a/lib/cmp_icu_new.c
+++ b/lib/cmp_icu_new.c
@@ -26,6 +26,52 @@
 /* return code if the bitstream buffer is too small to store the whole bitstream */
 #define CMP_ERROR_SAMLL_BUF -2
 
+/* pointer to a code word generation function */
+typedef uint32_t (*generate_cw_pt)(uint32_t value, uint32_t encoder_par1,
+				   uint32_t encoder_par2, uint32_t *cw);
+
+/* typedef uint32_t (*next_model_f_pt)(uint32_t model_mode_val, uint32_t diff_model_var); */
+
+struct encoder_setupt {
+	/* unsigned int lossy_par; */
+	/* next_model_f_pt *next_model_f; */
+	generate_cw_pt generate_cw; /* pointer to the code word generation function */
+	/* uint32_t updated_model; */
+	uint32_t encoder_par1;
+	uint32_t encoder_par2;
+	uint32_t outlier_par;
+	uint32_t model_value;
+	uint32_t max_value_bits; /* how many bits are needed to represent the highest possible value */
+	uint32_t max_bit_len; /* maximum length of the bitstream/icu_output_buf in bits */
+	uint32_t *bitstream_adr;
+};
+
+
+/**
+ * @brief map a signed value into a positive value range
+ *
+ * @param value_to_map		signed value to map
+ * @param max_value_bits	how many bits are needed to represent the
+ *				highest possible value
+ *
+ * @returns the positive mapped value
+ */
+
+static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_value_bits)
+{
+	uint32_t mask = (~0U >> (32 - max_value_bits)); /* mask the used bits */
+
+	value_to_map &= mask;
+	if (value_to_map >> (max_value_bits - 1)) { /* check the leading signed bit */
+		value_to_map |= ~mask; /* convert to 32-bit signed integer */
+		/* map negative values to uneven numbers */
+		return (-value_to_map) * 2 - 1; /* possible integer overflow is intended */
+	} else {
+		/* map positive values to even numbers */
+		return value_to_map * 2; /* possible integer overflow is intended */
+	}
+}
+
 
 /**
  * @brief put the value of up to 32 bits into a bitstream accessed as 32-bit
@@ -43,8 +89,6 @@
  * @returns length in bits of the generated bitstream on success; returns
  *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
  *          the bitstream buffer is too small to put the value in the bitstream
- * @note a value with more bits set as the n_bits parameter is considered as an
- *	erroneous input.
  */
 
 static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
@@ -60,21 +104,11 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
 		return -1;
 
 	if (n_bits == 0)
-		return 0;
+		return stream_len;
 
 	if (n_bits > 32)
 		return -1;
 
-	/* (M) is the n_bits parameter large enough to cover all value bits; the
-	 * calculations can be re-used in the unsegmented code, so we have no overhead
-	 */
-	shiftRight = 32 - n_bits;
-	mask = 0xFFFFFFFFU >> shiftRight;
-	if (value & ~mask) {
-		debug_print("Error: Not all set bits in the put value are added to the bitstream. Check value n_bits parameter combination.\n");
-		return -1;
-	}
-
 	/* Do we need to write data to the bitstream? */
 	if (!bitstream_adr)
 		return stream_len;
@@ -85,6 +119,13 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
 		return CMP_ERROR_SAMLL_BUF;
 	}
 
+	/* (M) is the n_bits parameter large enough to cover all value bits; the
+	 * calculations can be re-used in the unsegmented code, so we have no overhead
+	 */
+	shiftRight = 32 - n_bits;
+	mask = 0xFFFFFFFFU >> shiftRight;
+	value &= mask;
+
 	/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
 	local_adr = bitstream_adr + (bit_offset >> 5);
 	bitsLeft = bit_offset & 0x1F;
@@ -163,3 +204,235 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
 	return stream_len;
 }
 
+
+/**
+ * @brief forms the codeword according to the Rice code
+ *
+ * @param value		value to be encoded
+ * @param m		Golomb parameter, only m's which are power of 2 are allowed
+ * @param log2_m	Rice parameter, is log_2(m) calculate outside function
+ *			for better performance
+ * @param cw		address were the encode code word is stored
+ *
+ * @returns the length of the formed code word in bits
+ * @note no check if the generated code word is not longer than 32 bits.
+ */
+
+static uint32_t Rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
+				 uint32_t *cw)
+{
+	uint32_t g;  /* quotient of value/m */
+	uint32_t q;  /* quotient code without ending zero */
+	uint32_t r;  /* remainder of value/m */
+	uint32_t rl; /* remainder length */
+
+	g = value >> log2_m; /* quotient, number of leading bits */
+	q = (1U << g) - 1;   /* prepare the quotient code without ending zero */
+
+	r = value & (m-1);   /* calculate the remainder */
+	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the quotient code) */
+	*cw = (q << rl) | r; /* put the quotient and remainder code together */
+	/*
+	 * NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined
+	 * behavior. However, in this case, a valid code with a maximum of 32
+	 * bits can only be formed if q = 0. Any shift with 0 << x always
+	 * results in 0, which forms the correct codeword in this case. For
+	 * performance reasons, this undefined behaviour is not caught.
+	 */
+
+	return rl + g;	      /* calculate the length of the code word */
+}
+
+
+/**
+ * @brief forms a codeword according to the Golomb code
+ *
+ * @param value		value to be encoded
+ * @param m		Golomb parameter (have to be bigger than 0)
+ * @param log2_m	is log_2(m) calculate outside function for better
+ *			performance
+ * @param cw		address were the formed code word is stored
+ *
+ * @returns the length of the formed code word in bits
+ */
+
+static uint32_t Golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
+				   uint32_t *cw)
+{
+	uint32_t len0, b, g, q, lg;
+	uint32_t len;
+	uint32_t cutoff;
+
+	len0 = log2_m + 1;                 /* codeword length in group 0 */
+	cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */
+
+	if (value < cutoff) { /* group 0 */
+		*cw = value;
+		len = len0;
+	} else { /* other groups */
+		g = (value-cutoff) / m; /* this group is which one  */
+		b = cutoff << 1;        /* form the base codeword */
+		lg = len0 + g;          /* it has lg remainder bits */
+		q = (1U << g) - 1;      /* prepare the left side in unary */
+		*cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */
+		len = lg + 1;           /* length of the codeword */
+	}
+	return len;
+}
+
+
+/**
+ * @brief generate a code word without a outlier mechanism and put in the
+ *	bitstream
+ *
+ * @param value		value to encode in the bitstream
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
+ *
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error
+ */
+
+static int encode_normal(uint32_t value, int stream_len,
+			 struct encoder_setupt *setup)
+{
+	uint32_t code_word, cw_len;
+
+	cw_len = setup->generate_cw(value, setup->encoder_par1,
+				    setup->encoder_par2, &code_word);
+
+	return put_n_bits32(code_word, cw_len, stream_len, setup->bitstream_adr,
+			    setup->max_bit_len);
+}
+
+
+/**
+ * @brief subtract the model from the data and encode the result and put it into
+ *	bitstream, for outlier use the zero escape symbol mechanism
+ *
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
+ *
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error
+ *
+ * @note no check if data or model are in the allowed range
+ */
+
+static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
+			     struct encoder_setupt *setup)
+{
+	data -= model;
+
+	data = map_to_pos(data, setup->max_value_bits);
+
+	/* For performance reasons we check if there is an outlier before adding
+	 * one to the data, than the other way around:
+	 * data++;
+	 * if (data < setup->outlier_par && data != 0)
+	 *	return ...
+	 */
+	if (data < (setup->outlier_par - 1)) {
+		data++; /* add 1 to every value so we can use 0 as escape symbol */
+		return encode_normal(data, stream_len, setup);
+	}
+
+	data++; /* add 1 to every value so we can use 0 as escape symbol */
+
+	/* use zero as escape symbol */
+	stream_len = encode_normal(0, stream_len, setup);
+	if (stream_len <= 0)
+		return stream_len;
+
+	/* put the data unencoded in the bitstream */
+	stream_len = put_n_bits32(data, setup->max_value_bits, stream_len,
+				  setup->bitstream_adr, setup->max_bit_len);
+
+	return stream_len;
+
+}
+
+
+static int cal_multi_offset(unsigned int unencoded_data)
+{
+	if (unencoded_data <= 0x3)
+		return 0;
+	if (unencoded_data <= 0xF)
+		return 1;
+	if (unencoded_data <= 0x3F)
+		return 2;
+	if (unencoded_data <= 0xFF)
+		return 3;
+	if (unencoded_data <= 0x3FF)
+		return 4;
+	if (unencoded_data <= 0xFFF)
+		return 5;
+	if (unencoded_data <= 0x3FFF)
+		return 6;
+	if (unencoded_data <= 0xFFFF)
+		return 7;
+	if (unencoded_data <= 0x3FFFF)
+		return 8;
+	if (unencoded_data <= 0xFFFFF)
+		return 9;
+	if (unencoded_data <= 0x3FFFFF)
+		return 10;
+	if (unencoded_data <= 0xFFFFFF)
+		return 11;
+	if (unencoded_data <= 0x3FFFFFF)
+		return 12;
+	if (unencoded_data <= 0xFFFFFFF)
+		return 13;
+	if (unencoded_data <= 0x3FFFFFFF)
+		return 14;
+	else
+		return 15;
+}
+
+
+#if 0
+static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
+			      struct encoder_setupt *setup)
+{
+	uint32_t unencoded_data;
+	unsigned int unencoded_data_len;
+	uint32_t escape_sym;
+	uint32_t escape_sym_offset;
+
+	data -= model; /* possible underflow is intended */
+
+	data = map_to_pos(data, setup->max_value_bits);
+
+	if (data < setup->outlier_par)
+		return  encode_normal(data, stream_len, setup);
+	/*
+	 * In this mode we put the difference between the data and the spillover
+	 * threshold value (unencoded_data) after a encoded escape symbol, which
+	 * indicate that the next codeword is unencoded.
+	 * We use different escape symbol depended on the size the needed bit of
+	 * unencoded data:
+	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is spill + 0
+	 * 3, 4 bits needed for unencoded data -> escape symbol is spill + 1
+	 * ..
+	 */
+
+	unencoded_data = data - setup->outlier_par;
+
+	escape_sym_offset = cal_multi_offset(unencoded_data);
+	escape_sym  = setup->outlier_par + escape_sym_offset;
+	unencoded_data_len = (escape_sym_offset + 1) * 2;
+
+	/* put the escape symbol in the bitstream */
+	stream_len = encode_normal(escape_sym, stream_len, setup);
+	if (stream_len <= 0)
+		return stream_len;
+
+	/* put the unencoded data in the bitstream */
+	stream_len = put_n_bits32(unencoded_data, unencoded_data_len, stream_len,
+				  setup->bitstream_adr, setup->max_bit_len);
+
+	return stream_len;
+}
+#endif
diff --git a/test/cmp_icu/test_cmp_icu_new.c b/test/cmp_icu/test_cmp_icu_new.c
index 6e57615..986b7b6 100644
--- a/test/cmp_icu/test_cmp_icu_new.c
+++ b/test/cmp_icu/test_cmp_icu_new.c
@@ -2,10 +2,99 @@
 
 #include "unity.h"
 
+#include "cmp_support.h"
 /* this is a hack to test static functions */
 #include "../lib/cmp_icu_new.c"
 
 
+/**
+* @test map_to_pos
+*/
+
+void test_map_to_pos(void)
+{
+	uint32_t value_to_map;
+	uint32_t max_value_bits;
+	uint32_t mapped_value;
+
+	/* test mapping 32 bits values */
+	max_value_bits = 32;
+
+	value_to_map = 0;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(0, mapped_value);
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 1;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(2, mapped_value);
+
+	value_to_map = 42;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(84, mapped_value);
+
+	value_to_map = INT32_MAX;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value);
+
+	value_to_map = INT32_MIN;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value);
+
+	/* test mapping 16 bits values */
+	max_value_bits = 16;
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	/* test mapping 6 bits values */
+	max_value_bits = 6;
+
+	value_to_map = 0;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(0, mapped_value);
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = UINT32_MAX;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = -1U & 0x3FU;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 63;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 1;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(2, mapped_value);
+
+	value_to_map = 31;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(62, mapped_value);
+
+	value_to_map = -33U; /* aka 31 */
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(62, mapped_value);
+
+	value_to_map = -32U;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(63, mapped_value);
+
+	value_to_map = 32;
+	mapped_value = map_to_pos(value_to_map, max_value_bits);
+	TEST_ASSERT_EQUAL_INT(63, mapped_value);
+}
+
 
 /**
  * @test put_n_bits32
@@ -42,7 +131,11 @@ void test_put_n_bits32(void)
 
 	init_PB32_arrays(testarray0, testarray1);
 	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
 	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
 
 	/*** n=0 ***/
 
@@ -56,7 +149,9 @@ void test_put_n_bits32(void)
 	TEST_ASSERT_EQUAL_INT(0, rval);
 	TEST_ASSERT(testarray1[0] == 0xffffffff);
 
-	/* TODO: not a valid test */
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+
 	v = 0xffffffff; n = 0; o = 0;
 	rval = put_n_bits32(v, n, o, testarray0, l);
 	TEST_ASSERT_EQUAL_INT(0, rval);
@@ -66,27 +161,35 @@ void test_put_n_bits32(void)
 	TEST_ASSERT_EQUAL_INT(0, rval);
 	TEST_ASSERT(testarray1[0] == 0xffffffff);
 
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+
 	/* do not write, right border */
-	v = 0; n = 0; o = 31;
+	v = 0; n = 0; o = l;
 	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT_EQUAL_INT(l, rval);
 	TEST_ASSERT(testarray0[0] == 0);
 
 	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT_EQUAL_INT(l, rval);
 	TEST_ASSERT(testarray1[0] == 0xffffffff);
 
-	/* TODO: not a valid test */
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+
 	/* test value = 0xffffffff; N = 0 */
-	v = 0xffffffff; n = 0; o = 31;
+	v = 0xffffffff; n = 0; o = l;
 	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT_EQUAL_INT(l, rval);
 	TEST_ASSERT(testarray0[0] == 0);
 
 	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT_EQUAL_INT(l, rval);
 	TEST_ASSERT(testarray1[0] == 0xffffffff);
 
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+
 	/*** n=1 ***/
 
 	/* left border, write 0 */
@@ -114,10 +217,12 @@ void test_put_n_bits32(void)
 	rval = put_n_bits32(v, n, o, testarray0, l);
 	TEST_ASSERT_EQUAL_INT(rval, 32);
 	TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
+	TEST_ASSERT(testarray0[1] == 0);
 
 	rval = put_n_bits32(v, n, o, testarray1, l);
 	TEST_ASSERT_EQUAL_INT(rval, 32);
 	TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
 	/* re-init input arrays after clobbering */
 	init_PB32_arrays(testarray0, testarray1);
 
@@ -317,26 +422,49 @@ void test_put_n_bits32(void)
 	rval = put_n_bits32(v, n, o, NULL, l);
 	TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
 
-	/* error cases */
-	/* n too large */
-	v = 0x0; n = 33; o = 1;
+	/* value larger than n allows */
+	v = 0x7f; n = 6; o = 10;
 	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, -1);
-	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray0[0] == 0x003f0000);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	v = 0xffffffff; n = 6; o = 10;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray0[0] == 0x003f0000);
 	TEST_ASSERT(testarray0[1] == 0);
 
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+
 	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, -1);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
 
-	/* value larger than n allows */
-	v = 0x7f; n = 6; o = 10;
+	/*** error cases ***/
+	/* n too large */
+	v = 0x0; n = 33; o = 1;
 	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
 	TEST_ASSERT(testarray0[0] == 0);
 	TEST_ASSERT(testarray0[1] == 0);
 
 	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
 
 	/* try to put too much in the bitstream */
 	v = 0x1; n = 1; o = 96;
@@ -346,11 +474,11 @@ void test_put_n_bits32(void)
 	TEST_ASSERT(testarray0[1] == 0);
 	TEST_ASSERT(testarray0[2] == 0);
 
-	/* this should work */
+	/* this should work (if bitstream=NULL no length check) */
 	rval = put_n_bits32(v, n, o, NULL, l);
 	TEST_ASSERT_EQUAL_INT(97, rval);
 
-	/* offset lager than max_bit_len */
+	/* offset lager than max_bit_len(l) */
 	v = 0x0; n = 32; o = INT32_MAX;
 	rval = put_n_bits32(v, n, o, testarray1, l);
 	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
@@ -370,4 +498,305 @@ void test_put_n_bits32(void)
 
 	rval = put_n_bits32(v, n, o, NULL, l);
 	TEST_ASSERT_EQUAL_INT(-1, rval);
+
+	v = 0x0; n = 0; o = -2;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+}
+
+
+/**
+ * @test Rice_encoder
+ */
+
+void test_Rice_encoder(void)
+{
+	uint32_t value, g_par, log2_g_par, cw, cw_len;
+
+	/* test minimum Golomb parameter */
+	value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(1, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 31;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
+
+	/* test some arbitrary values */
+	value = 0; log2_g_par = 4; g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 42;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(7, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
+
+	value = 446;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
+
+	value = 447;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
+
+	/* test maximum Golomb parameter for Rice_encoder */
+	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 0x7FFFFFFE;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
+
+	value = 0x7FFFFFFF;
+	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
+}
+
+
+/**
+ * @test Golomb_encoder
+ */
+
+void test_Golomb_encoder(void)
+{
+	uint32_t value, g_par, log2_g_par, cw, cw_len;
+
+	/* test minimum Golomb parameter */
+	value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(1, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 31;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
+
+
+	/* test some arbitrary values with g_par = 16 */
+	value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 42;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(7, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
+
+	value = 446;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
+
+	value = 447;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
+
+
+	/* test some arbitrary values with g_par = 3 */
+	value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(2, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(3, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x2, cw);
+
+	value = 42;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(16, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFC, cw);
+
+	value = 44;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(17, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1FFFB, cw);
+
+	value = 88;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFA, cw);
+
+	value = 89;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw);
+
+
+	/* test maximum Golomb parameter for Golomb_encoder */
+	value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 0x7FFFFFFE;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
+
+	value = 0x7FFFFFFF;
+	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
+}
+
+
+/**
+ * @test encode_value_zero
+ */
+
+void test_encode_value_zero(void)
+{
+	uint32_t data, model;
+	int stream_len;
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[3] = {0};
+
+	/* setup the setup */
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
+	setup.outlier_par = 32;
+	setup.max_value_bits = 32;
+	setup.generate_cw = Rice_encoder;
+	setup.bitstream_adr = bitstream;
+	setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
+
+	stream_len = 0;
+
+	data = 0; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(2, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	data = 5; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(14, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	data = 2; model = 7;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(25, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* zero escape mechanism */
+	data = 100; model = 42;
+	/* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(58, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* test overflow */
+	data = INT32_MIN; model = 0;
+	/* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(91, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* small buffer error */
+	data = 23; model = 26;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+
+	/* reset bitstream to all bits set */
+	bitstream[0] = ~0U;
+	bitstream[1] = ~0U;
+	bitstream[2] = ~0U;
+	stream_len = 0;
+
+	/* we use now values with maximum 6 bits */
+	setup.max_value_bits = 6;
+
+	/* lowest value before zero encoding */
+	data = 53; model = 38;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(32, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* lowest value with zero encoding */
+	data = 0; model = 16;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(39, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* maximum positive value to encode */
+	data = 31; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(46, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* maximum negative value to encode */
+	data = -32U; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(53, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* small buffer error when creating the zero escape symbol*/
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	bitstream[2] = 0;
+	stream_len = 32;
+	setup.max_bit_len = 32;
+	data = 31; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(-2, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
 }
-- 
GitLab


From 83ba84a190e41c8535a99b2cb930d43470615867 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Wed, 23 Mar 2022 14:43:20 +0100
Subject: [PATCH 19/46] refactor and test encode_value_multi()

---
 lib/cmp_icu_new.c               |  92 ++++++++++++-----------------
 test/cmp_icu/test_cmp_icu_new.c | 100 ++++++++++++++++++++++++++++++--
 2 files changed, 134 insertions(+), 58 deletions(-)

diff --git a/lib/cmp_icu_new.c b/lib/cmp_icu_new.c
index f4bec36..d69ab0f 100644
--- a/lib/cmp_icu_new.c
+++ b/lib/cmp_icu_new.c
@@ -307,8 +307,8 @@ static int encode_normal(uint32_t value, int stream_len,
 
 
 /**
- * @brief subtract the model from the data and encode the result and put it into
- *	bitstream, for outlier use the zero escape symbol mechanism
+ * @brief subtract the model from the data, encode the result and put it into
+ *	bitstream, for encodeing outlier use the zero escape symbol mechanism
  *
  * @param data		data to encode
  * @param model		model of the data (0 if not used)
@@ -316,9 +316,11 @@ static int encode_normal(uint32_t value, int stream_len,
  * @param setup		pointer to the encoder setup
  *
  * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
  * @note no check if data or model are in the allowed range
+ * @note no check if the setup->outlier_par is in the allowed range
  */
 
 static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
@@ -328,13 +330,13 @@ static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
 
 	data = map_to_pos(data, setup->max_value_bits);
 
-	/* For performance reasons we check if there is an outlier before adding
-	 * one to the data, than the other way around:
+	/* For performance reasons, we check to see if there is an outlier
+	 * before adding one, rather than the other way around:
 	 * data++;
 	 * if (data < setup->outlier_par && data != 0)
 	 *	return ...
 	 */
-	if (data < (setup->outlier_par - 1)) {
+	if (data < (setup->outlier_par - 1)) { /* detect r */
 		data++; /* add 1 to every value so we can use 0 as escape symbol */
 		return encode_normal(data, stream_len, setup);
 	}
@@ -355,74 +357,57 @@ static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
 }
 
 
-static int cal_multi_offset(unsigned int unencoded_data)
-{
-	if (unencoded_data <= 0x3)
-		return 0;
-	if (unencoded_data <= 0xF)
-		return 1;
-	if (unencoded_data <= 0x3F)
-		return 2;
-	if (unencoded_data <= 0xFF)
-		return 3;
-	if (unencoded_data <= 0x3FF)
-		return 4;
-	if (unencoded_data <= 0xFFF)
-		return 5;
-	if (unencoded_data <= 0x3FFF)
-		return 6;
-	if (unencoded_data <= 0xFFFF)
-		return 7;
-	if (unencoded_data <= 0x3FFFF)
-		return 8;
-	if (unencoded_data <= 0xFFFFF)
-		return 9;
-	if (unencoded_data <= 0x3FFFFF)
-		return 10;
-	if (unencoded_data <= 0xFFFFFF)
-		return 11;
-	if (unencoded_data <= 0x3FFFFFF)
-		return 12;
-	if (unencoded_data <= 0xFFFFFFF)
-		return 13;
-	if (unencoded_data <= 0x3FFFFFFF)
-		return 14;
-	else
-		return 15;
-}
-
+/**
+ * @brief subtract the model from the data, encode the result and put it into
+ *	bitstream, for encoding outlier use the multi escape symbol mechanism
+ *
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
+ *
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
+ *
+ * @note no check if data or model are in the allowed range
+ * @note no check if the setup->outlier_par is in the allowed ragne
+ */
 
-#if 0
 static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
 			      struct encoder_setupt *setup)
 {
 	uint32_t unencoded_data;
 	unsigned int unencoded_data_len;
-	uint32_t escape_sym;
-	uint32_t escape_sym_offset;
+	uint32_t escape_sym, escape_sym_offset;
 
 	data -= model; /* possible underflow is intended */
 
 	data = map_to_pos(data, setup->max_value_bits);
 
-	if (data < setup->outlier_par)
+	if (data < setup->outlier_par) /* detect non-outlier */
 		return  encode_normal(data, stream_len, setup);
+
 	/*
 	 * In this mode we put the difference between the data and the spillover
 	 * threshold value (unencoded_data) after a encoded escape symbol, which
 	 * indicate that the next codeword is unencoded.
 	 * We use different escape symbol depended on the size the needed bit of
 	 * unencoded data:
-	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is spill + 0
-	 * 3, 4 bits needed for unencoded data -> escape symbol is spill + 1
-	 * ..
+	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is outlier_par + 0
+	 * 3, 4 bits needed for unencoded data -> escape symbol is outlier_par + 1
+	 * 5, 6 bits needed for unencoded data -> escape symbol is outlier_par + 2
+	 * and so on
 	 */
-
 	unencoded_data = data - setup->outlier_par;
 
-	escape_sym_offset = cal_multi_offset(unencoded_data);
-	escape_sym  = setup->outlier_par + escape_sym_offset;
-	unencoded_data_len = (escape_sym_offset + 1) * 2;
+	if (!unencoded_data) /* catch __builtin_clz(0) because the result is undefined.*/
+		escape_sym_offset = 0;
+	else
+		escape_sym_offset = (31U - (uint32_t)__builtin_clz(unencoded_data)) >> 1;
+
+	escape_sym = setup->outlier_par + escape_sym_offset;
+	unencoded_data_len = (escape_sym_offset + 1U) << 1;
 
 	/* put the escape symbol in the bitstream */
 	stream_len = encode_normal(escape_sym, stream_len, setup);
@@ -435,4 +420,3 @@ static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
 
 	return stream_len;
 }
-#endif
diff --git a/test/cmp_icu/test_cmp_icu_new.c b/test/cmp_icu/test_cmp_icu_new.c
index 986b7b6..a0d9109 100644
--- a/test/cmp_icu/test_cmp_icu_new.c
+++ b/test/cmp_icu/test_cmp_icu_new.c
@@ -8,8 +8,8 @@
 
 
 /**
-* @test map_to_pos
-*/
+ * @test map_to_pos
+ */
 
 void test_map_to_pos(void)
 {
@@ -780,7 +780,7 @@ void test_encode_value_zero(void)
 	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
 
 	/* maximum negative value to encode */
-	data = -32U; model = 0;
+	data = 0; model = 32;
 	stream_len = encode_value_zero(data, model, stream_len, &setup);
 	TEST_ASSERT_EQUAL_INT(53, stream_len);
 	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
@@ -795,8 +795,100 @@ void test_encode_value_zero(void)
 	setup.max_bit_len = 32;
 	data = 31; model = 0;
 	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(-2, stream_len);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
 }
+
+
+/**
+ * @test encode_value_multi
+ */
+
+void test_encode_value_multi(void)
+{
+	uint32_t data, model;
+	int stream_len;
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[4] = {0};
+
+	/* setup the setup */
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
+	setup.outlier_par = 16;
+	setup.max_value_bits = 32;
+	setup.generate_cw = Rice_encoder;
+	setup.bitstream_adr = bitstream;
+	setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
+
+	stream_len = 0;
+
+	data = 0; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(1, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	data = 0; model = 1;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(3, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x40000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	data = 1+23; model = 0+23;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(6, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x58000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* highest value without multi outlier encoding */
+	data = 0+42; model = 8+42;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(22, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFF800, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* lowest value with multi outlier encoding */
+	data = 8+42; model = 0+42;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(41, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFC000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* highest value with multi outlier encoding */
+	data = INT32_MIN; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(105, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0xF7800000, bitstream[3]);
+
+	/* small buffer error */
+	data = 0; model = 38;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+
+	/* small buffer error when creating the multi escape symbol*/
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	setup.max_bit_len = 32;
+
+	stream_len = 32;
+	data = 31; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+}
-- 
GitLab


From 721a8263099862b2927c9c0c12bc31dd46a0ed01 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 31 May 2022 15:19:12 +0200
Subject: [PATCH 20/46] add compression of non-imagette data

---
 cmp_tool.c                                 |  411 +--
 include/cmp_data_types.h                   |  350 ++-
 include/cmp_entity.h                       |   65 +-
 include/cmp_guess.h                        |   10 +-
 include/cmp_icu.h                          |   43 +-
 include/cmp_io.h                           |   10 +-
 include/cmp_rdcu.h                         |   28 +-
 include/cmp_support.h                      |  248 +-
 include/decmp.h                            |    8 +-
 lib/cmp_data_types.c                       |  936 ++----
 lib/cmp_entity.c                           |  679 +++--
 lib/cmp_guess.c                            |  127 +-
 lib/cmp_icu.c                              | 3207 ++++++++++++--------
 lib/cmp_icu_new.c                          |  422 ---
 lib/cmp_io.c                               |  295 +-
 lib/cmp_rdcu.c                             |  586 ++--
 lib/cmp_support.c                          |  919 +++---
 lib/decmp.c                                | 1599 ++--------
 lib/meson.build                            |    4 +-
 lib/rdcu_pkt_to_file.c                     |   14 +-
 meson.build                                |    2 +
 test/cmp_icu/meson.build                   |   26 +-
 test/cmp_icu/test_cmp_icu.c                | 1454 ++++++++-
 test/cmp_icu/test_cmp_icu_new.c            |  894 ------
 test/cmp_icu/test_decmp.c                  |  442 +++
 test/cmp_tool/cmp_tool_integration_test.py |  188 +-
 test/meson.build                           |    4 -
 27 files changed, 6847 insertions(+), 6124 deletions(-)
 mode change 100755 => 100644 cmp_tool.c
 delete mode 100644 lib/cmp_icu_new.c
 delete mode 100644 test/cmp_icu/test_cmp_icu_new.c
 create mode 100644 test/cmp_icu/test_decmp.c

diff --git a/cmp_tool.c b/cmp_tool.c
old mode 100755
new mode 100644
index e3b2716..c30ae6e
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -28,6 +28,7 @@
 #include "cmp_tool-config.h"
 #include "cmp_io.h"
 #include "cmp_icu.h"
+#include "cmp_rdcu.h" /*TODO: shift setup to support */
 #include "decmp.h"
 #include "cmp_guess.h"
 #include "cmp_entity.h"
@@ -37,11 +38,21 @@
 
 #define BUFFER_LENGTH_DEF_FAKTOR 2
 
-
 #define DEFAULT_MODEL_ID 53264  /* random default id */
 #define DEFAULT_MODEL_COUNTER 0
 
 
+/* find a good set of compression parameters for a given dataset */
+static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
+			  int guess_level);
+
+/* compress the data and write the results to files */
+static int compression(struct cmp_cfg *cfg, struct cmp_info *info);
+
+/* decompress the data and write the results in file(s)*/
+static int decompression(struct cmp_entity *ent, uint16_t *input_model_buf);
+
+
 /*
  * For long options that have no equivalent short option, use a
  * non-character as a pseudo short option, starting with CHAR_MAX + 1.
@@ -94,17 +105,6 @@ static int verbose_en;
 /* if non zero add a compression entity header in front of the compressed data */
 static int include_cmp_header = 1;
 
-/* find a good set of compression parameters for a given dataset */
-static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
-			  int guess_level);
-
-/* compress the data and write the results to files */
-static int compression(struct cmp_cfg *cfg, struct cmp_info *info);
-
-/* decompress the data and write the results in file(s)*/
-static int decompression(uint32_t *cmp_data_adr, uint16_t *input_model_buf,
-			 struct cmp_info *info);
-
 /* model ID string set by the --model_id option */
 static const char *model_id_str;
 
@@ -140,16 +140,16 @@ int main(int argc, char **argv)
 	int guess_level = DEFAULT_GUESS_LEVEL;
 	int print_diff_cfg = 0;
 
-	struct cmp_cfg cfg = {0}; /* compressor configuration struct */
-	struct cmp_info info = {0}; /* decompression information struct */
-
-	/* buffer containing all read in compressed data for decompression (including header if used) */
-	void *decomp_input_buf = NULL;
-	/* address to the compressed data for the decompression */
-	uint32_t *cmp_data_adr = NULL;
+	/* buffer containing all read in compressed data for decompression */
+	struct cmp_entity *decomp_entity = NULL;
 	/* buffer containing the read in model */
 	uint16_t *input_model_buf = NULL;
 
+	struct cmp_info info = {0}; /* decompression information struct */
+	struct cmp_cfg cfg = {0}; /* compressor configuration struct */
+
+	cfg.data_type = DATA_TYPE_IMAGETTE; /* use imagette as default data type */
+
 	/* show help if no arguments are provided */
 	if (argc < 2) {
 		print_help(program_name);
@@ -190,7 +190,7 @@ int main(int argc, char **argv)
 			verbose_en = 1;
 			break;
 		case 'V': /* --version */
-			printf("%s version %s\n", PROGRAM_NAME, VERSION);
+			printf("%s version %s\n", PROGRAM_NAME, CMP_TOOL_VERSION);
 			exit(EXIT_SUCCESS);
 			break;
 		case DIFF_CFG_OPTION:
@@ -262,20 +262,38 @@ int main(int argc, char **argv)
 #endif
 
 	if (print_model_cfg == 1) {
-		print_cfg(&DEFAULT_CFG_MODEL, print_rdcu_cfg);
+		cfg = rdcu_cfg_create(CMP_DEF_IMA_MODEL_DATA_TYPE, CMP_DEF_IMA_MODEL_CMP_MODE,
+				      CMP_DEF_IMA_MODEL_MODEL_VALUE, CMP_DEF_IMA_MODEL_LOSSY_PAR);
+		rdcu_cfg_buffers(&cfg, NULL, 0, NULL, CMP_DEF_IMA_MODEL_RDCU_DATA_ADR,
+				 CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR, CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR,
+				 CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR, 0);
+		rdcu_cfg_imagette(&cfg,
+				  CMP_DEF_IMA_MODEL_GOLOMB_PAR, CMP_DEF_IMA_MODEL_SPILL_PAR,
+				  CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP1_SPILL_PAR,
+				  CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP2_SPILL_PAR);
+		print_cfg(&cfg, print_rdcu_cfg);
 		exit(EXIT_SUCCESS);
 	}
 
 	if (print_diff_cfg == 1) {
-		print_cfg(&DEFAULT_CFG_DIFF, print_rdcu_cfg);
+		cfg = rdcu_cfg_create(CMP_DEF_IMA_DIFF_DATA_TYPE, CMP_DEF_IMA_DIFF_CMP_MODE,
+				      CMP_DEF_IMA_DIFF_MODEL_VALUE, CMP_DEF_IMA_DIFF_LOSSY_PAR);
+		rdcu_cfg_buffers(&cfg, NULL, 0, NULL, CMP_DEF_IMA_DIFF_RDCU_DATA_ADR,
+				 CMP_DEF_IMA_DIFF_RDCU_MODEL_ADR, CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR,
+				 CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR, 0);
+		rdcu_cfg_imagette(&cfg,
+				  CMP_DEF_IMA_DIFF_GOLOMB_PAR, CMP_DEF_IMA_DIFF_SPILL_PAR,
+				  CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR, CMP_DEF_IMA_DIFF_AP1_SPILL_PAR,
+				   CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR, CMP_DEF_IMA_DIFF_AP2_SPILL_PAR);
+		print_cfg(&cfg, print_rdcu_cfg);
 		exit(EXIT_SUCCESS);
 	}
 
 	printf("#########################################################\n");
 	printf("### PLATO Compression/Decompression Tool Version %s ###\n",
-	       VERSION);
+	       CMP_TOOL_VERSION);
 	printf("#########################################################\n");
-	if (!strcmp(VERSION, "0.07") || !strcmp(VERSION, "0.08"))
+	if (!strcmp(CMP_TOOL_VERSION, "0.07") || !strcmp(CMP_TOOL_VERSION, "0.08"))
 		printf("Info: Note that the behaviour of the cmp_tool has changed. From now on, the compressed data will be preceded by a header by default. The old behaviour can be achieved with the --no_header option.\n\n");
 
 	if (!data_file_name) {
@@ -293,6 +311,7 @@ int main(int argc, char **argv)
 
 	if (cmp_operation || guess_operation) {
 		ssize_t size;
+		uint32_t input_size;
 
 		if (cmp_operation) {
 			printf("## Starting the compression ##\n");
@@ -308,21 +327,26 @@ int main(int argc, char **argv)
 		printf("Importing data file %s ... ", data_file_name);
 		/* count the samples in the data file when samples == 0 */
 		if (cfg.samples == 0) {
-			size = read_file16(data_file_name, NULL, 0, 0);
-			if (size <= 0) /* empty file is treated as an error */
+			int samples;
+			size = read_file_data(data_file_name, cfg.data_type, NULL, 0, 0);
+			if (size <= 0 || size > UINT32_MAX) /* empty file is treated as an error */
 				goto fail;
-			cfg.samples = size/size_of_a_sample(cfg.cmp_mode);
+			samples = cmp_input_size_to_samples(size, cfg.data_type);
+			if (samples < 0)
+				goto fail;
+			cfg.samples = (uint32_t)samples;
 			printf("\nNo samples parameter set. Use samples = %u.\n... ", cfg.samples);
 		}
 
-		cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.cmp_mode));
+		input_size = cmp_cal_size_of_data(cfg.samples, cfg.data_type);
+		cfg.input_buf = malloc(input_size);
 		if (!cfg.input_buf) {
 			fprintf(stderr, "%s: Error allocating memory for input data buffer.\n", PROGRAM_NAME);
 			goto fail;
 		}
 
-		size = read_file16(data_file_name, cfg.input_buf, cfg.samples,
-				   verbose_en);
+		size = read_file_data(data_file_name, cfg.data_type, cfg.input_buf,
+				      input_size, verbose_en);
 		if (size < 0)
 			goto fail;
 		printf("DONE\n");
@@ -330,7 +354,8 @@ int main(int argc, char **argv)
 	} else { /* decompression mode*/
 		printf("## Starting the decompression ##\n");
 		if (info_file_name) {
-			ssize_t size;
+			ssize_t f_size;
+			size_t ent_size;
 			uint32_t cmp_size_byte;
 
 			printf("Importing decompression information file %s ... ", info_file_name);
@@ -341,63 +366,58 @@ int main(int argc, char **argv)
 
 			printf("Importing compressed data file %s ... ", data_file_name);
 			cmp_size_byte = cmp_bit_to_4byte(info.cmp_size);
-			cmp_data_adr = decomp_input_buf = malloc(cmp_size_byte);
-			if (!decomp_input_buf) {
+
+			ent_size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW,
+						  cmp_size_byte);
+			if (ent_size <= 0)
+				goto fail;
+			decomp_entity = malloc(ent_size);
+			if (!decomp_entity) {
 				fprintf(stderr, "%s: Error allocating memory for decompression input buffer.\n", PROGRAM_NAME);
 				goto fail;
 			}
+			ent_size = cmp_ent_create(decomp_entity, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW,
+						  cmp_size_byte);
+			if (ent_size <= 0)
+				goto fail;
 
-			size = read_file32(data_file_name, decomp_input_buf,
-					   cmp_size_byte/4, verbose_en);
-			if (size < 0)
+			if (info.cmp_mode_used == CMP_MODE_RAW)
+				/* the raw data does not have to be a multiple of 4 bytes */
+				cmp_size_byte = (info.cmp_size+7)/CHAR_BIT;
+
+			f_size = read_file8(data_file_name, cmp_ent_get_data_buf(decomp_entity),
+					    cmp_size_byte, verbose_en);
+			if (f_size < 0)
+				goto fail;
+
+			error = cmp_ent_write_rdcu_cmp_pars(decomp_entity, &info, NULL);
+			if (error)
 				goto fail;
 		} else { /* read in compressed data with header */
 			ssize_t size;
 			size_t buf_size;
-			struct cmp_entity *ent;
 
 			printf("Importing compressed data file %s ... ", data_file_name);
 			buf_size = size = read_file_cmp_entity(data_file_name,
 							       NULL, 0, 0);
-			if (size < 0)
+			if (size < 0 || size > UINT32_MAX)
 				goto fail;
 			/* to be save allocate at least the size of the cmp_entity struct */
 			if (buf_size < sizeof(struct cmp_entity))
 				buf_size = sizeof(struct cmp_entity);
 
-			decomp_input_buf = ent = malloc(buf_size);
-			if (!ent) {
+			decomp_entity = malloc(buf_size);
+			if (!decomp_entity) {
 				fprintf(stderr, "%s: Error allocating memory for the compression entity buffer.\n", PROGRAM_NAME);
 				goto fail;
 			}
-			size = read_file_cmp_entity(data_file_name, ent, size,
-						  verbose_en);
-			if (size < 0)
-				goto fail;
-			printf("DONE\n");
-
-			printf("Parse the compression entity header ... ");
-			error = cmp_ent_read_imagette_header(ent, &info);
-			if (error)
-				goto fail;
-			if (verbose_en)
-				print_cmp_info(&info);
-
-			/* we reuse the entity buffer for the compressed data */
-			cmp_data_adr = (uint32_t *)decomp_input_buf;
-			size = cmp_ent_get_cmp_data(ent, cmp_data_adr, buf_size);
-			ent = NULL;
+			size = read_file_cmp_entity(data_file_name, decomp_entity,
+						    size, verbose_en);
 			if (size < 0)
 				goto fail;
 
 			if (verbose_en) {
-				size_t i;
-				printf("\ncompressed data:\n");
-				for (i = 0; i < size/sizeof(uint32_t); i++) {
-					printf("%08X ", cmp_data_adr[i]);
-					if (i && !((i+1) % 4))
-						printf("\n");
-				}
+				cmp_ent_print(decomp_entity);
 				printf("\n");
 			}
 		}
@@ -406,10 +426,11 @@ int main(int argc, char **argv)
 
 	/* read in model */
 	if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
-	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used)) ||
+	    (!cmp_operation && model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity))) ||
 	    (guess_operation && model_file_name)) {
 		ssize_t size;
-		uint32_t model_length;
+		uint32_t model_size;
+		enum cmp_data_type data_type;
 
 		printf("Importing model file %s ... ", model_file_name ? model_file_name : "");
 		if (!model_file_name) {
@@ -417,19 +438,22 @@ int main(int argc, char **argv)
 			goto fail;
 		}
 
-		if (cmp_operation || guess_operation)
-			model_length = cfg.samples;
-		else
-			model_length = info.samples_used;
+		if (cmp_operation || guess_operation) {
+			data_type = cfg.data_type;
+			model_size = cmp_cal_size_of_data(cfg.samples, cfg.data_type);
+		} else {
+			data_type = cmp_ent_get_data_type(decomp_entity);
+			model_size = cmp_ent_get_original_size(decomp_entity);
+		}
 
-		input_model_buf = malloc(model_length * size_of_a_sample(cfg.cmp_mode));
+		input_model_buf = malloc(model_size);
 		if (!input_model_buf) {
 			fprintf(stderr, "%s: Error allocating memory for model buffer.\n", PROGRAM_NAME);
 			goto fail;
 		}
 
-		size = read_file16(model_file_name, input_model_buf,
-				   model_length, verbose_en);
+		size = read_file_data(model_file_name, data_type, input_model_buf,
+				      model_size, verbose_en);
 		if (size < 0)
 			goto fail;
 		printf("DONE\n");
@@ -446,7 +470,7 @@ int main(int argc, char **argv)
 		if (error)
 			goto fail;
 	} else {
-		error = decompression(cmp_data_adr, input_model_buf, &info);
+		error = decompression(decomp_entity, input_model_buf);
 		if (error)
 			goto fail;
 	}
@@ -454,17 +478,28 @@ int main(int argc, char **argv)
 	/* write our the updated model for compressed or decompression */
 	if (!guess_operation &&
 	    ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
-	    (!cmp_operation && model_mode_is_used(info.cmp_mode_used)))) {
+	    (!cmp_operation && model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity))))) {
+		enum cmp_data_type data_type = DATA_TYPE_UNKOWN;
+		uint32_t model_size;
+
 		printf("Write updated model to file %s_upmodel.dat ... ", output_prefix);
-		error = write_to_file16(input_model_buf, info.samples_used,
-					output_prefix, "_upmodel.dat", verbose_en);
+		if (cmp_operation) {
+			data_type = cfg.data_type;
+			model_size = cmp_cal_size_of_data(cfg.samples, data_type);
+		} else {
+			data_type = cmp_ent_get_data_type(decomp_entity);
+			model_size = cmp_ent_get_original_size(decomp_entity);
+		}
+
+		error = write_input_data_to_file(input_model_buf, model_size, data_type,
+						 output_prefix, "_upmodel.dat", verbose_en);
 		if (error)
 			goto fail;
 		printf("DONE\n");
 	}
 
 	free(cfg.input_buf);
-	free(decomp_input_buf);
+	free(decomp_entity);
 	free(input_model_buf);
 
 	exit(EXIT_SUCCESS);
@@ -473,56 +508,33 @@ fail:
 	printf("FAILED\n");
 
 	free(cfg.input_buf);
-	free(decomp_input_buf);
+	free(decomp_entity);
 	free(input_model_buf);
 
 	exit(EXIT_FAILURE);
 }
 
 
-static enum cmp_ent_data_type cmp_ent_map_cmp_mode_data_type(uint32_t cmp_mode)
-{
-	enum cmp_ent_data_type data_type;
-
-	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
-		if (print_rdcu_cfg)
-			data_type = DATA_TYPE_IMAGETTE_ADAPTIVE;
-		else
-			data_type = DATA_TYPE_IMAGETTE;
-		break;
-	default:
-		printf("No mapping between compression mode and header data type\n!");
-		return DATA_TYPE_UNKOWN;
-	}
-
-	/* set raw bit if needed */
-	if (raw_mode_is_used(cmp_mode))
-		data_type |= 1UL << RAW_BIT_DATA_TYPE_POS;
-
-	return data_type;
-}
-
-
 /* find a good set of compression parameters for a given dataset */
 static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 			  int guess_level)
 {
 	int error;
 	uint32_t cmp_size_bit;
-	float cr;
+	double cr;
 
 	printf("Search for a good set of compression parameters (level: %d) ... ", guess_level);
 	if (!strcmp(guess_cmp_mode, "RDCU")) {
+		if (print_rdcu_cfg)
+			cfg->data_type = DATA_TYPE_IMAGETTE_ADAPTIVE;
+		else
+			cfg->data_type = DATA_TYPE_IMAGETTE;
 		if (cfg->model_buf)
 			cfg->cmp_mode = CMP_GUESS_DEF_MODE_MODEL;
 		else
 			cfg->cmp_mode = CMP_GUESS_DEF_MODE_DIFF;
 	} else {
+		cfg->data_type = DATA_TYPE_IMAGETTE; /* TODO*/
 		error = cmp_mode_parse(guess_cmp_mode, &cfg->cmp_mode);
 		if (error) {
 			fprintf(stderr, "%s: Error: unknown compression mode: %s\n", PROGRAM_NAME, guess_cmp_mode);
@@ -540,7 +552,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 
 	if (include_cmp_header)
 		cmp_size_bit = CHAR_BIT * (cmp_bit_to_4byte(cmp_size_bit) +
-			cmp_ent_cal_hdr_size(cmp_ent_map_cmp_mode_data_type(cfg->cmp_mode)));
+			cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW));
 
 	printf("DONE\n");
 
@@ -550,7 +562,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 		return -1;
 	printf("DONE\n");
 
-	cr = (8.0 * cfg->samples * size_of_a_sample(cfg->cmp_mode))/cmp_size_bit;
+	cr = (8.0 * cmp_cal_size_of_data(cfg->samples, cfg->data_type))/cmp_size_bit;
 	printf("Guessed parameters can compress the data with a CR of %.2f.\n", cr);
 
 	return 0;
@@ -594,48 +606,58 @@ static int gen_rdcu_write_pkts(struct cmp_cfg *cfg)
 }
 
 
-/* add a compression entity header in front of the data */
-static int add_cmp_ent_hdr(struct cmp_cfg *cfg, struct cmp_info *info,
-			   uint64_t start_time)
+/**
+ * @brief generate the compression information used based on the compression
+ *	configuration, to emulate the RDCU behaviour
+ *
+ * @param cfg		compression configuration struct
+ * @param cmp_size_bit	length of the bitstream in bits
+ * @param info		compressor information struct to set the used compression
+ *	parameters (can be NULL)
+ *
+ * @note set cmp_size, ap1_cmp_size, ap2_cmp_size will be set to 0
+ *
+ * @returns 0 on success, error otherwise
+ * TODO: set cmp_err in error case
+ */
+
+static int cmp_gernate_rdcu_info(const struct cmp_cfg *cfg, int cmp_size_bit, struct cmp_info *info)
 {
-	int error;
-	uint32_t red_val;
-	uint8_t model_counter = DEFAULT_MODEL_COUNTER;
-	uint16_t model_id = DEFAULT_MODEL_ID;
-	size_t s, cmp_hdr_size;
-	struct cmp_entity *ent;
-	enum cmp_ent_data_type data_type = cmp_ent_map_cmp_mode_data_type(cfg->cmp_mode);
+	if (!cfg)
+		return -1;
 
-	if (model_id_str) {
-		error = atoui32("model_id", model_id_str, &red_val);
-		if (error || red_val > UINT16_MAX)
-			return -1;
-		model_id = red_val;
-	}
-	if (model_counter_str) {
-		error = atoui32("model_counter", model_counter_str, &red_val);
-		if (error || red_val > UINT8_MAX)
-			return -1;
-		model_counter = red_val;
-	} else {
-		if (model_mode_is_used(cfg->cmp_mode))
-			model_counter = DEFAULT_MODEL_COUNTER + 1;
-	}
+	if (cfg->cmp_mode > UINT8_MAX)
+		return -1;
 
-	cmp_hdr_size = cmp_ent_cal_hdr_size(data_type);
-	if (!cmp_hdr_size)
+	if (cfg->round > UINT8_MAX)
 		return -1;
-	memmove((uint8_t *)cfg->icu_output_buf+cmp_hdr_size, cfg->icu_output_buf,
-		cmp_bit_to_4byte(info->cmp_size));
 
-	ent = (struct cmp_entity *)cfg->icu_output_buf;
-	s = cmp_ent_build(ent, data_type, cmp_tool_gen_version_id(VERSION),
-			  start_time, cmp_ent_create_timestamp(NULL), model_id,
-			  model_counter, info, cfg);
-	if (!s) {
-		fprintf(stderr, "%s: error occurred while creating the compression entity header.\n", PROGRAM_NAME);
+	if (cfg->model_value > UINT8_MAX)
 		return -1;
+
+	if (info) {
+		info->cmp_err = 0;
+		info->cmp_mode_used = (uint8_t)cfg->cmp_mode;
+		info->model_value_used = (uint8_t)cfg->model_value;
+		info->round_used = (uint8_t)cfg->round;
+		info->spill_used = cfg->spill;
+		info->golomb_par_used = cfg->golomb_par;
+		info->samples_used = cfg->samples;
+		info->cmp_size = 0;
+		info->ap1_cmp_size = 0;
+		info->ap2_cmp_size = 0;
+		info->rdcu_new_model_adr_used = cfg->rdcu_new_model_adr;
+		info->rdcu_cmp_adr_used = cfg->rdcu_buffer_adr;
+
+		if (cmp_size_bit == CMP_ERROR_SAMLL_BUF)
+			/* the icu_output_buf is to small to store the whole bitstream */
+			info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
+		if (cmp_size_bit < 0)
+			info->cmp_size = 0;
+		else
+			info->cmp_size = (uint32_t)cmp_size_bit;
 	}
+
 	return 0;
 }
 
@@ -643,12 +665,14 @@ static int add_cmp_ent_hdr(struct cmp_cfg *cfg, struct cmp_info *info,
 /* compress the data and write the results to files */
 static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 {
-	int error;
-	uint32_t cmp_size_byte;
-	size_t out_buf_size;
+	int cmp_size, error;
+	uint32_t cmp_size_byte, out_buf_size;
+	size_t s;
 	uint64_t start_time = cmp_ent_create_timestamp(NULL);
-
-	cfg->icu_output_buf = NULL;
+	struct cmp_entity *cmp_entity = NULL;
+	uint8_t model_counter = DEFAULT_MODEL_COUNTER;
+	uint16_t model_id = DEFAULT_MODEL_ID;
+	void *data_to_write_to_file;
 
 	if (cfg->buffer_length == 0) {
 		cfg->buffer_length = (cfg->samples+1) * BUFFER_LENGTH_DEF_FAKTOR; /* +1 to prevent malloc(0)*/
@@ -666,30 +690,65 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 
 	printf("Compress data ... ");
 	/* round up to a multiple of 4 */
-	out_buf_size = (cmp_cal_size_of_data(cfg->buffer_length, cfg->cmp_mode) + 3) & ~0x3U;
+	out_buf_size = (cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type) + 3) & ~0x3U;
 
-	cfg->icu_output_buf = malloc(out_buf_size + sizeof(struct cmp_entity));
-	if (cfg->icu_output_buf == NULL) {
+	cmp_entity = calloc(1, out_buf_size + sizeof(struct cmp_entity));
+	if (cmp_entity == NULL) {
 		fprintf(stderr, "%s: Error allocating memory for output buffer.\n", PROGRAM_NAME);
 		goto error_cleanup;
 	}
+	s = cmp_ent_create(cmp_entity, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, out_buf_size);
+	if (!s) {
+		fprintf(stderr, "%s: error occurred while creating the compression entity header.\n", PROGRAM_NAME);
+		goto error_cleanup;
+	}
+	cfg->icu_output_buf = cmp_ent_get_data_buf(cmp_entity);
 
-	error = icu_compress_data(cfg, info);
-	if (error || info->cmp_err != 0) {
-		printf("\nCompression error 0x%02X\n... ", info->cmp_err);
+	cmp_size = icu_compress_data(cfg);
+	cmp_gernate_rdcu_info(cfg, cmp_size, info);
+	if (cmp_size < 0 || info->cmp_err != 0) {
+		if (info->cmp_err)
+			printf("\nCompression error 0x%02X\n... ", info->cmp_err);
 		/* TODO: add a parse cmp error function */
 		/* if ((info->cmp_err >> SMALL_BUFFER_ERR_BIT) & 1U) */
 		/*	fprintf(stderr, "%s: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n", PROGRAM_NAME); */
 		goto error_cleanup;
 	}
 
+	if (model_id_str) {
+		uint32_t red_val;
+		error = atoui32("model_id", model_id_str, &red_val);
+		if (error || red_val > UINT16_MAX)
+			return -1;
+		model_id = (uint16_t)red_val;
+	}
+	if (model_counter_str) {
+		uint32_t red_val;
+		error = atoui32("model_counter", model_counter_str, &red_val);
+		if (error || red_val > UINT8_MAX)
+			return -1;
+		model_counter = (uint8_t)red_val;
+	} else {
+		if (model_mode_is_used(cfg->cmp_mode))
+			model_counter = DEFAULT_MODEL_COUNTER + 1;
+	}
+
+	s = cmp_ent_build(cmp_entity,  cmp_tool_gen_version_id(CMP_TOOL_VERSION),
+			  start_time, cmp_ent_create_timestamp(NULL), model_id,
+			  model_counter, cfg, cmp_size);
+	if (!s) {
+		fprintf(stderr, "%s: error occurred while creating the compression entity header.\n", PROGRAM_NAME);
+		goto error_cleanup;
+	}
 	if (include_cmp_header) {
-		error = add_cmp_ent_hdr(cfg, info, start_time);
-		if (error)
-			goto error_cleanup;
-		cmp_size_byte = cmp_ent_get_size((struct cmp_entity *)cfg->icu_output_buf);
+		data_to_write_to_file = cmp_entity;
+		cmp_size_byte = cmp_ent_get_size(cmp_entity);
 	} else {
-		cmp_size_byte = cmp_bit_to_4byte(info->cmp_size);
+		data_to_write_to_file = cmp_ent_get_data_buf(cmp_entity);
+		if (cfg->cmp_mode == CMP_MODE_RAW)
+			cmp_size_byte = info->cmp_size/CHAR_BIT;
+		else
+			cmp_size_byte = cmp_bit_to_4byte(info->cmp_size);
 	}
 
 	printf("DONE\n");
@@ -703,7 +762,7 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 	}
 
 	printf("Write compressed data to file %s.cmp ... ", output_prefix);
-	error = write_cmp_data_file(cfg->icu_output_buf, cmp_size_byte,
+	error = write_cmp_data_file(data_to_write_to_file, cmp_size_byte,
 				    output_prefix, ".cmp", verbose_en);
 	if (error)
 		goto error_cleanup;
@@ -724,52 +783,56 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 		printf("\n");
 	}
 
-	free(cfg->icu_output_buf);
+	free(cmp_entity);
 	cfg->icu_output_buf = NULL;
 
 	return 0;
 
 error_cleanup:
-	free(cfg->icu_output_buf);
+	free(cmp_entity);
 	cfg->icu_output_buf = NULL;
+
 	return -1;
 }
 
 
 /* decompress the data and write the results in file(s)*/
-static int decompression(uint32_t *cmp_data_adr, uint16_t *input_model_buf,
-			 struct cmp_info *info)
+static int decompression(struct cmp_entity *ent, uint16_t *input_model_buf)
 {
 	int error;
+	int decomp_size;
 	uint16_t *decomp_output;
 
 	printf("Decompress data ... ");
 
-	if (info->samples_used == 0) {
+	decomp_size = decompress_cmp_entiy(ent, input_model_buf, input_model_buf, NULL);
+	if (decomp_size < 0)
+		return -1;
+	if (decomp_size == 0) {
 		printf("\nWarring: No data are decompressed.\n... ");
 		printf("DONE\n");
 		return 0;
 	}
 
-	decomp_output = malloc(cmp_cal_size_of_data(info->samples_used,
-						    info->cmp_mode_used));
+	decomp_output = malloc((size_t)decomp_size);
 	if (decomp_output == NULL) {
 		fprintf(stderr, "%s: Error allocating memory for decompressed data.\n", PROGRAM_NAME);
 		return -1;
 	}
 
-	error = decompress_data(cmp_data_adr, input_model_buf, info,
-				decomp_output);
-	if (error) {
+	decomp_size = decompress_cmp_entiy(ent, input_model_buf, input_model_buf, decomp_output);
+	if (decomp_size <= 0) {
 		free(decomp_output);
 		return -1;
 	}
+
 	printf("DONE\n");
 
 	printf("Write decompressed data to file %s.dat ... ", output_prefix);
 
-	error = write_to_file16(decomp_output, info->samples_used,
-				output_prefix, ".dat", verbose_en);
+	error = write_input_data_to_file(decomp_output, (uint32_t)decomp_size, cmp_ent_get_data_type(ent),
+					 output_prefix, ".dat", verbose_en);
+
 	free(decomp_output);
 	if (error)
 		return -1;
diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 2ec635e..75b69be 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -14,17 +14,20 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
+ * @see for N-DPU packed definition: PLATO-LESIA-PL-RP-0031 Issue: 1.9 (N-DPU->ICU data rate)
+ * @see for calculation of the max used bits: PLATO-LESIA-PDC-TN-0054 Issue: 1.7
  *
- * Three data rates:
+ * Three data rates (for N-DPU):
  * fast cadence (nominally 25s)
  * short cadence (nominally 50s)
  * long cadence (nominally 600s)
  *
  * The science products are identified as this:
- * FX = normal light flux
- * NCOB = normal center of brightness
- * EFX = extended flux
- * ECOB = extended center of brightness
+ * exp_flags = selected exposure flags
+ * fx = normal light flux
+ * ncob = normal center of brightness
+ * efx = extended flux
+ * ecob = extended center of brightness
  * The prefixes F, S and L stand for Fast, Short and Long cadence
  */
 
@@ -34,173 +37,240 @@
 #include <stdint.h>
 
 #include "compiler.h"
+#include "cmp_support.h"
+
+#define MAX_USED_NC_IMAGETTE_BITS		16
+#define MAX_USED_SATURATED_IMAGETTE_BITS	16 /* TBC */
+#define MAX_USED_FC_IMAGETTE_BITS		16 /* TBC */
+
+#define MAX_USED_F_FX_BITS	21 /* max exp. int value: (1.078*10^5)/0.1 = 1,078,000 -> 21 bits */
+#define MAX_USED_F_EFX_BITS	MAX_USED_F_FX_BITS /* we use the same as f_fx */
+#define MAX_USED_F_NCOB_BITS	20 /* max exp. int value: 6/10^−5 = 6*10^5 -> 20 bits */
+#define MAX_USED_F_ECOB_BITS	32 /* TBC */
+
+#define MAX_USED_S_FX_EXPOSURE_FLAGS_BITS	2 /* 2 flags + 6 spare bits */
+#define MAX_USED_S_FX_BITS			24 /* max exp. int value: (1.078*10^5-34.71)/0.01 = 10,780,000-> 24 bits */
+#define MAX_USED_S_EFX_BITS			MAX_USED_S_FX_BITS /* we use the same as s_fx */
+#define MAX_USED_S_NCOB_BITS			MAX_USED_F_NCOB_BITS
+#define MAX_USED_S_ECOB_BITS			32 /* TBC */
+
+#define MAX_USED_L_FX_EXPOSURE_FLAGS_BITS	24 /* 24 flags */
+#define MAX_USED_L_FX_BITS			MAX_USED_S_FX_BITS
+#define MAX_USED_L_FX_VARIANCE_BITS		32 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_L_EFX_BITS			MAX_USED_L_FX_BITS /* we use the same as l_fx */
+#define MAX_USED_L_NCOB_BITS			MAX_USED_F_NCOB_BITS
+#define MAX_USED_L_ECOB_BITS			32 /* TBC */
+#define MAX_USED_L_COB_VARIANCE_BITS		25 /* max exp int value: 0.1739/10^−8 = 17390000 -> 25 bits */
+
+#define MAX_USED_NC_OFFSET_MEAN_BITS		2 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_NC_OFFSET_VARIANCE_BITS	10 /* max exp. int value: 9.31/0.01 = 931 -> 10 bits */
+
+#define MAX_USED_NC_BACKGROUND_MEAN_BITS		16 /* max exp. int value: (391.8-(-50))/0.01 = 44,180 -> 16 bits */
+#define MAX_USED_NC_BACKGROUND_VARIANCE_BITS		16 /* max exp. int value: 6471/0.1 = 64710 -> 16 bit */
+#define MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS	5 /* maximum = 16 -> 5 bits */
+
+#define MAX_USED_SMEARING_MEAN_BITS		15 /* max exp. int value: (219.9 - -50)/0.01 = 26.990 */
+#define MAX_USED_SMEARING_VARIANCE_MEAN_BITS	16 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_SMEARING_OUTLIER_PIXELS_BITS	11 /* maximum = 1200 -> 11 bits */
+
+#define MAX_USED_FC_OFFSET_MEAN_BITS		32 /* no maximum value is given in PLATO-LESIA-PDC-TN-0054 */
+#define MAX_USED_FC_OFFSET_VARIANCE_BITS	9  /* max exp. int value: 342/1 = 342 -> 9 bits */
+#define MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS	16 /* TBC */
+
+#define MAX_USED_FC_BACKGROUND_MEAN_BITS		10 /* max exp. int value: (35.76-(-50))/0.1 = 858 -> 10 bits*/
+#define MAX_USED_FC_BACKGROUND_VARIANCE_BITS		6 /* max exp. int value: 53.9/1 = 54 -> 6 bits */
+#define MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS	16 /* TBC */
+
+
+/* struct holding the maximum length of the different data products types in bits */
+struct cmp_max_used_bits {
+	unsigned int version;
+	unsigned int s_exp_flags;
+	unsigned int s_fx;
+	unsigned int s_efx;
+	unsigned int s_ncob; /* s_ncob_x and s_ncob_y */
+	unsigned int s_ecob; /* s_ecob_x and s_ncob_y */
+	unsigned int f_fx;
+	unsigned int f_efx;
+	unsigned int f_ncob; /* f_ncob_x and f_ncob_y */
+	unsigned int f_ecob; /* f_ecob_x and f_ncob_y */
+	unsigned int l_exp_flags;
+	unsigned int l_fx;
+	unsigned int l_fx_variance;
+	unsigned int l_efx;
+	unsigned int l_ncob; /* l_ncob_x and l_ncob_y */
+	unsigned int l_ecob; /* l_ecob_x and l_ncob_y */
+	unsigned int l_cob_variance; /* l_cob_x_variance and l_cob_y_variance */
+	unsigned int nc_imagette;
+	unsigned int saturated_imagette;
+	unsigned int nc_offset_mean;
+	unsigned int nc_offset_variance;
+	unsigned int nc_background_mean;
+	unsigned int nc_background_variance;
+	unsigned int nc_background_outlier_pixels;
+	unsigned int smeating_mean;
+	unsigned int smeating_variance_mean;
+	unsigned int smearing_outlier_pixels;
+	unsigned int fc_imagette;
+	unsigned int fc_offset_mean;
+	unsigned int fc_offset_variance;
+	unsigned int fc_offset_pixel_in_error;
+	unsigned int fc_background_mean;
+	unsigned int fc_background_variance;
+	unsigned int fc_background_outlier_pixels;
+};
+
+
+/* Set and read the max_used_bits, which specify how many bits are needed to
+ * represent the highest possible value.
+ */
+void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits);
+struct cmp_max_used_bits cmp_get_max_used_bits(void);
+
+/* for internal use only! */
+extern struct cmp_max_used_bits max_used_bits;
 
-#define MODE_RAW_S_FX           100
-#define MODE_MODEL_ZERO_S_FX	101
-#define MODE_DIFF_ZERO_S_FX	102
-#define MODE_MODEL_MULTI_S_FX	103
-#define MODE_DIFF_MULTI_S_FX	104
-
-#define MODE_MODEL_ZERO_S_FX_EFX	110
-#define MODE_DIFF_ZERO_S_FX_EFX		111
-#define MODE_MODEL_MULTI_S_FX_EFX	112
-#define MODE_DIFF_MULTI_S_FX_EFX	113
-
-#define MODE_MODEL_ZERO_S_FX_NCOB	120
-#define MODE_DIFF_ZERO_S_FX_NCOB	121
-#define MODE_MODEL_MULTI_S_FX_NCOB	122
-#define MODE_DIFF_MULTI_S_FX_NCOB	123
-
-#define MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB	130
-#define MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB	131
-#define MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB	132
-#define MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB	133
-
-#define MODE_MODEL_ZERO_F_FX	140
-#define MODE_DIFF_ZERO_F_FX	141
-#define MODE_MODEL_MULTI_F_FX	142
-#define MODE_DIFF_MULTI_F_FX	143
-
-#define MODE_MODEL_ZERO_F_FX_EFX	150
-#define MODE_DIFF_ZERO_F_FX_EFX		151
-#define MODE_MODEL_MULTI_F_FX_EFX	152
-#define MODE_DIFF_MULTI_F_FX_EFX	153
-
-#define MODE_MODEL_ZERO_F_FX_NCOB	160
-#define MODE_DIFF_ZERO_F_FX_NCOB	161
-#define MODE_MODEL_MULTI_F_FX_NCOB	162
-#define MODE_DIFF_MULTI_F_FX_NCOB	163
-
-#define MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB	170
-#define MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB	171
-#define MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB	172
-#define MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB	173
-
-#define MODE_RAW_32		200
-#define MODE_DIFF_ZERO_32	201
-#define MODE_DIFF_MULTI_32	202
-#define MODE_MODEL_ZERO_32	203
-#define MODE_MODEL_MULTI_32	204
-
-int lossy_rounding_16(uint16_t *data_buf, unsigned int samples, unsigned int
-		      round);
-int de_lossy_rounding_16(uint16_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used);
 
-int lossy_rounding_32(uint32_t *data_buf, unsigned int samples, unsigned int
-		      round);
-int de_lossy_rounding_32(uint32_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used);
+/* Source data header structure for multi entry packet */
+#define MULTI_ENTRY_HDR_SIZE 12
+compile_time_assert(MULTI_ENTRY_HDR_SIZE % sizeof(uint32_t) == 0, N_DPU_ICU_MULTI_ENTRY_HDR_NOT_4_BYTE_ALLIED);
 
-void cmp_input_big_to_cpu_endiannessy(void *data, u_int32_t data_size_byte,
-				      uint32_t cmp_mode);
+struct multi_entry_hdr {
+	uint32_t timestamp_coarse;
+	uint16_t timestamp_fine;
+	uint16_t configuration_id;
+	uint16_t collection_id;
+	uint16_t collection_length;
+	uint8_t  entry[];
+} __attribute__((packed));
+compile_time_assert(sizeof(struct multi_entry_hdr) == MULTI_ENTRY_HDR_SIZE, N_DPU_ICU_MULTI_ENTRY_HDR_SIZE_IS_NOT_CORRECT);
 
-/* @see for packed definition: PLATO-LESIA-PL-RP-0031 Issue: 1.9 (N-DPU->ICU data rate) */
-#define N_DPU_ICU_MULTI_ENTRY_HDR_SIZE 12
 
-struct n_dpu_icu_multi_entry_hdr {
-	uint64_t ncxx_timestamp:48;
-	uint16_t ncxx_configuration_id;
-	uint16_t ncxx_collection_id;
-	uint16_t ncxx_collection_length;
+struct s_fx {
+	uint8_t exp_flags; /* selected exposure flags (2 flags + 6 spare bits) */
+	uint32_t fx;       /* normal light flux */
 } __attribute__((packed));
-compile_time_assert(sizeof(struct n_dpu_icu_multi_entry_hdr) == N_DPU_ICU_MULTI_ENTRY_HDR_SIZE, N_DPU_ICU_MULTI_ENTRY_HDR_SIZE_IS_NOT_CORRECT);
 
 
-struct S_FX {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
+struct s_fx_efx {
+	uint8_t exp_flags;
+	uint32_t fx;
+	uint32_t efx;
 } __attribute__((packed));
 
-struct S_FX sub_S_FX(struct S_FX a, struct S_FX b);
-struct S_FX add_S_FX(struct S_FX a, struct S_FX b);
-int lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples,
-			       unsigned int round);
-int de_lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples_used,
-			   unsigned int round_used);
-struct S_FX cal_up_model_S_FX(struct S_FX data_buf, struct S_FX model_buf,
-			      unsigned int model_value);
+
+struct s_fx_ncob {
+	uint8_t exp_flags;
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+} __attribute__((packed));
 
 
-struct S_FX_EFX {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
-	uint32_t EFX;
+struct s_fx_efx_ncob_ecob {
+	uint8_t exp_flags;
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t efx;
+	uint32_t ecob_x;
+	uint32_t ecob_y;
 } __attribute__((packed));
 
-struct S_FX_EFX sub_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b);
-struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b);
-int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples,
-				   unsigned int round);
-int de_lossy_rounding_S_FX_EFX(struct S_FX_EFX *data_buf, unsigned int
-			       samples_used, unsigned int round_used);
-struct S_FX_EFX cal_up_model_S_FX_EFX(struct S_FX_EFX data_buf, struct S_FX_EFX
-				      model_buf, unsigned int model_value);
 
+struct f_fx {
+	uint32_t fx;
+} __attribute__((packed));
 
-struct S_FX_NCOB {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
+
+struct f_fx_efx {
+	uint32_t fx;
+	uint32_t efx;
 } __attribute__((packed));
 
-struct S_FX_NCOB sub_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b);
-struct S_FX_NCOB add_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b);
-int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
-			     unsigned int round);
-int de_lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int
-				samples_used, unsigned int round_used);
-struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf,
-					struct S_FX_NCOB model_buf,
-					unsigned int model_value);
+
+struct f_fx_ncob {
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+} __attribute__((packed));
 
 
-struct S_FX_EFX_NCOB_ECOB {
-	uint8_t EXPOSURE_FLAGS;
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
-	uint32_t EFX;
-	uint32_t ECOB_X;
-	uint32_t ECOB_Y;
+struct f_fx_efx_ncob_ecob {
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t efx;
+	uint32_t ecob_x;
+	uint32_t ecob_y;
 } __attribute__((packed));
 
-struct S_FX_EFX_NCOB_ECOB sub_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b);
-struct S_FX_EFX_NCOB_ECOB add_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b);
-int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-				      unsigned int samples, unsigned int round);
-int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					 unsigned int samples,
-					 unsigned int round);
 
-struct F_FX {
-	uint32_t FX;
+struct l_fx {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t fx_variance;
 } __attribute__((packed));
 
 
-struct F_FX_EFX {
-	uint32_t FX;
-	uint32_t EFX;
+struct l_fx_efx {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t efx;
+	uint32_t fx_variance;
 } __attribute__((packed));
 
 
-struct F_FX_NCOB {
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
+struct l_fx_ncob {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t fx_variance;
+	uint32_t cob_x_variance;
+	uint32_t cob_y_variance;
 } __attribute__((packed));
 
 
-struct F_FX_EFX_NCOB_ECOB {
-	uint32_t FX;
-	uint32_t NCOB_X;
-	uint32_t NCOB_Y;
-	uint32_t EFX;
-	uint32_t ECOB_X;
-	uint32_t ECOB_Y;
+struct l_fx_efx_ncob_ecob {
+	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
+	uint32_t fx;
+	uint32_t ncob_x;
+	uint32_t ncob_y;
+	uint32_t efx;
+	uint32_t ecob_x;
+	uint32_t ecob_y;
+	uint32_t fx_variance;
+	uint32_t cob_x_variance;
+	uint32_t cob_y_variance;
 } __attribute__((packed));
 
+
+struct nc_offset {
+	uint32_t mean;
+	uint32_t variance;
+} __attribute__((packed));
+
+
+struct nc_background {
+	uint32_t mean;
+	uint32_t variance;
+	uint16_t outlier_pixels;
+} __attribute__((packed));
+
+
+struct smearing {
+	uint32_t mean;
+	uint16_t variance_mean;
+	uint16_t outlier_pixels;
+} __attribute__((packed));
+
+
+size_t size_of_a_sample(enum cmp_data_type data_type);
+unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type);
+int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type);
+
+int cmp_input_big_to_cpu_endianness(void *data, u_int32_t data_size_byte,
+				    enum cmp_data_type data_type);
+
 #endif /* CMP_DATA_TYPE_H */
diff --git a/include/cmp_entity.h b/include/cmp_entity.h
index 2d6bf54..a06715f 100644
--- a/include/cmp_entity.h
+++ b/include/cmp_entity.h
@@ -33,34 +33,6 @@
 #include "cmp_support.h"
 
 
-/* Defined Compression Data Product Types */
-enum cmp_ent_data_type {
-	DATA_TYPE_IMAGETTE = 1,
-	DATA_TYPE_IMAGETTE_ADAPTIVE,
-	DATA_TYPE_SAT_IMAGETTE,
-	DATA_TYPE_SAT_IMAGETTE_ADAPTIVE,
-	DATA_TYPE_OFFSET,
-	DATA_TYPE_BACKGROUND,
-	DATA_TYPE_SMEARING,
-	DATA_TYPE_S_FX,
-	DATA_TYPE_S_FX_DFX,
-	DATA_TYPE_S_FX_NCOB,
-	DATA_TYPE_S_FX_DFX_NCOB_ECOB,
-	DATA_TYPE_L_FX,
-	DATA_TYPE_L_FX_DFX,
-	DATA_TYPE_L_FX_NCOB,
-	DATA_TYPE_L_FX_DFX_NCOB_ECOB,
-	DATA_TYPE_F_FX,
-	DATA_TYPE_F_FX_DFX,
-	DATA_TYPE_F_FX_NCOB,
-	DATA_TYPE_F_FX_DFX_NCOB_ECOB,
-	DATA_TYPE_F_CAM_IMAGETTE,
-	DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE,
-	DATA_TYPE_F_CAM_OFFSET,
-	DATA_TYPE_F_CAM_BACKGROUND,
-	DATA_TYPE_UNKOWN = 0x7FFF,
-};
-
 #define GENERIC_HEADER_SIZE 32
 #define SPECIFIC_IMAGETTE_HEADER_SIZE		4
 #define SPECIFIC_IMAGETTE_ADAPTIVE_HEADER_SIZE	12
@@ -155,21 +127,31 @@ compile_time_assert(sizeof(struct cmp_entity) == NON_IMAGETTE_HEADER_SIZE, CMP_E
 
 
 
-/* brief create a compression entity by setting the size of the
- * compression entity and the data product type in the entity header
+/* create a compression entity by setting the size of the compression entity and
+ * the data product type in the entity header
  */
-size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		      uint32_t cmp_size_byte);
+uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type,
+			int raw_mode_flag, uint32_t cmp_size_byte);
 
 /* create a compression entity and set the header fields */
-size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		     uint32_t version_id, uint64_t start_time,
-		     uint64_t end_time, uint16_t model_id, uint8_t model_counter,
-		     struct cmp_info *info, struct cmp_cfg *cfg);
+size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id,
+		     uint64_t start_time, uint64_t end_time, uint16_t model_id,
+		     uint8_t model_counter, struct cmp_cfg *cfg, int cmp_size_bits);
+
+/* read in a compression entity header */
+int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg);
 
-/* read in a imagette compression entity header to a info struct */
-int cmp_ent_read_imagette_header(struct cmp_entity *ent, struct cmp_info *info);
+/* write the compression parameters from a compression configuration into the
+ * compression entity header
+ */
+int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
+			   int cmp_size_bits);
 
+/* write the parameters from the RDCU decompression information structure in the
+ * compression entity header
+ */
+int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *info,
+				const struct cmp_cfg *cfg);
 
 
 /* set functions for generic compression entity header */
@@ -187,8 +169,7 @@ int cmp_ent_set_coarse_end_time(struct cmp_entity *ent, uint32_t coarse_time);
 int cmp_ent_set_fine_end_time(struct cmp_entity *ent, uint16_t fine_time);
 
 int cmp_ent_set_data_type(struct cmp_entity *ent,
-			  enum cmp_ent_data_type data_type);
-int cmp_ent_data_type_valid(enum cmp_ent_data_type data_type);
+			  enum cmp_data_type data_type, int raw_mode);
 int cmp_ent_set_cmp_mode(struct cmp_entity *ent, uint32_t cmp_mode_used);
 int cmp_ent_set_model_value(struct cmp_entity *ent, uint32_t model_value_used);
 int cmp_ent_set_model_id(struct cmp_entity *ent, uint32_t model_id);
@@ -247,7 +228,7 @@ uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent);
 uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent);
 uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent);
 
-enum cmp_ent_data_type cmp_ent_get_data_type(struct cmp_entity *ent);
+enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent);
 int cmp_ent_get_data_type_raw_bit(struct cmp_entity *ent);
 uint8_t cmp_ent_get_cmp_mode(struct cmp_entity *ent);
 uint8_t cmp_ent_get_model_value_used(struct cmp_entity *ent);
@@ -301,7 +282,7 @@ ssize_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf,
 			     size_t data_buf_size);
 
 /* calculate the size of the compression entity header */
-uint32_t cmp_ent_cal_hdr_size(enum cmp_ent_data_type data_type);
+uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode);
 
 
 #if __has_include(<time.h>)
diff --git a/include/cmp_guess.h b/include/cmp_guess.h
index fe2ed09..9d3ac42 100644
--- a/include/cmp_guess.h
+++ b/include/cmp_guess.h
@@ -22,17 +22,23 @@
 
 #include "cmp_support.h"
 
+
+
 #define DEFAULT_GUESS_LEVEL 2
 
-#define CMP_GUESS_DEF_MODE_DIFF		MODE_DIFF_ZERO
-#define CMP_GUESS_DEF_MODE_MODEL	MODE_MODEL_MULTI
+#define CMP_GUESS_DEF_MODE_DIFF		CMP_MODE_DIFF_ZERO
+#define CMP_GUESS_DEF_MODE_MODEL	CMP_MODE_MODEL_MULTI
 
+/* good guess for the spill parameter using the MODE_DIFF_MULTI */
+#define CMP_GOOD_SPILL_DIFF_MULTI 2U
 /* how often the model is updated before it is reset default value */
 #define CMP_GUESS_N_MODEL_UPDATE_DEF	8
 
 uint32_t cmp_guess(struct cmp_cfg *cfg, int level);
 void cmp_guess_set_model_updates(int n_model_updates);
 
+uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode);
+
 uint16_t cmp_guess_model_value(int n_model_updates);
 
 #endif /* CMP_GUESS_H */
diff --git a/include/cmp_icu.h b/include/cmp_icu.h
index cd7f193..81a1160 100644
--- a/include/cmp_icu.h
+++ b/include/cmp_icu.h
@@ -13,7 +13,6 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- *
  * @brief software compression library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  */
@@ -21,13 +20,45 @@
 #ifndef _CMP_ICU_H_
 #define _CMP_ICU_H_
 
-#include "../include/cmp_support.h"
+#include "cmp_support.h"
+
+
+/* return code if the bitstream buffer is too small to store the whole bitstream */
+#define CMP_ERROR_SAMLL_BUF -2
+
+/* return code if the value or the model is bigger than the max_used_bits
+ * parameter allows
+ */
+#define CMP_ERROR_HIGH_VALUE -3
+
+
+/* create and setup a compression configuration */
+struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
+				  uint32_t model_value, uint32_t lossy_par);
+
+size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
+			   uint32_t data_samples, void *model_of_data,
+			   void *updated_model, uint32_t *compressed_data,
+			   uint32_t compressed_data_len_samples);
+
+int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
+			 uint32_t spillover_par);
+
+int cmp_cfg_fx_cob(struct cmp_cfg *cfg,
+		   uint32_t cmp_par_exp_flags, uint32_t spillover_exp_flags,
+		   uint32_t cmp_par_fx, uint32_t spillover_fx,
+		   uint32_t cmp_par_ncob, uint32_t spillover_ncob,
+		   uint32_t cmp_par_efx, uint32_t spillover_efx,
+		   uint32_t cmp_par_ecob, uint32_t spillover_ecob,
+		   uint32_t cmp_par_fx_cob_variance, uint32_t spillover_fx_cob_variance);
 
-int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info);
+int cmp_cfg_aux(struct cmp_cfg *cfg,
+		uint32_t cmp_par_mean, uint32_t spillover_mean,
+		uint32_t cmp_par_variance, uint32_t spillover_variance,
+		uint32_t cmp_par_pixels_error, uint32_t spillover_pixels_error);
 
 
-int cmp_pre_process(struct cmp_cfg *cfg);
-int cmp_map_to_pos(struct cmp_cfg *cfg);
-uint32_t cmp_encode_data(struct cmp_cfg *cfg);
+/* start the compression */
+int icu_compress_data(const struct cmp_cfg *cfg);
 
 #endif /* _CMP_ICU_H_ */
diff --git a/include/cmp_io.h b/include/cmp_io.h
index 39cfe59..f807825 100644
--- a/include/cmp_io.h
+++ b/include/cmp_io.h
@@ -31,8 +31,10 @@ void print_help(const char *program_name);
 int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en);
 int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en);
 
-ssize_t read_file_data(const char *file_name, unsigned int cmp_mode, void *buf,
-		       uint32_t buf_size, int verbose_en);
+ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t buf_size,
+		   int verbose_en);
+ssize_t read_file_data(const char *file_name, enum cmp_data_type data_type,
+		       void *buf, uint32_t buf_size, int verbose_en);
 ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 			     uint32_t ent_size, int verbose_en);
 ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_size,
@@ -42,8 +44,8 @@ uint32_t cmp_tool_gen_version_id(const char *version);
 
 int write_cmp_data_file(const void *buf, uint32_t buf_size, const char
 			*output_prefix, const char *name_extension, int verbose);
-int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
-		    *output_prefix, const char *name_extension, int verbose);
+int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type data_type,
+			     const char *output_prefix, const char *name_extension, int verbose);
 int write_info(const struct cmp_info *info, const char *output_prefix,
 	       int rdcu_cfg);
 int write_cfg(const struct cmp_cfg *cfg, const char *output_prefix, int rdcu_cfg,
diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h
index ee5cffb..14e0af9 100644
--- a/include/cmp_rdcu.h
+++ b/include/cmp_rdcu.h
@@ -21,10 +21,34 @@
 #ifndef _CMP_RDCU_H_
 #define _CMP_RDCU_H_
 
-#include <stdint.h>
-#include "../include/cmp_support.h"
+#include "cmp_support.h"
 
 
+/* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */
+#define SMALL_BUFFER_ERR_BIT	0x00 /* The length for the compressed data buffer is too small */
+#define CMP_MODE_ERR_BIT	0x01 /* The cmp_mode parameter is not set correctly */
+#define MODEL_VALUE_ERR_BIT	0x02 /* The model_value parameter is not set correctly */
+#define CMP_PAR_ERR_BIT		0x03 /* The spill, golomb_par combination is not set correctly */
+#define AP1_CMP_PAR_ERR_BIT	0x04 /* The ap1_spill, ap1_golomb_par combination is not set correctly (only HW compression) */
+#define AP2_CMP_PAR_ERR_BIT	0x05 /* The ap2_spill, ap2_golomb_par combination is not set correctly (only HW compression) */
+#define MB_ERR_BIT		0x06 /* Multi bit error detected by the memory controller (only HW compression) */
+#define SLAVE_BUSY_ERR_BIT	0x07 /* The bus master has received the "slave busy" status (only HW compression) */
+
+
+struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
+			       uint32_t model_value, uint32_t lossy_par);
+int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress,
+		     uint32_t data_samples, uint16_t *model_of_data,
+		     uint32_t rdcu_data_adr, uint32_t rdcu_model_adr,
+		     uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr,
+		     uint32_t rdcu_buffer_lenght);
+int rdcu_cfg_imagette(struct cmp_cfg *cfg,
+		      uint32_t golomb_par, uint32_t spillover_par,
+		      uint32_t ap1_golomb_par, uint32_t ap1_spillover_par,
+		      uint32_t ap2_golomb_par, uint32_t ap2_spillover_par);
+
+int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg);
+
 int rdcu_compress_data(const struct cmp_cfg *cfg);
 
 int rdcu_read_cmp_status(struct cmp_status *status);
diff --git a/include/cmp_support.h b/include/cmp_support.h
index cfe4bbd..850f0a7 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -23,97 +23,165 @@
 #include <stddef.h>
 
 
-#define GOLOMB_PAR_EXPOSURE_FLAGS 1
-
-/* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */
-#define SMALL_BUFFER_ERR_BIT	0x00 /* The length for the compressed data buffer is too small */
-#define CMP_MODE_ERR_BIT	0x01 /* The cmp_mode parameter is not set correctly */
-#define MODEL_VALUE_ERR_BIT	0x02 /* The model_value parameter is not set correctly */
-#define CMP_PAR_ERR_BIT		0x03 /* The spill, golomb_par combination is not set correctly */
-#define AP1_CMP_PAR_ERR_BIT	0x04 /* The ap1_spill, ap1_golomb_par combination is not set correctly (only HW compression) */
-#define AP2_CMP_PAR_ERR_BIT	0x05 /* The ap2_spill, ap2_golomb_par combination is not set correctly (only HW compression) */
-#define MB_ERR_BIT		0x06 /* Multi bit error detected by the memory controller (only HW compression) */
-#define SLAVE_BUSY_ERR_BIT	0x07 /* The bus master has received the "slave busy" status (only HW compression) */
-
-#define MODE_RAW 0
-#define MODE_MODEL_ZERO 1
-#define MODE_DIFF_ZERO 2
-#define MODE_MODEL_MULTI 3
-#define MODE_DIFF_MULTI 4
+#define CMP_LOSSLESS	0
+#define CMP_PAR_UNUNSED	0
+
 
 #define MAX_MODEL_VALUE                                                        \
-	16UL /* the maximal model values used in the update equation for the new model */
+	16U /* the maximal model values used in the update equation for the new model */
 
 /* valid compression parameter ranges for RDCU compression according to PLATO-UVIE-PL-UM-0001 */
-#define MAX_RDCU_CMP_MODE	4UL
-#define MIN_RDCU_GOLOMB_PAR	1UL
-#define MAX_RDCU_GOLOMB_PAR	63UL
-#define MIN_RDCU_SPILL		2UL
-#define MAX_RDCU_ROUND		2UL
+#define MAX_RDCU_CMP_MODE	4U
+#define MIN_RDCU_GOLOMB_PAR	1U
+#define MAX_RDCU_GOLOMB_PAR	63U
+#define MIN_RDCU_SPILL		2U
+#define MAX_RDCU_ROUND		2U
 /* for maximum spill value look at get_max_spill function */
 
 /* valid compression parameter ranges for ICU compression */
-#define MIN_ICU_GOLOMB_PAR	1UL
-#define MAX_ICU_GOLOMB_PAR	UINT32_MAX
-#define MIN_ICU_SPILL		2UL
+#define MIN_ICU_GOLOMB_PAR	1U
+#define MAX_ICU_GOLOMB_PAR	0x80000000U
+#define MIN_ICU_SPILL		2U
 /* for maximum spill value look at get_max_spill function */
-#define MAX_ICU_ROUND		3UL
+#define MAX_ICU_ROUND		3U
+#define MAX_STUFF_CMP_PAR	32U
+
+
+/* default imagette RDCU compression parameters for model compression */
+#define CMP_DEF_IMA_MODEL_DATA_TYPE		DATA_TYPE_IMAGETTE
+#define CMP_DEF_IMA_MODEL_CMP_MODE		CMP_MODE_MODEL_MULTI
+#define CMP_DEF_IMA_MODEL_MODEL_VALUE		8
+#define CMP_DEF_IMA_MODEL_LOSSY_PAR		0
+
+#define CMP_DEF_IMA_MODEL_GOLOMB_PAR		4
+#define CMP_DEF_IMA_MODEL_SPILL_PAR		48
+#define CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR	3
+#define CMP_DEF_IMA_MODEL_AP1_SPILL_PAR		35
+#define CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR	5
+#define CMP_DEF_IMA_MODEL_AP2_SPILL_PAR		60
+
+#define CMP_DEF_IMA_MODEL_RDCU_DATA_ADR		0x000000
+#define CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR	0x200000
+#define CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR	0x400000
+#define CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR	0x600000
+
+/* default imagette RDCU compression parameters for 1d-differencing compression */
+#define CMP_DEF_IMA_DIFF_DATA_TYPE		DATA_TYPE_IMAGETTE
+#define CMP_DEF_IMA_DIFF_CMP_MODE		CMP_MODE_DIFF_ZERO
+#define CMP_DEF_IMA_DIFF_MODEL_VALUE		8 /* not needed for 1d-differencing cmp_mode */
+#define CMP_DEF_IMA_DIFF_LOSSY_PAR		0
+
+#define CMP_DEF_IMA_DIFF_GOLOMB_PAR		7
+#define CMP_DEF_IMA_DIFF_SPILL_PAR		60
+#define CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR		6
+#define CMP_DEF_IMA_DIFF_AP1_SPILL_PAR		48
+#define CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR		8
+#define CMP_DEF_IMA_DIFF_AP2_SPILL_PAR		72
+
+#define CMP_DEF_IMA_DIFF_RDCU_DATA_ADR		0x000000
+#define CMP_DEF_IMA_DIFF_RDCU_MODEL_ADR		0x000000 /* not needed for 1d-differencing cmp_mode */
+#define CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR	0x000000 /* not needed for 1d-differencing cmp_mode */
+#define CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR	0x600000
+
+
+/* defined compression data product types */
+enum cmp_data_type {
+	DATA_TYPE_UNKOWN,
+	DATA_TYPE_IMAGETTE,
+	DATA_TYPE_IMAGETTE_ADAPTIVE,
+	DATA_TYPE_SAT_IMAGETTE,
+	DATA_TYPE_SAT_IMAGETTE_ADAPTIVE,
+	DATA_TYPE_OFFSET,
+	DATA_TYPE_BACKGROUND,
+	DATA_TYPE_SMEARING,
+	DATA_TYPE_S_FX,
+	DATA_TYPE_S_FX_DFX,
+	DATA_TYPE_S_FX_NCOB,
+	DATA_TYPE_S_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_L_FX,
+	DATA_TYPE_L_FX_DFX,
+	DATA_TYPE_L_FX_NCOB,
+	DATA_TYPE_L_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_F_FX,
+	DATA_TYPE_F_FX_DFX,
+	DATA_TYPE_F_FX_NCOB,
+	DATA_TYPE_F_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_F_CAM_IMAGETTE,
+	DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE,
+	DATA_TYPE_F_CAM_OFFSET,
+	DATA_TYPE_F_CAM_BACKGROUND,
+};
 
-#define SAM2BYT                                                                \
-	2 /* sample to byte conversion factor; one samples has 16 bits (2 bytes) */
 
-#define CMP_GOOD_SPILL_DIFF_MULTI 2 /* good guess for the spill parameter using the MODE_DIFF_MULTI */
+/* defined compression mode */
+enum cmp_mode {
+	CMP_MODE_RAW,
+	CMP_MODE_MODEL_ZERO,
+	CMP_MODE_DIFF_ZERO,
+	CMP_MODE_MODEL_MULTI,
+	CMP_MODE_DIFF_MULTI,
+	CMP_MODE_STUFF
+};
+
 
 /**
  * @brief The cmp_cfg structure can contain the complete configuration of the HW as
  *      well as the SW compressor.
- * @note when using the 1d-differentiating mode or the raw mode (cmp_error =
- *	0,2,4), the model parameters (model_value, model_buf, rdcu_model_adr,
- *	rdcu_new_model_adr) are ignored
  * @note the icu_output_buf will not be used for HW compression
  * @note the rdcu_***_adr parameters are ignored for SW compression
- * @note semi adaptive compression not supported for SW compression;
- *		configuration parameters ap1\_golomb\_par, ap2\_golomb\_par, ap1\_spill,
- *		ap2\_spill will be ignored;
  */
 
 struct cmp_cfg {
+	void *input_buf;            /* Pointer to the data to compress buffer */
+	void *model_buf;            /* Pointer to the model buffer */
+	void *icu_new_model_buf;    /* Pointer to the updated model buffer (not used for RDCU compression )*/
+	uint32_t *icu_output_buf;   /* Pointer to the compressed data buffer (not used for RDCU compression) */
+	uint32_t samples;           /* Number of samples to compress, length of the data and model buffer
+				     * (including the multi entity header by non-imagette data)
+				     */
+	uint32_t buffer_length;     /* Length of the compressed data buffer in number of samples */
+	uint32_t rdcu_data_adr;     /* RDCU data to compress start address, the first data address in the RDCU SRAM; HW only */
+	uint32_t rdcu_model_adr;    /* RDCU model start address, the first model address in the RDCU SRAM */
+	uint32_t rdcu_new_model_adr;/* RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored */
+	uint32_t rdcu_buffer_adr;   /* RDCU compressed data start address, the first output data address in the RDCU SRAM */
+	enum cmp_data_type data_type; /* Compression Data Product Types */
 	uint32_t cmp_mode;          /* 0: raw mode
 				     * 1: model mode with zero escape symbol mechanism
 				     * 2: 1d differencing mode without input model with zero escape symbol mechanism
 				     * 3: model mode with multi escape symbol mechanism
 				     * 4: 1d differencing mode without input model multi escape symbol mechanism
 				     */
-	uint32_t golomb_par;        /* Golomb parameter for dictionary selection */
-	uint32_t spill;             /* Spillover threshold for encoding outliers */
 	uint32_t model_value;       /* Model weighting parameter */
-	uint32_t round;             /* Number of noise bits to be rounded */
-	uint32_t ap1_golomb_par;    /* Adaptive 1 spillover threshold; HW only */
-	uint32_t ap1_spill;         /* Adaptive 1 Golomb parameter; HW only */
-	uint32_t ap2_golomb_par;    /* Adaptive 2 spillover threshold; HW only */
+	uint32_t round;             /* lossy compression parameter */
+	uint32_t golomb_par;        /* Golomb parameter for imagette data compression */
+	uint32_t spill;             /* Spillover threshold parameter for imagette compression */
+	uint32_t ap1_golomb_par;    /* Adaptive 1 spillover threshold for imagette data; HW only */
+	uint32_t ap1_spill;         /* Adaptive 1 Golomb parameter for imagette data; HW only */
+	uint32_t ap2_golomb_par;    /* Adaptive 2 spillover threshold for imagette data; HW only */
 	uint32_t ap2_spill;         /* Adaptive 2 Golomb parameter; HW only */
-	void *input_buf;            /* Pointer to the data to compress buffer */
-	uint32_t rdcu_data_adr;     /* RDCU data to compress start address, the first data address in the RDCU SRAM; HW only */
-	void *model_buf;            /* Pointer to the model buffer */
-	uint32_t rdcu_model_adr;    /* RDCU model start address, the first model address in the RDCU SRAM */
-	void *icu_new_model_buf;    /* Pointer to the updated model buffer */
-	uint32_t rdcu_new_model_adr;/* RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored*/
-	uint32_t samples;           /* Number of samples (16 bit value) to compress, length of the data and model buffer */
-	uint32_t *icu_output_buf;   /* Pointer to the compressed data buffer (not used for RDCU compression) */
-	uint32_t rdcu_buffer_adr;   /* RDCU compressed data start address, the first output data address in the RDCU SRAM */
-	uint32_t buffer_length;     /* Length of the compressed data buffer in number of samples (16 bit values)*/
+	uint32_t cmp_par_exp_flags; /* Compression parameter for exposure flags compression */
+	uint32_t spill_exp_flags;   /* Spillover threshold parameter for exposure flags compression */
+	uint32_t cmp_par_fx;	    /* Compression parameter for normal flux compression */
+	uint32_t spill_fx;          /* Spillover threshold parameter for normal flux compression */
+	uint32_t cmp_par_ncob;      /* Compression parameter for normal center of brightness compression */
+	uint32_t spill_ncob;        /* Spillover threshold parameter for normal center of brightness compression */
+	uint32_t cmp_par_efx;       /* Compression parameter for extended flux compression */
+	uint32_t spill_efx;         /* Spillover threshold parameter for extended flux compression */
+	uint32_t cmp_par_ecob;      /* Compression parameter for executed center of brightness compression */
+	uint32_t spill_ecob;        /* Spillover threshold parameter for executed center of brightness compression */
+	uint32_t cmp_par_fx_cob_variance; /* Compression parameter for flux/COB variance compression */
+	uint32_t spill_fx_cob_variance; /* Spillover threshold parameter for flux/COB variance compression */
+	uint32_t cmp_par_mean;      /* Compression parameter for auxiliary science mean compression */
+	uint32_t spill_mean;        /* Spillover threshold parameter for auxiliary science mean compression */
+	uint32_t cmp_par_variance;  /* Compression parameter for auxiliary science variance compression */
+	uint32_t spill_variance;    /* Spillover threshold parameter for auxiliary science variance compression */
+	uint32_t cmp_par_pixels_error; /* Compression parameter for auxiliary science outlier pixels number compression */
+	uint32_t spill_pixels_error; /* Spillover threshold parameter for auxiliary science outlier pixels number compression */
 };
 
 
-extern const struct cmp_cfg DEFAULT_CFG_MODEL;
-
-extern const struct cmp_cfg DEFAULT_CFG_DIFF;
-
-
-/**
- * @brief The cmp_status structure can contain the information of the
- *      compressor status register from the RDCU, see RDCU-FRS-FN-0632,
- *      but can also be used for the SW compression.
+/* The cmp_status structure can contain the information of the compressor status
+ * register from the RDCU, see RDCU-FRS-FN-0632.
  */
 
 struct cmp_status {
@@ -125,18 +193,12 @@ struct cmp_status {
 };
 
 
-/**
- * @brief The cmp_info structure can contain the information and metadata of an
- *      executed compression of the HW as well as the SW compressor.
- *
- * @note if SW compression is used the parameters rdcu_model_adr_used, rdcu_cmp_adr_used,
- *      ap1_cmp_size, ap2_cmp_size are not used and are therefore set to zero
+/* The cmp_info structure can contain the information and metadata of an
+ * executed RDCU compression.
  */
 
 struct cmp_info {
 	uint32_t cmp_mode_used;       /* Compression mode used */
-	uint8_t  model_value_used;    /* Model weighting parameter used */
-	uint8_t  round_used;          /* Number of noise bits to be rounded used */
 	uint32_t spill_used;          /* Spillover threshold used */
 	uint32_t golomb_par_used;     /* Golomb parameter used */
 	uint32_t samples_used;        /* Number of samples (16 bit value) to be stored */
@@ -145,6 +207,8 @@ struct cmp_info {
 	uint32_t ap2_cmp_size;        /* Adaptive compressed data size 2; measured in bits */
 	uint32_t rdcu_new_model_adr_used; /* Updated model start  address used */
 	uint32_t rdcu_cmp_adr_used;   /* Compressed data start address */
+	uint8_t  model_value_used;    /* Model weighting parameter used */
+	uint8_t  round_used;          /* Number of noise bits to be rounded used */
 	uint16_t cmp_err;             /* Compressor errors
 				       * [bit 0] small_buffer_err; The length for the compressed data buffer is too small
 				       * [bit 1] cmp_mode_err; The cmp_mode parameter is not set correctly
@@ -155,33 +219,43 @@ struct cmp_info {
 				       * [bit 6] mb_err; Multi bit error detected by the memory controller (only HW compression)
 				       * [bit 7] slave_busy_err; The bus master has received the "slave busy" status (only HW compression)
 				       * [bit 8] slave_blocked_err; The bus master has received the “slave blocked” status (only HW compression)
-				       * [bit 9] invalid address_err; The bus master has received the “invalid address” status (only HW compression) */
+				       * [bit 9] invalid address_err; The bus master has received the “invalid address” status (only HW compression)
+				       */
 };
 
+
 int is_a_pow_of_2(unsigned int v);
 int ilog_2(uint32_t x);
 
-int model_mode_is_used(unsigned int cmp_mode);
-int diff_mode_is_used(unsigned int cmp_mode);
-int raw_mode_is_used(unsigned int cmp_mode);
-int rdcu_supported_mode_is_used(unsigned int cmp_mode);
-int cmp_mode_available(unsigned int cmp_mode);
+unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit);
+
+int cmp_cfg_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg);
+int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg);
+uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type);
+
+int cmp_data_type_valid(enum cmp_data_type data_type);
+int rdcu_supported_data_type_is_used(enum cmp_data_type data_type);
+int cmp_imagette_data_type_is_used(enum cmp_data_type data_type);
+int cmp_ap_imagette_data_type_is_used(enum cmp_data_type data_type);
+int cmp_fx_cob_data_type_is_used(enum cmp_data_type data_type);
+int cmp_aux_data_type_is_used(enum cmp_data_type data_type);
 
-int zero_escape_mech_is_used(unsigned int cmp_mode);
-int multi_escape_mech_is_used(unsigned int cmp_mode);
+int cmp_mode_is_supported(enum cmp_mode cmp_mode);
+int model_mode_is_used(enum cmp_mode cmp_mode);
+int diff_mode_is_used(enum cmp_mode cmp_mode);
+int raw_mode_is_used(enum cmp_mode cmp_mode);
+int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode);
+int zero_escape_mech_is_used(enum cmp_mode cmp_mode);
+int multi_escape_mech_is_used(enum cmp_mode cmp_mode);
 
 unsigned int round_fwd(unsigned int value, unsigned int round);
 unsigned int round_inv(unsigned int value, unsigned int round);
-unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
-			  model_value);
-
-uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode);
-uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode);
-
-size_t size_of_a_sample(unsigned int cmp_mode);
-int cmp_input_size_to_samples(unsigned int size, unsigned int cmp_mode);
-unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit);
-unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode);
+unsigned int cmp_up_model(unsigned int data, unsigned int model,
+			  unsigned int model_value, unsigned int round);
 
 
 void print_cmp_cfg(const struct cmp_cfg *cfg);
diff --git a/include/decmp.h b/include/decmp.h
index 139273f..2f8478c 100644
--- a/include/decmp.h
+++ b/include/decmp.h
@@ -19,13 +19,17 @@
 #ifndef DECMP_H_
 #define DECMP_H_
 
-#include "../include/cmp_support.h"
+#include "cmp_entity.h"
+#include "cmp_support.h"
 
 void *malloc_decompressed_data(const struct cmp_info *info);
 
-int decompress_data(const void *compressed_data, void *de_model_buf,
+int decompress_data(uint32_t *compressed_data, void *de_model_buf,
 		    const struct cmp_info *info, void *decompressed_data);
 
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+			 void *up_model_buf, void *decompressed_data);
+
 double get_compression_ratio(const struct cmp_info *info);
 
 #endif /* DECMP_H_ */
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index cf8c08c..749964d 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -17,770 +17,504 @@
  */
 
 
-#include "../include/cmp_data_types.h"
-#include "../include/cmp_support.h"
-#include "../include/cmp_debug.h"
-#include "../include/byteorder.h"
+#include "cmp_data_types.h"
+#include "cmp_debug.h"
+#include "byteorder.h"
+
+
+/* the maximum length of the different data products types in bits */
+struct cmp_max_used_bits max_used_bits = {
+	0, /* default version */
+	MAX_USED_S_FX_EXPOSURE_FLAGS_BITS, /* s_fx_exp_flags */
+	MAX_USED_S_FX_BITS, /* s_fx */
+	MAX_USED_S_EFX_BITS, /* s_efx */
+	MAX_USED_S_NCOB_BITS, /* s_ncob_x and s_ncob_y */
+	MAX_USED_S_ECOB_BITS, /* s_ecob_x and s_ncob_y */
+	MAX_USED_F_FX_BITS, /* f_fx */
+	MAX_USED_F_EFX_BITS, /* f_efx */
+	MAX_USED_F_NCOB_BITS, /* f_ncob_x and f_ncob_y */
+	MAX_USED_F_ECOB_BITS, /* f_ecob_x and f_ncob_y */
+	MAX_USED_L_FX_EXPOSURE_FLAGS_BITS, /* l_fx_exp_flags */
+	MAX_USED_L_FX_BITS, /* l_fx */
+	MAX_USED_L_FX_VARIANCE_BITS, /* l_fx_variance */
+	MAX_USED_L_EFX_BITS, /* l_efx */
+	MAX_USED_L_NCOB_BITS, /* l_ncob_x and l_ncob_y */
+	MAX_USED_L_ECOB_BITS, /* l_ecob_x and l_ncob_y */
+	MAX_USED_L_COB_VARIANCE_BITS, /* l_cob_x_variance and l_cob_y_variance */
+	MAX_USED_NC_IMAGETTE_BITS, /* nc_imagette */
+	MAX_USED_SATURATED_IMAGETTE_BITS, /* saturated_imagette */
+	MAX_USED_NC_OFFSET_MEAN_BITS, /* nc_offset_mean */
+	MAX_USED_NC_OFFSET_VARIANCE_BITS, /* nc_offset_variance */
+	MAX_USED_NC_BACKGROUND_MEAN_BITS, /* nc_background_mean */
+	MAX_USED_NC_BACKGROUND_VARIANCE_BITS, /* nc_background_variance */
+	MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS, /* nc_background_outlier_pixels */
+	MAX_USED_SMEARING_MEAN_BITS, /* smeating_mean */
+	MAX_USED_SMEARING_VARIANCE_MEAN_BITS, /* smeating_variance_mean */
+	MAX_USED_SMEARING_OUTLIER_PIXELS_BITS, /* smearing_outlier_pixels */
+	MAX_USED_FC_IMAGETTE_BITS, /* fc_imagette */
+	MAX_USED_FC_OFFSET_MEAN_BITS, /* fc_offset_mean */
+	MAX_USED_FC_OFFSET_VARIANCE_BITS, /* fc_offset_variance */
+	MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS, /* fc_offset_pixel_in_error */
+	MAX_USED_FC_BACKGROUND_MEAN_BITS, /* fc_background_mean */
+	MAX_USED_FC_BACKGROUND_VARIANCE_BITS, /* fc_background_variance */
+	MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS /* fc_background_outlier_pixels */
+};
 
 
 /**
- * @brief rounding down the least significant digits of a uint16_t data buffer
+ * @brief sets the maximum length of the different data products types
  *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- *
- * @param  data_buf	uint16_t formatted data buffer
- * @param  samples	the size of the data buffer measured in uint16_t samples
- * @param  round	number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
+ * @param set_max_used_bits	pointer to a structure with the maximum length
+ *				of the different data products types in bits
  */
 
-int lossy_rounding_16(uint16_t *data_buf, unsigned int samples, unsigned int
-		      round)
+void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++)
-		data_buf[i] = round_fwd(data_buf[i], round);  /* this is the lossy step */
-
-	return 0;
+	if (set_max_used_bits)
+		max_used_bits = *set_max_used_bits;
 }
 
 
 /**
- * @brief rounding back the least significant digits of the data buffer
- *
- * @param data_buf	pointer to the data to process
- * @param samples_used	the size of the data and model buffer in 16 bit units
- * @param round_used	used number of bits to round; if zero no rounding takes place
+ * @brief get the maximum length of the different data products types
  *
- * @returns 0 on success, error otherwise
+ * @returns a structure with the used maximum length of the different data
+ *	products types in bits
  */
 
-int de_lossy_rounding_16(uint16_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is necessary */
-	if (round_used == 0)
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		/* check if data are not to big for a overflow */
-		uint16_t mask = (uint16_t)(~0U << (16-round_used));
-		if (data_buf[i] & mask) {
-			debug_print("de_lossy_rounding_16 failed!\n");
-			return -1;
-		}
-		data_buf[i] = round_inv(data_buf[i], round_used);
-	}
-	return 0;
-}
-
-
-static void be_to_cpus_16(uint16_t *a, uint32_t samples)
+struct cmp_max_used_bits cmp_get_max_used_bits(void)
 {
-	size_t i;
-
-	for (i = 0; i < samples; ++i)
-		be16_to_cpus(&a[i]);
+	return max_used_bits;
 }
 
 
 /**
- * @brief rounding down the least significant digits of a uint32_t data buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
+ * @brief calculate the size of a sample for the different compression data type
  *
- * @param  data_buf	a uint32_t formatted data buffer
- * @param  samples	the size of the data buffer measured in uint16_t samples
- * @param  round	number of bits to round; if zero no rounding takes place
+ * @param data_type	compression data_type
  *
- * @returns 0 on success, error otherwise
+ * @returns the size of a data sample in bytes for the selected compression
+ *	data type; zero on unknown data type
  */
 
-int lossy_rounding_32(uint32_t *data_buf, unsigned int samples, unsigned int
-		      round)
+size_t size_of_a_sample(enum cmp_data_type data_type)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++)
-		data_buf[i] = round_fwd(data_buf[i], round);  /* this is the lossy step */
-
-	return 0;
-}
-
-
-int de_lossy_rounding_32(uint32_t *data_buf, uint32_t samples_used, uint32_t
-			 round_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is necessary */
-	if (round_used == 0)
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		/* check if data are not to big for a overflow */
-		uint32_t mask = (uint32_t)(~0U << (32-round_used));
-		if (data_buf[i] & mask) {
-			debug_print("de_lossy_rounding_32 failed!\n");
-			return -1;
-		}
-		data_buf[i] = round_inv(data_buf[i], round_used);
+	size_t sample_size = 0;
+
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		sample_size = sizeof(uint16_t);
+		break;
+	case DATA_TYPE_OFFSET:
+		sample_size = sizeof(struct nc_offset);
+		break;
+	case DATA_TYPE_BACKGROUND:
+		sample_size = sizeof(struct nc_background);
+		break;
+	case DATA_TYPE_SMEARING:
+		sample_size = sizeof(struct smearing);
+		break;
+	case DATA_TYPE_S_FX:
+		sample_size = sizeof(struct s_fx);
+		break;
+	case DATA_TYPE_S_FX_DFX:
+		sample_size = sizeof(struct s_fx_efx);
+		break;
+	case DATA_TYPE_S_FX_NCOB:
+		sample_size = sizeof(struct s_fx_ncob);
+		break;
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		sample_size = sizeof(struct s_fx_efx_ncob_ecob);
+		break;
+	case DATA_TYPE_L_FX:
+		sample_size = sizeof(struct l_fx);
+		break;
+	case DATA_TYPE_L_FX_DFX:
+		sample_size = sizeof(struct l_fx_efx);
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		sample_size = sizeof(struct l_fx_ncob);
+		break;
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		sample_size = sizeof(struct l_fx_efx_ncob_ecob);
+		break;
+	case DATA_TYPE_F_FX:
+		sample_size = sizeof(struct f_fx);
+		break;
+	case DATA_TYPE_F_FX_DFX:
+		sample_size = sizeof(struct f_fx_efx);
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		sample_size = sizeof(struct f_fx_ncob);
+		break;
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		sample_size = sizeof(struct f_fx_efx_ncob_ecob);
+		break;
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
+	case DATA_TYPE_UNKOWN:
+	default:
+		debug_print("Error: Compression data type is not supported.\n");
+		break;
 	}
-	return 0;
-}
-
-
-struct S_FX sub_S_FX(struct S_FX a, struct S_FX b)
-{
-	struct S_FX result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-
-	return result;
-}
-
-
-struct S_FX add_S_FX(struct S_FX a, struct S_FX b)
-{
-	struct S_FX result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-
-	return result;
+	return sample_size;
 }
 
 
 /**
- * @brief rounding down the least significant digits of a S_FX data buffer
+ * @brief calculate the need bytes for the data
  *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
+ * @param samples	number of data samples
+ * @param data_type	compression data_type
  *
- * @param  data_buf	a S_FX formatted data buffer
- * @param  samples	the size of the data buffer measured in S_FX samples
- * @param  round	number of bits to round; if zero no rounding takes place
+ * @note for non-imagette data program types the multi entry header size is added
  *
- * @returns 0 on success, error otherwise
+ * @returns the size in bytes to store the data sample
  */
 
-int lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples, unsigned
-			int round)
+unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type)
 {
-	size_t i;
+	unsigned int s = size_of_a_sample(data_type);
 
-	if (!samples)
+	if (!s)
 		return 0;
 
-	if (!data_buf)
-		return -1;
+	s *= samples;
 
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++)
-		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
+	if (!rdcu_supported_data_type_is_used(data_type))
+		s += MULTI_ENTRY_HDR_SIZE;
 
-	return 0;
+	return s;
 }
 
 
-int de_lossy_rounding_S_FX(struct S_FX *data_buf, unsigned int samples_used,
-			   unsigned int round_used)
-{
-	size_t i;
+/**
+ * @brief calculates the number of samples for a given data size for the
+ *	different compression modes
+ *
+ * @param size		size of the data in bytes
+ * @param data_type	compression data type
+ *
+ * @returns the number samples for the given compression mode; negative on error
+ */
 
-	if (!samples_used)
-		return 0;
+int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type)
+{
+	int samples_size = (int)size_of_a_sample(data_type);
 
-	if (!data_buf)
+	if (!samples_size)
 		return -1;
 
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("Errolr: de_lossy_rounding_S_FX failed\n");
+	if (!rdcu_supported_data_type_is_used(data_type)) {
+		if (size < MULTI_ENTRY_HDR_SIZE)
 			return -1;
-		}
-
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
+		size -= MULTI_ENTRY_HDR_SIZE;
 	}
-	return 0;
-}
-
-
-struct S_FX cal_up_model_S_FX(struct S_FX data_buf, struct S_FX model_buf,
-			      unsigned int model_value)
-{
-	struct S_FX result;
 
-	result.EXPOSURE_FLAGS = (uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-						      model_buf.EXPOSURE_FLAGS,
-						      model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
+	if (size % samples_size)
+		return -1;
 
-	return result;
+	return size/samples_size;
 }
 
 
-void be_to_cpus_S_FX(struct S_FX *a, uint32_t samples)
+static uint32_t be24_to_cpu(uint32_t a)
 {
-	size_t i;
-
-	for (i = 0; i < samples; ++i)
-		a[i].FX = be32_to_cpu(a[i].FX);
+	return be32_to_cpu(a) >> 8;
 }
 
 
-struct S_FX_EFX sub_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
+static void be_to_cpus_16(uint16_t *a, int samples)
 {
-	struct S_FX_EFX result;
+	int i;
 
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-	result.EFX = a.EFX - b.EFX;
-
-	return result;
+	for (i = 0; i < samples; ++i)
+		be16_to_cpus(&a[i]);
 }
 
 
-struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
+static void be_to_cpus_nc_offset(struct nc_offset *a, int samples)
 {
-	struct S_FX_EFX result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-	result.EFX = a.EFX + b.EFX;
+	int i;
 
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].mean = be32_to_cpu(a[i].mean);
+		a[i].variance = be32_to_cpu(a[i].variance);
+	}
 }
 
 
-/**
- * @brief rounding down the least significant digits of a S_FX_EFX data buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
- *
- * @param  data		S_FX_EFX formatted data buffer
- * @param  samples	the size of the data buffer measured in S_FX_EFX samples
- * @param  round	number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples,
-			    unsigned int round)
+static void be_to_cpus_nc_background(struct nc_background *a, int samples)
 {
-	size_t i;
+	int i;
 
-	if (!samples)
-		return 0;
-
-	if (!data)
-		return -1;
-
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++) {
-		data[i].FX = round_fwd(data[i].FX, round);
-		data[i].EFX = round_fwd(data[i].EFX, round);
+	for (i = 0; i < samples; ++i) {
+		a[i].mean = be32_to_cpu(a[i].mean);
+		a[i].variance = be32_to_cpu(a[i].variance);
+		a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels);
 	}
-	return 0;
 }
 
 
-int de_lossy_rounding_S_FX_EFX(struct S_FX_EFX *data_buf, unsigned int
-			       samples_used, unsigned int round_used)
+static void be_to_cpus_smearing(struct smearing *a, int samples)
 {
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("de_lossy_rounding_S_FX failed!\n");
-			return -1;
-		}
-		if (data_buf[i].EFX & mask) {
-			debug_print("de_lossy_rounding_S_FX failed!\n");
-			return -1;
-		}
+	int i;
 
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
-		data_buf[i].EFX = round_inv(data_buf[i].EFX, round_used);
+	for (i = 0; i < samples; ++i) {
+		a[i].mean = be32_to_cpu(a[i].mean);
+		a[i].variance_mean = be16_to_cpu(a[i].variance_mean);
+		a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels);
 	}
-	return 0;
 }
 
 
-struct S_FX_EFX cal_up_model_S_FX_EFX(struct S_FX_EFX data_buf, struct S_FX_EFX
-				      model_buf, unsigned int model_value)
+static void be_to_cpus_s_fx(struct s_fx *a, int samples)
 {
-	struct S_FX_EFX result;
+	int i;
 
-	result.EXPOSURE_FLAGS =
-		(uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-				      model_buf.EXPOSURE_FLAGS, model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
-	result.EFX = cal_up_model(data_buf.EFX, model_buf.FX, model_value);
-
-	return result;
+	for (i = 0; i < samples; ++i)
+		a[i].fx = be32_to_cpu(a[i].fx);
 }
 
 
-void be_to_cpus_S_FX_EFX(struct S_FX_EFX *a, uint32_t samples)
+static void be_to_cpus_s_fx_efx(struct s_fx_efx *a, int samples)
 {
-	size_t i;
+	int i;
 
 	for (i = 0; i < samples; ++i) {
-		a[i].FX = be32_to_cpu(a[i].FX);
-		a[i].EFX = be32_to_cpu(a[i].EFX);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].efx = be32_to_cpu(a[i].efx);
 	}
 }
 
 
-struct S_FX_NCOB sub_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b)
+static void be_to_cpus_s_fx_ncob(struct s_fx_ncob *a, int samples)
 {
-	struct S_FX_NCOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-	result.NCOB_X = a.NCOB_X - b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y - b.NCOB_Y;
-
-	return result;
-}
-
+	int i;
 
-struct S_FX_NCOB add_S_FX_NCOB(struct S_FX_NCOB a, struct S_FX_NCOB b)
-{
-	struct S_FX_NCOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-	result.NCOB_X = a.NCOB_X + b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y + b.NCOB_Y;
-
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+	}
 }
 
 
-/**
- * @brief rounding down the least significant digits of a S_FX_NCOB data buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
- *
- * @param  data_buf	a S_FX_NCOB formatted data buffer
- * @param  samples	the size of the data buffer measured in S_FX_NCOB samples
- * @param  round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
-			     unsigned int round)
+static void be_to_cpus_s_fx_efx_ncob_ecob(struct s_fx_efx_ncob_ecob *a, int samples)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
+	int i;
 
-	/* round 0 means loss less compression, no further processing is
-	 * necessary */
-	if (round == 0)
-		return 0;
-
-	for (i = 0; i < samples; i++) {
-		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
-		data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
-		data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].ecob_x = be32_to_cpu(a[i].ecob_x);
+		a[i].ecob_y = be32_to_cpu(a[i].ecob_y);
 	}
-	return 0;
 }
 
 
-int de_lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int
-				samples_used, unsigned int round_used)
+static void be_to_cpus_l_fx(struct l_fx *a, int samples)
 {
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
-
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("de_lossy_rounding_S_FX_NCOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_X & mask) {
-			debug_print("de_lossy_rounding_S_FX_NCOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_Y & mask) {
-			debug_print("de_lossy_rounding_S_FX_NCOB failed!\n");
-			return -1;
-		}
+	int i;
 
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
-		data_buf[i].NCOB_X = round_inv(data_buf[i].NCOB_X, round_used);
-		data_buf[i].NCOB_Y = round_inv(data_buf[i].NCOB_Y, round_used);
+	for (i = 0; i < samples; ++i) {
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
 	}
-	return 0;
 }
 
 
-struct S_FX_NCOB cal_up_model_S_FX_NCOB(struct S_FX_NCOB data_buf, struct S_FX_NCOB
-					model_buf, unsigned int model_value)
+static void be_to_cpus_l_fx_efx(struct l_fx_efx *a, int samples)
 {
-	struct S_FX_NCOB result;
+	int i;
 
-	result.EXPOSURE_FLAGS =
-		(uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-				      model_buf.EXPOSURE_FLAGS, model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
-	result.NCOB_X = cal_up_model(data_buf.NCOB_X, model_buf.NCOB_X, model_value);
-	result.NCOB_Y = cal_up_model(data_buf.NCOB_Y, model_buf.NCOB_Y, model_value);
-
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
+	}
 }
 
 
-void be_to_cpus_S_FX_NCOB(struct S_FX_NCOB *a, uint32_t samples)
+static void be_to_cpus_l_fx_ncob(struct l_fx_ncob *a, int samples)
 {
-	size_t i;
+	int i;
 
 	for (i = 0; i < samples; ++i) {
-		a[i].FX = be32_to_cpu(a[i].FX);
-		a[i].NCOB_X = be32_to_cpu(a[i].NCOB_X);
-		a[i].NCOB_Y = be32_to_cpu(a[i].NCOB_Y);
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
+		a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance);
+		a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance);
 	}
 }
 
 
-struct S_FX_EFX_NCOB_ECOB sub_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b)
+static void be_to_cpus_l_fx_efx_ncob_ecob(struct l_fx_efx_ncob_ecob *a, int samples)
 {
-	struct S_FX_EFX_NCOB_ECOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS - b.EXPOSURE_FLAGS;
-	result.FX = a.FX - b.FX;
-	result.NCOB_X = a.NCOB_X - b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y - b.NCOB_Y;
-	result.EFX = a.EFX - b.EFX;
-	result.ECOB_X = a.ECOB_X - b.ECOB_X;
-	result.ECOB_Y = a.ECOB_Y - b.ECOB_Y;
+	int i;
 
-	return result;
+	for (i = 0; i < samples; ++i) {
+		a[i].exp_flags = be24_to_cpu(a[i].exp_flags);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].ecob_x = be32_to_cpu(a[i].ecob_x);
+		a[i].ecob_y = be32_to_cpu(a[i].ecob_y);
+		a[i].fx_variance = be32_to_cpu(a[i].fx_variance);
+		a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance);
+		a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance);
+	}
 }
 
 
-struct S_FX_EFX_NCOB_ECOB add_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB a,
-						 struct S_FX_EFX_NCOB_ECOB b)
+static void be_to_cpus_f_fx(struct f_fx *a, int samples)
 {
-	struct S_FX_EFX_NCOB_ECOB result;
-
-	result.EXPOSURE_FLAGS = a.EXPOSURE_FLAGS + b.EXPOSURE_FLAGS;
-	result.FX = a.FX + b.FX;
-	result.NCOB_X = a.NCOB_X + b.NCOB_X;
-	result.NCOB_Y = a.NCOB_Y + b.NCOB_Y;
-	result.EFX = a.EFX + b.EFX;
-	result.ECOB_X = a.ECOB_X + b.ECOB_X;
-	result.ECOB_Y = a.ECOB_Y + b.ECOB_Y;
+	int i;
 
-	return result;
+	for (i = 0; i < samples; ++i)
+		a[i].fx = be32_to_cpu(a[i].fx);
 }
 
 
-/**
- * @brief rounding down the least significant digits of a S_FX_EFX_NCOB_ECOB data
- *	buffer
- *
- * @note this step involves data loss (if round > 0)
- * @note change the data buffer in-place
- * @note the exposure_flags are not rounded
- *
- * @param  data_buf	a S_FX_EFX_NCOB_ECOB formatted data buffer
- * @param  samples	the size of the data buffer measured in
- *	S_FX_EFX_NCOB_ECOB samples
- * @param  round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-				      unsigned int samples, unsigned int round)
+static void be_to_cpus_f_fx_efx(struct f_fx_efx *a, int samples)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
+	int i;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].FX = round_fwd(data_buf[i].FX, round);
-		data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
-		data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
-		data_buf[i].EFX = round_fwd(data_buf[i].EFX, round);
-		data_buf[i].ECOB_X = round_fwd(data_buf[i].ECOB_X, round);
-		data_buf[i].ECOB_Y = round_fwd(data_buf[i].ECOB_Y, round);
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].efx = be32_to_cpu(a[i].efx);
 	}
-	return 0;
 }
 
 
-int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					 unsigned int samples_used,
-					 unsigned int round_used)
+static void be_to_cpus_f_fx_ncob(struct f_fx_ncob *a, int samples)
 {
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
-		return 0;
+	int i;
 
-	for (i = 0; i < samples_used; i++) {
-		uint32_t mask = (~0U << (32-round_used));
-
-		if (data_buf[i].FX & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_X & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].NCOB_Y & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].EFX & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].ECOB_X & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-		if (data_buf[i].ECOB_Y & mask) {
-			debug_print("de_lossy_rounding_S_FX_EFX_NCOB_ECOB failed!\n");
-			return -1;
-		}
-
-		data_buf[i].FX = round_inv(data_buf[i].FX, round_used);
-		data_buf[i].NCOB_X = round_inv(data_buf[i].NCOB_X, round_used);
-		data_buf[i].NCOB_Y = round_inv(data_buf[i].NCOB_Y, round_used);
-		data_buf[i].EFX = round_inv(data_buf[i].EFX, round_used);
-		data_buf[i].ECOB_X = round_inv(data_buf[i].ECOB_X, round_used);
-		data_buf[i].ECOB_Y = round_inv(data_buf[i].ECOB_Y, round_used);
+	for (i = 0; i < samples; ++i) {
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
 	}
-	return 0;
-}
-
-
-struct S_FX_EFX_NCOB_ECOB cal_up_model_S_FX_EFX_NCOB_ECOB
-	(struct S_FX_EFX_NCOB_ECOB data_buf, struct S_FX_EFX_NCOB_ECOB
-	 model_buf, unsigned int model_value)
-{
-	struct S_FX_EFX_NCOB_ECOB result;
-
-	result.EXPOSURE_FLAGS =
-		(uint8_t)cal_up_model(data_buf.EXPOSURE_FLAGS,
-				      model_buf.EXPOSURE_FLAGS, model_value);
-	result.FX = cal_up_model(data_buf.FX, model_buf.FX, model_value);
-	result.NCOB_X = cal_up_model(data_buf.NCOB_X, model_buf.NCOB_X, model_value);
-	result.NCOB_Y = cal_up_model(data_buf.NCOB_Y, model_buf.NCOB_Y, model_value);
-	result.EFX = cal_up_model(data_buf.EFX, model_buf.EFX, model_value);
-	result.ECOB_X = cal_up_model(data_buf.ECOB_X, model_buf.ECOB_X, model_value);
-	result.ECOB_Y = cal_up_model(data_buf.ECOB_Y, model_buf.ECOB_Y, model_value);
-
-	return result;
 }
 
 
-void be_to_cpus_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *a, uint32_t samples)
+static void be_to_cpus_f_fx_efx_ncob_ecob(struct f_fx_efx_ncob_ecob *a, int samples)
 {
-	size_t i;
+	int i;
 
 	for (i = 0; i < samples; ++i) {
-		a[i].FX = be32_to_cpu(a[i].FX);
-		a[i].NCOB_X = be32_to_cpu(a[i].NCOB_X);
-		a[i].NCOB_Y = be32_to_cpu(a[i].NCOB_Y);
-		a[i].EFX = be32_to_cpu(a[i].EFX);
-		a[i].ECOB_X = be32_to_cpu(a[i].ECOB_X);
-		a[i].ECOB_Y = be32_to_cpu(a[i].ECOB_Y);
+		a[i].fx = be32_to_cpu(a[i].fx);
+		a[i].ncob_x = be32_to_cpu(a[i].ncob_x);
+		a[i].ncob_y = be32_to_cpu(a[i].ncob_y);
+		a[i].efx = be32_to_cpu(a[i].efx);
+		a[i].ecob_x = be32_to_cpu(a[i].ecob_x);
+		a[i].ecob_y = be32_to_cpu(a[i].ecob_y);
 	}
 }
 
 
 /**
- * @brief swap the endianness of science products form big endian to the cpu
- *	endianness in place
+ * @brief swap the endianness of uncompressed data form big endian to the cpu
+ *	endianness (or the other way around) in place
  *
- * @param  data		pointer to a data sample
- * @param  cmp_mode	compression mode
+ * @param data			pointer to a data sample
+ * @param data_size_byte	size of the data in bytes
+ * @param data_type		compression data type
+ *
+ * @returns 0 on success; non-zero on failure
  */
 
-void cmp_input_big_to_cpu_endiannessy(void *data, u_int32_t data_size_byte,
-				      uint32_t cmp_mode)
+int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
+				    enum cmp_data_type data_type)
 {
-	int samples = cmp_input_size_to_samples(data_size_byte, cmp_mode);
+	int samples = cmp_input_size_to_samples(data_size_byte, data_type);
 
-	if (!data)
-		return;
+	if (!data) /* nothing to do */
+		return 0;
 
 	if (samples < 0) {
 		debug_print("Error: Can not convert data size in samples.\n");
-		return;
+		return -1;
 	}
 
-	if (!rdcu_supported_mode_is_used(cmp_mode))
-		data = (uint8_t *)data + N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
-
-	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
+	/* we do not convert the endianness of the multi entry header */
+	if (!rdcu_supported_data_type_is_used(data_type))
+		data = (uint8_t *)data + MULTI_ENTRY_HDR_SIZE;
+
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		be_to_cpus_16(data, samples);
 		break;
-	case MODE_RAW_S_FX:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		be_to_cpus_S_FX(data, samples);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		be_to_cpus_S_FX_EFX(data, samples);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		be_to_cpus_S_FX_EFX_NCOB_ECOB(data, samples);
-		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		/* be_to_cpus_F_FX(data, samples); */
-		/* break; */
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-		/* be_to_cpus_F_FX_EFX(data, samples); */
-		/* break; */
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-		/* be_to_cpus_F_FX_NCOB(data, samples); */
-		/* break; */
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-		/* be_to_cpus_F_FX_EFX_NCOB_ECOB(data, samples); */
-		/* break; */
-	case MODE_RAW_32:
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-		/* be32_to_cpus(data); */
-		/* break; */
-	default:
-		debug_print("Error: Compression mode not supported.\n");
+	case DATA_TYPE_OFFSET:
+		be_to_cpus_nc_offset(data, samples);
+		break;
+	case DATA_TYPE_BACKGROUND:
+		be_to_cpus_nc_background(data, samples);
+		break;
+	case DATA_TYPE_SMEARING:
+		be_to_cpus_smearing(data, samples);
+		break;
+	case DATA_TYPE_S_FX:
+		be_to_cpus_s_fx(data, samples);
+		break;
+	case DATA_TYPE_S_FX_DFX:
+		be_to_cpus_s_fx_efx(data, samples);
 		break;
+	case DATA_TYPE_S_FX_NCOB:
+		be_to_cpus_s_fx_ncob(data, samples);
+		break;
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		be_to_cpus_s_fx_efx_ncob_ecob(data, samples);
+		break;
+	case DATA_TYPE_L_FX:
+		be_to_cpus_l_fx(data, samples);
+		break;
+	case DATA_TYPE_L_FX_DFX:
+		be_to_cpus_l_fx_efx(data, samples);
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		be_to_cpus_l_fx_ncob(data, samples);
+		break;
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		be_to_cpus_l_fx_efx_ncob_ecob(data, samples);
+		break;
+	case DATA_TYPE_F_FX:
+		be_to_cpus_f_fx(data, samples);
+		break;
+	case DATA_TYPE_F_FX_DFX:
+		be_to_cpus_f_fx_efx(data, samples);
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		be_to_cpus_f_fx_ncob(data, samples);
+		break;
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		be_to_cpus_f_fx_efx_ncob_ecob(data, samples);
+		break;
+	/* TODO: implement F_CAM conversion */
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
+	case DATA_TYPE_UNKOWN:
+	default:
+		debug_print("Error: Can not swap endianness for this compression data type.\n");
+		return -1;
 	}
+
+	return 0;
 }
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index 99aa3bd..d058b17 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -17,24 +17,30 @@
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  */
 
+
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
 #include <limits.h>
-#if __has_include(<time.h>)
-	#include <time.h>
-	#include <stdlib.h>
+#if defined __has_include
+#  if __has_include(<time.h>)
+#    include <time.h>
+#    include <stdlib.h>
+#    define HAS_TIME_H 1
+#  endif
 #endif
 
-#include "../include/cmp_entity.h"
-#include "../include/cmp_support.h"
-#include "../include/byteorder.h"
+#include "byteorder.h"
+#include "cmp_debug.h"
+#include "cmp_support.h"
+#include "cmp_data_types.h"
+#include "cmp_entity.h"
 
 
-#if __has_include(<time.h>)
+#ifdef HAS_TIME_H
 /* Used as epoch Wed Jan  1 00:00:00 2020 */
 #  if defined(_WIN32) || defined(_WIN64)
-const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0, };
+const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0 };
 #  else
 const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0, 0, NULL };
 #  endif /* _WIN */
@@ -42,69 +48,61 @@ const struct tm EPOCH_DATE = { 0, 0, 0, 1, 0, 120, 0, 0, 0, 0, NULL };
 
 
 /**
- * @brief calculate the size of the compression entity header based of the data
+ * @brief calculate the size of the compression entity header based on the data
  *	product type
  *
  * @param data_type	compression entity data product type
+ * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
  *
  * @returns size of the compression entity header in bytes, 0 on unknown data
  *	type
  */
 
-uint32_t cmp_ent_cal_hdr_size(enum cmp_ent_data_type data_type)
-{
-	switch (data_type) {
-	case DATA_TYPE_IMAGETTE:
-	case DATA_TYPE_F_CAM_IMAGETTE:
-		return IMAGETTE_HEADER_SIZE;
-	case DATA_TYPE_IMAGETTE_ADAPTIVE:
-	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
-		return IMAGETTE_ADAPTIVE_HEADER_SIZE;
-	case DATA_TYPE_SAT_IMAGETTE:
-	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
-	case DATA_TYPE_OFFSET:
-	case DATA_TYPE_BACKGROUND:
-	case DATA_TYPE_SMEARING:
-	case DATA_TYPE_S_FX:
-	case DATA_TYPE_S_FX_DFX:
-	case DATA_TYPE_S_FX_NCOB:
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
-	case DATA_TYPE_L_FX:
-	case DATA_TYPE_L_FX_DFX:
-	case DATA_TYPE_L_FX_NCOB:
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
-	case DATA_TYPE_F_FX:
-	case DATA_TYPE_F_FX_DFX:
-	case DATA_TYPE_F_FX_NCOB:
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
-	case DATA_TYPE_F_CAM_OFFSET:
-	case DATA_TYPE_F_CAM_BACKGROUND:
-		return NON_IMAGETTE_HEADER_SIZE;
-	case DATA_TYPE_UNKOWN:
-		return 0;
+uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode_flag)
+{
+	uint32_t size = 0;
+
+	if (raw_mode_flag) {
+		if (cmp_data_type_valid(data_type))
+			/* for raw data we do not need a specific header */
+			size = GENERIC_HEADER_SIZE;
+	} else {
+		switch (data_type) {
+		case DATA_TYPE_IMAGETTE:
+		case DATA_TYPE_SAT_IMAGETTE:
+		case DATA_TYPE_F_CAM_IMAGETTE:
+			size = IMAGETTE_HEADER_SIZE;
+			break;
+		case DATA_TYPE_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+			size = IMAGETTE_ADAPTIVE_HEADER_SIZE;
+			break;
+		case DATA_TYPE_OFFSET:
+		case DATA_TYPE_BACKGROUND:
+		case DATA_TYPE_SMEARING:
+		case DATA_TYPE_S_FX:
+		case DATA_TYPE_S_FX_DFX:
+		case DATA_TYPE_S_FX_NCOB:
+		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_L_FX:
+		case DATA_TYPE_L_FX_DFX:
+		case DATA_TYPE_L_FX_NCOB:
+		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_FX:
+		case DATA_TYPE_F_FX_DFX:
+		case DATA_TYPE_F_FX_NCOB:
+		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_CAM_OFFSET:
+		case DATA_TYPE_F_CAM_BACKGROUND:
+			size = NON_IMAGETTE_HEADER_SIZE;
+			break;
+		case DATA_TYPE_UNKOWN:
+			size = 0;
+			break;
+		}
 	}
-
-	if ((data_type >> RAW_BIT_DATA_TYPE_POS) & 1U)
-		return GENERIC_HEADER_SIZE;
-
-	return 0;
-}
-
-
-/**
- * @brief check if the compression entity data product type is supported
- *
- * @param data_type	compression entity data product type to check
- *
- * @returns zero if data_type is invalid; non-zero if data_type is valid
- */
-
-int cmp_ent_data_type_valid(enum cmp_ent_data_type data_type)
-{
-	if (cmp_ent_cal_hdr_size(data_type))
-		return 1;
-	else
-		return 0;
+	return size;
 }
 
 
@@ -326,19 +324,23 @@ int cmp_ent_set_fine_end_time(struct cmp_entity *ent, uint16_t fine_time)
 /**
  * @brief set the data product type in the compression entity header
  *
- * @param ent		pointer to a compression entity (including the
- *	uncompressed data bit)
+ * @param ent		pointer to a compression entity
  * @param data_type	compression entity data product type
+ * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
  *
  * @returns 0 on success, otherwise error
  */
 
 int cmp_ent_set_data_type(struct cmp_entity *ent,
-			  enum cmp_ent_data_type data_type)
+			  enum cmp_data_type data_type,
+			  int raw_mode_flag)
 {
 	if (!ent)
 		return -1;
 
+	if (raw_mode_flag)
+		data_type |= 1U << RAW_BIT_DATA_TYPE_POS;
+
 	if (data_type > UINT16_MAX)
 		return -1;
 
@@ -932,7 +934,7 @@ int cmp_ent_set_non_ima_cmp_par6(struct cmp_entity *ent, uint32_t cmp_par_6_used
 
 
 /**
- * @brief get the ASW version identifier form the compression entity header
+ * @brief get the ASW version identifier from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -949,7 +951,7 @@ uint32_t cmp_ent_get_version_id(struct cmp_entity *ent)
 
 
 /**
- * @brief get the size of the compression entity form the compression entity header
+ * @brief get the size of the compression entity from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -970,7 +972,7 @@ uint32_t cmp_ent_get_size(struct cmp_entity *ent)
 
 
 /**
- * @brief get the original data size form the compression entity header
+ * @brief get the original data size from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -991,7 +993,7 @@ uint32_t cmp_ent_get_original_size(struct cmp_entity *ent)
 
 
 /**
- * @brief get the compression start timestamp form the compression entity header
+ * @brief get the compression start timestamp from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1012,7 +1014,7 @@ uint64_t cmp_ent_get_start_timestamp(struct cmp_entity *ent)
 
 
 /**
- * @brief get the coarse time form the compression start timestamp in the
+ * @brief get the coarse time from the compression start timestamp in the
  *	compression entity header
  *
  * @returns the coarse part of the compression start timestamp on success, 0 on
@@ -1029,7 +1031,7 @@ uint32_t cmp_ent_get_coarse_start_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get the fine time form the compression start timestamp in the
+ * @brief get the fine time from the compression start timestamp in the
  *	compression entity header
  *
  * @returns the fine part of the compression start timestamp on success, 0 on
@@ -1046,7 +1048,7 @@ uint16_t cmp_ent_get_fine_start_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get the compression end timestamp form the compression entity header
+ * @brief get the compression end timestamp from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1067,7 +1069,7 @@ uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent)
 
 
 /**
- * @brief get the coarse time form the compression end timestamp in the
+ * @brief get the coarse time from the compression end timestamp in the
  *	compression entity header
  *
  * @returns the coarse part of the compression end timestamp on success, 0 on
@@ -1084,7 +1086,7 @@ uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get the fine time form the compression end timestamp in the
+ * @brief get the fine time from the compression end timestamp in the
  *	compression entity header
  *
  * @returns the fine part of the compression end timestamp on success, 0 on
@@ -1101,30 +1103,33 @@ uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent)
 
 
 /**
- * @brief get data_type form the compression entity header
+ * @brief get data_type from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
- * @returns the data_type (including the uncompressed data bit) on success,
+ * @returns the data_type NOT including the uncompressed data bit on success,
  *	DATA_TYPE_UNKOWN on error
  */
 
-enum cmp_ent_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
+enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
 {
+	enum cmp_data_type data_type;
+
 	if (!ent)
 		return DATA_TYPE_UNKOWN;
 
-	enum cmp_ent_data_type data_type = be16_to_cpu(ent->data_type);
+	data_type = be16_to_cpu(ent->data_type);
+	data_type &= (1U << RAW_BIT_DATA_TYPE_POS)-1; /* remove uncompressed data flag */
 
-	if (cmp_ent_data_type_valid(data_type))
-		return data_type;
-	else
-		return DATA_TYPE_UNKOWN;
+	if (!cmp_data_type_valid(data_type))
+		data_type = DATA_TYPE_UNKOWN;
+
+	return data_type;
 }
 
 
 /**
- * @brief get raw bit form the data_type field of the compression entity header
+ * @brief get the raw bit from the data_type field of the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1176,7 +1181,7 @@ uint8_t cmp_ent_get_model_value_used(struct cmp_entity *ent)
 
 
 /**
- * @brief get model id form the compression entity header
+ * @brief get model id from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1210,7 +1215,7 @@ uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used lossy compression parameter form the compression entity header
+ * @brief get the used lossy compression parameter from the compression entity header
  *
  * @param ent	pointer to a compression entity
  *
@@ -1227,7 +1232,7 @@ uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold parameter form the (adaptive)
+ * @brief get the used spillover threshold parameter from the (adaptive)
  *	imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1245,7 +1250,7 @@ uint16_t cmp_ent_get_ima_spill(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used Golomb parameter form the (adaptive) imagette specific
+ * @brief get the used Golomb parameter from the (adaptive) imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1263,7 +1268,7 @@ uint8_t cmp_ent_get_ima_golomb_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 1 spillover threshold parameter form the
+ * @brief get the used adaptive 1 spillover threshold parameter from the
  *	adaptive imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1281,7 +1286,7 @@ uint16_t cmp_ent_get_ima_ap1_spill(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 1 Golomb parameter form adaptive imagette
+ * @brief get the used adaptive 1 Golomb parameter from adaptive imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1299,7 +1304,7 @@ uint8_t cmp_ent_get_ima_ap1_golomb_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 2 spillover threshold parameter form the
+ * @brief get the used adaptive 2 spillover threshold parameter from the
  *	adaptive imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1317,7 +1322,7 @@ uint16_t cmp_ent_get_ima_ap2_spill(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used adaptive 2 spillover threshold parameter form the
+ * @brief get the used adaptive 2 spillover threshold parameter from the
  *	adaptive imagette specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1335,7 +1340,7 @@ uint8_t cmp_ent_get_ima_ap2_golomb_par(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 1 parameter form the non-imagette
+ * @brief get the used spillover threshold 1 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1357,7 +1362,7 @@ uint32_t cmp_ent_get_non_ima_spill1(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 1 form the non-imagette specific
+ * @brief get the used compression parameter 1 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1375,7 +1380,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par1(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 2 parameter form the non-imagette
+ * @brief get the used spillover threshold 2 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1397,7 +1402,7 @@ uint32_t cmp_ent_get_non_ima_spill2(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 2 form the non-imagette specific
+ * @brief get the used compression parameter 2 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1415,7 +1420,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par2(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 3 parameter form the non-imagette
+ * @brief get the used spillover threshold 3 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1437,7 +1442,7 @@ uint32_t cmp_ent_get_non_ima_spill3(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 3 form the non-imagette specific
+ * @brief get the used compression parameter 3 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1455,7 +1460,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par3(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 4 parameter form the non-imagette
+ * @brief get the used spillover threshold 4 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1477,7 +1482,7 @@ uint32_t cmp_ent_get_non_ima_spill4(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 4 form the non-imagette specific
+ * @brief get the used compression parameter 4 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1495,7 +1500,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par4(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 5 parameter form the non-imagette
+ * @brief get the used spillover threshold 5 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1517,7 +1522,7 @@ uint32_t cmp_ent_get_non_ima_spill5(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 5 form the non-imagette specific
+ * @brief get the used compression parameter 5 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1535,7 +1540,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par5(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used spillover threshold 6 parameter form the non-imagette
+ * @brief get the used spillover threshold 6 parameter from the non-imagette
  *	specific compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1557,7 +1562,7 @@ uint32_t cmp_ent_get_non_ima_spill6(struct cmp_entity *ent)
 
 
 /**
- * @brief get the used compression parameter 6 form the non-imagette specific
+ * @brief get the used compression parameter 6 from the non-imagette specific
  *	compression entity header
  *
  * @param ent	pointer to a compression entity
@@ -1588,7 +1593,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par6(struct cmp_entity *ent)
 
 void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 {
-	enum cmp_ent_data_type data_type;
+	enum cmp_data_type data_type;
 
 	if (!ent)
 		return NULL;
@@ -1634,7 +1639,7 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 
 
 /**
- * @brief copy the data form a compression entity to a buffer
+ * @brief copy the data from a compression entity to a buffer
  *
  * @param ent		pointer to the compression entity containing the compressed data
  * @param data_buf	pointer where the destination data buffer where the
@@ -1699,7 +1704,8 @@ ssize_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf,
 
 static uint32_t cmp_ent_get_hdr_size(struct cmp_entity *ent)
 {
-	return cmp_ent_cal_hdr_size(cmp_ent_get_data_type(ent));
+	return cmp_ent_cal_hdr_size(cmp_ent_get_data_type(ent),
+				    cmp_ent_get_data_type_raw_bit(ent));
 }
 
 
@@ -1727,108 +1733,67 @@ uint32_t cmp_ent_get_cmp_data_size(struct cmp_entity *ent)
 
 
 /**
- * @brief set the parameters in the non-imagette specific compression
- *	entity header
+ * @brief write the compression parameters from a compression configuration
+ *	into the compression entity header
+ * @note no compressed data are put into the entity and no change of the entity
+ *	size
  *
- * @param ent	pointer to a compression entity
- * @param info	decompression information structure
- *
- * @returns 0 on success, otherwise error
+ * @param ent		pointer to a compression entity
+ * @param cfg		pointer to a compression configuration
+ * @param cmp_size_bits	size of the compressed data in bits
  *
- * @warning this functions is not implemented jet
+ * @returns 0 on success, negative on error
  */
 
-static int cmp_ent_write_non_ima_parameters(struct cmp_entity *ent, struct cmp_info *info)
+int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
+			   int cmp_size_bits)
 {
-	if (!info)
-		return -1;
-	(void)ent;
-
-	printf("not implemented jet!\n");
-	return -1;
-#if 0
-	if (cmp_ent_set_non_ima_spill1(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par1(ent, info->))
-		return -1;
-
-	if (cmp_ent_set_non_ima_spill2(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par2(ent, info->))
-		return -1;
-
-	if (cmp_ent_set_non_ima_spill3(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par3(ent, info->))
-		return -1;
-
-	if (cmp_ent_set_non_ima_spill4(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par4(ent, info->))
-		return -1;
+	uint32_t ent_cmp_data_size;
 
-	if (cmp_ent_set_non_ima_spill5(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par5(ent, info->))
+	if (!cfg)
 		return -1;
 
-	if (cmp_ent_set_non_ima_spill6(ent, info->))
-		return -1;
-	if (cmp_ent_set_non_ima_cmp_par6(ent, info->))
+	if (cmp_size_bits < 0)
 		return -1;
-	return 0;
-#endif
-}
-
 
-/**
- * @brief write the compression parameters in the entity header based on the data
- *	product type set in the entity and the provided decompression information
- *	struct
- *
- * @param ent	pointer to a compression entity
- * @param info	decompression information structure
- * @param cfg	compression configuration structure for adaptive compression
- *	parameters (can be NULL)
- *
- * @returns 0 on success, negative on error
- */
-
-static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
-				struct cmp_cfg *cfg)
-{
-	uint32_t ent_cmp_data_size;
-
-	if (!info)
+	if (cfg->data_type != cmp_ent_get_data_type(ent)) {
+		debug_print("Error: The entity data product type dos not match the configuration data product type.\n");
 		return -1;
+	}
 
 	ent_cmp_data_size = cmp_ent_get_cmp_data_size(ent);
 
 	/* check if the entity can hold the compressed data */
-	if (ent_cmp_data_size < cmp_bit_to_4byte(info->cmp_size))
+	if (ent_cmp_data_size < cmp_bit_to_4byte((unsigned int)cmp_size_bits)) {
+		debug_print("Error: The entity size is to small to hold the compressed data.\n");
 		return -2;
+	}
 
 	/* set compression parameter fields in the generic entity header */
-	if (cmp_ent_set_original_size(ent, cmp_cal_size_of_data(info->samples_used,
-								info->cmp_mode_used)))
+	if (cmp_ent_set_original_size(ent, cmp_cal_size_of_data(cfg->samples,
+								cfg->data_type)))
 		return -1;
-	if (cmp_ent_set_cmp_mode(ent, info->cmp_mode_used))
+	if (cmp_ent_set_cmp_mode(ent, cfg->cmp_mode))
 		return -1;
-	if (cmp_ent_set_model_value(ent, info->model_value_used))
+	if (cmp_ent_set_model_value(ent, cfg->model_value))
 		return -1;
-	if (cmp_ent_set_lossy_cmp_par(ent, info->round_used))
+	if (cmp_ent_set_lossy_cmp_par(ent, cfg->round))
 		return -1;
 
-	if (cmp_ent_get_data_type_raw_bit(ent))
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
+		/* check the raw data bit */
+		if (!cmp_ent_get_data_type_raw_bit(ent)) {
+			debug_print("Error: The entity's raw data bit is not set, but the configuration contains raw data.\n");
+			return -1;
+		}
 		/* no specific header is used for raw data we are done */
 		return 0;
+	}
 
 	switch (cmp_ent_get_data_type(ent)) {
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
-		if (!cfg)
-			return -1;
 		if (cmp_ent_set_ima_ap1_spill(ent, cfg->ap1_spill))
 			return -1;
 		if (cmp_ent_set_ima_ap1_golomb_par(ent, cfg->ap1_golomb_par))
@@ -1841,14 +1806,44 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
 	case DATA_TYPE_IMAGETTE:
 	case DATA_TYPE_SAT_IMAGETTE:
 	case DATA_TYPE_F_CAM_IMAGETTE:
-		if (cmp_ent_set_ima_spill(ent, info->spill_used))
+		if (cmp_ent_set_ima_spill(ent, cfg->spill))
 			return -1;
-		if (cmp_ent_set_ima_golomb_par(ent, info->golomb_par_used))
+		if (cmp_ent_set_ima_golomb_par(ent, cfg->golomb_par))
 			return -1;
 		break;
 	case DATA_TYPE_OFFSET:
 	case DATA_TYPE_BACKGROUND:
 	case DATA_TYPE_SMEARING:
+		if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_mean))
+			return -1;
+		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_mean))
+			return -1;
+
+		if (cmp_ent_set_non_ima_spill2(ent, cfg->cmp_par_variance))
+			return -1;
+		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->spill_variance))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_pixels_error))
+			return -1;
+		if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_pixels_error))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par4(ent, 0))
+			return -1;
+		if (cmp_ent_set_non_ima_spill4(ent, 0))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par5(ent, 0))
+			return -1;
+		if (cmp_ent_set_non_ima_spill5(ent, 0))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par6(ent, 0))
+			return -1;
+		if (cmp_ent_set_non_ima_spill6(ent, 0))
+			return -1;
+		break;
 	case DATA_TYPE_S_FX:
 	case DATA_TYPE_S_FX_DFX:
 	case DATA_TYPE_S_FX_NCOB:
@@ -1861,12 +1856,43 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
 	case DATA_TYPE_F_FX_DFX:
 	case DATA_TYPE_F_FX_NCOB:
 	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_exp_flags))
+			return -1;
+		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_exp_flags))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_fx))
+			return -1;
+		if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_fx))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_ncob))
+			return -1;
+		if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_ncob))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par4(ent, cfg->cmp_par_efx))
+			return -1;
+		if (cmp_ent_set_non_ima_spill4(ent, cfg->spill_efx))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par5(ent, cfg->cmp_par_ecob))
+			return -1;
+		if (cmp_ent_set_non_ima_spill5(ent, cfg->spill_ecob))
+			return -1;
+
+		if (cmp_ent_set_non_ima_cmp_par6(ent, cfg->cmp_par_fx_cob_variance))
+			return -1;
+		if (cmp_ent_set_non_ima_spill6(ent, cfg->spill_fx_cob_variance))
+			return -1;
+
+		break;
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
-		if (cmp_ent_write_non_ima_parameters(ent, info))
+		/* TODO: fix this*/
 			return -1;
 		break;
-	case DATA_TYPE_UNKOWN: /* fall through */
+	case DATA_TYPE_UNKOWN:
 	default:
 		return -1;
 	}
@@ -1876,12 +1902,94 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
 
 
 /**
- * @brief create a compression entity by setting the size of the
- * compression entity and the data product type in the entity header
+ * @brief write the parameters from the RDCU decompression information structure
+ *	in the compression entity header
+ * @note no compressed data are put into the entity and no change of the entity
+ *	size
+ *
+ * @param ent	pointer to a compression entity
+ * @param info	pointer to a decompression information structure
+ * @param cfg	pointer to a compression configuration structure for adaptive
+ *	compression parameters (can be NULL if non adaptive data_type is used)
+ *
+ * @returns 0 on success, negative on error
+ */
+
+int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *info,
+				const struct cmp_cfg *cfg)
+{
+	uint32_t ent_cmp_data_size;
+	enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
+
+	if (!info)
+		return -1;
+
+	ent_cmp_data_size = cmp_ent_get_cmp_data_size(ent);
+
+	/* check if the entity can hold the compressed data */
+	if (ent_cmp_data_size < cmp_bit_to_4byte(info->cmp_size)) {
+		debug_print("Error: The entity size is to small to hold the compressed data.\n");
+		return -2;
+	}
+
+	if (!rdcu_supported_data_type_is_used(data_type)) {
+		debug_print("Error: The compression data type is not one of the types supported by the RDCU.\n");
+		return -1;
+	}
+
+	/* set compression parameter fields in the generic entity header */
+	if (cmp_ent_set_original_size(ent, cmp_cal_size_of_data(info->samples_used, DATA_TYPE_IMAGETTE)))
+		return -1;
+	if (cmp_ent_set_cmp_mode(ent, info->cmp_mode_used))
+		return -1;
+	if (cmp_ent_set_model_value(ent, info->model_value_used))
+		return -1;
+	if (cmp_ent_set_lossy_cmp_par(ent, info->round_used))
+		return -1;
+
+	if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(info->cmp_mode_used)) {
+		debug_print("Error: The raw bit is set in data product type filed, but no raw compression mode is used.\n");
+		return -1;
+	}
+	if (raw_mode_is_used(info->cmp_mode_used))
+		/* no specific header is used for raw data we are done */
+		return 0;
+
+	if (cmp_ent_set_ima_spill(ent, info->spill_used))
+		return -1;
+	if (cmp_ent_set_ima_golomb_par(ent, info->golomb_par_used))
+		return -1;
+
+	/* use the adaptive imagette parameter from the compression configuration
+	 * if an adaptive imagette compression data type is ent in the entity
+	 */
+	if (cmp_ap_imagette_data_type_is_used(data_type)) {
+		if (!cfg) {
+			debug_print("Error: Need the compression configuration to get the adaptive parameters.\n");
+			return -1;
+		}
+		if (cmp_ent_set_ima_ap1_spill(ent, cfg->ap1_spill))
+			return -1;
+		if (cmp_ent_set_ima_ap1_golomb_par(ent, cfg->ap1_golomb_par))
+			return -1;
+		if (cmp_ent_set_ima_ap2_spill(ent, cfg->ap2_spill))
+			return -1;
+		if (cmp_ent_set_ima_ap2_golomb_par(ent, cfg->ap2_golomb_par))
+			return -1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * @brief create a compression entity by setting the size of the compression
+ *	entity and the data product type in the entity header
  *
  * @param ent		pointer to a compression entity; if NULL, the function
- *	returns the needed size
+ *			returns the needed size
  * @param data_type	compression entity data product type
+ * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
  * @param cmp_size_byte	size of the compressed data in bytes
  *
  * @note if the entity size is smaller than the largest header, the function
@@ -1890,12 +1998,12 @@ static int cmp_ent_write_cmp_pars(struct cmp_entity *ent, struct cmp_info *info,
  * @returns the size of the compression entity or 0 on error
  */
 
-size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		      uint32_t cmp_size_byte)
+uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type,
+			int raw_mode_flag, uint32_t cmp_size_byte)
 {
 	int err;
-	uint32_t hdr_size = cmp_ent_cal_hdr_size(data_type);
-	size_t ent_size = hdr_size + cmp_size_byte;
+	uint32_t hdr_size = cmp_ent_cal_hdr_size(data_type, raw_mode_flag);
+	uint32_t ent_size = hdr_size + cmp_size_byte;
 	uint32_t ent_size_cpy = ent_size;
 
 	if (!hdr_size)
@@ -1904,6 +2012,9 @@ size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 	if (cmp_size_byte > CMP_ENTITY_MAX_SIZE)
 		return 0;
 
+	if (ent_size > CMP_ENTITY_MAX_SIZE)
+		return 0;
+
 	if (ent_size < sizeof(struct cmp_entity))
 		ent_size = sizeof(struct cmp_entity);
 
@@ -1916,7 +2027,7 @@ size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 	if (err)
 		return 0;
 
-	err = cmp_ent_set_data_type(ent, data_type);
+	err = cmp_ent_set_data_type(ent, data_type, raw_mode_flag);
 	if (err)
 		return 0;
 
@@ -1927,35 +2038,37 @@ size_t cmp_ent_create(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 /**
  * @brief create a compression entity and set the header fields
  *
- * @note this function simplifies the entity setup by creating a entity and
+ * @note this function simplifies the entity set up by creating an entity and
  *	setting the header fields in one function call
+ * @note no compressed data are put into the entity
  *
  * @param ent			pointer to a compression entity; if NULL, the
  *	function returns the needed size
- * @param data_type		compression entity data product type
- * @param version_id	applications software version identifier
+ * @param version_id		applications software version identifier
  * @param start_time		compression start timestamp (coarse and fine)
  * @param end_time		compression end timestamp (coarse and fine)
  * @param model_id		model identifier
  * @param model_counter		model counter
- * @param info			decompression information structure
- * @param cfg			compression configuration structure for adaptive
- *	compression parameters (can be NULL)
+ * @param cfg			pointer to compression configuration (can be NULL)
+ * @param cmp_size_bits		length of the compressed data in bits
  *
  * @returns the size of the compression entity or 0 on error
  */
 
-size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
-		     uint32_t version_id, uint64_t start_time,
-		     uint64_t end_time, uint16_t model_id, uint8_t model_counter,
-		     struct cmp_info *info, struct cmp_cfg *cfg)
+size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id,
+		     uint64_t start_time, uint64_t end_time, uint16_t model_id,
+		     uint8_t model_counter, struct cmp_cfg *cfg, int cmp_size_bits)
 {
 	uint32_t ent_size;
 
-	if (!info)
+	if (!cfg)
 		return 0;
 
-	ent_size = cmp_ent_create(ent, data_type, cmp_bit_to_4byte(info->cmp_size));
+	if (cmp_size_bits < 0)
+		return 0;
+
+	ent_size = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW,
+				  cmp_bit_to_4byte((unsigned int)cmp_size_bits));
 	if (!ent_size)
 		return 0;
 
@@ -1970,7 +2083,7 @@ size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 			return 0;
 		if (cmp_ent_set_model_counter(ent, model_counter))
 			return 0;
-		if (cmp_ent_write_cmp_pars(ent, info, cfg))
+		if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits))
 			return 0;
 	}
 
@@ -1979,82 +2092,116 @@ size_t cmp_ent_build(struct cmp_entity *ent, enum cmp_ent_data_type data_type,
 
 
 /**
- * @brief read in read in a imagette compression entity header to a info struct
+ * @brief read in an imagette compression entity header to a
+ *	compression configuration
  *
- * @param ent			pointer to a compression entity
- * @param info			pointer to decompression information structure
- *	to store the read values
+ * @param ent	pointer to a compression entity
+ * @param cfg	pointer to a compression configuration
  *
  * @returns 0 on success; otherwise error
  */
 
-int cmp_ent_read_imagette_header(struct cmp_entity *ent, struct cmp_info *info)
+int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 {
-	uint32_t original_size;
-	uint32_t sample_size;
+	int samples;
 
-	if (!ent)
-		return -1;
-
-	if (!info)
-		return -1;
-
-	info->cmp_mode_used = cmp_ent_get_cmp_mode(ent);
-	info->model_value_used = cmp_ent_get_model_value_used(ent);
-	info->round_used = cmp_ent_get_lossy_cmp_par(ent);
-	info->spill_used = cmp_ent_get_ima_spill(ent);
-	info->golomb_par_used = cmp_ent_get_ima_golomb_par(ent);
-	info->cmp_size = cmp_ent_get_cmp_data_size(ent)*CHAR_BIT;
-
-	sample_size = size_of_a_sample(info->cmp_mode_used);
-	if (!sample_size) {
-		info->samples_used = 0;
+	cfg->data_type = cmp_ent_get_data_type(ent);
+	if (!cmp_data_type_valid(cfg->data_type)) {
+		debug_print("Error: Compression data type not supported.\n");
 		return -1;
 	}
 
-	original_size = cmp_ent_get_original_size(ent);
-	if (original_size % sample_size != 0) {
-		fprintf(stderr, "Error: original_size and cmp_mode compression header field are not compatible.\n");
-		info->samples_used = 0;
+	cfg->cmp_mode = cmp_ent_get_cmp_mode(ent);
+	cfg->model_value = cmp_ent_get_model_value_used(ent);
+	cfg->round = cmp_ent_get_lossy_cmp_par(ent);
+	cfg->buffer_length = cmp_ent_get_cmp_data_size(ent);
+
+	samples = cmp_input_size_to_samples(cmp_ent_get_original_size(ent), cfg->data_type);
+	if (samples < 0) {
+		debug_print("Error: original_size and data product type in the compression header field are not compatible.\n");
+		cfg->samples = 0;
 		return -1;
 	}
 
-	info->samples_used = original_size / sample_size;
+	cfg->samples = samples;
 
-	if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(info->cmp_mode_used)) {
-		fprintf(stderr, "Error: The raw bit is set in Data Product Type Filed, but no raw compression mode is used.\n");
+	if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(cfg->cmp_mode)) {
+		debug_print("Error: The raw bit is set in data product type filed, but no raw compression mode is used.\n");
 		return -1;
 	}
-	return 0;
-}
-
 
-#if 0
-int cmp_ent_read_adaptive_imagette_header(struct cmp_entity *ent, struct cmp_info *info)
-{
-	if (!ent)
-		return -1;
+	cfg->icu_output_buf = cmp_ent_get_data_buf(ent);
 
-	if (!info)
-		return -1;
-
-	if (cmp_ent_get_imagette_header(ent, info))
+	switch (cfg->data_type) {
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+		cfg->ap1_golomb_par = cmp_ent_get_ima_ap1_golomb_par(ent);
+		cfg->ap1_spill = cmp_ent_get_ima_ap1_spill(ent);
+		cfg->ap2_golomb_par = cmp_ent_get_ima_ap2_golomb_par(ent);
+		cfg->ap2_spill = cmp_ent_get_ima_ap2_spill(ent);
+		/* fall through */
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+		cfg->spill = cmp_ent_get_ima_spill(ent);
+		cfg->golomb_par = cmp_ent_get_ima_golomb_par(ent);
+		break;
+	case DATA_TYPE_OFFSET:
+	case DATA_TYPE_BACKGROUND:
+	case DATA_TYPE_SMEARING:
+		cfg->cmp_par_mean = cmp_ent_get_non_ima_cmp_par1(ent);
+		cfg->spill_mean = cmp_ent_get_non_ima_spill1(ent);
+		cfg->cmp_par_variance = cmp_ent_get_non_ima_cmp_par2(ent);
+		cfg->spill_variance = cmp_ent_get_non_ima_spill2(ent);
+		cfg->cmp_par_pixels_error = cmp_ent_get_non_ima_cmp_par3(ent);
+		cfg->spill_pixels_error = cmp_ent_get_non_ima_spill3(ent);
+		break;
+	case DATA_TYPE_S_FX:
+	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_NCOB:
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX:
+	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_NCOB:
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX:
+	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_NCOB:
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		cfg->cmp_par_exp_flags = cmp_ent_get_non_ima_cmp_par1(ent);
+		cfg->spill_exp_flags = cmp_ent_get_non_ima_spill1(ent);
+		cfg->cmp_par_fx = cmp_ent_get_non_ima_cmp_par2(ent);
+		cfg->spill_fx = cmp_ent_get_non_ima_spill2(ent);
+		cfg->cmp_par_ncob = cmp_ent_get_non_ima_cmp_par3(ent);
+		cfg->spill_ncob = cmp_ent_get_non_ima_spill3(ent);
+		cfg->cmp_par_efx = cmp_ent_get_non_ima_cmp_par4(ent);
+		cfg->spill_efx = cmp_ent_get_non_ima_spill4(ent);
+		cfg->cmp_par_ecob = cmp_ent_get_non_ima_cmp_par5(ent);
+		cfg->spill_ecob = cmp_ent_get_non_ima_spill5(ent);
+		cfg->cmp_par_fx_cob_variance = cmp_ent_get_non_ima_cmp_par6(ent);
+		cfg->spill_fx_cob_variance = cmp_ent_get_non_ima_spill6(ent);
+		break;
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
+		/* TODO: fix this*/
+			return -1;
+		break;
+	case DATA_TYPE_UNKOWN: /* fall through */
+	default:
 		return -1;
-	/* info->ap1_cmp_size_byte = cmp_ent_get_ap1_cmp_size_byte(ent); */
-	/* info->ap2_cmp_size_byte = cmp_ent_get_ap2_cmp_size_byte(ent); */
-	/* get ap1_spill and ap1/2 gpar*/
+	}
 
 	return 0;
 }
-#endif
 
 
-#if __has_include(<time.h>)
+#ifdef HAS_TIME_H
 /*
  * @brief Covert a calendar time expressed as a struct tm object to time since
  *	 epoch as a time_t object. The function interprets the input structure
  *	 as representing Universal Coordinated Time (UTC).
- * @note timegm is a GNU C Library extensions, not standardized. This function
+ * @note timegm is a GNU C Library extension, not standardized. This function
  *	is used as a portable alternative
  * @note The function is thread-unsafe
  *
@@ -2067,9 +2214,9 @@ int cmp_ent_read_adaptive_imagette_header(struct cmp_entity *ent, struct cmp_inf
 
 static time_t my_timegm(struct tm *tm)
 {
-#if defined(_WIN32) || defined(_WIN64)
+#  if defined(_WIN32) || defined(_WIN64)
 	return _mkgmtime(tm);
-#else
+#  else
 	time_t ret;
 	char *tz;
 
@@ -2086,14 +2233,14 @@ static time_t my_timegm(struct tm *tm)
 		unsetenv("TZ");
 	tzset();
 	return ret;
-#endif
+#  endif
 }
 
 
 /*
  * @brief Generate a timestamp for the compression header
  *
- * @param ts  pointer to object of type struct timespec of the timestamp time, null for now
+ * @param ts  pointer to an object of type struct timespec of the timestamp time, null for now
  *
  * @returns returns compression header timestamp or 0 on error
  */
@@ -2186,7 +2333,7 @@ void cmp_ent_print(struct cmp_entity *ent)
 
 
 /**
- * @brief parse the generic compressed entity header
+ * @brief parses the generic compressed entity header
  *
  * @param ent	pointer to a compression entity
  */
@@ -2197,13 +2344,14 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 		 model_value_used, model_id, model_counter, lossy_cmp_par_used,
 		 start_coarse_time, end_coarse_time;
 	uint16_t start_fine_time, end_fine_time;
-	enum cmp_ent_data_type data_type;
+	enum cmp_data_type data_type;
 	int raw_bit;
 
 	version_id = cmp_ent_get_version_id(ent);
 	if (version_id & CMP_TOOL_VERSION_ID_BIT) {
 		uint16_t major = (version_id & 0x7FFF0000U) >> 16U;
 		uint16_t minor = version_id & 0xFFFFU;
+
 		printf("Compressed with cmp_tool version: %u.%02u\n", major, minor);
 	} else
 		printf("ICU ASW Version ID: %u\n", version_id);
@@ -2226,10 +2374,11 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 	end_fine_time = cmp_ent_get_fine_end_time(ent);
 	printf("Compression Fine End Time: %d\n", end_fine_time);
 
-#if __has_include(<time.h>)
+#ifdef HAS_TIME_H
 	{
 		struct tm epoch_date = EPOCH_DATE;
 		time_t time = my_timegm(&epoch_date) + start_coarse_time;
+
 		printf("Data were compressed on (local time): %s", ctime(&time));
 	}
 #endif
@@ -2319,17 +2468,26 @@ static void cmp_ent_parese_adaptive_imagette_header(struct cmp_entity *ent)
 
 static void cmp_ent_parese_specific_header(struct cmp_entity *ent)
 {
-	enum cmp_ent_data_type data_type = cmp_ent_get_data_type(ent);
+	enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
+
+	if (cmp_ent_get_data_type_raw_bit(ent)) {
+		printf("Uncompressed data bit is set no specific header is used.\n");
+		return;
+	}
 
 	switch (data_type) {
 	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
 		cmp_ent_parese_imagette_header(ent);
 		break;
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		cmp_ent_parese_adaptive_imagette_header(ent);
 		break;
 	default:
-		printf("Data Product Type not supported!\n");
+		printf("For this data product type no parse functions is implemented!\n");
 		break;
 	}
 }
@@ -2347,3 +2505,4 @@ void cmp_ent_parse(struct cmp_entity *ent)
 
 	cmp_ent_parese_specific_header(ent);
 }
+
diff --git a/lib/cmp_guess.c b/lib/cmp_guess.c
index 265b9c5..c173814 100644
--- a/lib/cmp_guess.c
+++ b/lib/cmp_guess.c
@@ -17,12 +17,14 @@
  *	dataset
  */
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "../include/cmp_icu.h"
-#include "../include/cmp_guess.h"
+#include "cmp_data_types.h"
+#include "cmp_icu.h"
+#include "cmp_guess.h"
 
 
 /* how often the model is updated before it is rested */
@@ -67,6 +69,43 @@ uint16_t cmp_guess_model_value(int n_model_updates)
 }
 
 
+/**
+ * @brief get a good spill threshold parameter for the selected Golomb parameter
+ *	and compression mode
+ *
+ * @param golomb_par	Golomb parameter
+ * @param cmp_mode	compression mode
+ *
+ * @returns a good spill parameter (optimal for zero escape mechanism)
+ * @warning icu compression not support yet!
+ */
+
+uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode)
+{
+	const uint32_t LUT_RDCU_MULIT[MAX_RDCU_GOLOMB_PAR+1] = {0, 8, 16, 23,
+		30, 36, 44, 51, 58, 64, 71, 77, 84, 90, 97, 108, 115, 121, 128,
+		135, 141, 148, 155, 161, 168, 175, 181, 188, 194, 201, 207, 214,
+		229, 236, 242, 250, 256, 263, 269, 276, 283, 290, 296, 303, 310,
+		317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397,
+		405, 411, 418, 424, 431, 452 };
+
+	if (zero_escape_mech_is_used(cmp_mode))
+		return get_max_spill(golomb_par, DATA_TYPE_IMAGETTE);
+
+	if (cmp_mode == CMP_MODE_MODEL_MULTI) {
+		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
+			return 0;
+		else
+			return LUT_RDCU_MULIT[golomb_par];
+	}
+
+	if (cmp_mode == CMP_MODE_DIFF_MULTI)
+		return CMP_GOOD_SPILL_DIFF_MULTI;
+
+	return 0;
+}
+
+
 /**
  * @brief guess a good configuration with pre_cal_method
  *
@@ -79,18 +118,17 @@ uint16_t cmp_guess_model_value(int n_model_updates)
 static uint32_t pre_cal_method(struct cmp_cfg *cfg)
 {
 	uint32_t g;
-	uint32_t cmp_size;
-	uint32_t cmp_size_best = ~0U;
+	int cmp_size, cmp_size_best = INT_MAX;
 	uint32_t golomb_par_best = 0;
 	uint32_t spill_best = 0;
 
 	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
-		uint32_t s = cmp_get_good_spill(g, cfg->cmp_mode);
+		uint32_t s = cmp_rdcu_get_good_spill(g, cfg->cmp_mode);
 
 		cfg->golomb_par = g;
 		cfg->spill = s;
-		cmp_size = cmp_encode_data(cfg);
-		if (cmp_size == 0) {
+		cmp_size = icu_compress_data(cfg);
+		if (cmp_size <= 0) {
 			return 0;
 		} else if (cmp_size < cmp_size_best) {
 			cmp_size_best = cmp_size;
@@ -120,8 +158,7 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 	uint32_t g, s;
 	uint32_t n_cal_steps = 0, last = 0;
 	const uint32_t max_cal_steps = CMP_GUESS_MAX_CAL_STEPS;
-	uint32_t cmp_size;
-	uint32_t cmp_size_best = ~0U;
+	int cmp_size, cmp_size_best = INT_MAX;
 	uint32_t golomb_par_best = 0;
 	uint32_t spill_best = 0;
 	uint32_t percent;
@@ -134,12 +171,12 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 	fflush(stdout);
 
 	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
-		for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->cmp_mode); s++) {
+		for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->data_type); s++) {
 			cfg->golomb_par = g;
 			cfg->spill = s;
 
-			cmp_size = cmp_encode_data(cfg);
-			if (cmp_size == 0) {
+			cmp_size = icu_compress_data(cfg);
+			if (cmp_size <= 0) {
 				return 0;
 			} else if (cmp_size < cmp_size_best) {
 				cmp_size_best = cmp_size;
@@ -185,19 +222,19 @@ static void add_rdcu_pars_internal(struct cmp_cfg *cfg)
 		cfg->ap2_golomb_par = cfg->golomb_par + 1;
 	}
 
-	cfg->ap1_spill = cmp_get_good_spill(cfg->ap1_golomb_par, cfg->cmp_mode);
-	cfg->ap2_spill = cmp_get_good_spill(cfg->ap2_golomb_par, cfg->cmp_mode);
+	cfg->ap1_spill = cmp_rdcu_get_good_spill(cfg->ap1_golomb_par, cfg->cmp_mode);
+	cfg->ap2_spill = cmp_rdcu_get_good_spill(cfg->ap2_golomb_par, cfg->cmp_mode);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
-		cfg->rdcu_data_adr = DEFAULT_CFG_MODEL.rdcu_data_adr;
-		cfg->rdcu_model_adr = DEFAULT_CFG_MODEL.rdcu_model_adr;
-		cfg->rdcu_new_model_adr = DEFAULT_CFG_MODEL.rdcu_new_model_adr;
-		cfg->rdcu_buffer_adr = DEFAULT_CFG_MODEL.rdcu_buffer_adr;
+		cfg->rdcu_data_adr = CMP_DEF_IMA_MODEL_RDCU_DATA_ADR;
+		cfg->rdcu_model_adr = CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR;
+		cfg->rdcu_new_model_adr = CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR;
+		cfg->rdcu_buffer_adr = CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR;
 	} else {
-		cfg->rdcu_data_adr = DEFAULT_CFG_DIFF.rdcu_data_adr;
-		cfg->rdcu_model_adr = DEFAULT_CFG_DIFF.rdcu_model_adr;
-		cfg->rdcu_new_model_adr = DEFAULT_CFG_DIFF.rdcu_new_model_adr;
-		cfg->rdcu_buffer_adr = DEFAULT_CFG_DIFF.rdcu_buffer_adr;
+		cfg->rdcu_data_adr = CMP_DEF_IMA_DIFF_RDCU_DATA_ADR;
+		cfg->rdcu_model_adr = CMP_DEF_IMA_DIFF_RDCU_MODEL_ADR;
+		cfg->rdcu_new_model_adr = CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR;
+		cfg->rdcu_buffer_adr = CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR;
 	}
 }
 
@@ -220,7 +257,6 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 {
 	size_t size;
 	struct cmp_cfg work_cfg;
-	int err;
 	uint32_t cmp_size = 0;
 
 	if (!cfg)
@@ -228,38 +264,28 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 
 	if (!cfg->input_buf)
 		return 0;
+	if (model_mode_is_used(cfg->cmp_mode))
+		if (!cfg->model_buf)
+			return 0;
 
-	if (!rdcu_supported_mode_is_used(cfg->cmp_mode)) {
+	if (!rdcu_supported_cmp_mode_is_used(cfg->cmp_mode)) {
 		printf("This compression mode is not implied yet.\n");
 		return 0;
 	}
 	/* make a working copy of the input data (and model) because the
-	 * following function works inplace */
+	 * following function works inplace
+	 */
 	work_cfg = *cfg;
-	work_cfg.input_buf = NULL;
-	work_cfg.model_buf = NULL;
 	work_cfg.icu_new_model_buf = NULL;
 	work_cfg.icu_output_buf = NULL;
 	work_cfg.buffer_length = 0;
+	work_cfg.data_type = DATA_TYPE_IMAGETTE; /* TODO: adapt to others data types */
 
-	size = cfg->samples * size_of_a_sample(work_cfg.cmp_mode);
+	size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
 	if (size == 0)
 		goto error;
-	work_cfg.input_buf = malloc(size);
-	if (!work_cfg.input_buf) {
-		printf("malloc() failed!\n");
-		goto error;
-	}
-	memcpy(work_cfg.input_buf, cfg->input_buf, size);
-
-	if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode)) {
-		work_cfg.model_buf = malloc(size);
-		if (!work_cfg.model_buf) {
-			printf("malloc() failed!\n");
-			goto error;
-		}
-		memcpy(work_cfg.model_buf, cfg->model_buf, size);
 
+	if (model_mode_is_used(cfg->cmp_mode)) {
 		work_cfg.icu_new_model_buf = malloc(size);
 		if (!work_cfg.icu_new_model_buf) {
 			printf("malloc() failed!\n");
@@ -267,14 +293,6 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 		}
 	}
 
-	err = cmp_pre_process(&work_cfg);
-	if (err)
-		goto error;
-
-	err = cmp_map_to_pos(&work_cfg);
-	if (err)
-		goto error;
-
 	/* find the best parameters */
 	switch (level) {
 	case 3:
@@ -294,8 +312,6 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 	if (!cmp_size)
 		goto error;
 
-	free(work_cfg.input_buf);
-	free(work_cfg.model_buf);
 	free(work_cfg.icu_new_model_buf);
 
 	cfg->golomb_par = work_cfg.golomb_par;
@@ -303,16 +319,15 @@ uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
 
 	cfg->model_value = cmp_guess_model_value(num_model_updates);
 
-	if (rdcu_supported_mode_is_used(cfg->cmp_mode))
+	if (rdcu_supported_data_type_is_used(cfg->data_type))
 		add_rdcu_pars_internal(cfg);
 
-	cfg->buffer_length = ((cmp_size + 32)&~0x1FU)/(size_of_a_sample(work_cfg.cmp_mode)*8);
+	/* TODO: check that for non-imagette data */
+	cfg->buffer_length = ((cmp_size + 32)&~0x1FU)/(size_of_a_sample(cfg->data_type)*8);
 
 	return cmp_size;
 
 error:
-	free(work_cfg.input_buf);
-	free(work_cfg.model_buf);
 	free(work_cfg.icu_new_model_buf);
 	return 0;
 }
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 5409045..057ee64 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -15,1761 +15,2396 @@
  *
  * @brief software compression library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
+ *
+ * To compress data, first create a compression configuration with the
+ * cmp_cfg_icu_create() function.
+ * Then set the different data buffers with the data to compressed, the model
+ * data and the compressed data with the cmp_cfg_icu_buffers() function.
+ * Then set the compression data type specific compression parameters. For
+ * imagette data use the cmp_cfg_icu_imagette() function. For flux and center of
+ * brightness data use the cmp_cfg_fx_cob() function. And for background, offset
+ * and smearing data use the cmp_cfg_aux() function.
+ * Finally, you can compress the data with the icu_compress_data() function.
  */
 
 
-#include <stdio.h>
 #include <stdint.h>
 #include <string.h>
 #include <limits.h>
 
-#include "../include/cmp_support.h"
-#include "../include/cmp_data_types.h"
-#include "../include/cmp_icu.h"
-#include "../include/byteorder.h"
-#include "../include/cmp_debug.h"
+#include "byteorder.h"
+#include "cmp_debug.h"
+#include "cmp_data_types.h"
+#include "cmp_support.h"
+#include "cmp_icu.h"
+
+
+/* pointer to a code word generation function */
+typedef uint32_t (*generate_cw_f_pt)(uint32_t value, uint32_t encoder_par1,
+				     uint32_t encoder_par2, uint32_t *cw);
+
+
+/* structure to hold a setup to encode a value */
+struct encoder_setupt {
+	generate_cw_f_pt generate_cw_f; /* pointer to the code word generation function */
+	int (*encode_method_f)(uint32_t data, uint32_t model, int stream_len,
+			       const struct encoder_setupt *setup); /* pointer to the encoding function */
+	uint32_t *bitstream_adr; /* start address of the compressed data bitstream */
+	uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */
+	uint32_t encoder_par1; /* encoding parameter 1 */
+	uint32_t encoder_par2; /* encoding parameter 2 */
+	uint32_t spillover_par; /* outlier parameter */
+	uint32_t lossy_par; /* lossy compression parameter */
+	uint32_t max_data_bits; /* how many bits are needed to represent the highest possible value */
+};
 
 
 /**
- * @brief check if the compressor configuration is valid for a SW compression,
- *	see the user manual for more information (PLATO-UVIE-PL-UM-0001).
+ * @brief create a ICU compression configuration
  *
- * @param cfg	configuration contains all parameters required for compression
- * @param info	compressor information contains information of an executed
- *		compression (can be NULL)
+ * @param data_type	compression data product types
+ * @param cmp_mode	compression mode
+ * @param model_value	model weighting parameter (only need for model compression mode)
+ * @param lossy_par	lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
  *
- * @returns 0 when configuration is valid, invalid configuration otherwise
+ * @returns compression configuration containing the chosen parameters;
+ *	on error the data_type record is set to DATA_TYPE_UNKOWN
  */
 
-int icu_cmp_cfg_valid(const struct cmp_cfg *cfg, struct cmp_info *info)
+struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
+				  uint32_t model_value, uint32_t lossy_par)
 {
-	int cfg_invalid = 0;
-
-	if (!cfg) {
-		debug_print("Error: compression configuration structure is NULL.\n");
-		return -1;
-	}
+	int cfg_valid;
+	struct cmp_cfg cfg = {0};
 
-	if (!info)
-		debug_print("Warning: compressor information structure is NULL.\n");
+	cfg.data_type = data_type;
+	cfg.cmp_mode = cmp_mode;
+	cfg.model_value = model_value;
+	cfg.round = lossy_par;
 
-	if (info)
-		info->cmp_err = 0;  /* reset errors */
-
-	if (cfg->input_buf == NULL) {
-		debug_print("Error: The input_buf buffer for the data to be compressed is NULL.\n");
-		cfg_invalid++;
-	}
+	cfg_valid = cmp_cfg_icu_gen_par_is_valid(&cfg);
+	if (!cfg_valid)
+		cfg.data_type = DATA_TYPE_UNKOWN;
 
-	if (cfg->samples == 0)
-		debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
+	return cfg;
+}
 
-	/* icu_output_buf can be NULL if rdcu compression is used */
-	if (cfg->icu_output_buf == NULL) {
-		debug_print("Error: The icu_output_buf buffer for the compressed data is NULL.\n");
-		cfg_invalid++;
-	}
 
-	if (cfg->buffer_length == 0 && cfg->samples != 0) {
-		debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n");
-		cfg_invalid++;
-	}
+/**
+ * @brief setup of the different data buffers for an ICU compression
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the cmp_cfg_icu_create() function)
+ * @param data_to_compress	pointer to the data to be compressed
+ * @param data_samples		length of the data to be compressed measured in
+ *				data samples/entitys (multi entity header not
+ *				included by imagette data)
+ * @param model_of_data		pointer to model data buffer (can be NULL if no
+ *				model compression mode is used)
+ * @param updated_model		pointer to store the updated model for the next
+ *				model mode compression (can be the same as the model_of_data
+ *				buffer for in-place update or NULL if updated model is not needed)
+ * @param compressed_data	pointer to the compressed data buffer (can be NULL)
+ * @param compressed_data_len_samples	length of the compressed_data buffer in
+ *					measured in the same units as the data_samples
+ *
+ * @returns the size of the compressed_data buffer on success; 0 if the
+ *	parameters are invalid
+ */
 
-	if (cfg->icu_output_buf == cfg->input_buf) {
-		debug_print("Error: The icu_output_buf buffer is the same as the input_buf buffer.\n");
-		cfg_invalid++;
+size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
+			   uint32_t data_samples, void *model_of_data,
+			   void *updated_model, uint32_t *compressed_data,
+			   uint32_t compressed_data_len_samples)
+{
+	if (!cfg) {
+		debug_print("Error: pointer to the compression configuration structure is NULL.\n");
+		return 0;
 	}
 
-	if (model_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->model_buf == NULL) {
-			debug_print("Error: The model_buf buffer for the model data is NULL.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->model_buf == cfg->input_buf) {
-			debug_print("Error: The model_buf buffer is the same as the input_buf buffer.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->model_buf == cfg->icu_output_buf) {
-			debug_print("Error: The model_buf buffer is the same as the icu_output_buf buffer.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->icu_new_model_buf == cfg->input_buf) {
-			debug_print("Error: The icu_new_model_buf buffer is the same as the input_buf buffer.\n");
-			cfg_invalid++;
-		}
-
-		if (cfg->icu_new_model_buf == cfg->icu_output_buf) {
-			debug_print("Error: The icu_output_buf buffer is the same as the icu_output_buf buffer.\n");
-			cfg_invalid++;
-		}
-	}
+	cfg->input_buf = data_to_compress;
+	cfg->model_buf = model_of_data;
+	cfg->samples = data_samples;
+	cfg->icu_new_model_buf = updated_model;
+	cfg->icu_output_buf = compressed_data;
+	cfg->buffer_length = compressed_data_len_samples;
 
-	if (raw_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->samples > cfg->buffer_length) {
-			debug_print("Error: The buffer_length is to small to hold the data form the input_buf.\n");
-			cfg_invalid++;
-		}
-	} else {
-		if (cfg->samples*size_of_a_sample(cfg->cmp_mode) <
-		    cfg->buffer_length*sizeof(uint16_t)/3) /* TODO: have samples and buffer_lengt the same unit */
-			debug_print("Warning: The size of the icu_output_buf is 3 times smaller than the input_buf. This is probably unintentional.\n");
-	}
+	if (!cmp_cfg_icu_buffers_is_valid(cfg))
+		return 0;
 
+	return cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type);
+}
 
-	if (!(diff_mode_is_used(cfg->cmp_mode)
-	     || model_mode_is_used(cfg->cmp_mode)
-	     || raw_mode_is_used(cfg->cmp_mode))) {
-		debug_print("Error: selected cmp_mode: %u is not supported\n.",
-			    cfg->cmp_mode);
-		if (info)
-			info->cmp_err |= 1UL << CMP_MODE_ERR_BIT;
-		cfg_invalid++;
-	}
 
-	if (raw_mode_is_used(cfg->cmp_mode)) /* additional checks are not needed for the raw mode */
-		return -cfg_invalid;
+/**
+ * @brief set up the configuration parameters for an ICU imagette compression
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the cmp_cfg_icu_create() function)
+ * @param cmp_par		imagette compression parameter (Golomb parameter)
+ * @param spillover_par		imagette spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
 
-	if (model_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->model_value > MAX_MODEL_VALUE) {
-			debug_print("Error: selected model_value: %u is invalid. Largest supported value is: %lu.\n",
-				    cfg->model_value, MAX_MODEL_VALUE);
-			if (info)
-				info->cmp_err |= 1UL << MODEL_VALUE_ERR_BIT;
-			cfg_invalid++;
-		}
-	}
+int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
+			 uint32_t spillover_par)
+{
+	if (!cfg)
+		return -1;
 
-	if (cfg->golomb_par < MIN_ICU_GOLOMB_PAR ||
-	    cfg->golomb_par > MAX_ICU_GOLOMB_PAR) {
-		debug_print("Error: The selected Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%lu, %u].\n",
-			    cfg->golomb_par, MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
-		if (info)
-			info->cmp_err |= 1UL << CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+	cfg->golomb_par = cmp_par;
+	cfg->spill = spillover_par;
 
-	if (cfg->spill < MIN_ICU_SPILL) {
-		debug_print("Error: The selected spillover threshold value: %u is too small. Smallest possible spillover value is: %lu.\n",
-			    cfg->spill, MIN_ICU_SPILL);
-		if (info)
-			info->cmp_err |= 1UL << CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+	if (!cmp_cfg_imagette_is_valid(cfg))
+		return -1;
 
-	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->cmp_mode)) {
-		debug_print("Error: The selected spillover threshold value: %u is too large for the selected Golomb parameter: %u, the largest possible spillover value in the selected compression mode is: %u.\n",
-			    cfg->spill, cfg->golomb_par,
-			    get_max_spill(cfg->golomb_par, cfg->cmp_mode));
-		if (info)
-			info->cmp_err |= 1UL << CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+	return 0;
+}
 
-#ifdef ADAPTIVE_CHECK_ENA
-	/*
-	 * ap1_spill and ap2_spill are not used for the icu_compression
-	 */
 
-	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->cmp_mode)) {
-		if (info)
-			info->cmp_err |= 1UL << AP1_CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
+/**
+ * @brief set up of the configuration parameters for a flux/COB compression
+ * @note not all parameters are needed for every flux/COB compression data type
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the cmp_cfg_icu_create() function)
+ * @param cmp_par_exp_flags	exposure flags compression parameter
+ * @param spillover_exp_flags	exposure flags spillover threshold parameter
+ * @param cmp_par_fx		normal flux compression parameter
+ * @param spillover_fx		normal flux spillover threshold parameter
+ * @param cmp_par_ncob		normal center of brightness compression parameter
+ * @param spillover_ncob	normal center of brightness spillover threshold parameter
+ * @param cmp_par_efx		extended flux compression parameter
+ * @param spillover_efx		extended flux spillover threshold parameter
+ * @param cmp_par_ecob		extended center of brightness compression parameter
+ * @param spillover_ecob	extended center of brightness spillover threshold parameter
+ * @param cmp_par_fx_cob_variance	flux/COB variance compression parameter
+ * @param spillover_fx_cob_variance	flux/COB variance spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
 
-	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->cmp_mode)) {
-		if (info)
-			info->cmp_err |= 1UL << AP2_CMP_PAR_ERR_BIT;
-		cfg_invalid++;
-	}
-#endif
+int cmp_cfg_fx_cob(struct cmp_cfg *cfg,
+		   uint32_t cmp_par_exp_flags, uint32_t spillover_exp_flags,
+		   uint32_t cmp_par_fx, uint32_t spillover_fx,
+		   uint32_t cmp_par_ncob, uint32_t spillover_ncob,
+		   uint32_t cmp_par_efx, uint32_t spillover_efx,
+		   uint32_t cmp_par_ecob, uint32_t spillover_ecob,
+		   uint32_t cmp_par_fx_cob_variance, uint32_t spillover_fx_cob_variance)
+{
+	if (!cfg)
+		return -1;
 
-	if (cfg->round > MAX_ICU_ROUND) {
-		debug_print("Error: selected round parameter: %u is not supported. Largest supported value is: %lu.\n",
-			    cfg->round, MAX_ICU_ROUND);
-		cfg_invalid++;
-	}
+	cfg->cmp_par_exp_flags = cmp_par_exp_flags;
+	cfg->cmp_par_fx = cmp_par_fx;
+	cfg->cmp_par_ncob = cmp_par_ncob;
+	cfg->cmp_par_efx = cmp_par_efx;
+	cfg->cmp_par_ecob = cmp_par_ecob;
+	cfg->cmp_par_fx_cob_variance = cmp_par_fx_cob_variance;
+
+	cfg->spill_exp_flags = spillover_exp_flags;
+	cfg->spill_fx = spillover_fx;
+	cfg->spill_ncob = spillover_ncob;
+	cfg->spill_efx = spillover_efx;
+	cfg->spill_ecob = spillover_ecob;
+	cfg->spill_fx_cob_variance = spillover_fx_cob_variance;
+
+	if (!cmp_cfg_fx_cob_is_valid(cfg))
+		return -1;
 
-	return -(cfg_invalid);
+	return 0;
 }
 
 
 /**
- * @brief sets the compression information used based on the compression
- *	configuration
- *
- * @param cfg	compression configuration struct
- * @param info	compressor information struct to set the used compression
- *	parameters (can be NULL)
- *
- * @note set cmp_size, ap1_cmp_size, ap2_cmp_size will be set to 0
- *
- * @returns 0 on success, error otherwise
+ * @brief set up of the configuration parameters for an auxiliary science data compression
+ * @note auxiliary compression data types are: DATA_TYPE_OFFSET, DATA_TYPE_BACKGROUND,
+	DATA_TYPE_SMEARING, DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND
+ * @note not all parameters are needed for the every auxiliary compression data types
+ *
+ * @param cfg				pointer to a compression configuration (
+ *					created with the cmp_cfg_icu_create() function)
+ * @param cmp_par_mean			mean compression parameter
+ * @param spillover_mean		mean spillover threshold parameter
+ * @param cmp_par_variance		variance compression parameter
+ * @param spillover_variance		variance spillover threshold parameter
+ * @param cmp_par_pixels_error		outlier pixels number compression parameter
+ * @param spillover_pixels_error	outlier pixels number spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
  */
 
-
-static int set_info(struct cmp_cfg *cfg, struct cmp_info *info)
+int cmp_cfg_aux(struct cmp_cfg *cfg,
+		uint32_t cmp_par_mean, uint32_t spillover_mean,
+		uint32_t cmp_par_variance, uint32_t spillover_variance,
+		uint32_t cmp_par_pixels_error, uint32_t spillover_pixels_error)
 {
 	if (!cfg)
 		return -1;
 
-	if (cfg->cmp_mode > UINT8_MAX)
-		return -1;
+	cfg->cmp_par_mean = cmp_par_mean;
+	cfg->cmp_par_variance = cmp_par_variance;
+	cfg->cmp_par_pixels_error = cmp_par_pixels_error;
 
-	if (cfg->round > UINT8_MAX)
-		return -1;
+	cfg->spill_mean = spillover_mean;
+	cfg->spill_variance = spillover_variance;
+	cfg->spill_pixels_error = spillover_pixels_error;
 
-	if (cfg->model_value > UINT8_MAX)
+	if (!cmp_cfg_aux_is_valid(cfg))
 		return -1;
 
-	if (info) {
-		info->cmp_err = 0;
-		info->cmp_mode_used = (uint8_t)cfg->cmp_mode;
-		info->model_value_used = (uint8_t)cfg->model_value;
-		info->round_used = (uint8_t)cfg->round;
-		info->spill_used = cfg->spill;
-		info->golomb_par_used = cfg->golomb_par;
-		info->samples_used = cfg->samples;
-		info->cmp_size = 0;
-		info->ap1_cmp_size = 0;
-		info->ap2_cmp_size = 0;
-		info->rdcu_new_model_adr_used = cfg->rdcu_new_model_adr;
-		info->rdcu_cmp_adr_used = cfg->rdcu_buffer_adr;
-	}
 	return 0;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a uint16_t data buffer
- *
- * @note change the data_buf in-place
- * @note output is I[0] = I[0], I[i] = I[i] - I[i-1], where i is 1,2,..samples-1
+ * @brief map a signed value into a positive value range
  *
- * @param data_buf	pointer to the uint16_t formatted data buffer to process
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value_to_map	signed value to map
+ * @param max_data_bits	how many bits are needed to represent the
+ *			highest possible value
  *
- * @returns 0 on success, error otherwise
+ * @returns the positive mapped value
  */
 
-static int diff_16(uint16_t *data_buf, unsigned int samples, unsigned int round)
+static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits)
 {
-	size_t i;
-
-	if (!data_buf)
-		return -1;
-
-	lossy_rounding_16(data_buf, samples, round);
-
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data_buf[i] = data_buf[i] - data_buf[i-1];
+	uint32_t result;
+	uint32_t mask = (~0U >> (32 - max_data_bits)); /* mask the used bits */
+
+	value_to_map &= mask;
+	if (value_to_map >> (max_data_bits - 1)) { /* check the leading signed bit */
+		value_to_map |= ~mask; /* convert to 32-bit signed integer */
+		/* map negative values to uneven numbers */
+		result = (-value_to_map) * 2 - 1; /* possible integer overflow is intended */
+	} else {
+		/* map positive values to even numbers */
+		result = value_to_map * 2; /* possible integer overflow is intended */
 	}
-	return 0;
+
+	return result;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a uint32_t data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
- *
- * @param data_buf	pointer to the uint32_t formatted data buffer to process
- * @param samples	amount of data samples in the data_buf buffer
- * @param round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
+ * @brief put the value of up to 32 bits into a bitstream
+ *
+ * @param value			the value to put
+ * @param n_bits		number of bits to put in the bitstream
+ * @param bit_offset		bit index where the bits will be put, seen from
+ *				the very beginning of the bitstream
+ * @param bitstream_adr		this is the pointer to the beginning of the
+ *				bitstream (can be NULL)
+ * @param max_stream_len	maximum length of the bitstream in bits; is
+ *				ignored if bitstream_adr is NULL
+ *
+ * @returns length in bits of the generated bitstream on success; returns
+ *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
+ *          the bitstream buffer is too small to put the value in the bitstream
  */
 
-static int diff_32(uint32_t *data_buf, unsigned int samples, unsigned int round)
+static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
+			uint32_t *bitstream_adr, unsigned int max_stream_len)
 {
-	size_t i;
+	uint32_t *local_adr;
+	uint32_t mask;
+	unsigned int shiftRight, shiftLeft, bitsLeft, bitsRight;
+	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
 
-	if (!data_buf)
+	/* Leave in case of erroneous input */
+	if (bit_offset < 0)
 		return -1;
 
-	lossy_rounding_32(data_buf, samples, round);
+	if (n_bits == 0)
+		return stream_len;
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data_buf[i] = data_buf[i] - data_buf[i-1];
+	if (n_bits > 32)
+		return -1;
+
+	/* Do we need to write data to the bitstream? */
+	if (!bitstream_adr)
+		return stream_len;
+
+	/* Check if bitstream buffer is large enough */
+	if ((unsigned int)stream_len > max_stream_len) {
+		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
+		return CMP_ERROR_SAMLL_BUF;
 	}
-	return 0;
-}
 
+	/* (M) is the n_bits parameter large enough to cover all value bits; the
+	 * calculations can be re-used in the unsegmented code, so we have no overhead
+	 */
+	shiftRight = 32 - n_bits;
+	mask = 0xFFFFFFFFU >> shiftRight;
+	value &= mask;
 
-/**
- * @brief 1d-differentiating pre-processing and round of a S_FX data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
- *
- * @param data		pointer to a S_FX data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
+	/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
+	local_adr = bitstream_adr + (bit_offset >> 5);
+	bitsLeft = bit_offset & 0x1F;
 
-static int diff_S_FX(struct S_FX *data, unsigned int samples, unsigned int
-		     round)
-{
-	size_t i;
-	int err;
+	/* Calculate the bitsRight for the unsegmented case. If bitsRight is
+	 * negative we need to split the value over two words
+	 */
+	bitsRight = shiftRight - bitsLeft;
 
-	if (!data)
-		return -1;
+	if ((int)bitsRight >= 0) {
+		/*         UNSEGMENTED
+		 *
+		 *|-----------|XXXXX|----------------|
+		 *   bitsLeft    n       bitsRight
+		 *
+		 *  -> to get the mask:
+		 *  shiftRight = bitsLeft + bitsRight = 32 - n
+		 *  shiftLeft = bitsRight = 32 - n - bitsLeft = shiftRight - bitsLeft
+		 */
 
-	err = lossy_rounding_S_FX(data, samples, round);
-	if (err)
-		return err;
+		shiftLeft = bitsRight;
+
+		/* generate the mask, the bits for the values will be true
+		 * shiftRight = 32 - n_bits; see (M) above!
+		 * mask = (0XFFFFFFFF >> shiftRight) << shiftLeft; see (M) above!
+		 */
+		mask <<= shiftLeft;
+		value <<= shiftLeft;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value */
+		*(local_adr) |= value;
+
+	} else {
+		/*                             SEGMENTED
+		 *
+		 *|-----------------------------|XXX| |XX|------------------------------|
+		 *          bitsLeft              n1   n2          bitsRight
+		 *
+		 *  -> to get the mask part 1:
+		 *  shiftRight = bitsLeft
+		 *  n1 = n - (bitsLeft + n - 32) = 32 - bitsLeft
+		 *
+		 *  -> to get the mask part 2:
+		 *  n2 = bitsLeft + n - 32 = -(32 - n - bitsLeft) = -(bitsRight_UNSEGMENTED)
+		 *  shiftLeft = 32 - n2 = 32 - (bitsLeft + n - 32) = 64 - bitsLeft - n
+		 *
+		 */
+
+		unsigned int n2 = -bitsRight;
+
+		/* part 1: */
+		shiftRight = bitsLeft;
+		mask = 0XFFFFFFFFU >> shiftRight;
+
+		/* clear the destination with inverse mask */
+		*(local_adr) &= ~mask;
+
+		/* assign the value part 1 */
+		*(local_adr) |= (value >> n2);
+
+		/* part 2: */
+		/* adjust address */
+		local_adr += 1;
+		shiftLeft = 32 - n2;
+		mask = 0XFFFFFFFFU >> n2;
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX(data[i], data[i-1]);
+		/* clear the destination */
+		*(local_adr) &= mask;
+
+		/* assign the value part 2 */
+		*(local_adr) |= (value << shiftLeft);
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a S_FX_EFX data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
+ * @brief forms the codeword according to the Rice code
  *
- * @param data		pointer to a S_FX_EFX data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value		value to be encoded
+ * @param m		Golomb parameter, only m's which are power of 2 are allowed
+ * @param log2_m	Rice parameter, is log_2(m) calculate outside function
+ *			for better performance
+ * @param cw		address were the encode code word is stored
  *
- * @returns 0 on success, error otherwise
+ * @returns the length of the formed code word in bits
+ * @note no check if the generated code word is not longer than 32 bits!
  */
 
-static int diff_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples, unsigned
-			 int round)
+static uint32_t rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
+			     uint32_t *cw)
 {
-	size_t i;
-	int err;
+	uint32_t g;  /* quotient of value/m */
+	uint32_t q;  /* quotient code without ending zero */
+	uint32_t r;  /* remainder of value/m */
+	uint32_t rl; /* remainder length */
 
-	if (!data)
-		return -1;
+	g = value >> log2_m; /* quotient, number of leading bits */
+	q = (1U << g) - 1;   /* prepare the quotient code without ending zero */
 
-	err = lossy_rounding_S_FX_EFX(data, samples, round);
-	if (err)
-		return err;
+	r = value & (m-1);   /* calculate the remainder */
+	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the quotient code) */
+	*cw = (q << rl) | r; /* put the quotient and remainder code together */
+	/*
+	 * NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined
+	 * behavior. However, in this case, a valid code with a maximum of 32
+	 * bits can only be formed if q = 0. Any shift with 0 << x always
+	 * results in 0, which forms the correct codeword in this case. For
+	 * performance reasons, this undefined behaviour is not caught.
+	 */
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX_EFX(data[i], data[i-1]);
-	}
-	return 0;
+	return rl + g;	      /* calculate the length of the code word */
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a S_FX_NCOB data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
+ * @brief forms a codeword according to the Golomb code
  *
- * @param data		pointer to a S_FX_NCOB data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value		value to be encoded
+ * @param m		Golomb parameter (have to be bigger than 0)
+ * @param log2_m	is log_2(m) calculate outside function for better
+ *			performance
+ * @param cw		address were the formed code word is stored
  *
- * @returns 0 on success, error otherwise
+ * @returns the length of the formed code word in bits
+ * @note no check if the generated code word is not longer than 32 bits!
  */
 
-static int diff_S_FX_NCOB(struct S_FX_NCOB *data, unsigned int samples, unsigned
-			  int round)
+static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
+			       uint32_t *cw)
 {
-	size_t i;
-	int err;
-
-	if (!data)
-		return -1;
+	uint32_t len0, b, g, q, lg;
+	uint32_t len;
+	uint32_t cutoff;
 
-	err = lossy_rounding_S_FX_NCOB(data, samples, round);
-	if (err)
-		return err;
+	len0 = log2_m + 1;                 /* codeword length in group 0 */
+	cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */
 
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX_NCOB(data[i], data[i-1]);
+	if (value < cutoff) { /* group 0 */
+		*cw = value;
+		len = len0;
+	} else { /* other groups */
+		g = (value-cutoff) / m; /* this group is which one */
+		b = cutoff << 1;        /* form the base codeword */
+		lg = len0 + g;          /* it has lg remainder bits */
+		q = (1U << g) - 1;      /* prepare the left side in unary */
+		*cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */
+		len = lg + 1;           /* length of the codeword */
 	}
-	return 0;
+	return len;
 }
 
 
 /**
- * @brief 1d-differentiating pre-processing and rounding of a S_FX_EFX_NCOB_ECOB data buffer
- *
- * @note change the data_buf in-place
- * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
+ * @brief generate a code word without an outlier mechanism and put in the
+ *	bitstream
  *
- * @param data		pointer to a S_FX_EFX_NCOB_ECOB data buffer
- * @param samples	amount of data samples in the data buffer
- * @param round		number of bits to round; if zero no rounding takes place
+ * @param value		value to encode in the bitstream
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  */
 
-static int diff_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data, unsigned int
-				   samples, unsigned int round)
+static int encode_normal(uint32_t value, int stream_len,
+			 const struct encoder_setupt *setup)
 {
-	size_t i;
-	int err;
-
-	if (!data)
-		return -1;
+	uint32_t code_word, cw_len;
 
-	err = lossy_rounding_S_FX_EFX_NCOB_ECOB(data, samples, round);
-	if (err)
-		return err;
-
-	for (i = samples - 1; i > 0; i--) {
-		/* possible underflow is intended */
-		data[i] = sub_S_FX_EFX_NCOB_ECOB(data[i], data[i-1]);
-	}
+	cw_len = setup->generate_cw_f(value, setup->encoder_par1,
+				      setup->encoder_par2, &code_word);
 
-	return 0;
+	return put_n_bits32(code_word, cw_len, stream_len, setup->bitstream_adr,
+			    setup->max_stream_len);
 }
 
 
 /**
- * @brief model pre-processing and rounding of a uint16_t data buffer
+ * @brief subtract the model from the data, encode the result and put it into
+ *	bitstream, for encoding outlier use the zero escape symbol mechanism
  *
- * @note overwrite the data_buf in-place with the result
- * @note update the model_buf in-place if up_model_buf = NULL
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param model_buf	pointer to the model buffer of the data to process
- * @param up_model_buf	pointer to the updated model buffer can be NULL
- * @param samples	amount of data samples in the data_buf and model_buf buffer
- * @param model_value	model weighting parameter
- * @param round		number of bits to round; if zero no rounding takes place
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
- * @returns 0 on success, error otherwise
+ * @note no check if the data or model are in the allowed range
+ * @note no check if the setup->spillover_par is in the allowed range
  */
 
-static int model_16(uint16_t *data_buf, uint16_t *model_buf, uint16_t *up_model_buf,
-		    unsigned int samples, unsigned int model_value, unsigned int round)
+static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
+			     const struct encoder_setupt *setup)
 {
-	size_t i;
+	data -= model; /* possible underflow is intended */
 
-	if (!data_buf)
-		return -1;
+	data = map_to_pos(data, setup->max_data_bits);
 
-	if (!model_buf)
-		return -1;
+	/* For performance reasons, we check to see if there is an outlier
+	 * before adding one, rather than the other way around:
+	 * data++;
+	 * if (data < setup->spillover_par && data != 0)
+	 *	return ...
+	 */
+	if (data < (setup->spillover_par - 1)) { /* detect non-outlier */
+		data++; /* add 1 to every value so we can use 0 as escape symbol */
+		return encode_normal(data, stream_len, setup);
+	}
 
-	if (model_value > MAX_MODEL_VALUE)
-		return -1;
+	data++; /* add 1 to every value so we can use 0 as escape symbol */
 
-	if (!up_model_buf)
-		up_model_buf = model_buf;
+	/* use zero as escape symbol */
+	stream_len = encode_normal(0, stream_len, setup);
+	if (stream_len <= 0)
+		return stream_len;
 
-	for (i = 0; i < samples; i++) {
-		uint16_t round_input = (uint16_t)round_fwd(data_buf[i], round);
-		uint16_t round_model = (uint16_t)round_fwd(model_buf[i], round);
-		/* possible underflow is intended */
-		data_buf[i] = round_input - round_model; /* TDOO: check if this is the right order */
-		/* round back input because for decompression the accurate data
-		 * are not available
-		 */
-		up_model_buf[i] = (uint16_t)cal_up_model(round_inv(round_input, round),
-							 model_buf[i], model_value);
-	}
-	return 0;
+	/* put the data unencoded in the bitstream */
+	stream_len = put_n_bits32(data, setup->max_data_bits, stream_len,
+				  setup->bitstream_adr, setup->max_stream_len);
+
+	return stream_len;
 }
 
 
 /**
- * @brief model pre-processing and round_input of a uint32_t data buffer
+ * @brief subtract the model from the data, encode the result and put it into
+ *	bitstream, for encoding outlier use the multi escape symbol mechanism
  *
- * @note overwrite the data_buf in-place with the result
- * @note update the model_buf in-place if up_model_buf = NULL
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @param data_buf	pointer to the uint32_t data buffer to process
- * @param model_buf	pointer to the model buffer of the data to process
- * @param samples	amount of data samples in the data_buf and model_buf buffer
- * @param model_value	model weighting parameter
- * @param round		number of bits to round; if zero no rounding takes place
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
- * @returns 0 on success, error otherwise
+ * @note no check if the data or model are in the allowed range
+ * @note no check if the setup->spillover_par is in the allowed range
  */
 
-static int model_32(uint32_t *data_buf, uint32_t *model_buf, unsigned int samples,
-		    unsigned int model_value, unsigned int round)
+static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
+			      const struct encoder_setupt *setup)
 {
-	size_t i;
+	uint32_t unencoded_data;
+	unsigned int unencoded_data_len;
+	uint32_t escape_sym, escape_sym_offset;
 
-	if (!data_buf)
-		return -1;
+	data -= model; /* possible underflow is intended */
 
-	if (!model_buf)
-		return -1;
+	data = map_to_pos(data, setup->max_data_bits);
 
-	if (model_value > MAX_MODEL_VALUE)
-		return -1;
+	if (data < setup->spillover_par) /* detect non-outlier */
+		return  encode_normal(data, stream_len, setup);
 
-	for (i = 0; i < samples; i++) {
-		uint32_t round_input = round_fwd(data_buf[i], round);
-		uint32_t round_model = round_fwd(model_buf[i], round);
-		/* possible underflow is intended */
-		data_buf[i] = round_input - round_model;
-		/* round back input because for decompression the accurate data
-		 * are not available
-		 */
-		model_buf[i] = cal_up_model(round_inv(round_input, round),
-					    model_buf[i], model_value);
-	}
-	return 0;
+	/*
+	 * In this mode we put the difference between the data and the spillover
+	 * threshold value (unencoded_data) after an encoded escape symbol, which
+	 * indicate that the next codeword is unencoded.
+	 * We use different escape symbol depended on the size the needed bit of
+	 * unencoded data:
+	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is spillover_par + 0
+	 * 3, 4 bits needed for unencoded data -> escape symbol is spillover_par + 1
+	 * 5, 6 bits needed for unencoded data -> escape symbol is spillover_par + 2
+	 * and so on
+	 */
+	unencoded_data = data - setup->spillover_par;
+
+	if (!unencoded_data) /* catch __builtin_clz(0) because the result is undefined.*/
+		escape_sym_offset = 0;
+	else
+		escape_sym_offset = (31U - (uint32_t)__builtin_clz(unencoded_data)) >> 1;
+
+	escape_sym = setup->spillover_par + escape_sym_offset;
+	unencoded_data_len = (escape_sym_offset + 1U) << 1;
+
+	/* put the escape symbol in the bitstream */
+	stream_len = encode_normal(escape_sym, stream_len, setup);
+	if (stream_len <= 0)
+		return stream_len;
+
+	/* put the unencoded data in the bitstream */
+	stream_len = put_n_bits32(unencoded_data, unencoded_data_len, stream_len,
+				  setup->bitstream_adr, setup->max_stream_len);
+
+	return stream_len;
 }
 
 
 /**
- * @brief model pre-processing and round_input of a S_FX data buffer
+ * @brief put the value unencoded with(setup->cmp_par_1 bits without any changes
+ *	in the bitstream
  *
- * @note overwrite the data_buf in-place with the result
- * @note update the model_buf in-place if up_model_buf = NULL
+ * @param value		value to put unchanged in the bitstream
+ *	(setup->cmp_par_1 how many bits of the value are used)
+ * @param unused	this parameter is ignored
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
  *
- * @param data_buf	pointer to the S_FX data buffer to process
- * @param model_buf	pointer to the updated model buffer (if NULL model_buf
- *	will be overwrite with the updated model)
- * @param samples	amount of data samples in the data_buf and model_buf buffer
- * @param model_value	model weighting parameter
- * @param round		number of bits to round; if zero no rounding takes place
+ * @returns the bit length of the bitstream with the added unencoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream
  *
- * @returns 0 on success, error otherwise
  */
 
-int model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf,
-		      struct S_FX *up_model_buf, unsigned int samples,
-		      unsigned int model_value, unsigned int round)
+static int encode_value_none(uint32_t value, uint32_t unused, int stream_len,
+			     const struct encoder_setupt *setup)
 {
-	size_t i;
-
-	if (!samples)
-		return 0;
+	(void)(unused);
 
-	if (!model_buf)
-		return -1;
+	return put_n_bits32(value, setup->encoder_par1, stream_len,
+			    setup->bitstream_adr, setup->max_stream_len);
+}
 
-	if (model_value > MAX_MODEL_VALUE)
-		return -1;
 
-	if (!up_model_buf)  /* overwrite the model buffer if no up_model_buf is set */
-		up_model_buf = model_buf;
+/**
+ * @brief encodes the data with the model and the given setup and put it into
+ *	the bitstream
+ *
+ * @param data		data to encode
+ * @param model		model of the data (0 if not used)
+ * @param stream_len	length of the bitstream in bits
+ * @param setup		pointer to the encoder setup
+ *
+ * @returns the bit length of the bitstream with the added encoded value on
+ *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	is too small to put the value in the bitstream, CMP_ERROR_HIGH_VALUE if
+ *	the value or the model is bigger than the max_used_bits parameter allows
+ */
 
+static int encode_value(uint32_t data, uint32_t model, int stream_len,
+			const struct encoder_setupt *setup)
+{
+	uint32_t mask = ~(0xFFFFFFFFU >> (32-setup->max_data_bits));
 
-	for (i = 0; i < samples; i++) {
-		struct S_FX round_data = data_buf[i];
-		struct S_FX round_model = model_buf[i];
-		int err;
+	/* lossy rounding of the data if lossy_par > 0 */
+	data = round_fwd(data, setup->lossy_par);
+	model = round_fwd(model, setup->lossy_par);
 
-		err = lossy_rounding_S_FX(&round_data, 1, round);
-		if (err)
-			return err;
+	if (data & mask || model & mask) {
+		debug_print("Error: The data or the model of the data are bigger than expected.\n");
+		return CMP_ERROR_HIGH_VALUE;
+	}
 
-		err = lossy_rounding_S_FX(&round_model, 1, round);
-		if (err)
-			return err;
+	return setup->encode_method_f(data, model, stream_len, setup);
+}
 
-		/* possible underflow is intended */
-		data_buf[i] = sub_S_FX(round_data, round_model);
 
-		/* round back input because for decompression the accurate data
-		 * are not available
-		 */
-		err = de_lossy_rounding_S_FX(&round_data, 1, round);
-		if (err)
-			return err;
-		up_model_buf[i] = cal_up_model_S_FX(round_data, model_buf[i],
-						    model_value);
-	}
+/**
+ * @brief calculate the maximum length of the bitstream/icu_output_buf in bits
+ * @note we round down to the next 4-byte allied address because we access the
+ *	cmp_buffer in uint32_t words
+ *
+ * @param buffer_length	length of the icu_output_buf in samples
+ * @param data_type	used compression data type
+ *
+ * @returns buffer size in bits
+ *
+ */
 
-	return 0;
+static uint32_t cmp_buffer_length_to_bits(uint32_t buffer_length, enum cmp_data_type data_type)
+{
+	return (cmp_cal_size_of_data(buffer_length, data_type) & ~0x3U) * CHAR_BIT;
 }
 
 
 /**
- * @brief data pre-processing to decorrelate the data
+ * @brief configure an encoder setup structure to have a setup to encode a vale
  *
- * @param cfg	configuration contains all parameters required for compression
+ * @param setup		pointer to the encoder setup
+ * @param cmp_par	compression parameter
+ * @param spillover	spillover_par parameter
+ * @param lossy_par	lossy compression parameter
+ * @param max_data_bits	how many bits are needed to represent the highest possible value
+ * @param cfg		pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns 0 on success; otherwise error
  */
 
-int cmp_pre_process(struct cmp_cfg *cfg)
+static int configure_encoder_setup(struct encoder_setupt *setup,
+				   uint32_t cmp_par, uint32_t spillover,
+				   uint32_t lossy_par, uint32_t max_data_bits,
+				   const struct cmp_cfg *cfg)
 {
-	if (!cfg)
+	if (!setup)
 		return -1;
 
-	if (cfg->samples == 0)
-		return 0;
+	if (!cfg)
+		return -1;
 
-	if (!cfg->input_buf)
+	setup->encoder_par1 = cmp_par;
+	setup->spillover_par = spillover;
+	if (max_data_bits > 32) {
+		debug_print("Error: max_data_bits parameter is bigger than 32 bits.\n");
 		return -1;
+	}
+	setup->max_data_bits = max_data_bits;
+	setup->lossy_par = lossy_par;
 
 	switch (cfg->cmp_mode) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return 0; /* in raw mode no pre-processing is necessary */
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-		return model_16((uint16_t *)cfg->input_buf, (uint16_t *)cfg->model_buf,
-				(uint16_t *)cfg->icu_new_model_buf, cfg->samples,
-				cfg->model_value, cfg->round);
-		break;
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return diff_16((uint16_t *)cfg->input_buf, cfg->samples,
-			       cfg->round);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-		return model_S_FX((struct S_FX *)cfg->input_buf, (struct S_FX *)cfg->model_buf,
-				  (struct S_FX *)cfg->icu_new_model_buf, cfg->samples,
-				  cfg->model_value, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return diff_S_FX((struct S_FX *)cfg->input_buf, cfg->samples, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return diff_S_FX_EFX((struct S_FX_EFX *)cfg->input_buf,
-				     cfg->samples, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return diff_S_FX_NCOB((struct S_FX_NCOB *)cfg->input_buf,
-				      cfg->samples, cfg->round);
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_DIFF_ZERO:
+		setup->encode_method_f = &encode_value_zero;
+		if (ilog_2(cmp_par) < 0)
+			return -1;
+		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
 		break;
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return diff_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)cfg->input_buf,
-					       cfg->samples, cfg->round);
+	case CMP_MODE_MODEL_MULTI:
+	case CMP_MODE_DIFF_MULTI:
+		setup->encode_method_f = &encode_value_multi;
+		if (ilog_2(cmp_par) < 0)
+			return -1;
+		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
 		break;
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-		return model_32((uint32_t *)cfg->input_buf, (uint32_t *)cfg->model_buf,
-				cfg->samples, cfg->model_value, cfg->round);
-		break;
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return diff_32((uint32_t *)cfg->input_buf, cfg->samples, cfg->round);
+	case CMP_MODE_STUFF:
+		setup->encode_method_f = &encode_value_none;
+		setup->max_data_bits = cmp_par;
 		break;
 	default:
-		debug_print("Error: Compression mode not supported.\n");
+		return -1;
 	}
 
-	return -1;
-}
-
-
-static uint8_t map_to_pos_alg_8(int8_t value_to_map)
-{
-	if (value_to_map < 0)
-		/* NOTE: possible integer overflow is intended */
-		return (uint8_t)((-value_to_map) * 2 - 1);
-	else
-		/* NOTE: possible integer overflow is intended */
-		return (uint8_t)(value_to_map * 2);
-}
-
-
-static uint16_t map_to_pos_alg_16(int16_t value_to_map)
-{
-	if (value_to_map < 0)
-		/* NOTE: possible integer overflow is intended */
-		return (uint16_t)((-value_to_map) * 2 - 1);
+	/* for encoder_par1 which are a power of two we can use the faster rice_encoder */
+	if (is_a_pow_of_2(setup->encoder_par1))
+		setup->generate_cw_f = &rice_encoder;
 	else
-		/* NOTE: possible integer overflow is intended */
-		return (uint16_t)(value_to_map * 2);
-}
+		setup->generate_cw_f = &golomb_encoder;
 
+	setup->bitstream_adr = cfg->icu_output_buf;
+	setup->max_stream_len = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
 
-static uint32_t map_to_pos_alg_32(int32_t value_to_map)
-{
-	if (value_to_map < 0)
-		/* NOTE: possible integer overflow is intended */
-		return (uint32_t)((-value_to_map) * 2 - 1);
-	else
-		/* NOTE: possible integer overflow is intended */
-		return (uint32_t)(value_to_map * 2);
+	return 0;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a 16 bit buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress imagette data
  *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream, CMP_ERROR_HIGH_VALUE if the value or the model is
+ *	bigger than the max_used_bits parameter allows
  */
 
-static int map_to_pos_16(uint16_t *data_buf, uint32_t samples, int zero_mode_used)
+static int compress_imagette(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
+	struct encoder_setupt setup;
+
+	uint16_t *data_buf = cfg->input_buf;
+	uint16_t *model_buf = cfg->model_buf;
+	uint16_t model = 0;
+	uint16_t *next_model_p = data_buf;
+	uint16_t *up_model_buf = NULL;
+
+	if (cfg->samples == 0)
+		return 0;
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+		up_model_buf = cfg->icu_new_model_buf;
+	}
 
-	if (!data_buf)
+	err = configure_encoder_setup(&setup, cfg->golomb_par, cfg->spill,
+				      cfg->round, max_used_bits.nc_imagette, cfg);
+	if (err)
 		return -1;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i] = map_to_pos_alg_16(data_buf[i]);
-		if (zero_mode_used)
-			data_buf[i] += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i], model, stream_len, &setup);
+		if (stream_len <= 0)
+			break;
+
+		if (up_model_buf)
+			up_model_buf[i] = cmp_up_model(data_buf[i], model, cfg->model_value,
+						       setup.lossy_par);
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a 32 bit buffer
+ * @brief compress the multi-entry packet header structure and sets the data,
+ *	model and up_model pointers to the data after the header
  *
- * @note overwrite the data_buf in-place with the result
+ * @param data		pointer to a pointer pointing to the data to be compressed
+ * @param model		pointer to a pointer pointing to the model of the data
+ * @param up_model	pointer to a pointer pointing to the updated model buffer
+ * @param cfg		pointer to the compression configuration structure
  *
- * @param data_buf	pointer to the uint32_t data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @returns the bit length of the bitstream on success; negative on error,
  *
- * @returns 0 on success, error otherwise
+ * @note the (void **) cast relies on all pointer types having the same internal
+ *	representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html
  */
 
-static int map_to_pos_32(uint32_t *data_buf, uint32_t samples, int
-			 zero_mode_used)
+static int compress_multi_entry_hdr(void **data, void **model, void **up_model,
+				    const struct cmp_cfg *cfg)
 {
-	size_t i;
-
-	if (!data_buf)
+	if (cfg->buffer_length < 1)
 		return -1;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i] = map_to_pos_alg_32(data_buf[i]);
-		if (zero_mode_used)
-			data_buf[i] += 1;
+	if (*data) {
+		if (cfg->icu_output_buf)
+			memcpy(cfg->icu_output_buf, *data, MULTI_ENTRY_HDR_SIZE);
+		*data = (uint8_t *)*data + MULTI_ENTRY_HDR_SIZE;
 	}
-	return 0;
+
+	if (*model)
+		*model = (uint8_t *)*model + MULTI_ENTRY_HDR_SIZE;
+
+	if (*up_model) {
+		if (*data)
+			memcpy(*up_model, *data, MULTI_ENTRY_HDR_SIZE);
+		*up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE;
+	}
+
+	return MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress short normal light flux (S_FX) data
  *
- * @param data_buf	pointer to the S_FX data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-int map_to_pos_S_FX(struct S_FX *data_buf, uint32_t samples, int
-			   zero_mode_used)
+static int compress_s_fx(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
+	struct s_fx *data_buf = cfg->input_buf;
+	struct s_fx *model_buf = cfg->model_buf;
+	struct s_fx *up_model_buf = NULL;
+	struct s_fx *next_model_p;
+	struct s_fx model;
+	struct encoder_setupt setup_exp_flag, setup_fx;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
 
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX_EFX buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress S_FX_EFX data
  *
- * @param data_buf	pointer to the S_FX_EFX data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static int map_to_pos_S_FX_EFX(struct S_FX_EFX *data_buf, uint32_t samples, int
-			       zero_mode_used)
+static int compress_s_fx_efx(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
+	struct s_fx_efx *data_buf = cfg->input_buf;
+	struct s_fx_efx *model_buf = cfg->model_buf;
+	struct s_fx_efx *up_model_buf = NULL;
+	struct s_fx_efx *next_model_p;
+	struct s_fx_efx model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_efx;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].EFX = map_to_pos_alg_32(data_buf[i].EFX);
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.s_efx, cfg);
+	if (err)
+		return -1;
 
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
-			data_buf[i].EFX += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX_NCOB buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress S_FX_NCOB data
  *
- * @param data_buf	pointer to the S_FX_NCOB data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static int map_to_pos_S_FX_NCOB(struct S_FX_NCOB *data_buf, uint32_t samples,
-				int zero_mode_used)
+static int compress_s_fx_ncob(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
+	struct s_fx_ncob *data_buf = cfg->input_buf;
+	struct s_fx_ncob *model_buf = cfg->model_buf;
+	struct s_fx_ncob *up_model_buf = NULL;
+	struct s_fx_ncob *next_model_p;
+	struct s_fx_ncob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob;
 
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = map_to_pos_alg_32(data_buf[i].NCOB_Y);
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.s_ncob, cfg);
+	if (err)
+		return -1;
 
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
-			data_buf[i].NCOB_X += 1;
-			data_buf[i].NCOB_Y += 1;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range for a S_FX_EFX_NCOB_ECOB buffer
- *
- * @note overwrite the data_buf in-place with the result
+ * @brief compress S_FX_EFX_NCOB_ECOB data
  *
- * @param data_buf	pointer to the S_FX_EFX_NCOB_ECOB data buffer to process
- * @param samples	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static int map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					 uint32_t samples, int zero_mode_used)
+static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 {
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples; i++) {
-		data_buf[i].EXPOSURE_FLAGS =
-			map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = map_to_pos_alg_32(data_buf[i].NCOB_Y);
-		data_buf[i].EFX = map_to_pos_alg_32(data_buf[i].EFX);
-		data_buf[i].ECOB_X = map_to_pos_alg_32(data_buf[i].ECOB_X);
-		data_buf[i].ECOB_Y = map_to_pos_alg_32(data_buf[i].ECOB_Y);
-
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS += 1; */
-			data_buf[i].FX += 1;
-			data_buf[i].NCOB_X += 1;
-			data_buf[i].NCOB_Y += 1;
-			data_buf[i].EFX += 1;
-			data_buf[i].ECOB_X += 1;
-			data_buf[i].ECOB_Y += 1;
+	struct s_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct s_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct s_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct s_fx_efx_ncob_ecob *next_model_p;
+	struct s_fx_efx_ncob_ecob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_efx,
+			      setup_ecob;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.s_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.s_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.s_ncob, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.s_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				      cfg->round, max_used_bits.s_ecob, cfg);
+	if (err)
+		return -1;
+
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
 /**
- * @brief map the signed output of the pre-processing stage to a unsigned value
- *	range
+ * @brief compress F_FX data
  *
- * @note change the data_buf in-place
+ * @param cfg	pointer to the compression configuration structure
  *
- * @param cfg	configuration contains all parameters required for compression
- *
- * @returns 0 on success, error otherwise
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-int cmp_map_to_pos(struct cmp_cfg *cfg)
+static int compress_f_fx(const struct cmp_cfg *cfg)
 {
-	int zero_mode_used;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!cfg)
-		return -1;
+	struct f_fx *data_buf = cfg->input_buf;
+	struct f_fx *model_buf = cfg->model_buf;
+	struct f_fx *up_model_buf = NULL;
+	struct f_fx *next_model_p;
+	struct f_fx model;
+	struct encoder_setupt setup_fx;
 
-	if (cfg->samples == 0)
-		return 0;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (!cfg->input_buf)
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
 		return -1;
 
-	zero_mode_used = zero_escape_mech_is_used(cfg->cmp_mode);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
 
-	switch (cfg->cmp_mode) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return 0; /* in raw mode no mapping is necessary */
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return map_to_pos_16((uint16_t *)cfg->input_buf, cfg->samples,
-				     zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return map_to_pos_S_FX((struct S_FX *)cfg->input_buf,
-				       cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return map_to_pos_S_FX_EFX((struct S_FX_EFX *)cfg->input_buf,
-					   cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return map_to_pos_S_FX_NCOB((struct S_FX_NCOB *)cfg->input_buf,
-					    cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return map_to_pos_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)cfg->input_buf,
-						     cfg->samples, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return map_to_pos_32((uint32_t *)cfg->input_buf, cfg->samples,
-				     zero_mode_used);
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+		}
 
-	}
+		if (i >= cfg->samples-1)
+			break;
 
-	return -1;
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
 /**
- * @brief forms the codeword accurate to the Rice code and returns its length
+ * @brief compress F_FX_EFX data
  *
- * @param m		Golomb parameter, only m's which are power of 2 and >0
- *			are allowed!
- * @param log2_m	Rice parameter, is log_2(m) calculate outside function
- *			for better performance
- * @param value		value to be encoded
- * @param cw		address were the encode code word is stored
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns length of the encoded code word in bits
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static unsigned int Rice_encoder(unsigned int value, unsigned int m,
-				 unsigned int log2_m, unsigned int *cw)
+static int compress_f_fx_efx(const struct cmp_cfg *cfg)
 {
-	unsigned int g;  /* quotient of value/m */
-	unsigned int q;  /* quotient code without ending zero */
-	unsigned int r;  /* remainder of value/m */
-	unsigned int rl; /* remainder length */
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	g = value >> log2_m; /* quotient, number of leading bits */
-	q = (1U << g) - 1;    /* prepare the quotient code without ending zero */
+	struct f_fx_efx *data_buf = cfg->input_buf;
+	struct f_fx_efx *model_buf = cfg->model_buf;
+	struct f_fx_efx *up_model_buf = NULL;
+	struct f_fx_efx *next_model_p;
+	struct f_fx_efx model;
+	struct encoder_setupt setup_fx, setup_efx;
 
-	r = value & (m-1);   /* calculate the remainder */
-	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the
-			      * quotient code)
-			      */
-	*cw = (q << rl) | r; /* put the quotient and remainder code together */
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	return rl + g;	      /* calculate the length of the code word */
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.f_efx, cfg);
+	if (err)
+		return -1;
+
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
 /**
- * @brief forms the codeword accurate to the Golomb code and returns its length
+ * @brief compress F_FX_NCOB data
  *
- * @param m		Golomb parameter, only m's which are power of 2 and >0
- *			are allowed!
- * @param log2_m	is log_2(m) calculate outside function for better
- *			performance
- * @param value		value to be encoded
- * @param cw		address were the encode code word is stored
+ * @param cfg	pointer to the compression configuration structure
  *
- * @returns length of the encoded code word in bits
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static unsigned int Golomb_encoder(unsigned int value, unsigned int m,
-				   unsigned int log2_m, unsigned int *cw)
+static int compress_f_fx_ncob(const struct cmp_cfg *cfg)
 {
-	unsigned int len0, b, g, q, lg;
-	unsigned int len;
-	unsigned int cutoff;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	len0 = log2_m + 1; /* codeword length in group 0 */
-	cutoff = (1U << (log2_m+1)) - m; /* members in group 0 */
-	if (cutoff == 0) /* for powers of two we fix cutoff = m */
-		cutoff = m;
+	struct f_fx_ncob *data_buf = cfg->input_buf;
+	struct f_fx_ncob *model_buf = cfg->model_buf;
+	struct f_fx_ncob *up_model_buf = NULL;
+	struct f_fx_ncob *next_model_p;
+	struct f_fx_ncob model;
+	struct encoder_setupt setup_fx, setup_ncob;
 
-	if (value < cutoff) { /* group 0 */
-		*cw = value;
-		len = len0;
-	} else { /* other groups */
-		b = (cutoff << 1); /* form the base codeword */
-		g = (value-cutoff)/m; /* this group is which one  */
-		lg = len0 + g; /* it has lg remainder bits */
-		q = (1U << g) - 1; /* prepare the left side in unary */
-		*cw = (q << (len0+1)) + b + (value-cutoff)-g*m; /* composed codeword */
-		len = lg + 1; /* length of the codeword */
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
 	}
-	return len;
-}
 
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.f_ncob, cfg);
+	if (err)
+		return -1;
 
-typedef unsigned int (*encoder_ptr)(unsigned int, unsigned int, unsigned int,
-				    unsigned int*);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+		}
 
-static encoder_ptr select_encoder(unsigned int golomb_par)
-{
-	if (!golomb_par)
-		return NULL;
+		if (i >= cfg->samples-1)
+			break;
 
-	if (is_a_pow_of_2(golomb_par))
-		return &Rice_encoder;
-	else
-		return &Golomb_encoder;
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
 /**
- * @brief    safe (but slow) way to put the value of up to 32 bits into a
- *           bitstream accessed as 32-bit RAM in big endian
- * @param    value      the value to put, it will be masked
- * @param    bitOffset  bit index where the bits will be put, seen from the very
- *			beginning of the bitstream
- * @param    nBits      number of bits to put in the bitstream
- * @param    destAddr   this is the pointer to the beginning of the bitstream
- * @param    dest_len   length of the bitstream buffer (starting at destAddr)
- * @returns  TODO number of bits written, 0 if the number was too big, -2 if the
- *	     destAddr buffer is to small to store the bitstream
- * @note     works in SRAM2
+ * @brief compress F_FX_EFX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
  */
 
-static unsigned int put_n_bits32(unsigned int value, unsigned int bitOffset,
-				 unsigned int nBits, unsigned int *destAddr,
-				 unsigned int dest_len)
+static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 {
-	unsigned int *localAddr;
-	unsigned int bitsLeft, shiftRight, shiftLeft, localEndPos;
-	unsigned int mask;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!destAddr)
-		return nBits;
+	struct f_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct f_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct f_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct f_fx_efx_ncob_ecob *next_model_p;
+	struct f_fx_efx_ncob_ecob model;
+	struct encoder_setupt setup_fx, setup_ncob, setup_efx, setup_ecob;
 
-	/* check if destination buffer is large enough */
-	/* TODO: adapt that to the other science products */
-	if ((bitOffset + nBits) > ((dest_len&~0x1U)*16)) {
-		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
-		return -2U;
-	}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	/* leave in case of erroneous input */
-	if (nBits == 0)
-		return 0;
-	if (nBits > 32)
-		return 0;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	/* separate the bitOffset into word offset (set localAddr pointer) and local bit offset (bitsLeft) */
-	localAddr = destAddr + (bitOffset >> 5);
-	bitsLeft = bitOffset & 0x1f;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	/* (M) we mask the value first to match its size in nBits */
-	/* the calculations can be re-used in the unsegmented code, so we have no overhead */
-	shiftRight = 32 - nBits;
-	mask = 0xffffffff >> shiftRight;
-	value &= mask;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.f_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.f_ncob, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.f_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				      cfg->round, max_used_bits.f_ecob, cfg);
+	if (err)
+		return -1;
 
-	/* to see if we need to split the value over two words we need the right end position */
-	localEndPos = bitsLeft + nBits;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
+		}
 
-	if (localEndPos <= 32) {
-		/*         UNSEGMENTED
-		 *
-		 *|-----------|XXXXX|----------------|
-		 *   bitsLeft    n       bitsRight
-		 *
-		 *  -> to get the mask:
-		 *  shiftRight = bitsLeft + bitsRight = 32 - n
-		 *  shiftLeft = bitsRight
-		 *
-		 */
+		if (i >= cfg->samples-1)
+			break;
 
-		/* shiftRight = 32 - nBits; */ /* see (M) above! */
-		shiftLeft = shiftRight - bitsLeft;
+		model = next_model_p[i];
+	}
+	return stream_len;
+}
 
-		/* generate the mask, the bits for the values will be true */
-		/* mask = (0xffffffff >> shiftRight) << shiftLeft; */ /* see (M) above! */
-		mask <<= shiftLeft;
 
-		/* clear the destination with inverse mask */
-		*(localAddr) &= ~mask;
+/**
+ * @brief compress L_FX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-		/* assign the value */
-		*(localAddr) |= (value << (32 - localEndPos)); /* NOTE: 32-localEndPos = shiftLeft can be simplified */
+static int compress_l_fx(const struct cmp_cfg *cfg)
+{
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	} else {
-		/*                             SEGMENTED
-		 *
-		 *|-----------------------------|XXX| |XX|------------------------------|
-		 *          bitsLeft              n1   n2          bitsRight
-		 *
-		 *  -> to get the mask part 1:
-		 *  shiftright = bitsleft
-		 *  n1 = n - (bitsleft + n - 32) = 32 - bitsleft
-		 *
-		 *  -> to get the mask part 2:
-		 *  n2 = bitsleft + n - 32
-		 *  shiftleft = 32 - n2 = 32 - (bitsleft + n - 32) = 64 - bitsleft - n
-		 *
-		 */
+	struct l_fx *data_buf = cfg->input_buf;
+	struct l_fx *model_buf = cfg->model_buf;
+	struct l_fx *up_model_buf = NULL;
+	struct l_fx *next_model_p;
+	struct l_fx model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_fx_var;
 
-		unsigned int n2 = bitsLeft + nBits - 32;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-		/* part 1: */
-		shiftRight = bitsLeft;
-		mask = 0xffffffff >> shiftRight;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-		/* clear the destination with inverse mask */
-		*(localAddr) &= ~mask;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-		/* assign the value part 1 */
-		*(localAddr) |= (value >> n2);
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
+		return -1;
 
-		/* part 2: */
-		/* adjust address */
-		localAddr += 1;
-		shiftLeft = 64 - bitsLeft - nBits;
-		mask = 0xffffffff << shiftLeft;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+		}
 
-		/* clear the destination with inverse mask */
-		*(localAddr) &= ~mask;
+		if (i >= cfg->samples-1)
+			break;
 
-		/* assign the value part 2 */
-		*(localAddr) |= (value << (32 - n2));
+		model = next_model_p[i];
 	}
-	return nBits;
+	return stream_len;
 }
 
 
-struct encoder_struct {
-	encoder_ptr encoder;
-	unsigned int log2_golomb_par; /* pre-calculated for performance increase */
-	uint32_t cmp_size; /* Compressed data size; measured in bits */
-};
-
+/**
+ * @brief compress L_FX_EFX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-static int encode_raw(struct cmp_cfg *cfg, struct encoder_struct *enc)
+static int compress_l_fx_efx(const struct cmp_cfg *cfg)
 {
-	size_t cmp_size_in_bytes;
-
-	if (!cfg)
-		return -1;
+	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!cfg->icu_output_buf)
-		return -1;
+	struct l_fx_efx *data_buf = cfg->input_buf;
+	struct l_fx_efx *model_buf = cfg->model_buf;
+	struct l_fx_efx *up_model_buf = NULL;
+	struct l_fx_efx *next_model_p;
+	struct l_fx_efx model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_efx, setup_fx_var;
 
-	if (!cfg->input_buf)
-		return -1;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	cmp_size_in_bytes = cfg->samples * size_of_a_sample(cfg->cmp_mode);
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	enc->cmp_size = cmp_size_in_bytes * CHAR_BIT; /* cmp_size is measured in bits */
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (cmp_size_in_bytes > cfg->buffer_length * sizeof(uint16_t))
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.l_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
 		return -1;
 
-	memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size_in_bytes);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+		}
 
-	return 0;
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
-static int encode_raw_16(struct cmp_cfg *cfg, struct encoder_struct *enc)
+/**
+ * @brief compress L_FX_NCOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_l_fx_ncob(const struct cmp_cfg *cfg)
 {
 	int err;
+	int stream_len = 0;
 	size_t i;
 
-	enc->cmp_size = 0;
+	struct l_fx_ncob *data_buf = cfg->input_buf;
+	struct l_fx_ncob *model_buf = cfg->model_buf;
+	struct l_fx_ncob *up_model_buf = NULL;
+	struct l_fx_ncob *next_model_p;
+	struct l_fx_ncob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob,
+			      setup_fx_var, setup_cob_var;
 
-	for (i = 0; i < cfg->samples; i++) {
-		uint16_t *p = cfg->input_buf;
-		err = put_n_bits32(p[i], enc->cmp_size, 16, cfg->icu_output_buf,
-				   cfg->buffer_length);
-		if (err <= 0)
-			return err;
-		enc->cmp_size += 16;
-	}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	return 0;
-}
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-static int encode_raw_S_FX(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	int err;
-
-	err = encode_raw(cfg, enc);
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
 	if (err)
-		return err;
+		return -1;
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.l_ncob, cfg);
+	if (err)
+		return -1;
+	/* we use compression parameter for both variance data fields */
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_cob_variance, cfg);
+	if (err)
+		return -1;
 
-#if defined(__LITTLE_ENDIAN)
-	{
-		size_t i;
-		for (i = 0; i < cfg->samples; i++) {
-			struct S_FX *output_buf = (void *)cfg->icu_output_buf;
-			output_buf[i].FX = cpu_to_be32(output_buf[i].FX);
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_x_variance, model.cob_x_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_y_variance, model.cob_y_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+			up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
 		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
 	}
-#endif
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_normal(uint32_t value_to_encode, struct cmp_cfg *cfg,
-			 struct encoder_struct *enc)
+/**
+ * @brief compress L_FX_EFX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 {
-	unsigned int code_word;
-	unsigned int cw_len;
 	int err;
+	int stream_len = 0;
+	size_t i;
 
-	if (!enc->encoder)
-		return -1;
-
-	cw_len = enc->encoder(value_to_encode, cfg->golomb_par,
-			      enc->log2_golomb_par, &code_word);
-
-	err = put_n_bits32(code_word, enc->cmp_size, cw_len,
-			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0)
-		return err;
-
-	enc->cmp_size += cw_len;
+	struct l_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct l_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct l_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct l_fx_efx_ncob_ecob *next_model_p;
+	struct l_fx_efx_ncob_ecob model;
+	struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_efx,
+			      setup_ecob, setup_fx_var, setup_cob_var;
 
-	return 0;
-}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-static int encode_outlier_zero(uint32_t value_to_encode, int max_bits,
-			       struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	int err;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (max_bits > 32)
+	err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				      cfg->round, max_used_bits.l_exp_flags, cfg);
+	if (err)
 		return -1;
-
-	/* use zero as escape symbol */
-	err = encode_normal(0, cfg, enc);
+	err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				      cfg->round, max_used_bits.l_fx, cfg);
 	if (err)
-		return err;
+		return -1;
+	err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				      cfg->round, max_used_bits.l_ncob, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				      cfg->round, max_used_bits.l_efx, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				      cfg->round, max_used_bits.l_ecob, cfg);
+	if (err)
+		return -1;
+	/* we use compression parameter for both variance data fields */
+	err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_fx_variance, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				      cfg->round, max_used_bits.l_cob_variance, cfg);
+	if (err)
+		return -1;
 
-	/* put the data unencoded in the bitstream */
-	err = put_n_bits32(value_to_encode, enc->cmp_size, max_bits,
-			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0)
-		return err;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags,
+					  stream_len, &setup_exp_flag);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx, model.fx, stream_len,
+					  &setup_fx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y,
+					  stream_len, &setup_ncob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].efx, model.efx,
+					  stream_len, &setup_efx);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y,
+					  stream_len, &setup_ecob);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance,
+					  stream_len, &setup_fx_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_x_variance, model.cob_x_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].cob_y_variance, model.cob_y_variance,
+					  stream_len, &setup_cob_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flag.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+			up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+		}
 
-	enc->cmp_size += max_bits;
+		if (i >= cfg->samples-1)
+			break;
 
-	return 0;
+		model = next_model_p[i];
+	}
+	return stream_len;
 }
 
 
-static int cal_multi_offset(unsigned int unencoded_data)
-{
-	if (unencoded_data <= 0x3)
-		return 0;
-	if (unencoded_data <= 0xF)
-		return 1;
-	if (unencoded_data <= 0x3F)
-		return 2;
-	if (unencoded_data <= 0xFF)
-		return 3;
-	if (unencoded_data <= 0x3FF)
-		return 4;
-	if (unencoded_data <= 0xFFF)
-		return 5;
-	if (unencoded_data <= 0x3FFF)
-		return 6;
-	if (unencoded_data <= 0xFFFF)
-		return 7;
-	if (unencoded_data <= 0x3FFFF)
-		return 8;
-	if (unencoded_data <= 0xFFFFF)
-		return 9;
-	if (unencoded_data <= 0x3FFFFF)
-		return 10;
-	if (unencoded_data <= 0xFFFFFF)
-		return 11;
-	if (unencoded_data <= 0x3FFFFFF)
-		return 12;
-	if (unencoded_data <= 0xFFFFFFF)
-		return 13;
-	if (unencoded_data <= 0x3FFFFFFF)
-		return 14;
-	else
-		return 15;
-}
-
+/**
+ * @brief compress offset data from the normal cameras
+ *
+ * @param cfg	pointer to the compression configuration structure
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-static int encode_outlier_multi(uint32_t value_to_encode, struct cmp_cfg *cfg,
-				struct encoder_struct *enc)
+static int compress_nc_offset(const struct cmp_cfg *cfg)
 {
-	uint32_t unencoded_data;
-	unsigned int unencoded_data_len;
-	uint32_t escape_sym;
-	int escape_sym_offset;
 	int err;
+	int stream_len = 0;
+	size_t i;
 
-	/*
-	 * In this mode we put the difference between the data and the spillover
-	 * threshold value (unencoded_data) after a encoded escape symbol, which
-	 * indicate that the next codeword is unencoded.
-	 * We use different escape symbol depended on the size the needed bit of
-	 * unencoded data:
-	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is spill + 0
-	 * 3, 4 bits needed for unencoded data -> escape symbol is spill + 1
-	 * ..
-	 */
-
-	unencoded_data = value_to_encode - cfg->spill;
-	escape_sym_offset = cal_multi_offset(unencoded_data);
-	escape_sym  = cfg->spill + escape_sym_offset;
-	unencoded_data_len = (escape_sym_offset + 1) * 2;
-
-	/* put the escape symbol in the bitstream */
-	err = encode_normal(escape_sym, cfg, enc);
-	if (err)
-		return err;
-
-	/* put the unencoded data in the bitstream */
-	err = put_n_bits32(unencoded_data, enc->cmp_size, unencoded_data_len,
-			   cfg->icu_output_buf, cfg->buffer_length);
-	if (err <= 0)
-		return err;
-
-	enc->cmp_size += unencoded_data_len;
-
-	return 0;
-}
-
-static int encode_outlier(uint32_t value_to_encode, int bit_len, struct cmp_cfg
-			  *cfg, struct encoder_struct *enc)
-{
-	if (multi_escape_mech_is_used(cfg->cmp_mode))
-		return encode_outlier_multi(value_to_encode, cfg, enc);
-
-	if (zero_escape_mech_is_used(cfg->cmp_mode))
-		return encode_outlier_zero(value_to_encode, bit_len, cfg, enc);
-
-	return -1;
-}
-
+	struct nc_offset *data_buf = cfg->input_buf;
+	struct nc_offset *model_buf = cfg->model_buf;
+	struct nc_offset *up_model_buf = NULL;
+	struct nc_offset *next_model_p;
+	struct nc_offset model;
+	struct encoder_setupt setup_mean, setup_var;
 
-int encode_value(uint32_t value_to_encode, int bit_len, struct cmp_cfg *cfg,
-		 struct encoder_struct *enc)
-{
-	/* 0 is an outlier in case of a zero-escape mechanism, because an
-	 * overflow can occur by incrementing by one
-	 */
-	if (value_to_encode >= cfg->spill ||
-	    (zero_escape_mech_is_used(cfg->cmp_mode) && value_to_encode == 0))
-		return encode_outlier(value_to_encode, bit_len, cfg, enc);
-	else
-		return encode_normal(value_to_encode, cfg, enc);
-}
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-static int encode_16(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	size_t i;
-	uint16_t *data_to_encode;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (!cfg)
+	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				      cfg->round, max_used_bits.nc_offset_mean, cfg);
+	if (err)
 		return -1;
-
-	if (!enc)
+	err = configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				      cfg->round, max_used_bits.nc_offset_variance, cfg);
+	if (err)
 		return -1;
 
-	data_to_encode = cfg->input_buf;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].mean, model.mean,
+					  stream_len, &setup_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].variance, model.variance,
+					  stream_len, &setup_var);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, model.mean,
+				cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, model.variance,
+				cfg->model_value, setup_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err = encode_value(data_to_encode[i], 16, cfg, enc);
-		if (err)
-			return err;
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_32(struct cmp_cfg *cfg, struct encoder_struct *enc)
+/**
+ * @brief compress background data from the normal cameras
+ *
+ * @param cfg	pointer to the compression configuration structure
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_nc_background(const struct cmp_cfg *cfg)
 {
-	uint32_t *data_to_encode = cfg->input_buf;
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err = encode_value(data_to_encode[i], 32, cfg, enc);
-		if (err)
-			return err;
-	}
-	return 0;
-}
+	struct nc_background *data_buf = cfg->input_buf;
+	struct nc_background *model_buf = cfg->model_buf;
+	struct nc_background *up_model_buf = NULL;
+	struct nc_background *next_model_p;
+	struct nc_background model;
+	struct encoder_setupt setup_mean, setup_var, setup_pix;
 
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-static int encode_S_FX(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	struct S_FX *data_to_encode = cfg->input_buf;
-	size_t i;
-	struct cmp_cfg cfg_exp_flag = *cfg;
-	struct encoder_struct enc_exp_flag = *enc;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-	cfg_exp_flag.golomb_par = GOLOMB_PAR_EXPOSURE_FLAGS;
-	enc_exp_flag.log2_golomb_par = ilog_2(GOLOMB_PAR_EXPOSURE_FLAGS);
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
+	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				      cfg->round, max_used_bits.nc_background_mean, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				      cfg->round, max_used_bits.nc_background_variance, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+				      cfg->round, max_used_bits.nc_background_outlier_pixels, cfg);
+	if (err)
+		return -1;
 
-		/* err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, &cfg_exp_flag, enc); */
-		err = encode_normal(data_to_encode[i].EXPOSURE_FLAGS, &cfg_exp_flag, &enc_exp_flag);
-		if (err)
-			return err;
-		enc->cmp_size = enc_exp_flag.cmp_size;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].mean, model.mean,
+					  stream_len, &setup_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].variance, model.variance,
+					  stream_len, &setup_var);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].outlier_pixels, model.outlier_pixels,
+					  stream_len, &setup_pix);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, model.mean,
+				cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, model.variance,
+				cfg->model_value, setup_var.lossy_par);
+			up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, model.outlier_pixels,
+				cfg->model_value, setup_pix.lossy_par);
+		}
 
-		enc->log2_golomb_par = ilog_2(cfg->golomb_par);
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+		if (i >= cfg->samples-1)
+			break;
 
-		enc_exp_flag.cmp_size = enc->cmp_size;
+		model = next_model_p[i];
 	}
-
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_S_FX_EFX(struct cmp_cfg *cfg, struct encoder_struct *enc)
+/**
+ * @brief compress smearing data from the normal cameras
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int compress_smearing(const struct cmp_cfg *cfg)
 {
-	struct S_FX_EFX *data_to_encode = cfg->input_buf;
+	int err;
+	int stream_len = 0;
 	size_t i;
 
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
+	struct smearing *data_buf = cfg->input_buf;
+	struct smearing *model_buf = cfg->model_buf;
+	struct smearing *up_model_buf = NULL;
+	struct smearing *next_model_p;
+	struct smearing model;
+	struct encoder_setupt setup_mean, setup_var_mean, setup_pix;
 
-		err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, cfg, enc);
-		if (err)
-			return err;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+					      (void **)&up_model_buf, cfg);
 
-		err = encode_value(data_to_encode[i].EFX, 32, cfg, enc);
-		if (err)
-			return err;
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
 	}
-	return 0;
-}
-
 
-static int encode_S_FX_NCOB(struct cmp_cfg *cfg, struct encoder_struct *enc)
-{
-	struct S_FX_NCOB *data_to_encode = cfg->input_buf;
-	size_t i;
-
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
-
-		err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, cfg, enc);
-		if (err)
-			return err;
+	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				      cfg->round, max_used_bits.smeating_mean, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_var_mean, cfg->cmp_par_variance, cfg->spill_variance,
+				      cfg->round, max_used_bits.smeating_variance_mean, cfg);
+	if (err)
+		return -1;
+	err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+				      cfg->round, max_used_bits.smearing_outlier_pixels, cfg);
+	if (err)
+		return -1;
 
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+	for (i = 0;; i++) {
+		stream_len = encode_value(data_buf[i].mean, model.mean,
+					  stream_len, &setup_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].variance_mean, model.variance_mean,
+					  stream_len, &setup_var_mean);
+		if (stream_len <= 0)
+			return stream_len;
+		stream_len = encode_value(data_buf[i].outlier_pixels, model.outlier_pixels,
+					  stream_len, &setup_pix);
+		if (stream_len <= 0)
+			return stream_len;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, model.mean,
+				cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance_mean = cmp_up_model(data_buf[i].variance_mean, model.variance_mean,
+				cfg->model_value, setup_var_mean.lossy_par);
+			up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, model.outlier_pixels,
+				cfg->model_value, setup_pix.lossy_par);
+		}
 
-		err = encode_value(data_to_encode[i].NCOB_X, 32, cfg, enc);
-		if (err)
-			return err;
+		if (i >= cfg->samples-1)
+			break;
 
-		err = encode_value(data_to_encode[i].NCOB_Y, 32, cfg, enc);
-		if (err)
-			return err;
+		model = next_model_p[i];
 	}
-	return 0;
+	return stream_len;
 }
 
 
-static int encode_S_FX_EFX_NCOB_ECOB(struct cmp_cfg *cfg, struct encoder_struct
-				     *enc)
-{
-	struct S_FX_EFX_NCOB_ECOB *data_to_encode = cfg->input_buf;
-	size_t i;
-
-	for (i = 0; i < cfg->samples; i++) {
-		int err;
-
-		err = encode_value(data_to_encode[i].EXPOSURE_FLAGS, 8, cfg, enc);
-		if (err)
-			return err;
-
-		err = encode_value(data_to_encode[i].FX, 32, cfg, enc);
-		if (err)
-			return err;
+/**
+ * @brief fill the last part of the bitstream with zeros
+ *
+ * @param cfg		pointer to the compression configuration structure
+ * @param cmp_size	length of the bitstream in bits
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-		err = encode_value(data_to_encode[i].NCOB_X, 32, cfg, enc);
-		if (err)
-			return err;
+static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size)
+{
+	unsigned int output_buf_len_bits, n_pad_bits;
 
-		err = encode_value(data_to_encode[i].NCOB_Y, 32, cfg, enc);
-		if (err)
-			return err;
+	if (cmp_size < 0)
+		return cmp_size;
 
-		err = encode_value(data_to_encode[i].EFX, 32, cfg, enc);
-		if (err)
-			return err;
+	/* maximum length of the bitstream/icu_output_buf in bits */
+	output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
 
-		err = encode_value(data_to_encode[i].ECOB_X, 32, cfg, enc);
-		if (err)
-			return err;
+	/* no padding in RAW mode*/
+	if (cfg->cmp_mode == CMP_MODE_RAW)
+		return cmp_size;
 
-		err = encode_value(data_to_encode[i].ECOB_Y, 32, cfg, enc);
-		if (err)
-			return err;
+	n_pad_bits = 32 - ((unsigned int)cmp_size & 0x1FU);
+	if (n_pad_bits < 32) {
+		int n_bits = put_n_bits32(0, n_pad_bits, cmp_size, cfg->icu_output_buf,
+					  output_buf_len_bits);
+		if (n_bits < 0)
+			return n_bits;
 	}
-	return 0;
-}
-
 
-/* pad the bitstream with zeros */
-int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size)
-{
-	int n_bits = 0;
-
-	if (!cfg)
-		return -1;
-
-	/* is padding needed */
-	if (cmp_size) {
-		int n_pad_bits = 32U - (cmp_size & 0x1f);
-		if (n_pad_bits < 32) {
-			 n_bits = put_n_bits32(0, cmp_size, n_pad_bits,
-					       cfg->icu_output_buf,
-					       cfg->buffer_length);
-			if (n_bits <= 0)
-				return -2;
-		}
-	}
-	return n_bits;
+	return cmp_size;
 }
 
 
-uint32_t cmp_encode_data(struct cmp_cfg *cfg)
-{
-	struct encoder_struct enc;
-	int err, n_bits;
+/**
+ * @brief change the endianness of the compressed data to big-endian
+ *
+ * @param cfg		pointer to the compression configuration structure
+ * @param cmp_size	length of the bitstream in bits
+ *
+ * @returns 0 on success; non-zero on failure
+ */
 
-	enc.encoder = select_encoder(cfg->golomb_par);
-	enc.log2_golomb_par = ilog_2(cfg->golomb_par);
-	enc.cmp_size = 0;
+static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, unsigned int cmp_size)
+{
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+	size_t i;
+	uint32_t *p;
 
-	switch (cfg->cmp_mode) {
-	case MODE_RAW:
-		err = encode_raw_16(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		err = encode_16(cfg, &enc);
-		break;
-	case MODE_RAW_S_FX:
-		err = encode_raw_S_FX(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		err = encode_S_FX(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		err = encode_S_FX_EFX(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		err = encode_S_FX_NCOB(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		err = encode_S_FX_EFX_NCOB_ECOB(cfg, &enc);
-		break;
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		err = encode_32(cfg, &enc);
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		return -1;
-		break;
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
+		int err = cmp_input_big_to_cpu_endianness(cfg->icu_output_buf,
+							  cmp_size/CHAR_BIT, cfg->data_type);
+		return err;
 	}
 
-	n_bits = pad_bitstream(cfg, enc.cmp_size);
-	if (n_bits < 0)
-		return n_bits;
-
-#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-	{
-		size_t i;
-		uint32_t *p = (uint32_t *)cfg->icu_output_buf;
-
-		if (p) {
-			for (i = 0; i < cmp_bit_to_4byte(enc.cmp_size)/sizeof(uint32_t); i++)
-				cpu_to_be32s(&p[i]);
-		}
+	if (rdcu_supported_data_type_is_used(cfg->data_type)) {
+		p = cfg->icu_output_buf;
+	} else {
+		p = &cfg->icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
+		cmp_size -= MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
 	}
-#endif /*__BYTE_ORDER__ */
 
-	if (err)
-		return err;
-	else
-		return enc.cmp_size;
+	for (i = 0; i < cmp_bit_to_4byte(cmp_size)/sizeof(uint32_t); i++)
+		cpu_to_be32s(&p[i]);
+#else
+	/* do nothing data are already in big-endian */
+	(void)cfg;
+#endif /*__BYTE_ORDER__ */
+	return 0;
 }
 
 
 /**
  * @brief	compress data on the ICU
  *
- * @param cfg	compressor configuration contains all parameters required for
- *		compression
- * @param info	compressor information contains information of the executed
- *		compression
+ * @param cfg	pointer to a compression configuration (created with the
+ *		cmp_cfg_icu_create() function, setup with the cmp_cfg_xxx() functions)
  *
- * @note this function violates the input_buf in place
- * @note if icu_new_model_buf = model_buf or NULL, the model will be updated in place
  * @note the validity of the cfg structure is checked before the compression is
  *	 started
- * @note when using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
- *      the model parameters (model_value, model_buf, rdcu_model_adr) are ignored
- * @note the rdcu_***_adr configuration parameters are ignored for icu
- *	 compression
- * @note semi adaptive compression not supported; configuration parameters
- *	 ap1\_golomb\_par, ap2\_golomb\_par, ap1\_spill ap2\_spill will be
- *	 ignored; information parameters ap1_cmp_size, ap2_cmp_size will always
- *	 be 0
- *
- * @returns 0 on success, error otherwise
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF (-2) if the compressed data buffer is too small to
+ *	hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or
+ *	model value is bigger than the max_used_bits parameter allows (set with
+ *	the cmp_set_max_used_bits() function)
  */
 
-int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info)
+int icu_compress_data(const struct cmp_cfg *cfg)
 {
-	int err;
 	int cmp_size = 0;
 
-	err = set_info(cfg, info);
-	if (err)
-		return err;
+	if (!cfg)
+		return -1;
 
-	err = icu_cmp_cfg_valid(cfg, info);
-	if (err)
-		return err;
+	if (cfg->samples == 0) /* nothing to compress we are done*/
+		return 0;
 
-	err = cmp_pre_process(cfg);
-	if (err)
-		return err;
+	if (!cmp_cfg_is_valid(cfg))
+		return -1;
 
-	err = cmp_map_to_pos(cfg);
-	if (err)
-		return err;
+	if (model_mode_is_used(cfg->cmp_mode) && !cfg->model_buf)
+		return -1;
 
-	cmp_size = cmp_encode_data(cfg);
-	if (cmp_size == -2 && info)
-		/* the icu_output_buf is to small to store the whole bitstream */
-		info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
-	if (cmp_size < 0)
-		return cmp_size;
-	if (info)
-		info->cmp_size = cmp_size;
+	if (raw_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->samples > cfg->buffer_length) {
+			cmp_size = CMP_ERROR_SAMLL_BUF;
+		} else {
+			cmp_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+			if (cfg->icu_output_buf)
+				memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size);
+			cmp_size *= CHAR_BIT; /* convert to bits */
+		}
+	} else {
+		switch (cfg->data_type) {
+		case DATA_TYPE_IMAGETTE:
+		case DATA_TYPE_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_SAT_IMAGETTE:
+		case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_F_CAM_IMAGETTE:
+		case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+			cmp_size = compress_imagette(cfg);
+			break;
+
+		case DATA_TYPE_S_FX:
+			cmp_size = compress_s_fx(cfg);
+			break;
+		case DATA_TYPE_S_FX_DFX:
+			cmp_size = compress_s_fx_efx(cfg);
+			break;
+		case DATA_TYPE_S_FX_NCOB:
+			cmp_size = compress_s_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+			cmp_size = compress_s_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_F_FX:
+			cmp_size = compress_f_fx(cfg);
+			break;
+		case DATA_TYPE_F_FX_DFX:
+			cmp_size = compress_f_fx_efx(cfg);
+			break;
+		case DATA_TYPE_F_FX_NCOB:
+			cmp_size = compress_f_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+			cmp_size = compress_f_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_L_FX:
+			cmp_size = compress_l_fx(cfg);
+			break;
+		case DATA_TYPE_L_FX_DFX:
+			cmp_size = compress_l_fx_efx(cfg);
+			break;
+		case DATA_TYPE_L_FX_NCOB:
+			cmp_size = compress_l_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+			cmp_size = compress_l_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_OFFSET:
+			cmp_size = compress_nc_offset(cfg);
+			break;
+		case DATA_TYPE_BACKGROUND:
+			cmp_size = compress_nc_background(cfg);
+			break;
+		case DATA_TYPE_SMEARING:
+			cmp_size = compress_smearing(cfg);
+			break;
+
+		case DATA_TYPE_F_CAM_OFFSET:
+		case DATA_TYPE_F_CAM_BACKGROUND:
+		case DATA_TYPE_UNKOWN:
+		default:
+			debug_print("Error: Data type not supported.\n");
+			cmp_size = -1;
+		}
+	}
 
-	return 0;
+	if (cfg->icu_output_buf && cmp_size > 0) {
+		cmp_size = pad_bitstream(cfg, cmp_size);
+		cmp_data_to_big_endian(cfg, (unsigned int)cmp_size);
+	}
+
+	return cmp_size;
 }
diff --git a/lib/cmp_icu_new.c b/lib/cmp_icu_new.c
deleted file mode 100644
index d69ab0f..0000000
--- a/lib/cmp_icu_new.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/**
- * @file   icu_cmp.c
- * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
- * @date   2020
- *
- * @copyright GPLv2
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * @brief software compression library
- * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
- */
-
-
-#include <stdint.h>
-
-#include "cmp_debug.h"
-
-
-/* return code if the bitstream buffer is too small to store the whole bitstream */
-#define CMP_ERROR_SAMLL_BUF -2
-
-/* pointer to a code word generation function */
-typedef uint32_t (*generate_cw_pt)(uint32_t value, uint32_t encoder_par1,
-				   uint32_t encoder_par2, uint32_t *cw);
-
-/* typedef uint32_t (*next_model_f_pt)(uint32_t model_mode_val, uint32_t diff_model_var); */
-
-struct encoder_setupt {
-	/* unsigned int lossy_par; */
-	/* next_model_f_pt *next_model_f; */
-	generate_cw_pt generate_cw; /* pointer to the code word generation function */
-	/* uint32_t updated_model; */
-	uint32_t encoder_par1;
-	uint32_t encoder_par2;
-	uint32_t outlier_par;
-	uint32_t model_value;
-	uint32_t max_value_bits; /* how many bits are needed to represent the highest possible value */
-	uint32_t max_bit_len; /* maximum length of the bitstream/icu_output_buf in bits */
-	uint32_t *bitstream_adr;
-};
-
-
-/**
- * @brief map a signed value into a positive value range
- *
- * @param value_to_map		signed value to map
- * @param max_value_bits	how many bits are needed to represent the
- *				highest possible value
- *
- * @returns the positive mapped value
- */
-
-static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_value_bits)
-{
-	uint32_t mask = (~0U >> (32 - max_value_bits)); /* mask the used bits */
-
-	value_to_map &= mask;
-	if (value_to_map >> (max_value_bits - 1)) { /* check the leading signed bit */
-		value_to_map |= ~mask; /* convert to 32-bit signed integer */
-		/* map negative values to uneven numbers */
-		return (-value_to_map) * 2 - 1; /* possible integer overflow is intended */
-	} else {
-		/* map positive values to even numbers */
-		return value_to_map * 2; /* possible integer overflow is intended */
-	}
-}
-
-
-/**
- * @brief put the value of up to 32 bits into a bitstream accessed as 32-bit
- *	RAM in big-endian
- *
- * @param value		the value to put
- * @param n_bits	number of bits to put in the bitstream
- * @param bit_offset	bit index where the bits will be put, seen from the very
- *			beginning of the bitstream
- * @param bitstream_adr	this is the pointer to the beginning of the bitstream
- *			(can be NULL)
- * @param max_bit_len	maximum length of the bitstream in bits; is ignored if
- *			bitstream_adr is NULL
- *
- * @returns length in bits of the generated bitstream on success; returns
- *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
- *          the bitstream buffer is too small to put the value in the bitstream
- */
-
-static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
-			uint32_t *bitstream_adr, unsigned int max_bit_len)
-{
-	uint32_t *local_adr;
-	uint32_t mask;
-	unsigned int shiftRight, shiftLeft, bitsLeft, bitsRight;
-	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
-
-	/* leave in case of erroneous input */
-	if (bit_offset < 0)
-		return -1;
-
-	if (n_bits == 0)
-		return stream_len;
-
-	if (n_bits > 32)
-		return -1;
-
-	/* Do we need to write data to the bitstream? */
-	if (!bitstream_adr)
-		return stream_len;
-
-	/* Check if bitstream buffer is large enough */
-	if ((unsigned int)stream_len > max_bit_len) {
-		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
-		return CMP_ERROR_SAMLL_BUF;
-	}
-
-	/* (M) is the n_bits parameter large enough to cover all value bits; the
-	 * calculations can be re-used in the unsegmented code, so we have no overhead
-	 */
-	shiftRight = 32 - n_bits;
-	mask = 0xFFFFFFFFU >> shiftRight;
-	value &= mask;
-
-	/* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */
-	local_adr = bitstream_adr + (bit_offset >> 5);
-	bitsLeft = bit_offset & 0x1F;
-
-	/* Calculate the bitsRight for the unsegmented case. If bitsRight is
-	 * negative we need to split the value over two words
-	 */
-	bitsRight = shiftRight - bitsLeft;
-
-	if ((int)bitsRight >= 0) {
-		/*         UNSEGMENTED
-		 *
-		 *|-----------|XXXXX|----------------|
-		 *   bitsLeft    n       bitsRight
-		 *
-		 *  -> to get the mask:
-		 *  shiftRight = bitsLeft + bitsRight = 32 - n
-		 *  shiftLeft = bitsRight = 32 - n - bitsLeft = shiftRight - bitsLeft
-		 */
-
-		shiftLeft = bitsRight;
-
-		/* generate the mask, the bits for the values will be true
-		 * shiftRight = 32 - n_bits; see (M) above!
-		 * mask = (0XFFFFFFFF >> shiftRight) << shiftLeft; see (M) above!
-		 */
-		mask <<= shiftLeft;
-		value <<= shiftLeft;
-
-		/* clear the destination with inverse mask */
-		*(local_adr) &= ~mask;
-
-		/* assign the value */
-		*(local_adr) |= value;
-
-	} else {
-		/*                             SEGMENTED
-		 *
-		 *|-----------------------------|XXX| |XX|------------------------------|
-		 *          bitsLeft              n1   n2          bitsRight
-		 *
-		 *  -> to get the mask part 1:
-		 *  shiftRight = bitsLeft
-		 *  n1 = n - (bitsLeft + n - 32) = 32 - bitsLeft
-		 *
-		 *  -> to get the mask part 2:
-		 *  n2 = bitsLeft + n - 32 = -(32 - n - bitsLeft) = -(bitsRight_UNSEGMENTED)
-		 *  shiftLeft = 32 - n2 = 32 - (bitsLeft + n - 32) = 64 - bitsLeft - n
-		 *
-		 */
-
-		unsigned int n2 = -bitsRight;
-
-		/* part 1: */
-		shiftRight = bitsLeft;
-		mask = 0XFFFFFFFFU >> shiftRight;
-
-		/* clear the destination with inverse mask */
-		*(local_adr) &= ~mask;
-
-		/* assign the value part 1 */
-		*(local_adr) |= (value >> n2);
-
-		/* part 2: */
-		/* adjust address */
-		local_adr += 1;
-		shiftLeft = 32 - n2;
-		mask = 0XFFFFFFFFU << shiftLeft;
-
-		/* clear the destination with inverse mask */
-		*(local_adr) &= ~mask;
-
-		/* assign the value part 2 */
-		*(local_adr) |= (value << shiftLeft);
-	}
-	return stream_len;
-}
-
-
-/**
- * @brief forms the codeword according to the Rice code
- *
- * @param value		value to be encoded
- * @param m		Golomb parameter, only m's which are power of 2 are allowed
- * @param log2_m	Rice parameter, is log_2(m) calculate outside function
- *			for better performance
- * @param cw		address were the encode code word is stored
- *
- * @returns the length of the formed code word in bits
- * @note no check if the generated code word is not longer than 32 bits.
- */
-
-static uint32_t Rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
-				 uint32_t *cw)
-{
-	uint32_t g;  /* quotient of value/m */
-	uint32_t q;  /* quotient code without ending zero */
-	uint32_t r;  /* remainder of value/m */
-	uint32_t rl; /* remainder length */
-
-	g = value >> log2_m; /* quotient, number of leading bits */
-	q = (1U << g) - 1;   /* prepare the quotient code without ending zero */
-
-	r = value & (m-1);   /* calculate the remainder */
-	rl = log2_m + 1;     /* length of the remainder (+1 for the 0 in the quotient code) */
-	*cw = (q << rl) | r; /* put the quotient and remainder code together */
-	/*
-	 * NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined
-	 * behavior. However, in this case, a valid code with a maximum of 32
-	 * bits can only be formed if q = 0. Any shift with 0 << x always
-	 * results in 0, which forms the correct codeword in this case. For
-	 * performance reasons, this undefined behaviour is not caught.
-	 */
-
-	return rl + g;	      /* calculate the length of the code word */
-}
-
-
-/**
- * @brief forms a codeword according to the Golomb code
- *
- * @param value		value to be encoded
- * @param m		Golomb parameter (have to be bigger than 0)
- * @param log2_m	is log_2(m) calculate outside function for better
- *			performance
- * @param cw		address were the formed code word is stored
- *
- * @returns the length of the formed code word in bits
- */
-
-static uint32_t Golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
-				   uint32_t *cw)
-{
-	uint32_t len0, b, g, q, lg;
-	uint32_t len;
-	uint32_t cutoff;
-
-	len0 = log2_m + 1;                 /* codeword length in group 0 */
-	cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */
-
-	if (value < cutoff) { /* group 0 */
-		*cw = value;
-		len = len0;
-	} else { /* other groups */
-		g = (value-cutoff) / m; /* this group is which one  */
-		b = cutoff << 1;        /* form the base codeword */
-		lg = len0 + g;          /* it has lg remainder bits */
-		q = (1U << g) - 1;      /* prepare the left side in unary */
-		*cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */
-		len = lg + 1;           /* length of the codeword */
-	}
-	return len;
-}
-
-
-/**
- * @brief generate a code word without a outlier mechanism and put in the
- *	bitstream
- *
- * @param value		value to encode in the bitstream
- * @param stream_len	length of the bitstream in bits
- * @param setup		pointer to the encoder setup
- *
- * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error
- */
-
-static int encode_normal(uint32_t value, int stream_len,
-			 struct encoder_setupt *setup)
-{
-	uint32_t code_word, cw_len;
-
-	cw_len = setup->generate_cw(value, setup->encoder_par1,
-				    setup->encoder_par2, &code_word);
-
-	return put_n_bits32(code_word, cw_len, stream_len, setup->bitstream_adr,
-			    setup->max_bit_len);
-}
-
-
-/**
- * @brief subtract the model from the data, encode the result and put it into
- *	bitstream, for encodeing outlier use the zero escape symbol mechanism
- *
- * @param data		data to encode
- * @param model		model of the data (0 if not used)
- * @param stream_len	length of the bitstream in bits
- * @param setup		pointer to the encoder setup
- *
- * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
- *	is too small to put the value in the bitstream
- *
- * @note no check if data or model are in the allowed range
- * @note no check if the setup->outlier_par is in the allowed range
- */
-
-static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
-			     struct encoder_setupt *setup)
-{
-	data -= model;
-
-	data = map_to_pos(data, setup->max_value_bits);
-
-	/* For performance reasons, we check to see if there is an outlier
-	 * before adding one, rather than the other way around:
-	 * data++;
-	 * if (data < setup->outlier_par && data != 0)
-	 *	return ...
-	 */
-	if (data < (setup->outlier_par - 1)) { /* detect r */
-		data++; /* add 1 to every value so we can use 0 as escape symbol */
-		return encode_normal(data, stream_len, setup);
-	}
-
-	data++; /* add 1 to every value so we can use 0 as escape symbol */
-
-	/* use zero as escape symbol */
-	stream_len = encode_normal(0, stream_len, setup);
-	if (stream_len <= 0)
-		return stream_len;
-
-	/* put the data unencoded in the bitstream */
-	stream_len = put_n_bits32(data, setup->max_value_bits, stream_len,
-				  setup->bitstream_adr, setup->max_bit_len);
-
-	return stream_len;
-
-}
-
-
-/**
- * @brief subtract the model from the data, encode the result and put it into
- *	bitstream, for encoding outlier use the multi escape symbol mechanism
- *
- * @param data		data to encode
- * @param model		model of the data (0 if not used)
- * @param stream_len	length of the bitstream in bits
- * @param setup		pointer to the encoder setup
- *
- * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
- *	is too small to put the value in the bitstream
- *
- * @note no check if data or model are in the allowed range
- * @note no check if the setup->outlier_par is in the allowed ragne
- */
-
-static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
-			      struct encoder_setupt *setup)
-{
-	uint32_t unencoded_data;
-	unsigned int unencoded_data_len;
-	uint32_t escape_sym, escape_sym_offset;
-
-	data -= model; /* possible underflow is intended */
-
-	data = map_to_pos(data, setup->max_value_bits);
-
-	if (data < setup->outlier_par) /* detect non-outlier */
-		return  encode_normal(data, stream_len, setup);
-
-	/*
-	 * In this mode we put the difference between the data and the spillover
-	 * threshold value (unencoded_data) after a encoded escape symbol, which
-	 * indicate that the next codeword is unencoded.
-	 * We use different escape symbol depended on the size the needed bit of
-	 * unencoded data:
-	 * 0, 1, 2 bits needed for unencoded data -> escape symbol is outlier_par + 0
-	 * 3, 4 bits needed for unencoded data -> escape symbol is outlier_par + 1
-	 * 5, 6 bits needed for unencoded data -> escape symbol is outlier_par + 2
-	 * and so on
-	 */
-	unencoded_data = data - setup->outlier_par;
-
-	if (!unencoded_data) /* catch __builtin_clz(0) because the result is undefined.*/
-		escape_sym_offset = 0;
-	else
-		escape_sym_offset = (31U - (uint32_t)__builtin_clz(unencoded_data)) >> 1;
-
-	escape_sym = setup->outlier_par + escape_sym_offset;
-	unencoded_data_len = (escape_sym_offset + 1U) << 1;
-
-	/* put the escape symbol in the bitstream */
-	stream_len = encode_normal(escape_sym, stream_len, setup);
-	if (stream_len <= 0)
-		return stream_len;
-
-	/* put the unencoded data in the bitstream */
-	stream_len = put_n_bits32(unencoded_data, unencoded_data_len, stream_len,
-				  setup->bitstream_adr, setup->max_bit_len);
-
-	return stream_len;
-}
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 7c00d56..99e80c6 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -32,6 +32,38 @@
 #include "cmp_data_types.h"
 
 
+/* directory to convert from data_type to string */
+static const struct {
+	enum cmp_data_type data_type;
+	const char *str;
+} data_type_string_table[] = {
+	{DATA_TYPE_IMAGETTE, "DATA_TYPE_IMAGETTE"},
+	{DATA_TYPE_IMAGETTE_ADAPTIVE, "DATA_TYPE_IMAGETTE_ADAPTIVE"},
+	{DATA_TYPE_SAT_IMAGETTE, "DATA_TYPE_SAT_IMAGETTE"},
+	{DATA_TYPE_SAT_IMAGETTE_ADAPTIVE, "DATA_TYPE_SAT_IMAGETTE_ADAPTIVE"},
+	{DATA_TYPE_OFFSET, "DATA_TYPE_OFFSET"},
+	{DATA_TYPE_BACKGROUND, "DATA_TYPE_BACKGROUND"},
+	{DATA_TYPE_SMEARING, "DATA_TYPE_SMEARING"},
+	{DATA_TYPE_S_FX, "DATA_TYPE_S_FX"},
+	{DATA_TYPE_S_FX_DFX, "DATA_TYPE_S_FX_DFX"},
+	{DATA_TYPE_S_FX_NCOB, "DATA_TYPE_S_FX_NCOB"},
+	{DATA_TYPE_S_FX_DFX_NCOB_ECOB, "DATA_TYPE_S_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_L_FX, "DATA_TYPE_L_FX"},
+	{DATA_TYPE_L_FX_DFX, "DATA_TYPE_L_FX_DFX"},
+	{DATA_TYPE_L_FX_NCOB, "DATA_TYPE_L_FX_NCOB"},
+	{DATA_TYPE_L_FX_DFX_NCOB_ECOB, "DATA_TYPE_L_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_F_FX, "DATA_TYPE_F_FX"},
+	{DATA_TYPE_F_FX_DFX, "DATA_TYPE_F_FX_DFX"},
+	{DATA_TYPE_F_FX_NCOB, "DATA_TYPE_F_FX_NCOB"},
+	{DATA_TYPE_F_FX_DFX_NCOB_ECOB, "DATA_TYPE_F_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_F_CAM_IMAGETTE, "DATA_TYPE_F_CAM_IMAGETTE"},
+	{DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE, "DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE"},
+	{DATA_TYPE_F_CAM_OFFSET, "DATA_TYPE_F_CAM_OFFSET"},
+	{DATA_TYPE_F_CAM_BACKGROUND, "DATA_TYPE_F_CAM_BACKGROUND"},
+	{DATA_TYPE_UNKOWN, "DATA_TYPE_UNKOWN"}
+};
+
+
 /**
  * @brief print help information
  *
@@ -114,31 +146,34 @@ static FILE *open_file(const char *dirname, const char *filename)
 
 
 /**
- * @brief write a uint16_t buffer to an output file
- *
- * @param buf		the buffer to write a file
- * @param buf_len	length of the buffer
+ * @brief write uncompressed input data to an output file
  *
+ * @param data		the data to write a file
+ * @param data_size	size of the data in bytes
  * @param output_prefix  file name without file extension
  * @param name_extension file extension (with leading point character)
- *
  * @param verbose	print verbose output if not zero
  *
  * @returns 0 on success, error otherwise
  */
 
-int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
-		    *output_prefix, const char *name_extension, int verbose)
+int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type data_type,
+			     const char *output_prefix, const char *name_extension, int verbose)
 {
-	uint32_t i;
+	uint32_t i = 0;
 	FILE *fp;
+	uint8_t *tmp_buf;
+	size_t sample_size = size_of_a_sample(data_type);
 
-	if (!buf)
+	if (!data)
 		abort();
 
-	if (buf_len == 0)
+	if (data_size == 0)
 		return 0;
 
+	if (!sample_size)
+		return -1;
+
 	fp = open_file(output_prefix, name_extension);
 	if (fp == NULL) {
 		fprintf(stderr, "%s: %s%s: %s\n", PROGRAM_NAME, output_prefix,
@@ -146,8 +181,12 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 		return -1;
 	}
 
-	for (i = 0; i < buf_len; i++) {
-		fprintf(fp, "%02X %02X", buf[i] >> 8, buf[i] & 0xFF);
+	tmp_buf = malloc(data_size);
+	memcpy(tmp_buf, data, data_size);
+	cmp_input_big_to_cpu_endianness(tmp_buf, data_size, data_type);
+
+	for (i = 0 ; i < data_size; i++) {
+		fprintf(fp, "%02X",  tmp_buf[i]);
 		if ((i + 1) % 16 == 0)
 			fprintf(fp, "\n");
 		else
@@ -159,8 +198,8 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 
 	if (verbose) {
 		printf("\n\n");
-			for (i = 0; i < buf_len; i++) {
-				printf("%02X %02X", buf[i] >> 8, buf[i] & 0xFF);
+			for (i = 0; i < data_size; i++) {
+				printf("%02X ", tmp_buf[i]);
 			if ((i + 1) % 16 == 0)
 				printf("\n");
 			else
@@ -170,6 +209,7 @@ int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
 		printf("\n\n");
 	}
 
+	free(tmp_buf);
 	return 0;
 }
 
@@ -356,6 +396,67 @@ int atoui32(const char *dep_str, const char *val_str, uint32_t *red_val)
 }
 
 
+/**
+ * @brief parse a compression data_type string to a data_type
+ * @note string can be either a number or the name of the compression data type
+ *
+ * @param data_type_str	string containing the compression data type to parse
+ *
+ * @returns data type on success, DATA_TYPE_UNKOWN on error
+ */
+
+enum cmp_data_type string2data_type(const char *data_type_str)
+{
+	enum cmp_data_type data_type = DATA_TYPE_UNKOWN;
+
+	if (data_type_str) {
+		if (isalpha(data_type_str[0])) {  /* check if mode is given as text */
+			size_t j;
+
+			for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
+				if (!strcmp(data_type_str, data_type_string_table[j].str)) {
+					data_type = data_type_string_table[j].data_type;
+					break;
+				}
+			}
+		} else {
+			uint32_t read_val;
+
+			if (!atoui32("Compression Data Type", data_type_str, &read_val)) {
+				data_type = read_val;
+				if (!cmp_data_type_valid(data_type))
+					data_type = DATA_TYPE_UNKOWN;
+			}
+		}
+	}
+	return data_type;
+}
+
+/**
+ * @brief parse a compression data_type string to a data_type
+ * @note string can be either a number or the name of the compression data type
+ *
+ * @param data_type compression data type to convert in string
+ *
+ * @returns data type on success, DATA_TYPE_UNKOWN on error
+ */
+
+const char *data_type2string(enum cmp_data_type data_type)
+{
+	size_t j;
+	const char *string = "DATA_TYPE_UNKOWN";
+
+	for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
+		if (data_type == data_type_string_table[j].data_type) {
+			string = data_type_string_table[j].str;
+			break;
+		}
+	}
+
+	return string;
+}
+
+
 /**
  * @brief parse a compression mode vale string to an integer
  * @note string can be either a number or the name of the compression mode
@@ -373,11 +474,16 @@ int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
 		uint32_t  cmp_mode;
 		const char *str;
 	} conversion[] = {
-		{MODE_RAW, "MODE_RAW"},
-		{MODE_MODEL_ZERO, "MODE_MODEL_ZERO"},
-		{MODE_DIFF_ZERO, "MODE_DIFF_ZERO"},
-		{MODE_MODEL_MULTI, "MODE_MODEL_MULTI"},
-		{MODE_DIFF_MULTI, "MODE_DIFF_MULTI"},
+		{CMP_MODE_RAW, "MODE_RAW"},
+		{CMP_MODE_MODEL_ZERO, "MODE_MODEL_ZERO"},
+		{CMP_MODE_DIFF_ZERO, "MODE_DIFF_ZERO"},
+		{CMP_MODE_MODEL_MULTI, "MODE_MODEL_MULTI"},
+		{CMP_MODE_DIFF_MULTI, "MODE_DIFF_MULTI"},
+		{CMP_MODE_RAW, "CMP_MODE_RAW"},
+		{CMP_MODE_MODEL_ZERO, "CMP_MODE_MODEL_ZERO"},
+		{CMP_MODE_DIFF_ZERO, "CMP_MODE_DIFF_ZERO"},
+		{CMP_MODE_MODEL_MULTI, "CMP_MODE_MODEL_MULTI"},
+		{CMP_MODE_DIFF_MULTI, "CMP_MODE_DIFF_MULTI"},
 	};
 
 	if (!cmp_mode_str)
@@ -398,7 +504,7 @@ int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
 			return -1;
 	}
 
-	if (!cmp_mode_available(*cmp_mode))
+	if (!cmp_mode_is_supported(*cmp_mode))
 		return -1;
 
 	return 0;
@@ -450,9 +556,16 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 			continue;
 
 
+		if (!strcmp(token1, "data_type")) {
+			cfg->data_type = string2data_type(token2);
+			if (cfg->data_type == DATA_TYPE_UNKOWN)
+				return -1;
+			continue;
+		}
 		if (!strcmp(token1, "cmp_mode")) {
 			must_read_items[CMP_MODE] = 1;
 			if (isalpha(*token2)) { /* check if mode is given as text or val*/
+				/* TODO: use conversion function for this: */
 				if (!strcmp(token2, "MODE_RAW")) {
 					cfg->cmp_mode = 0;
 					continue;
@@ -645,12 +758,6 @@ int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 		printf("\n");
 	}
 
-	if (cfg->buffer_length < cfg->samples/2) {
-		fprintf(stderr,
-			"%s: warning: buffer_length: %u is relative small to the chosen samples parameter of %u.\n",
-			PROGRAM_NAME, cfg->buffer_length, cfg->samples);
-	}
-
 	return 0;
 }
 
@@ -705,6 +812,7 @@ static int parse_info(FILE *fp, struct cmp_info *info)
 		if (!strcmp(token1, "cmp_mode_used")) {
 			must_read_items[CMP_MODE_USED] = 1;
 			if (isalpha(*token2)) { /* check if mode is given as text or val*/
+				/* TODO: use conversion function for this: */
 				if (!strcmp(token2, "MODE_RAW")) {
 					info->cmp_mode_used = 0;
 					continue;
@@ -1013,7 +1121,7 @@ static uint8_t str_to_uint8(const char *str, char **str_end)
 
 
 /**
- * @brief reads n_word words of a hex-encoded string to a uint8_t buffer
+ * @brief reads buf_size words of a hex-encoded string to a uint8_t buffer
  *
  * @note A whitespace (space (0x20), form feed (0x0c), line feed (0x0a), carriage
  *	return (0x0d), horizontal tab (0x09), or vertical tab (0x0b) or several in a
@@ -1026,14 +1134,14 @@ static uint8_t str_to_uint8(const char *str, char **str_end)
  *
  * @param str		pointer to the null-terminated byte string to be interpreted
  * @param data		buffer to write the interpreted content (can be NULL)
- * @param n_word	number of uint8_t data words to read in
+ * @param buf_size	number of uint8_t data words to read in
  * @param file_name	file name for better error output (can be NULL)
  * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the string content; negative on error
  */
 
-static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
+static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t buf_size,
 			     const char *file_name, int verbose_en)
 {
 	const char *nptr = str;
@@ -1043,12 +1151,12 @@ static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
 	errno = 0;
 
 	if (!data)
-		n_word = ~0;
+		buf_size = ~0;
 
 	if (!file_name)
 		file_name = "unknown file name";
 
-	for (i = 0; i < n_word; ) {
+	for (i = 0; i < buf_size; ) {
 		uint8_t read_val;
 		unsigned char c = *nptr;
 
@@ -1118,8 +1226,7 @@ static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
 
 
 /**
- * @brief reads n_word words of a hex-encoded uint8_t data form a file to a
- *	buffer
+ * @brief reads hex-encoded uint8_t data form a file to a buffer
  *
  * @note A whitespace (space (0x20), form feed (0x0c), line feed (0x0a), carriage
  *	return (0x0d), horizontal tab (0x09), or vertical tab (0x0b) or several in a
@@ -1132,13 +1239,13 @@ static ssize_t str2uint8_arr(const char *str, uint8_t *data, uint32_t n_word,
  *
  * @param file_name	data/model file name
  * @param buf		buffer to write the file content (can be NULL)
- * @param n_word	number of uint8_t data words to read in
+ * @param buf_size	number of uint8_t data words to read in
  * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the file content; negative on error
  */
 
-ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int verbose_en)
+ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t buf_size, int verbose_en)
 {
 	FILE *fp;
 	char *file_cpy = NULL;
@@ -1165,6 +1272,10 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int ver
 		fclose(fp);
 		return 0;
 	}
+	if (file_size < buf_size) {
+		fprintf(stderr, "%s: %s: Error: The files do not contain enough data as requested.\n", PROGRAM_NAME, file_name);
+		goto fail;
+	}
 	/* reset the file position indicator to the beginning of the file */
 	if (fseek(fp, 0L, SEEK_SET) != 0)
 		goto fail;
@@ -1188,7 +1299,7 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, int ver
 	fclose(fp);
 	fp = NULL;
 
-	size = str2uint8_arr(file_cpy, buf, n_word, file_name, verbose_en);
+	size = str2uint8_arr(file_cpy, buf, buf_size, file_name, verbose_en);
 
 	free(file_cpy);
 	file_cpy = NULL;
@@ -1206,75 +1317,38 @@ fail:
 
 
 /**
- * @brief reads the number of uint16_t samples of a hex-encoded data (or model)
- *	file into a buffer
+ * @brief reads hex-encoded data from a file into a buffer
  *
  * @param file_name	data/model file name
+ * @param data_type	compression data type used for the data
  * @param buf		buffer to write the file content (can be NULL)
- * @param samples	amount of uint16_t data samples to read in
+ * @param buf_size	size in bytes of the buffer
  * @param verbose_en	print verbose output if not zero
  *
  * @returns the size in bytes to store the file content; negative on error
  */
 
-ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples,
-		    int verbose_en)
+ssize_t read_file_data(const char *file_name, enum cmp_data_type data_type,
+		       void *buf, uint32_t buf_size, int verbose_en)
 {
-	ssize_t size = read_file8(file_name, (uint8_t *)buf,
-				  samples*sizeof(uint16_t), verbose_en);
+	ssize_t size;
+	int samples, err;
+
+	size = read_file8(file_name, (uint8_t *)buf, buf_size, verbose_en);
 
 	if (size < 0)
 		return size;
 
-	if (size & 0x1) {
-		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 2 hex words.\n",
+	samples = cmp_input_size_to_samples(size, data_type);
+	if (samples < 0) {
+		fprintf(stderr, "%s: %s: Error: The data are not correct formatted for the used compression data type.\n",
 				PROGRAM_NAME, file_name);
 		return -1;
 	}
 
-	if (buf) {
-		size_t i;
-		for (i = 0; i < samples; i++)
-			be16_to_cpus(&buf[i]);
-	}
-
-
-	return size;
-}
-
-
-/**
- * @brief reads the number of uint32_t samples of a hex-encoded data (or model)
- *	file into a buffer
- *
- * @param file_name	data/model file name
- * @param buf		buffer to write the file content (can be NULL)
- * @param samples	amount of uint32_t data samples to read in
- * @param verbose_en	print verbose output if not zero
- *
- * @returns the size in bytes to store the file content; negative on error
- */
-
-ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
-		    int verbose_en)
-{
-	ssize_t size = read_file8(file_name, (uint8_t *)buf,
-				  samples*sizeof(uint32_t), verbose_en);
-
-	if (size < 0)
-		return -1;
-
-	if (size & 0x3) {
-		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 4 hex words.\n",
-				PROGRAM_NAME, file_name);
+	err = cmp_input_big_to_cpu_endianness(buf, size, data_type);
+	if (err)
 		return -1;
-	}
-
-	if (buf) {
-		size_t i;
-		for (i = 0; i < samples; i++)
-			be32_to_cpus(&buf[i]);
-	}
 
 	return size;
 }
@@ -1292,7 +1366,7 @@ ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
  */
 
 ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
-			   uint32_t ent_size, int verbose_en)
+			     uint32_t ent_size, int verbose_en)
 {
 	ssize_t size;
 
@@ -1307,9 +1381,9 @@ ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 	}
 
 	if (ent) {
-		enum cmp_ent_data_type data_type = cmp_ent_get_data_type(ent);
+		enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
 
-		if (!cmp_ent_data_type_valid(data_type)) {
+		if (data_type == DATA_TYPE_UNKOWN) {
 			fprintf(stderr, "%s: %s: Error: Compression data type is not supported.\n",
 				PROGRAM_NAME, file_name);
 			return -1;
@@ -1328,6 +1402,41 @@ ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 }
 
 
+/**
+ * @brief reads hex-encoded uint32_t samples from a file into a buffer
+ *
+ * @param file_name	data/model file name
+ * @param buf		buffer to write the file content (can be NULL)
+ * @param buf_size	size of the buf buffer in bytes
+ * @param verbose_en	print verbose output if not zero
+ *
+ * @returns the size in bytes to store the file content; negative on error
+ */
+
+ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_size,
+		    int verbose_en)
+{
+	ssize_t size = read_file8(file_name, (uint8_t *)buf, buf_size, verbose_en);
+
+	if (size < 0)
+		return -1;
+
+	if (size & 0x3) {
+		fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 4 hex words.\n",
+				PROGRAM_NAME, file_name);
+		return -1;
+	}
+
+	if (buf) {
+		size_t i;
+		for (i = 0; i < buf_size/sizeof(uint32_t); i++)
+			be32_to_cpus(&buf[i]);
+	}
+
+	return size;
+}
+
+
 /*
  * @brief generate from the cmp_tool version string a version_id for the
  * compression entity header
@@ -1371,7 +1480,7 @@ uint32_t cmp_tool_gen_version_id(const char *version)
 
 	version_id |= n;
 
-	return version_id |= CMP_TOOL_VERSION_ID_BIT;
+	return version_id | CMP_TOOL_VERSION_ID_BIT;
 }
 
 
@@ -1389,6 +1498,10 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg, int rdcu_cfg
 	fprintf(fp, "#-------------------------------------------------------------------------------\n");
 	fprintf(fp, "# Default Configuration File\n");
 	fprintf(fp, "#-------------------------------------------------------------------------------\n");
+	fprintf(fp, "# Selected compression data type\n");
+	fprintf(fp, "\n");
+	fprintf(fp, "data_type = %u\n", cfg->data_type);
+	fprintf(fp, "\n");
 	fprintf(fp, "# Selected compression mode\n");
 	fprintf(fp, "# 0: raw mode\n");
 	fprintf(fp, "# 1: model mode with zero escape symbol mechanism\n");
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index c24ebed..34606f4 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -15,21 +15,36 @@
  *
  * @brief hardware compressor control library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
+ *
+ * To compress data, first create a compression configuration with the
+ * rdcu_cfg_create() function.
+ * Then set the different data buffers with the data to compressed, the model
+ * data and the RDCU SRAM addresses with the rdcu_cfg_buffers() function.
+ * Then set the imagette compression parameters with the rdcu_cfg_imagette()
+ * function.
+ * Finally, you can compress the data with the RDCU using the
+ * rdcu_compress_data() function.
  */
 
 #include <stdint.h>
 #include <stdio.h>
 
-#include "../include/rdcu_cmd.h"
-#include "../include/cmp_support.h"
-#include "../include/rdcu_ctrl.h"
-#include "../include/rdcu_rmap.h"
+#include "rdcu_cmd.h"
+#include "cmp_support.h"
+#include "cmp_data_types.h"
+#include "rdcu_ctrl.h"
+#include "rdcu_rmap.h"
+#include "cmp_debug.h"
+
 
+#define IMA_SAM2BYT                                                            \
+	2 /* imagette sample to byte conversion factor; one imagette samples has 16 bits (2 bytes) */
 
 #define RDCU_INTR_SIG_ENA 1 /* RDCU interrupt signal enabled */
 #define RDCU_INTR_SIG_DIS 0 /* RDCU interrupt signal disable */
-#define RDCU_INTR_SIG_DEFAULT RDCU_INTR_SIG_ENA /* default start value for RDCU
-						   interrupt signal */
+#define RDCU_INTR_SIG_DEFAULT RDCU_INTR_SIG_ENA /* default start value for RDCU interrupt signal */
+
+
 /* RDCU interrupt signal status */
 static int interrupt_signal_enabled = RDCU_INTR_SIG_DEFAULT;
 
@@ -48,6 +63,7 @@ static void sync(void)
 	not needed for packed generation
 
 	int cnt = 0;
+
 	printf("syncing...");
 	while (rdcu_rmap_sync_status()) {
 		printf("pending: %d\n", rdcu_rmap_sync_status());
@@ -63,6 +79,84 @@ static void sync(void)
 }
 
 
+/**
+ * @brief check if the compression data product type, compression mode, model
+ *	value and the lossy rounding parameters are valid for a RDCU compression
+ *
+ * @param cfg	pointer to a compression configuration containing the compression
+ *	data product type, compression mode, model value and the rounding parameters
+ *
+ * @returns 0 if the compression data type, compression mode, model value and
+ *	the lossy rounding parameters are valid for a RDCU compression, non-zero
+ *	if parameters are invalid
+ */
+
+static int rdcu_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cfg)
+		return -1;
+
+	if (!cmp_imagette_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The selected compression data type is not supported for RDCU compression");
+		cfg_invalid++;
+	}
+
+	if (cfg->cmp_mode > MAX_RDCU_CMP_MODE) {
+		debug_print("Error: selected cmp_mode: %u is not supported. Largest supported mode is: %u.\n",
+			    cfg->cmp_mode, MAX_RDCU_CMP_MODE);
+		cfg_invalid++;
+	}
+
+	if (cfg->model_value > MAX_MODEL_VALUE) {
+		debug_print("Error: selected model_value: %u is invalid. Largest supported value is: %u.\n",
+			    cfg->model_value, MAX_MODEL_VALUE);
+		cfg_invalid++;
+	}
+
+	if (cfg->round > MAX_RDCU_ROUND) {
+		debug_print("Error: selected round parameter: %u is not supported. Largest supported value is: %u.\n",
+			    cfg->round, MAX_RDCU_ROUND);
+		cfg_invalid++;
+	}
+
+#ifdef SKIP_CMP_PAR_CHECK
+	return 0;
+#endif
+
+	return -cfg_invalid;
+}
+
+
+/**
+ * @brief create a RDCU compression configuration
+ *
+ * @param data_type	compression data product types
+ * @param cmp_mode	compression mode
+ * @param model_value	model weighting parameter (only need for model compression mode)
+ * @param lossy_par	lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
+ *
+ * @returns compression configuration containing the chosen parameters;
+ *	on error the data_type record is set to DATA_TYPE_UNKOWN
+ */
+
+struct cmp_cfg rdcu_cfg_create(enum cmp_ent_data_type data_type, enum cmp_mode cmp_mode,
+			       uint32_t model_value, uint32_t lossy_par)
+{
+	struct cmp_cfg cfg = {0};
+
+	cfg.data_type = data_type;
+	cfg.cmp_mode = cmp_mode;
+	cfg.model_value = model_value;
+	cfg.round = lossy_par;
+
+	if (rdcu_cfg_gen_par_is_invalid(&cfg))
+		cfg.data_type = DATA_TYPE_UNKOWN;
+
+	return cfg;
+}
+
 /**
  * @brief check if a buffer is in inside the RDCU SRAM
  *
@@ -99,6 +193,7 @@ static int in_sram_range(uint32_t addr, uint32_t size)
  * @returns 0 if buffers are not overlapping, otherwise buffer are
  *	overlapping
  */
+
 static int buffers_overlap(uint32_t start_a, uint32_t end_a, uint32_t start_b,
 			   uint32_t end_b)
 {
@@ -110,302 +205,373 @@ static int buffers_overlap(uint32_t start_a, uint32_t end_a, uint32_t start_b,
 
 
 /**
- * @brief check if the compressor configuration is valid for a RDCU compression,
- * see the user manual for more information (PLATO-UVIE-PL-UM-0001).
+ * @brief check if RDCU buffer settings are invalid
  *
- * @param cfg	configuration contains all parameters required for compression
+ * @param cfg	a pointer to a compression configuration
  *
- * @returns  >= 0 on success, error otherwise
+ * @returns 0 if buffers configuration is valid, otherwise the configuration is
+ *	invalid
  */
 
-int rdcu_cmp_cfg_valid(const struct cmp_cfg *cfg)
+static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
-	int cfg_warning = 0;
-
-	if (cfg == NULL)
-		return -1;
-
-	if (cfg->cmp_mode > MAX_RDCU_CMP_MODE) {
-		printf("Error: selected cmp_mode: %u is not supported. "
-		       "Largest supported mode is: %lu.\n", cfg->cmp_mode,
-		       MAX_RDCU_CMP_MODE);
-		cfg_invalid++;
-	}
-
-	if (cfg->model_value > MAX_MODEL_VALUE) {
-		printf("Error: selected model_value: %u is invalid. "
-		       "Largest supported value is: %lu.\n", cfg->model_value,
-		       MAX_MODEL_VALUE);
-		cfg_invalid++;
-	}
-
-	if (cfg->golomb_par < MIN_RDCU_GOLOMB_PAR||
-	    cfg->golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		printf("Error: The selected Golomb parameter: %u is not supported. "
-		       "The Golomb parameter has to  be between [%lu, %lu].\n",
-		       cfg->golomb_par, MIN_RDCU_GOLOMB_PAR,
-		       MAX_RDCU_GOLOMB_PAR);
-		cfg_invalid++;
-	}
-
-	if (cfg->ap1_golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->ap1_golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		printf("Error: The selected adaptive 1 Golomb parameter: %u is not supported. "
-		       "The Golomb parameter has to  be between [%lu, %lu].\n",
-		       cfg->ap1_golomb_par, MIN_RDCU_GOLOMB_PAR,
-		       MAX_RDCU_GOLOMB_PAR);
-		cfg_invalid++;
-	}
 
-	if (cfg->ap2_golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->ap2_golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		printf("Error: The selected adaptive 2 Golomb parameter: %u is not supported. "
-		       "The Golomb parameter has to be between [%lu, %lu].\n",
-		       cfg->ap2_golomb_par, MIN_RDCU_GOLOMB_PAR,
-		       MAX_RDCU_GOLOMB_PAR);
-		cfg_invalid++;
-	}
-
-	if (cfg->spill < MIN_RDCU_SPILL) {
-		printf("Error: The selected spillover threshold value: %u is too small. "
-		       "Smallest possible spillover value is: %lu.\n",
-		       cfg->spill, MIN_RDCU_SPILL);
-		cfg_invalid++;
-	}
-
-	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->cmp_mode)) {
-		printf("Error: The selected spillover threshold value: %u is "
-		       "too large for the selected Golomb parameter: %u, the "
-		       "largest possible spillover value is: %u.\n",
-		       cfg->spill, cfg->golomb_par,
-		       get_max_spill(cfg->golomb_par, cfg->cmp_mode));
-		cfg_invalid++;
-	}
-
-	if (cfg->ap1_spill < MIN_RDCU_SPILL) {
-		printf("Error: The selected adaptive 1 spillover threshold "
-		       "value: %u is too small. "
-		       "Smallest possible spillover value is: %lu.\n",
-		       cfg->ap1_spill, MIN_RDCU_SPILL);
-		cfg_invalid++;
-	}
-
-	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->cmp_mode)) {
-		printf("Error: The selected adaptive 1 spillover threshold "
-		       "value: %u is too large for the selected adaptive 1 "
-		       "Golomb parameter: %u, the largest possible adaptive 1 "
-		       "spillover value is: %u.\n",
-		       cfg->ap1_spill, cfg->ap1_golomb_par,
-		       get_max_spill(cfg->ap1_golomb_par, cfg->cmp_mode));
-		cfg_invalid++;
-	}
-
-	if (cfg->ap2_spill < MIN_RDCU_SPILL) {
-		printf("Error: The selected adaptive 2 spillover threshold "
-		       "value: %u is too small."
-		       "Smallest possible spillover value is: %lu.\n",
-		       cfg->ap2_spill, MIN_RDCU_SPILL);
-		cfg_invalid++;
-	}
-
-	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->cmp_mode)) {
-		printf("Error: The selected adaptive 2 spillover threshold "
-		       "value: %u is too large for the selected adaptive 2 "
-		       "Golomb parameter: %u, the largest possible adaptive 2 "
-		       "spillover value is: %u.\n",
-		       cfg->ap2_spill, cfg->ap2_golomb_par,
-		       get_max_spill(cfg->ap2_golomb_par, cfg->cmp_mode));
-		cfg_invalid++;
-	}
-
-	if (cfg->round > MAX_RDCU_ROUND) {
-		printf("Error: selected round parameter: %u is not supported. "
-		       "Largest supported value is: %lu.\n",
-		       cfg->round, MAX_RDCU_ROUND);
-		cfg_invalid++;
-	}
-
-	if (cfg->samples == 0) {
-		printf("Warning: The samples parameter is set to 0. No data will be compressed.\n");
-		cfg_warning++;
-	}
-
-	if (cfg->buffer_length == 0) {
-		printf("Error: The buffer_length is set to 0. There is no place "
-		       "to store the compressed data.\n");
-		cfg_invalid++;
-	}
-
-	if (cfg->cmp_mode == MODE_RAW) {
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
 		if (cfg->buffer_length < cfg->samples) {
-			printf("buffer_length is smaller than samples parameter. "
-			       "There is not enough space to copy the data in "
-			       "RAW mode.\n");
+			debug_print("rdcu_buffer_length is smaller than samples parameter. There is not enough space to copy the data in RAW mode.\n");
 			cfg_invalid++;
 		}
 	}
 
-	if (!cfg->input_buf) {
-		printf("Warning: The data to compress buffer is set to NULL. "
-		       "No data will be transferred to the rdcu_data_adr in  "
-		       "the RDCU-SRAM.\n");
-		cfg_warning++;
-	}
-
 	if (cfg->rdcu_data_adr & 0x3) {
-		printf("Error: The RDCU data to compress start address is not 4-Byte aligned.\n");
+		debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned.\n");
 		cfg_invalid++;
 	}
 
 	if (cfg->rdcu_buffer_adr & 0x3) {
-		printf("Error: The RDCU compressed data start address is not 4-Byte aligned.\n");
+		debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned.\n");
 		cfg_invalid++;
 	}
 
-	if (!in_sram_range(cfg->rdcu_data_adr, cfg->samples * SAM2BYT)) {
-		printf("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.\n");
+	if (!in_sram_range(cfg->rdcu_data_adr, cfg->samples * IMA_SAM2BYT)) {
+		debug_print("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.\n");
 		cfg_invalid++;
 	}
 
-	if (!in_sram_range(cfg->rdcu_buffer_adr, cfg->buffer_length * SAM2BYT)) {
-		printf("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.\n");
+	if (!in_sram_range(cfg->rdcu_buffer_adr, cfg->buffer_length * IMA_SAM2BYT)) {
+		debug_print("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.\n");
 		cfg_invalid++;
 	}
 
 	if (buffers_overlap(cfg->rdcu_data_adr,
-			    cfg->rdcu_data_adr + cfg->samples * SAM2BYT,
+			    cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT,
 			    cfg->rdcu_buffer_adr,
-			    cfg->rdcu_buffer_adr + cfg->buffer_length * SAM2BYT)) {
-		printf("Error: The RDCU data to compress buffer and the RDCU "
-		       "compressed data buffer are overlapping.\n");
+			    cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT)) {
+		debug_print("Error: The RDCU data to compress buffer and the RDCU compressed data buffer are overlapping.\n");
 		cfg_invalid++;
 	}
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->model_buf == cfg->input_buf) {
-			printf("Error: The model buffer (model_buf) and the data "
-			       "to be compressed (input_buf) are equal.");
+		if (cfg->model_buf && cfg->model_buf == cfg->input_buf) {
+			debug_print("Error: The model buffer (model_buf) and the data to be compressed (input_buf) are equal.");
 			cfg_invalid++;
 		}
 
-		if (!cfg->model_buf) {
-			printf("Warning: The model buffer is set to NULL. No "
-			       "model data will be transferred to the "
-			       "rdcu_model_adr in the RDCU-SRAM.\n");
-			cfg_warning++;
-		}
-
 		if (cfg->rdcu_model_adr & 0x3) {
-			printf("Error: The RDCU model start address is not 4-Byte aligned.\n");
+			debug_print("Error: The RDCU model start address is not 4-Byte aligned.\n");
 			cfg_invalid++;
 		}
 
-		if (!in_sram_range(cfg->rdcu_model_adr, cfg->samples * SAM2BYT)) {
-			printf("Error: The RDCU model buffer is outside the RDCU SRAM address space.\n");
+		if (!in_sram_range(cfg->rdcu_model_adr, cfg->samples * IMA_SAM2BYT)) {
+			debug_print("Error: The RDCU model buffer is outside the RDCU SRAM address space.\n");
 			cfg_invalid++;
 		}
 
 		if (buffers_overlap(
 			    cfg->rdcu_model_adr,
-			    cfg->rdcu_model_adr + cfg->samples * SAM2BYT,
+			    cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT,
 			    cfg->rdcu_data_adr,
-			    cfg->rdcu_data_adr + cfg->samples * SAM2BYT)) {
-			printf("Error: The model buffer and the data to compress buffer are overlapping.\n");
+			    cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT)) {
+			debug_print("Error: The model buffer and the data to compress buffer are overlapping.\n");
 			cfg_invalid++;
 		}
 
 		if (buffers_overlap(
 			cfg->rdcu_model_adr,
-			cfg->rdcu_model_adr + cfg->samples * SAM2BYT,
+			cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT,
 			cfg->rdcu_buffer_adr,
-			cfg->rdcu_buffer_adr + cfg->buffer_length * SAM2BYT)
-		    ){
-			printf("Error: The model buffer and the compressed data buffer are overlapping.\n");
+			cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT)
+		    ) {
+			debug_print("Error: The model buffer and the compressed data buffer are overlapping.\n");
 			cfg_invalid++;
 		}
 
 		if (cfg->rdcu_model_adr != cfg->rdcu_new_model_adr) {
 			if (cfg->rdcu_new_model_adr & 0x3) {
-				printf("Error: The RDCU updated model start address "
-				       "(rdcu_new_model_adr) is not 4-Byte aligned.\n");
+				debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned.\n");
 				cfg_invalid++;
 			}
 
 			if (!in_sram_range(cfg->rdcu_new_model_adr,
-					   cfg->samples * SAM2BYT)) {
-				printf("Error: The RDCU updated model buffer is "
-				       "outside the RDCU SRAM address space.\n");
+					   cfg->samples * IMA_SAM2BYT)) {
+				debug_print("Error: The RDCU updated model buffer is outside the RDCU SRAM address space.\n");
 				cfg_invalid++;
 			}
 
 			if (buffers_overlap(
 				cfg->rdcu_new_model_adr,
-				cfg->rdcu_new_model_adr + cfg->samples * SAM2BYT,
+				cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT,
 				cfg->rdcu_data_adr,
-				cfg->rdcu_data_adr + cfg->samples * SAM2BYT)
-			    ){
-				printf("Error: The updated model buffer and the data to "
-				       "compress buffer are overlapping.\n");
+				cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT)
+			    ) {
+				debug_print("Error: The updated model buffer and the data to compress buffer are overlapping.\n");
 				cfg_invalid++;
 			}
 
 			if (buffers_overlap(
 				cfg->rdcu_new_model_adr,
-				cfg->rdcu_new_model_adr + cfg->samples * SAM2BYT,
+				cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT,
 				cfg->rdcu_buffer_adr,
-				cfg->rdcu_buffer_adr + cfg->buffer_length * SAM2BYT)
-			    ){
-				printf("Error: The updated model buffer and the compressed "
-				       "data buffer are overlapping.\n");
+				cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT)
+			    ) {
+				debug_print("Error: The updated model buffer and the compressed data buffer are overlapping.\n");
 				cfg_invalid++;
 			}
 			if (buffers_overlap(
 				cfg->rdcu_new_model_adr,
-				cfg->rdcu_new_model_adr + cfg->samples * SAM2BYT,
+				cfg->rdcu_new_model_adr + cfg->samples * IMA_SAM2BYT,
 				cfg->rdcu_model_adr,
-				cfg->rdcu_model_adr + cfg->samples * SAM2BYT)
-			    ){
-				printf("Error: The updated model buffer and the "
-				       "model buffer are overlapping.\n");
+				cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT)
+			    ) {
+				debug_print("Error: The updated model buffer and the model buffer are overlapping.\n");
 				cfg_invalid++;
 			}
 		}
 	}
 
-	if (cfg->icu_new_model_buf) {
-		printf("Warning: ICU updated model buffer is set. This "
-		       "buffer is not used for an RDCU compression.\n");
-		cfg_warning++;
+	if (cfg->icu_new_model_buf)
+		debug_print("Warning: ICU updated model buffer is set. This buffer is not used for an RDCU compression.\n");
+
+	if (cfg->icu_output_buf)
+		debug_print("Warning: ICU compressed data buffer is set. This buffer is not used for an RDCU compression.\n");
+
+#ifdef SKIP_CMP_PAR_CHECK
+	return 0;
+#endif
+	return -cfg_invalid;
+}
+
+
+/**
+ *@brief setup of the different data buffers for an RDCU compression
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the rdcu_cfg_create() function)
+ * @param data_to_compress	pointer to the data to be compressed (if NULL no
+ *				data transfer to the RDCU)
+ * @param data_samples		length of the data to be compressed measured in
+ *				16-bit data samples (ignoring the multi entity header)
+ * @param model_of_data		pointer to model data buffer (only needed for
+ *				model compression mode, if NULL no model data
+ *				transfer to the RDCU)
+ * @param rdcu_data_adr		RDCU data to compress start address, the first
+ *				data address in the RDCU SRAM
+ * @param rdcu_model_adr	RDCU model start address, the first model address
+ *				in the RDCU SRAM (only need for model compression mode)
+ * @param rdcu_new_model_adr	RDCU new/updated model start address(can be the
+ *				by the same as rdcu_model_adr for in-place model update)
+ * @param rdcu_buffer_adr	RDCU compressed data start address, the first
+ *				output data address in the RDCU SRAM
+ * @param rdcu_buffer_lenght	length of the RDCU compressed data SRAM buffer
+ *				in number of 16-bit samples
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
+
+int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress,
+		     uint32_t data_samples, uint16_t *model_of_data,
+		     uint32_t rdcu_data_adr, uint32_t rdcu_model_adr,
+		     uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr,
+		     uint32_t rdcu_buffer_lenght)
+{
+	if (!cfg) {
+		debug_print("Error: pointer to the compression configuration structure is NULL.\n");
+		return -1;
 	}
 
-	if (cfg->icu_output_buf) {
-		printf("Warning: ICU compressed data buffer is set. This "
-		       "buffer is not used for an RDCU compression.\n");
-		cfg_warning++;
+	cfg->input_buf = data_to_compress;
+	cfg->samples = data_samples;
+	cfg->model_buf = model_of_data;
+	cfg->rdcu_data_adr = rdcu_data_adr;
+	cfg->rdcu_model_adr = rdcu_model_adr;
+	cfg->rdcu_new_model_adr = rdcu_new_model_adr;
+	cfg->rdcu_buffer_adr = rdcu_buffer_adr;
+	cfg->buffer_length = rdcu_buffer_lenght;
+
+	if (rdcu_cfg_buffers_is_invalid(cfg))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the Golomb and spillover threshold parameter combination is
+ *	invalid for a RDCU compression
+ * @note also checked the adaptive Golomb and spillover threshold parameter combinations
+ *
+ * @param cfg	a pointer to a compression configuration
+ *
+ * @returns 0 if (adaptive) Golomb spill threshold parameter combinations are
+ *	valid, otherwise the configuration is invalid
+ */
+
+static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (cfg->golomb_par < MIN_RDCU_GOLOMB_PAR ||
+	    cfg->golomb_par > MAX_RDCU_GOLOMB_PAR) {
+		debug_print("Error: The selected Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%u, %u].\n",
+			    cfg->golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap1_golomb_par < MIN_RDCU_GOLOMB_PAR ||
+	    cfg->ap1_golomb_par > MAX_RDCU_GOLOMB_PAR) {
+		debug_print("Error: The selected adaptive 1 Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%u, %u].\n",
+			    cfg->ap1_golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap2_golomb_par < MIN_RDCU_GOLOMB_PAR ||
+	    cfg->ap2_golomb_par > MAX_RDCU_GOLOMB_PAR) {
+		debug_print("Error: The selected adaptive 2 Golomb parameter: %u is not supported. The Golomb parameter has to be between [%u, %u].\n",
+			    cfg->ap2_golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg_invalid++;
+	}
+
+	if (cfg->spill < MIN_RDCU_SPILL) {
+		debug_print("Error: The selected spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+			    cfg->spill, MIN_RDCU_SPILL);
+		cfg_invalid++;
+	}
+
+	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->data_type)) {
+		debug_print("Error: The selected spillover threshold value: %u is too large for the selected Golomb parameter: %u, the largest possible spillover value is: %u.\n",
+			    cfg->spill, cfg->golomb_par, get_max_spill(cfg->golomb_par, cfg->data_type));
+		cfg_invalid++;
+	}
+
+	if (cfg->ap1_spill < MIN_RDCU_SPILL) {
+		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+			    cfg->ap1_spill, MIN_RDCU_SPILL);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->data_type)) {
+		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too large for the selected adaptive 1 Golomb parameter: %u, the largest possible adaptive 1 spillover value is: %u.\n",
+			    cfg->ap1_spill, cfg->ap1_golomb_par, get_max_spill(cfg->ap1_golomb_par, cfg->data_type));
+		cfg_invalid++;
+	}
+
+	if (cfg->ap2_spill < MIN_RDCU_SPILL) {
+		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+			    cfg->ap2_spill, MIN_RDCU_SPILL);
+		cfg_invalid++;
+	}
+
+	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->data_type)) {
+		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too large for the selected adaptive 2 Golomb parameter: %u, the largest possible adaptive 2 spillover value is: %u.\n",
+			    cfg->ap2_spill, cfg->ap2_golomb_par, get_max_spill(cfg->ap2_golomb_par, cfg->data_type));
+		cfg_invalid++;
 	}
 
 #ifdef SKIP_CMP_PAR_CHECK
 	return 0;
 #endif
-	if (cfg_invalid)
-		return -cfg_invalid;
-	else
-		return cfg_warning;
+
+	return -cfg_invalid;
+}
+
+
+/**
+ * @brief set up the configuration parameters for an RDCU imagette compression
+ *
+ * @param cfg			pointer to a compression configuration (created
+ *				with the rdcu_cfg_create() function)
+ * @param golomb_par		imagette compression parameter (Golomb parameter)
+ * @param spillover_par		imagette spillover threshold parameter
+ * @param ap1_golomb_par	adaptive 1 imagette compression parameter (ap1_golomb parameter)
+ * @param ap1_spillover_par	adaptive 1 imagette spillover threshold parameter
+ * @param ap2_golomb_par	adaptive 2 imagette compression parameter (ap2_golomb parameter)
+ * @param ap2_spillover_par	adaptive 1 imagette spillover threshold parameter
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
+
+int rdcu_cfg_imagette(struct cmp_cfg *cfg,
+		      uint32_t golomb_par, uint32_t spillover_par,
+		      uint32_t ap1_golomb_par, uint32_t ap1_spillover_par,
+		      uint32_t ap2_golomb_par, uint32_t ap2_spillover_par)
+{
+	if (!cfg) {
+		debug_print("Error: pointer to the compression configuration structure is NULL.\n");
+		return -1;
+	}
+
+	cfg->golomb_par = golomb_par;
+	cfg->spill = spillover_par;
+	cfg->ap1_golomb_par = ap1_golomb_par;
+	cfg->ap1_spill = ap1_spillover_par;
+	cfg->ap2_golomb_par = ap2_golomb_par;
+	cfg->ap2_spill = ap2_spillover_par;
+
+	if (rdcu_cfg_imagette_is_invalid(cfg))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the compressor configuration is invalid for a RDCU compression,
+ *	see the user manual for more information (PLATO-UVIE-PL-UM-0001).
+ *
+ * @param cfg	pointer to a compression configuration contains all parameters
+ *	required for compression
+ *
+ * @returns 0 if parameters are valid, non-zero if parameters are invalid
+ */
+
+int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cfg) {
+		debug_print("Error: pointer to the compression configuration structure is NULL.\n");
+		return -1;
+	}
+
+	if (!cfg->input_buf)
+		debug_print("Warning: The data to compress buffer is set to NULL. No data will be transferred to the rdcu_data_adr in the RDCU-SRAM.\n");
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		if (!cfg->model_buf)
+			debug_print("Warning: The model buffer is set to NULL. No model data will be transferred to the rdcu_model_adr in the RDCU-SRAM.\n");
+	}
+
+	if (cfg->input_buf && cfg->samples == 0)
+		debug_print("Warning: The samples parameter is set to 0. No data will be compressed.\n");
+
+	if (cfg->buffer_length == 0) {
+		debug_print("Error: The buffer_length is set to 0. There is no place to store the compressed data.\n");
+		cfg_invalid++;
+	}
+
+	if (rdcu_cfg_gen_par_is_invalid(cfg))
+		cfg_invalid++;
+	if (rdcu_cfg_buffers_is_invalid(cfg))
+		cfg_invalid++;
+	if (rdcu_cfg_imagette_is_invalid(cfg))
+		cfg_invalid++;
+
+	return -cfg_invalid;
 }
 
 
 /**
  * @brief set up RDCU compression register
  *
- * @param cfg  configuration contains all parameters required for compression
+ * @param cfg  pointer to a compression configuration contains all parameters
+ *	required for compression
  *
  * @returns 0 on success, error otherwise
  */
 
 int rdcu_set_compression_register(const struct cmp_cfg *cfg)
 {
-	if (rdcu_cmp_cfg_valid(cfg) < 0)
+	if (rdcu_cmp_cfg_is_invalid(cfg))
 		return -1;
 
 	/* first, set compression parameters in local mirror registers */
@@ -509,8 +675,6 @@ int rdcu_start_compression(void)
  *
  * @note when using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
  *      the model parameters (model_value, model_buf, rdcu_model_adr) are ignored
- * @note the icu_output_buf will not be used for the RDCU compression
- * @note the overlapping of the different rdcu buffers is not checked
  * @note the validity of the cfg structure is checked before the compression is
  *	 started
  *
@@ -700,7 +864,7 @@ int rdcu_read_model(const struct cmp_info *info, void *model_buf)
 		return -1;
 
 	/* calculate the need bytes for the model */
-	s = cmp_cal_size_of_data(info->samples_used, info->cmp_mode_used);
+	s = info->samples_used * IMA_SAM2BYT;
 
 	if (model_buf == NULL)
 		return (int)s;
@@ -790,19 +954,17 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 	if (last_info->cmp_err)
 		return -1;
 
-	/* TODO: check read write buffer overlapping */
-
 	rdcu_set_compression_register(cfg);
 
 	/* round up needed size must be a multiple of 4 bytes */
-	samples_4byte = (cfg->samples * SAM2BYT + 3) & ~3U;
+	samples_4byte = (cfg->samples * IMA_SAM2BYT + 3) & ~3U;
 
 	if (cfg->input_buf != NULL) {
 		uint32_t cmp_size_4byte;
 
 		/* now set the data in the local mirror... */
 		if (rdcu_write_sram_16(cfg->input_buf, cfg->rdcu_data_adr,
-				       cfg->samples * SAM2BYT) < 0)
+				       cfg->samples * IMA_SAM2BYT) < 0)
 			return -1;
 
 		/* calculate the need bytes for the bitstream */
@@ -823,7 +985,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 				return -1;
 		}
 	} else {
-		printf("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the sram\n");
+		debug_print("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the SRAM\n");
 	}
 
 	/* read model and write model in parallel */
@@ -832,10 +994,10 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 
 		/* set the model in the local mirror... */
 		if (rdcu_write_sram_16(cfg->model_buf, cfg->rdcu_model_adr,
-				       cfg->samples * SAM2BYT) < 0)
+				       cfg->samples * IMA_SAM2BYT) < 0)
 			return -1;
 
-		new_model_size_4byte = last_info->samples_used * SAM2BYT ;
+		new_model_size_4byte = last_info->samples_used * IMA_SAM2BYT;
 		if (rdcu_sync_sram_mirror_parallel(last_info->rdcu_new_model_adr_used,
 						   (new_model_size_4byte+3) & ~0x3U,
 						   cfg->rdcu_model_adr,
@@ -853,7 +1015,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg,
 	} else if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode)) {
 		/* set the model in the local mirror... */
 		if (rdcu_write_sram_16(cfg->model_buf, cfg->rdcu_model_adr,
-				       cfg->samples * SAM2BYT) < 0)
+				       cfg->samples * IMA_SAM2BYT) < 0)
 			return -1;
 
 		if (rdcu_sync_mirror_to_sram(cfg->rdcu_model_adr, samples_4byte,
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index 93db7b6..a02e897 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -18,75 +18,15 @@
  */
 
 
-#include "../include/cmp_support.h"
-#include "../include/cmp_data_types.h"
-#include "../include/cmp_debug.h"
-
-
-/**
- * @brief Default configuration of the Compressor in model imagette mode.
- * @warning All ICU buffers are set to NULL. Samples and buffer_length are set to 0
- * @note see PLATO-IWF-PL-RS-0005 V1.1
- */
-
-
-const struct cmp_cfg DEFAULT_CFG_MODEL = {
-	MODE_MODEL_MULTI, /* cmp_mode */
-	4, /* golomb_par */
-	48, /* spill */
-	8, /* model_value */
-	0, /* round */
-	3, /* ap1_golomb_par */
-	35, /* ap1_spill */
-	5, /* ap2_golomb_par */
-	60, /* ap2_spill */
-	NULL, /* *input_buf */
-	0x000000, /* rdcu_data_adr */
-	NULL, /* *model_buf */
-	0x200000, /* rdcu_model_adr */
-	NULL, /* *icu_new_model_buf */
-	0x400000, /* rdcu_up_model_adr */
-	0, /* samples */
-	NULL, /* *icu_output_buf */
-	0x600000, /* rdcu_buffer_adr */
-	0x0 /* buffer_length */
-};
-
-
-/**
- * @brief Default configuration of the Compressor in 1d-differencing imagette mode.
- * @warning All ICU buffers are set to NULL. Samples and buffer_length are set to 0
- * @note see PLATO-IWF-PL-RS-0005 V1.1
- */
-
-const struct cmp_cfg DEFAULT_CFG_DIFF = {
-	MODE_DIFF_ZERO, /* cmp_mode */
-	7, /* golomb_par */
-	60, /* spill */
-	8, /* model_value */
-	0, /* round */
-	6, /* ap1_golomb_par */
-	48, /* ap1_spill */
-	8, /* ap2_golomb_par */
-	72, /* ap2_spill */
-	NULL, /* *input_buf */
-	0x000000, /* rdcu_data_adr */
-	NULL, /* *model_buf */
-	0x000000, /* rdcu_model_adr */
-	NULL, /* *icu_new_model_buf */
-	0x000000, /* rdcu_up_model_adr */
-	0, /* samples */
-	NULL, /* *icu_output_buf */
-	0x600000, /* rdcu_buffer_adr */
-	0x0 /* buffer_length */
-};
+#include "cmp_support.h"
+#include "cmp_debug.h"
 
 
 /**
  * @brief implementation of the logarithm base of floor(log2(x)) for integers
  * @note ilog_2(0) = -1 defined
  *
- * @param x input parameter
+ * @param x	input parameter
  *
  * @returns the result of floor(log2(x))
  */
@@ -101,10 +41,10 @@ int ilog_2(uint32_t x)
 
 
 /**
- * @brief Determining if an integer is a power of 2
+ * @brief determining if an integer is a power of 2
  * @note 0 is incorrectly considered a power of 2 here
  *
- * @param v we want to see if v is a power of 2
+ * @param v	we want to see if v is a power of 2
  *
  * @returns 1 if v is a power of 2, otherwise 0
  *
@@ -117,231 +57,278 @@ int is_a_pow_of_2(unsigned int v)
 }
 
 
+/**
+ * @brief check if the compression entity data product type is supported
+ *
+ * @param data_type	compression entity data product type to check
+ *
+ * @returns zero if data_type is invalid; non-zero if data_type is valid
+ */
+
+int cmp_data_type_valid(enum cmp_data_type data_type)
+{
+	if (data_type <= DATA_TYPE_UNKOWN || data_type > DATA_TYPE_F_CAM_OFFSET)
+		return 0;
+
+	return 1;
+}
+
+
 /**
  * @brief check if a model mode is selected
  *
- * @param cmp_mode compression mode
+ * @param cmp_mode	compression mode
  *
- * @returns 1 when model mode is set, otherwise 0
+ * @returns 1 when the model mode is used, otherwise 0
  */
 
-int model_mode_is_used(unsigned int cmp_mode)
+int model_mode_is_used(enum cmp_mode cmp_mode)
 {
-	switch (cmp_mode) {
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
+	if (cmp_mode == CMP_MODE_MODEL_ZERO ||
+	    cmp_mode == CMP_MODE_MODEL_MULTI)
 		return 1;
-		break;
-	default:
-		return 0;
-		break;
-	}
+
+	return 0;
 }
 
 
 /**
  * @brief check if a 1d-differencing mode is selected
  *
- * @param cmp_mode compression mode
+ * @param cmp_mode	compression mode
  *
- * @returns 1 when 1d-differencing mode is set, otherwise 0
+ * @returns 1 when the 1d-differencing mode is used, otherwise 0
  */
 
-int diff_mode_is_used(unsigned int cmp_mode)
+int diff_mode_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_DIFF_ZERO ||
+	    cmp_mode == CMP_MODE_DIFF_MULTI)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the raw mode is selected
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when the raw mode is used, otherwise 0
+ */
+
+int raw_mode_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_RAW)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if the compression mode is supported by the RDCU compressor
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when the compression mode is supported by the RDCU, otherwise 0
+ */
+
+int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode)
 {
 	switch (cmp_mode) {
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI:
-	case MODE_DIFF_MULTI_S_FX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
+	case CMP_MODE_RAW:
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_DIFF_ZERO:
+	case CMP_MODE_MODEL_MULTI:
+	case CMP_MODE_DIFF_MULTI:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
+
 }
 
 
 /**
- * @brief check if the raw mode is selected
+ * @brief check if the data product data type is supported by the RDCU compressor
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data product types
  *
- * @returns 1 when raw mode is set, otherwise 0
+ * @returns 1 when the data type is supported by the RDCU, otherwise 0
  */
 
-int raw_mode_is_used(unsigned int cmp_mode)
+int rdcu_supported_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-	case MODE_RAW_32:
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
 }
 
 
 /**
- * @brief check if the mode is supported by the RDCU compressor
+ * @brief check if the compression mode is supported for an ICU compression
  *
- * @param cmp_mode compression mode
+ * @param cmp_mode	compression mode
  *
- * @returns 1 when mode is supported by the RDCU, otherwise 0
+ * @returns 1 when the compression mode is supported, otherwise 0
  */
 
-int rdcu_supported_mode_is_used(unsigned int cmp_mode)
+int cmp_mode_is_supported(enum cmp_mode cmp_mode)
 {
 	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
+	case CMP_MODE_RAW:
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_DIFF_ZERO:
+	case CMP_MODE_MODEL_MULTI:
+	case CMP_MODE_DIFF_MULTI:
+	case CMP_MODE_STUFF:
+		return 1;
+	}
+	return 0;
+}
+
+
+/**
+ * @brief check if zero escape symbol mechanism mode is used
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when zero escape symbol mechanism is set, otherwise 0
+ */
+
+int zero_escape_mech_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_MODEL_ZERO ||
+	    cmp_mode == CMP_MODE_DIFF_ZERO)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if multi escape symbol mechanism mode is used
+ *
+ * @param cmp_mode	compression mode
+ *
+ * @returns 1 when multi escape symbol mechanism is set, otherwise 0
+ */
+
+int multi_escape_mech_is_used(enum cmp_mode cmp_mode)
+{
+	if (cmp_mode == CMP_MODE_MODEL_MULTI ||
+	    cmp_mode == CMP_MODE_DIFF_MULTI)
+		return 1;
+
+	return 0;
+}
+
+
+/**
+ * @brief check if an imagette compression data type is used
+ * @note adaptive imagette compression data types included
+ *
+ * @param data_type	compression data type
+ *
+ * @returns 1 when data_type is an imagette data type, otherwise 0
+ */
+
+int cmp_imagette_data_type_is_used(enum cmp_data_type data_type)
+{
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
 }
 
 
 /**
- * @brief check if the mode is available
+ * @brief check if an adaptive imagette compression data type is used
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data type
  *
- * @returns 1 when mode is available, otherwise 0
+ * @returns 1 when data_type is an adaptive imagette data type, otherwise 0
  */
 
-int cmp_mode_available(unsigned int cmp_mode)
+int cmp_ap_imagette_data_type_is_used(enum cmp_data_type data_type)
 {
-	if (diff_mode_is_used(cmp_mode) ||
-	    model_mode_is_used(cmp_mode) ||
-	    raw_mode_is_used(cmp_mode))
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return 1;
-	else
+	default:
 		return 0;
-
+	}
 }
 
 
 /**
- * @brief check if zero escape symbol mechanism mode is used
+ * @brief check if a flux/center of brightness compression data type is used
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data type
  *
- * @returns 1 when zero escape symbol mechanism is set, otherwise 0
+ * @returns 1 when data_type is a flux/center of brightness data type, otherwise 0
  */
 
-int zero_escape_mech_is_used(unsigned int cmp_mode)
+int cmp_fx_cob_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (cmp_mode) {
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_ZERO_32:
-	case MODE_DIFF_ZERO_32:
+	switch (data_type) {
+	case DATA_TYPE_S_FX:
+	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_NCOB:
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX:
+	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_NCOB:
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX:
+	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_NCOB:
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
-
 }
 
 
 /**
- * @brief check if multi escape symbol mechanism mode is used
+ * @brief check if an auxiliary science compression data type is used
  *
- * @param cmp_mode compression mode
+ * @param data_type	compression data type
  *
- * @returns 1 when multi escape symbol mechanism is set, otherwise 0
+ * @returns 1 when data_type is an auxiliary science data type, otherwise 0
  */
 
-int multi_escape_mech_is_used(unsigned int cmp_mode)
+int cmp_aux_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (cmp_mode) {
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_MULTI_32:
+	switch (data_type) {
+	case DATA_TYPE_OFFSET:
+	case DATA_TYPE_BACKGROUND:
+	case DATA_TYPE_SMEARING:
+	case DATA_TYPE_F_CAM_OFFSET:
+	case DATA_TYPE_F_CAM_BACKGROUND:
 		return 1;
-		break;
 	default:
 		return 0;
-		break;
 	}
 }
 
@@ -349,8 +336,8 @@ int multi_escape_mech_is_used(unsigned int cmp_mode)
 /**
  * @brief method for lossy rounding
  *
- * @param value value to round
- * @param round round parameter
+ * @param value	the value to round
+ * @param round	rounding parameter
  *
  * @return rounded value
  */
@@ -364,8 +351,8 @@ unsigned int round_fwd(unsigned int value, unsigned int round)
 /**
  * @brief inverse method for lossy rounding
  *
- * @param value value to round back
- * @param round round parameter
+ * @param value	the value to round back
+ * @param round	rounding parameter
  *
  * @return back rounded value
  */
@@ -378,9 +365,8 @@ unsigned int round_inv(unsigned int value, unsigned int round)
 
 /**
  * @brief implantation of the model update equation
- *
  * @note check before that model_value is not greater than MAX_MODEL_VALUE
-
+ *
  * @param data		data to process
  * @param model		(current) model of the data to process
  * @param model_value	model weighting parameter
@@ -388,9 +374,14 @@ unsigned int round_inv(unsigned int value, unsigned int round)
  * @returns (new) updated model
  */
 
-unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
-			  model_value)
+unsigned int cmp_up_model(unsigned int data, unsigned int model,
+			  unsigned int model_value, unsigned int round)
+
 {
+	/* round and round back input because for decompression the accurate
+	 * data values are not available
+	 */
+	data = round_inv(round_fwd(data, round), round);
 	/* cast uint64_t to prevent overflow in the multiplication */
 	uint64_t weighted_model = (uint64_t)model * model_value;
 	uint64_t weighted_data = (uint64_t)data * (MAX_MODEL_VALUE - model_value);
@@ -402,13 +393,13 @@ unsigned int cal_up_model(unsigned int data, unsigned int model, unsigned int
 /**
  * @brief get the maximum valid spill threshold value for a given golomb_par
  *
- * @param golomb_par Golomb parameter
- * @param cmp_mode   compression mode
+ * @param golomb_par	Golomb parameter
+ * @param data_type	compression data type
  *
  * @returns the highest still valid spill threshold value
  */
 
-uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode)
+uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type data_type)
 {
 	const uint32_t LUT_MAX_RDCU[MAX_RDCU_GOLOMB_PAR+1] = { 0, 8, 22, 35, 48,
 		60, 72, 84, 96, 107, 118, 129, 140, 151, 162, 173, 184, 194,
@@ -420,208 +411,447 @@ uint32_t get_max_spill(unsigned int golomb_par, unsigned int cmp_mode)
 	if (golomb_par == 0)
 		return 0;
 
-	if (rdcu_supported_mode_is_used(cmp_mode)) {
+	/* the RDCU can only generate 16 bit long code words -> lower max spill needed */
+	if (rdcu_supported_data_type_is_used(data_type)) {
 		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
 			return 0;
 
 		return LUT_MAX_RDCU[golomb_par];
+	}
+
+	if (golomb_par > MAX_ICU_GOLOMB_PAR) {
+		return 0;
 	} else {
-		if (golomb_par > MAX_ICU_GOLOMB_PAR) {
-			return 0;
-		} else {
-			/* the ICU compressor can generate code words with a length of
-			 * maximal 32 bits.  */
-			unsigned int max_cw_bits = 32;
-			unsigned int cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
-			unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
-			return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
-				max_n_sym_offset - 1;
+		/* the ICU compressor can generate code words with a length of
+		 * maximal 32 bits.
+		 */
+		unsigned int max_cw_bits = 32;
+		unsigned int cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
+		unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
+
+		return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
+			max_n_sym_offset - 1;
+	}
+}
+
+
+/**
+ * @brief calculate the need bytes to hold a bitstream
+ *
+ * @param cmp_size_bit	compressed data size, measured in bits
+ *
+ * @returns the size in bytes to store the hole bitstream
+ * @note we round up the result to multiples of 4 bytes
+ */
+
+unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
+{
+	return (((cmp_size_bit + 7) / 8) + 3) & ~0x3UL;
+}
+
+
+/**
+ * @brief check if the compression data type, compression mode, model value and
+ *	the lossy rounding parameters are valid for a ICU compression
+ *
+ * @param cfg	pointer to the compressor configuration
+ *
+ * @returns 1 if generic compression parameters are valid, otherwise 0
+ */
+
+int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cmp_data_type_valid(cfg->data_type)) {
+		debug_print("Error: selected compression data type is not supported.\n");
+		cfg_invalid++;
+	}
+
+	if (cfg->cmp_mode > CMP_MODE_STUFF) {
+		debug_print("Error: selected cmp_mode: %u is not supported\n.", cfg->cmp_mode);
+		cfg_invalid++;
+	}
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->model_value > MAX_MODEL_VALUE) {
+			debug_print("Error: selected model_value: %u is invalid. Largest supported value is: %u.\n",
+				    cfg->model_value, MAX_MODEL_VALUE);
+			cfg_invalid++;
 		}
 	}
+
+	if (cfg->round > MAX_ICU_ROUND) {
+		debug_print("Error: selected lossy parameter: %u is not supported. Largest supported value is: %u.\n",
+			    cfg->round, MAX_ICU_ROUND);
+		cfg_invalid++;
+	}
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief get a good spill threshold parameter for the selected Golomb parameter
- *	and compression mode
+ * @brief check if the buffer parameters are valid
  *
- * @param golomb_par Golomb parameter
- * @param cmp_mode compression mode
+ * @param cfg	pointer to the compressor configuration
  *
- * @returns a good spill parameter (optimal for zero escape mechanism)
- * @warning icu compression not support yet!
+ * @returns 1 if the buffer parameters are valid, otherwise 0
  */
 
-uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode)
+int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
 {
-	const uint32_t LUT_RDCU_MULIT[MAX_RDCU_GOLOMB_PAR+1] = {0, 8, 16, 23,
-		30, 36, 44, 51, 58, 64, 71, 77, 84, 90, 97, 108, 115, 121, 128,
-		135, 141, 148, 155, 161, 168, 175, 181, 188, 194, 201, 207, 214,
-		229, 236, 242, 250, 256, 263, 269, 276, 283, 290, 296, 303, 310,
-		317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397,
-		405, 411, 418, 424, 431, 452 };
+	int cfg_invalid = 0;
 
-	if (zero_escape_mech_is_used(cmp_mode))
-		return get_max_spill(golomb_par, cmp_mode);
+	if (!cfg)
+		return 0;
 
-	if (cmp_mode == MODE_MODEL_MULTI) {
-		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
-			return 0;
-		else
-			return LUT_RDCU_MULIT[golomb_par];
+	if (cfg->input_buf == NULL) {
+		debug_print("Error: The data_to_compress buffer for the data to be compressed is NULL.\n");
+		cfg_invalid++;
 	}
 
-	if (cmp_mode == MODE_DIFF_MULTI)
-		return CMP_GOOD_SPILL_DIFF_MULTI;
+	if (cfg->samples == 0)
+		debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
 
-	return 0;
+	if (cfg->icu_output_buf && cfg->buffer_length == 0 && cfg->samples != 0) {
+		debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n");
+		cfg_invalid++;
+	}
+
+	if (cfg->icu_output_buf == cfg->input_buf) {
+		debug_print("Error: The compressed_data buffer is the same as the data_to_compress buffer.\n");
+		cfg_invalid++;
+	}
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->model_buf == NULL) {
+			debug_print("Error: The model_of_data buffer for the model data is NULL.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->model_buf == cfg->input_buf) {
+			debug_print("Error: The model_of_data buffer is the same as the data_to_compress buffer.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->model_buf == cfg->icu_output_buf) {
+			debug_print("Error: The model_of_data buffer is the same as the compressed_data buffer.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->icu_new_model_buf) {
+			if (cfg->icu_new_model_buf == cfg->input_buf) {
+				debug_print("Error: The updated_model buffer is the same as the data_to_compress buffer.\n");
+				cfg_invalid++;
+			}
+
+			if (cfg->icu_new_model_buf == cfg->icu_output_buf) {
+				debug_print("Error: The compressed_data buffer is the same as the compressed_data buffer.\n");
+				cfg_invalid++;
+			}
+		}
+	}
+
+	if (raw_mode_is_used(cfg->cmp_mode)) {
+		if (cfg->buffer_length < cfg->samples) {
+			debug_print("Error: The compressed_data_len_samples is to small to hold the data form the data_to_compress.\n");
+			cfg_invalid++;
+		}
+	} else {
+		if (cfg->samples < cfg->buffer_length/3)
+			debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended.This is probably unintended.\n");
+	}
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculate the size of a sample for the different compression modes
+ * @brief check if the combination of the different compression parameters is valid
  *
- * @param cmp_mode compression mode
+ * @param cmp_par	compression parameter
+ * @param spill		spillover threshold parameter
+ * @param cmp_mode	compression mode
+ * @param data_type	compression data type
+ * @param par_name	string describing the use of the compression par. for
+ *			debug messages (can be NULL)
  *
- * @returns the size of a data sample in bytes for the selected compression
- *	mode;
+ * @returns 1 if the parameter combination is valid, otherwise 0
  */
 
-size_t size_of_a_sample(unsigned int cmp_mode)
+static int cmp_pars_are_valid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cmp_mode,
+			      enum cmp_data_type data_type, char *par_name)
 {
-	size_t sample_len;
+	int cfg_invalid = 0;
+
+	if (!par_name)
+		par_name = "";
 
 	switch (cmp_mode) {
-	case MODE_RAW:
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		sample_len = sizeof(uint16_t);
-		break;
-	case MODE_RAW_S_FX:
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		sample_len = sizeof(struct S_FX);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		sample_len = sizeof(struct S_FX_NCOB);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		sample_len = sizeof(struct S_FX_EFX_NCOB_ECOB);
+	case CMP_MODE_RAW:
+		/* no checks needed */
 		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		sample_len = sizeof(struct F_FX);
-		break;
-	case MODE_MODEL_ZERO_F_FX_EFX:
-	case MODE_MODEL_MULTI_F_FX_EFX:
-	case MODE_DIFF_ZERO_F_FX_EFX:
-	case MODE_DIFF_MULTI_F_FX_EFX:
-		sample_len = sizeof(struct F_FX_EFX);
-		break;
-	case MODE_MODEL_ZERO_F_FX_NCOB:
-	case MODE_MODEL_MULTI_F_FX_NCOB:
-	case MODE_DIFF_ZERO_F_FX_NCOB:
-	case MODE_DIFF_MULTI_F_FX_NCOB:
-		sample_len = sizeof(struct F_FX_NCOB);
-		break;
-	case MODE_MODEL_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_F_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_F_FX_EFX_NCOB_ECOB:
-		sample_len = sizeof(struct F_FX_EFX_NCOB_ECOB);
+	case CMP_MODE_STUFF:
+		if (cmp_par > MAX_STUFF_CMP_PAR) {
+			debug_print("Error: The selected %s stuff mode compression parameter: %u is too large, the largest possible value in the selected compression mode is: %u.\n",
+				    par_name, cmp_par, MAX_STUFF_CMP_PAR);
+			cfg_invalid++;
+		}
 		break;
-	case MODE_RAW_32:
-	case MODE_MODEL_ZERO_32:
-	case MODE_MODEL_MULTI_32:
-	case MODE_DIFF_ZERO_32:
-	case MODE_DIFF_MULTI_32:
-		sample_len = sizeof(uint32_t);
+	case CMP_MODE_DIFF_ZERO:
+	case CMP_MODE_DIFF_MULTI:
+	case CMP_MODE_MODEL_ZERO:
+	case CMP_MODE_MODEL_MULTI:
+		if (cmp_par < MIN_ICU_GOLOMB_PAR ||
+		    cmp_par > MAX_ICU_GOLOMB_PAR) {
+			debug_print("Error: The selected %s compression parameter: %u is not supported. The compression parameter has to be between [%u, %u].\n",
+				    par_name, cmp_par, MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+			cfg_invalid++;
+		}
+		if (spill < MIN_ICU_SPILL) {
+			debug_print("Error: The selected %s spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
+				    par_name, spill, MIN_ICU_SPILL);
+			cfg_invalid++;
+		}
+		if (spill > get_max_spill(cmp_par, data_type)) {
+			debug_print("Error: The selected %s spillover threshold value: %u is too large for the selected %s compression parameter: %u, the largest possible spillover value in the selected compression mode is: %u.\n",
+				    par_name, spill, par_name, cmp_par, get_max_spill(cmp_par, data_type));
+			cfg_invalid++;
+		}
+
 		break;
 	default:
-		debug_print("Error: Compression mode not supported.\n");
-		return 0;
+		debug_print("Error: The compression mode is not supported.\n");
+		cfg_invalid++;
 		break;
 	}
-	return sample_len;
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculates the number of samples for a given data size for the
- *	different compression modes
+ * @brief check if the imagette specific compression parameters are valid
  *
- * @param size		size of the data me
- * @param cmp_mode	compression mode
+ * @param cfg	pointer to the compressor configuration
  *
- * @returns the number samples for the given compression mode; negative on error
+ * @returns 1 if the imagette specific parameters are valid, otherwise 0
  */
 
-int cmp_input_size_to_samples(unsigned int size, unsigned int cmp_mode)
+int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg)
 {
-	unsigned int samples_size = size_of_a_sample(cmp_mode);
+	int cfg_invalid = 0;
 
-	if (!samples_size)
-		return -1;
+	if (!cfg)
+		return 0;
 
-	if (!rdcu_supported_mode_is_used(cmp_mode)) {
-		if (size < N_DPU_ICU_MULTI_ENTRY_HDR_SIZE)
-			return -1;
-		size -= N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+	if (!cmp_imagette_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The compression data type is not an imagette compression data type.!\n");
+		cfg_invalid++;
 	}
 
-	if (size % samples_size)
-		return -1;
+	if (!cmp_pars_are_valid(cfg->golomb_par, cfg->spill, cfg->cmp_mode,
+				cfg->data_type, "imagette"))
+		cfg_invalid++;
+
+	if (cmp_ap_imagette_data_type_is_used(cfg->data_type)) {
+		if (!cmp_pars_are_valid(cfg->ap1_golomb_par, cfg->ap1_spill,
+					cfg->cmp_mode, cfg->data_type, "adaptive 1 imagette"))
+			cfg_invalid++;
+		if (!cmp_pars_are_valid(cfg->ap2_golomb_par, cfg->ap2_spill,
+					cfg->cmp_mode, cfg->data_type, "adaptive 2 imagette"))
+			cfg_invalid++;
+	}
 
-	return size/samples_size;
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculate the need bytes to hold a bitstream
+ * @brief check if the flux/center of brightness specific compression parameters are valid
  *
- * @param cmp_size_bit compressed data size, measured in bits
+ * @param cfg	pointer to the compressor configuration
  *
- * @returns the size in bytes to store the hole bitstream
- * @note we round up the result to multiples of 4 bytes
+ * @returns 1 if the flux/center of brightness specific parameters are valid, otherwise 0
  */
 
-unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
+int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 {
-	return (((cmp_size_bit + 7) / 8) + 3) & ~0x3UL;
+	int cfg_invalid = 0;
+	int check_exp_flags = 0, check_ncob = 0, check_efx = 0, check_ecob = 0, check_var = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cmp_fx_cob_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The compression data type is not a flux/center of brightness compression data type.!\n");
+		cfg_invalid++;
+	}
+	/* flux parameter is needed for every fx_cob data_type */
+	if (!cmp_pars_are_valid(cfg->cmp_par_fx, cfg->spill_fx, cfg->cmp_mode, cfg->data_type, "flux"))
+		cfg_invalid++;
+
+	switch (cfg->data_type) {
+	case DATA_TYPE_S_FX:
+		check_exp_flags = 1;
+		break;
+	case DATA_TYPE_S_FX_DFX:
+		check_exp_flags = 1;
+		check_efx = 1;
+		break;
+	case DATA_TYPE_S_FX_NCOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		break;
+	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		check_efx = 1;
+		check_ecob = 1;
+		break;
+	case DATA_TYPE_L_FX:
+		check_exp_flags = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_L_FX_DFX:
+		check_exp_flags = 1;
+		check_efx = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		check_exp_flags = 1;
+		check_ncob = 1;
+		check_efx = 1;
+		check_ecob = 1;
+		check_var = 1;
+		break;
+	case DATA_TYPE_F_FX:
+		break;
+	case DATA_TYPE_F_FX_DFX:
+		check_efx = 1;
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		check_ncob = 1;
+		break;
+	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		check_ncob = 1;
+		check_efx = 1;
+		check_ecob = 1;
+		break;
+	default:
+		cfg_invalid++;
+		break;
+	}
+
+	if (check_exp_flags && !cmp_pars_are_valid(cfg->cmp_par_exp_flags, cfg->spill_exp_flags, cfg->cmp_mode, cfg->data_type, "exposure flags"))
+		cfg_invalid++;
+	if (check_ncob && !cmp_pars_are_valid(cfg->cmp_par_ncob, cfg->spill_ncob, cfg->cmp_mode, cfg->data_type, "center of brightness"))
+		cfg_invalid++;
+	if (check_efx && !cmp_pars_are_valid(cfg->cmp_par_efx, cfg->spill_efx, cfg->cmp_mode, cfg->data_type, "extended flux"))
+		cfg_invalid++;
+	if (check_ecob && !cmp_pars_are_valid(cfg->cmp_par_ecob, cfg->spill_ecob, cfg->cmp_mode, cfg->data_type, "extended center of brightness"))
+		cfg_invalid++;
+	if (check_var && !cmp_pars_are_valid(cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, cfg->cmp_mode, cfg->data_type, "flux COB varianc"))
+		cfg_invalid++;
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
 }
 
 
 /**
- * @brief calculate the need bytes for the data
+ * @brief check if the auxiliary science specific compression parameters are valid
  *
- * @param samples number of data samples
- * @param cmp_mode used compression mode
+ * @param cfg	pointer to the compressor configuration
  *
- * @note for non RDCU modes the N_DPU ICU multi entry header size is added
+ * @returns 1 if the auxiliary science specific parameters are valid, otherwise 0
+ */
+
+int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
+{
+	int cfg_invalid = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cmp_aux_data_type_is_used(cfg->data_type)) {
+		debug_print("Error: The compression data type is not an auxiliary science compression data type.!\n");
+		cfg_invalid++;
+	}
+
+	if (!cmp_pars_are_valid(cfg->cmp_par_mean, cfg->spill_mean, cfg->cmp_mode, cfg->data_type, "mean"))
+		cfg_invalid++;
+	if (!cmp_pars_are_valid(cfg->cmp_par_variance, cfg->spill_variance, cfg->cmp_mode, cfg->data_type, "variance"))
+		cfg_invalid++;
+	if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET)
+		if (!cmp_pars_are_valid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error, cfg->cmp_mode, cfg->data_type, "outlier pixls num"))
+			cfg_invalid++;
+
+	if (cfg_invalid)
+		return 0;
+
+	return 1;
+}
+
+
+/**
+ * @brief check if a compression configuration is valid
  *
- * @returns the size in bytes to store the data sample
+ * @param cfg	pointer to the compressor configuration
+ *
+ * @returns 1 if the compression configuration is valid, otherwise 0
  */
 
-unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode)
+int cmp_cfg_is_valid(const struct cmp_cfg *cfg)
 {
-	unsigned int s = samples * size_of_a_sample(cmp_mode);
+	int cfg_invalid = 0;
+
+	if (!cfg)
+		return 0;
+
+	if (!cmp_cfg_icu_gen_par_is_valid(cfg))
+		cfg_invalid++;
+
+	if (!cmp_cfg_icu_buffers_is_valid(cfg))
+		cfg_invalid++;
+
+	if (cmp_imagette_data_type_is_used(cfg->data_type)) {
+		if (!cmp_cfg_imagette_is_valid(cfg))
+			cfg_invalid++;
+	} else if (cmp_fx_cob_data_type_is_used(cfg->data_type)) {
+		if (!cmp_cfg_fx_cob_is_valid(cfg))
+			cfg_invalid++;
+	} else if (cmp_aux_data_type_is_used(cfg->data_type)) {
+		if (!cmp_cfg_aux_is_valid(cfg))
+			cfg_invalid++;
+	} else {
+		cfg_invalid++;
+	}
 
-	if (!rdcu_supported_mode_is_used(cmp_mode))
-		s += N_DPU_ICU_MULTI_ENTRY_HDR_SIZE;
+	if (cfg_invalid)
+		return 0;
 
-	return s;
+	return 1;
 }
 
 
@@ -630,7 +860,6 @@ unsigned int cmp_cal_size_of_data(unsigned int samples, unsigned int cmp_mode)
  *
  * @param cfg	compressor configuration contains all parameters required for
  *		compression
- *
  */
 
 void print_cmp_cfg(const struct cmp_cfg *cfg)
diff --git a/lib/decmp.c b/lib/decmp.c
index 4953f5d..c22e5e4 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -4,823 +4,43 @@
 #include <limits.h>
 #include <string.h>
 
-#include "../include/cmp_support.h"
-#include "../include/cmp_icu.h"
-#include "../include/cmp_data_types.h"
-#include "../include/byteorder.h"
-#include "../include/cmp_debug.h"
+#include "byteorder.h"
+#include "cmp_debug.h"
+#include "cmp_support.h"
+#include "cmp_data_types.h"
+#include "cmp_entity.h"
 
+#define CMP_ERROR_SAMLL_BUF -2
 
-double get_compression_ratio(const struct cmp_info *info)
-{
-	unsigned long orign_len_bits = info->samples_used * size_of_a_sample(info->cmp_mode_used) * CHAR_BIT;
-
-	return (double)orign_len_bits/(double)info->cmp_size;
-}
-
-
-void *malloc_decompressed_data(const struct cmp_info *info)
-{
-	size_t sample_len;
-
-	if (!info)
-		return NULL;
-
-	if (info->samples_used == 0)
-		return NULL;
-
-	sample_len = size_of_a_sample(info->cmp_mode_used);
-
-	return malloc(info->samples_used * sample_len);
-}
-
-
-/**
- * @brief decompression data pre-processing in RAW mode
- *
- * @note in RAW mode the data are uncompressed no pre_processing needed
- *
- * @param  cmp_mode_used used compression mode
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_raw_pre_process(uint8_t cmp_mode_used)
-{
-	if (!raw_mode_is_used(cmp_mode_used))
-		return -1;
-
-	return 0;
-}
-
-
-/**
- * @brief model decompression pre-processing
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the data to process
- * @param model_buf	pointer to the model of the data to process
- * @param samples_used	the size of the data and model buffer in 16 bit units
- * @param model_value_used used model weighting parameter
- * @param round_used	used number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_model_16(uint16_t *data_buf, uint16_t *model_buf, uint32_t
-		       samples_used, uint8_t model_value_used, uint8_t
-		       round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (!model_buf)
-		return -1;
-
-	if (model_value_used > MAX_MODEL_VALUE)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		/* overflow is intended */
-		data_buf[i] = (uint16_t)(data_buf[i] + round_fwd(model_buf[i],
-								  round_used));
-	}
-
-	err = de_lossy_rounding_16(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		model_buf[i] = (uint16_t)cal_up_model(data_buf[i], model_buf[i],
-						      model_value_used);
-	}
-	return 0;
-}
-
-
-static int de_model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf, uint32_t
-		       samples_used, uint8_t model_value_used, uint8_t
-		       round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	if (!model_buf)
-		return -1;
-
-	if (model_value_used > MAX_MODEL_VALUE)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		/* overflow is intended */
-		struct S_FX round_model = model_buf[i];
-
-		lossy_rounding_S_FX(&round_model, 1, round_used);
-		data_buf[i] = add_S_FX(data_buf[i], model_buf[i]);
-	}
-
-	err = de_lossy_rounding_S_FX(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	for (i = 0; i < samples_used; i++)
-		model_buf[i] = cal_up_model_S_FX(data_buf[i], model_buf[i],
-						 model_value_used);
-
-	return 0;
-}
-
-
-/**
- * @brief 1d-differencing decompression per-processing
- *
- * @param data_buf	pointer to the data to process
- * @param samples_used	the size of the data and model buffer in 16 bit units
- * @param round_used	used number of bits to round; if zero no rounding takes place
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_diff_16(uint16_t *data_buf, uint32_t samples_used, uint8_t
-		      round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = data_buf[i] + data_buf[i-1];
-	}
-
-	err = de_lossy_rounding_16(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_32(uint32_t *data_buf, uint32_t samples_used, uint8_t
-		      round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = data_buf[i] + data_buf[i-1];
-	}
-
-	err = de_lossy_rounding_32(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX(struct S_FX *data_buf, uint32_t samples_used, uint8_t
-			round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX_EFX(struct S_FX_EFX *data_buf, uint32_t samples_used,
-			    uint8_t round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX_EFX(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX_EFX(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX_NCOB(struct S_FX_NCOB *data_buf, uint32_t samples_used,
-			     uint8_t round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX_NCOB(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX_NCOB(data_buf, samples_used, round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_diff_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-				      uint32_t samples_used, uint8_t round_used)
-{
-	size_t i;
-	int err;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 1; i < samples_used; i++) {
-		/* overflow intended */
-		data_buf[i] = add_S_FX_EFX_NCOB_ECOB(data_buf[i], data_buf[i-1]);
-	}
-
-	err = de_lossy_rounding_S_FX_EFX_NCOB_ECOB(data_buf, samples_used,
-						   round_used);
-	if (err)
-		return -1;
-
-	return 0;
-}
-
-
-static int de_pre_process(void *decoded_data, void *de_model_buf,
-			  const struct cmp_info *info)
-{
-	if (!decoded_data)
-		return -1;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
-
-	switch (info->cmp_mode_used) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return de_raw_pre_process(info->cmp_mode_used);
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-		return de_model_16((uint16_t *)decoded_data,
-				   (uint16_t *)de_model_buf, info->samples_used,
-				   info->model_value_used, info->round_used);
-		break;
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return de_diff_16((uint16_t *)decoded_data, info->samples_used,
-				  info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-		return de_model_S_FX((struct S_FX *)decoded_data,
-				   (struct S_FX *)de_model_buf,
-				   info->samples_used, info->model_value_used,
-				   info->round_used);
-		break;
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return de_diff_S_FX((struct S_FX *)decoded_data,
-				    info->samples_used, info->round_used);
-		break;
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return de_diff_S_FX_EFX((struct S_FX_EFX *)decoded_data,
-					info->samples_used, info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-		return -1;
-		break;
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return de_diff_S_FX_NCOB((struct S_FX_NCOB *)decoded_data,
-					 info->samples_used, info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-		return -1;
-		break;
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return de_diff_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)
-						  decoded_data,
-						  info->samples_used,
-						  info->round_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-		return -1;
-		break;
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return de_diff_32((uint32_t *)decoded_data, info->samples_used,
-				  info->round_used);
-		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-		return -1;
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
-	}
-
-	return -1;
-}
-
-
-static uint8_t de_map_to_pos_alg_8(uint8_t value_to_unmap)
-{
-	if (value_to_unmap & 0x1) /* if uneven */
-		return (value_to_unmap + 1) / -2;
-	else
-		return value_to_unmap / 2;
-}
-
-
-static uint16_t de_map_to_pos_alg_16(uint16_t value_to_unmap)
-{
-	if (value_to_unmap & 0x1) /* if uneven */
-		return (value_to_unmap + 1) / -2;
-	else
-		return value_to_unmap / 2;
-}
-
-
-static uint32_t de_map_to_pos_alg_32(uint32_t value_to_unmap)
-{
-
-	if (value_to_unmap & 0x1) /* if uneven */
-		return ((int64_t)value_to_unmap + 1) / -2; /* typecast to prevent overflow */
-	else
-		return value_to_unmap / 2;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	16-bit buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_16(uint16_t *data_buf, uint32_t samples_used, int
-			    zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used)
-			data_buf[i] -= 1;
-
-		data_buf[i] = (uint16_t)de_map_to_pos_alg_16(data_buf[i]);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	32-bit buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the uint16_t data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_32(uint32_t *data_buf, uint32_t samples_used, int
-			    zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used)
-			data_buf[i] -= 1;
-
-		data_buf[i] = (uint32_t)de_map_to_pos_alg_32(data_buf[i]);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX(struct S_FX *data_buf, uint32_t samples_used, int
-			      zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX_EFX buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX_EFX data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX_EFX(struct S_FX_EFX *data_buf, uint32_t
-				  samples_used, int zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-			data_buf[i].EFX -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].EFX = de_map_to_pos_alg_32(data_buf[i].EFX);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX_NCOB buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX_NCOB data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX_NCOB(struct S_FX_NCOB *data_buf, uint32_t
-				   samples_used, int zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-			data_buf[i].NCOB_X -= 1;
-			data_buf[i].NCOB_Y -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = de_map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = de_map_to_pos_alg_32(data_buf[i].NCOB_Y);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	S_FX_EFX_NCOB_ECOB buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the S_FX_EFX_NCOB_ECOB data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
-					    uint32_t samples_used,
-					    int zero_mode_used)
-{
-	size_t i;
-
-	if (!samples_used)
-		return 0;
-
-	if (!data_buf)
-		return -1;
-
-	for (i = 0; i < samples_used; i++) {
-		if (zero_mode_used) {
-			/* data_buf[i].EXPOSURE_FLAGS -= 1; */
-			data_buf[i].FX -= 1;
-			data_buf[i].NCOB_X -= 1;
-			data_buf[i].NCOB_Y -= 1;
-			data_buf[i].EFX -= 1;
-			data_buf[i].ECOB_X -= 1;
-			data_buf[i].ECOB_Y -= 1;
-		}
-
-		data_buf[i].EXPOSURE_FLAGS =
-			de_map_to_pos_alg_8(data_buf[i].EXPOSURE_FLAGS);
-		data_buf[i].FX = de_map_to_pos_alg_32(data_buf[i].FX);
-		data_buf[i].NCOB_X = de_map_to_pos_alg_32(data_buf[i].NCOB_X);
-		data_buf[i].NCOB_Y = de_map_to_pos_alg_32(data_buf[i].NCOB_Y);
-		data_buf[i].EFX = de_map_to_pos_alg_32(data_buf[i].EFX);
-		data_buf[i].ECOB_X = de_map_to_pos_alg_32(data_buf[i].ECOB_X);
-		data_buf[i].ECOB_Y = de_map_to_pos_alg_32(data_buf[i].ECOB_Y);
-	}
-	return 0;
-}
-
-
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range for a
- *	F_FX buffer
- *
- * @note change the data_buf in-place
- *
- * @param data_buf	pointer to the F_FX data buffer to process
- * @param samples_used	amount of data samples in the data_buf
- * @param zero_mode_used needs to be set if the zero escape symbol mechanism is used
- *
- * @returns 0 on success, error otherwise
- */
-
-static int de_map_to_pos_F_FX(uint32_t *data_buf, uint32_t samples_used, int
-			      zero_mode_used)
-{
-	return de_map_to_pos_32(data_buf, samples_used, zero_mode_used);
-}
 
+/* structure to hold a setup to encode a value */
+typedef unsigned int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
+struct decoder_setup {
+	/* generate_cw_f_pt generate_cw_f; /1* pointer to the code word generation function *1/ */
+	decoder_ptr decode_cw_f;
+	int (*encode_method_f)(uint32_t *decoded_value, int stream_pos,
+			       const struct decoder_setup *setup); /* pointer to the decoding function */
+	uint32_t *bitstream_adr; /* start address of the compressed data bitstream */
+	uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */
+	uint32_t max_cw_len;
+	uint32_t encoder_par1; /* encoding parameter 1 */
+	uint32_t encoder_par2; /* encoding parameter 2 */
+	uint32_t outlier_par; /* outlier parameter */
+	uint32_t lossy_par; /* lossy compression parameter */
+	uint32_t model_value; /* model value parameter */
+	uint32_t max_data_bits; /* how many bits are needed to represent the highest possible value */
+};
 
-/**
- * @brief map the unsigned output of the pre-stage to a signed value range
- *
- * @note change the data_buf in-place
- *
- * @param decompressed_data	pointer to the data to process
- * @param info			compressor information contains information of
- *				an executed compression
- *
- * @returns 0 on success, error otherwise
- */
 
-static int de_map_to_pos(void *decompressed_data, const struct cmp_info *info)
+double get_compression_ratio(uint32_t samples, uint32_t cmp_size_bits,
+			     enum cmp_data_type data_type)
 {
-	int zero_mode_used;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
-
-	if (!decompressed_data)
-		return -1;
+	double orign_len_bits = (double)cmp_cal_size_of_data(samples, data_type) * CHAR_BIT;
 
-	zero_mode_used = zero_escape_mech_is_used(info->cmp_mode_used);
-
-	switch (info->cmp_mode_used) {
-	case MODE_RAW:
-	case MODE_RAW_S_FX:
-		return 0; /* in raw mode no mapping is necessary */
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_ZERO:
-	case MODE_DIFF_MULTI:
-		return de_map_to_pos_16((uint16_t *)decompressed_data,
-					info->samples_used, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return de_map_to_pos_S_FX((struct S_FX *)decompressed_data,
-					  info->samples_used, zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return de_map_to_pos_S_FX_EFX((struct S_FX_EFX *)
-					      decompressed_data,
-					      info->samples_used,
-					      zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return de_map_to_pos_S_FX_NCOB((struct S_FX_NCOB *)
-					       decompressed_data,
-					       info->samples_used,
-					       zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return de_map_to_pos_S_FX_EFX_NCOB_ECOB((struct S_FX_EFX_NCOB_ECOB *)
-							decompressed_data,
-							info->samples_used,
-							zero_mode_used);
-		break;
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		return de_map_to_pos_F_FX((uint32_t *)decompressed_data,
-					  info->samples_used, zero_mode_used);
-		break;
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
-	}
-	return -1;
+	return orign_len_bits/(double)cmp_size_bits;
 }
 
 
-static unsigned int get_n_bits32(uint32_t *p_value, unsigned int bitOffset,
-				unsigned int nBits, const unsigned int *srcAddr,
-				size_t src_len_bit)
-{
-	const unsigned int *localAddr;
-	unsigned int bitsLeft, bitsRight, localEndPos;
-	unsigned int mask;
-	/*leave in case of erroneous input */
-	if (nBits == 0)
-		return 0;
-	if (nBits > 32)
-		return 0;
-	if (!srcAddr)
-		return 0;
-	if (!p_value)
-		return 0;
-	if ((bitOffset + nBits) > src_len_bit) {
-		debug_print("Error: Buffer overflow detected.\n");
-		return 0;
-	}
-	/* separate the bitOffset into word offset (set localAddr pointer) and
-	 * local bit offset (bitsLeft)
-	 */
-
-	localAddr = srcAddr + (bitOffset >> 5);
-	bitsLeft = bitOffset & 0x1f;
-
-	localEndPos = bitsLeft + nBits;
-
-	if (localEndPos <= 32) {
-		unsigned int shiftRight = 32 - nBits;
-
-		bitsRight = shiftRight - bitsLeft;
-
-		*(p_value) = *(localAddr) >> bitsRight;
-
-		mask = (0xffffffff >> shiftRight);
-
-		*(p_value) &= mask;
-	} else {
-		unsigned int n1 = 32 - bitsLeft;
-		unsigned int n2 = nBits - n1;
-		/* part 1 ; */
-		mask = 0xffffffff >> bitsLeft;
-		*(p_value) = (*localAddr) & mask;
-		*(p_value) <<= n2;
-		/*part 2: */
-		/* adjust address*/
-		localAddr += 1;
-
-		bitsRight = 32 - n2;
-		*(p_value) |= *(localAddr) >> bitsRight;
-	}
-	return nBits;
-}
-
 static unsigned int count_leading_ones(unsigned int value)
 {
 	unsigned int n_ones = 0; /* number of leading 1s */
@@ -831,16 +51,15 @@ static unsigned int count_leading_ones(unsigned int value)
 		leading_bit = value & 0x80000000;
 		if (!leading_bit)
 			break;
-		else {
-			n_ones++;
-			value <<= 1;
-		}
+
+		n_ones++;
+		value <<= 1;
 	}
 	return n_ones;
 }
 
 
-static unsigned int Rice_decoder(uint32_t code_word, unsigned int m,
+static unsigned int rice_decoder(uint32_t code_word, unsigned int m,
 				 unsigned int log2_m, unsigned int *decoded_cw)
 {
 	unsigned int q; /* quotient code */
@@ -863,7 +82,7 @@ static unsigned int Rice_decoder(uint32_t code_word, unsigned int m,
 
 	code_word = code_word << ql;  /* shift quotient code out */
 
-	/* Right shifting an integer by a number of bits equal orgreater than
+	/* Right shifting an integer by a number of bits equal or greater than
 	 * its size is undefined behavior
 	 */
 	if (rl == 0)
@@ -877,7 +96,7 @@ static unsigned int Rice_decoder(uint32_t code_word, unsigned int m,
 }
 
 
-static unsigned int Golomb_decoder(unsigned int code_word, unsigned int m,
+static unsigned int golomb_decoder(unsigned int code_word, unsigned int m,
 				   unsigned int log2_m, unsigned int
 				   *decoded_cw)
 {
@@ -915,608 +134,382 @@ static unsigned int Golomb_decoder(unsigned int code_word, unsigned int m,
 }
 
 
-typedef unsigned int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
-
 static decoder_ptr select_decoder(unsigned int golomb_par)
 {
 	if (!golomb_par)
 		return NULL;
 
 	if (is_a_pow_of_2(golomb_par))
-		return &Rice_decoder;
+		return &rice_decoder;
 	else
-		return &Golomb_decoder;
+		return &golomb_decoder;
 }
 
 
-static int decode_raw(const void *compressed_data, const struct cmp_info
-			*info, void *const decompressed_data)
-{
-	if (!info)
-		return -1;
-	if (info->samples_used == 0)
-		return 0;
-	if (!compressed_data)
-		return -1;
-	if (!decompressed_data)
-		return -1;
-
-	if (info->samples_used*size_of_a_sample(info->cmp_mode_used)*CHAR_BIT
-	    != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
-	memcpy(decompressed_data, compressed_data, info->cmp_size/CHAR_BIT);
-
-	return 0;
-}
+/**
+ * @brief read a value of up to 32 bits from a bitstream
+ *
+ * @param p_value		pointer to the read value
+ * @param n_bits		number of bits to read from the bitstream
+ * @param bit_offset		bit index where the bits will be read, seen from
+ *				the very beginning of the bitstream
+ * @param bitstream_adr		this is the pointer to the beginning of the
+ *				bitstream (can be NULL)
+ * @param max_stream_len	maximum length of the bitstream in bits; is
+ *				ignored if bitstream_adr is NULL
+ *
+ * @returns length in bits of the generated bitstream on success; returns
+ *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
+ *          the bitstream buffer is too small to read the value from the bitstream
+ */
 
-static int decode_raw_16(const void *compressed_data, const struct cmp_info
-			*info, uint16_t *const decompressed_data)
+static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
+			uint32_t *bitstream_adr, unsigned int max_stream_len)
 {
-	size_t i;
-	uint16_t *p = decompressed_data;
-	uint32_t read_pos = 0;
-	unsigned int read_bits;
-	uint32_t read_val;
+	const unsigned int *local_adr;
+	unsigned int bitsLeft, bitsRight, localEndPos;
+	unsigned int mask;
+	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
 
-	if (!info)
-		return -1;
-	if (info->samples_used == 0)
-		return 0;
-	if (!compressed_data)
-		return -1;
-	if (!decompressed_data)
+	/*leave in case of erroneous input */
+	if (bit_offset < 0)
 		return -1;
 
-	for (i = 0; i < info->samples_used; ++i) {
-		read_bits = get_n_bits32(&read_val, read_pos, 16,
-					 compressed_data, info->cmp_size);
-		if (!read_bits)
-			return -1;
-		read_pos += 16;
-		p[i] =read_val;
-	}
-	return 0;
-}
-
-
-static int decode_raw_S_FX(const void *compressed_data, const struct cmp_info
-			   *info, struct S_FX *const decompressed_data)
-{
-	int err = decode_raw(compressed_data, info, decompressed_data);
-	if (err)
-		return err;
+	if (n_bits == 0)
+		return stream_len;
 
-#if defined(LITTLE_ENDIAN)
-	{
-		size_t i;
-		for (i = 0; i < info->samples_used; i++) {
-			decompressed_data[i].FX = cpu_to_be32(decompressed_data[i].FX);
-		}
-	}
-#endif
-	return 0;
-}
+	if (n_bits > 32)
+		return -1;
 
-static unsigned int decode_normal(const void *compressed_data,
-				  const struct cmp_info *info,
-				  unsigned int read_pos,
-				  unsigned int max_cw_len,
-				  uint32_t *const decoded_val)
-{
-	decoder_ptr decoder;
-	unsigned int n_read_bits;
-	uint32_t read_val;
-	unsigned int n_bits;
-	unsigned int read_bits;
-	unsigned int log2_g;
+	if (!bitstream_adr)
+		return stream_len;
 
-	if (!compressed_data)
-		return -1U;
+	if (!p_value)
+		return stream_len;
 
-	if (!info)
-		return -1U;
+	/* Check if bitstream buffer is large enough */
+	if ((unsigned int)stream_len > max_stream_len) {
+		debug_print("Error: Buffer overflow detected.\n");
+		return CMP_ERROR_SAMLL_BUF;
 
-	if (!decoded_val)
-		return -1U;
+	}
 
-	if (read_pos > info->cmp_size)
-		return -1U;
+	/* separate the bit_offset into word offset (set local_adr pointer) and
+	 * local bit offset (bitsLeft)
+	 */
+	local_adr = bitstream_adr + (bit_offset >> 5);
+	bitsLeft = bit_offset & 0x1f;
 
-	if (max_cw_len > 32)
-		return -1U;
+	localEndPos = bitsLeft + n_bits;
 
-	if (max_cw_len == 0)
-		return read_pos;
+	if (localEndPos <= 32) {
+		unsigned int shiftRight = 32 - n_bits;
 
-	decoder = select_decoder(info->golomb_par_used);
-	if (!decoder)
-		return -1U;
+		bitsRight = shiftRight - bitsLeft;
 
-	if (read_pos + max_cw_len > info->cmp_size)   /* check buffer overflow */
-		n_read_bits = info->cmp_size - read_pos;
-	else
-		n_read_bits = max_cw_len;
+		*(p_value) = cpu_to_be32(*(local_adr)) >> bitsRight;
 
-	read_bits = get_n_bits32(&read_val, read_pos, n_read_bits,
-				 compressed_data, info->cmp_size);
-	if (!read_bits)
-		return -1U;
+		mask = (0xffffffff >> shiftRight);
 
-	read_val = read_val << (32 - n_read_bits);
+		*(p_value) &= mask;
+	} else {
+		unsigned int n1 = 32 - bitsLeft;
+		unsigned int n2 = n_bits - n1;
+		/* part 1 ; */
+		mask = 0xffffffff >> bitsLeft;
+		*(p_value) = cpu_to_be32(*(local_adr)) & mask;
+		*(p_value) <<= n2;
+		/*part 2: */
+		/* adjust address*/
+		local_adr += 1;
 
-	log2_g = ilog_2(info->golomb_par_used);
-	n_bits = decoder(read_val, info->golomb_par_used, log2_g, decoded_val);
+		bitsRight = 32 - n2;
+		*(p_value) |= cpu_to_be32(*(local_adr)) >> bitsRight;
+	}
 
-	return read_pos + n_bits;
+	return stream_len;
 }
 
 
-static unsigned int decode_zero(const void *compressed_data,
-				const struct cmp_info *info,
-				unsigned int read_pos, unsigned int max_cw_len,
-				uint32_t *const decoded_val)
+static int decode_normal(uint32_t *decoded_value, int stream_pos, const struct decoder_setup *setup)
 {
-	if (!info)
-		return -1U;
-
-	if (info->samples_used == 0)
-		return read_pos;
-
-	if (!compressed_data)
-		return -1U;
-
-	if (!decoded_val)
-		return -1U;
-
-	if (read_pos > info->cmp_size)
-		return -1U;
-
-	if (max_cw_len > 32)
-		return -1U;
+	uint32_t read_val = ~0U;
+	int n_read_bits, cw_len, n_bits;
 
-	if (max_cw_len == 0)
-		return read_pos;
+	if (stream_pos + setup->max_cw_len > setup->max_stream_len)   /* check buffer overflow */
+		n_read_bits = setup->max_stream_len - stream_pos;
+	else
+		n_read_bits = setup->max_cw_len;
+	if (n_read_bits >= 32 || n_read_bits == 0)
+		return -1;
 
-	read_pos = decode_normal(compressed_data, info, read_pos, max_cw_len,
-				 decoded_val);
-	if (read_pos == -1U)
-		return -1U;
-	if (*decoded_val >= info->spill_used) /* consistency check */
-		return -1U;
+	n_bits = get_n_bits32(&read_val, n_read_bits, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+	if (n_bits <= 0)
+		return -1;
 
-	if (*decoded_val == 0) {/* escape symbol mechanism was used; read unencoded value */
-		unsigned int n_bits;
-		uint32_t unencoded_val;
+	read_val = read_val << (32 - n_read_bits);
 
-		n_bits = get_n_bits32(&unencoded_val, read_pos, max_cw_len,
-				      compressed_data, info->cmp_size);
-		if (!n_bits)
-			return -1U;
-		if (unencoded_val < info->spill_used && unencoded_val != 0) /* consistency check */
-			return -1U;
+	cw_len = setup->decode_cw_f(read_val, setup->encoder_par1, setup->encoder_par2, decoded_value);
+	if (cw_len < 0)
+		return -1;
 
-		*decoded_val = unencoded_val;
-		read_pos += n_bits;
-	}
-	return read_pos;
+	return stream_pos + cw_len;
 }
 
 
-static unsigned int decode_multi(const void *compressed_data,
-				 const struct cmp_info *info,
-				 unsigned int read_pos, unsigned int max_cw_len,
-				 uint32_t *const decoded_val)
+static int decode_multi(uint32_t *decoded_value, int stream_pos,
+			    const struct decoder_setup *setup)
 {
-	if (!info)
-		return -1U;
-
-	if (info->samples_used == 0)
-		return read_pos;
+	stream_pos = decode_normal(decoded_value, stream_pos, setup);
+	if (stream_pos < 0)
+		return stream_pos;
 
-	if (!compressed_data)
-		return -1U;
-
-	if (!decoded_val)
-		return -1U;
-
-	if (read_pos > info->cmp_size)
-		return -1U;
-
-	if (max_cw_len > 32)
-		return -1U;
-
-	if (max_cw_len == 0)
-		return read_pos;
-
-	read_pos = decode_normal(compressed_data, info, read_pos, max_cw_len,
-				 decoded_val);
-	if (read_pos == -1U)
-		return -1U;
-
-	if (*decoded_val >= info->spill_used) {
+	if (*decoded_value >= setup->outlier_par) {
 		/* escape symbol mechanism was used; read unencoded value */
-		unsigned int n_bits;
-		uint32_t unencoded_val;
+		int n_bits;
+		uint32_t unencoded_val = 0;
 		unsigned int unencoded_len;
 
-		unencoded_len = (*decoded_val - info->spill_used + 1) * 2;
-		if (unencoded_len > max_cw_len) /* consistency check */
-			return -1U;
+		unencoded_len = (*decoded_value - setup->outlier_par + 1) * 2;
 
-		/* check buffer overflow */
-		if ((read_pos + unencoded_len) > info->cmp_size) {
-			/*TODO: debug message */
-			return -1U;
-		}
-		n_bits = get_n_bits32(&unencoded_val, read_pos, unencoded_len,
-				      compressed_data, info->cmp_size);
-		if (!n_bits)
-			return -1U;
+		n_bits = get_n_bits32(&unencoded_val, unencoded_len, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+		if (n_bits <= 0)
+			return -1;
 
-		*decoded_val = unencoded_val + info->spill_used;
-		read_pos += n_bits;
+		*decoded_value = unencoded_val + setup->outlier_par;
+		stream_pos += unencoded_len;
 	}
-	return read_pos;
-}
-
-
-static unsigned int decode_value(const void *compressed_data,
-				 const struct cmp_info *info,
-				 unsigned int read_pos,
-				 unsigned int max_cw_len, uint32_t *decoded_val)
-{
-	if (multi_escape_mech_is_used(info->cmp_mode_used))
-		return decode_multi(compressed_data, info, read_pos, max_cw_len,
-				    decoded_val);
-
-	if (zero_escape_mech_is_used(info->cmp_mode_used))
-		return decode_zero(compressed_data, info, read_pos, max_cw_len,
-				   decoded_val);
-	return -1U;
+	return stream_pos;
 }
 
 
-static int decode_16(const void *compressed_data, const struct cmp_info *info,
-		     uint16_t *decoded_data)
+static int decode_zero(uint32_t *decoded_value, int stream_pos,
+			   const struct decoder_setup *setup)
 {
-	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
-		return -1;
+	stream_pos = decode_normal(decoded_value, stream_pos, setup);
 
-	if (info->samples_used == 0)
-		return 0;
+	if (stream_pos <= 0)
+		return stream_pos;
 
-	if (!decoded_data)
+	if (*decoded_value > setup->outlier_par) /* consistency check */
 		return -1;
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
+	if (*decoded_value == 0) {/* escape symbol mechanism was used; read unencoded value */
+		int n_bits;
+		uint32_t unencoded_val = 0;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 16,
-					&decoded_val);
-		if (read_pos == -1U) {
-			debug_print("Error: Compressed values could not be decoded.\n");
+		n_bits = get_n_bits32(&unencoded_val, setup->max_data_bits, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+		if (n_bits <= 0)
 			return -1;
-		}
-
-		if (decoded_val > UINT16_MAX)
+		if (unencoded_val < setup->outlier_par && unencoded_val != 0) /* consistency check */
 			return -1;
 
-		decoded_data[i] = (uint16_t)decoded_val;
+		*decoded_value = unencoded_val;
+		stream_pos += setup->max_data_bits;
 	}
-
-	if (read_pos != info->cmp_size &&
-	    cmp_bit_to_4byte(read_pos) != cmp_bit_to_4byte(info->cmp_size)) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
-	return 0;
+	(*decoded_value)--;
+	if (*decoded_value == 0xFFFFFFFF) /* catch underflow */
+		(*decoded_value) = (*decoded_value) >> (32-setup->max_data_bits);
+	return stream_pos;
 }
 
 
-static int decode_S_FX(const void *compressed_data, const struct cmp_info *info,
-		       struct S_FX *decoded_data)
-{
-	size_t i;
-	unsigned int read_pos = 0;
-	struct cmp_info info_exp_flag;
+/**
+ * @brief remap a unsigned value back to a signed value
+ * @note this is the reverse function of map_to_pos()
+ *
+ * @param value_to_unmap	unsigned value to remap
+ *
+ * @returns the signed remapped value
+ */
 
-	info_exp_flag.golomb_par_used = GOLOMB_PAR_EXPOSURE_FLAGS;
+static uint32_t re_map_to_pos(uint32_t value_to_unmap)
+{
+	if (value_to_unmap & 0x1) { /* if uneven */
+		if (value_to_unmap == 0xFFFFFFFF) /* catch overflow */
+			return 0x80000000;
+		return -((value_to_unmap + 1) / 2);
+	} else
+		return value_to_unmap / 2;
+}
 
-	if (!info)
-		return -1;
 
-	if (info->samples_used == 0)
-		return 0;
+static int decode_value(uint32_t *decoded_value, uint32_t model,
+			int stream_pos, const struct decoder_setup *setup)
+{
+	uint32_t mask = (~0U >> (32 - setup->max_data_bits)); /* mask the used bits */
 
-	if (!decoded_data)
-		return -1;
+	stream_pos = setup->encode_method_f(decoded_value, stream_pos, setup);
+	if (stream_pos <= 0)
+		return stream_pos;
 
-	info_exp_flag = *info;
+	*decoded_value = re_map_to_pos(*decoded_value); //, setup->max_used_bits);
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
+	*decoded_value += round_fwd(model, setup->lossy_par);
 
-		/* read_pos = decode_value(compressed_data, &info_exp_flag, read_pos, 8, */
-		/* 			&decoded_val); */
-		read_pos = decode_normal(compressed_data, &info_exp_flag, read_pos, 8,
-					 &decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
+	*decoded_value &= mask;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].FX = decoded_val;
-	}
+	*decoded_value = round_inv(*decoded_value, setup->lossy_par);
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.");
-		return 1;
-	}
-	return 0;
+	return stream_pos;
 }
 
 
-static int decode_S_FX_EFX(const void *compressed_data, const struct cmp_info
-			   *info, struct S_FX_EFX *decoded_data)
+static int configure_decoder_setup(struct decoder_setup *setup,
+				   uint32_t cmp_par, uint32_t spill,
+				   uint32_t lossy_par, uint32_t max_data_bits,
+				   const struct cmp_cfg *cfg)
 {
-	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
+	if (multi_escape_mech_is_used(cfg->cmp_mode))
+		setup->encode_method_f = &decode_multi;
+	else if (zero_escape_mech_is_used(cfg->cmp_mode))
+		setup->encode_method_f = &decode_zero;
+	else {
+		debug_print("Error: Compression mode not supported.\n");
 		return -1;
+	}
 
-	if (info->samples_used == 0)
-		return 0;
-
-	if (!decoded_data)
+	setup->bitstream_adr = cfg->icu_output_buf; /* start address of the compressed data bitstream */
+	if (cfg->buffer_length & 0x3) {
+		debug_print("Error: The length of the compressed data is not a multiple of 4 bytes.");
 		return -1;
-
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 8,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].FX = decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].EFX = decoded_val;
 	}
+	setup->max_stream_len = (cfg->buffer_length) * CHAR_BIT;  /* maximum length of the bitstream/icu_output_buf in bits */
+	if (rdcu_supported_data_type_is_used(cfg->data_type))
+		setup->max_cw_len = 16;
+	else
+		setup->max_cw_len = 32;
+	setup->encoder_par1 = cmp_par; /* encoding parameter 1 */
+	setup->encoder_par2 = ilog_2(cmp_par); /* encoding parameter 2 */
+	setup->outlier_par = spill; /* outlier parameter */
+	setup->lossy_par = lossy_par; /* lossy compression parameter */
+	setup->model_value = cfg->model_value; /* model value parameter */
+	setup->max_data_bits = max_data_bits; /* how many bits are needed to represent the highest possible value */
+	setup->decode_cw_f = select_decoder(cmp_par);
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
 	return 0;
 }
 
 
-static int decode_S_FX_NCOB(const void *compressed_data, const struct cmp_info
-			    *info, struct S_FX_NCOB *decoded_data)
+static int decompress_imagette(struct cmp_cfg *cfg)
 {
 	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
+	int stream_pos = 0;
+	struct decoder_setup setup;
+	uint16_t *decompressed_data = cfg->input_buf;
+	uint16_t *model_buf = cfg->model_buf;
+	uint16_t *up_model_buf = cfg->icu_new_model_buf;
+	uint32_t decoded_value = 0;
+	uint16_t model;
+	int err;
 
-	if (!decoded_data)
+	err = configure_decoder_setup(&setup, cfg->golomb_par, cfg->spill,
+				      cfg->round, 16, cfg);
+	if (err)
 		return -1;
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 8,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].FX = decoded_val;
+	for (i = 0; i < cfg->samples; i++) {
+		if (model_mode_is_used(cfg->cmp_mode))
+			model = model_buf[i];
+		else
+			model = decoded_value;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].NCOB_X = decoded_val;
+		stream_pos = decode_value(&decoded_value, model, stream_pos, &setup);
+		if (stream_pos <= 0)
+			return stream_pos;
+		decompressed_data[i] = decoded_value;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].NCOB_Y = decoded_val;
+		if (up_model_buf) {
+			up_model_buf[i] = cmp_up_model(decoded_value, model,
+						       cfg->model_value, setup.lossy_par);
+		}
 	}
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.\n");
-		return 1;
-	}
-	return 0;
+	return stream_pos;
 }
 
-
-static int decode_S_FX_EFX_NCOB_ECOB(const void *compressed_data,
-				     const struct cmp_info *info,
-				     struct S_FX_EFX_NCOB_ECOB *decoded_data)
+static int decompressed_data_internal(struct cmp_cfg *cfg)
 {
-	size_t i;
-	unsigned int read_pos = 0;
-
-	if (!info)
-		return -1;
-
-	if (info->samples_used == 0)
-		return 0;
+	int data_size, strem_len_bit = -1;
 
-	if (!decoded_data)
+	if (!cfg)
+		return 0; /* or -1? */
+	if (!cfg->icu_output_buf)
 		return -1;
 
-	for (i = 0; i < info->samples_used; i++) {
-		uint32_t decoded_val;
-
-		read_pos = decode_value(compressed_data, info, read_pos, 8,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		if (decoded_val > UINT8_MAX)
-			return -1;
-		decoded_data[i].EXPOSURE_FLAGS = (uint8_t)decoded_val;
+	data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+	if (!cfg->input_buf || !data_size)
+		return data_size;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
+	if (model_mode_is_used(cfg->cmp_mode))
+		if (!cfg->model_buf)
 			return -1;
-		decoded_data[i].FX = decoded_val;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].NCOB_X = decoded_val;
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
+		if ((unsigned int)data_size < cfg->buffer_length/CHAR_BIT)
 			return -1;
-		decoded_data[i].NCOB_Y = decoded_val;
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].EFX = decoded_val;
+		if (cfg->input_buf) {
+			memcpy(cfg->input_buf, cfg->icu_output_buf, data_size);
+			if (cmp_input_big_to_cpu_endianness(cfg->input_buf, data_size, cfg->data_type))
+				return -1;
+			strem_len_bit = data_size * CHAR_BIT;
+		}
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].ECOB_X = decoded_val;
+	} else {
+		switch (cfg->data_type) {
+		case DATA_TYPE_IMAGETTE:
+			strem_len_bit = decompress_imagette(cfg);
+			break;
+		default:
+			strem_len_bit = -1;
+			debug_print("Error: Compressed data type not supported.\n");
+			break;
+		}
 
-		read_pos = decode_value(compressed_data, info, read_pos, 32,
-					&decoded_val);
-		if (read_pos == -1U)
-			return -1;
-		decoded_data[i].ECOB_Y = decoded_val;
 	}
+	/* TODO: is this usefull? if (strem_len_bit != data_size * CHAR_BIT) { */
+	if (strem_len_bit <= 0)
+		return -1;
 
-	if (read_pos != info->cmp_size) {
-		debug_print("Warning: The size of the decompressed bitstream does not match the size of the compressed bitstream. Check if the parameters used for decompression are the same as those used for compression.");
-		return 1;
-	}
-	return 0;
+
+	return data_size;
 }
 
 
-static int decode_data(const void *compressed_data, const struct cmp_info *info,
-		       void *decompressed_data)
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+			 void *up_model_buf, void *decompressed_data)
 {
-	if (!info)
-		return -1;
+	int err;
+	struct cmp_cfg cfg = {0};
 
-	if (info->samples_used == 0)
-		return 0;
+	cfg.model_buf = model_buf;
+	cfg.icu_new_model_buf = up_model_buf;
+	cfg.input_buf = decompressed_data;
 
-	if (!compressed_data)
+	if (!ent)
 		return -1;
 
-	if (!decompressed_data)
+	err = cmp_ent_read_header(ent, &cfg);
+	if (err)
 		return -1;
 
-	switch (info->cmp_mode_used) {
-	case MODE_RAW:
-		return decode_raw_16(compressed_data, info, decompressed_data);
-		break;
-	case MODE_MODEL_ZERO:
-	case MODE_DIFF_ZERO:
-	case MODE_MODEL_MULTI:
-	case MODE_DIFF_MULTI:
-		return decode_16(compressed_data, info,
-				 (uint16_t *)decompressed_data);
-		break;
-	case MODE_RAW_S_FX:
-		return decode_raw_S_FX(compressed_data, info, decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX:
-	case MODE_MODEL_MULTI_S_FX:
-	case MODE_DIFF_ZERO_S_FX:
-	case MODE_DIFF_MULTI_S_FX:
-		return decode_S_FX(compressed_data, info,
-				   (struct S_FX *)decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX:
-	case MODE_MODEL_MULTI_S_FX_EFX:
-	case MODE_DIFF_ZERO_S_FX_EFX:
-	case MODE_DIFF_MULTI_S_FX_EFX:
-		return decode_S_FX_EFX(compressed_data, info,
-				       (struct S_FX_EFX *)decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX_NCOB:
-	case MODE_MODEL_MULTI_S_FX_NCOB:
-	case MODE_DIFF_ZERO_S_FX_NCOB:
-	case MODE_DIFF_MULTI_S_FX_NCOB:
-		return decode_S_FX_NCOB(compressed_data, info,
-					(struct S_FX_NCOB *)decompressed_data);
-		break;
-	case MODE_MODEL_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_MODEL_MULTI_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_ZERO_S_FX_EFX_NCOB_ECOB:
-	case MODE_DIFF_MULTI_S_FX_EFX_NCOB_ECOB:
-		return decode_S_FX_EFX_NCOB_ECOB(compressed_data, info,
-						 (struct S_FX_EFX_NCOB_ECOB *)
-						 decompressed_data);
-		break;
-#if 0
-	case MODE_MODEL_ZERO_F_FX:
-	case MODE_MODEL_MULTI_F_FX:
-	case MODE_DIFF_ZERO_F_FX:
-	case MODE_DIFF_MULTI_F_FX:
-		break;
-#endif
-	default:
-		debug_print("Error: Compression mode not supported.\n");
-		break;
-
-	}
-	return -1;
+	return decompressed_data_internal(&cfg);
 }
 
-/* model buffer is overwritten with updated model*/
 
-int decompress_data(const void *compressed_data, void *de_model_buf, const
-		    struct cmp_info *info, void *decompressed_data)
+/* model buffer is overwritten with updated model */
+
+int decompress_data(uint32_t *compressed_data, void *de_model_buf,
+		    const struct cmp_info *info, void *decompressed_data)
 {
-	int err;
+	int size_decomp_data;
+	struct cmp_cfg cfg = {0};
 
 	if (!compressed_data)
 		return -1;
@@ -1535,18 +528,22 @@ int decompress_data(const void *compressed_data, void *de_model_buf, const
 	if (!decompressed_data)
 		return -1;
 
+	/* cfg.data_type = info->data_type_used; */
+	cfg.cmp_mode = info->cmp_mode_used;
+	cfg.model_value = info->model_value_used;
+	cfg.round = info->round_used;
+	cfg.spill = info->spill_used;
+	cfg.golomb_par = info->golomb_par_used;
+	cfg.samples = info->samples_used;
+	cfg.icu_output_buf = compressed_data;
+	cfg.buffer_length = cmp_bit_to_4byte(info->cmp_size);
+	cfg.input_buf = decompressed_data;
+	cfg.model_buf = de_model_buf;
+	size_decomp_data = decompressed_data_internal(&cfg);
+	if (size_decomp_data <= 0)
+		return -1;
+	else
+		return 0;
 
-	err = decode_data(compressed_data, info, decompressed_data);
-	if (err)
-		return err;
-
-	err = de_map_to_pos(decompressed_data, info);
-	if (err)
-		return err;
-
-	err = de_pre_process(decompressed_data, de_model_buf, info);
-	if (err)
-		return err;
 
-	return 0;
 }
diff --git a/lib/meson.build b/lib/meson.build
index 21f72ad..f072ce4 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -17,6 +17,6 @@ cmplib_sources = files([
 cmp_lib = static_library('cmp_lib',
   sources : cmplib_sources,
   include_directories : incdir,
-  c_args : ['-DDEBUGLEVEL=1'], 
-  install : 'true' # linking under windows mingw only works if this is set
+  c_args : ['-DDEBUGLEVEL=1'],
+#  install : 'true' # linking under windows mingw only works if this is set
 )
diff --git a/lib/rdcu_pkt_to_file.c b/lib/rdcu_pkt_to_file.c
index 83074d7..0c71c8e 100644
--- a/lib/rdcu_pkt_to_file.c
+++ b/lib/rdcu_pkt_to_file.c
@@ -28,11 +28,11 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#include "../include/rdcu_pkt_to_file.h"
-#include "../include/cmp_rdcu_extended.h"
-#include "../include/rdcu_rmap.h"
-#include "../include/rdcu_ctrl.h"
-#include "../include/rdcu_cmd.h"
+#include "rdcu_pkt_to_file.h"
+#include "cmp_rdcu_extended.h"
+#include "rdcu_rmap.h"
+#include "rdcu_ctrl.h"
+#include "rdcu_cmd.h"
 
 /* Name of directory were the RMAP packages are stored */
 static char tc_folder_dir[MAX_TC_FOLDER_DIR_LEN] = "TC_FILES";
@@ -52,7 +52,6 @@ void set_tc_folder_dir(const char *dir_name)
 	strncpy(tc_folder_dir, dir_name, sizeof(tc_folder_dir));
 	/*  Ensure null-termination. */
 	tc_folder_dir[sizeof(tc_folder_dir) - 1] = '\0';
-	return;
 }
 
 
@@ -292,8 +291,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
 	if (read_all < 0x7)
 		return -1;
 
-	printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %d for the "
-	       "RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
+	printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %d for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
 
 	return 0;
 }
diff --git a/meson.build b/meson.build
index d300c11..6757167 100644
--- a/meson.build
+++ b/meson.build
@@ -5,6 +5,8 @@ project('cmp_tool', 'c',
   default_options : ['warning_level=3', 'c_std=gnu99']
 )
 
+add_project_arguments('-DDEBUGLEVEL=1', language : 'c')
+
 if host_machine.system() == 'windows' and meson.get_compiler('c').get_id() == 'gcc'
   # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)),
   # you need to add -mno-ms-bitfields to make it work as expected.
diff --git a/test/cmp_icu/meson.build b/test/cmp_icu/meson.build
index 80c3e27..405d376 100644
--- a/test/cmp_icu/meson.build
+++ b/test/cmp_icu/meson.build
@@ -1,14 +1,26 @@
-test_cmp_icu_files = files ([
-  'test_cmp_icu.c'
-])
+test_case = files('test_cmp_icu.c')
+test_runner = test_runner_generator.process(test_case)
 
 test_cmp_icu = executable('test_cmp_icu',
-   test_cmp_icu_files,
+   test_case, test_runner,
    include_directories : incdir,
    link_with : cmp_lib,
-   # c_args : ['-DMAIN']
-   dependencies : cunit_dep,
+   dependencies : unity_dep,
    build_by_default : false
 )
 
-test('cmp_icu unit test', test_cmp_icu)
+test('cmp_icu Unit Tests', test_cmp_icu)
+
+
+test_case = files('test_decmp.c')
+test_runner = test_runner_generator.process(test_case)
+
+test_cmp_decomp = executable('test_cmp_decomp',
+   test_case, test_runner,
+   include_directories : incdir,
+   link_with : cmp_lib,
+   dependencies : unity_dep,
+   build_by_default : false
+)
+
+test('Compression Decompression Unit Tests', test_cmp_decomp)
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index 8bf30d6..35f938a 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -1,128 +1,1388 @@
-/*
- *  Simple example of a CUnit unit test.
- *
- *  This program (crudely) demonstrates a very simple "black box"
- *  test of the standard library functions fprintf() and fread().
- *  It uses suite initialization and cleanup functions to open
- *  and close a common temporary file used by the test functions.
- *  The test functions then write to and read from the temporary
- *  file in the course of testing the library functions.
- *
- *  The 2 test functions are added to a single CUnit suite, and
- *  then run using the CUnit Basic interface.  The output of the
- *  program (on CUnit version 2.0-2) is:
- *
- *           CUnit : A Unit testing framework for C.
- *           http://cunit.sourceforge.net/
- *
- *       Suite: Suite_1
- *         Test: test of fprintf() ... passed
- *         Test: test of fread() ... passed
- *
- *       --Run Summary: Type      Total     Ran  Passed  Failed
- *                      suites        1       1     n/a       0
- *                      tests         2       2       2       0
- *                      asserts       5       5       5       0
+#include <string.h>
+#include <stdlib.h>
+
+#include "unity.h"
+
+#include "cmp_support.h"
+/* this is a hack to test static functions */
+#include "../lib/cmp_icu.c"
+
+
+/**
+ * @test map_to_pos
  */
 
-#include <stdio.h>
-#include <string.h>
-#include "CUnit/Basic.h"
+void test_map_to_pos(void)
+{
+	uint32_t value_to_map;
+	uint32_t max_data_bits;
+	uint32_t mapped_value;
+
+	/* test mapping 32 bits values */
+	max_data_bits = 32;
+
+	value_to_map = 0;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(0, mapped_value);
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 1;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(2, mapped_value);
+
+	value_to_map = 42;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(84, mapped_value);
+
+	value_to_map = INT32_MAX;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value);
+
+	value_to_map = INT32_MIN;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value);
+
+	/* test mapping 16 bits values */
+	max_data_bits = 16;
+
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	/* test mapping 6 bits values */
+	max_data_bits = 6;
 
-/* Pointer to the file used by the tests. */
-static FILE* temp_file = NULL;
+	value_to_map = 0;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(0, mapped_value);
 
-/* The suite initialization function.
- * Opens the temporary file used by the tests.
- * Returns zero on success, non-zero otherwise.
+	value_to_map = -1U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = UINT32_MAX;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = -1U & 0x3FU;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 63;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(1, mapped_value);
+
+	value_to_map = 1;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(2, mapped_value);
+
+	value_to_map = 31;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(62, mapped_value);
+
+	value_to_map = -33U; /* aka 31 */
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(62, mapped_value);
+
+	value_to_map = -32U;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(63, mapped_value);
+
+	value_to_map = 32;
+	mapped_value = map_to_pos(value_to_map, max_data_bits);
+	TEST_ASSERT_EQUAL_INT(63, mapped_value);
+}
+
+
+/**
+ * @test put_n_bits32
  */
-int init_suite1(void)
+
+#define SDP_PB_N 3
+
+
+static void init_PB32_arrays(uint32_t *z, uint32_t *o)
 {
-	if (NULL == (temp_file = fopen("temp.txt", "w+"))) {
-		return -1;
-	}
-	else {
-		return 0;
+	uint32_t i;
+
+	/* init testarray with all 0 and all 1 */
+	for (i = 0; i < SDP_PB_N; i++) {
+		z[i] = 0;
+		o[i] = 0xffffffff;
 	}
 }
 
-/* The suite cleanup function.
- * Closes the temporary file used by the tests.
- * Returns zero on success, non-zero otherwise.
+
+void test_put_n_bits32(void)
+{
+	uint32_t v, n;
+	int o, rval; /* return value */
+	uint32_t testarray0[SDP_PB_N];
+	uint32_t testarray1[SDP_PB_N];
+	const uint32_t l = sizeof(testarray0) * CHAR_BIT;
+
+	/* hereafter, the value is v,
+	 * the number of bits to write is n,
+	 * the offset of the bit is o,
+	 * the max length the bitstream in bits is l
+	 */
+
+	init_PB32_arrays(testarray0, testarray1);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+
+	/*** n=0 ***/
+
+	/* do not write, left border */
+	v = 0; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+
+	v = 0xffffffff; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(0, rval);
+
+	/* do not write, right border */
+	v = 0; n = 0; o = l;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+
+	/* test value = 0xffffffff; N = 0 */
+	v = 0xffffffff; n = 0; o = l;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(l, rval);
+
+	/*** n=1 ***/
+
+	/* left border, write 0 */
+	v = 0; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray1[0] == 0x7fffffff);
+
+	/* left border, write 1 */
+	v = 1; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray0[0] == 0x80000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(1, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+
+	/* left border, write 32 */
+	v = 0xf0f0abcd; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 2 bits */
+	v = 3; n = 2; o = 29;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 31);
+	TEST_ASSERT(testarray0[0] == 0x6);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT_EQUAL_INT(rval, 31);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/*** n=5, unsegmented ***/
+
+	/* left border, write 0 */
+	v = 0; n = 5; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT(testarray1[0] == 0x07ffffff);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* left border, write 11111 */
+	v = 0x1f; n = 5; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray0[0] == 0xf8000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 5);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 0 */
+	v = 0; n = 5; o = 7;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray1[0] == 0xfe0fffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* middle, write 11111 */
+	v = 0x1f; n = 5; o = 7;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray0[0] == 0x01f00000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 12);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* right, write 0 */
+	v = 0; n = 5; o = 91;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[0] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffe0);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* right, write 11111 */
+	v = 0x1f; n = 5; o = 91;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0x0000001f);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 96);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write 0 */
+	v = 0; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0x00000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0x00000000);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write -1 */
+	v = 0xffffffff; n = 32; o = 0;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray0[0] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 32);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* SEGMENTED cases */
+	/* 5 bit, write 0 */
+	v = 0; n = 5; o = 62;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xfffffffc);
+	TEST_ASSERT(testarray1[2] == 0x1fffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 5 bit, write 1f */
+	v = 0x1f; n = 5; o = 62;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 3);
+	TEST_ASSERT(testarray0[2] == 0xe0000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 67);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write 0 */
+	v = 0; n = 32; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray0[0] == 0x00000000);
+	TEST_ASSERT(testarray0[1] == 0x00000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray1[0] == 0x80000000);
+	TEST_ASSERT(testarray1[1] == 0x7fffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* 32 bit, write -1 */
+	v = 0xffffffff; n = 32; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray0[0] == 0x7fffffff);
+	TEST_ASSERT(testarray0[1] == 0x80000000);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(rval, 33);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/* test NULL buffer */
+	v = 0; n = 0; o = 0;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 0);
+
+	v = 0; n = 1; o = 0;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 1);
+
+	v = 0; n = 5; o = 31;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 36);
+
+	v = 0; n = 2; o = 95;
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
+
+	/* value larger than n allows */
+	v = 0x7f; n = 6; o = 10;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray0[0] == 0x003f0000);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	v = 0xffffffff; n = 6; o = 10;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray0[0] == 0x003f0000);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(16, rval);
+	/* re-init input arrays after clobbering */
+	init_PB32_arrays(testarray0, testarray1);
+
+	/*** error cases ***/
+	/* n too large */
+	v = 0x0; n = 33; o = 1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(rval, -1);
+
+	/* try to put too much in the bitstream */
+	v = 0x1; n = 1; o = 96;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+	TEST_ASSERT(testarray0[2] == 0);
+
+	/* this should work (if bitstream=NULL no length check) */
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(97, rval);
+
+	/* offset lager than max_stream_len(l) */
+	v = 0x0; n = 32; o = INT32_MAX;
+	rval = put_n_bits32(v, n, o, testarray1, l);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT(testarray1[0] == 0xffffffff);
+	TEST_ASSERT(testarray1[1] == 0xffffffff);
+	TEST_ASSERT(testarray1[2] == 0xffffffff);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT(rval < 0);
+
+	/* negative offset */
+	v = 0x0; n = 0; o = -1;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+
+	v = 0x0; n = 0; o = -2;
+	rval = put_n_bits32(v, n, o, testarray0, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+	TEST_ASSERT(testarray0[0] == 0);
+	TEST_ASSERT(testarray0[1] == 0);
+
+	rval = put_n_bits32(v, n, o, NULL, l);
+	TEST_ASSERT_EQUAL_INT(-1, rval);
+}
+
+
+/**
+ * @test rice_encoder
  */
-int clean_suite1(void)
+
+void test_rice_encoder(void)
 {
-	if (0 != fclose(temp_file)) {
-		return -1;
-	}
-	else {
-		temp_file = NULL;
-		return 0;
-	}
+	uint32_t value, g_par, log2_g_par, cw, cw_len;
+
+	/* test minimum Golomb parameter */
+	value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(1, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 31;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
+
+	/* test some arbitrary values */
+	value = 0; log2_g_par = 4; g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 42;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(7, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
+
+	value = 446;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
+
+	value = 447;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
+
+	/* test maximum Golomb parameter for rice_encoder */
+	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 0x7FFFFFFE;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
+
+	value = 0x7FFFFFFF;
+	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
 }
 
-/* Simple test of fprintf().
- * Writes test data to the temporary file and checks
- * whether the expected number of bytes were written.
+
+/**
+ * @test golomb_encoder
  */
-void testFPRINTF(void)
+
+void test_Golomb_encoder(void)
 {
-	int i1 = 10;
+	uint32_t value, g_par, log2_g_par, cw, cw_len;
 
-	if (NULL != temp_file) {
-		CU_ASSERT(0 == fprintf(temp_file, ""));
-		CU_ASSERT(2 == fprintf(temp_file, "Q\n"));
-		CU_ASSERT(7 == fprintf(temp_file, "i1 = %d", i1));
-	}
+	/* test minimum Golomb parameter */
+	value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(1, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 31;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
+
+
+	/* test some arbitrary values with g_par = 16 */
+	value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(5, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 42;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(7, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
+
+	value = 446;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
+
+	value = 447;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
+
+
+	/* test some arbitrary values with g_par = 3 */
+	value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(2, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(3, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x2, cw);
+
+	value = 42;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(16, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFC, cw);
+
+	value = 44;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(17, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1FFFB, cw);
+
+	value = 88;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFA, cw);
+
+	value = 89;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw);
+
+
+	/* test maximum Golomb parameter for golomb_encoder */
+	value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x0, cw);
+
+	value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x1, cw);
+
+	value = 0x7FFFFFFE;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
+
+	value = 0x7FFFFFFF;
+	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
+	TEST_ASSERT_EQUAL_INT(32, cw_len);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
 }
 
-/* Simple test of fread().
- * Reads the data previously written by testFPRINTF()
- * and checks whether the expected characters are present.
- * Must be run after testFPRINTF().
+
+/**
+ * @test encode_value_zero
  */
-void testFREAD(void)
+
+void test_encode_value_zero(void)
 {
-	unsigned char buffer[20];
+	uint32_t data, model;
+	int stream_len;
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[3] = {0};
 
-	if (NULL != temp_file) {
-		rewind(temp_file);
-		CU_ASSERT(9 == fread(buffer, sizeof(unsigned char), 20, temp_file));
-		CU_ASSERT(0 == strncmp(buffer, "Q\ni1 = 10", 9));
-	}
+	/* setup the setup */
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
+	setup.spillover_par = 32;
+	setup.max_data_bits = 32;
+	setup.generate_cw_f = rice_encoder;
+	setup.bitstream_adr = bitstream;
+	setup.max_stream_len = sizeof(bitstream) * CHAR_BIT;
+
+	stream_len = 0;
+
+	data = 0; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(2, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	data = 5; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(14, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	data = 2; model = 7;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(25, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* zero escape mechanism */
+	data = 100; model = 42;
+	/* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(58, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* test overflow */
+	data = INT32_MIN; model = 0;
+	/* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(91, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+
+	/* small buffer error */
+	data = 23; model = 26;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+
+	/* reset bitstream to all bits set */
+	bitstream[0] = ~0U;
+	bitstream[1] = ~0U;
+	bitstream[2] = ~0U;
+	stream_len = 0;
+
+	/* we use now values with maximum 6 bits */
+	setup.max_data_bits = 6;
+
+	/* lowest value before zero encoding */
+	data = 53; model = 38;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(32, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* lowest value with zero encoding */
+	data = 0; model = 16;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(39, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* maximum positive value to encode */
+	data = 31; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(46, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* maximum negative value to encode */
+	data = 0; model = 32;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(53, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
+
+	/* small buffer error when creating the zero escape symbol*/
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	bitstream[2] = 0;
+	stream_len = 32;
+	setup.max_stream_len = 32;
+	data = 31; model = 0;
+	stream_len = encode_value_zero(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
 }
 
-/* The main() function for setting up and running the tests.
- * Returns a CUE_SUCCESS on successful running, another
- * CUnit error code on failure.
+
+/**
+ * @test encode_value_multi
  */
-int main()
+
+void test_encode_value_multi(void)
 {
-	CU_pSuite pSuite = NULL;
+	uint32_t data, model;
+	int stream_len;
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[4] = {0};
 
-	/* initialize the CUnit test registry */
-	if (CUE_SUCCESS != CU_initialize_registry())
-		return CU_get_error();
+	/* setup the setup */
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
+	setup.spillover_par = 16;
+	setup.max_data_bits = 32;
+	setup.generate_cw_f = golomb_encoder;
+	setup.bitstream_adr = bitstream;
+	setup.max_stream_len = sizeof(bitstream) * CHAR_BIT;
 
-	/* add a suite to the registry */
-	pSuite = CU_add_suite("Suite_1", init_suite1, clean_suite1);
-	if (NULL == pSuite) {
-		CU_cleanup_registry();
-		return CU_get_error();
-	}
+	stream_len = 0;
+
+	data = 0; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(1, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	data = 0; model = 1;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(3, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x40000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	data = 1+23; model = 0+23;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(6, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x58000000, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* highest value without multi outlier encoding */
+	data = 0+42; model = 8+42;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(22, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFF800, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* lowest value with multi outlier encoding */
+	data = 8+42; model = 0+42;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(41, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFC000000, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* highest value with multi outlier encoding */
+	data = INT32_MIN; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(105, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0xF7800000, bitstream[3]);
+
+	/* small buffer error */
+	data = 0; model = 38;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+
+	/* small buffer error when creating the multi escape symbol*/
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	setup.max_stream_len = 32;
+
+	stream_len = 32;
+	data = 31; model = 0;
+	stream_len = encode_value_multi(data, model, stream_len, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+}
+
+
+/**
+ * @test encode_value
+ */
+
+void test_encode_value(void)
+{
+	struct encoder_setupt setup = {0};
+	uint32_t bitstream[4] = {0};
+	uint32_t data, model;
+	int cmp_size;
+
+	setup.encode_method_f = encode_value_none;
+	setup.bitstream_adr = bitstream;
+	setup.max_stream_len = 128;
+	cmp_size = 0;
+
+	/* test 32 bit input */
+	setup.encoder_par1 = 32;
+	setup.max_data_bits = 32;
+	setup.lossy_par = 0;
+
+	data = 0; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(32, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	data = UINT32_MAX; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(64, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	/* test rounding */
+	setup.lossy_par = 1;
+	data = UINT32_MAX; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(96, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	setup.lossy_par = 2;
+	data = 0x3; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(128, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
+
+	/* small buffer error bitstream can not hold more data*/
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+
+	/* reset bitstream */
+	bitstream[0] = 0;
+	bitstream[1] = 0;
+	bitstream[2] = 0;
+	bitstream[3] = 0;
+	cmp_size = 0;
+
+	/* test 31 bit input */
+	setup.encoder_par1 = 31;
+	setup.max_data_bits = 31;
+	setup.lossy_par = 0;
+
+	data = 0; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(31, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	data = 0x7FFFFFFF; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(62, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0x00000001, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFC, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	/* round = 1 */
+	setup.lossy_par = 1;
+	data = UINT32_MAX; model = UINT32_MAX;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(93, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0x00000001, bitstream[0]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFFFFF8, bitstream[2]);
+	TEST_ASSERT_EQUAL_HEX(0, bitstream[3]);
+
+	/* data are bigger than max_data_bits */
+	setup.lossy_par = 0;
+	data = UINT32_MAX; model = 0;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_size);
+
+	/* model are bigger than max_data_bits */
+	setup.lossy_par = 0;
+	cmp_size = 93;
+	data = 0; model = UINT32_MAX;
+	cmp_size = encode_value(data, model, cmp_size, &setup);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_size);
+}
+
+
+/**
+ * @test cmp_get_max_used_bits
+ */
+
+void test_cmp_get_max_used_bits(void)
+{
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_imagette, MAX_USED_NC_IMAGETTE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.saturated_imagette, MAX_USED_SATURATED_IMAGETTE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_imagette, MAX_USED_FC_IMAGETTE_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_fx, MAX_USED_F_FX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_efx, MAX_USED_F_EFX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_ncob, MAX_USED_F_NCOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.f_ecob, MAX_USED_F_ECOB_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_exp_flags, MAX_USED_S_FX_EXPOSURE_FLAGS_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_fx, MAX_USED_S_FX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_efx, MAX_USED_S_EFX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_ncob, MAX_USED_S_NCOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.s_ecob, MAX_USED_S_ECOB_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_fx_variance, MAX_USED_L_FX_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_efx, MAX_USED_L_EFX_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_ncob, MAX_USED_L_NCOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_ecob, MAX_USED_L_ECOB_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.l_cob_variance, MAX_USED_L_COB_VARIANCE_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_offset_mean, MAX_USED_NC_OFFSET_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_offset_variance, MAX_USED_NC_OFFSET_VARIANCE_BITS);
 
-	/* add the tests to the suite */
-	/* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */
-	if ((NULL == CU_add_test(pSuite, "test of fprintf()", testFPRINTF)) ||
-	    (NULL == CU_add_test(pSuite, "test of fread()", testFREAD)))
-	{
-		CU_cleanup_registry();
-		return CU_get_error();
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_mean, MAX_USED_NC_BACKGROUND_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_variance, MAX_USED_NC_BACKGROUND_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_outlier_pixels, MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smeating_mean, MAX_USED_SMEARING_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smeating_variance_mean, MAX_USED_SMEARING_VARIANCE_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smearing_outlier_pixels, MAX_USED_SMEARING_OUTLIER_PIXELS_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_mean, MAX_USED_FC_OFFSET_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_variance, MAX_USED_FC_OFFSET_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_pixel_in_error, MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS);
+
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_background_mean, MAX_USED_FC_BACKGROUND_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_background_variance, MAX_USED_FC_BACKGROUND_VARIANCE_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_background_outlier_pixels, MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS);
+}
+
+
+void test_compress_imagette_diff(void)
+{
+	uint16_t data[] = {0xFFFF, 1, 0, 42, 0x8000, 0x7FFF, 0xFFFF};
+	uint32_t output_buf[3] = {0xFFFF, 0xFFFF, 0xFFFF};
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.golomb_par = 1;
+	cfg.spill = 8;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 7;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(66, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0xDF6002AB, be32_to_cpu(output_buf[0]));
+	TEST_ASSERT_EQUAL_HEX(0xFEB70000, be32_to_cpu(output_buf[1]));
+	TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(output_buf[2]));
+}
+
+void test_compress_imagette_model(void)
+{
+	uint16_t data[]  = {0x0000, 0x0001, 0x0042, 0x8000, 0x7FFF, 0xFFFF, 0xFFFF};
+	uint16_t model[] = {0x0000, 0xFFFF, 0xF301, 0x8FFF, 0x0000, 0xFFFF, 0x0000};
+	uint16_t model_up[7] = {0};
+	uint32_t output_buf[3] = {0xFFFF, 0xFFFF, 0xFFFF};
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.icu_new_model_buf = model_up;
+	cfg.samples = 7;
+	cfg.golomb_par = 3;
+	cfg.spill = 8;
+	cfg.model_value = 8;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 8;
+
+	cmp_size = icu_compress_data(&cfg);
+
+	TEST_ASSERT_EQUAL_INT(76, cmp_size);
+	TEST_ASSERT_EQUAL_HEX(0x2BDB4F5E, be32_to_cpu(output_buf[0]));
+	TEST_ASSERT_EQUAL_HEX(0xDFF5F9FF, be32_to_cpu(output_buf[1]));
+	TEST_ASSERT_EQUAL_HEX(0xEC200000, be32_to_cpu(output_buf[2]));
+
+	TEST_ASSERT_EQUAL_HEX(0x0000, model_up[0]);
+	TEST_ASSERT_EQUAL_HEX(0x8000, model_up[1]);
+	TEST_ASSERT_EQUAL_HEX(0x79A1, model_up[2]);
+	TEST_ASSERT_EQUAL_HEX(0x87FF, model_up[3]);
+	TEST_ASSERT_EQUAL_HEX(0x3FFF, model_up[4]);
+	TEST_ASSERT_EQUAL_HEX(0xFFFF, model_up[5]);
+	TEST_ASSERT_EQUAL_HEX(0x7FFF, model_up[6]);
+}
+
+
+void test_compress_imagette_stuff(void)
+{
+	uint16_t data[] = {0x0, 0x1, 0x23, 0x42, 0x8000, 0x7FFF, 0xFFFF};
+	uint32_t output_buf[4] = {0};
+	struct cmp_cfg cfg = {0};
+
+	int cmp_size;
+	uint8_t output_buf_exp[] = {
+		0x00, 0x00, 0x00, 0x01,
+		0x00, 0x23, 0x00, 0x42,
+		0x80, 0x00, 0x7F, 0xFF,
+		0xFF, 0xFF, 0x00, 0x00};
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_STUFF;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 8;
+	cfg.golomb_par = 16; /* how many used bits has the maximum data value */
+
+	cmp_size = icu_compress_data(&cfg);
+
+	uint32_t *output_buf_exp_32 = (uint32_t *)output_buf_exp;
+	TEST_ASSERT_EQUAL_INT(7*16, cmp_size);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[0], output_buf[0]);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[1], output_buf[1]);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[2], output_buf[2]);
+	TEST_ASSERT_EQUAL_HEX16(output_buf_exp_32[3], output_buf[3]);
+}
+
+
+void test_compress_imagette_raw(void)
+{
+	uint16_t data[] = {0x0, 0x1, 0x23, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX};
+	uint16_t output_buf[7] = {0};
+	struct cmp_cfg cfg = {0};
+
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.model_buf = NULL;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 7;
+
+
+	cmp_size = icu_compress_data(&cfg);
+
+	TEST_ASSERT_EQUAL_INT(7*16, cmp_size);
+	TEST_ASSERT_EQUAL_HEX16(0x0, be16_to_cpu(output_buf[0]));
+	TEST_ASSERT_EQUAL_HEX16(0x1, be16_to_cpu(output_buf[1]));
+	TEST_ASSERT_EQUAL_HEX16(0x23, be16_to_cpu(output_buf[2]));
+	TEST_ASSERT_EQUAL_HEX16(0x42, be16_to_cpu(output_buf[3]));
+	TEST_ASSERT_EQUAL_HEX16(INT16_MIN, be16_to_cpu(output_buf[4]));
+	TEST_ASSERT_EQUAL_HEX16(INT16_MAX, be16_to_cpu(output_buf[5]));
+	TEST_ASSERT_EQUAL_HEX16(UINT16_MAX, be16_to_cpu(output_buf[6]));
+}
+
+
+void test_compress_s_fx_raw(void)
+{
+	struct s_fx data[7];
+	struct cmp_cfg cfg = {0};
+	int cmp_size, cmp_size_exp;
+	size_t i;
+
+	cfg.data_type = DATA_TYPE_S_FX;
+	cfg.model_buf = NULL;
+	cfg.samples = 7;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	cfg.buffer_length = 7;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[4].exp_flags = 0x0;
+	data[4].fx = INT32_MIN;
+	data[5].exp_flags = 0x3;
+	data[5].fx = INT32_MAX;
+	data[6].exp_flags = 0x1;
+	data[6].fx = UINT32_MAX;
+
+	struct multi_entry_hdr *hdr = cfg.input_buf;
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	memcpy(hdr->entry, data, sizeof(data));
+
+	cmp_size = icu_compress_data(&cfg);
+
+	cmp_size_exp = (sizeof(data) + sizeof(struct multi_entry_hdr)) * CHAR_BIT;
+	TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size);
+
+	for (i = 0; i < ARRAY_SIZE(data); i++) {
+		hdr = (struct multi_entry_hdr *)cfg.icu_output_buf;
+		struct s_fx *p = (struct s_fx *)hdr->entry;
+
+		TEST_ASSERT_EQUAL_HEX(data[i].exp_flags, p[i].exp_flags);
+		TEST_ASSERT_EQUAL_HEX(data[i].fx, cpu_to_be32(p[i].fx));
 	}
+}
+
+
+void test_compress_s_fx_staff(void)
+{
+	struct s_fx data[5];
+	struct cmp_cfg cfg = {0};
+	int cmp_size, cmp_size_exp;
+	struct multi_entry_hdr *hdr;
+	uint32_t *cmp_data;
+
+	/* setup configuration */
+	cfg.data_type = DATA_TYPE_S_FX;
+	cfg.cmp_mode = CMP_MODE_STUFF;
+	cfg.samples = 5;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+	cfg.buffer_length = 5;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	cfg.cmp_par_exp_flags = 2;
+	cfg.cmp_par_fx = 21;
+
+	/* generate input data */
+	hdr = cfg.input_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[4].exp_flags = 0x0;
+	data[4].fx = 0x001FFFFF;
+	memcpy(hdr->entry, data, sizeof(data));
+
+	cmp_size = icu_compress_data(&cfg);
 
-	/* Run all tests using the CUnit Basic interface */
-	CU_basic_set_mode(CU_BRM_VERBOSE);
-	CU_basic_run_tests();
-	CU_cleanup_registry();
-	return CU_get_error();
+	cmp_size_exp = 5 * (2 + 21) + MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
+	TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size);
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	hdr = (void *)cfg.icu_output_buf;
+	cmp_data = (uint32_t *)hdr->entry;
+	TEST_ASSERT_EQUAL_HEX(0x00000080, be32_to_cpu(cmp_data[0]));
+	TEST_ASSERT_EQUAL_HEX(0x00060001, be32_to_cpu(cmp_data[1]));
+	TEST_ASSERT_EQUAL_HEX(0x1E000423, be32_to_cpu(cmp_data[2]));
+	TEST_ASSERT_EQUAL_HEX(0xFFFFE000, be32_to_cpu(cmp_data[3]));
+
+	free(cfg.input_buf);
+	free(cfg.icu_output_buf);
+}
+
+
+void test_compress_s_fx_model_multi(void)
+{
+	struct s_fx data[6], model[6];
+	struct s_fx *up_model_buf;
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+	struct multi_entry_hdr *hdr;
+	uint32_t *cmp_data;
+	struct cmp_max_used_bits max_used_bits;
+
+	/* setup configuration */
+	cfg.data_type = DATA_TYPE_S_FX;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.model_value = 11;
+	cfg.samples = 6;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+	cfg.model_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.model_buf);
+	cfg.icu_new_model_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_new_model_buf);
+	cfg.buffer_length = 6;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	cfg.cmp_par_exp_flags = 1;
+	cfg.spill_exp_flags = 8;
+	cfg.cmp_par_fx = 3;
+	cfg.spill_fx = 35;
+
+
+	/* generate input data */
+	hdr = cfg.input_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[4].exp_flags = 0x0;
+	data[4].fx = 0x001FFFFF;
+	data[5].exp_flags = 0x0;
+	data[5].fx = 0x0;
+	memcpy(hdr->entry, data, sizeof(data));
+
+	/* generate model data */
+	hdr = cfg.model_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x41, sizeof(struct multi_entry_hdr));
+	model[0].exp_flags = 0x0;
+	model[0].fx = 0x0;
+	model[1].exp_flags = 0x3;
+	model[1].fx = 0x1;
+	model[2].exp_flags = 0x0;
+	model[2].fx = 0x42;
+	model[3].exp_flags = 0x0;
+	model[3].fx = 0x23;
+	model[4].exp_flags = 0x3;
+	model[4].fx = 0x0;
+	model[5].exp_flags = 0x2;
+	model[5].fx = 0x001FFFFF;
+	memcpy(hdr->entry, model, sizeof(model));
+
+	max_used_bits = cmp_get_max_used_bits();
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cmp_size = icu_compress_data(&cfg);
+
+	TEST_ASSERT_EQUAL_INT(166, cmp_size);
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	cmp_data = &cfg.icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
+	TEST_ASSERT_EQUAL_HEX(0x1C77FFA6, be32_to_cpu(cmp_data[0]));
+	TEST_ASSERT_EQUAL_HEX(0xAFFF4DE5, be32_to_cpu(cmp_data[1]));
+	TEST_ASSERT_EQUAL_HEX(0xCC000000, be32_to_cpu(cmp_data[2]));
+
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	hdr = cfg.icu_new_model_buf;
+	up_model_buf = (struct s_fx *)hdr->entry;
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].fx);
+	TEST_ASSERT_EQUAL_HEX(0x2, up_model_buf[1].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x1, up_model_buf[1].fx);
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[2].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x38, up_model_buf[2].fx);
+	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[3].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x2C, up_model_buf[3].fx);
+	TEST_ASSERT_EQUAL_HEX(0x2, up_model_buf[4].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x9FFFF, up_model_buf[4].fx);
+	TEST_ASSERT_EQUAL_HEX(0x1, up_model_buf[5].exp_flags);
+	TEST_ASSERT_EQUAL_HEX(0x15FFFF, up_model_buf[5].fx);
+
+	free(cfg.input_buf);
+	free(cfg.model_buf);
+	free(cfg.icu_new_model_buf);
+	free(cfg.icu_output_buf);
 }
+
+
diff --git a/test/cmp_icu/test_cmp_icu_new.c b/test/cmp_icu/test_cmp_icu_new.c
deleted file mode 100644
index a0d9109..0000000
--- a/test/cmp_icu/test_cmp_icu_new.c
+++ /dev/null
@@ -1,894 +0,0 @@
-#include <string.h>
-
-#include "unity.h"
-
-#include "cmp_support.h"
-/* this is a hack to test static functions */
-#include "../lib/cmp_icu_new.c"
-
-
-/**
- * @test map_to_pos
- */
-
-void test_map_to_pos(void)
-{
-	uint32_t value_to_map;
-	uint32_t max_value_bits;
-	uint32_t mapped_value;
-
-	/* test mapping 32 bits values */
-	max_value_bits = 32;
-
-	value_to_map = 0;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(0, mapped_value);
-
-	value_to_map = -1U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = 1;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(2, mapped_value);
-
-	value_to_map = 42;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(84, mapped_value);
-
-	value_to_map = INT32_MAX;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value);
-
-	value_to_map = INT32_MIN;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value);
-
-	/* test mapping 16 bits values */
-	max_value_bits = 16;
-
-	value_to_map = -1U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	/* test mapping 6 bits values */
-	max_value_bits = 6;
-
-	value_to_map = 0;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(0, mapped_value);
-
-	value_to_map = -1U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = UINT32_MAX;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = -1U & 0x3FU;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = 63;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(1, mapped_value);
-
-	value_to_map = 1;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(2, mapped_value);
-
-	value_to_map = 31;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(62, mapped_value);
-
-	value_to_map = -33U; /* aka 31 */
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(62, mapped_value);
-
-	value_to_map = -32U;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(63, mapped_value);
-
-	value_to_map = 32;
-	mapped_value = map_to_pos(value_to_map, max_value_bits);
-	TEST_ASSERT_EQUAL_INT(63, mapped_value);
-}
-
-
-/**
- * @test put_n_bits32
- */
-
-#define SDP_PB_N 3
-
-
-static void init_PB32_arrays(uint32_t *z, uint32_t *o)
-{
-	uint32_t i;
-
-	/* init testarray with all 0 and all 1 */
-	for (i = 0; i < SDP_PB_N; i++) {
-		z[i] = 0;
-		o[i] = 0xffffffff;
-	}
-}
-
-
-void test_put_n_bits32(void)
-{
-	uint32_t v, n;
-	int o, rval; /* return value */
-	uint32_t testarray0[SDP_PB_N];
-	uint32_t testarray1[SDP_PB_N];
-	const uint32_t l = sizeof(testarray0) * CHAR_BIT;
-
-	/* hereafter, the value is v,
-	 * the number of bits to write is n,
-	 * the offset of the bit is o,
-	 * the max length the bitstream in bits is l
-	 */
-
-	init_PB32_arrays(testarray0, testarray1);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-
-	/*** n=0 ***/
-
-	/* do not write, left border */
-	v = 0; n = 0; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-
-	v = 0xffffffff; n = 0; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(0, rval);
-
-	/* do not write, right border */
-	v = 0; n = 0; o = l;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-
-	/* test value = 0xffffffff; N = 0 */
-	v = 0xffffffff; n = 0; o = l;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(l, rval);
-
-	/*** n=1 ***/
-
-	/* left border, write 0 */
-	v = 0; n = 1; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray1[0] == 0x7fffffff);
-
-	/* left border, write 1 */
-	v = 1; n = 1; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray0[0] == 0x80000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(1, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-
-	/* left border, write 32 */
-	v = 0xf0f0abcd; n = 32; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray0[0] == 0xf0f0abcd);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray1[0] == 0xf0f0abcd);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* middle, write 2 bits */
-	v = 3; n = 2; o = 29;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 31);
-	TEST_ASSERT(testarray0[0] == 0x6);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT_EQUAL_INT(rval, 31);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/*** n=5, unsegmented ***/
-
-	/* left border, write 0 */
-	v = 0; n = 5; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT(testarray1[0] == 0x07ffffff);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* left border, write 11111 */
-	v = 0x1f; n = 5; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	TEST_ASSERT(testarray0[0] == 0xf8000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 5);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* middle, write 0 */
-	v = 0; n = 5; o = 7;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray1[0] == 0xfe0fffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* middle, write 11111 */
-	v = 0x1f; n = 5; o = 7;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray0[0] == 0x01f00000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 12);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* right, write 0 */
-	v = 0; n = 5; o = 91;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[0] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffe0);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* right, write 11111 */
-	v = 0x1f; n = 5; o = 91;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0x0000001f);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 96);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write 0 */
-	v = 0; n = 32; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray0[0] == 0x00000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray1[0] == 0x00000000);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write -1 */
-	v = 0xffffffff; n = 32; o = 0;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray0[0] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 32);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* SEGMENTED cases */
-	/* 5 bit, write 0 */
-	v = 0; n = 5; o = 62;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xfffffffc);
-	TEST_ASSERT(testarray1[2] == 0x1fffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 5 bit, write 1f */
-	v = 0x1f; n = 5; o = 62;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 3);
-	TEST_ASSERT(testarray0[2] == 0xe0000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 67);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write 0 */
-	v = 0; n = 32; o = 1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray0[0] == 0x00000000);
-	TEST_ASSERT(testarray0[1] == 0x00000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray1[0] == 0x80000000);
-	TEST_ASSERT(testarray1[1] == 0x7fffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* 32 bit, write -1 */
-	v = 0xffffffff; n = 32; o = 1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray0[0] == 0x7fffffff);
-	TEST_ASSERT(testarray0[1] == 0x80000000);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(rval, 33);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/* test NULL buffer */
-	v = 0; n = 0; o = 0;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 0);
-
-	v = 0; n = 1; o = 0;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 1);
-
-	v = 0; n = 5; o = 31;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 36);
-
-	v = 0; n = 2; o = 95;
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, 97); /* rval can be longer than l */
-
-	/* value larger than n allows */
-	v = 0x7f; n = 6; o = 10;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray0[0] == 0x003f0000);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	v = 0xffffffff; n = 6; o = 10;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray0[0] == 0x003f0000);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(16, rval);
-	/* re-init input arrays after clobbering */
-	init_PB32_arrays(testarray0, testarray1);
-
-	/*** error cases ***/
-	/* n too large */
-	v = 0x0; n = 33; o = 1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(rval, -1);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(rval, -1);
-
-	/* try to put too much in the bitstream */
-	v = 0x1; n = 1; o = 96;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-	TEST_ASSERT(testarray0[2] == 0);
-
-	/* this should work (if bitstream=NULL no length check) */
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(97, rval);
-
-	/* offset lager than max_bit_len(l) */
-	v = 0x0; n = 32; o = INT32_MAX;
-	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
-	TEST_ASSERT(testarray1[0] == 0xffffffff);
-	TEST_ASSERT(testarray1[1] == 0xffffffff);
-	TEST_ASSERT(testarray1[2] == 0xffffffff);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT(rval < 0);
-
-	/* negative offset */
-	v = 0x0; n = 0; o = -1;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-
-	v = 0x0; n = 0; o = -2;
-	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-	TEST_ASSERT(testarray0[0] == 0);
-	TEST_ASSERT(testarray0[1] == 0);
-
-	rval = put_n_bits32(v, n, o, NULL, l);
-	TEST_ASSERT_EQUAL_INT(-1, rval);
-}
-
-
-/**
- * @test Rice_encoder
- */
-
-void test_Rice_encoder(void)
-{
-	uint32_t value, g_par, log2_g_par, cw, cw_len;
-
-	/* test minimum Golomb parameter */
-	value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(1, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 31;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
-
-	/* test some arbitrary values */
-	value = 0; log2_g_par = 4; g_par = 1U << log2_g_par; cw = ~0U;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 42;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(7, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
-
-	value = 446;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
-
-	value = 447;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
-
-	/* test maximum Golomb parameter for Rice_encoder */
-	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 0x7FFFFFFE;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
-
-	value = 0x7FFFFFFF;
-	cw_len = Rice_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
-}
-
-
-/**
- * @test Golomb_encoder
- */
-
-void test_Golomb_encoder(void)
-{
-	uint32_t value, g_par, log2_g_par, cw, cw_len;
-
-	/* test minimum Golomb parameter */
-	value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(1, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 31;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw);
-
-
-	/* test some arbitrary values with g_par = 16 */
-	value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(5, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 42;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(7, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x6a, cw);
-
-	value = 446;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEE, cw);
-
-	value = 447;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
-
-
-	/* test some arbitrary values with g_par = 3 */
-	value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(2, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(3, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x2, cw);
-
-	value = 42;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(16, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFC, cw);
-
-	value = 44;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(17, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1FFFB, cw);
-
-	value = 88;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFA, cw);
-
-	value = 89;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw);
-
-
-	/* test maximum Golomb parameter for Golomb_encoder */
-	value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x0, cw);
-
-	value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x1, cw);
-
-	value = 0x7FFFFFFE;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFE, cw);
-
-	value = 0x7FFFFFFF;
-	cw_len = Golomb_encoder(value, g_par, log2_g_par, &cw);
-	TEST_ASSERT_EQUAL_INT(32, cw_len);
-	TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw);
-}
-
-
-/**
- * @test encode_value_zero
- */
-
-void test_encode_value_zero(void)
-{
-	uint32_t data, model;
-	int stream_len;
-	struct encoder_setupt setup = {0};
-	uint32_t bitstream[3] = {0};
-
-	/* setup the setup */
-	setup.encoder_par1 = 1;
-	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
-	setup.outlier_par = 32;
-	setup.max_value_bits = 32;
-	setup.generate_cw = Rice_encoder;
-	setup.bitstream_adr = bitstream;
-	setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
-
-	stream_len = 0;
-
-	data = 0; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(2, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	data = 5; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(14, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	data = 2; model = 7;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(25, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	/* zero escape mechanism */
-	data = 100; model = 42;
-	/* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(58, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	/* test overflow */
-	data = INT32_MIN; model = 0;
-	/* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(91, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-
-	/* small buffer error */
-	data = 23; model = 26;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-
-	/* reset bitstream to all bits set */
-	bitstream[0] = ~0U;
-	bitstream[1] = ~0U;
-	bitstream[2] = ~0U;
-	stream_len = 0;
-
-	/* we use now values with maximum 6 bits */
-	setup.max_value_bits = 6;
-
-	/* lowest value before zero encoding */
-	data = 53; model = 38;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(32, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* lowest value with zero encoding */
-	data = 0; model = 16;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(39, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* maximum positive value to encode */
-	data = 31; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(46, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* maximum negative value to encode */
-	data = 0; model = 32;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(53, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]);
-
-	/* small buffer error when creating the zero escape symbol*/
-	bitstream[0] = 0;
-	bitstream[1] = 0;
-	bitstream[2] = 0;
-	stream_len = 32;
-	setup.max_bit_len = 32;
-	data = 31; model = 0;
-	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
-}
-
-
-/**
- * @test encode_value_multi
- */
-
-void test_encode_value_multi(void)
-{
-	uint32_t data, model;
-	int stream_len;
-	struct encoder_setupt setup = {0};
-	uint32_t bitstream[4] = {0};
-
-	/* setup the setup */
-	setup.encoder_par1 = 1;
-	setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1);
-	setup.outlier_par = 16;
-	setup.max_value_bits = 32;
-	setup.generate_cw = Rice_encoder;
-	setup.bitstream_adr = bitstream;
-	setup.max_bit_len = sizeof(bitstream) * CHAR_BIT;
-
-	stream_len = 0;
-
-	data = 0; model = 0;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(1, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	data = 0; model = 1;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(3, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x40000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	data = 1+23; model = 0+23;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(6, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x58000000, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	/* highest value without multi outlier encoding */
-	data = 0+42; model = 8+42;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(22, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x5BFFF800, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	/* lowest value with multi outlier encoding */
-	data = 8+42; model = 0+42;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(41, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0xFC000000, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]);
-
-	/* highest value with multi outlier encoding */
-	data = INT32_MIN; model = 0;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(105, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, bitstream[1]);
-	TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, bitstream[2]);
-	TEST_ASSERT_EQUAL_HEX(0xF7800000, bitstream[3]);
-
-	/* small buffer error */
-	data = 0; model = 38;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-
-	/* small buffer error when creating the multi escape symbol*/
-	bitstream[0] = 0;
-	bitstream[1] = 0;
-	setup.max_bit_len = 32;
-
-	stream_len = 32;
-	data = 31; model = 0;
-	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
-	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
-}
diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c
new file mode 100644
index 0000000..523b64f
--- /dev/null
+++ b/test/cmp_icu/test_decmp.c
@@ -0,0 +1,442 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "unity.h"
+
+#include "compiler.h"
+#include "cmp_debug.h"
+#include "cmp_entity.h"
+#include "../../lib/cmp_icu.c" /* .c file included to test static functions */
+#include "../../lib/decmp.c" /* .c file included to test static functions */
+
+
+/* returns the needed size of the compression entry header plus the max size of the
+ * compressed data if ent ==  NULL if ent is set the size of the compression
+ * entry */
+size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cfg)
+{
+	size_t s, hdr_size;
+	struct cmp_cfg cfg_cpy;
+	int cmp_size_bits;
+
+	if (!cfg)
+		return 0;
+
+	if (cfg->icu_output_buf)
+		debug_print("Warning the set buffer for the compressed data is ignored! The compressed data are write to the compression entry.");
+
+	if (!ent) {
+		s = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type);
+		if (!s)
+			return 0;
+
+		hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW);
+		if (!hdr_size)
+			return 0;
+
+		return s + hdr_size;
+	}
+
+	cfg_cpy = *cfg;
+	cfg_cpy.icu_output_buf = cmp_ent_get_data_buf(ent);
+
+	cmp_size_bits = icu_compress_data(&cfg_cpy);
+	if (cmp_size_bits < 0)
+		return 0;
+
+	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW,
+					 cmp_bit_to_4byte(cmp_size_bits));
+	if (!s)
+		return 0;
+
+	if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits))
+		return 0;
+
+	return s;
+}
+
+
+void test_cmp_decmp_n_imagette_raw(void)
+{
+	int cmp_size;
+	size_t s, i;
+	struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 0, CMP_LOSSLESS);
+	uint16_t data[] = {0, 1, 2, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX};
+	uint32_t *compressed_data;
+	uint16_t *decompressed_data;
+	struct cmp_entity *ent;
+
+	s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL,
+				NULL, ARRAY_SIZE(data));
+	TEST_ASSERT_TRUE(s);
+	compressed_data = malloc(s);
+	TEST_ASSERT_TRUE(compressed_data);
+	s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL,
+				compressed_data, ARRAY_SIZE(data));
+	TEST_ASSERT_TRUE(s);
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(sizeof(data)*CHAR_BIT, cmp_size);
+
+	s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_bit_to_4byte(cmp_size));
+	TEST_ASSERT_TRUE(s);
+	ent = malloc(s);
+	TEST_ASSERT_TRUE(ent);
+	s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_bit_to_4byte(cmp_size));
+	TEST_ASSERT_TRUE(s);
+	memcpy(cmp_ent_get_data_buf(ent), compressed_data, (cmp_size+7)/8);
+
+	s = decompress_cmp_entiy(ent, NULL, NULL, NULL);
+	TEST_ASSERT_EQUAL_INT(sizeof(data), s);
+	decompressed_data = malloc(s);
+	TEST_ASSERT_TRUE(decompressed_data);
+	s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(sizeof(data), s);
+
+	for (i = 0; i < ARRAY_SIZE(data); ++i) {
+		TEST_ASSERT_EQUAL_INT(data[i], decompressed_data[i]);
+
+	}
+
+	free(compressed_data);
+	free(ent);
+	free(decompressed_data);
+}
+
+
+/*
+ * @test re_map_to_pos
+ */
+
+void test_re_map_to_pos(void)
+{
+	int j;
+	uint32_t input, result;
+	unsigned int max_value_bits;
+
+	input = INT32_MIN;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = INT32_MAX;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = -1;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = 0;
+	result = re_map_to_pos(map_to_pos(input, 32));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	input = 1; max_value_bits = 6;
+	result = re_map_to_pos(map_to_pos(input, max_value_bits));
+	TEST_ASSERT_EQUAL_INT32(input, result);
+
+	for (j = -16; j < 15; j++) {
+		uint32_t map_val =  map_to_pos(j, 16) & 0x3F;
+		result = re_map_to_pos(map_val);
+		TEST_ASSERT_EQUAL_INT32(j, result);
+	}
+
+	for (j = INT16_MIN; j < INT16_MAX; j++) {
+		uint32_t map_val =  map_to_pos(j, 16) & 0xFFFF;
+		result = re_map_to_pos(map_val);
+		TEST_ASSERT_EQUAL_INT32(j, result);
+	}
+#if 0
+	for (j = INT32_MIN; j < INT32_MAX; j++) {
+		result = re_map_to_pos(map_to_pos(j, 32));
+		TEST_ASSERT_EQUAL_INT32(j, result);
+	}
+#endif
+}
+
+
+void test_decode_normal(void)
+{
+	uint32_t decoded_value;
+	int stream_pos, sample;
+	 /* compressed data from 0 to 6; */
+	uint32_t cmp_data[] = {0x5BBDF7E0};
+	struct decoder_setup setup = {0};
+
+	cpu_to_be32s(cmp_data);
+
+	setup.decode_cw_f = rice_decoder;
+	setup.encoder_par1 = 1;
+	setup.encoder_par2 = ilog_2(setup.encoder_par1);
+	setup.bitstream_adr = cmp_data;
+	setup.max_stream_len = 32;
+	setup.max_cw_len = 16;
+
+	stream_pos = 0;
+	for (sample = 0; sample < 7; sample++) {
+		stream_pos = decode_normal(&decoded_value, stream_pos, &setup);
+		TEST_ASSERT_EQUAL_HEX(sample, decoded_value);
+	}
+
+	 /* TODO error case: negativ stream_pos */
+}
+
+
+void test_decode_zero(void)
+{
+	uint32_t decoded_value;
+	int stream_pos;
+	uint32_t cmp_data[] = {0x88449FE0};
+	struct decoder_setup setup = {0};
+	struct cmp_cfg cfg = {0};
+
+	cpu_to_be32s(cmp_data);
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.icu_output_buf = cmp_data;
+	cfg.buffer_length = 4;
+
+	int err = configure_decoder_setup(&setup, 1, 8, CMP_LOSSLESS, 16, &cfg);
+	TEST_ASSERT_FALSE(err);
+
+	stream_pos = 0;
+
+	stream_pos = decode_zero(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0, decoded_value);
+	stream_pos = decode_zero(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value);
+	stream_pos = decode_zero(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(7, decoded_value);
+	TEST_ASSERT_EQUAL_INT(28, stream_pos);
+
+	 /* TODO error case: negativ stream_pos */
+}
+
+void test_decode_multi(void)
+{
+	uint32_t decoded_value;
+	int stream_pos;
+	uint32_t cmp_data[] = {0x16B66DF8, 0x84360000};
+	struct decoder_setup setup = {0};
+	struct cmp_cfg cfg = {0};
+
+	cpu_to_be32s(&cmp_data[0]);
+	cpu_to_be32s(&cmp_data[1]);
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_MULTI;
+	cfg.icu_output_buf = cmp_data;
+	cfg.buffer_length = 8;
+
+	int err = configure_decoder_setup(&setup, 3, 8, CMP_LOSSLESS, 16, &cfg);
+	TEST_ASSERT_FALSE(err);
+
+	stream_pos = 0;
+
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(1, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(7, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(8, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(9, decoded_value);
+	stream_pos = decode_multi(&decoded_value, stream_pos, &setup);
+	TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value);
+	TEST_ASSERT_EQUAL_INT(47, stream_pos);
+
+}
+
+
+void test_decompress_imagette_model(void)
+{
+	uint16_t data[5]  = {0};
+	uint16_t model[5] = {0, 1, 2, 3, 4};
+	uint16_t up_model[5]  = {0};
+	uint32_t cmp_data[] = {0};
+	struct cmp_cfg cfg = {0};
+	int stream_pos;
+
+	cmp_data[0] = cpu_to_be32(0x49240000);
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.input_buf = data;
+	cfg.model_buf = model;
+	cfg.icu_new_model_buf = up_model;
+	cfg.icu_output_buf = cmp_data;
+	cfg.buffer_length = 4;
+	cfg.samples = 5;
+	cfg.model_value = 16;
+	cfg.golomb_par = 4;
+	cfg.spill = 48;
+
+	stream_pos = decompress_imagette(&cfg);
+	TEST_ASSERT_EQUAL_INT(15, stream_pos);
+	TEST_ASSERT_EQUAL_HEX(1, data[0]);
+	TEST_ASSERT_EQUAL_HEX(2, data[1]);
+	TEST_ASSERT_EQUAL_HEX(3, data[2]);
+	TEST_ASSERT_EQUAL_HEX(4, data[3]);
+	TEST_ASSERT_EQUAL_HEX(5, data[4]);
+
+	TEST_ASSERT_EQUAL_HEX(0, up_model[0]);
+	TEST_ASSERT_EQUAL_HEX(1, up_model[1]);
+	TEST_ASSERT_EQUAL_HEX(2, up_model[2]);
+	TEST_ASSERT_EQUAL_HEX(3, up_model[3]);
+	TEST_ASSERT_EQUAL_HEX(4, up_model[4]);
+}
+
+int my_random(unsigned int min, unsigned int max)
+{
+	if (max-min > RAND_MAX)
+		TEST_ASSERT(0);
+	if (min > max)
+		TEST_ASSERT(0);
+	return min + rand() / (RAND_MAX / (max - min + 1) + 1);
+}
+
+/* #include <cmp_io.h> */
+/* void test_imagette_1(void) */
+/* { */
+/* 	size_t i; */
+
+/* 	enum cmp_mode cmp_mode = 1; */
+/* 	uint16_t model_value = 10; */
+/* 	struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, cmp_mode, model_value, CMP_LOSSLESS); */
+/* 	unsigned int samples = 1; */
+/* 	uint16_t data[1] = {0x8000}; */
+/* 	uint16_t model[1] = {0}; */
+/* 	uint16_t up_model[1] = {0}; */
+/* 	uint16_t de_up_model[1] = {0}; */
+/* 	uint32_t compressed_data[1]; */
+
+/* 	size_t s = cmp_cfg_buffers(&cfg, data, samples, model, up_model, */
+/* 			      compressed_data, 2*samples); */
+/* 	TEST_ASSERT(s > 0); */
+
+/* 	uint32_t golomb_par = 9; */
+/* 	uint32_t spill = 44; */
+
+/* 	cfg.spill = spill; */
+/* 	cfg.golomb_par = golomb_par; */
+/* 	/1* print_cfg(&cfg, 0); *1/ */
+/* 	int cmp_size = icu_compress_data(&cfg, NULL); */
+/* 	TEST_ASSERT(cmp_size > 0); */
+
+
+/* 	s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_size); */
+/* 	TEST_ASSERT_TRUE(s); */
+/* 	struct cmp_entity *ent = malloc(s); */
+/* 	TEST_ASSERT_TRUE(ent); */
+/* 	s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_size); */
+/* 	TEST_ASSERT_TRUE(s); */
+/* 	memcpy(cmp_ent_get_data_buf(ent), compressed_data, cmp_bit_to_4byte(cmp_size)); */
+
+/* 	s = decompress_cmp_entiy(ent, model, de_up_model, NULL); */
+/* 	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); */
+/* 	uint16_t *decompressed_data = malloc(s); */
+/* 	TEST_ASSERT_TRUE(decompressed_data); */
+/* 	s = decompress_cmp_entiy(ent, model, de_up_model, decompressed_data); */
+/* 	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); */
+
+/* 	for (i = 0; i < samples; ++i) { */
+/* 		if (data[i] != decompressed_data[i]) */
+/* 			TEST_ASSERT(0); */
+/* 		/1* TEST_ASSERT_EQUAL_HEX16(data[i], decompressed_data[i]); *1/ */
+/* 		/1* TEST_ASSERT_EQUAL_HEX16(up_model[i], de_up_model[i]); *1/ */
+/* 	} */
+
+
+/* 	free(ent); */
+/* 	free(decompressed_data); */
+/* } */
+
+#include <unistd.h>
+#include "cmp_io.h"
+
+void test_imagette_random(void)
+{
+	unsigned int seed = time(NULL) * getpid();
+	size_t i, s, cmp_data_size;
+	int error;
+	struct cmp_cfg cfg;
+	struct cmp_entity *ent;
+
+	enum cmp_mode cmp_mode = my_random(0, 4);
+	enum cmp_data_type data_type = DATA_TYPE_IMAGETTE;
+	uint16_t model_value = my_random(0, MAX_MODEL_VALUE);
+	uint32_t round = my_random(0, 3);
+	uint32_t samples, compressed_data_len_samples;
+	uint16_t *data, *model = NULL, *up_model = NULL, *de_up_model = NULL;
+
+	/* Seeds the pseudo-random number generator used by rand() */
+	srand(seed);
+	printf("seed: %u\n", seed);
+
+	/* create random test _data */
+	samples = my_random(1, 100000);
+	s = cmp_cal_size_of_data(samples, data_type);
+	data = malloc(s); TEST_ASSERT_TRUE(data);
+	for (i = 0; i < samples; ++i) {
+		data[i] = my_random(0, UINT16_MAX);
+	}
+	if (model_mode_is_used(cmp_mode)) {
+		model = malloc(s); TEST_ASSERT_TRUE(model);
+		up_model = malloc(s); TEST_ASSERT_TRUE(up_model);
+		de_up_model = malloc(s); TEST_ASSERT(de_up_model);
+		for (i = 0; i < samples; ++i) {
+			model[i] = my_random(0, UINT16_MAX);
+		}
+	}
+	compressed_data_len_samples = 6*samples;
+
+	/* create a compression configuration */
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, round);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKOWN);
+
+
+	cmp_data_size = cmp_cfg_icu_buffers(&cfg, data, samples, model, up_model,
+					    NULL, compressed_data_len_samples);
+	TEST_ASSERT_TRUE(cmp_data_size);
+
+	uint32_t golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+	uint32_t max_spill = get_max_spill(golomb_par, data_type);
+	TEST_ASSERT(max_spill > 1);
+	uint32_t spill = my_random(2, max_spill);
+
+	error = cmp_cfg_icu_imagette(&cfg, golomb_par, spill);
+	TEST_ASSERT_FALSE(error);
+
+	print_cfg(&cfg, 0);
+	s = icu_compress_data_entity(NULL, &cfg);
+	TEST_ASSERT_TRUE(s);
+	ent = malloc(s); TEST_ASSERT_TRUE(ent);
+	s = icu_compress_data_entity(ent, &cfg);
+	TEST_ASSERT_TRUE(s);
+
+	s = decompress_cmp_entiy(ent, model, de_up_model, NULL);
+	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s);
+	uint16_t *decompressed_data = malloc(s);
+	TEST_ASSERT_TRUE(decompressed_data);
+	s = decompress_cmp_entiy(ent, model, de_up_model, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s);
+
+	for (i = 0; i < samples; ++i) {
+		printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round);
+		uint32_t mask = ~0U << round;
+		if ((data[i]&mask) != (decompressed_data[i]&mask))
+			TEST_ASSERT(0);
+		if (model_mode_is_used(cmp_mode))
+			if (up_model[i] != de_up_model[i])
+				TEST_ASSERT(0);
+	}
+
+	free(data);
+	free(model);
+	free(up_model);
+	free(de_up_model);
+	free(ent);
+	free(decompressed_data);
+}
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
index 9804d41..aac8b0b 100755
--- a/test/cmp_tool/cmp_tool_integration_test.py
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -14,6 +14,7 @@ PATH_CMP_TOOL = "./cmp_tool"
 EXIT_FAILURE = 1
 EXIT_SUCCESS = 0
 
+DATA_TYPE_IMAGETTE  = 1
 
 GENERIC_HEADER_SIZE = 32
 IMAGETTE_HEADER_SIZE = GENERIC_HEADER_SIZE+4
@@ -409,14 +410,13 @@ def test_compression_diff():
                     assert(info['cmp_size'] == '20')
                     assert(info['cmp_err'] == '0')
                 else:
-                    # import pdb; pdb.set_trace()
                     header = read_in_cmp_header(f.read())
                     assert(header['asw_version_id']['value'] == VERSION)
                     assert(header['cmp_ent_size']['value'] == IMAGETTE_HEADER_SIZE+4)
                     assert(header['original_size']['value'] == 10)
                     # todo
                     assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow()))
-                    #todo
+                    # todo
                     assert(header['end_timestamp']['value'] < cuc_timestamp(datetime.utcnow()))
                     assert(header['data_type']['value'] == 1)
                     assert(header['cmp_mode_used']['value'] == 2)
@@ -428,7 +428,7 @@ def test_compression_diff():
                     assert(header['golomb_par_used']['value'] == 7)
                     assert(header['compressed_data']['value'] == "44444000")
 
-                # decompression
+            # decompression
             if add_arg == " --no_header":
                 returncode, stdout, stderr = call_cmp_tool(
                     " -i "+output_prefix+".info -d "+output_prefix+".cmp -o "+output_prefix)
@@ -441,8 +441,8 @@ def test_compression_diff():
                    "%s" % ((lambda arg : "Importing decompression information file %s.info ... DONE\n" % (output_prefix)
                             if "--no_header" in arg else "")(add_arg)) +
                    "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix) +
-                   "%s" % ((lambda arg : "Parse the compression entity header ... DONE\n"
-                            if not "--no_header" in arg else "")(add_arg)) +
+                   # "%s" % ((lambda arg : "Parse the compression entity header ... DONE\n"
+                   #          if not "--no_header" in arg else "")(add_arg)) +
                    "Decompress data ... DONE\n" +
                    "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix))
 
@@ -459,7 +459,7 @@ def test_compression_diff():
         del_file(output_prefix+'.dat')
 
 
-def test_model_compression_no_header():
+def test_model_compression():
     # generate test data
     data = '00 01 00 02 00 03 00 04 00 05 \n'
     model = '00 00 00 01 00 02 00 03 00 04 \n'
@@ -481,62 +481,93 @@ def test_model_compression_no_header():
             assert(stderr == "")
             cfg = parse_key_value(stdout)
             cfg['cmp_mode'] = 'MODE_MODEL_MULTI'
+            cfg['model_value'] = '16'
             cfg["samples"] = '5'
             cfg["buffer_length"] = '2'
             for key, value in cfg.items():
                 f.write(key + ' = ' + str(value) + '\n')
 
-        # compression
-        returncode, stdout, stderr = call_cmp_tool(
-            " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix1+" --no_header")
+        add_args = [" --no_header", ""]
+        for add_arg in add_args:
+            print("Remove this", add_arg)
+            # compression
+            returncode, stdout, stderr = call_cmp_tool(
+                " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix1+ add_arg)
 
-        # check compression results
-        assert(returncode == EXIT_SUCCESS)
-        assert(stderr == "")
-        assert(stdout == CMP_START_STR_CMP +
-               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
-               "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Importing model file %s ... DONE\n" % (model_file_name) +
-               "Compress data ... DONE\n" +
-               "Write compressed data to file %s.cmp ... DONE\n" % (output_prefix1) +
-               "Write decompression information to file %s.info ... DONE\n" % (output_prefix1) +
-               "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix1))
-        # check compressed data
-        with open(output_prefix1+".cmp", encoding='utf-8') as f:
-            assert(f.read() == "49 24 00 00 \n")
-        # check info file
-        with open(output_prefix1+".info", encoding='utf-8') as f:
-            info = parse_key_value(f.read())
-        assert(info['cmp_mode_used'] == '3')
-        assert(info['model_value_used'] == cfg['model_value'])
-        assert(info['round_used'] == cfg['round'])
-        assert(info['spill_used'] == cfg['spill'])
-        assert(info['golomb_par_used'] == cfg['golomb_par'])
-        assert(info['samples_used'] == cfg['samples'])
-        assert(info['cmp_size'] == '15')
-        assert(info['cmp_err'] == '0')
-
-        # decompression
-        returncode, stdout, stderr = call_cmp_tool(
-            " -i "+output_prefix1+".info -d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
-        assert(returncode == EXIT_SUCCESS)
-        assert(stdout == CMP_START_STR_DECMP +
-               "Importing decompression information file %s.info ... DONE\n" % (output_prefix1) +
-               "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix1) +
-               "Importing model file %s ... DONE\n" % (model_file_name) +
-               "Decompress data ... DONE\n" +
-               "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix2) +
-               "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix2))
-        assert(stderr == "")
-        # check compressed data
+            # check compression results
+            assert(stderr == "")
+            assert(stdout == CMP_START_STR_CMP +
+                   "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+                   "Importing data file %s ... DONE\n" % (data_file_name) +
+                   "Importing model file %s ... DONE\n" % (model_file_name) +
+                   "Compress data ... DONE\n" +
+                   "Write compressed data to file %s.cmp ... DONE\n" % (output_prefix1) +
+                   "%s" % ((lambda arg : "Write decompression information to file %s.info ... DONE\n" % (output_prefix1)
+                            if arg == " --no_header" else "")(add_arg)) +
+                   "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix1)
+            )
+            assert(returncode == EXIT_SUCCESS)
+
+            if add_arg == " --no_header":
+                # check compressed data
+                with open(output_prefix1+".cmp", encoding='utf-8') as f:
+                    assert(f.read() == "49 24 00 00 \n")
+                # check info file
+                with open(output_prefix1+".info", encoding='utf-8') as f:
+                    info = parse_key_value(f.read())
+                assert(info['cmp_mode_used'] == '3')
+                assert(info['model_value_used'] == cfg['model_value'])
+                assert(info['round_used'] == cfg['round'])
+                assert(info['spill_used'] == cfg['spill'])
+                assert(info['golomb_par_used'] == cfg['golomb_par'])
+                assert(info['samples_used'] == cfg['samples'])
+                assert(info['cmp_size'] == '15')
+                assert(info['cmp_err'] == '0')
+            else:
+                with open(output_prefix1+".cmp", encoding='utf-8') as f:
+                    header = read_in_cmp_header(f.read())
+                assert(header['asw_version_id']['value'] == VERSION)
+                assert(header['cmp_ent_size']['value'] == IMAGETTE_HEADER_SIZE+4)
+                assert(header['original_size']['value'] == 10)
+                # todo
+                assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow()))
+                #todo
+                assert(header['end_timestamp']['value'] < cuc_timestamp(datetime.utcnow()))
+                assert(header['data_type']['value'] == DATA_TYPE_IMAGETTE)
+                assert(header['cmp_mode_used']['value'] == 3)
+                assert(header['model_value_used']['value'] == int(cfg['model_value']))
+                assert(header['model_id']['value'] == 53264)
+                assert(header['model_counter']['value'] == 1)
+                assert(header['lossy_cmp_par_used']['value'] == int(cfg['round']))
+                assert(header['spill_used']['value'] == int(cfg['spill']))
+                assert(header['golomb_par_used']['value'] == int(cfg['golomb_par']))
+                assert(header['compressed_data']['value'] == "49240000")
+
+            # decompression
+            if add_arg == " --no_header":
+                returncode, stdout, stderr = call_cmp_tool(
+                    " -i "+output_prefix1+".info -d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
+            else:
+                returncode, stdout, stderr = call_cmp_tool("-d "+output_prefix1+".cmp -m "+model_file_name+" -o "+output_prefix2)
+            assert(stderr == "")
+            assert(stdout == CMP_START_STR_DECMP +
+                   "%s" % ((lambda arg : "Importing decompression information file %s.info ... DONE\n" % (output_prefix1)
+                            if "--no_header" in arg else "")(add_arg)) +
+                   "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix1) +
+                   "Importing model file %s ... DONE\n" % (model_file_name) +
+                   "Decompress data ... DONE\n" +
+                   "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix2) +
+                   "Write updated model to file %s_upmodel.dat ... DONE\n" % (output_prefix2))
+            assert(returncode == EXIT_SUCCESS)
+            # check compressed data
 
-        with open(output_prefix2+".dat", encoding='utf-8') as f:
-            assert(f.read() == data)
+            with open(output_prefix2+".dat", encoding='utf-8') as f:
+                assert(f.read() == data)
 
-        with open(output_prefix1+"_upmodel.dat", encoding='utf-8') as f1:
-            with open(output_prefix2+"_upmodel.dat", encoding='utf-8') as f2:
-                assert(f1.read() == f2.read() ==
-                       '00 00 00 01 00 02 00 03 00 04 \n')
+            with open(output_prefix1+"_upmodel.dat", encoding='utf-8') as f1:
+                with open(output_prefix2+"_upmodel.dat", encoding='utf-8') as f2:
+                    assert(f1.read() == f2.read() ==
+                           '00 00 00 01 00 02 00 03 00 04 \n')
     # clean up
     finally:
         del_file(data_file_name)
@@ -582,7 +613,7 @@ def test_raw_mode_compression():
             with open(output_prefix+".cmp", encoding='utf-8') as f:
                 if "--no_header" in arg:
                     # check compressed data file
-                    assert(f.read() == data[:-1]+"00 00 \n")
+                    assert(f.read() == data)#[:-1]+"00 00 \n")
                     # check info file
                     with open(output_prefix+".info", encoding='utf-8') as f:
                         info = parse_key_value(f.read())
@@ -627,8 +658,6 @@ def test_raw_mode_compression():
                    "%s" % ((lambda arg : "Importing decompression information file %s.info ... DONE\n" % (output_prefix)
                             if "--no_header" in arg else "")(arg)) +
                    "Importing compressed data file %s.cmp ... DONE\n" % (output_prefix) +
-                   "%s" % ((lambda arg : "Parse the compression entity header ... DONE\n"
-                            if not "--no_header" in arg else "")(arg)) +
                    "Decompress data ... DONE\n" +
                    "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix))
             assert(returncode == EXIT_SUCCESS)
@@ -979,11 +1008,9 @@ def test_sample_used_is_to_big():
             else:
                 assert(stdout == CMP_START_STR_DECMP +
                        "Importing compressed data file %s ... DONE\n" % (cmp_file_name) +
-                       "Parse the compression entity header ... DONE\n" +
                        "Decompress data ... FAILED\n")
 
-            assert(stderr == "Error: Buffer overflow detected.\n" +
-                   "Error: Compressed values could not be decoded.\n")
+            assert(stderr == "Error: Buffer overflow detected.\n")
 
             assert(returncode == EXIT_FAILURE)
     finally:
@@ -1009,6 +1036,7 @@ def test_header_wrong_formatted():
     finally:
         del_file(cmp_file_name)
 
+
 def test_header_read_in():
     cmp_file_name = 'test_header_read_in.cmp'
 
@@ -1081,7 +1109,7 @@ def test_header_read_in():
         assert(returncode == EXIT_FAILURE)
         assert(stdout == CMP_START_STR_DECMP +
                "Importing compressed data file %s ... DONE\n" % (cmp_file_name) +
-               "Parse the compression entity header ... FAILED\n" )
+               "Decompress data ... FAILED\n" )
         assert(stderr == "Error: Compression mode not supported.\n")
 
     finally:
@@ -1106,25 +1134,27 @@ def test_model_fiel_erros():
             f.write(cfg)
 
         # no -m option in model mode
-        returncode, stdout, stderr = call_cmp_tool(
-            " -c "+cfg_file_name+" -d "+data_file_name + " -o "+output_prefix+" --no_header")
-        assert(returncode == EXIT_FAILURE)
-        assert(stdout == CMP_START_STR_CMP +
-               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
-               "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Importing model file  ... FAILED\n" )
-        assert(stderr == "cmp_tool: No model file (-m option) specified.\n")
+        add_args = [" --no_header", ""]
+        for add_arg in add_args:
+            returncode, stdout, stderr = call_cmp_tool(
+                " -c "+cfg_file_name+" -d "+data_file_name + " -o "+output_prefix+add_arg)
+            assert(returncode == EXIT_FAILURE)
+            assert(stdout == CMP_START_STR_CMP +
+                   "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+                   "Importing data file %s ... DONE\n" % (data_file_name) +
+                   "Importing model file  ... FAILED\n" )
+            assert(stderr == "cmp_tool: No model file (-m option) specified.\n")
 
-        # model file to small
-        with open(model_file_name, 'w', encoding='utf-8') as f:
-            f.write(model)
-        returncode, stdout, stderr = call_cmp_tool(
-            " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix)
-        assert(returncode == EXIT_FAILURE)
-        assert(stdout == CMP_START_STR_CMP +
-               "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
-               "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Importing model file %s ... FAILED\n" % (model_file_name) )
+            # model file to small
+            with open(model_file_name, 'w', encoding='utf-8') as f:
+                f.write(model)
+            returncode, stdout, stderr = call_cmp_tool(
+                " -c "+cfg_file_name+" -d "+data_file_name + " -m "+model_file_name+" -o "+output_prefix)
+            assert(returncode == EXIT_FAILURE)
+            assert(stdout == CMP_START_STR_CMP +
+                   "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
+                   "Importing data file %s ... DONE\n" % (data_file_name) +
+                   "Importing model file %s ... FAILED\n" % (model_file_name) )
         assert(stderr == "cmp_tool: %s: Error: The files do not contain enough data as requested.\n" % (model_file_name))
 
         # updated model can not write
diff --git a/test/meson.build b/test/meson.build
index b843e00..4743653 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -34,10 +34,6 @@ subdir('tools')
 
 subdir('cmp_tool')
 
-cunit_dep = dependency('cunit', required : false)
-
 unity_dep = dependency('unity', fallback : ['unity', 'unity_dep'])
-# unity_proj = subproject('unity')
-# unity_dep = unity_proj.get_variable('unity_dep')
 
 subdir('cmp_icu')
-- 
GitLab


From b2e77e60a76c5a24b932f540881043929d3e475d Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 31 May 2022 15:32:34 +0200
Subject: [PATCH 21/46] bug fixing

---
 include/cmp_data_types.h | 2 +-
 lib/cmp_rdcu.c           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 75b69be..02bb840 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -270,7 +270,7 @@ size_t size_of_a_sample(enum cmp_data_type data_type);
 unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type);
 int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type);
 
-int cmp_input_big_to_cpu_endianness(void *data, u_int32_t data_size_byte,
+int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
 				    enum cmp_data_type data_type);
 
 #endif /* CMP_DATA_TYPE_H */
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index 34606f4..2a8f214 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -141,7 +141,7 @@ static int rdcu_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg)
  *	on error the data_type record is set to DATA_TYPE_UNKOWN
  */
 
-struct cmp_cfg rdcu_cfg_create(enum cmp_ent_data_type data_type, enum cmp_mode cmp_mode,
+struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
 			       uint32_t model_value, uint32_t lossy_par)
 {
 	struct cmp_cfg cfg = {0};
-- 
GitLab


From 59ee1a0c21f212fab55517f397be1f47ba721dfe Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Wed, 8 Jun 2022 15:34:32 +0200
Subject: [PATCH 22/46] Incorporate the update from the ICU integration

---
 include/cmp_data_types.h    |  9 +++-
 include/cmp_entity.h        | 10 +++--
 include/cmp_guess.h         |  3 +-
 include/cmp_icu.h           |  2 +-
 include/cmp_io.h            |  4 +-
 include/cmp_rdcu.h          |  2 +-
 include/cmp_rdcu_extended.h |  2 +-
 include/cmp_support.h       |  2 +-
 include/decmp.h             |  8 +---
 include/rdcu_ctrl.h         |  9 ++--
 include/rdcu_pkt_to_file.h  |  2 +-
 include/rmap.h              |  9 ++--
 lib/cmp_data_types.c        |  6 +--
 lib/cmp_entity.c            | 10 ++---
 lib/cmp_guess.c             |  1 +
 lib/cmp_icu.c               | 14 ++++---
 lib/cmp_io.c                | 13 +++---
 lib/cmp_rdcu.c              | 24 ++++++-----
 lib/cmp_support.c           | 10 +++--
 lib/rdcu_ctrl.c             | 83 ++++++++++++++++++++++++++++++-------
 lib/rdcu_pkt_to_file.c      | 12 +++---
 lib/rdcu_rmap.c             | 34 ++++++---------
 lib/rmap.c                  | 13 +++---
 23 files changed, 168 insertions(+), 114 deletions(-)

diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 02bb840..9c8a470 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -36,8 +36,8 @@
 
 #include <stdint.h>
 
-#include "compiler.h"
-#include "cmp_support.h"
+#include <compiler.h>
+#include <cmp_support.h>
 
 #define MAX_USED_NC_IMAGETTE_BITS		16
 #define MAX_USED_SATURATED_IMAGETTE_BITS	16 /* TBC */
@@ -135,6 +135,7 @@ extern struct cmp_max_used_bits max_used_bits;
 #define MULTI_ENTRY_HDR_SIZE 12
 compile_time_assert(MULTI_ENTRY_HDR_SIZE % sizeof(uint32_t) == 0, N_DPU_ICU_MULTI_ENTRY_HDR_NOT_4_BYTE_ALLIED);
 
+__extension__
 struct multi_entry_hdr {
 	uint32_t timestamp_coarse;
 	uint16_t timestamp_fine;
@@ -206,6 +207,7 @@ struct f_fx_efx_ncob_ecob {
 } __attribute__((packed));
 
 
+__extension__
 struct l_fx {
 	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
 	uint32_t fx;
@@ -213,6 +215,7 @@ struct l_fx {
 } __attribute__((packed));
 
 
+__extension__
 struct l_fx_efx {
 	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
 	uint32_t fx;
@@ -221,6 +224,7 @@ struct l_fx_efx {
 } __attribute__((packed));
 
 
+__extension__
 struct l_fx_ncob {
 	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
 	uint32_t fx;
@@ -232,6 +236,7 @@ struct l_fx_ncob {
 } __attribute__((packed));
 
 
+__extension__
 struct l_fx_efx_ncob_ecob {
 	uint32_t exp_flags:24; /* selected exposure flags (24 flags) */
 	uint32_t fx;
diff --git a/include/cmp_entity.h b/include/cmp_entity.h
index a06715f..0c9a606 100644
--- a/include/cmp_entity.h
+++ b/include/cmp_entity.h
@@ -29,8 +29,8 @@
 
 #include <stdint.h>
 
-#include "compiler.h"
-#include "cmp_support.h"
+#include <compiler.h>
+#include <cmp_support.h>
 
 
 #define GENERIC_HEADER_SIZE 32
@@ -285,11 +285,13 @@ ssize_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf,
 uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode);
 
 
-#if __has_include(<time.h>)
-#include <time.h>
+#if defined __has_include
+#  if __has_include(<time.h>)
+#    include <time.h>
 /* create a timestamp for the compression header */
 extern const struct tm EPOCH_DATE;
 uint64_t cmp_ent_create_timestamp(const struct timespec *ts);
+#  endif
 #endif
 
 /* print and parse functions */
diff --git a/include/cmp_guess.h b/include/cmp_guess.h
index 9d3ac42..4b26e9c 100644
--- a/include/cmp_guess.h
+++ b/include/cmp_guess.h
@@ -20,8 +20,7 @@
 #ifndef CMP_GUESS_H
 #define CMP_GUESS_H
 
-#include "cmp_support.h"
-
+#include <cmp_support.h>
 
 
 #define DEFAULT_GUESS_LEVEL 2
diff --git a/include/cmp_icu.h b/include/cmp_icu.h
index 81a1160..01e528c 100644
--- a/include/cmp_icu.h
+++ b/include/cmp_icu.h
@@ -20,7 +20,7 @@
 #ifndef _CMP_ICU_H_
 #define _CMP_ICU_H_
 
-#include "cmp_support.h"
+#include <cmp_support.h>
 
 
 /* return code if the bitstream buffer is too small to store the whole bitstream */
diff --git a/include/cmp_io.h b/include/cmp_io.h
index f807825..6de2222 100644
--- a/include/cmp_io.h
+++ b/include/cmp_io.h
@@ -17,8 +17,8 @@
 
 #include <string.h>
 
-#include "cmp_support.h"
-#include "cmp_entity.h"
+#include <cmp_support.h>
+#include <cmp_entity.h>
 
 #define MAX_CONFIG_LINE 256
 
diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h
index 14e0af9..6273549 100644
--- a/include/cmp_rdcu.h
+++ b/include/cmp_rdcu.h
@@ -21,7 +21,7 @@
 #ifndef _CMP_RDCU_H_
 #define _CMP_RDCU_H_
 
-#include "cmp_support.h"
+#include <cmp_support.h>
 
 
 /* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */
diff --git a/include/cmp_rdcu_extended.h b/include/cmp_rdcu_extended.h
index a4f33e0..7ab229b 100644
--- a/include/cmp_rdcu_extended.h
+++ b/include/cmp_rdcu_extended.h
@@ -18,7 +18,7 @@
 #ifndef _CMP_RDCU_EXTENDED_H_
 #define _CMP_RDCU_EXTENDED_H_
 
-#include "../include/cmp_rdcu.h"
+#include <cmp_rdcu.h>
 
 int rdcu_start_compression(void);
 
diff --git a/include/cmp_support.h b/include/cmp_support.h
index 850f0a7..f5e0b38 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -109,7 +109,7 @@ enum cmp_data_type {
 	DATA_TYPE_F_CAM_IMAGETTE,
 	DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE,
 	DATA_TYPE_F_CAM_OFFSET,
-	DATA_TYPE_F_CAM_BACKGROUND,
+	DATA_TYPE_F_CAM_BACKGROUND
 };
 
 
diff --git a/include/decmp.h b/include/decmp.h
index 2f8478c..4046798 100644
--- a/include/decmp.h
+++ b/include/decmp.h
@@ -19,10 +19,8 @@
 #ifndef DECMP_H_
 #define DECMP_H_
 
-#include "cmp_entity.h"
-#include "cmp_support.h"
-
-void *malloc_decompressed_data(const struct cmp_info *info);
+#include <cmp_entity.h>
+#include <cmp_support.h>
 
 int decompress_data(uint32_t *compressed_data, void *de_model_buf,
 		    const struct cmp_info *info, void *decompressed_data);
@@ -30,6 +28,4 @@ int decompress_data(uint32_t *compressed_data, void *de_model_buf,
 int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
 			 void *up_model_buf, void *decompressed_data);
 
-double get_compression_ratio(const struct cmp_info *info);
-
 #endif /* DECMP_H_ */
diff --git a/include/rdcu_ctrl.h b/include/rdcu_ctrl.h
index ec5b9a2..ac3f03f 100644
--- a/include/rdcu_ctrl.h
+++ b/include/rdcu_ctrl.h
@@ -245,11 +245,14 @@ uint32_t rdcu_get_golomb_param(void);
 
 uint32_t rdcu_get_compr_data_start_addr(void);
 
-uint32_t rdcu_get_compr_data_size(void);
+uint32_t rdcu_get_compr_data_size_bit(void);
+uint32_t rdcu_get_compr_data_size_byte(void);
 
-uint32_t rdcu_get_compr_data_adaptive_1_size(void);
+uint32_t rdcu_get_compr_data_adaptive_1_size_bit(void);
+uint32_t rdcu_get_compr_data_adaptive_1_size_byte(void);
 
-uint32_t rdcu_get_compr_data_adaptive_2_size(void);
+uint32_t rdcu_get_compr_data_adaptive_2_size_bit(void);
+uint32_t rdcu_get_compr_data_adaptive_2_size_byte(void);
 
 uint16_t rdcu_get_compr_error(void);
 
diff --git a/include/rdcu_pkt_to_file.h b/include/rdcu_pkt_to_file.h
index 87c3d4b..1c350c8 100644
--- a/include/rdcu_pkt_to_file.h
+++ b/include/rdcu_pkt_to_file.h
@@ -18,7 +18,7 @@
 #ifndef _RDCU_PKT_TO_FILE_H_
 #define _RDCU_PKT_TO_FILE_H_
 
-#include "cmp_support.h"
+#include <cmp_support.h>
 
 /* directory where the tc files are stored, when --rdcu_pkt option is set */
 #define TC_DIR "TC_FILES"
diff --git a/include/rmap.h b/include/rmap.h
index 5156679..c581575 100644
--- a/include/rmap.h
+++ b/include/rmap.h
@@ -20,6 +20,7 @@
 #define RMAP_H
 
 #include <stdint.h>
+#include <compiler.h>
 
 /**
  * valid RMAP command codes, see Table 5-1 of ECSS‐E‐ST‐50‐52C
@@ -149,11 +150,9 @@ struct rmap_instruction {
 #else
 #error "Unknown byte order"
 #endif
-}__attribute__((packed));
-#if 0
-compile_time_assert((sizeof(struct rmap_instruction) == sizeof(uint8_t),
-		    RMAP_INSTRUCTION_STRUCT_WRONG_SIZE));
-#endif
+} __attribute__((packed));
+
+compile_time_assert(sizeof(struct rmap_instruction) == sizeof(uint8_t), RMAP_INSTRUCTION_STRUCT_WRONG_SIZE);
 
 
 /**
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 749964d..8dd5792 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -17,9 +17,9 @@
  */
 
 
-#include "cmp_data_types.h"
-#include "cmp_debug.h"
-#include "byteorder.h"
+#include <cmp_data_types.h>
+#include <cmp_debug.h>
+#include <byteorder.h>
 
 
 /* the maximum length of the different data products types in bits */
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index d058b17..0296894 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -30,11 +30,11 @@
 #  endif
 #endif
 
-#include "byteorder.h"
-#include "cmp_debug.h"
-#include "cmp_support.h"
-#include "cmp_data_types.h"
-#include "cmp_entity.h"
+#include <byteorder.h>
+#include <cmp_debug.h>
+#include <cmp_support.h>
+#include <cmp_data_types.h>
+#include <cmp_entity.h>
 
 
 #ifdef HAS_TIME_H
diff --git a/lib/cmp_guess.c b/lib/cmp_guess.c
index c173814..3107aaf 100644
--- a/lib/cmp_guess.c
+++ b/lib/cmp_guess.c
@@ -15,6 +15,7 @@
  *
  * @brief helps the user to find a good compression parameters for a given
  *	dataset
+ * @warning this part of the software is not intended to run on-board on the ICU.
  */
 
 #include <limits.h>
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 057ee64..2d11006 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -32,11 +32,11 @@
 #include <string.h>
 #include <limits.h>
 
-#include "byteorder.h"
-#include "cmp_debug.h"
-#include "cmp_data_types.h"
-#include "cmp_support.h"
-#include "cmp_icu.h"
+#include <byteorder.h>
+#include <cmp_debug.h>
+#include <cmp_data_types.h>
+#include <cmp_support.h>
+#include <cmp_icu.h>
 
 
 /* pointer to a code word generation function */
@@ -75,7 +75,9 @@ struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cm
 				  uint32_t model_value, uint32_t lossy_par)
 {
 	int cfg_valid;
-	struct cmp_cfg cfg = {0};
+	struct cmp_cfg cfg;
+
+	memset(&cfg, 0, sizeof(cfg));
 
 	cfg.data_type = data_type;
 	cfg.cmp_mode = cmp_mode;
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 99e80c6..0e74c0d 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -15,6 +15,7 @@
  * more details.
  *
  * @brief compression tool Input/Output library
+ * @warning this part of the software is not intended to run on-board on the ICU.
  */
 
 #include <stdio.h>
@@ -24,12 +25,12 @@
 #include <ctype.h>
 #include <sys/stat.h>
 
-#include "cmp_tool-config.h"
-#include "cmp_io.h"
-#include "cmp_support.h"
-#include "rdcu_cmd.h"
-#include "byteorder.h"
-#include "cmp_data_types.h"
+#include <cmp_tool-config.h>
+#include <cmp_io.h>
+#include <cmp_support.h>
+#include <rdcu_cmd.h>
+#include <byteorder.h>
+#include <cmp_data_types.h>
 
 
 /* directory to convert from data_type to string */
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index 2a8f214..336fc87 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -28,13 +28,14 @@
 
 #include <stdint.h>
 #include <stdio.h>
+#include <string.h>
 
-#include "rdcu_cmd.h"
-#include "cmp_support.h"
-#include "cmp_data_types.h"
-#include "rdcu_ctrl.h"
-#include "rdcu_rmap.h"
-#include "cmp_debug.h"
+#include <rdcu_cmd.h>
+#include <cmp_debug.h>
+#include <cmp_support.h>
+#include <cmp_data_types.h>
+#include <rdcu_ctrl.h>
+#include <rdcu_rmap.h>
 
 
 #define IMA_SAM2BYT                                                            \
@@ -144,7 +145,9 @@ static int rdcu_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg)
 struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
 			       uint32_t model_value, uint32_t lossy_par)
 {
-	struct cmp_cfg cfg = {0};
+	struct cmp_cfg cfg;
+
+	memset(&cfg, 0, sizeof(cfg));
 
 	cfg.data_type = data_type;
 	cfg.cmp_mode = cmp_mode;
@@ -157,6 +160,7 @@ struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_m
 	return cfg;
 }
 
+
 /**
  * @brief check if a buffer is in inside the RDCU SRAM
  *
@@ -801,9 +805,9 @@ int rdcu_read_cmp_info(struct cmp_info *info)
 		info->rdcu_new_model_adr_used = rdcu_get_new_model_addr_used();
 		info->samples_used = rdcu_get_samples_used();
 		info->rdcu_cmp_adr_used = rdcu_get_compr_data_start_addr();
-		info->cmp_size = rdcu_get_compr_data_size();
-		info->ap1_cmp_size = rdcu_get_compr_data_adaptive_1_size();
-		info->ap2_cmp_size = rdcu_get_compr_data_adaptive_2_size();
+		info->cmp_size = rdcu_get_compr_data_size_bit();
+		info->ap1_cmp_size = rdcu_get_compr_data_adaptive_1_size_bit();
+		info->ap2_cmp_size = rdcu_get_compr_data_adaptive_2_size_bit();
 		info->cmp_err = rdcu_get_compr_error();
 	}
 	return 0;
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index a02e897..666ce96 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -18,8 +18,8 @@
  */
 
 
-#include "cmp_support.h"
-#include "cmp_debug.h"
+#include <cmp_support.h>
+#include <cmp_debug.h>
 
 
 /**
@@ -378,13 +378,15 @@ unsigned int cmp_up_model(unsigned int data, unsigned int model,
 			  unsigned int model_value, unsigned int round)
 
 {
+	uint64_t weighted_model, weighted_data;
+
 	/* round and round back input because for decompression the accurate
 	 * data values are not available
 	 */
 	data = round_inv(round_fwd(data, round), round);
 	/* cast uint64_t to prevent overflow in the multiplication */
-	uint64_t weighted_model = (uint64_t)model * model_value;
-	uint64_t weighted_data = (uint64_t)data * (MAX_MODEL_VALUE - model_value);
+	weighted_model = (uint64_t)model * model_value;
+	weighted_data = (uint64_t)data * (MAX_MODEL_VALUE - model_value);
 	/* truncation is intended */
 	return (unsigned int)((weighted_model + weighted_data) / MAX_MODEL_VALUE);
 }
diff --git a/lib/rdcu_ctrl.c b/lib/rdcu_ctrl.c
index a1e3b0f..6f743c6 100644
--- a/lib/rdcu_ctrl.c
+++ b/lib/rdcu_ctrl.c
@@ -1305,44 +1305,97 @@ uint32_t rdcu_get_compr_data_start_addr(void)
 
 
 /**
- * @brief get compressed data size
+ * @brief get the need bytes for the given bits
+ *
+ * @param cmp_size_bit compressed data size, measured in bits
+ *
+ * @returns the size in bytes to store the compressed data
+ */
+
+static uint32_t rdcu_bit_to_byte(unsigned int cmp_size_bit)
+{
+	return ((cmp_size_bit + 7) / 8);
+}
+
+
+/**
+ * @brief get compressed data size in bits
  * @see RDCU-FRS-FN-0922
  *
  * @returns the compressed data size in bits
  */
 
-uint32_t rdcu_get_compr_data_size(void)
+uint32_t rdcu_get_compr_data_size_bit(void)
 {
 	return rdcu->compr_data_size;
 }
 
 
 /**
- * @brief get compressed data adaptive 1 size
+ * @brief get compressed data size in bytes
+ * @see RDCU-FRS-FN-0922
+ *
+ * @returns the compressed data size in bytes
+ */
+
+uint32_t rdcu_get_compr_data_size_byte(void)
+{
+	return rdcu_bit_to_byte(rdcu_get_compr_data_size_bit());
+}
+
+
+/**
+ * @brief get compressed data adaptive 1 size in bits
  * @see RDCU-FRS-FN-0932
  *
  * @returns the adaptive 1 compressed data size in bits
  */
 
-uint32_t rdcu_get_compr_data_adaptive_1_size(void)
+uint32_t rdcu_get_compr_data_adaptive_1_size_bit(void)
 {
 	return rdcu->compr_data_adaptive_1_size;
 }
 
 
 /**
- * @brief get compressed data adaptive 2 size
+ * @brief get compressed data adaptive 1 size in bytes
+ * @see RDCU-FRS-FN-0932
+ *
+ * @returns the adaptive 1 compressed data size in bytes
+ */
+
+uint32_t rdcu_get_compr_data_adaptive_1_size_byte(void)
+{
+	return rdcu_bit_to_byte(rdcu_get_compr_data_adaptive_1_size_bit());
+}
+
+
+/**
+ * @brief get compressed data adaptive 2 size in bits
  * @see RDCU-FRS-FN-0942
  *
  * @returns the adaptive 2 compressed data size in bits
  */
 
-uint32_t rdcu_get_compr_data_adaptive_2_size(void)
+uint32_t rdcu_get_compr_data_adaptive_2_size_bit(void)
 {
 	return rdcu->compr_data_adaptive_2_size;
 }
 
 
+/**
+ * @brief get compressed data adaptive 2 size in bytes
+ * @see RDCU-FRS-FN-0942
+ *
+ * @returns the adaptive 2 compressed data size in bytes
+ */
+
+uint32_t rdcu_get_compr_data_adaptive_2_size_byte(void)
+{
+	return rdcu_bit_to_byte(rdcu_get_compr_data_adaptive_2_size_bit());
+}
+
+
 /**
  * @brief get compression error code
  * @see RDCU-FRS-FN-0954
@@ -1606,7 +1659,7 @@ int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size)
 	{
 		uint32_t i;
 
-		for (i = 0; i < size/sizeof(uint16_t); i++){
+		for (i = 0; i < size/sizeof(uint16_t); i++) {
 			uint16_t *sram_buf = (uint16_t *)&rdcu->sram[addr];
 
 			sram_buf[i] = cpu_to_be16(buf[i]);
@@ -1652,9 +1705,9 @@ int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size)
 	{
 		uint32_t i;
 
-	for (i = 0; i < size/sizeof(uint32_t); i++){
-		uint32_t *sram_buf = (uint32_t *)&rdcu->sram[addr];
-	
+		for (i = 0; i < size/sizeof(uint32_t); i++) {
+			uint32_t *sram_buf = (uint32_t *)&rdcu->sram[addr];
+
 			sram_buf[i] = cpu_to_be32(buf[i]);
 		}
 	}
@@ -2466,14 +2519,12 @@ int rdcu_sync_sram_mirror_parallel(uint32_t rx_addr, uint32_t rx_size,
 
 int rdcu_ctrl_init(void)
 {
-	rdcu = (struct rdcu_mirror *) malloc(sizeof(struct rdcu_mirror));
-	if (!rdcu){
+	rdcu = (struct rdcu_mirror *) calloc(1, sizeof(struct rdcu_mirror));
+	if (!rdcu) {
 		printf("Error allocating memory for the RDCU mirror\n");
 		return -1;
 	}
 
-	memset(rdcu, 0, sizeof(struct rdcu_mirror));
-
 #if (__sparc__)
 	rdcu->sram =  (uint8_t *) 0x60000000;
 #else /* assume PC */
@@ -2485,7 +2536,7 @@ int rdcu_ctrl_init(void)
 	}
 #endif
 
-	memset(rdcu->sram, 0, RDCU_SRAM_SIZE);
-	
+	memset(rdcu->sram, 0, RDCU_SRAM_SIZE);  /* clear sram buffer */
+
 	return 0;
 }
diff --git a/lib/rdcu_pkt_to_file.c b/lib/rdcu_pkt_to_file.c
index 0c71c8e..ed10778 100644
--- a/lib/rdcu_pkt_to_file.c
+++ b/lib/rdcu_pkt_to_file.c
@@ -17,7 +17,7 @@
  *
  * This library provided a rmap_rx and rmap_tx function for the rdcu_rmap
  * library to write generated packets into text files.
- *
+ * @warning this part of the software is not intended to run on-board on the ICU.
  */
 
 #include <stdint.h>
@@ -28,11 +28,11 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#include "rdcu_pkt_to_file.h"
-#include "cmp_rdcu_extended.h"
-#include "rdcu_rmap.h"
-#include "rdcu_ctrl.h"
-#include "rdcu_cmd.h"
+#include <rdcu_pkt_to_file.h>
+#include <cmp_rdcu_extended.h>
+#include <rdcu_rmap.h>
+#include <rdcu_ctrl.h>
+#include <rdcu_cmd.h>
 
 /* Name of directory were the RMAP packages are stored */
 static char tc_folder_dir[MAX_TC_FOLDER_DIR_LEN] = "TC_FILES";
diff --git a/lib/rdcu_rmap.c b/lib/rdcu_rmap.c
index f6035cb..b314b47 100644
--- a/lib/rdcu_rmap.c
+++ b/lib/rdcu_rmap.c
@@ -70,7 +70,7 @@
 #include <rmap.h>
 #include <rdcu_rmap.h>
 
-
+#define RDCU_CONFIG_DEBUG 0
 
 static uint8_t rdcu_addr;
 static uint8_t icu_addr;
@@ -116,8 +116,8 @@ static size_t data_mtu;	/* maximum data transfer size per unit */
  * Every time a slot is retrieved, the "pending" counter is incremented to
  * have a fast indicator of the synchronisation status, i.e. if "pending"
  * is not set, the synchronisation procedure is complete and the local data may
- * be read, or the remote data has been written and further commands may may
- * be issued.
+ * be read, or the remote data has been written and further commands may be
+ * issued.
  *
  * The local (mirror) start address of the requested remote address is stored
  * into the same slot in the "local_addr" array, so we'll know where to put the
@@ -261,7 +261,7 @@ static int rdcu_process_rx(void)
 
 		cnt++;
 
-		if ((0))
+		if (RDCU_CONFIG_DEBUG)
 			rmap_parse_pkt(spw_pckt);
 
 		/* convert format */
@@ -276,25 +276,20 @@ static int rdcu_process_rx(void)
 		local_addr = trans_log_get_addr(rp->tr_id);
 
 		if (!local_addr) {
-			printf("warning: response packet received not in "
-			       "transaction log\n");
+			printf("Warning: response packet received not in transaction log\n");
 			rmap_erase_packet(rp);
 			continue;
 		}
 
-
 		if (rp->data_len & 0x3) {
-			printf("Error: response packet data size is not a "
-			       "multiple of 4, transaction dropped\n");
+			printf("Error: response packet data size is not a multiple of 4, transaction dropped\n");
 
 			trans_log_release_slot(rp->tr_id);
 			rmap_erase_packet(rp);
 			return -1;
 		}
 
-
 		if (rp->data_len) {
-
 			uint8_t crc8;
 
 			/* convert endianess if needed */
@@ -308,13 +303,9 @@ static int rdcu_process_rx(void)
 			}
 #endif /* __BYTE_ORDER__ */
 
-
 			crc8 = rmap_crc8(rp->data, rp->data_len);
-
 			if (crc8 != rp->data_crc) {
-
-				printf("Error: data CRC8 mismatch, data invalid or "
-				       "packet truncated. Transaction dropped\n");
+				printf("Error: data CRC8 mismatch, data invalid or packet truncated. Transaction dropped\n");
 
 				trans_log_release_slot(rp->tr_id);
 				rmap_erase_packet(rp);
@@ -353,7 +344,7 @@ int rdcu_submit_tx(const uint8_t *cmd,  int cmd_size,
 	if (!rmap_tx)
 		return -1;
 
-	if ((0))
+	if (RDCU_CONFIG_DEBUG)
 		printf("Transmitting RMAP command\n");
 
 	if (rmap_tx(cmd, cmd_size, dpath_len, data, data_size)) {
@@ -413,7 +404,7 @@ int rdcu_gen_cmd(uint16_t trans_id, uint8_t *cmd,
 		return n;
 	}
 
-	memset(cmd, 0, n);
+	memset(cmd, 0, n);  /* clear command buffer */
 
 	n = rmap_build_hdr(pkt, cmd);
 
@@ -476,8 +467,7 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd),
 
 	/* convert endianess if needed */
 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-	if (data_len)
-	{
+	if (data_len) {
 		int i;
 		uint32_t *tmp_buf = alloca(data_len);
 		uint32_t *p = (uint32_t *) addr;
@@ -530,7 +520,7 @@ int rdcu_sync_data(int (*fn)(uint16_t trans_id, uint8_t *cmd,
 
 	slot = trans_log_grab_slot(data);
 	if (slot < 0) {
-		if ((0))
+		if (RDCU_CONFIG_DEBUG)
 			printf("Error: all slots busy!\n");
 		return 1;
 	}
@@ -782,7 +772,7 @@ int rdcu_rmap_sync_status(void)
 
 void rdcu_rmap_reset_log(void)
 {
-	memset(trans_log.in_use, 0, TRANS_LOG_SIZE);
+	memset(trans_log.in_use, 0, sizeof(trans_log.in_use));  /* clear in_use buffer */
 	trans_log.pending = 0;
 }
 
diff --git a/lib/rmap.c b/lib/rmap.c
index f8b6eb0..703add5 100644
--- a/lib/rmap.c
+++ b/lib/rmap.c
@@ -178,7 +178,7 @@ struct rmap_pkt *rmap_create_packet(void)
 	struct rmap_pkt *pkt;
 
 
-	pkt = (struct rmap_pkt *) calloc(sizeof(struct rmap_pkt), 1);
+	pkt = (struct rmap_pkt *) calloc(1, sizeof(struct rmap_pkt));
 	if (pkt)
 		pkt->proto_id = RMAP_PROTOCOL_ID;
 
@@ -206,7 +206,7 @@ void rmap_destroy_packet(struct rmap_pkt *pkt)
  * @param pkt a struct rmap_pkt
  *
  * @note this will attempt to deallocate any pointer references assigned by the
- * 	 user
+ *	 user
  * @warning use with care
  */
 
@@ -563,7 +563,7 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len)
 
 	pkt->src   = buf[RMAP_SRC_ADDR + n];
 	pkt->tr_id = ((uint16_t) buf[RMAP_TRANS_ID_BYTE0 + n] << 8) |
-	              (uint16_t) buf[RMAP_TRANS_ID_BYTE1 + n];
+		      (uint16_t) buf[RMAP_TRANS_ID_BYTE1 + n];
 
 	/* commands have a data address */
 	if (pkt->ri.cmd_resp) {
@@ -576,10 +576,9 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len)
 
 	/* all headers have data length unless they are a write reply */
 	if (!(!pkt->ri.cmd_resp && (pkt->ri.cmd & (RMAP_CMD_BIT_WRITE)))) {
-
 		pkt->data_len = ((uint32_t) buf[RMAP_DATALEN_BYTE0 + n] << 16) |
 				((uint32_t) buf[RMAP_DATALEN_BYTE1 + n] <<  8) |
-			         (uint32_t) buf[RMAP_DATALEN_BYTE2 + n];
+				 (uint32_t) buf[RMAP_DATALEN_BYTE2 + n];
 	}
 
 	pkt->hdr_crc  = buf[RMAP_HEADER_CRC];
@@ -587,7 +586,7 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len)
 	if (pkt->data_len) {
 		if (len < RMAP_DATA_START + n + pkt->data_len + 1) {  /* +1 for data CRC */
 			printf("buffer len is smaller than the contained RMAP packet; buf len: %u bytes vs RMAP: %zu bytes needed\n",
-				len , RMAP_DATA_START + n + pkt->data_len);
+				len, RMAP_DATA_START + n + pkt->data_len);
 			goto error;
 		}
 		if (len > RMAP_DATA_START + n + pkt->data_len + 1)  /* +1 for data CRC */
@@ -702,7 +701,7 @@ static void rmap_process_read_reply(uint8_t *pkt)
 	for (i = 0; i < len; i++)
 		printf("%02x:", pkt[RMAP_DATA_START + i]);
 
-	printf("\b \n");
+	printf("\b\n");
 }
 
 
-- 
GitLab


From f934932225d45ca266c34db4c5b5965bcad616f2 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 12 Jul 2022 11:03:54 +0200
Subject: [PATCH 23/46] Unification of buffer names between RDCU and ICU
 compression Fix some typos Use default values if .rdcu_pkt_mode_cfg file is
 not available

---
 cmp_tool.c                 |  2 +-
 include/cmp_io.h           |  3 +++
 include/cmp_rdcu.h         |  4 +--
 include/rdcu_pkt_to_file.h |  5 ++++
 lib/cmp_io.c               |  2 +-
 lib/cmp_rdcu.c             | 50 ++++++++++++++++++++------------------
 lib/rdcu_pkt_to_file.c     | 13 ++++++----
 lib/rdcu_rmap.c            |  2 +-
 8 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/cmp_tool.c b/cmp_tool.c
index c30ae6e..54e20ab 100644
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -569,7 +569,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 }
 
 
-/* generate packets to setup a RDCU compression */
+/* generate packets to setup an RDCU compression */
 static int gen_rdcu_write_pkts(struct cmp_cfg *cfg)
 {
 	int error;
diff --git a/include/cmp_io.h b/include/cmp_io.h
index 6de2222..873bf91 100644
--- a/include/cmp_io.h
+++ b/include/cmp_io.h
@@ -54,3 +54,6 @@ void print_cfg(const struct cmp_cfg *cfg, int rdcu_cfg);
 
 int atoui32(const char *dep_str, const char *val_str, uint32_t *red_val);
 int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode);
+
+enum cmp_data_type string2data_type(const char *data_type_str);
+const char *data_type2string(enum cmp_data_type data_type);
diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h
index 6273549..780c869 100644
--- a/include/cmp_rdcu.h
+++ b/include/cmp_rdcu.h
@@ -55,9 +55,9 @@ int rdcu_read_cmp_status(struct cmp_status *status);
 
 int rdcu_read_cmp_info(struct cmp_info *info);
 
-int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *output_buf);
+int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *compressed_data);
 
-int rdcu_read_model(const struct cmp_info *info, void *model_buf);
+int rdcu_read_model(const struct cmp_info *info, void *updated_model);
 
 int rdcu_interrupt_compression(void);
 
diff --git a/include/rdcu_pkt_to_file.h b/include/rdcu_pkt_to_file.h
index 1c350c8..b0f0558 100644
--- a/include/rdcu_pkt_to_file.h
+++ b/include/rdcu_pkt_to_file.h
@@ -27,6 +27,11 @@
 
 #define MAX_TC_FOLDER_DIR_LEN 256
 
+/* default values when no .rdcu_pkt_mode_cfg file is available */
+#define DEF_ICU_ADDR 0xA7
+#define DEF_RDCU_ADDR 0xFE
+#define DEF_MTU 4224
+
 int init_rmap_pkt_to_file(void);
 
 void set_tc_folder_dir(const char *dir_name);
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 0e74c0d..9e4eb3a 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -200,7 +200,7 @@ int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type
 	if (verbose) {
 		printf("\n\n");
 			for (i = 0; i < data_size; i++) {
-				printf("%02X ", tmp_buf[i]);
+				printf("%02X", tmp_buf[i]);
 			if ((i + 1) % 16 == 0)
 				printf("\n");
 			else
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index 336fc87..ff4eb6c 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -82,13 +82,13 @@ static void sync(void)
 
 /**
  * @brief check if the compression data product type, compression mode, model
- *	value and the lossy rounding parameters are valid for a RDCU compression
+ *	value and the lossy rounding parameters are valid for an RDCU compression
  *
  * @param cfg	pointer to a compression configuration containing the compression
  *	data product type, compression mode, model value and the rounding parameters
  *
  * @returns 0 if the compression data type, compression mode, model value and
- *	the lossy rounding parameters are valid for a RDCU compression, non-zero
+ *	the lossy rounding parameters are valid for an RDCU compression, non-zero
  *	if parameters are invalid
  */
 
@@ -131,7 +131,7 @@ static int rdcu_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief create a RDCU compression configuration
+ * @brief create an RDCU compression configuration
  *
  * @param data_type	compression data product types
  * @param cmp_mode	compression mode
@@ -401,7 +401,7 @@ int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress,
 
 /**
  * @brief check if the Golomb and spillover threshold parameter combination is
- *	invalid for a RDCU compression
+ *	invalid for an RDCU compression
  * @note also checked the adaptive Golomb and spillover threshold parameter combinations
  *
  * @param cfg	a pointer to a compression configuration
@@ -519,7 +519,7 @@ int rdcu_cfg_imagette(struct cmp_cfg *cfg,
 
 
 /**
- * @brief check if the compressor configuration is invalid for a RDCU compression,
+ * @brief check if the compressor configuration is invalid for an RDCU compression,
  *	see the user manual for more information (PLATO-UVIE-PL-UM-0001).
  *
  * @param cfg	pointer to a compression configuration contains all parameters
@@ -677,10 +677,13 @@ int rdcu_start_compression(void)
  *
  * @param cfg  configuration contains all parameters required for compression
  *
- * @note when using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
- *      the model parameters (model_value, model_buf, rdcu_model_adr) are ignored
- * @note the validity of the cfg structure is checked before the compression is
- *	 started
+ * @note Before the rdcu_compress function can be used, an initialization of
+ *	the RMAP library is required. This is achieved with the functions
+ *	rdcu_ctrl_init() and rdcu_rmap_init().
+ * @note When using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
+ *       the model parameters (model_value, model_of_data, rdcu_model_adr) are ignored.
+ * @note The validity of the cfg structure is checked before the compression is
+ *	 started.
  *
  * @returns 0 on success, error otherwise
  */
@@ -761,7 +764,7 @@ int rdcu_read_cmp_status(struct cmp_status *status)
 
 
 /**
- * @brief read out the metadata of a RDCU compression
+ * @brief read out the metadata of an RDCU compression
  *
  * @param info  compression information contains the metadata of a compression
  *
@@ -817,15 +820,14 @@ int rdcu_read_cmp_info(struct cmp_info *info)
 /**
  * @brief read the compressed bitstream from the RDCU SRAM
  *
- * @param info  compression information contains the metadata of a compression
- *
- * @param output_buf  the buffer to store the bitstream (if NULL, the required
- *		      size is returned)
+ * @param info			compression information contains the metadata of a compression
+ * @param compressed_data	the buffer to store the bitstream (if NULL, the
+ *				required size is returned)
  *
  * @returns the number of bytes read, < 0 on error
  */
 
-int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *output_buf)
+int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *compressed_data)
 {
 	uint32_t s;
 
@@ -835,7 +837,7 @@ int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *output_buf)
 	/* calculate the need bytes for the bitstream */
 	s = cmp_bit_to_4byte(info->cmp_size);
 
-	if (output_buf == NULL)
+	if (compressed_data == NULL)
 		return (int)s;
 
 	if (rdcu_sync_sram_to_mirror(info->rdcu_cmp_adr_used, s,
@@ -845,22 +847,22 @@ int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *output_buf)
 	/* wait for it */
 	sync();
 
-	return rdcu_read_sram(output_buf, info->rdcu_cmp_adr_used, s);
+	return rdcu_read_sram(compressed_data, info->rdcu_cmp_adr_used, s);
 }
 
 
 /**
- * @brief read the model from the RDCU SRAM
+ * @brief read the updated model from the RDCU SRAM
  *
- * @param info  compression information contains the metadata of a compression
+ * @param info		compression information contains the metadata of a compression
  *
- * @param model_buf  the buffer to store the model (if NULL, the required size
- *		     is returned)
+ * @param updated_model	the buffer to store the updated model (if NULL, the required size
+ *			is returned)
  *
  * @returns the number of bytes read, < 0 on error
  */
 
-int rdcu_read_model(const struct cmp_info *info, void *model_buf)
+int rdcu_read_model(const struct cmp_info *info, void *updated_model)
 {
 	uint32_t s;
 
@@ -870,7 +872,7 @@ int rdcu_read_model(const struct cmp_info *info, void *model_buf)
 	/* calculate the need bytes for the model */
 	s = info->samples_used * IMA_SAM2BYT;
 
-	if (model_buf == NULL)
+	if (updated_model == NULL)
 		return (int)s;
 
 	if (rdcu_sync_sram_to_mirror(info->rdcu_new_model_adr_used, (s+3) & ~3U,
@@ -880,7 +882,7 @@ int rdcu_read_model(const struct cmp_info *info, void *model_buf)
 	/* wait for it */
 	sync();
 
-	return rdcu_read_sram(model_buf, info->rdcu_new_model_adr_used, s);
+	return rdcu_read_sram(updated_model, info->rdcu_new_model_adr_used, s);
 }
 
 
diff --git a/lib/rdcu_pkt_to_file.c b/lib/rdcu_pkt_to_file.c
index ed10778..9e80125 100644
--- a/lib/rdcu_pkt_to_file.c
+++ b/lib/rdcu_pkt_to_file.c
@@ -311,8 +311,11 @@ int init_rmap_pkt_to_file(void)
 	uint8_t icu_addr, rdcu_addr;
 	int mtu;
 
-	if (read_rdcu_pkt_mode_cfg(&icu_addr, &rdcu_addr, &mtu))
-		return -1;
+	if (read_rdcu_pkt_mode_cfg(&icu_addr, &rdcu_addr, &mtu)) {
+		icu_addr = DEF_ICU_ADDR;
+		rdcu_addr = DEF_RDCU_ADDR;
+		mtu = DEF_MTU;
+	}
 	rdcu_ctrl_init();
 	rdcu_set_source_logical_address(icu_addr);
 	rdcu_set_destination_logical_address(rdcu_addr);
@@ -323,7 +326,7 @@ int init_rmap_pkt_to_file(void)
 
 
 /**
- * @brief generate the rmap packets to set up a RDCU compression
+ * @brief generate the rmap packets to set up an RDCU compression
  * @note note that the initialization function init_rmap_pkt_to_file() must be
  *	executed before
  * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
@@ -363,7 +366,7 @@ int gen_write_rdcu_pkts(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief generate the rmap packets to read the result of a RDCU compression
+ * @brief generate the rmap packets to read the result of an RDCU compression
  * @note note that the initialization function init_rmap_pkt_to_file() must be
  *	executed before
  * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
@@ -434,7 +437,7 @@ int gen_read_rdcu_pkts(const struct cmp_info *info)
 
 
 /**
- * @brief generate the rmap packets to set up a RDCU compression, read the
+ * @brief generate the rmap packets to set up an RDCU compression, read the
  *	bitstream and the updated model in parallel to write the data to compressed
  *	and the model and start the compression
  * @note the compressed data are read from cfg->rdcu_buffer_adr with the length
diff --git a/lib/rdcu_rmap.c b/lib/rdcu_rmap.c
index b314b47..e4ec4b6 100644
--- a/lib/rdcu_rmap.c
+++ b/lib/rdcu_rmap.c
@@ -490,7 +490,7 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd),
 /**
  * @brief submit a data sync command
  *
- * @param fn a RDCU data transfer generation function
+ * @param fn an RDCU data transfer generation function
  * @param addr the remote address
  * @param data the local data address
  * @param data_len the length of the data payload
-- 
GitLab


From 1da2d6052eca2d0dd172863108cee715079abe13 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 1 Sep 2022 12:39:39 +0200
Subject: [PATCH 24/46] fix a bug in the compress_multi_entry_hdr() function
 reduce the max golomb_par (cmp_par) because the entity field has 16 bits
 split get_max_spill() function in 2 for RDCU cmp_rdcu_max_spill() and ICU
 cmp_icu_max_spill() fix some typos refactoring pad_bitstream() and
 cmp_data_to_big_endian() configure_encoder_setup() functions refactoring RAW
 compression update tests

---
 include/cmp_icu.h           |   10 +-
 include/cmp_rdcu.h          |    4 +-
 include/cmp_support.h       |   19 +-
 lib/cmp_guess.c             |    4 +-
 lib/cmp_icu.c               |  202 +++--
 lib/cmp_rdcu.c              |   53 +-
 lib/cmp_support.c           |  143 +--
 test/cmp_icu/test_cmp_icu.c | 1676 ++++++++++++++++++++++++++++++++++-
 8 files changed, 1895 insertions(+), 216 deletions(-)

diff --git a/include/cmp_icu.h b/include/cmp_icu.h
index 01e528c..8b68fcb 100644
--- a/include/cmp_icu.h
+++ b/include/cmp_icu.h
@@ -22,15 +22,7 @@
 
 #include <cmp_support.h>
 
-
-/* return code if the bitstream buffer is too small to store the whole bitstream */
-#define CMP_ERROR_SAMLL_BUF -2
-
-/* return code if the value or the model is bigger than the max_used_bits
- * parameter allows
- */
-#define CMP_ERROR_HIGH_VALUE -3
-
+#define CMP_PAR_UNUSED 0
 
 /* create and setup a compression configuration */
 struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h
index 780c869..93da3d0 100644
--- a/include/cmp_rdcu.h
+++ b/include/cmp_rdcu.h
@@ -47,8 +47,6 @@ int rdcu_cfg_imagette(struct cmp_cfg *cfg,
 		      uint32_t ap1_golomb_par, uint32_t ap1_spillover_par,
 		      uint32_t ap2_golomb_par, uint32_t ap2_spillover_par);
 
-int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg);
-
 int rdcu_compress_data(const struct cmp_cfg *cfg);
 
 int rdcu_read_cmp_status(struct cmp_status *status);
@@ -64,4 +62,6 @@ int rdcu_interrupt_compression(void);
 void rdcu_enable_interrput_signal(void);
 void rdcu_disable_interrput_signal(void);
 
+int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg);
+
 #endif /* _CMP_RDCU_H_ */
diff --git a/include/cmp_support.h b/include/cmp_support.h
index f5e0b38..5c85a99 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -23,6 +23,14 @@
 #include <stddef.h>
 
 
+/* return code if the bitstream buffer is too small to store the whole bitstream */
+#define CMP_ERROR_SAMLL_BUF -2
+
+/* return code if the value or the model is bigger than the max_used_bits
+ * parameter allows
+ */
+#define CMP_ERROR_HIGH_VALUE -3
+
 #define CMP_LOSSLESS	0
 #define CMP_PAR_UNUNSED	0
 
@@ -36,13 +44,13 @@
 #define MAX_RDCU_GOLOMB_PAR	63U
 #define MIN_RDCU_SPILL		2U
 #define MAX_RDCU_ROUND		2U
-/* for maximum spill value look at get_max_spill function */
+/* for maximum spill value look at cmp_rdcu_max_spill function */
 
 /* valid compression parameter ranges for ICU compression */
 #define MIN_ICU_GOLOMB_PAR	1U
-#define MAX_ICU_GOLOMB_PAR	0x80000000U
+#define MAX_ICU_GOLOMB_PAR	UINT16_MAX /* the compression entity dos not allow larger values */
 #define MIN_ICU_SPILL		2U
-/* for maximum spill value look at get_max_spill function */
+/* for maximum spill value look at cmp_icu_max_spill function */
 #define MAX_ICU_ROUND		3U
 #define MAX_STUFF_CMP_PAR	32U
 
@@ -86,7 +94,7 @@
 
 /* defined compression data product types */
 enum cmp_data_type {
-	DATA_TYPE_UNKOWN,
+	DATA_TYPE_UNKNOWN,
 	DATA_TYPE_IMAGETTE,
 	DATA_TYPE_IMAGETTE_ADAPTIVE,
 	DATA_TYPE_SAT_IMAGETTE,
@@ -235,7 +243,8 @@ int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg);
 int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg);
 int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg);
 int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg);
-uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type);
+uint32_t cmp_rdcu_max_spill(unsigned int golomb_par);
+uint32_t cmp_icu_max_spill(unsigned int cmp_par);
 
 int cmp_data_type_valid(enum cmp_data_type data_type);
 int rdcu_supported_data_type_is_used(enum cmp_data_type data_type);
diff --git a/lib/cmp_guess.c b/lib/cmp_guess.c
index 3107aaf..40e3ebe 100644
--- a/lib/cmp_guess.c
+++ b/lib/cmp_guess.c
@@ -91,7 +91,7 @@ uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode
 		405, 411, 418, 424, 431, 452 };
 
 	if (zero_escape_mech_is_used(cmp_mode))
-		return get_max_spill(golomb_par, DATA_TYPE_IMAGETTE);
+		return cmp_rdcu_max_spill(golomb_par);
 
 	if (cmp_mode == CMP_MODE_MODEL_MULTI) {
 		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
@@ -172,7 +172,7 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 	fflush(stdout);
 
 	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
-		for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->data_type); s++) {
+		for (s = MIN_RDCU_SPILL; s < cmp_rdcu_max_spill(g); s++) {
 			cfg->golomb_par = g;
 			cfg->spill = s;
 
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 2d11006..c6d4a27 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -39,6 +39,10 @@
 #include <cmp_icu.h>
 
 
+/* maximum used bits registry */
+extern struct cmp_max_used_bits max_used_bits;
+
+
 /* pointer to a code word generation function */
 typedef uint32_t (*generate_cw_f_pt)(uint32_t value, uint32_t encoder_par1,
 				     uint32_t encoder_par2, uint32_t *cw);
@@ -46,7 +50,7 @@ typedef uint32_t (*generate_cw_f_pt)(uint32_t value, uint32_t encoder_par1,
 
 /* structure to hold a setup to encode a value */
 struct encoder_setupt {
-	generate_cw_f_pt generate_cw_f; /* pointer to the code word generation function */
+	generate_cw_f_pt generate_cw_f; /* pointer to the code word encoder */
 	int (*encode_method_f)(uint32_t data, uint32_t model, int stream_len,
 			       const struct encoder_setupt *setup); /* pointer to the encoding function */
 	uint32_t *bitstream_adr; /* start address of the compressed data bitstream */
@@ -60,15 +64,15 @@ struct encoder_setupt {
 
 
 /**
- * @brief create a ICU compression configuration
+ * @brief create an ICU compression configuration
  *
- * @param data_type	compression data product types
+ * @param data_type	compression data product type
  * @param cmp_mode	compression mode
- * @param model_value	model weighting parameter (only need for model compression mode)
+ * @param model_value	model weighting parameter (only needed for model compression mode)
  * @param lossy_par	lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
  *
- * @returns compression configuration containing the chosen parameters;
- *	on error the data_type record is set to DATA_TYPE_UNKOWN
+ * @returns a compression configuration containing the chosen parameters;
+ *	on error the data_type record is set to DATA_TYPE_UNKNOWN
  */
 
 struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
@@ -86,20 +90,20 @@ struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cm
 
 	cfg_valid = cmp_cfg_icu_gen_par_is_valid(&cfg);
 	if (!cfg_valid)
-		cfg.data_type = DATA_TYPE_UNKOWN;
+		cfg.data_type = DATA_TYPE_UNKNOWN;
 
 	return cfg;
 }
 
 
 /**
- * @brief setup of the different data buffers for an ICU compression
+ * @brief setup the different data buffers for an ICU compression
  *
  * @param cfg			pointer to a compression configuration (created
  *				with the cmp_cfg_icu_create() function)
  * @param data_to_compress	pointer to the data to be compressed
  * @param data_samples		length of the data to be compressed measured in
- *				data samples/entitys (multi entity header not
+ *				data samples/entitys (collection header not
  *				included by imagette data)
  * @param model_of_data		pointer to model data buffer (can be NULL if no
  *				model compression mode is used)
@@ -142,7 +146,7 @@ size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
  * @brief set up the configuration parameters for an ICU imagette compression
  *
  * @param cfg			pointer to a compression configuration (created
- *				with the cmp_cfg_icu_create() function)
+ *				by the cmp_cfg_icu_create() function)
  * @param cmp_par		imagette compression parameter (Golomb parameter)
  * @param spillover_par		imagette spillover threshold parameter
  *
@@ -166,11 +170,11 @@ int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
 
 
 /**
- * @brief set up of the configuration parameters for a flux/COB compression
+ * @brief set up the configuration parameters for a flux/COB compression
  * @note not all parameters are needed for every flux/COB compression data type
  *
  * @param cfg			pointer to a compression configuration (created
- *				with the cmp_cfg_icu_create() function)
+ *				by the cmp_cfg_icu_create() function)
  * @param cmp_par_exp_flags	exposure flags compression parameter
  * @param spillover_exp_flags	exposure flags spillover threshold parameter
  * @param cmp_par_fx		normal flux compression parameter
@@ -220,13 +224,13 @@ int cmp_cfg_fx_cob(struct cmp_cfg *cfg,
 
 
 /**
- * @brief set up of the configuration parameters for an auxiliary science data compression
+ * @brief set up the configuration parameters for an auxiliary science data compression
  * @note auxiliary compression data types are: DATA_TYPE_OFFSET, DATA_TYPE_BACKGROUND,
 	DATA_TYPE_SMEARING, DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND
- * @note not all parameters are needed for the every auxiliary compression data types
+ * @note not all parameters are needed for the every auxiliary compression data type
  *
- * @param cfg				pointer to a compression configuration (
- *					created with the cmp_cfg_icu_create() function)
+ * @param cfg				pointer to a compression configuration (created
+ *					with the cmp_cfg_icu_create() function)
  * @param cmp_par_mean			mean compression parameter
  * @param spillover_mean		mean spillover threshold parameter
  * @param cmp_par_variance		variance compression parameter
@@ -739,29 +743,41 @@ static int configure_encoder_setup(struct encoder_setupt *setup,
 	if (!cfg)
 		return -1;
 
-	setup->encoder_par1 = cmp_par;
-	setup->spillover_par = spillover;
 	if (max_data_bits > 32) {
 		debug_print("Error: max_data_bits parameter is bigger than 32 bits.\n");
 		return -1;
 	}
+
+	memset(setup, 0, sizeof(*setup));
+
+	setup->encoder_par1 = cmp_par;
 	setup->max_data_bits = max_data_bits;
 	setup->lossy_par = lossy_par;
+	setup->bitstream_adr = cfg->icu_output_buf;
+	setup->max_stream_len = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
+
+	if (cfg->cmp_mode != CMP_MODE_STUFF) {
+		if (ilog_2(cmp_par) < 0)
+			return -1;
+		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
+
+		setup->spillover_par = spillover;
+
+		/* for encoder_par1 which are a power of two we can use the faster rice_encoder */
+		if (is_a_pow_of_2(setup->encoder_par1))
+			setup->generate_cw_f = &rice_encoder;
+		else
+			setup->generate_cw_f = &golomb_encoder;
+	}
 
 	switch (cfg->cmp_mode) {
 	case CMP_MODE_MODEL_ZERO:
 	case CMP_MODE_DIFF_ZERO:
 		setup->encode_method_f = &encode_value_zero;
-		if (ilog_2(cmp_par) < 0)
-			return -1;
-		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
 		break;
 	case CMP_MODE_MODEL_MULTI:
 	case CMP_MODE_DIFF_MULTI:
 		setup->encode_method_f = &encode_value_multi;
-		if (ilog_2(cmp_par) < 0)
-			return -1;
-		setup->encoder_par2 = (uint32_t)ilog_2(cmp_par);
 		break;
 	case CMP_MODE_STUFF:
 		setup->encode_method_f = &encode_value_none;
@@ -771,14 +787,6 @@ static int configure_encoder_setup(struct encoder_setupt *setup,
 		return -1;
 	}
 
-	/* for encoder_par1 which are a power of two we can use the faster rice_encoder */
-	if (is_a_pow_of_2(setup->encoder_par1))
-		setup->generate_cw_f = &rice_encoder;
-	else
-		setup->generate_cw_f = &golomb_encoder;
-
-	setup->bitstream_adr = cfg->icu_output_buf;
-	setup->max_stream_len = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
 
 	return 0;
 }
@@ -808,9 +816,6 @@ static int compress_imagette(const struct cmp_cfg *cfg)
 	uint16_t *next_model_p = data_buf;
 	uint16_t *up_model_buf = NULL;
 
-	if (cfg->samples == 0)
-		return 0;
-
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
 		next_model_p = &model_buf[1];
@@ -843,10 +848,10 @@ static int compress_imagette(const struct cmp_cfg *cfg)
  * @brief compress the multi-entry packet header structure and sets the data,
  *	model and up_model pointers to the data after the header
  *
- * @param data		pointer to a pointer pointing to the data to be compressed
- * @param model		pointer to a pointer pointing to the model of the data
- * @param up_model	pointer to a pointer pointing to the updated model buffer
- * @param cfg		pointer to the compression configuration structure
+ * @param data			pointer to a pointer pointing to the data to be compressed
+ * @param model			pointer to a pointer pointing to the model of the data
+ * @param up_model		pointer to a pointer pointing to the updated model buffer
+ * @param compressed_data	pointer to the compressed data buffer
  *
  * @returns the bit length of the bitstream on success; negative on error,
  *
@@ -855,26 +860,23 @@ static int compress_imagette(const struct cmp_cfg *cfg)
  */
 
 static int compress_multi_entry_hdr(void **data, void **model, void **up_model,
-				    const struct cmp_cfg *cfg)
+				    void *compressed_data)
 {
-	if (cfg->buffer_length < 1)
-		return -1;
+	if (*up_model) {
+		if (*data)
+			memcpy(*up_model, *data, MULTI_ENTRY_HDR_SIZE);
+		*up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE;
+	}
 
 	if (*data) {
-		if (cfg->icu_output_buf)
-			memcpy(cfg->icu_output_buf, *data, MULTI_ENTRY_HDR_SIZE);
+		if (compressed_data)
+			memcpy(compressed_data, *data, MULTI_ENTRY_HDR_SIZE);
 		*data = (uint8_t *)*data + MULTI_ENTRY_HDR_SIZE;
 	}
 
 	if (*model)
 		*model = (uint8_t *)*model + MULTI_ENTRY_HDR_SIZE;
 
-	if (*up_model) {
-		if (*data)
-			memcpy(*up_model, *data, MULTI_ENTRY_HDR_SIZE);
-		*up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE;
-	}
-
 	return MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
 }
 
@@ -906,7 +908,7 @@ static int compress_s_fx(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -978,7 +980,7 @@ static int compress_s_fx_efx(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1060,7 +1062,7 @@ static int compress_s_fx_ncob(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1149,7 +1151,7 @@ static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1263,7 +1265,7 @@ static int compress_f_fx(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1325,7 +1327,7 @@ static int compress_f_fx_efx(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1397,7 +1399,7 @@ static int compress_f_fx_ncob(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1475,7 +1477,7 @@ static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1579,7 +1581,7 @@ static int compress_l_fx(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1661,7 +1663,7 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1754,7 +1756,7 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -1870,7 +1872,7 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -2010,7 +2012,7 @@ static int compress_nc_offset(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -2081,7 +2083,7 @@ static int compress_nc_background(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -2163,7 +2165,7 @@ static int compress_smearing(const struct cmp_cfg *cfg)
 		up_model_buf = cfg->icu_new_model_buf;
 
 	stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
-					      (void **)&up_model_buf, cfg);
+					      (void **)&up_model_buf, cfg->icu_output_buf);
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
 		model = model_buf[0];
@@ -2236,13 +2238,13 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size)
 	if (cmp_size < 0)
 		return cmp_size;
 
-	/* maximum length of the bitstream/icu_output_buf in bits */
-	output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
-
-	/* no padding in RAW mode*/
+	/* no padding in RAW mode; DIFFERENCE ENDIANNESS */
 	if (cfg->cmp_mode == CMP_MODE_RAW)
 		return cmp_size;
 
+	/* maximum length of the bitstream/icu_output_buf in bits */
+	output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type);
+
 	n_pad_bits = 32 - ((unsigned int)cmp_size & 0x1FU);
 	if (n_pad_bits < 32) {
 		int n_bits = put_n_bits32(0, n_pad_bits, cmp_size, cfg->icu_output_buf,
@@ -2264,37 +2266,41 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size)
  * @returns 0 on success; non-zero on failure
  */
 
-static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, unsigned int cmp_size)
+static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, int cmp_size)
 {
 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
 	size_t i;
 	uint32_t *p;
+	uint32_t s = (uint32_t)cmp_size;
 
-	if (cfg->cmp_mode == CMP_MODE_RAW) {
-		int err = cmp_input_big_to_cpu_endianness(cfg->icu_output_buf,
-							  cmp_size/CHAR_BIT, cfg->data_type);
-		return err;
-	}
+	if (cmp_size < 0)
+		return cmp_size;
 
-	if (rdcu_supported_data_type_is_used(cfg->data_type)) {
-		p = cfg->icu_output_buf;
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
+		if (cmp_input_big_to_cpu_endianness(cfg->icu_output_buf,
+						    s/CHAR_BIT, cfg->data_type))
+			cmp_size = -1;
 	} else {
-		p = &cfg->icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
-		cmp_size -= MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
-	}
+		if (rdcu_supported_data_type_is_used(cfg->data_type)) {
+			p = cfg->icu_output_buf;
+		} else {
+			p = &cfg->icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
+			s -= MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
+		}
 
-	for (i = 0; i < cmp_bit_to_4byte(cmp_size)/sizeof(uint32_t); i++)
-		cpu_to_be32s(&p[i]);
+		for (i = 0; i < cmp_bit_to_4byte(s)/sizeof(uint32_t); i++)
+			cpu_to_be32s(&p[i]);
+	}
 #else
 	/* do nothing data are already in big-endian */
 	(void)cfg;
 #endif /*__BYTE_ORDER__ */
-	return 0;
+	return cmp_size;
 }
 
 
 /**
- * @brief	compress data on the ICU
+ * @brief compress data on the ICU in software
  *
  * @param cfg	pointer to a compression configuration (created with the
  *		cmp_cfg_icu_create() function, setup with the cmp_cfg_xxx() functions)
@@ -2319,22 +2325,22 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 	if (cfg->samples == 0) /* nothing to compress we are done*/
 		return 0;
 
-	if (!cmp_cfg_is_valid(cfg))
-		return -1;
+	if (raw_mode_is_used(cfg->cmp_mode))
+		if (cfg->samples > cfg->buffer_length)
+			return CMP_ERROR_SAMLL_BUF;
 
-	if (model_mode_is_used(cfg->cmp_mode) && !cfg->model_buf)
+	if (!cmp_cfg_is_valid(cfg))
 		return -1;
 
 	if (raw_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->samples > cfg->buffer_length) {
-			cmp_size = CMP_ERROR_SAMLL_BUF;
-		} else {
-			cmp_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
-			if (cfg->icu_output_buf)
-				memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size);
-			cmp_size *= CHAR_BIT; /* convert to bits */
-		}
+		cmp_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+		if (cfg->icu_output_buf)
+			memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size);
+		cmp_size *= CHAR_BIT; /* convert to bits */
 	} else {
+		if (cfg->samples < cfg->buffer_length/3)
+			debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended.\n");
+
 		switch (cfg->data_type) {
 		case DATA_TYPE_IMAGETTE:
 		case DATA_TYPE_IMAGETTE_ADAPTIVE:
@@ -2396,16 +2402,16 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 
 		case DATA_TYPE_F_CAM_OFFSET:
 		case DATA_TYPE_F_CAM_BACKGROUND:
-		case DATA_TYPE_UNKOWN:
+		case DATA_TYPE_UNKNOWN:
 		default:
 			debug_print("Error: Data type not supported.\n");
 			cmp_size = -1;
 		}
 	}
 
-	if (cfg->icu_output_buf && cmp_size > 0) {
+	if (cfg->icu_output_buf) {
 		cmp_size = pad_bitstream(cfg, cmp_size);
-		cmp_data_to_big_endian(cfg, (unsigned int)cmp_size);
+		cmp_size = cmp_data_to_big_endian(cfg, cmp_size);
 	}
 
 	return cmp_size;
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index ff4eb6c..c3ffb7c 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -133,13 +133,13 @@ static int rdcu_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg)
 /**
  * @brief create an RDCU compression configuration
  *
- * @param data_type	compression data product types
+ * @param data_type	compression data product type
  * @param cmp_mode	compression mode
- * @param model_value	model weighting parameter (only need for model compression mode)
+ * @param model_value	model weighting parameter (only needed for model compression mode)
  * @param lossy_par	lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
  *
- * @returns compression configuration containing the chosen parameters;
- *	on error the data_type record is set to DATA_TYPE_UNKOWN
+ * @returns a compression configuration containing the chosen parameters;
+ *	on error the data_type record is set to DATA_TYPE_UNKNOWN
  */
 
 struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
@@ -155,7 +155,7 @@ struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_m
 	cfg.round = lossy_par;
 
 	if (rdcu_cfg_gen_par_is_invalid(&cfg))
-		cfg.data_type = DATA_TYPE_UNKOWN;
+		cfg.data_type = DATA_TYPE_UNKNOWN;
 
 	return cfg;
 }
@@ -348,27 +348,26 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg)
 
 
 /**
- *@brief setup of the different data buffers for an RDCU compression
+ * @brief setup of the different data buffers for an RDCU compression
  *
  * @param cfg			pointer to a compression configuration (created
  *				with the rdcu_cfg_create() function)
  * @param data_to_compress	pointer to the data to be compressed (if NULL no
  *				data transfer to the RDCU)
  * @param data_samples		length of the data to be compressed measured in
- *				16-bit data samples (ignoring the multi entity header)
+ *				16-bit data samples (ignoring the collection header)
  * @param model_of_data		pointer to model data buffer (only needed for
  *				model compression mode, if NULL no model data
  *				transfer to the RDCU)
- * @param rdcu_data_adr		RDCU data to compress start address, the first
- *				data address in the RDCU SRAM
- * @param rdcu_model_adr	RDCU model start address, the first model address
- *				in the RDCU SRAM (only need for model compression mode)
- * @param rdcu_new_model_adr	RDCU new/updated model start address(can be the
+ * @param rdcu_data_adr		RDCU SRAM data to compress start address
+ * @param rdcu_model_adr	RDCU SRAM model start address (only need for
+ *				model compression mode)
+ * @param rdcu_new_model_adr	RDCU SRAM new/updated model start address(can be the
  *				by the same as rdcu_model_adr for in-place model update)
- * @param rdcu_buffer_adr	RDCU compressed data start address, the first
- *				output data address in the RDCU SRAM
+ * @param rdcu_buffer_adr	RDCU SRAM compressed data start address
  * @param rdcu_buffer_lenght	length of the RDCU compressed data SRAM buffer
- *				in number of 16-bit samples
+ *				measured in 16-bit units (same as data_samples)
+ *
  * @returns 0 if parameters are valid, non-zero if parameters are invalid
  */
 
@@ -441,9 +440,9 @@ static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (cfg->spill > get_max_spill(cfg->golomb_par, cfg->data_type)) {
+	if (cfg->spill > cmp_rdcu_max_spill(cfg->golomb_par)) {
 		debug_print("Error: The selected spillover threshold value: %u is too large for the selected Golomb parameter: %u, the largest possible spillover value is: %u.\n",
-			    cfg->spill, cfg->golomb_par, get_max_spill(cfg->golomb_par, cfg->data_type));
+			    cfg->spill, cfg->golomb_par, cmp_rdcu_max_spill(cfg->golomb_par));
 		cfg_invalid++;
 	}
 
@@ -453,9 +452,9 @@ static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (cfg->ap1_spill > get_max_spill(cfg->ap1_golomb_par, cfg->data_type)) {
+	if (cfg->ap1_spill > cmp_rdcu_max_spill(cfg->ap1_golomb_par)) {
 		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too large for the selected adaptive 1 Golomb parameter: %u, the largest possible adaptive 1 spillover value is: %u.\n",
-			    cfg->ap1_spill, cfg->ap1_golomb_par, get_max_spill(cfg->ap1_golomb_par, cfg->data_type));
+			    cfg->ap1_spill, cfg->ap1_golomb_par, cmp_rdcu_max_spill(cfg->ap1_golomb_par));
 		cfg_invalid++;
 	}
 
@@ -465,9 +464,9 @@ static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (cfg->ap2_spill > get_max_spill(cfg->ap2_golomb_par, cfg->data_type)) {
+	if (cfg->ap2_spill > cmp_rdcu_max_spill(cfg->ap2_golomb_par)) {
 		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too large for the selected adaptive 2 Golomb parameter: %u, the largest possible adaptive 2 spillover value is: %u.\n",
-			    cfg->ap2_spill, cfg->ap2_golomb_par, get_max_spill(cfg->ap2_golomb_par, cfg->data_type));
+			    cfg->ap2_spill, cfg->ap2_golomb_par, cmp_rdcu_max_spill(cfg->ap2_golomb_par));
 		cfg_invalid++;
 	}
 
@@ -484,12 +483,12 @@ static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
  *
  * @param cfg			pointer to a compression configuration (created
  *				with the rdcu_cfg_create() function)
- * @param golomb_par		imagette compression parameter (Golomb parameter)
+ * @param golomb_par		imagette compression parameter
  * @param spillover_par		imagette spillover threshold parameter
- * @param ap1_golomb_par	adaptive 1 imagette compression parameter (ap1_golomb parameter)
+ * @param ap1_golomb_par	adaptive 1 imagette compression parameter
  * @param ap1_spillover_par	adaptive 1 imagette spillover threshold parameter
- * @param ap2_golomb_par	adaptive 2 imagette compression parameter (ap2_golomb parameter)
- * @param ap2_spillover_par	adaptive 1 imagette spillover threshold parameter
+ * @param ap2_golomb_par	adaptive 2 imagette compression parameter
+ * @param ap2_spillover_par	adaptive 2 imagette spillover threshold parameter
  *
  * @returns 0 if parameters are valid, non-zero if parameters are invalid
  */
@@ -677,11 +676,9 @@ int rdcu_start_compression(void)
  *
  * @param cfg  configuration contains all parameters required for compression
  *
- * @note Before the rdcu_compress function can be used, an initialization of
+ * @note Before the rdcu_compress function can be used, an initialisation of
  *	the RMAP library is required. This is achieved with the functions
  *	rdcu_ctrl_init() and rdcu_rmap_init().
- * @note When using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
- *       the model parameters (model_value, model_of_data, rdcu_model_adr) are ignored.
  * @note The validity of the cfg structure is checked before the compression is
  *	 started.
  *
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index 666ce96..cfa7dc5 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -67,7 +67,12 @@ int is_a_pow_of_2(unsigned int v)
 
 int cmp_data_type_valid(enum cmp_data_type data_type)
 {
-	if (data_type <= DATA_TYPE_UNKOWN || data_type > DATA_TYPE_F_CAM_OFFSET)
+	if (data_type == DATA_TYPE_F_CAM_OFFSET)
+		debug_print("Error: DATA_TYPE_F_CAM_OFFSET is TBD and not implemented yet.\n");
+	if (data_type == DATA_TYPE_F_CAM_BACKGROUND)
+		debug_print("Error: DATA_TYPE_F_CAM_BACKGROUND is TBD  and not implemented yet.\n");
+
+	if (data_type <= DATA_TYPE_UNKNOWN || data_type > DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE)
 		return 0;
 
 	return 1;
@@ -154,7 +159,7 @@ int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode)
 /**
  * @brief check if the data product data type is supported by the RDCU compressor
  *
- * @param data_type	compression data product types
+ * @param data_type	compression data product type
  *
  * @returns 1 when the data type is supported by the RDCU, otherwise 0
  */
@@ -393,16 +398,18 @@ unsigned int cmp_up_model(unsigned int data, unsigned int model,
 
 
 /**
- * @brief get the maximum valid spill threshold value for a given golomb_par
+ * @brief get the maximum valid spill threshold value for a RDCU HW compression
+ *	in diff or model mode
  *
  * @param golomb_par	Golomb parameter
- * @param data_type	compression data type
  *
- * @returns the highest still valid spill threshold value
+ * @returns the highest still valid spill threshold value for a diff of model
+ *	 mode compression; 0 if golomb_par is invalid
  */
 
-uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type data_type)
+uint32_t cmp_rdcu_max_spill(unsigned int golomb_par)
 {
+	/* the RDCU can only generate 16 bit long code words -> lower max spill needed */
 	const uint32_t LUT_MAX_RDCU[MAX_RDCU_GOLOMB_PAR+1] = { 0, 8, 22, 35, 48,
 		60, 72, 84, 96, 107, 118, 129, 140, 151, 162, 173, 184, 194,
 		204, 214, 224, 234, 244, 254, 264, 274, 284, 294, 304, 314, 324,
@@ -410,30 +417,36 @@ uint32_t get_max_spill(unsigned int golomb_par, enum cmp_data_type data_type)
 		452, 461, 470, 479, 488, 497, 506, 515, 524, 533, 542, 551, 560,
 		569, 578, 587, 596, 605, 614, 623 };
 
-	if (golomb_par == 0)
+
+	if (golomb_par > MAX_RDCU_GOLOMB_PAR)
 		return 0;
 
-	/* the RDCU can only generate 16 bit long code words -> lower max spill needed */
-	if (rdcu_supported_data_type_is_used(data_type)) {
-		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
-			return 0;
+	return LUT_MAX_RDCU[golomb_par];
+}
 
-		return LUT_MAX_RDCU[golomb_par];
-	}
 
-	if (golomb_par > MAX_ICU_GOLOMB_PAR) {
+/**
+ * @brief get the maximum valid spill threshold value for a ICU SW compression
+ *	in diff or model mode
+ *
+ * @param cmp_par	compression parameter
+ *
+ * @returns the highest still valid spill threshold value for diff or model
+ *	mode compression; 0 if the cmp_par is not valid
+ */
+
+uint32_t cmp_icu_max_spill(unsigned int cmp_par)
+{
+	/* the ICU compressor can generate code words with a length of maximal 32 bits. */
+	unsigned int max_cw_bits = 32;
+	unsigned int cutoff = (1UL << (ilog_2(cmp_par)+1)) - cmp_par;
+	unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
+
+	if (!cmp_par || cmp_par > MAX_ICU_GOLOMB_PAR)
 		return 0;
-	} else {
-		/* the ICU compressor can generate code words with a length of
-		 * maximal 32 bits.
-		 */
-		unsigned int max_cw_bits = 32;
-		unsigned int cutoff = (1UL << (ilog_2(golomb_par)+1)) - golomb_par;
-		unsigned int max_n_sym_offset = max_cw_bits/2 - 1;
-
-		return (max_cw_bits-1-ilog_2(golomb_par))*golomb_par + cutoff -
-			max_n_sym_offset - 1;
-	}
+
+	return (max_cw_bits-1-ilog_2(cmp_par))*cmp_par + cutoff
+		- max_n_sym_offset - 1;
 }
 
 
@@ -465,13 +478,16 @@ int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 
+	if (!cfg)
+		return 0;
+
 	if (!cmp_data_type_valid(cfg->data_type)) {
 		debug_print("Error: selected compression data type is not supported.\n");
 		cfg_invalid++;
 	}
 
 	if (cfg->cmp_mode > CMP_MODE_STUFF) {
-		debug_print("Error: selected cmp_mode: %u is not supported\n.", cfg->cmp_mode);
+		debug_print("Error: selected cmp_mode: %u is not supported.\n", cfg->cmp_mode);
 		cfg_invalid++;
 	}
 
@@ -519,14 +535,21 @@ int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
 	if (cfg->samples == 0)
 		debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
 
-	if (cfg->icu_output_buf && cfg->buffer_length == 0 && cfg->samples != 0) {
-		debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n");
-		cfg_invalid++;
-	}
+	if (cfg->icu_output_buf) {
+		if (cfg->buffer_length == 0 && cfg->samples != 0) {
+			debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n");
+			cfg_invalid++;
+		}
 
-	if (cfg->icu_output_buf == cfg->input_buf) {
-		debug_print("Error: The compressed_data buffer is the same as the data_to_compress buffer.\n");
-		cfg_invalid++;
+		if (raw_mode_is_used(cfg->cmp_mode) && cfg->buffer_length < cfg->samples) {
+			debug_print("Error: The compressed_data_len_samples is to small to hold the data form the data_to_compress.\n");
+			cfg_invalid++;
+		}
+
+		if (cfg->icu_output_buf == cfg->input_buf) {
+			debug_print("Error: The compressed_data buffer is the same as the data_to_compress buffer.\n");
+			cfg_invalid++;
+		}
 	}
 
 	if (model_mode_is_used(cfg->cmp_mode)) {
@@ -558,16 +581,6 @@ int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
 		}
 	}
 
-	if (raw_mode_is_used(cfg->cmp_mode)) {
-		if (cfg->buffer_length < cfg->samples) {
-			debug_print("Error: The compressed_data_len_samples is to small to hold the data form the data_to_compress.\n");
-			cfg_invalid++;
-		}
-	} else {
-		if (cfg->samples < cfg->buffer_length/3)
-			debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended.This is probably unintended.\n");
-	}
-
 	if (cfg_invalid)
 		return 0;
 
@@ -589,7 +602,7 @@ int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
  */
 
 static int cmp_pars_are_valid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cmp_mode,
-			      enum cmp_data_type data_type, char *par_name)
+			      char *par_name)
 {
 	int cfg_invalid = 0;
 
@@ -622,9 +635,9 @@ static int cmp_pars_are_valid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cm
 				    par_name, spill, MIN_ICU_SPILL);
 			cfg_invalid++;
 		}
-		if (spill > get_max_spill(cmp_par, data_type)) {
+		if (spill > cmp_icu_max_spill(cmp_par)) {
 			debug_print("Error: The selected %s spillover threshold value: %u is too large for the selected %s compression parameter: %u, the largest possible spillover value in the selected compression mode is: %u.\n",
-				    par_name, spill, par_name, cmp_par, get_max_spill(cmp_par, data_type));
+				    par_name, spill, par_name, cmp_par, cmp_icu_max_spill(cmp_par));
 			cfg_invalid++;
 		}
 
@@ -658,20 +671,20 @@ int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg)
 		return 0;
 
 	if (!cmp_imagette_data_type_is_used(cfg->data_type)) {
-		debug_print("Error: The compression data type is not an imagette compression data type.!\n");
+		debug_print("Error: The compression data type is not an imagette compression data type!\n");
 		cfg_invalid++;
 	}
 
 	if (!cmp_pars_are_valid(cfg->golomb_par, cfg->spill, cfg->cmp_mode,
-				cfg->data_type, "imagette"))
+				"imagette"))
 		cfg_invalid++;
 
 	if (cmp_ap_imagette_data_type_is_used(cfg->data_type)) {
 		if (!cmp_pars_are_valid(cfg->ap1_golomb_par, cfg->ap1_spill,
-					cfg->cmp_mode, cfg->data_type, "adaptive 1 imagette"))
+					cfg->cmp_mode, "adaptive 1 imagette"))
 			cfg_invalid++;
 		if (!cmp_pars_are_valid(cfg->ap2_golomb_par, cfg->ap2_spill,
-					cfg->cmp_mode, cfg->data_type, "adaptive 2 imagette"))
+					cfg->cmp_mode, "adaptive 2 imagette"))
 			cfg_invalid++;
 	}
 
@@ -703,7 +716,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 	/* flux parameter is needed for every fx_cob data_type */
-	if (!cmp_pars_are_valid(cfg->cmp_par_fx, cfg->spill_fx, cfg->cmp_mode, cfg->data_type, "flux"))
+	if (!cmp_pars_are_valid(cfg->cmp_par_fx, cfg->spill_fx, cfg->cmp_mode, "flux"))
 		cfg_invalid++;
 
 	switch (cfg->data_type) {
@@ -763,15 +776,20 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		break;
 	}
 
-	if (check_exp_flags && !cmp_pars_are_valid(cfg->cmp_par_exp_flags, cfg->spill_exp_flags, cfg->cmp_mode, cfg->data_type, "exposure flags"))
+	if (check_exp_flags && !cmp_pars_are_valid(cfg->cmp_par_exp_flags,
+			cfg->spill_exp_flags, cfg->cmp_mode, "exposure flags"))
 		cfg_invalid++;
-	if (check_ncob && !cmp_pars_are_valid(cfg->cmp_par_ncob, cfg->spill_ncob, cfg->cmp_mode, cfg->data_type, "center of brightness"))
+	if (check_ncob && !cmp_pars_are_valid(cfg->cmp_par_ncob, cfg->spill_ncob,
+			cfg->cmp_mode, "center of brightness"))
 		cfg_invalid++;
-	if (check_efx && !cmp_pars_are_valid(cfg->cmp_par_efx, cfg->spill_efx, cfg->cmp_mode, cfg->data_type, "extended flux"))
+	if (check_efx && !cmp_pars_are_valid(cfg->cmp_par_efx, cfg->spill_efx,
+			cfg->cmp_mode, "extended flux"))
 		cfg_invalid++;
-	if (check_ecob && !cmp_pars_are_valid(cfg->cmp_par_ecob, cfg->spill_ecob, cfg->cmp_mode, cfg->data_type, "extended center of brightness"))
+	if (check_ecob && !cmp_pars_are_valid(cfg->cmp_par_ecob, cfg->spill_ecob,
+			cfg->cmp_mode, "extended center of brightness"))
 		cfg_invalid++;
-	if (check_var && !cmp_pars_are_valid(cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, cfg->cmp_mode, cfg->data_type, "flux COB varianc"))
+	if (check_var && !cmp_pars_are_valid(cfg->cmp_par_fx_cob_variance,
+			cfg->spill_fx_cob_variance, cfg->cmp_mode, "flux COB varianc"))
 		cfg_invalid++;
 
 	if (cfg_invalid)
@@ -787,6 +805,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compressor configuration
  *
  * @returns 1 if the auxiliary science specific parameters are valid, otherwise 0
+ * TODO: implemented DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND
  */
 
 int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
@@ -801,12 +820,16 @@ int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (!cmp_pars_are_valid(cfg->cmp_par_mean, cfg->spill_mean, cfg->cmp_mode, cfg->data_type, "mean"))
+	if (!cmp_pars_are_valid(cfg->cmp_par_mean, cfg->spill_mean,
+				cfg->cmp_mode, "mean"))
 		cfg_invalid++;
-	if (!cmp_pars_are_valid(cfg->cmp_par_variance, cfg->spill_variance, cfg->cmp_mode, cfg->data_type, "variance"))
+	if (!cmp_pars_are_valid(cfg->cmp_par_variance, cfg->spill_variance,
+				cfg->cmp_mode, "variance"))
 		cfg_invalid++;
-	if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET)
-		if (!cmp_pars_are_valid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error, cfg->cmp_mode, cfg->data_type, "outlier pixls num"))
+	/* if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET) */
+	if (cfg->data_type != DATA_TYPE_OFFSET)
+		if (!cmp_pars_are_valid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+					cfg->cmp_mode, "outlier pixls num"))
 			cfg_invalid++;
 
 	if (cfg_invalid)
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index 35f938a..d2c46ce 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -1,11 +1,1151 @@
+#include "cmp_support.h"
 #include <string.h>
 #include <stdlib.h>
+#if defined __has_include
+#  if __has_include(<time.h>)
+#    include <time.h>
+#    include <unistd.h>
+#    define HAS_TIME_H 1
+#  endif
+#endif
 
 #include "unity.h"
+#include "cmp_icu.h"
+#include "../lib/cmp_icu.c" /* this is a hack to test static functions */
 
-#include "cmp_support.h"
-/* this is a hack to test static functions */
-#include "../lib/cmp_icu.c"
+/* TODO: test compression with samples = 0 and buffer_length = 0; */
+
+/**
+ * @brief  Seeds the pseudo-random number generator used by rand()
+ */
+
+void setUp(void)
+{
+	unsigned int seed;
+	static int n;
+
+#if HAS_TIME_H
+	seed = time(NULL) * getpid();
+#else
+	seed = 1;
+#endif
+
+	if (!n) {
+		n++;
+		srand(seed);
+		printf("seed: %u\n", seed);
+	}
+}
+
+
+/**
+ * @brief generate a random number
+ *
+ * @param min minimum value
+ * @param max maximum value
+ *
+ * @returns "random" numbers in the range [M, N]
+ *
+ * @see https://c-faq.com/lib/randrange.html
+ */
+
+int random_range(unsigned int min, unsigned int max)
+{
+	if (min > max)
+		TEST_ASSERT(0);
+	if (max-min > RAND_MAX)
+		TEST_ASSERT(0);
+	return min + rand() / (RAND_MAX / (max - min + 1) + 1);
+}
+
+
+/**
+ * @test cmp_cfg_icu_create
+ */
+
+void test_cmp_cfg_icu_create(void)
+{
+	struct cmp_cfg cfg;
+	enum cmp_data_type data_type;
+	enum cmp_mode cmp_mode;
+	uint32_t model_value, lossy_par;
+	/* TODO: change that when DATA_TYPE_BACKGROUND and
+	 * DATA_TYPE_F_CAM_BACKGROUND are implemented */
+	const enum cmp_data_type biggest_data_type = DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE;
+
+	/* wrong data type tests */
+	data_type = DATA_TYPE_UNKNOWN; /* not valid data type */
+	cmp_mode = CMP_MODE_RAW;
+	model_value = 0;
+	lossy_par = CMP_LOSSLESS;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+	memset(&cfg, 0, sizeof(cfg));
+
+	data_type = biggest_data_type + 1; /* not valid data type */
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+	memset(&cfg, 0, sizeof(cfg));
+
+	data_type = biggest_data_type;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(biggest_data_type, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(CMP_MODE_RAW, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(0, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(0, cfg.round);
+	memset(&cfg, 0, sizeof(cfg));
+
+	/* this should work */
+	data_type = DATA_TYPE_IMAGETTE;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_IMAGETTE, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(CMP_MODE_RAW, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(0, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(0, cfg.round);
+	memset(&cfg, 0, sizeof(cfg));
+
+	/* wrong compression mode tests */
+	cmp_mode = CMP_MODE_STUFF + 1;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+	memset(&cfg, 0, sizeof(cfg));
+
+	cmp_mode = -1;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+	memset(&cfg, 0, sizeof(cfg));
+
+	/* this should work */
+	cmp_mode = CMP_MODE_STUFF;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_IMAGETTE, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(CMP_MODE_STUFF, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(0, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(0, cfg.round);
+	memset(&cfg, 0, sizeof(cfg));
+
+	/* wrong model_value tests */
+	cmp_mode = CMP_MODE_MODEL_MULTI; /* model value checks only active on model mode */
+	model_value = MAX_MODEL_VALUE + 1;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+
+	model_value = -1U;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+
+	/* this should work */
+	model_value = MAX_MODEL_VALUE;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_IMAGETTE, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(CMP_MODE_MODEL_MULTI, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(16, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(0, cfg.round);
+
+	/* no checks for model mode -> no model cmp_mode */
+	cmp_mode = CMP_MODE_STUFF;
+	model_value = MAX_MODEL_VALUE + 1;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_IMAGETTE, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(CMP_MODE_STUFF, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(MAX_MODEL_VALUE + 1, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(0, cfg.round);
+	model_value = MAX_MODEL_VALUE;
+
+	/* wrong lossy_par tests */
+	lossy_par = MAX_ICU_ROUND + 1;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+
+	lossy_par = -1U;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type);
+
+	/* this should work */
+	lossy_par = MAX_ICU_ROUND;
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(DATA_TYPE_IMAGETTE, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(CMP_MODE_STUFF, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(16, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(3, cfg.round);
+
+	/* random test */
+	data_type = random_range(DATA_TYPE_IMAGETTE, biggest_data_type);
+	cmp_mode = random_range(CMP_MODE_RAW, CMP_MODE_STUFF);
+	model_value = random_range(0, MAX_MODEL_VALUE);
+	lossy_par = random_range(CMP_LOSSLESS, MAX_ICU_ROUND);
+	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
+	TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
+	TEST_ASSERT_EQUAL_INT(cmp_mode, cfg.cmp_mode);
+	TEST_ASSERT_EQUAL_INT(model_value, cfg.model_value);
+	TEST_ASSERT_EQUAL_INT(lossy_par, cfg.round);
+}
+
+
+/**
+ * @test cmp_cfg_icu_buffers
+ */
+
+void test_cmp_cfg_icu_buffers(void)
+{
+	struct cmp_cfg cfg;
+	void *data_to_compress;
+	uint32_t data_samples;
+	void *model_of_data;
+	void *updated_model;
+	uint32_t *compressed_data;
+	uint32_t compressed_data_len_samples;
+	size_t s;
+	uint16_t ima_data[4] = {42, 23, 0, 0xFFFF};
+	uint16_t ima_model[4] = {0xC, 0xA, 0xFF, 0xE};
+	uint16_t ima_up_model[4] = {0};
+	uint32_t cmp_data[2] = {0};
+
+	/* error case: unknown  data_type */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_UNKNOWN, CMP_MODE_DIFF_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	data_samples = 4;
+	model_of_data = NULL;
+	updated_model = NULL;
+	compressed_data = cmp_data;
+	compressed_data_len_samples = 4;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* error case: no data test */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_DIFF_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = NULL; /* no data set */
+	data_samples = 4;
+	model_of_data = NULL;
+	updated_model = NULL;
+	compressed_data = cmp_data;
+	compressed_data_len_samples = 4;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* now its should work */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_DIFF_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(8, s);
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(NULL, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.samples);
+	TEST_ASSERT_EQUAL(NULL, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(cmp_data, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.buffer_length);
+
+	/* error case: model mode and no model */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	model_of_data = NULL;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* now its should work */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	model_of_data = ima_model;
+	updated_model = ima_model;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(8, s);
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(ima_model, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.samples);
+	TEST_ASSERT_EQUAL(ima_model, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(cmp_data, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.buffer_length);
+
+	/* error case: data == model */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	model_of_data = ima_data;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* error case: data == compressed_data */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	model_of_data = ima_model;
+	compressed_data = (void *)ima_data;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* error case: data == updated_model */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	model_of_data = ima_model;
+	updated_model = ima_data;
+	compressed_data = (void *)ima_data;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* error case: model == compressed_data */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	model_of_data = ima_model;
+	compressed_data = (void *)ima_model;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* error case: updated_model == compressed_data */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	model_of_data = ima_model;
+	updated_model = ima_up_model;
+	compressed_data = (void *)ima_up_model;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* warning case: samples = 0 */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_to_compress = ima_data;
+	data_samples = 0;
+	model_of_data = ima_model;
+	updated_model = ima_up_model;
+	compressed_data = cmp_data;
+	compressed_data_len_samples = 4;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(8, s);
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(ima_model, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(0, cfg.samples);
+	TEST_ASSERT_EQUAL(ima_up_model, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(cmp_data, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.buffer_length);
+	memset(&cfg, 0, sizeof(cfg));
+
+	/* error case: compressed_data_len_samples = 0 */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_samples = 4;
+	compressed_data_len_samples = 0;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* this should now work */
+	/* if data_samples = 0 -> compressed_data_len_samples = 0 is allowed */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_samples = 0;
+	compressed_data_len_samples = 0;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s); /* not an error, it is the size of the compressed data */
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(ima_model, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(0, cfg.samples);
+	TEST_ASSERT_EQUAL(ima_up_model, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(cmp_data, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(0, cfg.buffer_length);
+
+	/* this should now work */
+	/* if compressed_data = NULL -> compressed_data_len_samples = 0 is allowed */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	data_samples = 4;
+	compressed_data = NULL;
+	compressed_data_len_samples = 0;
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s); /* not an error, it is the size of the compressed data */
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(ima_model, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.samples);
+	TEST_ASSERT_EQUAL(ima_up_model, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(NULL, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(0, cfg.buffer_length);
+
+	/* error case: RAW mode compressed_data smaller than data_samples */
+	compressed_data = cmp_data;
+	compressed_data_len_samples = 3;
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+
+	/* this should now work */
+	compressed_data = NULL;
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(6, s);
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(ima_model, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.samples);
+	TEST_ASSERT_EQUAL(ima_up_model, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(NULL, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(3, cfg.buffer_length);
+
+	/* this should also now work */
+	compressed_data = cmp_data;
+	compressed_data_len_samples = 4;
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(8, s);
+	TEST_ASSERT_EQUAL(ima_data, cfg.input_buf);
+	TEST_ASSERT_EQUAL_INT(ima_model, cfg.model_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.samples);
+	TEST_ASSERT_EQUAL(ima_up_model, cfg.icu_new_model_buf);
+	TEST_ASSERT_EQUAL(cmp_data, cfg.icu_output_buf);
+	TEST_ASSERT_EQUAL_INT(4, cfg.buffer_length);
+
+	/* error case: cfg = NULL */
+	s = cmp_cfg_icu_buffers(NULL, data_to_compress, data_samples,
+				model_of_data, updated_model, compressed_data,
+				compressed_data_len_samples);
+	TEST_ASSERT_EQUAL_size_t(0, s);
+}
+
+
+/**
+ * @test cmp_cfg_icu_imagette
+ */
+
+void test_cmp_cfg_icu_imagette(void)
+{
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par;
+	uint32_t spillover_par;
+	enum cmp_data_type data_type;
+
+	int error;
+
+	/* lowest values 1d/model mode */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 0, CMP_LOSSLESS);
+	cmp_par = MIN_ICU_GOLOMB_PAR;
+	spillover_par = MIN_ICU_SPILL;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 1);
+	TEST_ASSERT_EQUAL_INT(cfg.spill, 2);
+
+	/* highest values 1d/model mode */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_IMAGETTE, CMP_MODE_DIFF_MULTI, 16, CMP_LOSSLESS);
+	cmp_par = MAX_ICU_GOLOMB_PAR;
+	spillover_par = cmp_icu_max_spill(cmp_par);
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 0xFFFF);
+	TEST_ASSERT_EQUAL_INT(cfg.spill, 1048545);
+
+	/* wrong data type  test */
+	for (data_type = 0; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) {
+		cfg = cmp_cfg_icu_create(data_type, CMP_MODE_DIFF_MULTI, 16, CMP_LOSSLESS);
+		error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+		if (data_type == DATA_TYPE_IMAGETTE ||
+		    data_type == DATA_TYPE_SAT_IMAGETTE ||
+		    data_type == DATA_TYPE_F_CAM_IMAGETTE) {
+			TEST_ASSERT_FALSE(error);
+			TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
+			TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 0xFFFF);
+			TEST_ASSERT_EQUAL_INT(cfg.spill, 1048545);
+		} else {
+			TEST_ASSERT_TRUE(error);
+		}
+	}
+
+	/* model/1d MODE tests */
+
+	/* cmp_par to big */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_MULTI, 16, CMP_LOSSLESS);
+	cmp_par = MAX_ICU_GOLOMB_PAR + 1;
+	spillover_par = MIN_ICU_SPILL;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+	/* ignore in RAW MODE */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+
+	/* cmp_par to small */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_MULTI, 16, CMP_LOSSLESS);
+	cmp_par = MIN_ICU_GOLOMB_PAR - 1;
+	spillover_par = MIN_ICU_SPILL;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+	/* ignore in RAW MODE */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+
+	/* spillover_par to big */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_MULTI, 16, CMP_LOSSLESS);
+	cmp_par = MIN_ICU_GOLOMB_PAR;
+	spillover_par = cmp_icu_max_spill(cmp_par)+1;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+	/* ignore in RAW MODE */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+
+	/* spillover_par to small */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	cmp_par = MAX_ICU_GOLOMB_PAR;
+	spillover_par = MIN_ICU_SPILL -1 ;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+	/* ignore in RAW MODE */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 16, CMP_LOSSLESS);
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+
+	/* CMP_MODE_STUFF tests */
+	spillover_par = ~0; /* is ignored */
+
+	/* highest values STUFF MODE */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_STUFF, ~0, CMP_LOSSLESS);
+	cmp_par = MAX_STUFF_CMP_PAR;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 32);
+
+	/* lowest values STUFF MODE */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_STUFF, ~0, CMP_LOSSLESS);
+	cmp_par = 0;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 0);
+
+	/* cmp_par to big */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_SAT_IMAGETTE, CMP_MODE_STUFF, ~0, CMP_LOSSLESS);
+	cmp_par = MAX_STUFF_CMP_PAR+1;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+
+	/* cfg = NULL test*/
+	error = cmp_cfg_icu_imagette(NULL, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+
+	/* invalid compression mode  test*/
+	cfg = cmp_cfg_icu_create(DATA_TYPE_SAT_IMAGETTE, CMP_MODE_STUFF+1, ~0, CMP_LOSSLESS);
+	cmp_par = MAX_STUFF_CMP_PAR+1;
+	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
+	TEST_ASSERT_TRUE(error);
+}
+
+
+/**
+ * @test cmp_cfg_fx_cob
+ */
+
+void test_cmp_cfg_fx_cob(void)
+{
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = 2;
+	uint32_t spillover_exp_flags = 2;
+	uint32_t cmp_par_fx = 2;
+	uint32_t spillover_fx = 2;
+	uint32_t cmp_par_ncob = 2;
+	uint32_t spillover_ncob = 2;
+	uint32_t cmp_par_efx = 2;
+	uint32_t spillover_efx = 2;
+	uint32_t cmp_par_ecob = 2;
+	uint32_t spillover_ecob = 2;
+	uint32_t cmp_par_fx_cob_variance = 2;
+	uint32_t spillover_fx_cob_variance = 2;
+	int error;
+	enum cmp_data_type data_type;
+
+
+	/* wrong data type test */
+	for (data_type = 0; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) {
+		cfg = cmp_cfg_icu_create(data_type, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+		error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+				       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+				       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+				       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+		if (data_type == DATA_TYPE_S_FX ||
+		    data_type == DATA_TYPE_S_FX_DFX ||
+		    data_type == DATA_TYPE_S_FX_NCOB ||
+		    data_type == DATA_TYPE_S_FX_DFX_NCOB_ECOB ||
+		    data_type == DATA_TYPE_L_FX ||
+		    data_type == DATA_TYPE_L_FX_DFX ||
+		    data_type == DATA_TYPE_L_FX_NCOB ||
+		    data_type == DATA_TYPE_L_FX_DFX_NCOB_ECOB ||
+		    data_type == DATA_TYPE_F_FX ||
+		    data_type == DATA_TYPE_F_FX_DFX ||
+		    data_type == DATA_TYPE_F_FX_NCOB ||
+		    data_type == DATA_TYPE_F_FX_DFX_NCOB_ECOB) {
+			TEST_ASSERT_FALSE(error);
+			TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_fx);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_fx);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_exp_flags);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_exp_flags);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_efx);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_efx);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_ncob);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_ncob);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_ecob);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_ecob);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_fx_cob_variance);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_fx_cob_variance);
+		} else {
+			TEST_ASSERT_TRUE(error);
+		}
+	}
+
+	/* cfg == NULL test */
+	error = cmp_cfg_fx_cob(NULL, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+	/* test DATA_TYPE_S_FX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = ~0; /* invalid parameter */
+	spillover_ncob = ~0; /* invalid parameter */
+	cmp_par_efx = ~0; /* invalid parameter */
+	spillover_efx = ~0; /* invalid parameter */
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+
+	/* invalid spillover_exp_flags parameter */
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags)+1;
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+	/* invalid cmp_par_fx parameter */
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR - 1;
+	spillover_fx = MIN_ICU_SPILL;
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* test DATA_TYPE_S_FX_DFX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_DFX, CMP_MODE_MODEL_ZERO, 0, 1);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = ~0; /* invalid parameter */
+	spillover_ncob = ~0; /* invalid parameter */
+	cmp_par_efx = 23;
+	spillover_efx = 42;
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_efx, cfg.cmp_par_efx);
+	TEST_ASSERT_EQUAL_INT(spillover_efx, cfg.spill_efx);
+
+	/* invalid spillover_efx parameter */
+	spillover_efx = 0;
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* test DATA_TYPE_S_FX_NCOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_NCOB, CMP_MODE_MODEL_ZERO, 0, 1);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = 19;
+	spillover_ncob = 5;
+	cmp_par_efx = ~0; /* invalid parameter */
+	spillover_efx = ~0; /* invalid parameter */
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ncob, cfg.cmp_par_ncob);
+	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
+
+	/* invalid cmp_par_ncob parameter */
+	cmp_par_ncob = 0;
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* test DATA_TYPE_S_FX_DFX_NCOB_ECOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_DFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = 19;
+	spillover_ncob = 5;
+	cmp_par_efx = 23;
+	spillover_efx = 42;
+	cmp_par_ecob = MAX_ICU_GOLOMB_PAR;
+	spillover_ecob = MIN_ICU_SPILL;
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ncob, cfg.cmp_par_ncob);
+	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
+	TEST_ASSERT_EQUAL_INT(cmp_par_efx, cfg.cmp_par_efx);
+	TEST_ASSERT_EQUAL_INT(spillover_efx, cfg.spill_efx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ecob, cfg.cmp_par_ecob);
+	TEST_ASSERT_EQUAL_INT(spillover_ecob, cfg.spill_ecob);
+
+	/* invalid cmp_par_ecob parameter */
+	cmp_par_ecob = -1U;
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* DATA_TYPE_L_FX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = ~0; /* invalid parameter */
+	spillover_ncob = ~0; /* invalid parameter */
+	cmp_par_efx = ~0; /* invalid parameter */
+	spillover_efx = ~0; /* invalid parameter */
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = 30;
+	spillover_fx_cob_variance = 8;
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx_cob_variance, cfg.cmp_par_fx_cob_variance);
+	TEST_ASSERT_EQUAL_INT(spillover_fx_cob_variance, cfg.spill_fx_cob_variance);
+
+	/* invalid spillover_fx_cob_variance parameter */
+	spillover_fx_cob_variance = 1;
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* DATA_TYPE_L_FX_DFX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_DFX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = ~0; /* invalid parameter */
+	spillover_ncob = ~0; /* invalid parameter */
+	cmp_par_efx = 23;
+	spillover_efx = 42;
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = 30;
+	spillover_fx_cob_variance = 8;
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_efx, cfg.cmp_par_efx);
+	TEST_ASSERT_EQUAL_INT(spillover_efx, cfg.spill_efx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx_cob_variance, cfg.cmp_par_fx_cob_variance);
+	TEST_ASSERT_EQUAL_INT(spillover_fx_cob_variance, cfg.spill_fx_cob_variance);
+
+
+	/* DATA_TYPE_L_FX_NCOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_NCOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = 19;
+	spillover_ncob = 5;
+	cmp_par_efx = ~0; /* invalid parameter */
+	spillover_efx = ~0; /* invalid parameter */
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = 30;
+	spillover_fx_cob_variance = 8;
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ncob, cfg.cmp_par_ncob);
+	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx_cob_variance, cfg.cmp_par_fx_cob_variance);
+	TEST_ASSERT_EQUAL_INT(spillover_fx_cob_variance, cfg.spill_fx_cob_variance);
+
+
+	/* DATA_TYPE_L_FX_DFX_NCOB_ECOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_DFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = 19;
+	spillover_ncob = 5;
+	cmp_par_efx = 23;
+	spillover_efx = 42;
+	cmp_par_ecob = MAX_ICU_GOLOMB_PAR;
+	spillover_ecob = MIN_ICU_SPILL;
+	cmp_par_fx_cob_variance = 30;
+	spillover_fx_cob_variance = 8;
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_exp_flags, cfg.cmp_par_exp_flags);
+	TEST_ASSERT_EQUAL_INT(spillover_exp_flags, cfg.spill_exp_flags);
+	TEST_ASSERT_EQUAL_INT(cmp_par_efx, cfg.cmp_par_efx);
+	TEST_ASSERT_EQUAL_INT(spillover_efx, cfg.spill_efx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ncob, cfg.cmp_par_ncob);
+	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ecob, cfg.cmp_par_ecob);
+	TEST_ASSERT_EQUAL_INT(spillover_ecob, cfg.spill_ecob);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx_cob_variance, cfg.cmp_par_fx_cob_variance);
+	TEST_ASSERT_EQUAL_INT(spillover_fx_cob_variance, cfg.spill_fx_cob_variance);
+
+
+	/* DATA_TYPE_F_FX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = ~0; /* invalid parameter */
+	spillover_exp_flags = ~0; /* invalid parameter */
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = ~0; /* invalid parameter */
+	spillover_ncob = ~0; /* invalid parameter */
+	cmp_par_efx = ~0; /* invalid parameter */
+	spillover_efx = ~0; /* invalid parameter */
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+
+
+	/* DATA_TYPE_F_FX_DFX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_DFX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = ~0; /* invalid parameter */
+	spillover_exp_flags = ~0; /* invalid parameter */
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = ~0; /* invalid parameter */
+	spillover_ncob = ~0; /* invalid parameter */
+	cmp_par_efx = 23;
+	spillover_efx = 42;
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_efx, cfg.cmp_par_efx);
+	TEST_ASSERT_EQUAL_INT(spillover_efx, cfg.spill_efx);
+
+
+	/* DATA_TYPE_F_FX_NCOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_NCOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = ~0; /* invalid parameter */
+	spillover_exp_flags = ~0; /* invalid parameter */
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = MIN_ICU_GOLOMB_PAR;
+	spillover_ncob = cmp_icu_max_spill(cmp_par_ncob);
+	cmp_par_efx = ~0; /* invalid parameter */
+	spillover_efx = ~0; /* invalid parameter */
+	cmp_par_ecob = ~0; /* invalid parameter */
+	spillover_ecob = ~0; /* invalid parameter */
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ncob, cfg.cmp_par_ncob);
+	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
+
+
+	/* DATA_TYPE_F_FX_DFX_NCOB_ECOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_DFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_exp_flags = ~0; /* invalid parameter */
+	spillover_exp_flags = ~0; /* invalid parameter */
+	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
+	spillover_fx = MIN_ICU_SPILL;
+	cmp_par_ncob = MIN_ICU_GOLOMB_PAR;
+	spillover_ncob = cmp_icu_max_spill(cmp_par_ncob);
+	cmp_par_efx = 23;
+	spillover_efx = 42;
+	cmp_par_ecob = MAX_ICU_GOLOMB_PAR;
+	spillover_ecob = MIN_ICU_SPILL;
+	cmp_par_fx_cob_variance = ~0; /* invalid parameter */
+	spillover_fx_cob_variance = ~0; /* invalid parameter */
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(cmp_par_fx, cfg.cmp_par_fx);
+	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ncob, cfg.cmp_par_ncob);
+	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
+	TEST_ASSERT_EQUAL_INT(cmp_par_efx, cfg.cmp_par_efx);
+	TEST_ASSERT_EQUAL_INT(spillover_efx, cfg.spill_efx);
+	TEST_ASSERT_EQUAL_INT(cmp_par_ecob, cfg.cmp_par_ecob);
+	TEST_ASSERT_EQUAL_INT(spillover_ecob, cfg.spill_ecob);
+}
+
+/**
+ * @test cmp_cfg_aux
+ */
+
+void test_cmp_cfg_aux(void)
+{	struct cmp_cfg cfg;
+	uint32_t cmp_par_mean = 2;
+	uint32_t spillover_mean = 2;
+	uint32_t cmp_par_variance = 2;
+	uint32_t spillover_variance = 2;
+	uint32_t cmp_par_pixels_error = 2;
+	uint32_t spillover_pixels_error = 2;
+	int error;
+	enum cmp_data_type data_type;
+
+	/* wrong data type test */
+	for (data_type = 0; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) {
+		cfg = cmp_cfg_icu_create(data_type, CMP_MODE_MODEL_ZERO, 16, CMP_LOSSLESS);
+		error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+				    cmp_par_variance, spillover_variance,
+				    cmp_par_pixels_error, spillover_pixels_error);
+		if (data_type == DATA_TYPE_OFFSET ||
+		    data_type == DATA_TYPE_BACKGROUND ||
+		    data_type == DATA_TYPE_SMEARING
+		    /* data_type == DATA_TYPE_F_CAM_OFFSET || */
+		    /* data_type == DATA_TYPE_F_CAM_BACKGROUND */
+		    ) {
+			TEST_ASSERT_FALSE(error);
+			TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_mean);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_mean);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_variance);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_variance);
+			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_pixels_error);
+			TEST_ASSERT_EQUAL_INT(2, cfg.spill_pixels_error);
+		} else {
+			TEST_ASSERT_TRUE(error);
+		}
+	}
+
+	/* cfg == NULL test */
+	error = cmp_cfg_aux(NULL, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* DATA_TYPE_OFFSET */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_OFFSET, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_mean = MIN_ICU_GOLOMB_PAR;
+	spillover_mean = cmp_icu_max_spill(MIN_ICU_GOLOMB_PAR);
+	cmp_par_variance = MIN_ICU_GOLOMB_PAR;
+	spillover_variance = MIN_ICU_SPILL;
+	cmp_par_pixels_error = ~0;
+	spillover_pixels_error = ~0;
+
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(MIN_ICU_GOLOMB_PAR, cfg.cmp_par_mean);
+	TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MIN_ICU_GOLOMB_PAR), cfg.spill_mean);
+	TEST_ASSERT_EQUAL_INT(MIN_ICU_GOLOMB_PAR, cfg.cmp_par_variance);
+	TEST_ASSERT_EQUAL_INT(2, cfg.spill_variance);
+
+	/* This should fail */
+	cmp_par_mean = MIN_ICU_GOLOMB_PAR-1;
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* DATA_TYPE_BACKGROUND */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_BACKGROUND, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_mean = MAX_ICU_GOLOMB_PAR;
+	spillover_mean = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	cmp_par_variance = MIN_ICU_GOLOMB_PAR;
+	spillover_variance = MIN_ICU_SPILL;
+	cmp_par_pixels_error = 42;
+	spillover_pixels_error = 23;
+
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(MAX_ICU_GOLOMB_PAR, cfg.cmp_par_mean);
+	TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR), cfg.spill_mean);
+	TEST_ASSERT_EQUAL_INT(MIN_ICU_GOLOMB_PAR, cfg.cmp_par_variance);
+	TEST_ASSERT_EQUAL_INT(MIN_ICU_SPILL, cfg.spill_variance);
+	TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_pixels_error);
+	TEST_ASSERT_EQUAL_INT(23, cfg.spill_pixels_error);
+
+	/* This should fail */
+	cmp_par_variance = MIN_ICU_GOLOMB_PAR-1;
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_TRUE(error);
+
+
+	/* DATA_TYPE_SMEARING */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_SMEARING, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	cmp_par_mean = MAX_ICU_GOLOMB_PAR;
+	spillover_mean = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	cmp_par_variance = MIN_ICU_GOLOMB_PAR;
+	spillover_variance = MIN_ICU_SPILL;
+	cmp_par_pixels_error = 42;
+	spillover_pixels_error = 23;
+
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL_INT(MAX_ICU_GOLOMB_PAR, cfg.cmp_par_mean);
+	TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR), cfg.spill_mean);
+	TEST_ASSERT_EQUAL_INT(MIN_ICU_GOLOMB_PAR, cfg.cmp_par_variance);
+	TEST_ASSERT_EQUAL_INT(MIN_ICU_SPILL, cfg.spill_variance);
+	TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_pixels_error);
+	TEST_ASSERT_EQUAL_INT(23, cfg.spill_pixels_error);
+
+	/* This should fail */
+	spillover_pixels_error = cmp_icu_max_spill(42)+1;
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_TRUE(error);
+
+#if 0
+TODO: implemented F_CAM DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND
+	/* DATA_TYPE_F_CAM_OFFSET */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_OFFSET, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	/* DATA_TYPE_F_CAM_BACKGROUND */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_BACKGROUND, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+#endif
+}
 
 
 /**
@@ -518,6 +1658,7 @@ void test_put_n_bits32(void)
 void test_rice_encoder(void)
 {
 	uint32_t value, g_par, log2_g_par, cw, cw_len;
+	const uint32_t MAX_GOLOMB_PAR = 0x80000000;
 
 	/* test minimum Golomb parameter */
 	value = 0; log2_g_par = (uint32_t)ilog_2(MIN_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
@@ -557,7 +1698,7 @@ void test_rice_encoder(void)
 	TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw);
 
 	/* test maximum Golomb parameter for rice_encoder */
-	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_ICU_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
+	value = 0; log2_g_par = (uint32_t)ilog_2(MAX_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U;
 	cw_len = rice_encoder(value, g_par, log2_g_par, &cw);
 	TEST_ASSERT_EQUAL_INT(32, cw_len);
 	TEST_ASSERT_EQUAL_HEX(0x0, cw);
@@ -583,9 +1724,10 @@ void test_rice_encoder(void)
  * @test golomb_encoder
  */
 
-void test_Golomb_encoder(void)
+void test_golomb_encoder(void)
 {
 	uint32_t value, g_par, log2_g_par, cw, cw_len;
+	const uint32_t MAX_GOLOMB_PAR = 0x80000000;
 
 	/* test minimum Golomb parameter */
 	value = 0; g_par = MIN_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
@@ -659,12 +1801,12 @@ void test_Golomb_encoder(void)
 
 
 	/* test maximum Golomb parameter for golomb_encoder */
-	value = 0; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	value = 0; g_par = MAX_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
 	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
 	TEST_ASSERT_EQUAL_INT(32, cw_len);
 	TEST_ASSERT_EQUAL_HEX(0x0, cw);
 
-	value = 1; g_par = MAX_ICU_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
+	value = 1; g_par = MAX_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U;
 	cw_len = golomb_encoder(value, g_par, log2_g_par, &cw);
 	TEST_ASSERT_EQUAL_INT(32, cw_len);
 	TEST_ASSERT_EQUAL_HEX(0x1, cw);
@@ -1010,6 +2152,7 @@ void test_encode_value(void)
 
 /**
  * @test cmp_get_max_used_bits
+ * TODO: move this test
  */
 
 void test_cmp_get_max_used_bits(void)
@@ -1058,6 +2201,188 @@ void test_cmp_get_max_used_bits(void)
 }
 
 
+/**
+ * @test configure_encoder_setup
+ */
+
+void test_configure_encoder_setup(void)
+{
+	struct encoder_setupt setup;
+	uint32_t cmp_par;
+	uint32_t spillover;
+	uint32_t lossy_par;
+	uint32_t max_data_bits;
+	struct cmp_cfg cfg;
+	int error;
+
+	/* test Golomb encoder zero escape mechanism */
+	cmp_par = 42;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 15;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_ZERO;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL(golomb_encoder, setup.generate_cw_f); /* pointer to the code word encoder */
+	TEST_ASSERT_EQUAL(encode_value_zero, setup.encode_method_f); /* pointer to the encoding function */
+	TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */
+	TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */
+	TEST_ASSERT_EQUAL_INT(42, setup.encoder_par1); /* encoding parameter 1 */
+	TEST_ASSERT_EQUAL_INT(5, setup.encoder_par2); /* encoding parameter 2 */
+	TEST_ASSERT_EQUAL_INT(23, setup.spillover_par); /* outlier parameter */
+	TEST_ASSERT_EQUAL_INT(0, setup.lossy_par); /* lossy compression parameter */
+	TEST_ASSERT_EQUAL_INT(15, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */
+	memset(&setup, 0, sizeof(setup));
+
+	/* test Rice encoder multi escape mechanism */
+	cmp_par = 32;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 32;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_MULTI;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL(rice_encoder, setup.generate_cw_f); /* pointer to the code word encoder */
+	TEST_ASSERT_EQUAL(encode_value_multi, setup.encode_method_f); /* pointer to the encoding function */
+	TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */
+	TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */
+	TEST_ASSERT_EQUAL_INT(32, setup.encoder_par1); /* encoding parameter 1 */
+	TEST_ASSERT_EQUAL_INT(5, setup.encoder_par2); /* encoding parameter 2 */
+	TEST_ASSERT_EQUAL_INT(23, setup.spillover_par); /* outlier parameter */
+	TEST_ASSERT_EQUAL_INT(0, setup.lossy_par); /* lossy compression parameter */
+	TEST_ASSERT_EQUAL_INT(32, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */
+	memset(&setup, 0, sizeof(setup));
+
+	/* test CMP_MODE_STUFF */
+	cmp_par = 32;
+	spillover = ~0;
+	lossy_par = 1;
+	max_data_bits = 32;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_STUFF;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL(NULL, setup.generate_cw_f); /* pointer to the code word encoder */
+	TEST_ASSERT_EQUAL(encode_value_none, setup.encode_method_f); /* pointer to the encoding function */
+	TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */
+	TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */
+	TEST_ASSERT_EQUAL_INT(32, setup.encoder_par1); /* encoding parameter 1 */
+	TEST_ASSERT_EQUAL_INT(0, setup.encoder_par2); /* encoding parameter 2 */
+	TEST_ASSERT_EQUAL_INT(0, setup.spillover_par); /* outlier parameter */
+	TEST_ASSERT_EQUAL_INT(1, setup.lossy_par); /* lossy compression parameter */
+	TEST_ASSERT_EQUAL_INT(32, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */
+	memset(&setup, 0, sizeof(setup));
+
+	/* test max_used_bits = 33 */
+	cmp_par = 32;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 33;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_MULTI;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_TRUE(error);
+	memset(&setup, 0, sizeof(setup));
+
+	/* cmp_par = 0 test */
+	cmp_par = 0;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 32;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_MULTI;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_TRUE(error);
+	memset(&setup, 0, sizeof(setup));
+
+	/* cmp_par = 0 test STUFF MODE this should work*/
+	cmp_par = 0;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 32;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_STUFF;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_FALSE(error);
+	TEST_ASSERT_EQUAL(NULL, setup.generate_cw_f); /* pointer to the code word encoder */
+	TEST_ASSERT_EQUAL(encode_value_none, setup.encode_method_f); /* pointer to the encoding function */
+	TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */
+	TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */
+	TEST_ASSERT_EQUAL_INT(0, setup.encoder_par1); /* encoding parameter 1 */
+	TEST_ASSERT_EQUAL_INT(0, setup.encoder_par2); /* encoding parameter 2 */
+	TEST_ASSERT_EQUAL_INT(0, setup.spillover_par); /* outlier parameter */
+	TEST_ASSERT_EQUAL_INT(0, setup.lossy_par); /* lossy compression parameter */
+	TEST_ASSERT_EQUAL_INT(0, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */
+	memset(&setup, 0, sizeof(setup));
+
+	/* cmp_mode = STUFF_MODE +1  */
+	cmp_par = 32;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 1;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_STUFF+1;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_TRUE(error);
+	memset(&setup, 0, sizeof(setup));
+
+	/* setup = NULL test */
+	cmp_par = 42;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 15;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_ZERO;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(NULL, cmp_par, spillover,lossy_par,
+					max_data_bits, &cfg);
+	TEST_ASSERT_TRUE(error);
+	memset(&setup, 0, sizeof(setup));
+
+	/* cfg = NULL test */
+	cmp_par = 42;
+	spillover = 23;
+	lossy_par = 0;
+	max_data_bits = 15;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_MODEL_ZERO;
+	cfg.icu_output_buf = (void *)123;
+	cfg.buffer_length = 2;
+	error = configure_encoder_setup(&setup, cmp_par, spillover,lossy_par,
+					max_data_bits, NULL);
+	TEST_ASSERT_TRUE(error);
+	memset(&setup, 0, sizeof(setup));
+}
+
+
+/**
+ * @test compress_imagette
+ */
+
 void test_compress_imagette_diff(void)
 {
 	uint16_t data[] = {0xFFFF, 1, 0, 42, 0x8000, 0x7FFF, 0xFFFF};
@@ -1081,6 +2406,11 @@ void test_compress_imagette_diff(void)
 	TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(output_buf[2]));
 }
 
+
+/**
+ * @test compress_imagette
+ */
+
 void test_compress_imagette_model(void)
 {
 	uint16_t data[]  = {0x0000, 0x0001, 0x0042, 0x8000, 0x7FFF, 0xFFFF, 0xFFFF};
@@ -1116,9 +2446,19 @@ void test_compress_imagette_model(void)
 	TEST_ASSERT_EQUAL_HEX(0x3FFF, model_up[4]);
 	TEST_ASSERT_EQUAL_HEX(0xFFFF, model_up[5]);
 	TEST_ASSERT_EQUAL_HEX(0x7FFF, model_up[6]);
+
+
+	/* error case: model mode without model data */
+	cfg.model_buf = NULL; /* this is the error */
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL(-1, cmp_size);
 }
 
 
+/**
+ * @test compress_imagette
+ */
+
 void test_compress_imagette_stuff(void)
 {
 	uint16_t data[] = {0x0, 0x1, 0x23, 0x42, 0x8000, 0x7FFF, 0xFFFF};
@@ -1151,12 +2491,15 @@ void test_compress_imagette_stuff(void)
 }
 
 
+/**
+ * @test compress_imagette
+ */
+
 void test_compress_imagette_raw(void)
 {
 	uint16_t data[] = {0x0, 0x1, 0x23, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX};
-	uint16_t output_buf[7] = {0};
+	uint16_t output_buf[7] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 	struct cmp_cfg cfg = {0};
-
 	int cmp_size;
 
 	cfg.data_type = DATA_TYPE_IMAGETTE;
@@ -1166,9 +2509,7 @@ void test_compress_imagette_raw(void)
 	cfg.icu_output_buf = (uint32_t *)output_buf;
 	cfg.buffer_length = 7;
 
-
 	cmp_size = icu_compress_data(&cfg);
-
 	TEST_ASSERT_EQUAL_INT(7*16, cmp_size);
 	TEST_ASSERT_EQUAL_HEX16(0x0, be16_to_cpu(output_buf[0]));
 	TEST_ASSERT_EQUAL_HEX16(0x1, be16_to_cpu(output_buf[1]));
@@ -1177,6 +2518,181 @@ void test_compress_imagette_raw(void)
 	TEST_ASSERT_EQUAL_HEX16(INT16_MIN, be16_to_cpu(output_buf[4]));
 	TEST_ASSERT_EQUAL_HEX16(INT16_MAX, be16_to_cpu(output_buf[5]));
 	TEST_ASSERT_EQUAL_HEX16(UINT16_MAX, be16_to_cpu(output_buf[6]));
+
+
+	/* compressed data buf = NULL test */
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.icu_output_buf = NULL;
+	cfg.buffer_length = 7;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(7*16, cmp_size);
+
+
+	/* error case: input_buf = NULL */
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.input_buf = NULL; /* no data to compress */
+	cfg.samples = 7;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 7;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_size);
+
+
+	/* error case: compressed data buffer to small */
+	memset(&cfg, 0, sizeof(struct cmp_cfg));
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 6; /* the buffer is to small */
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+}
+
+
+/**
+ * @test compress_imagette
+ */
+
+void test_compress_imagette_error_cases(void)
+{
+	uint16_t data[] = {0xFFFF, 1, 0, 42, 0x8000, 0x7FFF, 0xFFFF};
+	uint32_t output_buf[2] = {0xFFFF, 0xFFFF};
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.input_buf = NULL;
+	cfg.samples = 0;  /* nothing to compress */
+	cfg.golomb_par = 1;
+	cfg.spill = 8;
+	cfg.icu_output_buf = NULL;
+	cfg.buffer_length = 0;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(0, cmp_size);
+
+
+	/* compressed data buffer to small test */
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.input_buf = data;
+	cfg.samples = 7;
+	cfg.golomb_par = 1;
+	cfg.spill = 8;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 4;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+
+
+	/* error in setup */
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+	max_used_bits.nc_imagette = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_DIFF_ZERO;
+	cfg.input_buf = data;
+	cfg.samples = 2;
+	cfg.golomb_par = 1;
+	cfg.spill = 8;
+	cfg.icu_output_buf = (uint32_t *)output_buf;
+	cfg.buffer_length = 4;
+
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_size);
+}
+
+
+/**
+ * @test compress_multi_entry_hdr
+ */
+
+void test_compress_multi_entry_hdr(void)
+{
+	int stream_len;
+	uint8_t data[MULTI_ENTRY_HDR_SIZE];
+	uint8_t model[MULTI_ENTRY_HDR_SIZE];
+	uint8_t up_model[MULTI_ENTRY_HDR_SIZE];
+	uint8_t cmp_data[MULTI_ENTRY_HDR_SIZE];
+	uint8_t *data_p = NULL;
+	uint8_t *model_p = NULL;
+	uint8_t *up_model_p = NULL;
+
+	memset(data, 0x42, sizeof(data));
+
+	/* no data; no cmp_data no model test */
+	/* no data; no model; no up_model; no cmp_data */
+	stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p,
+					      (void **)&up_model_p, NULL);
+	TEST_ASSERT_EQUAL_INT(96, stream_len);
+
+	/* no model; no up_model */
+	data_p = data;
+	stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p,
+					      (void **)&up_model_p, cmp_data);
+	TEST_ASSERT_EQUAL_INT(96, stream_len);
+	TEST_ASSERT_FALSE(memcmp(cmp_data, data, MULTI_ENTRY_HDR_SIZE));
+	TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE);
+
+	/* no up_model */
+	memset(cmp_data, 0, sizeof(cmp_data));
+	data_p = data;
+	model_p = model;
+	up_model_p = NULL;
+	stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p,
+					      (void **)&up_model_p, cmp_data);
+	TEST_ASSERT_EQUAL_INT(96, stream_len);
+	TEST_ASSERT_FALSE(memcmp(cmp_data, data, MULTI_ENTRY_HDR_SIZE));
+	TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE);
+	TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE);
+
+	/* all buffer test */
+	memset(cmp_data, 0, sizeof(cmp_data));
+	data_p = data;
+	model_p = model;
+	up_model_p = up_model;
+	stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p,
+					      (void **)&up_model_p, cmp_data);
+	TEST_ASSERT_EQUAL_INT(96, stream_len);
+	TEST_ASSERT_FALSE(memcmp(cmp_data, data, MULTI_ENTRY_HDR_SIZE));
+	TEST_ASSERT_FALSE(memcmp(up_model, data, MULTI_ENTRY_HDR_SIZE));
+	TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE);
+	TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE);
+	TEST_ASSERT_EQUAL(up_model_p-up_model, MULTI_ENTRY_HDR_SIZE);
+
+	/* all buffer test; no cmp_data */
+	memset(cmp_data, 0, sizeof(cmp_data));
+	data_p = data;
+	model_p = model;
+	up_model_p = up_model;
+	stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p,
+					      (void **)&up_model_p, NULL);
+	TEST_ASSERT_EQUAL_INT(96, stream_len);
+	TEST_ASSERT_FALSE(memcmp(up_model, data, MULTI_ENTRY_HDR_SIZE));
+	TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE);
+	TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE);
+	TEST_ASSERT_EQUAL(up_model_p-up_model, MULTI_ENTRY_HDR_SIZE);
+
+	/* no data, use up_model test */
+	memset(cmp_data, 0, sizeof(cmp_data));
+	data_p = NULL;
+	model_p = model;
+	up_model_p = up_model;
+	stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p,
+					      (void **)&up_model_p, NULL);
+	TEST_ASSERT_EQUAL_INT(96, stream_len);
+	TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE);
+	TEST_ASSERT_EQUAL(up_model_p-up_model, MULTI_ENTRY_HDR_SIZE);
 }
 
 
@@ -1363,9 +2879,9 @@ void test_compress_s_fx_model_multi(void)
 	TEST_ASSERT_EQUAL_HEX(0xAFFF4DE5, be32_to_cpu(cmp_data[1]));
 	TEST_ASSERT_EQUAL_HEX(0xCC000000, be32_to_cpu(cmp_data[2]));
 
-	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
 	hdr = cfg.icu_new_model_buf;
 	up_model_buf = (struct s_fx *)hdr->entry;
+	TEST_ASSERT_FALSE(memcmp(hdr, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
 	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].exp_flags);
 	TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].fx);
 	TEST_ASSERT_EQUAL_HEX(0x2, up_model_buf[1].exp_flags);
@@ -1386,3 +2902,139 @@ void test_compress_s_fx_model_multi(void)
 }
 
 
+void test_compress_s_fx_efx_model_multi(void)
+{
+	uint32_t i;
+	struct s_fx_efx data[6], model[6];
+	struct s_fx_efx *up_model_buf;
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+	struct multi_entry_hdr *hdr;
+	uint32_t *cmp_data;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	/* define max_used_bits */
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	max_used_bits.s_efx = 21;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	/* setup configuration */
+	cfg.data_type = DATA_TYPE_S_FX_DFX;
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cfg.model_value = 16;
+	cfg.samples = 6;
+	cfg.input_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.input_buf);
+	cfg.model_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.model_buf);
+	cfg.icu_new_model_buf = malloc(cmp_cal_size_of_data(cfg.samples, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_new_model_buf);
+	cfg.buffer_length = 6;
+	cfg.icu_output_buf = malloc(cmp_cal_size_of_data(cfg.buffer_length, cfg.data_type));
+	TEST_ASSERT_NOT_NULL(cfg.icu_output_buf);
+	cfg.cmp_par_exp_flags = 1;
+	cfg.spill_exp_flags = 8;
+	cfg.cmp_par_fx = 3;
+	cfg.spill_fx = 35;
+	cfg.cmp_par_efx = 4;
+	cfg.spill_efx = 35;
+
+
+	/* generate input data */
+	hdr = cfg.input_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x42, sizeof(struct multi_entry_hdr));
+	data[0].exp_flags = 0x0;
+	data[0].fx = 0x0;
+	data[0].efx = 0x0;
+	data[1].exp_flags = 0x1;
+	data[1].fx = 0x1;
+	data[1].efx = 0;
+	data[2].exp_flags = 0x2;
+	data[2].fx = 0x23;
+	data[2].efx = 0;
+	data[3].exp_flags = 0x3;
+	data[3].fx = 0x42;
+	data[3].efx = 0;
+	data[4].exp_flags = 0x0;
+	data[4].fx = 0x001FFFFF;
+	data[4].efx = 0;
+	data[5].exp_flags = 0x0;
+	data[5].fx = 0x0;
+	data[5].efx = 0;
+	memcpy(hdr->entry, data, sizeof(data));
+
+	/* generate model data */
+	hdr = cfg.model_buf;
+	/* use dummy data for the header */
+	memset(hdr, 0x41, sizeof(struct multi_entry_hdr));
+	model[0].exp_flags = 0x0;
+	model[0].fx = 0x0;
+	model[0].efx = 0x1FFFFF;
+	model[1].exp_flags = 0x3;
+	model[1].fx = 0x1;
+	model[1].efx = 0x1FFFFF;
+	model[2].exp_flags = 0x0;
+	model[2].fx = 0x42;
+	model[2].efx = 0x1FFFFF;
+	model[3].exp_flags = 0x0;
+	model[3].fx = 0x23;
+	model[3].efx = 0x1FFFFF;
+	model[4].exp_flags = 0x3;
+	model[4].fx = 0x0;
+	model[4].efx = 0x1FFFFF;
+	model[5].exp_flags = 0x2;
+	model[5].fx = 0x001FFFFF;
+	model[5].efx = 0x1FFFFF;
+	memcpy(hdr->entry, model, sizeof(model));
+
+	cmp_size = icu_compress_data(&cfg);
+#if 0
+	TEST_ASSERT_EQUAL_INT(166, cmp_size);
+	TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	cmp_data = &cfg.icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)];
+	TEST_ASSERT_EQUAL_HEX(0x1C77FFA6, be32_to_cpu(cmp_data[0]));
+	TEST_ASSERT_EQUAL_HEX(0xAFFF4DE5, be32_to_cpu(cmp_data[1]));
+	TEST_ASSERT_EQUAL_HEX(0xCC000000, be32_to_cpu(cmp_data[2]));
+
+#endif
+	hdr = cfg.icu_new_model_buf;
+	up_model_buf = (struct s_fx *)hdr->entry;
+	TEST_ASSERT_FALSE(memcmp(hdr, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE));
+	for (i = 0; i < cfg.samples; i++) {
+		TEST_ASSERT_EQUAL(model[i].exp_flags, up_model_buf[i].exp_flags);
+		TEST_ASSERT_EQUAL(model[i].fx, up_model_buf[i].fx);
+		TEST_ASSERT_EQUAL(model[i].efx, up_model_buf[i].efx);
+	}
+
+
+	free(cfg.input_buf);
+	free(cfg.model_buf);
+	free(cfg.icu_new_model_buf);
+	free(cfg.icu_output_buf);
+}
+
+
+/**
+ * @test icu_compress_data
+ */
+
+void test_icu_compress_data_error_cases(void)
+{
+	int cmp_size;
+	struct cmp_cfg cfg = {0};
+	uint16_t data[4] = {0, 0xFFFF, 23, 42};
+	uint32_t cmp_data_buf[4] = {0};
+
+	/* cfg = NULL test */
+	cmp_size = icu_compress_data(NULL);
+	TEST_ASSERT_EQUAL(-1, cmp_size);
+
+	/* samples = 0 test */
+	cfg.samples = 0;
+	cmp_size = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL(0, cmp_size);
+
+}
+
-- 
GitLab


From a6bc7b3e211d1d4e95cc875ea2192efef4ce145a Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 1 Sep 2022 14:02:50 +0200
Subject: [PATCH 25/46] fix a bug in the model update; add a test for this bug
 warn if -m option is used without model compression mode read in compression
 parameter for non-imagette compression

---
 cmp_tool.c                                 |   8 +-
 lib/cmp_io.c                               | 143 +++++++++++++++------
 test/cmp_tool/cmp_tool_integration_test.py |   6 +-
 3 files changed, 112 insertions(+), 45 deletions(-)

diff --git a/cmp_tool.c b/cmp_tool.c
index 54e20ab..0cf72ef 100644
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -424,6 +424,11 @@ int main(int argc, char **argv)
 		printf("DONE\n");
 	}
 
+	if (model_file_name && !guess_operation &&
+	    ((cmp_operation && !model_mode_is_used(cfg.cmp_mode)) ||
+	     (!cmp_operation && !model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity)))))
+		printf("Warring: Model file (-m option) specified but no model is used.\n");
+
 	/* read in model */
 	if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
 	    (!cmp_operation && model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity))) ||
@@ -459,6 +464,7 @@ int main(int argc, char **argv)
 		printf("DONE\n");
 
 		cfg.model_buf = input_model_buf;
+		cfg.icu_new_model_buf = input_model_buf; /* in-place model update */
 	}
 
 	if (guess_operation) {
@@ -479,7 +485,7 @@ int main(int argc, char **argv)
 	if (!guess_operation &&
 	    ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
 	    (!cmp_operation && model_mode_is_used(cmp_ent_get_cmp_mode(decomp_entity))))) {
-		enum cmp_data_type data_type = DATA_TYPE_UNKOWN;
+		enum cmp_data_type data_type = DATA_TYPE_UNKNOWN;
 		uint32_t model_size;
 
 		printf("Write updated model to file %s_upmodel.dat ... ", output_prefix);
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 9e4eb3a..83c6906 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -61,7 +61,7 @@ static const struct {
 	{DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE, "DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE"},
 	{DATA_TYPE_F_CAM_OFFSET, "DATA_TYPE_F_CAM_OFFSET"},
 	{DATA_TYPE_F_CAM_BACKGROUND, "DATA_TYPE_F_CAM_BACKGROUND"},
-	{DATA_TYPE_UNKOWN, "DATA_TYPE_UNKOWN"}
+	{DATA_TYPE_UNKNOWN, "DATA_TYPE_UNKNOWN"}
 };
 
 
@@ -403,12 +403,12 @@ int atoui32(const char *dep_str, const char *val_str, uint32_t *red_val)
  *
  * @param data_type_str	string containing the compression data type to parse
  *
- * @returns data type on success, DATA_TYPE_UNKOWN on error
+ * @returns data type on success, DATA_TYPE_UNKNOWN on error
  */
 
 enum cmp_data_type string2data_type(const char *data_type_str)
 {
-	enum cmp_data_type data_type = DATA_TYPE_UNKOWN;
+	enum cmp_data_type data_type = DATA_TYPE_UNKNOWN;
 
 	if (data_type_str) {
 		if (isalpha(data_type_str[0])) {  /* check if mode is given as text */
@@ -426,7 +426,7 @@ enum cmp_data_type string2data_type(const char *data_type_str)
 			if (!atoui32("Compression Data Type", data_type_str, &read_val)) {
 				data_type = read_val;
 				if (!cmp_data_type_valid(data_type))
-					data_type = DATA_TYPE_UNKOWN;
+					data_type = DATA_TYPE_UNKNOWN;
 			}
 		}
 	}
@@ -439,13 +439,13 @@ enum cmp_data_type string2data_type(const char *data_type_str)
  *
  * @param data_type compression data type to convert in string
  *
- * @returns data type on success, DATA_TYPE_UNKOWN on error
+ * @returns data type on success, DATA_TYPE_UNKNOWN on error
  */
 
 const char *data_type2string(enum cmp_data_type data_type)
 {
 	size_t j;
-	const char *string = "DATA_TYPE_UNKOWN";
+	const char *string = "DATA_TYPE_UNKNOWN";
 
 	for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
 		if (data_type == data_type_string_table[j].data_type) {
@@ -527,7 +527,7 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 {
 	char *token1, *token2;
 	char line[MAX_CONFIG_LINE];
-	enum {CMP_MODE, GOLOMB_PAR, SPILL, SAMPLES, BUFFER_LENGTH, LAST_ITEM};
+	enum {CMP_MODE, SAMPLES, BUFFER_LENGTH, LAST_ITEM};
 	int j, must_read_items[LAST_ITEM] = {0};
 
 	if (!fp)
@@ -559,53 +559,24 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 
 		if (!strcmp(token1, "data_type")) {
 			cfg->data_type = string2data_type(token2);
-			if (cfg->data_type == DATA_TYPE_UNKOWN)
+			if (cfg->data_type == DATA_TYPE_UNKNOWN)
 				return -1;
 			continue;
 		}
 		if (!strcmp(token1, "cmp_mode")) {
 			must_read_items[CMP_MODE] = 1;
-			if (isalpha(*token2)) { /* check if mode is given as text or val*/
-				/* TODO: use conversion function for this: */
-				if (!strcmp(token2, "MODE_RAW")) {
-					cfg->cmp_mode = 0;
-					continue;
-				}
-				if (!strcmp(token2, "MODE_MODEL_ZERO")) {
-					cfg->cmp_mode = 1;
-					continue;
-				}
-				if (!strcmp(token2, "MODE_DIFF_ZERO")) {
-					cfg->cmp_mode = 2;
-					continue;
-				}
-				if (!strcmp(token2, "MODE_MODEL_MULTI")) {
-					cfg->cmp_mode = 3;
-					continue;
-				}
-				if (!strcmp(token2, "MODE_DIFF_MULTI")) {
-					cfg->cmp_mode = 4;
-					continue;
-				}
-				fprintf(stderr, "%s: Error read in cmp_mode.\n",
-					PROGRAM_NAME);
+			if (cmp_mode_parse(token2, &cfg->cmp_mode))
 				return -1;
-			} else {
-				if (atoui32(token1, token2, &cfg->cmp_mode))
-					return -1;
-				continue;
-			}
+			continue;
 		}
 		if (!strcmp(token1, "golomb_par")) {
 			if (atoui32(token1, token2, &cfg->golomb_par))
 				return -1;
-			must_read_items[GOLOMB_PAR] = 1;
 			continue;
 		}
 		if (!strcmp(token1, "spill")) {
 			if (atoui32(token1, token2, &cfg->spill))
 				return -1;
-			must_read_items[SPILL] = 1;
 			continue;
 		}
 		if (!strcmp(token1, "model_value")) {
@@ -638,6 +609,96 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg)
 				return -1;
 			continue;
 		}
+		if (!strcmp(token1, "cmp_par_exp_flags")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_exp_flags))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_exp_flags")) {
+			if (atoui32(token1, token2, &cfg->spill_exp_flags))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_fx")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_fx))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_fx")) {
+			if (atoui32(token1, token2, &cfg->spill_fx))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_ncob")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_ncob))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_ncob")) {
+			if (atoui32(token1, token2, &cfg->spill_ncob))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_efx")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_efx))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_efx")) {
+			if (atoui32(token1, token2, &cfg->spill_efx))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_ecob")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_ecob))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_ecob")) {
+			if (atoui32(token1, token2, &cfg->spill_ecob))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_fx_cob_variance")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_fx_cob_variance))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_fx_cob_variance")) {
+			if (atoui32(token1, token2, &cfg->spill_fx_cob_variance))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_mean")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_mean))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_mean")) {
+			if (atoui32(token1, token2, &cfg->spill_mean))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_variance")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_variance))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_variance")) {
+			if (atoui32(token1, token2, &cfg->spill_variance))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "cmp_par_pixels_error")) {
+			if (atoui32(token1, token2, &cfg->cmp_par_pixels_error))
+				return -1;
+			continue;
+		}
+		if (!strcmp(token1, "spill_pixels_error")) {
+			if (atoui32(token1, token2, &cfg->spill_pixels_error))
+				return -1;
+			continue;
+		}
 		if (!strcmp(token1, "rdcu_data_adr")) {
 			int i = sram_addr_to_int(token2);
 
@@ -1384,7 +1445,7 @@ ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent,
 	if (ent) {
 		enum cmp_data_type data_type = cmp_ent_get_data_type(ent);
 
-		if (data_type == DATA_TYPE_UNKOWN) {
+		if (data_type == DATA_TYPE_UNKNOWN) {
 			fprintf(stderr, "%s: %s: Error: Compression data type is not supported.\n",
 				PROGRAM_NAME, file_name);
 			return -1;
@@ -1501,7 +1562,7 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg, int rdcu_cfg
 	fprintf(fp, "#-------------------------------------------------------------------------------\n");
 	fprintf(fp, "# Selected compression data type\n");
 	fprintf(fp, "\n");
-	fprintf(fp, "data_type = %u\n", cfg->data_type);
+	fprintf(fp, "data_type = %s\n", data_type2string(cfg->data_type));
 	fprintf(fp, "\n");
 	fprintf(fp, "# Selected compression mode\n");
 	fprintf(fp, "# 0: raw mode\n");
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
index aac8b0b..f08d53b 100755
--- a/test/cmp_tool/cmp_tool_integration_test.py
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -481,7 +481,7 @@ def test_model_compression():
             assert(stderr == "")
             cfg = parse_key_value(stdout)
             cfg['cmp_mode'] = 'MODE_MODEL_MULTI'
-            cfg['model_value'] = '16'
+            cfg['model_value'] = '0'
             cfg["samples"] = '5'
             cfg["buffer_length"] = '2'
             for key, value in cfg.items():
@@ -566,8 +566,8 @@ def test_model_compression():
 
             with open(output_prefix1+"_upmodel.dat", encoding='utf-8') as f1:
                 with open(output_prefix2+"_upmodel.dat", encoding='utf-8') as f2:
-                    assert(f1.read() == f2.read() ==
-                           '00 00 00 01 00 02 00 03 00 04 \n')
+                    assert(f1.read() == f2.read() == data) # upmodel == data -> model_value = 0
+                           # '00 00 00 01 00 02 00 03 00 04 \n')
     # clean up
     finally:
         del_file(data_file_name)
-- 
GitLab


From 4fd8c3394ba016e4a6f331c1d02985bb08c4c594 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 1 Sep 2022 14:05:43 +0200
Subject: [PATCH 26/46] fix a bug if setting the non_ima_spill2
 non_ima_cmp_par2 in the cmp_ent_write_cmp_pars() functions add max_used_bits
 registry version to the compression entity header catch overflows in the
 cmp_cal_size_of_data() function

---
 include/cmp_data_types.h |  5 ++-
 include/cmp_entity.h     |  4 ++-
 lib/cmp_data_types.c     | 29 ++++++++++++---
 lib/cmp_entity.c         | 77 +++++++++++++++++++++++++++++++++-------
 test/meson.build         |  1 +
 5 files changed, 94 insertions(+), 22 deletions(-)

diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 9c8a470..8878557 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -84,7 +84,7 @@
 
 /* struct holding the maximum length of the different data products types in bits */
 struct cmp_max_used_bits {
-	unsigned int version;
+	uint8_t version;
 	unsigned int s_exp_flags;
 	unsigned int s_fx;
 	unsigned int s_efx;
@@ -127,8 +127,7 @@ struct cmp_max_used_bits {
 void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits);
 struct cmp_max_used_bits cmp_get_max_used_bits(void);
 
-/* for internal use only! */
-extern struct cmp_max_used_bits max_used_bits;
+uint8_t cmp_get_max_used_bits_version(void);
 
 
 /* Source data header structure for multi entry packet */
diff --git a/include/cmp_entity.h b/include/cmp_entity.h
index 0c9a606..c56cef5 100644
--- a/include/cmp_entity.h
+++ b/include/cmp_entity.h
@@ -116,7 +116,7 @@ struct cmp_entity {
 	uint8_t  model_value_used;		/* used Model Updating Weighing Value */
 	uint16_t model_id;			/* Model ID */
 	uint8_t  model_counter;			/* Model Counter */
-	uint8_t  spare;
+	uint8_t  max_used_bits_version;
 	uint16_t lossy_cmp_par_used;		/* used Lossy Compression Parameters */
 	union {	/* specific Compression Entity Header for the different Data Product Types */
 		struct imagette_header ima;
@@ -174,6 +174,7 @@ int cmp_ent_set_cmp_mode(struct cmp_entity *ent, uint32_t cmp_mode_used);
 int cmp_ent_set_model_value(struct cmp_entity *ent, uint32_t model_value_used);
 int cmp_ent_set_model_id(struct cmp_entity *ent, uint32_t model_id);
 int cmp_ent_set_model_counter(struct cmp_entity *ent, uint32_t model_counter);
+int cmp_ent_set_max_used_bits_version(struct cmp_entity *ent, uint8_t max_used_bits_version);
 int cmp_ent_set_lossy_cmp_par(struct cmp_entity *ent, uint32_t lossy_cmp_par_used);
 
 
@@ -235,6 +236,7 @@ uint8_t cmp_ent_get_model_value_used(struct cmp_entity *ent);
 
 uint16_t cmp_ent_get_model_id(struct cmp_entity *ent);
 uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent);
+uint8_t cmp_ent_get_max_used_bits_version(struct cmp_entity *ent);
 uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent);
 
 
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 8dd5792..5a01f8b 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -20,6 +20,8 @@
 #include <cmp_data_types.h>
 #include <cmp_debug.h>
 #include <byteorder.h>
+#include <stdint.h>
+#include <stdio.h>
 
 
 /* the maximum length of the different data products types in bits */
@@ -88,6 +90,17 @@ struct cmp_max_used_bits cmp_get_max_used_bits(void)
 }
 
 
+/**
+ * @brief get the version record form the max used bits registry
+ *
+ * @returns version of the max used bits registry
+ */
+
+uint8_t cmp_get_max_used_bits_version(void) {
+	return max_used_bits.version;
+}
+
+
 /**
  * @brief calculate the size of a sample for the different compression data type
  *
@@ -106,6 +119,8 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_SAT_IMAGETTE:
 	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		sample_size = sizeof(uint16_t);
 		break;
 	case DATA_TYPE_OFFSET:
@@ -155,7 +170,7 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 		break;
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
 	default:
 		debug_print("Error: Compression data type is not supported.\n");
 		break;
@@ -178,16 +193,20 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type)
 {
 	unsigned int s = size_of_a_sample(data_type);
+	uint64_t x; /* use 64 bit to catch overflow */
 
 	if (!s)
 		return 0;
 
-	s *= samples;
+	x = (uint64_t)s*samples;
 
 	if (!rdcu_supported_data_type_is_used(data_type))
-		s += MULTI_ENTRY_HDR_SIZE;
+		x += MULTI_ENTRY_HDR_SIZE;
+
+	if (x > UINT32_MAX) /* catch overflow */
+		return 0;
 
-	return s;
+	return (unsigned int)x;
 }
 
 
@@ -510,7 +529,7 @@ int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
 	/* TODO: implement F_CAM conversion */
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
 	default:
 		debug_print("Error: Can not swap endianness for this compression data type.\n");
 		return -1;
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index 0296894..6a5b040 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -97,7 +97,7 @@ uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode_flag)
 		case DATA_TYPE_F_CAM_BACKGROUND:
 			size = NON_IMAGETTE_HEADER_SIZE;
 			break;
-		case DATA_TYPE_UNKOWN:
+		case DATA_TYPE_UNKNOWN:
 			size = 0;
 			break;
 		}
@@ -442,6 +442,27 @@ int cmp_ent_set_model_counter(struct cmp_entity *ent, uint32_t model_counter)
 }
 
 
+/**
+ * @brief set version identifier for the max. used bits registry in the
+ *	compression entity header
+ *
+ * @param ent			pointer to a compression entity
+ * @param max_used_bits_version	the identifier for the max. used bits registry
+ *
+ * @returns 0 on success, otherwise error
+ */
+
+int cmp_ent_set_max_used_bits_version(struct cmp_entity *ent, uint8_t max_used_bits_version)
+{
+	if (!ent)
+		return -1;
+
+	ent->max_used_bits_version = max_used_bits_version;
+
+	return 0;
+}
+
+
 /**
  * @brief set the used lossy compression parameter in the compression entity
  *	header
@@ -1108,7 +1129,7 @@ uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent)
  * @param ent	pointer to a compression entity
  *
  * @returns the data_type NOT including the uncompressed data bit on success,
- *	DATA_TYPE_UNKOWN on error
+ *	DATA_TYPE_UNKNOWN on error
  */
 
 enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
@@ -1116,13 +1137,13 @@ enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
 	enum cmp_data_type data_type;
 
 	if (!ent)
-		return DATA_TYPE_UNKOWN;
+		return DATA_TYPE_UNKNOWN;
 
 	data_type = be16_to_cpu(ent->data_type);
 	data_type &= (1U << RAW_BIT_DATA_TYPE_POS)-1; /* remove uncompressed data flag */
 
 	if (!cmp_data_type_valid(data_type))
-		data_type = DATA_TYPE_UNKOWN;
+		data_type = DATA_TYPE_UNKNOWN;
 
 	return data_type;
 }
@@ -1214,6 +1235,25 @@ uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent)
 }
 
 
+/**
+ * @brief get the version identifier for the max. used bits registry from the
+ *	compression entity header
+ *
+ * @param ent	pointer to a compression entity
+ *
+ * @returns the version identifier for the max. used bits registry on success,
+ *	0 on error
+ */
+
+uint8_t cmp_ent_get_max_use_bits_version(struct cmp_entity *ent)
+{
+	if (!ent)
+		return 0;
+
+	return ent->max_used_bits_version;
+}
+
+
 /**
  * @brief get the used lossy compression parameter from the compression entity header
  *
@@ -1598,10 +1638,15 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 	if (!ent)
 		return NULL;
 
+	data_type = cmp_ent_get_data_type(ent);
+	if (!cmp_data_type_valid(data_type)) {
+		debug_print("Error: Compression data type not supported.\n");
+		return NULL;
+	}
+
 	if (cmp_ent_get_data_type_raw_bit(ent))
 		return (uint8_t *)ent + GENERIC_HEADER_SIZE;
 
-	data_type = cmp_ent_get_data_type(ent);
 
 	switch (data_type) {
 	case DATA_TYPE_IMAGETTE:
@@ -1630,7 +1675,8 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
 		return ent->non_ima.cmp_data;
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
+	default:
 		return NULL;
 	}
 
@@ -1777,6 +1823,8 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 		return -1;
 	if (cmp_ent_set_model_value(ent, cfg->model_value))
 		return -1;
+	if (cmp_ent_set_max_used_bits_version(ent, cmp_get_max_used_bits_version()))
+		return -1;
 	if (cmp_ent_set_lossy_cmp_par(ent, cfg->round))
 		return -1;
 
@@ -1819,9 +1867,9 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_mean))
 			return -1;
 
-		if (cmp_ent_set_non_ima_spill2(ent, cfg->cmp_par_variance))
+		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_variance))
 			return -1;
-		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->spill_variance))
+		if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_variance))
 			return -1;
 
 		if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_pixels_error))
@@ -1892,7 +1940,7 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 		/* TODO: fix this*/
 			return -1;
 		break;
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
 	default:
 		return -1;
 	}
@@ -2187,7 +2235,7 @@ int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 		/* TODO: fix this*/
 			return -1;
 		break;
-	case DATA_TYPE_UNKOWN: /* fall through */
+	case DATA_TYPE_UNKNOWN: /* fall through */
 	default:
 		return -1;
 	}
@@ -2341,8 +2389,8 @@ void cmp_ent_print(struct cmp_entity *ent)
 static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 {
 	uint32_t version_id, cmp_ent_size, original_size, cmp_mode_used,
-		 model_value_used, model_id, model_counter, lossy_cmp_par_used,
-		 start_coarse_time, end_coarse_time;
+		 model_value_used, model_id, model_counter, max_used_bits_version,
+		 lossy_cmp_par_used, start_coarse_time, end_coarse_time;
 	uint16_t start_fine_time, end_fine_time;
 	enum cmp_data_type data_type;
 	int raw_bit;
@@ -2386,7 +2434,7 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 		+ ((end_fine_time - start_fine_time)/256./256.));
 
 	data_type = cmp_ent_get_data_type(ent);
-	if (data_type != DATA_TYPE_UNKOWN)
+	if (data_type != DATA_TYPE_UNKNOWN)
 		printf("Data Product Type: %d\n", data_type);
 	else
 		printf("Data Product Type: unknown!");
@@ -2406,6 +2454,9 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 	model_counter = cmp_ent_get_model_counter(ent);
 	printf("Model Counter: %u\n", model_counter);
 
+	max_used_bits_version = cmp_ent_get_max_use_bits_version(ent);
+	printf("Maximum Used Bits Registry Version: %u\n", max_used_bits_version);
+
 	lossy_cmp_par_used = cmp_ent_get_lossy_cmp_par(ent);
 	printf("Used Lossy Compression Parameters: %u\n", lossy_cmp_par_used);
 }
diff --git a/test/meson.build b/test/meson.build
index 4743653..145cdb8 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -37,3 +37,4 @@ subdir('cmp_tool')
 unity_dep = dependency('unity', fallback : ['unity', 'unity_dep'])
 
 subdir('cmp_icu')
+subdir('cmp_data_types')
-- 
GitLab


From d75ff55b4ef70fd1e2e89f282564f2f010eeb8e1 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 1 Sep 2022 14:07:00 +0200
Subject: [PATCH 27/46] add decompression for non-imagette data types

---
 lib/decmp.c               | 1917 +++++++++++++++++++++++++++++++++----
 test/cmp_icu/test_decmp.c |  340 ++++++-
 2 files changed, 2068 insertions(+), 189 deletions(-)

diff --git a/lib/decmp.c b/lib/decmp.c
index c22e5e4..3c7acfb 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -1,3 +1,24 @@
+/**
+ * @file   decmp.c
+ * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
+ * @date   2020
+ *
+ * @copyright GPLv2
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * @brief software decompression library
+ * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
+ *
+ * TODO: how to decomprss?
+ */
+
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -10,19 +31,21 @@
 #include "cmp_data_types.h"
 #include "cmp_entity.h"
 
-#define CMP_ERROR_SAMLL_BUF -2
 
+/* maximum used bits registry */
+extern struct cmp_max_used_bits max_used_bits;
+
+/* function pointer to a code word decoder function */
+typedef int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
 
 /* structure to hold a setup to encode a value */
-typedef unsigned int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
 struct decoder_setup {
-	/* generate_cw_f_pt generate_cw_f; /1* pointer to the code word generation function *1/ */
-	decoder_ptr decode_cw_f;
-	int (*encode_method_f)(uint32_t *decoded_value, int stream_pos,
+	decoder_ptr decode_cw_f; /* pointer to the code word decoder (Golomb/Rice)*/
+	int (*decode_method_f)(uint32_t *decoded_value, int stream_pos,
 			       const struct decoder_setup *setup); /* pointer to the decoding function */
 	uint32_t *bitstream_adr; /* start address of the compressed data bitstream */
 	uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */
-	uint32_t max_cw_len;
+	uint32_t max_cw_len; /* TODO */
 	uint32_t encoder_par1; /* encoding parameter 1 */
 	uint32_t encoder_par2; /* encoding parameter 2 */
 	uint32_t outlier_par; /* outlier parameter */
@@ -32,23 +55,22 @@ struct decoder_setup {
 };
 
 
-double get_compression_ratio(uint32_t samples, uint32_t cmp_size_bits,
-			     enum cmp_data_type data_type)
-{
-	double orign_len_bits = (double)cmp_cal_size_of_data(samples, data_type) * CHAR_BIT;
-
-	return orign_len_bits/(double)cmp_size_bits;
-}
-
+/**
+ * @brief count leading 1-bits
+ *
+ * @param value	input vale
+ *
+ * @returns the number of leading 1-bits in value, starting at the most
+ *	significant bit position
+ */
 
-static unsigned int count_leading_ones(unsigned int value)
+static unsigned int count_leading_ones(uint32_t value)
 {
 	unsigned int n_ones = 0; /* number of leading 1s */
 
 	while (1) {
-		unsigned int leading_bit;
+		uint32_t leading_bit = value & 0x80000000;
 
-		leading_bit = value & 0x80000000;
 		if (!leading_bit)
 			break;
 
@@ -59,7 +81,19 @@ static unsigned int count_leading_ones(unsigned int value)
 }
 
 
-static unsigned int rice_decoder(uint32_t code_word, unsigned int m,
+/**
+ * @brief decode a Rice code word
+ *
+ * @param code_word	Rice code word bitstream starting at the MSB
+ * @param m		Golomb parameter (not used)
+ * @param log2_m	Rice parameter, must be the same used for encoding
+ * @param decoded_cw	pointer where decoded value is written
+ *
+ * @returns the length of the decoded code word in bits (NOT the decoded value);
+ *	0 on failure
+ */
+
+static int rice_decoder(uint32_t code_word, unsigned int m,
 				 unsigned int log2_m, unsigned int *decoded_cw)
 {
 	unsigned int q; /* quotient code */
@@ -68,9 +102,9 @@ static unsigned int rice_decoder(uint32_t code_word, unsigned int m,
 	unsigned int rl; /* length of the remainder code */
 	unsigned int cw_len; /* length of the decoded code word in bits */
 
-	(void)m;
+	(void)m; /* we don't need the Golomb parameter */
 
-	q = count_leading_ones(code_word);
+	q = count_leading_ones(code_word); /* decode unary coding */
 	ql = q + 1; /* Number of 1's + following 0 */
 
 	rl = log2_m;
@@ -96,7 +130,20 @@ static unsigned int rice_decoder(uint32_t code_word, unsigned int m,
 }
 
 
-static unsigned int golomb_decoder(unsigned int code_word, unsigned int m,
+/**
+ * @brief decode a Golomb code word
+ *
+ * @param code_word	Golomb code word bitstream starting at the MSB
+ * @param m		Golomb parameter (have to be bigger than 0)
+ * @param log2_m	is log_2(m) calculate outside function for better
+ *			performance
+ * @param decoded_cw	pointer where decoded value is written
+ *
+ * @returns the length of the decoded code word in bits (NOT the decoded value);
+ *	0 on failure
+ */
+
+static int golomb_decoder(unsigned int code_word, unsigned int m,
 				   unsigned int log2_m, unsigned int
 				   *decoded_cw)
 {
@@ -108,7 +155,7 @@ static unsigned int golomb_decoder(unsigned int code_word, unsigned int m,
 	unsigned int cutoff; /* cutoff between group 1 and 2 */
 	unsigned int cw_len; /* length of the decoded code word in bits */
 
-	q = count_leading_ones(code_word);
+	q = count_leading_ones(code_word); /* decode unary coding */
 
 	rl = log2_m + 1;
 	code_word <<= (q+1);  /* shift quotient code out */
@@ -118,10 +165,10 @@ static unsigned int golomb_decoder(unsigned int code_word, unsigned int m,
 
 	cutoff = (1UL << rl) - m;
 
-	if (r1 < cutoff) {
+	if (r1 < cutoff) { /* group 1 */
 		cw_len = q + rl;
 		r = r1;
-	} else {
+	} else { /* group 2 */
 		cw_len = q + rl + 1;
 		r = r2 - cutoff;
 	}
@@ -134,6 +181,16 @@ static unsigned int golomb_decoder(unsigned int code_word, unsigned int m,
 }
 
 
+/**
+ * @brief select the decoder based on the used Golomb parameter
+ * @note if the Golomb parameter is a power of 2 we can use the faster Rice
+ *	decoder
+ *
+ * @param golomb_par	Golomb parameter (have to be bigger than 0)
+ *
+ * @returns function pointer to the select decoder function; NULL on failure
+ */
+
 static decoder_ptr select_decoder(unsigned int golomb_par)
 {
 	if (!golomb_par)
@@ -149,7 +206,9 @@ static decoder_ptr select_decoder(unsigned int golomb_par)
 /**
  * @brief read a value of up to 32 bits from a bitstream
  *
- * @param p_value		pointer to the read value
+ * @param p_value		pointer to the read value (can be NULL), the
+ *				read value will be converted to the system
+ *				endianness
  * @param n_bits		number of bits to read from the bitstream
  * @param bit_offset		bit index where the bits will be read, seen from
  *				the very beginning of the bitstream
@@ -158,9 +217,10 @@ static decoder_ptr select_decoder(unsigned int golomb_par)
  * @param max_stream_len	maximum length of the bitstream in bits; is
  *				ignored if bitstream_adr is NULL
  *
- * @returns length in bits of the generated bitstream on success; returns
- *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
- *          the bitstream buffer is too small to read the value from the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF
+ *	if the bitstream buffer is too small to read the value from the
+ *	bitstream
  */
 
 static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
@@ -174,16 +234,14 @@ static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
 	/*leave in case of erroneous input */
 	if (bit_offset < 0)
 		return -1;
-
 	if (n_bits == 0)
-		return stream_len;
-
+		return -1;
 	if (n_bits > 32)
 		return -1;
 
+	/* nothing to read */
 	if (!bitstream_adr)
 		return stream_len;
-
 	if (!p_value)
 		return stream_len;
 
@@ -231,88 +289,130 @@ static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
 }
 
 
-static int decode_normal(uint32_t *decoded_value, int stream_pos, const struct decoder_setup *setup)
-{
-	uint32_t read_val = ~0U;
-	int n_read_bits, cw_len, n_bits;
+/**
+ * @brief decode a Golomb/Rice encoded code word from the bitstream
+ *
+ * @param decoded_value	pointer to the decoded value
+ * @param stream_pos	start bit position code word to be decoded in the bitstream
+ * @param setup		pointer to the decoder setup
+ *
+ * @returns bit index of the next code word in the bitstream on success; returns
+ *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	bitstream buffer is too small to read the value from the bitstream
+ */
 
-	if (stream_pos + setup->max_cw_len > setup->max_stream_len)   /* check buffer overflow */
-		n_read_bits = setup->max_stream_len - stream_pos;
+static int decode_normal(uint32_t *decoded_value, int stream_pos,
+			 const struct decoder_setup *setup)
+{
+	uint32_t read_val;
+	unsigned int n_read_bits;
+	int stream_pos_read, cw_len;
+
+	/* check if we can read max_cw_len or less; we do not now how long the
+	 * code word actually is so we try to read the maximum cw length */
+	if ((unsigned int)stream_pos + setup->max_cw_len > setup->max_stream_len)
+		n_read_bits = setup->max_stream_len - (unsigned int)stream_pos;
 	else
 		n_read_bits = setup->max_cw_len;
-	if (n_read_bits >= 32 || n_read_bits == 0)
-		return -1;
 
-	n_bits = get_n_bits32(&read_val, n_read_bits, stream_pos,
-				  setup->bitstream_adr, setup->max_stream_len);
-	if (n_bits <= 0)
-		return -1;
+	stream_pos_read = get_n_bits32(&read_val, n_read_bits, stream_pos,
+				       setup->bitstream_adr, setup->max_stream_len);
+	if (stream_pos_read < 0)
+		return stream_pos_read;
 
+	/* if we read less than 32, we shift the bitstream so that it starts at the MSB */
 	read_val = read_val << (32 - n_read_bits);
 
-	cw_len = setup->decode_cw_f(read_val, setup->encoder_par1, setup->encoder_par2, decoded_value);
-	if (cw_len < 0)
+	cw_len = setup->decode_cw_f(read_val, setup->encoder_par1,
+				    setup->encoder_par2, decoded_value);
+	if (cw_len <= 0)
+		return -1;
+	/* consistency check: code word length can not be bigger than read bits */
+	if (cw_len > (int)n_read_bits)
 		return -1;
 
 	return stream_pos + cw_len;
 }
 
 
-static int decode_multi(uint32_t *decoded_value, int stream_pos,
-			    const struct decoder_setup *setup)
+/**
+ * @brief decode a Golomb/Rice encoded code word with zero escape system
+ *	mechanism from the bitstream
+ *
+ * @param decoded_value	pointer to the decoded value
+ * @param stream_pos	start bit position code word to be decoded in the bitstream
+ * @param setup		pointer to the decoder setup
+ *
+ * @returns bit index of the next code word in the bitstream on success; returns
+ *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	bitstream buffer is too small to read the value from the bitstream
+ */
+
+static int decode_zero(uint32_t *decoded_value, int stream_pos,
+		       const struct decoder_setup *setup)
 {
 	stream_pos = decode_normal(decoded_value, stream_pos, setup);
 	if (stream_pos < 0)
 		return stream_pos;
 
-	if (*decoded_value >= setup->outlier_par) {
-		/* escape symbol mechanism was used; read unencoded value */
-		int n_bits;
-		uint32_t unencoded_val = 0;
-		unsigned int unencoded_len;
+	/* consistency check: value lager than the outlier parameter should not
+	 * be Golomb/Rice encoded */
+	if (*decoded_value > setup->outlier_par)
+		return -1;
 
-		unencoded_len = (*decoded_value - setup->outlier_par + 1) * 2;
+	if (*decoded_value == 0) {
+		/* escape symbol mechanism was used; read unencoded value */
+		uint32_t unencoded_val;
 
-		n_bits = get_n_bits32(&unencoded_val, unencoded_len, stream_pos,
-				  setup->bitstream_adr, setup->max_stream_len);
-		if (n_bits <= 0)
+		stream_pos = get_n_bits32(&unencoded_val, setup->max_data_bits, stream_pos,
+					  setup->bitstream_adr, setup->max_stream_len);
+		if (stream_pos < 0)
+			return stream_pos;
+		/* consistency check: outliers must be bigger than the outlier_par */
+		if (unencoded_val < setup->outlier_par && unencoded_val != 0)
 			return -1;
 
-		*decoded_value = unencoded_val + setup->outlier_par;
-		stream_pos += unencoded_len;
+		*decoded_value = unencoded_val;
 	}
+
+	(*decoded_value)--;
+	if (*decoded_value == 0xFFFFFFFF) /* catch underflow */
+		(*decoded_value) >>=  (32 - setup->max_data_bits);
+
 	return stream_pos;
 }
 
 
-static int decode_zero(uint32_t *decoded_value, int stream_pos,
-			   const struct decoder_setup *setup)
+/**
+ * @brief decode a Golomb/Rice encoded code word with multi escape system
+ *	mechanism from the bitstream
+ *
+ * @param decoded_value	pointer to the decoded value
+ * @param stream_pos	start bit position code word to be decoded in the bitstream
+ * @param setup		pointer to the decoder setup
+ *
+ * @returns bit index of the next code word in the bitstream on success; returns
+ *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	bitstream buffer is too small to read the value from the bitstream
+ */
+
+static int decode_multi(uint32_t *decoded_value, int stream_pos,
+			const struct decoder_setup *setup)
 {
 	stream_pos = decode_normal(decoded_value, stream_pos, setup);
 
-	if (stream_pos <= 0)
-		return stream_pos;
-
-	if (*decoded_value > setup->outlier_par) /* consistency check */
-		return -1;
+	if (*decoded_value >= setup->outlier_par) {
+		/* escape symbol mechanism was used; read unencoded value */
+		uint32_t unencoded_val;
+		unsigned int unencoded_len;
 
-	if (*decoded_value == 0) {/* escape symbol mechanism was used; read unencoded value */
-		int n_bits;
-		uint32_t unencoded_val = 0;
+		unencoded_len = (*decoded_value - setup->outlier_par + 1) * 2;
 
-		n_bits = get_n_bits32(&unencoded_val, setup->max_data_bits, stream_pos,
-				  setup->bitstream_adr, setup->max_stream_len);
-		if (n_bits <= 0)
-			return -1;
-		if (unencoded_val < setup->outlier_par && unencoded_val != 0) /* consistency check */
-			return -1;
+		stream_pos = get_n_bits32(&unencoded_val, unencoded_len, stream_pos,
+					  setup->bitstream_adr, setup->max_stream_len);
 
-		*decoded_value = unencoded_val;
-		stream_pos += setup->max_data_bits;
+		*decoded_value = unencoded_val + setup->outlier_par;
 	}
-	(*decoded_value)--;
-	if (*decoded_value == 0xFFFFFFFF) /* catch underflow */
-		(*decoded_value) = (*decoded_value) >> (32-setup->max_data_bits);
 	return stream_pos;
 }
 
@@ -332,21 +432,36 @@ static uint32_t re_map_to_pos(uint32_t value_to_unmap)
 		if (value_to_unmap == 0xFFFFFFFF) /* catch overflow */
 			return 0x80000000;
 		return -((value_to_unmap + 1) / 2);
-	} else
+	} else {
 		return value_to_unmap / 2;
+	}
 }
 
 
+/**
+ * @brief decompress the next code word in the bitstream and decorate it with
+ *	the model
+ *
+ * @param decoded_value	pointer to the decoded value
+ * @param model		model of the decoded_value (0 if not used)
+ * @param stream_pos	start bit position code word to be decoded in the bitstream
+ * @param setup		pointer to the decoder setup
+ *
+ * @returns bit index of the next code word in the bitstream on success; returns
+ *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	bitstream buffer is too small to read the value from the bitstream
+ */
+
 static int decode_value(uint32_t *decoded_value, uint32_t model,
 			int stream_pos, const struct decoder_setup *setup)
 {
 	uint32_t mask = (~0U >> (32 - setup->max_data_bits)); /* mask the used bits */
 
-	stream_pos = setup->encode_method_f(decoded_value, stream_pos, setup);
+	stream_pos = setup->decode_method_f(decoded_value, stream_pos, setup);
 	if (stream_pos <= 0)
 		return stream_pos;
 
-	*decoded_value = re_map_to_pos(*decoded_value); //, setup->max_used_bits);
+	*decoded_value = re_map_to_pos(*decoded_value);
 
 	*decoded_value += round_fwd(model, setup->lossy_par);
 
@@ -364,9 +479,9 @@ static int configure_decoder_setup(struct decoder_setup *setup,
 				   const struct cmp_cfg *cfg)
 {
 	if (multi_escape_mech_is_used(cfg->cmp_mode))
-		setup->encode_method_f = &decode_multi;
+		setup->decode_method_f = &decode_multi;
 	else if (zero_escape_mech_is_used(cfg->cmp_mode))
-		setup->encode_method_f = &decode_zero;
+		setup->decode_method_f = &decode_zero;
 	else {
 		debug_print("Error: Compression mode not supported.\n");
 		return -1;
@@ -396,6 +511,7 @@ static int configure_decoder_setup(struct decoder_setup *setup,
 
 static int decompress_imagette(struct cmp_cfg *cfg)
 {
+	int err;
 	size_t i;
 	int stream_pos = 0;
 	struct decoder_setup setup;
@@ -404,10 +520,9 @@ static int decompress_imagette(struct cmp_cfg *cfg)
 	uint16_t *up_model_buf = cfg->icu_new_model_buf;
 	uint32_t decoded_value = 0;
 	uint16_t model;
-	int err;
 
 	err = configure_decoder_setup(&setup, cfg->golomb_par, cfg->spill,
-				      cfg->round, 16, cfg);
+				      cfg->round, max_used_bits.nc_imagette, cfg);
 	if (err)
 		return -1;
 
@@ -432,118 +547,1588 @@ static int decompress_imagette(struct cmp_cfg *cfg)
 	return stream_pos;
 }
 
-static int decompressed_data_internal(struct cmp_cfg *cfg)
-{
-	int data_size, strem_len_bit = -1;
 
-	if (!cfg)
-		return 0; /* or -1? */
-	if (!cfg->icu_output_buf)
+/**
+ * @brief TODO: decompress the multi-entry packet header structure and sets the data,
+ *	model and up_model pointers to the data after the header
+ *
+ * @param data		pointer to a pointer pointing to the data to be compressed
+ * @param model		pointer to a pointer pointing to the model of the data
+ * @param up_model	pointer to a pointer pointing to the updated model buffer
+ * @param cfg		pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *
+ * @note the (void **) cast relies on all pointer types having the same internal
+ *	representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html
+ */
+
+static int decompress_multi_entry_hdr(void **data, void **model, void **up_model,
+				      const struct cmp_cfg *cfg)
+{
+	if (cfg->buffer_length < MULTI_ENTRY_HDR_SIZE)
 		return -1;
 
-	data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
-	if (!cfg->input_buf || !data_size)
-		return data_size;
+	if (*data) {
+		if (cfg->icu_output_buf)
+			memcpy(*data, cfg->icu_output_buf, MULTI_ENTRY_HDR_SIZE);
+		*data = (uint8_t *)*data + MULTI_ENTRY_HDR_SIZE;
+	}
 
-	if (model_mode_is_used(cfg->cmp_mode))
-		if (!cfg->model_buf)
-			return -1;
+	if (*model) {
+		if (cfg->icu_output_buf)
+			memcpy(*model, cfg->icu_output_buf, MULTI_ENTRY_HDR_SIZE);
+		*model = (uint8_t *)*model + MULTI_ENTRY_HDR_SIZE;
+	}
 
-	if (cfg->cmp_mode == CMP_MODE_RAW) {
+	if (*up_model) {
+		if (cfg->icu_output_buf)
+			memcpy(*up_model, cfg->icu_output_buf, MULTI_ENTRY_HDR_SIZE);
+		*up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE;
+	}
 
-		if ((unsigned int)data_size < cfg->buffer_length/CHAR_BIT)
-			return -1;
+	return MULTI_ENTRY_HDR_SIZE * CHAR_BIT;
+}
 
-		if (cfg->input_buf) {
-			memcpy(cfg->input_buf, cfg->icu_output_buf, data_size);
-			if (cmp_input_big_to_cpu_endianness(cfg->input_buf, data_size, cfg->data_type))
-				return -1;
-			strem_len_bit = data_size * CHAR_BIT;
-		}
 
-	} else {
-		switch (cfg->data_type) {
-		case DATA_TYPE_IMAGETTE:
-			strem_len_bit = decompress_imagette(cfg);
-			break;
-		default:
-			strem_len_bit = -1;
-			debug_print("Error: Compressed data type not supported.\n");
-			break;
-		}
+/**
+ * @brief decompress short normal light flux (S_FX) data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_s_fx(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx;
+	struct s_fx *data_buf = cfg->input_buf;
+	struct s_fx *model_buf = cfg->model_buf;
+	struct s_fx *up_model_buf = NULL;
+	struct s_fx *next_model_p;
+	struct s_fx model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
 	}
-	/* TODO: is this usefull? if (strem_len_bit != data_size * CHAR_BIT) { */
-	if (strem_len_bit <= 0)
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.s_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.s_fx, cfg))
 		return -1;
 
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
 
-	return data_size;
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
 }
 
 
-int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
-			 void *up_model_buf, void *decompressed_data)
+/**
+ * @brief decompress S_FX_DFX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_s_fx_efx(const struct cmp_cfg *cfg)
 {
-	int err;
-	struct cmp_cfg cfg = {0};
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_efx;
+	struct s_fx_efx *data_buf = cfg->input_buf;
+	struct s_fx_efx *model_buf = cfg->model_buf;
+	struct s_fx_efx *up_model_buf = NULL;
+	struct s_fx_efx *next_model_p;
+	struct s_fx_efx model;
 
-	cfg.model_buf = model_buf;
-	cfg.icu_new_model_buf = up_model_buf;
-	cfg.input_buf = decompressed_data;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	if (!ent)
-		return -1;
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
 
-	err = cmp_ent_read_header(ent, &cfg);
-	if (err)
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.s_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.s_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				    cfg->round, max_used_bits.s_efx, cfg))
 		return -1;
 
-	return decompressed_data_internal(&cfg);
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.efx, stream_pos,
+					  &setup_efx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].efx = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+							   cfg->model_value, setup_efx.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
 }
 
 
-/* model buffer is overwritten with updated model */
+/**
+ * @brief decompress short S_FX_NCOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
 
-int decompress_data(uint32_t *compressed_data, void *de_model_buf,
-		    const struct cmp_info *info, void *decompressed_data)
+static int decompress_s_fx_ncob(const struct cmp_cfg *cfg)
 {
-	int size_decomp_data;
-	struct cmp_cfg cfg = {0};
-
-	if (!compressed_data)
-		return -1;
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_ncob;
+	struct s_fx_ncob *data_buf = cfg->input_buf;
+	struct s_fx_ncob *model_buf = cfg->model_buf;
+	struct s_fx_ncob *up_model_buf = NULL;
+	struct s_fx_ncob *next_model_p;
+	struct s_fx_ncob model;
 
-	if (!info)
-		return -1;
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
 
-	if (info->cmp_err)
-		return -1;
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
 
-	if (model_mode_is_used(info->cmp_mode_used))
-		if (!de_model_buf)
-			return -1;
-	/* TODO: add ohter modes */
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
 
-	if (!decompressed_data)
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.s_exp_flags, cfg))
 		return -1;
-
-	/* cfg.data_type = info->data_type_used; */
-	cfg.cmp_mode = info->cmp_mode_used;
-	cfg.model_value = info->model_value_used;
-	cfg.round = info->round_used;
-	cfg.spill = info->spill_used;
-	cfg.golomb_par = info->golomb_par_used;
-	cfg.samples = info->samples_used;
-	cfg.icu_output_buf = compressed_data;
-	cfg.buffer_length = cmp_bit_to_4byte(info->cmp_size);
-	cfg.input_buf = decompressed_data;
-	cfg.model_buf = de_model_buf;
-	size_decomp_data = decompressed_data_internal(&cfg);
-	if (size_decomp_data <= 0)
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.s_fx, cfg))
 		return -1;
-	else
-		return 0;
+	if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				    cfg->round, max_used_bits.s_ncob, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
 
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
 
+		stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_y = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+							      cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+							      cfg->model_value, setup_ncob.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress short S_FX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, setup_efx, setup_ecob;
+	struct s_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct s_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct s_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct s_fx_efx_ncob_ecob *next_model_p;
+	struct s_fx_efx_ncob_ecob model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.s_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.s_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				    cfg->round, max_used_bits.s_ncob, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				    cfg->round, max_used_bits.s_efx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				    cfg->round, max_used_bits.s_ecob, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_y = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.efx, stream_pos,
+					  &setup_efx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].efx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ecob_x, stream_pos,
+					  &setup_ecob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ecob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ecob_y, stream_pos,
+					  &setup_ecob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ecob_y = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+							      cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+							      cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+							   cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+							      cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+							      cfg->model_value, setup_ecob.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress fast normal light flux (F_FX) data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_f_fx(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_fx;
+	struct f_fx *data_buf = cfg->input_buf;
+	struct f_fx *model_buf = cfg->model_buf;
+	struct f_fx *up_model_buf = NULL;
+	struct f_fx *next_model_p;
+	struct f_fx model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.f_fx, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		if (up_model_buf)
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress F_FX_DFX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_f_fx_efx(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_fx, setup_efx;
+	struct f_fx_efx *data_buf = cfg->input_buf;
+	struct f_fx_efx *model_buf = cfg->model_buf;
+	struct f_fx_efx *up_model_buf = NULL;
+	struct f_fx_efx *next_model_p;
+	struct f_fx_efx model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.f_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				    cfg->round, max_used_bits.f_efx, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.efx, stream_pos,
+					  &setup_efx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].efx = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+							   cfg->model_value, setup_efx.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress short F_FX_NCOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_f_fx_ncob(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_fx, setup_ncob;
+	struct f_fx_ncob *data_buf = cfg->input_buf;
+	struct f_fx_ncob *model_buf = cfg->model_buf;
+	struct f_fx_ncob *up_model_buf = NULL;
+	struct f_fx_ncob *next_model_p;
+	struct f_fx_ncob model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.f_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				    cfg->round, max_used_bits.f_ncob, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_y = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+							      cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+							      cfg->model_value, setup_ncob.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress short F_FX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_fx, setup_ncob, setup_efx, setup_ecob;
+	struct f_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct f_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct f_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct f_fx_efx_ncob_ecob *next_model_p;
+	struct f_fx_efx_ncob_ecob model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.f_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				    cfg->round, max_used_bits.f_ncob, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				    cfg->round, max_used_bits.f_efx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				    cfg->round, max_used_bits.f_ecob, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos,
+					  &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_y = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.efx, stream_pos,
+					  &setup_efx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].efx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ecob_x, stream_pos,
+					  &setup_ecob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ecob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ecob_y, stream_pos,
+					  &setup_ecob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ecob_y = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress long normal light flux (L_FX) data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_l_fx(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_fx_var;
+	struct l_fx *data_buf = cfg->input_buf;
+	struct l_fx *model_buf = cfg->model_buf;
+	struct l_fx *up_model_buf = NULL;
+	struct l_fx *next_model_p;
+	struct l_fx model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.l_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.l_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				    cfg->round, max_used_bits.l_fx_variance, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx_variance, stream_pos,
+					  &setup_fx_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx_variance = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+								   cfg->model_value, setup_fx_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress L_FX_EFX data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_l_fx_efx(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_efx, setup_fx_var;
+	struct l_fx_efx *data_buf = cfg->input_buf;
+	struct l_fx_efx *model_buf = cfg->model_buf;
+	struct l_fx_efx *up_model_buf = NULL;
+	struct l_fx_efx *next_model_p;
+	struct l_fx_efx model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.l_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.l_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				    cfg->round, max_used_bits.l_efx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				    cfg->round, max_used_bits.l_fx_variance, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.efx, stream_pos,
+					  &setup_efx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].efx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx_variance, stream_pos,
+					  &setup_fx_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx_variance = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+								 cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+							  cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+							   cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+								   cfg->model_value, setup_fx_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress L_FX_NCOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_l_fx_ncob(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_ncob,
+			     setup_fx_var, setup_cob_var;
+	struct l_fx_ncob *data_buf = cfg->input_buf;
+	struct l_fx_ncob *model_buf = cfg->model_buf;
+	struct l_fx_ncob *up_model_buf = NULL;
+	struct l_fx_ncob *next_model_p;
+	struct l_fx_ncob model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.l_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.l_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				    cfg->round, max_used_bits.l_ncob, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				    cfg->round, max_used_bits.l_fx_variance, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				    cfg->round, max_used_bits.l_cob_variance, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_x,
+					  stream_pos, &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_y,
+					  stream_pos, &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_y = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx_variance,
+					  stream_pos, &setup_fx_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx_variance = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.cob_x_variance,
+					  stream_pos, &setup_cob_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].cob_x_variance = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.cob_y_variance,
+					  stream_pos, &setup_cob_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].cob_y_variance = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+			up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress L_FX_EFX_NCOB_ECOB data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, setup_efx,
+			     setup_ecob, setup_fx_var, setup_cob_var;
+	struct l_fx_efx_ncob_ecob *data_buf = cfg->input_buf;
+	struct l_fx_efx_ncob_ecob *model_buf = cfg->model_buf;
+	struct l_fx_efx_ncob_ecob *up_model_buf = NULL;
+	struct l_fx_efx_ncob_ecob *next_model_p;
+	struct l_fx_efx_ncob_ecob model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+				    cfg->round, max_used_bits.l_exp_flags, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
+				    cfg->round, max_used_bits.l_fx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
+				    cfg->round, max_used_bits.l_ncob, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
+				    cfg->round, max_used_bits.l_efx, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
+				    cfg->round, max_used_bits.l_ecob, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				    cfg->round, max_used_bits.l_fx_variance, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance,
+				    cfg->round, max_used_bits.l_cob_variance, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.exp_flags,
+					  stream_pos, &setup_exp_flags);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].exp_flags = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx, stream_pos,
+					  &setup_fx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_x,
+					  stream_pos, &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ncob_y,
+					  stream_pos, &setup_ncob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ncob_y = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.efx, stream_pos,
+					  &setup_efx);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].efx = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ecob_x,
+					  stream_pos, &setup_ecob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ecob_x = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.ecob_y,
+					  stream_pos, &setup_ecob);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].ecob_y = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.fx_variance,
+					  stream_pos, &setup_fx_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].fx_variance = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.cob_x_variance,
+					  stream_pos, &setup_cob_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].cob_x_variance = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.cob_y_variance,
+					  stream_pos, &setup_cob_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].cob_y_variance = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags,
+				cfg->model_value, setup_exp_flags.lossy_par);
+			up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx,
+				cfg->model_value, setup_fx.lossy_par);
+			up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
+				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
+				cfg->model_value, setup_fx_var.lossy_par);
+			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+			up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance,
+				cfg->model_value, setup_cob_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress N-CAM offset data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_nc_offset(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_mean, setup_var;
+	struct nc_offset *data_buf = cfg->input_buf;
+	struct nc_offset *model_buf = cfg->model_buf;
+	struct nc_offset *up_model_buf = NULL;
+	struct nc_offset *next_model_p;
+	struct nc_offset model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				    cfg->round, max_used_bits.nc_offset_mean, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				    cfg->round, max_used_bits.nc_offset_variance, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.mean, stream_pos,
+					  &setup_mean);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].mean = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.variance, stream_pos,
+					  &setup_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].variance = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean,
+				model.mean, cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance = cmp_up_model(data_buf[i].variance,
+				model.variance, cfg->model_value, setup_var.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress N-CAM background data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_nc_background(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_mean, setup_var, setup_pix;
+	struct nc_background *data_buf = cfg->input_buf;
+	struct nc_background *model_buf = cfg->model_buf;
+	struct nc_background *up_model_buf = NULL;
+	struct nc_background *next_model_p;
+	struct nc_background model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				    cfg->round, max_used_bits.nc_background_mean, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				    cfg->round, max_used_bits.nc_background_variance, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+				    cfg->round, max_used_bits.nc_background_outlier_pixels, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.mean, stream_pos,
+					  &setup_mean);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].mean = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.variance, stream_pos,
+					  &setup_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].variance = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.outlier_pixels, stream_pos,
+					  &setup_pix);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].outlier_pixels = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean,
+				model.mean, cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance = cmp_up_model(data_buf[i].variance,
+				model.variance, cfg->model_value, setup_var.lossy_par);
+			up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels,
+				model.outlier_pixels, cfg->model_value, setup_pix.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+/**
+ * @brief decompress N-CAM smearing data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns the bit length of the bitstream on success; negative on error,
+ *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	value in the bitstream
+ */
+
+static int decompress_smearing(const struct cmp_cfg *cfg)
+{
+	size_t i;
+	int stream_pos = 0;
+	uint32_t decoded_value;
+	struct decoder_setup setup_mean, setup_var, setup_pix;
+	struct smearing *data_buf = cfg->input_buf;
+	struct smearing *model_buf = cfg->model_buf;
+	struct smearing *up_model_buf = NULL;
+	struct smearing *next_model_p;
+	struct smearing model;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		up_model_buf = cfg->icu_new_model_buf;
+
+	stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf,
+						(void **)&up_model_buf, cfg);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		model = model_buf[0];
+		next_model_p = &model_buf[1];
+	} else {
+		memset(&model, 0, sizeof(model));
+		next_model_p = data_buf;
+	}
+
+	if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+				    cfg->round, max_used_bits.smeating_mean, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+				    cfg->round, max_used_bits.smeating_variance_mean, cfg))
+		return -1;
+	if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+				    cfg->round, max_used_bits.smearing_outlier_pixels, cfg))
+		return -1;
+
+	for (i = 0; ; i++) {
+		stream_pos = decode_value(&decoded_value, model.mean, stream_pos,
+					  &setup_mean);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].mean = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.variance_mean, stream_pos,
+					  &setup_var);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].variance_mean = decoded_value;
+
+		stream_pos = decode_value(&decoded_value, model.outlier_pixels, stream_pos,
+					  &setup_pix);
+		if (stream_pos <= 0)
+			return stream_pos;
+		data_buf[i].outlier_pixels = decoded_value;
+
+		if (up_model_buf) {
+			up_model_buf[i].mean = cmp_up_model(data_buf[i].mean,
+				model.mean, cfg->model_value, setup_mean.lossy_par);
+			up_model_buf[i].variance_mean = cmp_up_model(data_buf[i].variance_mean,
+				model.variance_mean, cfg->model_value, setup_var.lossy_par);
+			up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels,
+				model.outlier_pixels, cfg->model_value, setup_pix.lossy_par);
+		}
+
+		if (i >= cfg->samples-1)
+			break;
+
+		model = next_model_p[i];
+	}
+	return stream_pos;
+}
+
+
+static int decompressed_data_internal(struct cmp_cfg *cfg)
+{
+	int data_size, strem_len_bit = -1;
+
+	if (!cfg)
+		return 0; /* or -1? */
+	if (!cfg->icu_output_buf)
+		return -1;
+
+	data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+	if (!cfg->input_buf || !data_size)
+		return data_size;
+
+	if (model_mode_is_used(cfg->cmp_mode))
+		if (!cfg->model_buf)
+			return -1;
+
+	if (cfg->cmp_mode == CMP_MODE_RAW) {
+
+		if ((unsigned int)data_size < cfg->buffer_length/CHAR_BIT)
+			return -1;
+
+		if (cfg->input_buf) {
+			memcpy(cfg->input_buf, cfg->icu_output_buf, data_size);
+			if (cmp_input_big_to_cpu_endianness(cfg->input_buf, data_size, cfg->data_type))
+				return -1;
+			strem_len_bit = data_size * CHAR_BIT;
+		}
+
+	} else {
+		switch (cfg->data_type) {
+		case DATA_TYPE_IMAGETTE:
+		case DATA_TYPE_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_SAT_IMAGETTE:
+		case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+		case DATA_TYPE_F_CAM_IMAGETTE:
+		case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+			strem_len_bit = decompress_imagette(cfg);
+			break;
+		case DATA_TYPE_S_FX:
+			strem_len_bit = decompress_s_fx(cfg);
+			break;
+		case DATA_TYPE_S_FX_DFX:
+			strem_len_bit = decompress_s_fx_efx(cfg);
+			break;
+		case DATA_TYPE_S_FX_NCOB:
+			strem_len_bit = decompress_s_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+			strem_len_bit = decompress_s_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_F_FX:
+			strem_len_bit = decompress_f_fx(cfg);
+			break;
+		case DATA_TYPE_F_FX_DFX:
+			strem_len_bit = decompress_f_fx_efx(cfg);
+			break;
+		case DATA_TYPE_F_FX_NCOB:
+			strem_len_bit = decompress_f_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+			strem_len_bit = decompress_f_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_L_FX:
+			strem_len_bit = decompress_l_fx(cfg);
+			break;
+		case DATA_TYPE_L_FX_DFX:
+			strem_len_bit = decompress_l_fx_efx(cfg);
+			break;
+		case DATA_TYPE_L_FX_NCOB:
+			strem_len_bit = decompress_l_fx_ncob(cfg);
+			break;
+		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+			strem_len_bit = decompress_l_fx_efx_ncob_ecob(cfg);
+			break;
+
+		case DATA_TYPE_OFFSET:
+			strem_len_bit = decompress_nc_offset(cfg);
+			break;
+		case DATA_TYPE_BACKGROUND:
+			strem_len_bit = decompress_nc_background(cfg);
+			break;
+		case DATA_TYPE_SMEARING:
+			strem_len_bit = decompress_smearing(cfg);
+			break;
+
+		case DATA_TYPE_F_CAM_OFFSET:
+		case DATA_TYPE_F_CAM_BACKGROUND:
+		case DATA_TYPE_UNKNOWN:
+		default:
+			strem_len_bit = -1;
+			debug_print("Error: Compressed data type not supported.\n");
+			break;
+		}
+
+	}
+	/* TODO: is this usefull? if (strem_len_bit != data_size * CHAR_BIT) { */
+	if (strem_len_bit <= 0)
+		return -1;
+
+	return data_size;
+}
+
+
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+			 void *up_model_buf, void *decompressed_data)
+{
+	int err;
+	struct cmp_cfg cfg = {0};
+
+	cfg.model_buf = model_buf;
+	cfg.icu_new_model_buf = up_model_buf;
+	cfg.input_buf = decompressed_data;
+
+	if (!ent)
+		return -1;
+
+	err = cmp_ent_read_header(ent, &cfg);
+	if (err)
+		return -1;
+
+	return decompressed_data_internal(&cfg);
+}
+
+
+/* model buffer is overwritten with updated model */
+
+int decompress_data(uint32_t *compressed_data, void *de_model_buf,
+		    const struct cmp_info *info, void *decompressed_data)
+{
+	int size_decomp_data;
+	struct cmp_cfg cfg = {0};
+
+	if (!compressed_data)
+		return -1;
+
+	if (!info)
+		return -1;
+
+	if (info->cmp_err)
+		return -1;
+
+	if (model_mode_is_used(info->cmp_mode_used))
+		if (!de_model_buf)
+			return -1;
+	/* TODO: add ohter modes */
+
+	if (!decompressed_data)
+		return -1;
+
+	/* cfg.data_type = info->data_type_used; */
+	cfg.cmp_mode = info->cmp_mode_used;
+	cfg.model_value = info->model_value_used;
+	cfg.round = info->round_used;
+	cfg.spill = info->spill_used;
+	cfg.golomb_par = info->golomb_par_used;
+	cfg.samples = info->samples_used;
+	cfg.icu_output_buf = compressed_data;
+	cfg.buffer_length = cmp_bit_to_4byte(info->cmp_size);
+	cfg.input_buf = decompressed_data;
+	cfg.model_buf = de_model_buf;
+	size_decomp_data = decompressed_data_internal(&cfg);
+	if (size_decomp_data <= 0)
+		return -1;
+	else
+		return 0;
 }
diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c
index 523b64f..cb00bb0 100644
--- a/test/cmp_icu/test_decmp.c
+++ b/test/cmp_icu/test_decmp.c
@@ -10,12 +10,14 @@
 #include "../../lib/decmp.c" /* .c file included to test static functions */
 
 
-/* returns the needed size of the compression entry header plus the max size of the
+/**
+ * returns the needed size of the compression entry header plus the max size of the
  * compressed data if ent ==  NULL if ent is set the size of the compression
- * entry */
+ * entry (entity header + compressed data)
+ */
 size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cfg)
 {
-	size_t s, hdr_size;
+	size_t s;
 	struct cmp_cfg cfg_cpy;
 	int cmp_size_bits;
 
@@ -25,33 +27,38 @@ size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cf
 	if (cfg->icu_output_buf)
 		debug_print("Warning the set buffer for the compressed data is ignored! The compressed data are write to the compression entry.");
 
-	if (!ent) {
-		s = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type);
-		if (!s)
-			return 0;
+	s = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type);
+	if (!s)
+		return 0;
+	/* we round down to the next 4-byte allied address because we access the
+	 * cmp_buffer in uint32_t words
+	 */
+	if (cfg->cmp_mode != CMP_MODE_RAW)
+		s &= ~0x3U;
 
-		hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW);
-		if (!hdr_size)
-			return 0;
+	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, s);
 
-		return s + hdr_size;
-	}
+	if (!ent || !s)
+		return s;
 
 	cfg_cpy = *cfg;
 	cfg_cpy.icu_output_buf = cmp_ent_get_data_buf(ent);
-
+	if (!cfg_cpy.icu_output_buf)
+		return 0;
 	cmp_size_bits = icu_compress_data(&cfg_cpy);
 	if (cmp_size_bits < 0)
 		return 0;
 
+	/* XXX overwrite the size of the compression entity with the size of the
+	 * actual size of the compressed data */
+	/* not all allocated memory is normally needed */
 	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW,
-					 cmp_bit_to_4byte(cmp_size_bits));
-	if (!s)
-		return 0;
+			   cmp_bit_to_4byte(cmp_size_bits));
 
 	if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits))
 		return 0;
 
+
 	return s;
 }
 
@@ -177,7 +184,7 @@ void test_decode_normal(void)
 		TEST_ASSERT_EQUAL_HEX(sample, decoded_value);
 	}
 
-	 /* TODO error case: negativ stream_pos */
+	 /* TODO error case: negative stream_pos */
 }
 
 
@@ -288,12 +295,75 @@ void test_decompress_imagette_model(void)
 	TEST_ASSERT_EQUAL_HEX(4, up_model[4]);
 }
 
+
+
+#define CMP_PAR_UNUSED 0 /*TODO: remove this*/
+#define DATA_SAMPLES 5
+void test_cmp_decmp_s_fx_diff(void)
+{
+	size_t s;
+	int err;
+
+	struct cmp_entity *ent;
+	const uint32_t MAX_VALUE = ~(~0U << MAX_USED_S_FX_BITS);
+	struct s_fx data_entry[DATA_SAMPLES] = {
+		{0,0}, {1,23}, {2,42}, {3,MAX_VALUE}, {3,MAX_VALUE>>1} };
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE + sizeof(data_entry)];
+	struct s_fx *decompressed_data = NULL;
+	/* uint32_t *compressed_data = NULL; */
+	uint32_t compressed_data_len_samples = DATA_SAMPLES;
+	struct cmp_cfg cfg;
+
+	for (s = 0; s < MULTI_ENTRY_HDR_SIZE; s++)
+		data_to_compress[s] = s;
+	memcpy(&data_to_compress[MULTI_ENTRY_HDR_SIZE], data_entry, sizeof(data_entry));
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_DIFF_MULTI,
+				 CMP_PAR_UNUSED, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	s = cmp_cfg_icu_buffers(&cfg, data_to_compress, DATA_SAMPLES, NULL, NULL,
+				NULL, compressed_data_len_samples);
+	TEST_ASSERT_TRUE(s);
+
+	err = cmp_cfg_fx_cob(&cfg, 2, 6, 4, 14, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			     CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			     CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(err);
+
+	s = icu_compress_data_entity(NULL, &cfg);
+	TEST_ASSERT_TRUE(s);
+	ent = malloc(s); TEST_ASSERT_TRUE(ent);
+	s = icu_compress_data_entity(ent, &cfg);
+	TEST_ASSERT_TRUE(s);
+
+	/* now decompress the data */
+	s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), s);
+	decompressed_data = malloc(s); TEST_ASSERT_TRUE(decompressed_data);
+	s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), s);
+
+	TEST_ASSERT_FALSE(memcmp(data_to_compress, decompressed_data, s));
+	/* for (i = 0; i < samples; ++i) { */
+	/* 	printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round); */
+	/* 	uint32_t mask = ~0U << round; */
+	/* 	if ((data[i]&mask) != (decompressed_data[i]&mask)) */
+	/* 		TEST_ASSERT(0); */
+	/* 	if (model_mode_is_used(cmp_mode)) */
+	/* 		if (up_model[i] != de_up_model[i]) */
+	/* 			TEST_ASSERT(0); */
+	/* } */
+}
+#undef DATA_SAMPLES
+
+
 int my_random(unsigned int min, unsigned int max)
 {
-	if (max-min > RAND_MAX)
-		TEST_ASSERT(0);
 	if (min > max)
 		TEST_ASSERT(0);
+	if (max-min > RAND_MAX)
+		TEST_ASSERT(0);
 	return min + rand() / (RAND_MAX / (max - min + 1) + 1);
 }
 
@@ -394,7 +464,7 @@ void test_imagette_random(void)
 
 	/* create a compression configuration */
 	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, round);
-	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKOWN);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
 
 
 	cmp_data_size = cmp_cfg_icu_buffers(&cfg, data, samples, model, up_model,
@@ -402,14 +472,14 @@ void test_imagette_random(void)
 	TEST_ASSERT_TRUE(cmp_data_size);
 
 	uint32_t golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
-	uint32_t max_spill = get_max_spill(golomb_par, data_type);
+	uint32_t max_spill = cmp_icu_max_spill(golomb_par);
 	TEST_ASSERT(max_spill > 1);
 	uint32_t spill = my_random(2, max_spill);
 
 	error = cmp_cfg_icu_imagette(&cfg, golomb_par, spill);
 	TEST_ASSERT_FALSE(error);
 
-	print_cfg(&cfg, 0);
+	/* print_cfg(&cfg, 0); */
 	s = icu_compress_data_entity(NULL, &cfg);
 	TEST_ASSERT_TRUE(s);
 	ent = malloc(s); TEST_ASSERT_TRUE(ent);
@@ -424,7 +494,7 @@ void test_imagette_random(void)
 	TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s);
 
 	for (i = 0; i < samples; ++i) {
-		printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round);
+		/* printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round); */
 		uint32_t mask = ~0U << round;
 		if ((data[i]&mask) != (decompressed_data[i]&mask))
 			TEST_ASSERT(0);
@@ -440,3 +510,227 @@ void test_imagette_random(void)
 	free(ent);
 	free(decompressed_data);
 }
+
+
+void test_s_fx_diff(void)
+{
+	size_t s, i;
+	uint8_t cmp_entity[88] = {
+		0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x58, 0x00, 0x00, 0x20, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x1C, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x41, 0x00, 0x08, 0x02, 0x08, 0xD0, 0x10, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xAE, 0xDE, 0x00, 0x00, 0x00, 0x73, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00,
+	};
+
+	uint8_t result_data[32] = {0};
+	struct multi_entry_hdr *hdr = (struct multi_entry_hdr *)result_data;
+	struct s_fx *data = (struct s_fx *)hdr->entry;
+	/* put some dummy data in the header*/
+	for (i = 0; i < sizeof(*hdr); ++i)
+		result_data[i] = i;
+	data[0].exp_flags = 0;
+	data[0].fx = 0;
+	data[1].exp_flags = 1;
+	data[1].fx = 0xFFFFFF;
+	data[2].exp_flags = 3;
+	data[2].fx = 0x7FFFFF;
+	data[3].exp_flags = 0;
+	data[3].fx = 0;
+
+	s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, NULL);
+	TEST_ASSERT_EQUAL_INT(sizeof(result_data), s);
+	uint8_t *decompressed_data = malloc(s);
+	TEST_ASSERT_TRUE(decompressed_data);
+	s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(sizeof(result_data), s);
+	for (i = 0; i < s; ++i) {
+		TEST_ASSERT_EQUAL(result_data[i], decompressed_data[i]);
+	}
+}
+
+
+void test_s_fx_model(void)
+{
+	size_t s, i;
+	uint8_t compressed_data_buf[92] = {
+		0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x20, 0x04, 0xF0, 0xC2, 0xD3, 0x47, 0xE4, 0x04, 0xF0, 0xC2, 0xD3, 0x48, 0x16, 0x00, 0x08, 0x03, 0x08, 0xD0, 0x10, 0x01, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x3B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5D, 0x80, 0x00, 0x00,
+	};
+	struct cmp_entity * cmp_entity = (struct cmp_entity *)compressed_data_buf;
+
+	uint8_t model_buf[32];
+	uint8_t decompressed_data[32];
+	uint8_t up_model_buf[32];
+	uint8_t exp_data_buf[32] = {0}; /* expected uncompressed data */
+	uint8_t exp_up_model_buf[32] = {0};
+
+	struct multi_entry_hdr *model_collection = (struct multi_entry_hdr *)model_buf;
+	struct s_fx *model_data = (struct s_fx *)model_collection->entry;
+
+	memset(model_collection, 0xFF, sizeof(*model_collection));
+	model_data[0].exp_flags = 0;
+	model_data[0].fx = 0;
+	model_data[1].exp_flags = 3;
+	model_data[1].fx = 0x7FFFFF;
+	model_data[2].exp_flags = 0;
+	model_data[2].fx = 0xFFFFFF;
+	model_data[3].exp_flags = 3;
+	model_data[3].fx = 0xFFFFFF;
+
+	struct multi_entry_hdr *exp_data_collection = (struct multi_entry_hdr *)exp_data_buf;
+	struct s_fx *exp_data = (struct s_fx *)exp_data_collection->entry;
+	/* put some dummy data in the header */
+	for (i = 0; i < sizeof(*exp_data_collection); i++)
+		exp_data_buf[i] = i;
+	exp_data[0].exp_flags = 0;
+	exp_data[0].fx = 0;
+	exp_data[1].exp_flags = 1;
+	exp_data[1].fx = 0xFFFFFF;
+	exp_data[2].exp_flags = 3;
+	exp_data[2].fx = 0x7FFFFF;
+	exp_data[3].exp_flags = 0;
+	exp_data[3].fx = 0;
+
+	struct multi_entry_hdr *exp_up_model_collection = (struct multi_entry_hdr *)exp_up_model_buf;
+	struct s_fx *exp_updated_model_data = (struct s_fx *)exp_up_model_collection->entry;
+	/* put some dummy data in the header*/
+	for (i = 0; i < sizeof(*exp_up_model_collection); i++)
+		exp_up_model_buf[i] = i;
+	exp_updated_model_data[0].exp_flags = 0;
+	exp_updated_model_data[0].fx = 0;
+	exp_updated_model_data[1].exp_flags = 2;
+	exp_updated_model_data[1].fx = 0xBFFFFF;
+	exp_updated_model_data[2].exp_flags = 1;
+	exp_updated_model_data[2].fx = 0xBFFFFF;
+	exp_updated_model_data[3].exp_flags = 1;
+	exp_updated_model_data[3].fx = 0x7FFFFF;
+
+	s = decompress_cmp_entiy(cmp_entity, model_buf, up_model_buf, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(sizeof(exp_data_buf), s);
+
+	TEST_ASSERT_FALSE(memcmp(exp_data_buf, decompressed_data, s));
+	TEST_ASSERT_FALSE(memcmp(exp_up_model_buf, up_model_buf, s));
+}
+
+/* TODO: implement this! */
+void generate_random_test_data(void *data, int samples,
+			       enum cmp_data_type data_type)
+{
+	int s = cmp_cal_size_of_data(samples, data_type);
+	memset(data, 0x0, s);
+}
+
+
+void test_random_compression_decompression(void)
+{
+	size_t s;
+	struct cmp_cfg cfg = {0};
+	struct cmp_entity *cmp_ent;
+	void *decompressed_data;
+	void *decompressed_up_model = NULL;
+
+	srand(0); /* TODO:XXX*/
+	puts("--------------------------------------------------------------");
+
+	/* for (cfg.data_type = DATA_TYPE_IMAGETTE; TODO:!! implement this */
+	/*      cfg.data_type < DATA_TYPE_F_CAM_BACKGROUND+1; cfg.data_type++) { */
+	for (cfg.data_type = DATA_TYPE_IMAGETTE;
+	     cfg.data_type < DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE+1; cfg.data_type++) {
+		cfg.samples = my_random(1,0x30000);
+			if (cfg.data_type == DATA_TYPE_OFFSET)
+				puts("FADF");
+
+		cfg.buffer_length = (CMP_ENTITY_MAX_SIZE - NON_IMAGETTE_HEADER_SIZE - MULTI_ENTRY_HDR_SIZE)/size_of_a_sample(cfg.data_type);;
+		s = cmp_cal_size_of_data(cfg.samples, cfg.data_type);
+		printf("%s\n", data_type2string(cfg.data_type));
+		TEST_ASSERT_TRUE(s);
+		cfg.input_buf = calloc(1, s);
+		TEST_ASSERT_NOT_NULL(cfg.input_buf);
+		cfg.model_buf = calloc(1, s);
+		TEST_ASSERT_TRUE(cfg.model_buf);
+		decompressed_data = calloc(1, s);
+		TEST_ASSERT_NOT_NULL(decompressed_data);
+		cfg.icu_new_model_buf = calloc(1, s);
+		TEST_ASSERT_TRUE(cfg.icu_new_model_buf);
+		decompressed_up_model = calloc(1, s);
+		TEST_ASSERT_TRUE(decompressed_up_model);
+		cmp_ent = calloc(1, CMP_ENTITY_MAX_SIZE);
+
+		generate_random_test_data(cfg.input_buf, cfg.samples, cfg.data_type);
+		generate_random_test_data(cfg.model_buf, cfg.samples, cfg.data_type);
+
+		cfg.model_value = my_random(0,16);
+		/* cfg.round = my_random(0,3); /1* XXX *1/ */
+		cfg.round = 0;
+
+		cfg.golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg.ap1_golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg.ap2_golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg.cmp_par_exp_flags = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_fx = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_ncob = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_efx = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_ecob = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_fx_cob_variance = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_mean = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_variance = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+		cfg.cmp_par_pixels_error = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+
+		cfg.spill = my_random(MIN_RDCU_SPILL, cmp_icu_max_spill(cfg.golomb_par));
+		cfg.ap1_spill = my_random(MIN_RDCU_SPILL, cmp_icu_max_spill(cfg.ap1_golomb_par));
+		cfg.ap2_spill = my_random(MIN_RDCU_SPILL, cmp_icu_max_spill(cfg.ap2_golomb_par));
+		if (!rdcu_supported_data_type_is_used(cfg.data_type)) {
+			cfg.spill_exp_flags = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_exp_flags));
+			cfg.spill_fx = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_fx));
+			cfg.spill_ncob = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_ncob));
+			cfg.spill_efx = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_efx));
+			cfg.spill_ecob = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_ecob));
+			cfg.spill_fx_cob_variance = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_fx_cob_variance));
+			cfg.spill_mean = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_mean));
+			cfg.spill_variance = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_variance));
+			cfg.spill_pixels_error = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_pixels_error));
+		}
+
+		for (cfg.cmp_mode = CMP_MODE_RAW; cfg.cmp_mode < CMP_MODE_STUFF; cfg.cmp_mode++) {
+			int cmp_size, decompress_size;
+
+			cmp_size = icu_compress_data_entity(cmp_ent, &cfg);
+			if (cmp_size <= 0) {
+				printf("cmp_size: %i\n", cmp_size);
+				print_cfg(&cfg, 0);
+			}
+			TEST_ASSERT_GREATER_THAN(0, cmp_size);
+
+			/* now decompress the data */
+			decompress_size = decompress_cmp_entiy(cmp_ent, cfg.model_buf,
+							       decompressed_up_model, decompressed_data);
+
+			TEST_ASSERT_EQUAL_INT(s, decompress_size);
+			if (memcmp(cfg.input_buf, decompressed_data, s)) {
+				print_cfg(&cfg, 0);
+				TEST_ASSERT_FALSE(memcmp(cfg.input_buf, decompressed_data, s));
+			}
+			if (model_mode_is_used(cfg.cmp_mode))
+				TEST_ASSERT_FALSE(memcmp(cfg.icu_new_model_buf, decompressed_up_model, s));
+
+			memset(cmp_ent, 0, CMP_ENTITY_MAX_SIZE);
+			memset(decompressed_data, 0, s);
+			memset(decompressed_up_model, 0, s);
+			memset(cfg.icu_new_model_buf, 0, s);
+		}
+
+		free(cfg.model_buf);
+		cfg.model_buf = NULL;
+		free(cfg.input_buf);
+		cfg.input_buf = NULL;
+		free(cfg.icu_new_model_buf);
+		cfg.icu_new_model_buf = NULL;
+		free(cmp_ent);
+		cmp_ent = NULL;
+		free(decompressed_data);
+		decompressed_data = NULL;
+		free(decompressed_up_model);
+		decompressed_up_model = NULL;
+
+	}
+}
-- 
GitLab


From 00d1990f9c454949bd6541e7e4278ef23fe195f1 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 1 Sep 2022 14:08:34 +0200
Subject: [PATCH 28/46] add test for cmp data types

---
 test/cmp_data_types/meson.build           | 12 +++++++++++
 test/cmp_data_types/test_cmp_data_types.c | 26 +++++++++++++++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 test/cmp_data_types/meson.build
 create mode 100644 test/cmp_data_types/test_cmp_data_types.c

diff --git a/test/cmp_data_types/meson.build b/test/cmp_data_types/meson.build
new file mode 100644
index 0000000..8de2ef8
--- /dev/null
+++ b/test/cmp_data_types/meson.build
@@ -0,0 +1,12 @@
+test_case = files('test_cmp_data_types.c')
+test_runner = test_runner_generator.process(test_case)
+
+test_cmp_icu = executable('test_cmp_data_types',
+   test_case, test_runner,
+   include_directories : incdir,
+   link_with : cmp_lib,
+   dependencies : unity_dep,
+   build_by_default : false
+)
+
+test('Compression Data Types Unit Tests', test_cmp_icu)
diff --git a/test/cmp_data_types/test_cmp_data_types.c b/test/cmp_data_types/test_cmp_data_types.c
new file mode 100644
index 0000000..881f46a
--- /dev/null
+++ b/test/cmp_data_types/test_cmp_data_types.c
@@ -0,0 +1,26 @@
+#include <stdint.h>
+
+#include "unity.h"
+#include "cmp_data_types.h"
+
+/**
+ * @test cmp_cal_size_of_data
+ */
+
+void test_cmp_cal_size_of_data(void)
+{
+	unsigned int s;
+
+	s = cmp_cal_size_of_data(1, DATA_TYPE_IMAGETTE);
+	TEST_ASSERT_EQUAL_UINT(sizeof(uint16_t), s);
+
+	s = cmp_cal_size_of_data(1, DATA_TYPE_F_FX);
+	TEST_ASSERT_EQUAL_UINT(sizeof(struct f_fx)+MULTI_ENTRY_HDR_SIZE, s);
+
+	/* overflow tests */
+	s = cmp_cal_size_of_data(0x1999999A, DATA_TYPE_BACKGROUND);
+	TEST_ASSERT_EQUAL_UINT(0, s);
+	s = cmp_cal_size_of_data(0x19999999, DATA_TYPE_BACKGROUND);
+	TEST_ASSERT_EQUAL_UINT(0, s);
+}
+
-- 
GitLab


From 326a32b1eacefed4ecc6b716c33524a427889a0b Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 2 Sep 2022 09:26:07 +0200
Subject: [PATCH 29/46] Change compression data types containing DFX to EFX

---
 include/cmp_support.h       | 12 +++++-----
 lib/cmp_data_types.c        | 24 +++++++++----------
 lib/cmp_entity.c            | 48 ++++++++++++++++++-------------------
 lib/cmp_icu.c               | 12 +++++-----
 lib/cmp_io.c                | 12 +++++-----
 lib/cmp_support.c           | 24 +++++++++----------
 lib/decmp.c                 | 16 ++++++-------
 test/cmp_icu/test_cmp_icu.c | 38 ++++++++++++++---------------
 8 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/include/cmp_support.h b/include/cmp_support.h
index 5c85a99..aa455a5 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -103,17 +103,17 @@ enum cmp_data_type {
 	DATA_TYPE_BACKGROUND,
 	DATA_TYPE_SMEARING,
 	DATA_TYPE_S_FX,
-	DATA_TYPE_S_FX_DFX,
+	DATA_TYPE_S_FX_EFX,
 	DATA_TYPE_S_FX_NCOB,
-	DATA_TYPE_S_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_S_FX_EFX_NCOB_ECOB,
 	DATA_TYPE_L_FX,
-	DATA_TYPE_L_FX_DFX,
+	DATA_TYPE_L_FX_EFX,
 	DATA_TYPE_L_FX_NCOB,
-	DATA_TYPE_L_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_L_FX_EFX_NCOB_ECOB,
 	DATA_TYPE_F_FX,
-	DATA_TYPE_F_FX_DFX,
+	DATA_TYPE_F_FX_EFX,
 	DATA_TYPE_F_FX_NCOB,
-	DATA_TYPE_F_FX_DFX_NCOB_ECOB,
+	DATA_TYPE_F_FX_EFX_NCOB_ECOB,
 	DATA_TYPE_F_CAM_IMAGETTE,
 	DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE,
 	DATA_TYPE_F_CAM_OFFSET,
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 5a01f8b..6ce5f4b 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -135,37 +135,37 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 	case DATA_TYPE_S_FX:
 		sample_size = sizeof(struct s_fx);
 		break;
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 		sample_size = sizeof(struct s_fx_efx);
 		break;
 	case DATA_TYPE_S_FX_NCOB:
 		sample_size = sizeof(struct s_fx_ncob);
 		break;
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 		sample_size = sizeof(struct s_fx_efx_ncob_ecob);
 		break;
 	case DATA_TYPE_L_FX:
 		sample_size = sizeof(struct l_fx);
 		break;
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 		sample_size = sizeof(struct l_fx_efx);
 		break;
 	case DATA_TYPE_L_FX_NCOB:
 		sample_size = sizeof(struct l_fx_ncob);
 		break;
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 		sample_size = sizeof(struct l_fx_efx_ncob_ecob);
 		break;
 	case DATA_TYPE_F_FX:
 		sample_size = sizeof(struct f_fx);
 		break;
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 		sample_size = sizeof(struct f_fx_efx);
 		break;
 	case DATA_TYPE_F_FX_NCOB:
 		sample_size = sizeof(struct f_fx_ncob);
 		break;
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		sample_size = sizeof(struct f_fx_efx_ncob_ecob);
 		break;
 	case DATA_TYPE_F_CAM_OFFSET:
@@ -493,37 +493,37 @@ int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
 	case DATA_TYPE_S_FX:
 		be_to_cpus_s_fx(data, samples);
 		break;
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 		be_to_cpus_s_fx_efx(data, samples);
 		break;
 	case DATA_TYPE_S_FX_NCOB:
 		be_to_cpus_s_fx_ncob(data, samples);
 		break;
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 		be_to_cpus_s_fx_efx_ncob_ecob(data, samples);
 		break;
 	case DATA_TYPE_L_FX:
 		be_to_cpus_l_fx(data, samples);
 		break;
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 		be_to_cpus_l_fx_efx(data, samples);
 		break;
 	case DATA_TYPE_L_FX_NCOB:
 		be_to_cpus_l_fx_ncob(data, samples);
 		break;
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 		be_to_cpus_l_fx_efx_ncob_ecob(data, samples);
 		break;
 	case DATA_TYPE_F_FX:
 		be_to_cpus_f_fx(data, samples);
 		break;
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 		be_to_cpus_f_fx_efx(data, samples);
 		break;
 	case DATA_TYPE_F_FX_NCOB:
 		be_to_cpus_f_fx_ncob(data, samples);
 		break;
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		be_to_cpus_f_fx_efx_ncob_ecob(data, samples);
 		break;
 	/* TODO: implement F_CAM conversion */
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index 6a5b040..c0b2898 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -82,17 +82,17 @@ uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode_flag)
 		case DATA_TYPE_BACKGROUND:
 		case DATA_TYPE_SMEARING:
 		case DATA_TYPE_S_FX:
-		case DATA_TYPE_S_FX_DFX:
+		case DATA_TYPE_S_FX_EFX:
 		case DATA_TYPE_S_FX_NCOB:
-		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 		case DATA_TYPE_L_FX:
-		case DATA_TYPE_L_FX_DFX:
+		case DATA_TYPE_L_FX_EFX:
 		case DATA_TYPE_L_FX_NCOB:
-		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 		case DATA_TYPE_F_FX:
-		case DATA_TYPE_F_FX_DFX:
+		case DATA_TYPE_F_FX_EFX:
 		case DATA_TYPE_F_FX_NCOB:
-		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		case DATA_TYPE_F_CAM_OFFSET:
 		case DATA_TYPE_F_CAM_BACKGROUND:
 			size = NON_IMAGETTE_HEADER_SIZE;
@@ -1661,17 +1661,17 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 	case DATA_TYPE_BACKGROUND:
 	case DATA_TYPE_SMEARING:
 	case DATA_TYPE_S_FX:
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 	case DATA_TYPE_S_FX_NCOB:
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_L_FX:
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 	case DATA_TYPE_L_FX_NCOB:
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_F_FX:
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 	case DATA_TYPE_F_FX_NCOB:
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
 		return ent->non_ima.cmp_data;
@@ -1893,17 +1893,17 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 			return -1;
 		break;
 	case DATA_TYPE_S_FX:
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 	case DATA_TYPE_S_FX_NCOB:
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_L_FX:
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 	case DATA_TYPE_L_FX_NCOB:
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_F_FX:
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 	case DATA_TYPE_F_FX_NCOB:
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_exp_flags))
 			return -1;
 		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_exp_flags))
@@ -2206,17 +2206,17 @@ int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 		cfg->spill_pixels_error = cmp_ent_get_non_ima_spill3(ent);
 		break;
 	case DATA_TYPE_S_FX:
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 	case DATA_TYPE_S_FX_NCOB:
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_L_FX:
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 	case DATA_TYPE_L_FX_NCOB:
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_F_FX:
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 	case DATA_TYPE_F_FX_NCOB:
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		cfg->cmp_par_exp_flags = cmp_ent_get_non_ima_cmp_par1(ent);
 		cfg->spill_exp_flags = cmp_ent_get_non_ima_spill1(ent);
 		cfg->cmp_par_fx = cmp_ent_get_non_ima_cmp_par2(ent);
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index c6d4a27..2d04120 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -2354,39 +2354,39 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 		case DATA_TYPE_S_FX:
 			cmp_size = compress_s_fx(cfg);
 			break;
-		case DATA_TYPE_S_FX_DFX:
+		case DATA_TYPE_S_FX_EFX:
 			cmp_size = compress_s_fx_efx(cfg);
 			break;
 		case DATA_TYPE_S_FX_NCOB:
 			cmp_size = compress_s_fx_ncob(cfg);
 			break;
-		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 			cmp_size = compress_s_fx_efx_ncob_ecob(cfg);
 			break;
 
 		case DATA_TYPE_F_FX:
 			cmp_size = compress_f_fx(cfg);
 			break;
-		case DATA_TYPE_F_FX_DFX:
+		case DATA_TYPE_F_FX_EFX:
 			cmp_size = compress_f_fx_efx(cfg);
 			break;
 		case DATA_TYPE_F_FX_NCOB:
 			cmp_size = compress_f_fx_ncob(cfg);
 			break;
-		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 			cmp_size = compress_f_fx_efx_ncob_ecob(cfg);
 			break;
 
 		case DATA_TYPE_L_FX:
 			cmp_size = compress_l_fx(cfg);
 			break;
-		case DATA_TYPE_L_FX_DFX:
+		case DATA_TYPE_L_FX_EFX:
 			cmp_size = compress_l_fx_efx(cfg);
 			break;
 		case DATA_TYPE_L_FX_NCOB:
 			cmp_size = compress_l_fx_ncob(cfg);
 			break;
-		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 			cmp_size = compress_l_fx_efx_ncob_ecob(cfg);
 			break;
 
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 83c6906..be0f8ed 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -46,17 +46,17 @@ static const struct {
 	{DATA_TYPE_BACKGROUND, "DATA_TYPE_BACKGROUND"},
 	{DATA_TYPE_SMEARING, "DATA_TYPE_SMEARING"},
 	{DATA_TYPE_S_FX, "DATA_TYPE_S_FX"},
-	{DATA_TYPE_S_FX_DFX, "DATA_TYPE_S_FX_DFX"},
+	{DATA_TYPE_S_FX_EFX, "DATA_TYPE_S_FX_EFX"},
 	{DATA_TYPE_S_FX_NCOB, "DATA_TYPE_S_FX_NCOB"},
-	{DATA_TYPE_S_FX_DFX_NCOB_ECOB, "DATA_TYPE_S_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_S_FX_EFX_NCOB_ECOB, "DATA_TYPE_S_FX_EFX_NCOB_ECOB"},
 	{DATA_TYPE_L_FX, "DATA_TYPE_L_FX"},
-	{DATA_TYPE_L_FX_DFX, "DATA_TYPE_L_FX_DFX"},
+	{DATA_TYPE_L_FX_EFX, "DATA_TYPE_L_FX_EFX"},
 	{DATA_TYPE_L_FX_NCOB, "DATA_TYPE_L_FX_NCOB"},
-	{DATA_TYPE_L_FX_DFX_NCOB_ECOB, "DATA_TYPE_L_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_L_FX_EFX_NCOB_ECOB, "DATA_TYPE_L_FX_EFX_NCOB_ECOB"},
 	{DATA_TYPE_F_FX, "DATA_TYPE_F_FX"},
-	{DATA_TYPE_F_FX_DFX, "DATA_TYPE_F_FX_DFX"},
+	{DATA_TYPE_F_FX_EFX, "DATA_TYPE_F_FX_EFX"},
 	{DATA_TYPE_F_FX_NCOB, "DATA_TYPE_F_FX_NCOB"},
-	{DATA_TYPE_F_FX_DFX_NCOB_ECOB, "DATA_TYPE_F_FX_DFX_NCOB_ECOB"},
+	{DATA_TYPE_F_FX_EFX_NCOB_ECOB, "DATA_TYPE_F_FX_EFX_NCOB_ECOB"},
 	{DATA_TYPE_F_CAM_IMAGETTE, "DATA_TYPE_F_CAM_IMAGETTE"},
 	{DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE, "DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE"},
 	{DATA_TYPE_F_CAM_OFFSET, "DATA_TYPE_F_CAM_OFFSET"},
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index cfa7dc5..ae7941b 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -297,17 +297,17 @@ int cmp_fx_cob_data_type_is_used(enum cmp_data_type data_type)
 {
 	switch (data_type) {
 	case DATA_TYPE_S_FX:
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 	case DATA_TYPE_S_FX_NCOB:
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_L_FX:
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 	case DATA_TYPE_L_FX_NCOB:
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 	case DATA_TYPE_F_FX:
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 	case DATA_TYPE_F_FX_NCOB:
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		return 1;
 	default:
 		return 0;
@@ -723,7 +723,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 	case DATA_TYPE_S_FX:
 		check_exp_flags = 1;
 		break;
-	case DATA_TYPE_S_FX_DFX:
+	case DATA_TYPE_S_FX_EFX:
 		check_exp_flags = 1;
 		check_efx = 1;
 		break;
@@ -731,7 +731,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		check_exp_flags = 1;
 		check_ncob = 1;
 		break;
-	case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 		check_exp_flags = 1;
 		check_ncob = 1;
 		check_efx = 1;
@@ -741,7 +741,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		check_exp_flags = 1;
 		check_var = 1;
 		break;
-	case DATA_TYPE_L_FX_DFX:
+	case DATA_TYPE_L_FX_EFX:
 		check_exp_flags = 1;
 		check_efx = 1;
 		check_var = 1;
@@ -751,7 +751,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		check_ncob = 1;
 		check_var = 1;
 		break;
-	case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 		check_exp_flags = 1;
 		check_ncob = 1;
 		check_efx = 1;
@@ -760,13 +760,13 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		break;
 	case DATA_TYPE_F_FX:
 		break;
-	case DATA_TYPE_F_FX_DFX:
+	case DATA_TYPE_F_FX_EFX:
 		check_efx = 1;
 		break;
 	case DATA_TYPE_F_FX_NCOB:
 		check_ncob = 1;
 		break;
-	case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		check_ncob = 1;
 		check_efx = 1;
 		check_ecob = 1;
diff --git a/lib/decmp.c b/lib/decmp.c
index 3c7acfb..534fc46 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -664,7 +664,7 @@ static int decompress_s_fx(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief decompress S_FX_DFX data
+ * @brief decompress S_FX_EFX data
  *
  * @param cfg	pointer to the compression configuration structure
  *
@@ -1019,7 +1019,7 @@ static int decompress_f_fx(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief decompress F_FX_DFX data
+ * @brief decompress F_FX_EFX data
  *
  * @param cfg	pointer to the compression configuration structure
  *
@@ -2005,39 +2005,39 @@ static int decompressed_data_internal(struct cmp_cfg *cfg)
 		case DATA_TYPE_S_FX:
 			strem_len_bit = decompress_s_fx(cfg);
 			break;
-		case DATA_TYPE_S_FX_DFX:
+		case DATA_TYPE_S_FX_EFX:
 			strem_len_bit = decompress_s_fx_efx(cfg);
 			break;
 		case DATA_TYPE_S_FX_NCOB:
 			strem_len_bit = decompress_s_fx_ncob(cfg);
 			break;
-		case DATA_TYPE_S_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
 			strem_len_bit = decompress_s_fx_efx_ncob_ecob(cfg);
 			break;
 
 		case DATA_TYPE_F_FX:
 			strem_len_bit = decompress_f_fx(cfg);
 			break;
-		case DATA_TYPE_F_FX_DFX:
+		case DATA_TYPE_F_FX_EFX:
 			strem_len_bit = decompress_f_fx_efx(cfg);
 			break;
 		case DATA_TYPE_F_FX_NCOB:
 			strem_len_bit = decompress_f_fx_ncob(cfg);
 			break;
-		case DATA_TYPE_F_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 			strem_len_bit = decompress_f_fx_efx_ncob_ecob(cfg);
 			break;
 
 		case DATA_TYPE_L_FX:
 			strem_len_bit = decompress_l_fx(cfg);
 			break;
-		case DATA_TYPE_L_FX_DFX:
+		case DATA_TYPE_L_FX_EFX:
 			strem_len_bit = decompress_l_fx_efx(cfg);
 			break;
 		case DATA_TYPE_L_FX_NCOB:
 			strem_len_bit = decompress_l_fx_ncob(cfg);
 			break;
-		case DATA_TYPE_L_FX_DFX_NCOB_ECOB:
+		case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
 			strem_len_bit = decompress_l_fx_efx_ncob_ecob(cfg);
 			break;
 
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index d2c46ce..9038a39 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -582,17 +582,17 @@ void test_cmp_cfg_fx_cob(void)
 				       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
 				       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
 		if (data_type == DATA_TYPE_S_FX ||
-		    data_type == DATA_TYPE_S_FX_DFX ||
+		    data_type == DATA_TYPE_S_FX_EFX ||
 		    data_type == DATA_TYPE_S_FX_NCOB ||
-		    data_type == DATA_TYPE_S_FX_DFX_NCOB_ECOB ||
+		    data_type == DATA_TYPE_S_FX_EFX_NCOB_ECOB ||
 		    data_type == DATA_TYPE_L_FX ||
-		    data_type == DATA_TYPE_L_FX_DFX ||
+		    data_type == DATA_TYPE_L_FX_EFX ||
 		    data_type == DATA_TYPE_L_FX_NCOB ||
-		    data_type == DATA_TYPE_L_FX_DFX_NCOB_ECOB ||
+		    data_type == DATA_TYPE_L_FX_EFX_NCOB_ECOB ||
 		    data_type == DATA_TYPE_F_FX ||
-		    data_type == DATA_TYPE_F_FX_DFX ||
+		    data_type == DATA_TYPE_F_FX_EFX ||
 		    data_type == DATA_TYPE_F_FX_NCOB ||
-		    data_type == DATA_TYPE_F_FX_DFX_NCOB_ECOB) {
+		    data_type == DATA_TYPE_F_FX_EFX_NCOB_ECOB) {
 			TEST_ASSERT_FALSE(error);
 			TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
 			TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_fx);
@@ -665,8 +665,8 @@ void test_cmp_cfg_fx_cob(void)
 	TEST_ASSERT_TRUE(error);
 
 
-	/* test DATA_TYPE_S_FX_DFX */
-	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_DFX, CMP_MODE_MODEL_ZERO, 0, 1);
+	/* test DATA_TYPE_S_FX_EFX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_EFX, CMP_MODE_MODEL_ZERO, 0, 1);
 	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
 	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
 	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
@@ -735,8 +735,8 @@ void test_cmp_cfg_fx_cob(void)
 	TEST_ASSERT_TRUE(error);
 
 
-	/* test DATA_TYPE_S_FX_DFX_NCOB_ECOB */
-	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_DFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	/* test DATA_TYPE_S_FX_EFX_NCOB_ECOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
 	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
 	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
 	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
@@ -810,8 +810,8 @@ void test_cmp_cfg_fx_cob(void)
 	TEST_ASSERT_TRUE(error);
 
 
-	/* DATA_TYPE_L_FX_DFX */
-	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_DFX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	/* DATA_TYPE_L_FX_EFX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_EFX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
 	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
 	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
 	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
@@ -870,8 +870,8 @@ void test_cmp_cfg_fx_cob(void)
 	TEST_ASSERT_EQUAL_INT(spillover_fx_cob_variance, cfg.spill_fx_cob_variance);
 
 
-	/* DATA_TYPE_L_FX_DFX_NCOB_ECOB */
-	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_DFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	/* DATA_TYPE_L_FX_EFX_NCOB_ECOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
 	cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
 	spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
 	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
@@ -928,8 +928,8 @@ void test_cmp_cfg_fx_cob(void)
 	TEST_ASSERT_EQUAL_INT(spillover_fx, cfg.spill_fx);
 
 
-	/* DATA_TYPE_F_FX_DFX */
-	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_DFX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	/* DATA_TYPE_F_FX_EFX */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_EFX, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
 	cmp_par_exp_flags = ~0; /* invalid parameter */
 	spillover_exp_flags = ~0; /* invalid parameter */
 	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
@@ -980,8 +980,8 @@ void test_cmp_cfg_fx_cob(void)
 	TEST_ASSERT_EQUAL_INT(spillover_ncob, cfg.spill_ncob);
 
 
-	/* DATA_TYPE_F_FX_DFX_NCOB_ECOB */
-	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_DFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
+	/* DATA_TYPE_F_FX_EFX_NCOB_ECOB */
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS);
 	cmp_par_exp_flags = ~0; /* invalid parameter */
 	spillover_exp_flags = ~0; /* invalid parameter */
 	cmp_par_fx = MIN_ICU_GOLOMB_PAR;
@@ -2920,7 +2920,7 @@ void test_compress_s_fx_efx_model_multi(void)
 	cmp_set_max_used_bits(&max_used_bits);
 
 	/* setup configuration */
-	cfg.data_type = DATA_TYPE_S_FX_DFX;
+	cfg.data_type = DATA_TYPE_S_FX_EFX;
 	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
 	cfg.model_value = 16;
 	cfg.samples = 6;
-- 
GitLab


From 89aeee27665395540068c5aa9be97822caf37bfd Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 8 Sep 2022 16:43:03 +0200
Subject: [PATCH 30/46] fix some typos

---
 cmp_tool.c                  |    2 +-
 include/cmp_data_types.h    |    4 +-
 include/cmp_support.h       |    2 +-
 lib/cmp_data_types.c        |    4 +-
 lib/cmp_icu.c               |   60 +-
 lib/cmp_support.c           |    6 +-
 lib/decmp.c                 |   46 +-
 test/cmp_icu/test_cmp_icu.c | 1391 ++++++++++++++++++++++++++++++++++-
 8 files changed, 1428 insertions(+), 87 deletions(-)

diff --git a/cmp_tool.c b/cmp_tool.c
index 0cf72ef..86302b3 100644
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -655,7 +655,7 @@ static int cmp_gernate_rdcu_info(const struct cmp_cfg *cfg, int cmp_size_bit, st
 		info->rdcu_new_model_adr_used = cfg->rdcu_new_model_adr;
 		info->rdcu_cmp_adr_used = cfg->rdcu_buffer_adr;
 
-		if (cmp_size_bit == CMP_ERROR_SAMLL_BUF)
+		if (cmp_size_bit == CMP_ERROR_SMALL_BUF)
 			/* the icu_output_buf is to small to store the whole bitstream */
 			info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
 		if (cmp_size_bit < 0)
diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 8878557..41a39f7 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -108,8 +108,8 @@ struct cmp_max_used_bits {
 	unsigned int nc_background_mean;
 	unsigned int nc_background_variance;
 	unsigned int nc_background_outlier_pixels;
-	unsigned int smeating_mean;
-	unsigned int smeating_variance_mean;
+	unsigned int smearing_mean;
+	unsigned int smearing_variance_mean;
 	unsigned int smearing_outlier_pixels;
 	unsigned int fc_imagette;
 	unsigned int fc_offset_mean;
diff --git a/include/cmp_support.h b/include/cmp_support.h
index aa455a5..b69eb5c 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -24,7 +24,7 @@
 
 
 /* return code if the bitstream buffer is too small to store the whole bitstream */
-#define CMP_ERROR_SAMLL_BUF -2
+#define CMP_ERROR_SMALL_BUF -2
 
 /* return code if the value or the model is bigger than the max_used_bits
  * parameter allows
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 6ce5f4b..3064e6c 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -50,8 +50,8 @@ struct cmp_max_used_bits max_used_bits = {
 	MAX_USED_NC_BACKGROUND_MEAN_BITS, /* nc_background_mean */
 	MAX_USED_NC_BACKGROUND_VARIANCE_BITS, /* nc_background_variance */
 	MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS, /* nc_background_outlier_pixels */
-	MAX_USED_SMEARING_MEAN_BITS, /* smeating_mean */
-	MAX_USED_SMEARING_VARIANCE_MEAN_BITS, /* smeating_variance_mean */
+	MAX_USED_SMEARING_MEAN_BITS, /* smearing_mean */
+	MAX_USED_SMEARING_VARIANCE_MEAN_BITS, /* smearing_variance_mean */
 	MAX_USED_SMEARING_OUTLIER_PIXELS_BITS, /* smearing_outlier_pixels */
 	MAX_USED_FC_IMAGETTE_BITS, /* fc_imagette */
 	MAX_USED_FC_OFFSET_MEAN_BITS, /* fc_offset_mean */
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 2d04120..107b85d 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -306,7 +306,7 @@ static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits)
  *				ignored if bitstream_adr is NULL
  *
  * @returns length in bits of the generated bitstream on success; returns
- *          negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if
+ *          negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if
  *          the bitstream buffer is too small to put the value in the bitstream
  */
 
@@ -335,7 +335,7 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset,
 	/* Check if bitstream buffer is large enough */
 	if ((unsigned int)stream_len > max_stream_len) {
 		debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n");
-		return CMP_ERROR_SAMLL_BUF;
+		return CMP_ERROR_SMALL_BUF;
 	}
 
 	/* (M) is the n_bits parameter large enough to cover all value bits; the
@@ -510,7 +510,7 @@ static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m,
  * @param setup		pointer to the encoder setup
  *
  * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	success; negative on error, CMP_ERROR_SMALL_BUF if the bitstream buffer
  *	is too small to put the value in the bitstream
  */
 
@@ -537,7 +537,7 @@ static int encode_normal(uint32_t value, int stream_len,
  * @param setup		pointer to the encoder setup
  *
  * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	success; negative on error, CMP_ERROR_SMALL_BUF if the bitstream buffer
  *	is too small to put the value in the bitstream
  *
  * @note no check if the data or model are in the allowed range
@@ -587,7 +587,7 @@ static int encode_value_zero(uint32_t data, uint32_t model, int stream_len,
  * @param setup		pointer to the encoder setup
  *
  * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	success; negative on error, CMP_ERROR_SMALL_BUF if the bitstream buffer
  *	is too small to put the value in the bitstream
  *
  * @note no check if the data or model are in the allowed range
@@ -653,7 +653,7 @@ static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
  * @param setup		pointer to the encoder setup
  *
  * @returns the bit length of the bitstream with the added unencoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	success; negative on error, CMP_ERROR_SMALL_BUF if the bitstream buffer
  *	is too small to put the value in the bitstream
  *
  */
@@ -678,7 +678,7 @@ static int encode_value_none(uint32_t value, uint32_t unused, int stream_len,
  * @param setup		pointer to the encoder setup
  *
  * @returns the bit length of the bitstream with the added encoded value on
- *	success; negative on error, CMP_ERROR_SAMLL_BUF if the bitstream buffer
+ *	success; negative on error, CMP_ERROR_SMALL_BUF if the bitstream buffer
  *	is too small to put the value in the bitstream, CMP_ERROR_HIGH_VALUE if
  *	the value or the model is bigger than the max_used_bits parameter allows
  */
@@ -798,7 +798,7 @@ static int configure_encoder_setup(struct encoder_setupt *setup,
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream, CMP_ERROR_HIGH_VALUE if the value or the model is
  *	bigger than the max_used_bits parameter allows
  */
@@ -887,7 +887,7 @@ static int compress_multi_entry_hdr(void **data, void **model, void **up_model,
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -959,7 +959,7 @@ static int compress_s_fx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1041,7 +1041,7 @@ static int compress_s_fx_efx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1129,7 +1129,7 @@ static int compress_s_fx_ncob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1244,7 +1244,7 @@ static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1306,7 +1306,7 @@ static int compress_f_fx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1378,7 +1378,7 @@ static int compress_f_fx_efx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1456,7 +1456,7 @@ static int compress_f_fx_ncob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1560,7 +1560,7 @@ static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1642,7 +1642,7 @@ static int compress_l_fx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1734,7 +1734,7 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1850,7 +1850,7 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1991,7 +1991,7 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -2062,7 +2062,7 @@ static int compress_nc_offset(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -2144,7 +2144,7 @@ static int compress_nc_background(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -2176,11 +2176,11 @@ static int compress_smearing(const struct cmp_cfg *cfg)
 	}
 
 	err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
-				      cfg->round, max_used_bits.smeating_mean, cfg);
+				      cfg->round, max_used_bits.smearing_mean, cfg);
 	if (err)
 		return -1;
 	err = configure_encoder_setup(&setup_var_mean, cfg->cmp_par_variance, cfg->spill_variance,
-				      cfg->round, max_used_bits.smeating_variance_mean, cfg);
+				      cfg->round, max_used_bits.smearing_variance_mean, cfg);
 	if (err)
 		return -1;
 	err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
@@ -2227,7 +2227,7 @@ static int compress_smearing(const struct cmp_cfg *cfg)
  * @param cmp_size	length of the bitstream in bits
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -2277,6 +2277,8 @@ static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, int cmp_size)
 		return cmp_size;
 
 	if (cfg->cmp_mode == CMP_MODE_RAW) {
+		if (s & 0x7) /* size must be a multiple of 8 in RAW mode */
+			return -1;
 		if (cmp_input_big_to_cpu_endianness(cfg->icu_output_buf,
 						    s/CHAR_BIT, cfg->data_type))
 			cmp_size = -1;
@@ -2309,7 +2311,7 @@ static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, int cmp_size)
  *	 started
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF (-2) if the compressed data buffer is too small to
+ *	CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too small to
  *	hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or
  *	model value is bigger than the max_used_bits parameter allows (set with
  *	the cmp_set_max_used_bits() function)
@@ -2327,7 +2329,7 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 
 	if (raw_mode_is_used(cfg->cmp_mode))
 		if (cfg->samples > cfg->buffer_length)
-			return CMP_ERROR_SAMLL_BUF;
+			return CMP_ERROR_SMALL_BUF;
 
 	if (!cmp_cfg_is_valid(cfg))
 		return -1;
@@ -2402,11 +2404,13 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 
 		case DATA_TYPE_F_CAM_OFFSET:
 		case DATA_TYPE_F_CAM_BACKGROUND:
+		/* LCOV_EXCL_START */
 		case DATA_TYPE_UNKNOWN:
 		default:
 			debug_print("Error: Data type not supported.\n");
 			cmp_size = -1;
 		}
+		/* LCOV_EXCL_STOP */
 	}
 
 	if (cfg->icu_output_buf) {
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index ae7941b..f157a6e 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -671,7 +671,7 @@ int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg)
 		return 0;
 
 	if (!cmp_imagette_data_type_is_used(cfg->data_type)) {
-		debug_print("Error: The compression data type is not an imagette compression data type!\n");
+		debug_print("Error: The compression data type is not an imagette compression data type.\n");
 		cfg_invalid++;
 	}
 
@@ -712,7 +712,7 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		return 0;
 
 	if (!cmp_fx_cob_data_type_is_used(cfg->data_type)) {
-		debug_print("Error: The compression data type is not a flux/center of brightness compression data type.!\n");
+		debug_print("Error: The compression data type is not a flux/center of brightness compression data type.\n");
 		cfg_invalid++;
 	}
 	/* flux parameter is needed for every fx_cob data_type */
@@ -816,7 +816,7 @@ int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
 		return 0;
 
 	if (!cmp_aux_data_type_is_used(cfg->data_type)) {
-		debug_print("Error: The compression data type is not an auxiliary science compression data type.!\n");
+		debug_print("Error: The compression data type is not an auxiliary science compression data type.\n");
 		cfg_invalid++;
 	}
 
diff --git a/lib/decmp.c b/lib/decmp.c
index 534fc46..f15c943 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -218,7 +218,7 @@ static decoder_ptr select_decoder(unsigned int golomb_par)
  *				ignored if bitstream_adr is NULL
  *
  * @returns bit position of the last read bit in the bitstream on success;
- *	returns negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF
+ *	returns negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF
  *	if the bitstream buffer is too small to read the value from the
  *	bitstream
  */
@@ -248,7 +248,7 @@ static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
 	/* Check if bitstream buffer is large enough */
 	if ((unsigned int)stream_len > max_stream_len) {
 		debug_print("Error: Buffer overflow detected.\n");
-		return CMP_ERROR_SAMLL_BUF;
+		return CMP_ERROR_SMALL_BUF;
 
 	}
 
@@ -297,7 +297,7 @@ static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
  * @param setup		pointer to the decoder setup
  *
  * @returns bit index of the next code word in the bitstream on success; returns
- *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the
  *	bitstream buffer is too small to read the value from the bitstream
  */
 
@@ -344,7 +344,7 @@ static int decode_normal(uint32_t *decoded_value, int stream_pos,
  * @param setup		pointer to the decoder setup
  *
  * @returns bit index of the next code word in the bitstream on success; returns
- *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the
  *	bitstream buffer is too small to read the value from the bitstream
  */
 
@@ -392,7 +392,7 @@ static int decode_zero(uint32_t *decoded_value, int stream_pos,
  * @param setup		pointer to the decoder setup
  *
  * @returns bit index of the next code word in the bitstream on success; returns
- *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the
  *	bitstream buffer is too small to read the value from the bitstream
  */
 
@@ -448,7 +448,7 @@ static uint32_t re_map_to_pos(uint32_t value_to_unmap)
  * @param setup		pointer to the decoder setup
  *
  * @returns bit index of the next code word in the bitstream on success; returns
- *	negative in case of erroneous input; returns CMP_ERROR_SAMLL_BUF if the
+ *	negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the
  *	bitstream buffer is too small to read the value from the bitstream
  */
 
@@ -597,7 +597,7 @@ static int decompress_multi_entry_hdr(void **data, void **model, void **up_model
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -669,7 +669,7 @@ static int decompress_s_fx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -752,7 +752,7 @@ static int decompress_s_fx_efx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -843,7 +843,7 @@ static int decompress_s_fx_ncob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -964,7 +964,7 @@ static int decompress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1024,7 +1024,7 @@ static int decompress_f_fx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1096,7 +1096,7 @@ static int decompress_f_fx_efx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1176,7 +1176,7 @@ static int decompress_f_fx_ncob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1286,7 +1286,7 @@ static int decompress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1369,7 +1369,7 @@ static int decompress_l_fx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1463,7 +1463,7 @@ static int decompress_l_fx_efx(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1585,7 +1585,7 @@ static int decompress_l_fx_ncob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1731,7 +1731,7 @@ static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1803,7 +1803,7 @@ static int decompress_nc_offset(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1886,7 +1886,7 @@ static int decompress_nc_background(const struct cmp_cfg *cfg)
  * @param cfg	pointer to the compression configuration structure
  *
  * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SAMLL_BUF if the bitstream buffer is too small to put the
+ *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
  *	value in the bitstream
  */
 
@@ -1917,10 +1917,10 @@ static int decompress_smearing(const struct cmp_cfg *cfg)
 	}
 
 	if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
-				    cfg->round, max_used_bits.smeating_mean, cfg))
+				    cfg->round, max_used_bits.smearing_mean, cfg))
 		return -1;
 	if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
-				    cfg->round, max_used_bits.smeating_variance_mean, cfg))
+				    cfg->round, max_used_bits.smearing_variance_mean, cfg))
 		return -1;
 	if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
 				    cfg->round, max_used_bits.smearing_outlier_pixels, cfg))
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index 9038a39..3eae4be 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -31,7 +31,7 @@ void setUp(void)
 #endif
 
 	if (!n) {
-		n++;
+		n = 1;
 		srand(seed);
 		printf("seed: %u\n", seed);
 	}
@@ -41,20 +41,18 @@ void setUp(void)
 /**
  * @brief generate a random number
  *
- * @param min minimum value
- * @param max maximum value
+ * @param min minimum value (inclusive)
+ * @param max maximum value (inclusive)
  *
  * @returns "random" numbers in the range [M, N]
  *
  * @see https://c-faq.com/lib/randrange.html
  */
 
-int random_range(unsigned int min, unsigned int max)
+int random_between(unsigned int min, unsigned int max)
 {
-	if (min > max)
-		TEST_ASSERT(0);
-	if (max-min > RAND_MAX)
-		TEST_ASSERT(0);
+	TEST_ASSERT(min < max);
+	TEST_ASSERT(max-min <= RAND_MAX);
 	return min + rand() / (RAND_MAX / (max - min + 1) + 1);
 }
 
@@ -170,10 +168,10 @@ void test_cmp_cfg_icu_create(void)
 	TEST_ASSERT_EQUAL_INT(3, cfg.round);
 
 	/* random test */
-	data_type = random_range(DATA_TYPE_IMAGETTE, biggest_data_type);
-	cmp_mode = random_range(CMP_MODE_RAW, CMP_MODE_STUFF);
-	model_value = random_range(0, MAX_MODEL_VALUE);
-	lossy_par = random_range(CMP_LOSSLESS, MAX_ICU_ROUND);
+	data_type = random_between(DATA_TYPE_IMAGETTE, biggest_data_type);
+	cmp_mode = random_between(CMP_MODE_RAW, CMP_MODE_STUFF);
+	model_value = random_between(0, MAX_MODEL_VALUE);
+	lossy_par = random_between(CMP_LOSSLESS, MAX_ICU_ROUND);
 	cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par);
 	TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
 	TEST_ASSERT_EQUAL_INT(cmp_mode, cfg.cmp_mode);
@@ -1610,7 +1608,7 @@ void test_put_n_bits32(void)
 	/* try to put too much in the bitstream */
 	v = 0x1; n = 1; o = 96;
 	rval = put_n_bits32(v, n, o, testarray0, l);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, rval);
 	TEST_ASSERT(testarray0[0] == 0);
 	TEST_ASSERT(testarray0[1] == 0);
 	TEST_ASSERT(testarray0[2] == 0);
@@ -1622,7 +1620,7 @@ void test_put_n_bits32(void)
 	/* offset lager than max_stream_len(l) */
 	v = 0x0; n = 32; o = INT32_MAX;
 	rval = put_n_bits32(v, n, o, testarray1, l);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, rval);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, rval);
 	TEST_ASSERT(testarray1[0] == 0xffffffff);
 	TEST_ASSERT(testarray1[1] == 0xffffffff);
 	TEST_ASSERT(testarray1[2] == 0xffffffff);
@@ -1887,7 +1885,7 @@ void test_encode_value_zero(void)
 	/* small buffer error */
 	data = 23; model = 26;
 	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, stream_len);
 
 	/* reset bitstream to all bits set */
 	bitstream[0] = ~0U;
@@ -1938,7 +1936,7 @@ void test_encode_value_zero(void)
 	setup.max_stream_len = 32;
 	data = 31; model = 0;
 	stream_len = encode_value_zero(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, stream_len);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[2]);
@@ -2021,7 +2019,7 @@ void test_encode_value_multi(void)
 	/* small buffer error */
 	data = 0; model = 38;
 	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, stream_len);
 
 	/* small buffer error when creating the multi escape symbol*/
 	bitstream[0] = 0;
@@ -2031,7 +2029,7 @@ void test_encode_value_multi(void)
 	stream_len = 32;
 	data = 31; model = 0;
 	stream_len = encode_value_multi(data, model, stream_len, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, stream_len);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, stream_len);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[0]);
 	TEST_ASSERT_EQUAL_HEX(0, bitstream[1]);
 }
@@ -2095,7 +2093,7 @@ void test_encode_value(void)
 
 	/* small buffer error bitstream can not hold more data*/
 	cmp_size = encode_value(data, model, cmp_size, &setup);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size);
 
 	/* reset bitstream */
 	bitstream[0] = 0;
@@ -2187,8 +2185,8 @@ void test_cmp_get_max_used_bits(void)
 	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_variance, MAX_USED_NC_BACKGROUND_VARIANCE_BITS);
 	TEST_ASSERT_EQUAL_INT(max_used_bits.nc_background_outlier_pixels, MAX_USED_NC_BACKGROUND_OUTLIER_PIXELS_BITS);
 
-	TEST_ASSERT_EQUAL_INT(max_used_bits.smeating_mean, MAX_USED_SMEARING_MEAN_BITS);
-	TEST_ASSERT_EQUAL_INT(max_used_bits.smeating_variance_mean, MAX_USED_SMEARING_VARIANCE_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smearing_mean, MAX_USED_SMEARING_MEAN_BITS);
+	TEST_ASSERT_EQUAL_INT(max_used_bits.smearing_variance_mean, MAX_USED_SMEARING_VARIANCE_MEAN_BITS);
 	TEST_ASSERT_EQUAL_INT(max_used_bits.smearing_outlier_pixels, MAX_USED_SMEARING_OUTLIER_PIXELS_BITS);
 
 	TEST_ASSERT_EQUAL_INT(max_used_bits.fc_offset_mean, MAX_USED_FC_OFFSET_MEAN_BITS);
@@ -2553,7 +2551,7 @@ void test_compress_imagette_raw(void)
 	cfg.buffer_length = 6; /* the buffer is to small */
 
 	cmp_size = icu_compress_data(&cfg);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size);
 }
 
 
@@ -2592,7 +2590,7 @@ void test_compress_imagette_error_cases(void)
 	cfg.buffer_length = 4;
 
 	cmp_size = icu_compress_data(&cfg);
-	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SAMLL_BUF, cmp_size);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size);
 
 
 	/* error in setup */
@@ -2902,7 +2900,8 @@ void test_compress_s_fx_model_multi(void)
 }
 
 
-void test_compress_s_fx_efx_model_multi(void)
+#if 0
+void todo_est_compress_s_fx_efx_model_multi(void)
 {
 	uint32_t i;
 	struct s_fx_efx data[6], model[6];
@@ -3014,6 +3013,1347 @@ void test_compress_s_fx_efx_model_multi(void)
 	free(cfg.icu_new_model_buf);
 	free(cfg.icu_output_buf);
 }
+#endif
+
+
+/**
+ * @test compress_s_fx
+ */
+
+void test_compress_s_fx_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_exp_flags = 6;
+	uint32_t cmp_par_fx = 2;
+	uint32_t spillover_fx = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct s_fx *data_p = (struct s_fx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL,
+						   NULL, (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* test if data are higher than max used bits value */
+	data_p[0].fx = 0x200000; /* has more than 21 bits (max_used_bits.s_fx) */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	/* compressed data are to small for the compressed_data buffer */
+	max_used_bits.s_exp_flags = 8;
+	max_used_bits.s_fx= 32;
+	cmp_set_max_used_bits(&max_used_bits);
+	memset(data_to_compress, 0xff, sizeof(data_to_compress));
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits);
+
+	max_used_bits.s_exp_flags = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.s_exp_flags = 32;
+	max_used_bits.s_fx= 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_s_fx_efx
+ */
+
+void test_compress_s_fx_efx_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = 2;
+	uint32_t spillover_exp_flags = 6;
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_efx = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_efx = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+2*sizeof(struct s_fx_efx)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx_efx)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct s_fx_efx *data_p= (struct s_fx_efx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	max_used_bits.s_efx = 16;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_EFX, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, cmp_par_efx, spillover_efx,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 2, NULL,
+						   NULL, (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* test if data are higher than max used bits value */
+	data_p[0].exp_flags = 0x4; /* has more than 2 bits (max_used_bits.s_exp_flags) */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].exp_flags = 0x3;
+	data_p[1].fx = 0x200000; /* has more than 21 bits (max_used_bits.fx) */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].fx = 0x1FFFFF;
+	data_p[1].efx = 0x100000; /* has more than 16 bits (max_used_bits.efx) */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	/* error case exp_flag setup */
+	max_used_bits.s_exp_flags = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	/* error case fx setup */
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	/* error case efx setup */
+	max_used_bits.s_fx = 21;
+	max_used_bits.s_efx = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_s_fx_ncob
+ */
+
+void test_compress_s_fx_ncob_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = 3;
+	uint32_t spillover_exp_flags = 6;
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_ncob = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_ncob = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_ncob)] = {0};
+	uint8_t model_data[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_ncob)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx_ncob)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct s_fx_ncob *data_p = (struct s_fx_ncob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	max_used_bits.s_ncob = 31;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_NCOB, CMP_MODE_MODEL_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, model_data,
+						   NULL, (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* the compressed_data buffer is to small */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits);
+
+	/* test if data are higher than max used bits value */
+	data_p[2].exp_flags = 0x4; /* has more than 2 bits (max_used_bits.s_exp_flags) */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].exp_flags = 0x3;
+	data_p[1].fx = 0x200000; /* value to high */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].fx = 0x1FFFFF; /* value to high */
+	data_p[0].ncob_y = 0x80000000; /* value to high */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+	data_p[0].ncob_y = 0x7FFFFFFF; /* value to high */
+
+	/* error case exp_flag setup */
+	max_used_bits.s_exp_flags = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	/* error case fx setup */
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	/* error case efx setup */
+	max_used_bits.s_fx = 21;
+	max_used_bits.s_ncob = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_s_fx_efx_ncob_ecob
+ */
+
+void test_compress_s_fx_efx_ncob_ecob_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = 3;
+	uint32_t spillover_exp_flags = 6;
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_ncob = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_ncob = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint32_t cmp_par_efx = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_efx =  cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint32_t cmp_par_ecob = 23;
+	uint32_t spillover_ecob = cmp_icu_max_spill(23);
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_efx_ncob_ecob)] = {0};
+	uint8_t model_data[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_efx_ncob_ecob)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx_efx_ncob_ecob)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct s_fx_efx_ncob_ecob *data_p = (struct s_fx_efx_ncob_ecob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+
+	max_used_bits.s_exp_flags = 2;
+	max_used_bits.s_fx = 21;
+	max_used_bits.s_ncob = 31;
+	max_used_bits.s_efx = 23;
+	max_used_bits.s_ecob = 7;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_EFX_NCOB_ECOB, CMP_MODE_MODEL_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob,
+			       spillover_ncob, cmp_par_efx, spillover_efx,
+			       cmp_par_ecob, spillover_ecob, CMP_PAR_UNUSED, CMP_PAR_UNUSED);
+
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, model_data,
+						   NULL, (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* the compressed_data buffer is to small */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits);
+
+	/* test if data are higher than max used bits value */
+	data_p[2].exp_flags = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].exp_flags = 0x3;
+	data_p[2].fx = 0x200000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].fx = 0x1FFFFF;
+	data_p[1].ncob_x = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].ncob_x = 0x7FFFFFFF;
+	data_p[1].ncob_y = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].ncob_y = 0x7FFFFFFF;
+	data_p[1].efx = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].efx = 0x7FFFFF;
+	data_p[1].ecob_y = 0x80;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+	data_p[1].ecob_y = 0x7F;
+
+	/* error case exp_flag setup */
+	max_used_bits.s_exp_flags = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	/* error case fx setup */
+	max_used_bits.s_exp_flags = 32;
+	max_used_bits.s_fx = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	/* error case efx setup */
+	max_used_bits.s_fx = 32;
+	max_used_bits.s_ncob = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.s_ncob = 32;
+	max_used_bits.s_efx = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.s_efx = 32;
+	max_used_bits.s_ecob = 33;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+	max_used_bits.s_ecob = 32;
+}
+
+
+/**
+ * @test compress_f_fx
+ */
+
+void test_compress_f_fx_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_fx = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_fx = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct f_fx)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+
+	max_used_bits.f_fx = 23;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx, spillover_fx, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL, (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* compressed data are to small for the compressed_data buffer */
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits);
+
+	max_used_bits.f_fx= 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_f_fx_efx
+ */
+
+void test_compress_f_fx_efx_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_efx = 1;
+	uint32_t spillover_efx = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+2*sizeof(struct f_fx_efx)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx_efx)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct f_fx_efx *data_p = (struct f_fx_efx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.f_fx = 23;
+	max_used_bits.f_efx = 31;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_EFX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx, spillover_fx, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, cmp_par_efx, spillover_efx,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 2, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* compressed data are to small for the compressed_data buffer */
+	data_p[0].fx = 42;
+	data_p[0].efx = 42;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits);
+
+	/* efx value is to big for the max used bits values */
+	data_p[0].efx = 0x80000000;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+	data_p[0].efx = 0x7FFFFFFF;
+
+	max_used_bits.f_fx= 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.f_fx= 32;
+	max_used_bits.f_efx= 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_f_fx_ncob
+ */
+
+void test_compress_f_fx_ncob_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_fx = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_ncob = 1;
+	uint32_t spillover_ncob = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+2*sizeof(struct f_fx_ncob)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx_ncob)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct f_fx_ncob *data_p = (struct f_fx_ncob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.f_fx = 31;
+	max_used_bits.f_ncob = 23;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_NCOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 2, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* compressed data are to small for the compressed_data buffer */
+	data_p[0].fx = 42;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits);
+
+	/* value is to big for the max used bits values */
+	data_p[0].ncob_x = 0x800000;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+	data_p[0].ncob_x = 0x7FFFFF;
+	data_p[0].ncob_y = 0x800000;
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+	data_p[0].ncob_y = 0x7FFFFF;
+
+	max_used_bits.f_fx= 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.f_fx= 32;
+	max_used_bits.f_ncob= 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_f_fx_efx_ncob_ecob
+ */
+
+void test_compress_f_fx_efx_ncob_ecob(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_ncob = 2;
+	uint32_t spillover_ncob = 10;
+	uint32_t cmp_par_efx = 3;
+	uint32_t spillover_efx = 44;
+	uint32_t cmp_par_ecob = 5;
+	uint32_t spillover_ecob = 55;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+4*sizeof(struct f_fx_efx_ncob_ecob)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx_efx_ncob_ecob)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct f_fx_efx_ncob_ecob *data_p = (struct f_fx_efx_ncob_ecob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.f_fx = 31;
+	max_used_bits.f_ncob = 3;
+	max_used_bits.f_efx = 16;
+	max_used_bits.f_ecob = 8;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 4, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[3].fx = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[3].fx = 0x80000000-1;
+	data_p[2].ncob_x = 0x8;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].ncob_x = 0x7;
+	data_p[1].ncob_y = 0x8;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].ncob_y = 0x7;
+	data_p[0].efx = 0x10000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].efx = 0x10000-1;
+	data_p[2].ecob_x = 0x100;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].ecob_x = 0x100-1;
+	data_p[3].ecob_y = 0x100;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+	data_p[3].ecob_y = 0x100-1;
+
+	max_used_bits.f_fx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.f_fx = 32;
+	max_used_bits.f_ncob = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.f_ncob = 32;
+	max_used_bits.f_efx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.f_efx = 32;
+	max_used_bits.f_ecob = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_l_fx
+ */
+
+void test_compress_l_fx_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = 3;
+	uint32_t spillover_exp_flags = 10;
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_fx_cob_variance = 30;
+	uint32_t spillover_fx_cob_variance = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct l_fx *data_p = (struct l_fx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.l_exp_flags = 23;
+	max_used_bits.l_fx = 31;
+	max_used_bits.l_efx = 1;
+	max_used_bits.l_fx_variance = 23;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[2].exp_flags = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].exp_flags = 0x800000-1;
+	data_p[2].fx = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].fx = 0x80000000-1;
+	data_p[0].fx_variance = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].fx_variance = 0x800000-1;
+
+	max_used_bits.l_exp_flags = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_exp_flags = 32;
+	max_used_bits.l_fx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_fx = 32;
+	max_used_bits.l_fx_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_l_fx_efx
+ */
+
+void test_compress_l_fx_efx_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_efx = 3;
+	uint32_t spillover_efx = 44;
+	uint32_t cmp_par_fx_cob_variance = 30;
+	uint32_t spillover_fx_cob_variance = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx_efx)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx_efx)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct l_fx_efx *data_p = (struct l_fx_efx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.l_exp_flags = 23;
+	max_used_bits.l_fx = 31;
+	max_used_bits.l_efx = 1;
+	max_used_bits.l_fx_variance = 23;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_EFX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_efx, spillover_efx, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[2].exp_flags = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].exp_flags = 0x800000-1;
+	data_p[2].fx = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].fx = 0x80000000-1;
+	data_p[1].efx = 0x2;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].efx = 0x1;
+	data_p[0].fx_variance = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].fx_variance = 0x800000-1;
+
+	max_used_bits.l_exp_flags = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_exp_flags = 32;
+	max_used_bits.l_fx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_fx = 32;
+	max_used_bits.l_efx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_efx = 32;
+	max_used_bits.l_fx_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_l_fx_ncob
+ */
+
+void test_compress_l_fx_ncob_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_ncob = 2;
+	uint32_t spillover_ncob = 10;
+	uint32_t cmp_par_fx_cob_variance = 30;
+	uint32_t spillover_fx_cob_variance = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx_ncob)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx_ncob)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct l_fx_ncob *data_p = (struct l_fx_ncob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.l_exp_flags = 23;
+	max_used_bits.l_fx = 31;
+	max_used_bits.l_ncob = 2;
+	max_used_bits.l_fx_variance = 23;
+	max_used_bits.l_cob_variance = 11;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_NCOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[2].exp_flags = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].exp_flags = 0x800000-1;
+	data_p[2].fx = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].fx = 0x80000000-1;
+	data_p[2].ncob_x = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].ncob_x = 0x3;
+	data_p[2].ncob_y = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].ncob_y = 0x3;
+	data_p[0].fx_variance = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].fx_variance = 0x800000-1;
+	data_p[2].cob_x_variance = 0x800;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].cob_x_variance = 0x800-1;
+	data_p[2].cob_y_variance = 0x800;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].cob_y_variance = 0x800-1;
+
+	max_used_bits.l_exp_flags = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_exp_flags = 32;
+	max_used_bits.l_fx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_fx = 32;
+	max_used_bits.l_ncob = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_ncob = 32;
+	max_used_bits.l_fx_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_fx_variance = 32;
+	max_used_bits.l_cob_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_l_fx_efx_ncob_ecob
+ */
+
+void test_compress_l_fx_efx_ncob_ecob_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_exp_flags = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags);
+	uint32_t cmp_par_fx = 1;
+	uint32_t spillover_fx = 8;
+	uint32_t cmp_par_ncob = 2;
+	uint32_t spillover_ncob = 10;
+	uint32_t cmp_par_efx = 3;
+	uint32_t spillover_efx = 44;
+	uint32_t cmp_par_ecob = 5;
+	uint32_t spillover_ecob = 55;
+	uint32_t cmp_par_fx_cob_variance = 30;
+	uint32_t spillover_fx_cob_variance = 8;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx_efx_ncob_ecob)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx_efx_ncob_ecob)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct l_fx_efx_ncob_ecob *data_p = (struct l_fx_efx_ncob_ecob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.l_exp_flags = 23;
+	max_used_bits.l_fx = 31;
+	max_used_bits.l_ncob = 2;
+	max_used_bits.l_efx = 1;
+	max_used_bits.l_ecob = 3;
+	max_used_bits.l_fx_variance = 23;
+	max_used_bits.l_cob_variance = 11;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_fx_cob(&cfg, cmp_par_exp_flags, spillover_exp_flags,
+			       cmp_par_fx, spillover_fx, cmp_par_ncob, spillover_ncob,
+			       cmp_par_efx, spillover_efx, cmp_par_ecob, spillover_ecob,
+			       cmp_par_fx_cob_variance, spillover_fx_cob_variance);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[2].exp_flags = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].exp_flags = 0x800000-1;
+	data_p[2].fx = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].fx = 0x80000000-1;
+	data_p[2].ncob_x = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].ncob_x = 0x3;
+	data_p[2].ncob_y = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].ncob_y = 0x3;
+	data_p[1].efx = 0x2;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].efx = 0x1;
+	data_p[1].ecob_x = 0x8;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].ecob_x = 0x7;
+	data_p[1].ecob_y = 0x8;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].ecob_y = 0x7;
+	data_p[0].fx_variance = 0x800000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].fx_variance = 0x800000-1;
+	data_p[2].cob_x_variance = 0x800;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].cob_x_variance = 0x800-1;
+	data_p[2].cob_y_variance = 0x800;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[2].cob_y_variance = 0x800-1;
+
+	max_used_bits.l_exp_flags = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_exp_flags = 32;
+	max_used_bits.l_fx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_fx = 32;
+	max_used_bits.l_ncob = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_ncob = 32;
+	max_used_bits.l_efx = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_efx = 32;
+	max_used_bits.l_ecob = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_ecob = 32;
+	max_used_bits.l_fx_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.l_fx_variance = 32;
+	max_used_bits.l_cob_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_nc_offset
+ */
+
+void test_compress_nc_offset_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_mean = 1;
+	uint32_t spillover_mean = 2;
+	uint32_t cmp_par_variance = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_variance = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct nc_offset)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct nc_offset)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct nc_offset *data_p = (struct nc_offset *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.nc_offset_mean = 1;
+	max_used_bits.nc_offset_variance = 31;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_OFFSET, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    CMP_PAR_UNUSED, CMP_PAR_UNUSED);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[0].mean = 0x2;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].mean = 0x1;
+	data_p[1].variance = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].variance = 0x80000000-1;
+
+	max_used_bits.nc_offset_mean = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.nc_offset_mean = 32;
+	max_used_bits.nc_offset_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_nc_background
+ */
+
+void test_compress_nc_background_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_mean = 1;
+	uint32_t spillover_mean = 2;
+	uint32_t cmp_par_variance = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_variance = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint32_t cmp_par_pixels_error = 23;
+	uint32_t spillover_pixels_error = 42;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct nc_background)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct nc_background)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct nc_background *data_p = (struct nc_background *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.nc_background_mean = 1;
+	max_used_bits.nc_background_variance = 31;
+	max_used_bits.nc_background_outlier_pixels = 2;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_BACKGROUND, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[0].mean = 0x2;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].mean = 0x1;
+	data_p[1].variance = 0x80000000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].variance = 0x80000000-1;
+	data_p[1].outlier_pixels = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].outlier_pixels = 0x3;
+
+	max_used_bits.nc_background_mean = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.nc_background_mean = 32;
+	max_used_bits.nc_background_variance = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.nc_background_variance = 32;
+	max_used_bits.nc_background_outlier_pixels = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test compress_smearing
+ */
+
+void test_compress_smearing_error_cases(void)
+{
+	int error, cmp_bits, compressed_data_size;
+	struct cmp_cfg cfg = {0};
+	uint32_t cmp_par_mean = 1;
+	uint32_t spillover_mean = 2;
+	uint32_t cmp_par_variance = MAX_ICU_GOLOMB_PAR;
+	uint32_t spillover_variance = cmp_icu_max_spill(MAX_ICU_GOLOMB_PAR);
+	uint32_t cmp_par_pixels_error = 23;
+	uint32_t spillover_pixels_error = 42;
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct smearing)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct smearing)] = {0};
+	struct cmp_max_used_bits max_used_bits = {0};
+	struct smearing *data_p = (struct smearing *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+
+	max_used_bits.smearing_mean = 1;
+	max_used_bits.smearing_variance_mean = 15;
+	max_used_bits.smearing_outlier_pixels = 2;
+	cmp_set_max_used_bits(&max_used_bits);
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_SMEARING, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS);
+	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
+
+	error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean,
+			    cmp_par_variance, spillover_variance,
+			    cmp_par_pixels_error, spillover_pixels_error);
+	TEST_ASSERT_FALSE(error);
+
+	compressed_data_size = cmp_cfg_icu_buffers(&cfg, data_to_compress, 3, NULL, NULL,
+						   (uint32_t *)compressed_data, 1);
+	TEST_ASSERT_EQUAL_INT(sizeof(compressed_data), compressed_data_size);
+
+	/* value is to big for the max used bits values */
+	data_p[0].mean = 0x2;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[0].mean = 0x1;
+	data_p[1].variance_mean = 0x8000;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].variance_mean = 0x8000-1;
+	data_p[1].outlier_pixels = 0x4;
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits);
+
+	data_p[1].outlier_pixels = 0x3;
+
+	max_used_bits.smearing_mean = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.smearing_mean = 32;
+	max_used_bits.smearing_variance_mean = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+
+	max_used_bits.smearing_variance_mean = 32;
+	max_used_bits.smearing_outlier_pixels = 33; /* more than 32 bits are not allowed */
+	cmp_set_max_used_bits(&max_used_bits);
+	cmp_bits = icu_compress_data(&cfg);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_bits);
+}
+
+
+/**
+ * @test pad_bitstream
+ */
+
+void test_pad_bitstream(void)
+{
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+	int cmp_size_return;
+	uint32_t cmp_data[3];
+	const int MAX_BIT_LEN = 96;
+
+	memset(cmp_data, 0xFF, sizeof(cmp_data));
+	cfg.icu_output_buf = cmp_data;
+	cfg.data_type = DATA_TYPE_IMAGETTE; /* 16 bit samples */
+	cfg.buffer_length = 6; /* 6 * 16 bit samples -> 3 * 32 bit */
+
+	/* test negative cmp_size */
+	cmp_size = -1;
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(-1, cmp_size_return);
+	cmp_size = -3;
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(-3, cmp_size_return);
+
+	/* test RAW_MODE */
+	cfg.cmp_mode = CMP_MODE_RAW;
+	cmp_size = MAX_BIT_LEN;
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(MAX_BIT_LEN, cmp_size_return);
+	TEST_ASSERT_EQUAL_INT(cmp_data[0], 0xFFFFFFFF);
+	TEST_ASSERT_EQUAL_INT(cmp_data[1], 0xFFFFFFFF);
+	TEST_ASSERT_EQUAL_INT(cmp_data[2], 0xFFFFFFFF);
+
+	/* test Normal operation */
+	cfg.cmp_mode = CMP_MODE_MODEL_MULTI;
+	cmp_size = 0;
+	/* set the first 32 bits zero no change should occur */
+	cmp_size = put_n_bits32(0, 32, cmp_size, cfg.icu_output_buf, MAX_BIT_LEN);
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size, cmp_size_return);
+	TEST_ASSERT_EQUAL_INT(cmp_data[0], 0);
+	TEST_ASSERT_EQUAL_INT(cmp_data[1], 0xFFFFFFFF);
+	TEST_ASSERT_EQUAL_INT(cmp_data[2], 0xFFFFFFFF);
+
+	/* set the first 33 bits zero; and checks the padding  */
+	cmp_size = put_n_bits32(0, 1, cmp_size, cfg.icu_output_buf, MAX_BIT_LEN);
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size, cmp_size_return);
+	TEST_ASSERT_EQUAL_INT(cmp_data[0], 0);
+	TEST_ASSERT_EQUAL_INT(cmp_data[1], 0);
+	TEST_ASSERT_EQUAL_INT(cmp_data[2], 0xFFFFFFFF);
+
+	/* set the first 63 bits zero; and checks the padding  */
+	cmp_data[1] = 0xFFFFFFFF;
+	cmp_size = 32;
+	cmp_size = put_n_bits32(0, 31, cmp_size, cfg.icu_output_buf, MAX_BIT_LEN);
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size, cmp_size_return);
+	TEST_ASSERT_EQUAL_INT(cmp_data[0], 0);
+	TEST_ASSERT_EQUAL_INT(cmp_data[1], 0);
+	TEST_ASSERT_EQUAL_INT(cmp_data[2], 0xFFFFFFFF);
+
+	/* error case the rest of the compressed data are to small dor a 32 bit
+	 * access  */
+	cfg.buffer_length = 5;
+	cmp_size = 64;
+	cmp_size = put_n_bits32(0, 1, cmp_size, cfg.icu_output_buf, MAX_BIT_LEN);
+	cmp_size_return = pad_bitstream(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size_return);
+}
+
+
+/**
+ * @test cmp_data_to_big_endian
+ */
+
+void test_cmp_data_to_big_endian_error_cases(void)
+{
+	struct cmp_cfg cfg = {0};
+	int cmp_size;
+	int cmp_size_return;
+	uint16_t cmp_data[3] = {0x0123, 0x4567, 0x89AB};
+	uint8_t *p;
+
+	cfg.icu_output_buf = (uint32_t *)cmp_data;
+
+	/* this should work */
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_RAW;
+	cmp_size = 48;
+	cmp_size_return = cmp_data_to_big_endian(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size_return, 48);
+	p = (uint8_t *)cfg.icu_output_buf;
+	TEST_ASSERT_EQUAL(p[0], 0x01);
+	TEST_ASSERT_EQUAL(p[1], 0x23);
+	TEST_ASSERT_EQUAL(p[2], 0x45);
+	TEST_ASSERT_EQUAL(p[3], 0x67);
+	TEST_ASSERT_EQUAL(p[4], 0x89);
+	TEST_ASSERT_EQUAL(p[5], 0xAB);
+
+	/* error cases */
+	cmp_data[0] = 0x0123;
+	cmp_data[1] = 0x4567;
+	cmp_data[2] = 0x89AB;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_RAW;
+	cmp_size = 47; /* wrong size */
+	cmp_size_return = cmp_data_to_big_endian(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size_return, -1);
+
+	cmp_data[0] = 0x0123;
+	cmp_data[1] = 0x4567;
+	cmp_data[2] = 0x89AB;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.cmp_mode = CMP_MODE_RAW;
+	cmp_size = 49; /* wrong size */
+	cmp_size_return = cmp_data_to_big_endian(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size_return, -1);
+
+	cmp_data[0] = 0x0123;
+	cmp_data[1] = 0x4567;
+	cmp_data[2] = 0x89AB;
+	cfg.data_type = DATA_TYPE_UNKNOWN; /* wrong data_type */
+	cfg.cmp_mode = CMP_MODE_RAW;
+	cmp_size = 48;
+	cmp_size_return = cmp_data_to_big_endian(&cfg, cmp_size);
+	TEST_ASSERT_EQUAL_INT(cmp_size_return, -1);
+}
 
 
 /**
@@ -3024,8 +4364,6 @@ void test_icu_compress_data_error_cases(void)
 {
 	int cmp_size;
 	struct cmp_cfg cfg = {0};
-	uint16_t data[4] = {0, 0xFFFF, 23, 42};
-	uint32_t cmp_data_buf[4] = {0};
 
 	/* cfg = NULL test */
 	cmp_size = icu_compress_data(NULL);
@@ -3035,6 +4373,5 @@ void test_icu_compress_data_error_cases(void)
 	cfg.samples = 0;
 	cmp_size = icu_compress_data(&cfg);
 	TEST_ASSERT_EQUAL(0, cmp_size);
-
 }
 
-- 
GitLab


From d63effd98c023bc9772ccf6665c3940e0695e3fb Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 20 Sep 2022 12:30:12 +0200
Subject: [PATCH 31/46] Add check in the cmp_cfg_icu_buffers function if the
 compressed data can fit in a compression entity fix some typos; disable 3
 times smaller warning if cfg->icu_output_buf = NULL

---
 include/cmp_icu.h |  8 ++++----
 lib/cmp_icu.c     | 26 +++++++++++++++++++-------
 2 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/include/cmp_icu.h b/include/cmp_icu.h
index 8b68fcb..743e7d1 100644
--- a/include/cmp_icu.h
+++ b/include/cmp_icu.h
@@ -28,10 +28,10 @@
 struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
 				  uint32_t model_value, uint32_t lossy_par);
 
-size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
-			   uint32_t data_samples, void *model_of_data,
-			   void *updated_model, uint32_t *compressed_data,
-			   uint32_t compressed_data_len_samples);
+uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
+			     uint32_t data_samples, void *model_of_data,
+			     void *updated_model, uint32_t *compressed_data,
+			     uint32_t compressed_data_len_samples);
 
 int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
 			 uint32_t spillover_par);
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index 107b85d..a05a98f 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -37,6 +37,7 @@
 #include <cmp_data_types.h>
 #include <cmp_support.h>
 #include <cmp_icu.h>
+#include <cmp_entity.h>
 
 
 /* maximum used bits registry */
@@ -118,11 +119,13 @@ struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cm
  *	parameters are invalid
  */
 
-size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
-			   uint32_t data_samples, void *model_of_data,
-			   void *updated_model, uint32_t *compressed_data,
-			   uint32_t compressed_data_len_samples)
+uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
+			     uint32_t data_samples, void *model_of_data,
+			     void *updated_model, uint32_t *compressed_data,
+			     uint32_t compressed_data_len_samples)
 {
+	uint32_t data_size, hdr_size;
+
 	if (!cfg) {
 		debug_print("Error: pointer to the compression configuration structure is NULL.\n");
 		return 0;
@@ -138,7 +141,15 @@ size_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
 	if (!cmp_cfg_icu_buffers_is_valid(cfg))
 		return 0;
 
-	return cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type);
+	data_size = cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type);
+	hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW);
+
+	if ((data_size + hdr_size) > CMP_ENTITY_MAX_SIZE) {
+		debug_print("Error: The buffer for the compressed data is too large to fit in a compression entity.\n");
+		return 0;
+	}
+
+	return data_size;
 }
 
 
@@ -643,7 +654,7 @@ static int encode_value_multi(uint32_t data, uint32_t model, int stream_len,
 
 
 /**
- * @brief put the value unencoded with(setup->cmp_par_1 bits without any changes
+ * @brief put the value unencoded with setup->cmp_par_1 bits without any changes
  *	in the bitstream
  *
  * @param value		value to put unchanged in the bitstream
@@ -783,6 +794,7 @@ static int configure_encoder_setup(struct encoder_setupt *setup,
 		setup->encode_method_f = &encode_value_none;
 		setup->max_data_bits = cmp_par;
 		break;
+	case CMP_MODE_RAW:
 	default:
 		return -1;
 	}
@@ -2340,7 +2352,7 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 			memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size);
 		cmp_size *= CHAR_BIT; /* convert to bits */
 	} else {
-		if (cfg->samples < cfg->buffer_length/3)
+		if (cfg->icu_output_buf && cfg->samples/3 > cfg->buffer_length)
 			debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended.\n");
 
 		switch (cfg->data_type) {
-- 
GitLab


From 315ce82bbece6bd37bb9dc6167a90eea614febdf Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 20 Sep 2022 13:42:39 +0200
Subject: [PATCH 32/46] fix some type stuff

---
 lib/cmp_data_types.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 3064e6c..ee0131f 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -17,11 +17,14 @@
  */
 
 
+#include <stdint.h>
+#include <stdio.h>
+#include <limits.h>
+
+
 #include <cmp_data_types.h>
 #include <cmp_debug.h>
 #include <byteorder.h>
-#include <stdint.h>
-#include <stdio.h>
 
 
 /* the maximum length of the different data products types in bits */
@@ -187,12 +190,12 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
  *
  * @note for non-imagette data program types the multi entry header size is added
  *
- * @returns the size in bytes to store the data sample
+ * @returns the size in bytes to store the data sample; zero on failure
  */
 
 unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type)
 {
-	unsigned int s = size_of_a_sample(data_type);
+	size_t s = size_of_a_sample(data_type);
 	uint64_t x; /* use 64 bit to catch overflow */
 
 	if (!s)
@@ -203,7 +206,7 @@ unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_
 	if (!rdcu_supported_data_type_is_used(data_type))
 		x += MULTI_ENTRY_HDR_SIZE;
 
-	if (x > UINT32_MAX) /* catch overflow */
+	if (x > UINT_MAX) /* catch overflow */
 		return 0;
 
 	return (unsigned int)x;
@@ -222,7 +225,7 @@ unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_
 
 int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type)
 {
-	int samples_size = (int)size_of_a_sample(data_type);
+	uint32_t samples_size = size_of_a_sample(data_type);
 
 	if (!samples_size)
 		return -1;
@@ -236,7 +239,7 @@ int cmp_input_size_to_samples(unsigned int size, enum cmp_data_type data_type)
 	if (size % samples_size)
 		return -1;
 
-	return size/samples_size;
+	return (int)(size/samples_size);
 }
 
 
-- 
GitLab


From acf80c8c013f4a179bad28036dca21ede07f0327 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 20 Sep 2022 13:47:13 +0200
Subject: [PATCH 33/46] minor changes

---
 include/cmp_support.h |  2 +-
 lib/cmp_support.c     | 18 ++++--------------
 2 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/include/cmp_support.h b/include/cmp_support.h
index b69eb5c..d0ffbe3 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -153,7 +153,7 @@ struct cmp_cfg {
 	uint32_t rdcu_new_model_adr;/* RDCU updated model start address, the address in the RDCU SRAM where the updated model is stored */
 	uint32_t rdcu_buffer_adr;   /* RDCU compressed data start address, the first output data address in the RDCU SRAM */
 	enum cmp_data_type data_type; /* Compression Data Product Types */
-	uint32_t cmp_mode;          /* 0: raw mode
+	enum cmp_mode cmp_mode;     /* 0: raw mode
 				     * 1: model mode with zero escape symbol mechanism
 				     * 2: 1d differencing mode without input model with zero escape symbol mechanism
 				     * 3: model mode with multi escape symbol mechanism
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index f157a6e..5572a90 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -149,6 +149,7 @@ int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode)
 	case CMP_MODE_MODEL_MULTI:
 	case CMP_MODE_DIFF_MULTI:
 		return 1;
+	case CMP_MODE_STUFF:
 	default:
 		return 0;
 	}
@@ -250,17 +251,7 @@ int multi_escape_mech_is_used(enum cmp_mode cmp_mode)
 
 int cmp_imagette_data_type_is_used(enum cmp_data_type data_type)
 {
-	switch (data_type) {
-	case DATA_TYPE_IMAGETTE:
-	case DATA_TYPE_IMAGETTE_ADAPTIVE:
-	case DATA_TYPE_SAT_IMAGETTE:
-	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
-	case DATA_TYPE_F_CAM_IMAGETTE:
-	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
-		return 1;
-	default:
-		return 0;
-	}
+	return rdcu_supported_data_type_is_used(data_type);
 }
 
 
@@ -487,7 +478,7 @@ int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg)
 	}
 
 	if (cfg->cmp_mode > CMP_MODE_STUFF) {
-		debug_print("Error: selected cmp_mode: %u is not supported.\n", cfg->cmp_mode);
+		debug_print("Error: selected cmp_mode: %i is not supported.\n", cfg->cmp_mode);
 		cfg_invalid++;
 	}
 
@@ -594,7 +585,6 @@ int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
  * @param cmp_par	compression parameter
  * @param spill		spillover threshold parameter
  * @param cmp_mode	compression mode
- * @param data_type	compression data type
  * @param par_name	string describing the use of the compression par. for
  *			debug messages (can be NULL)
  *
@@ -891,7 +881,7 @@ void print_cmp_cfg(const struct cmp_cfg *cfg)
 {
 	size_t i;
 
-	printf("cmp_mode: %u\n", cfg->cmp_mode);
+	printf("cmp_mode: %i\n", cfg->cmp_mode);
 	printf("golomb_par: %u\n", cfg->golomb_par);
 	printf("spill: %u\n", cfg->spill);
 	printf("model_value: %u\n", cfg->model_value);
-- 
GitLab


From 11f472d00b8c3ca25455a2134b630f199998bec8 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 20 Sep 2022 13:49:06 +0200
Subject: [PATCH 34/46] fix a bug in the cmp_ent_get_data_buf() function

---
 lib/cmp_entity.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index c0b2898..b66216c 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -1650,13 +1650,13 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 
 	switch (data_type) {
 	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE:
 	case DATA_TYPE_F_CAM_IMAGETTE:
 		return ent->ima.ima_cmp_dat;
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		return ent->ima.ap_ima_cmp_data;
-	case DATA_TYPE_SAT_IMAGETTE:
-	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_OFFSET:
 	case DATA_TYPE_BACKGROUND:
 	case DATA_TYPE_SMEARING:
@@ -2038,7 +2038,7 @@ int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *i
  *			returns the needed size
  * @param data_type	compression entity data product type
  * @param raw_mode_flag	set this flag if the raw compression mode (CMP_MODE_RAW) is used
- * @param cmp_size_byte	size of the compressed data in bytes
+ * @param cmp_size_byte	size of the compressed data in bytes (should be a multiple of 4)
  *
  * @note if the entity size is smaller than the largest header, the function
  *	rounds up the entity size to the largest header
@@ -2063,6 +2063,8 @@ uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type,
 	if (ent_size > CMP_ENTITY_MAX_SIZE)
 		return 0;
 
+	/* to be safe a compression entity should be at least the size of the
+	 * largest entity header */
 	if (ent_size < sizeof(struct cmp_entity))
 		ent_size = sizeof(struct cmp_entity);
 
-- 
GitLab


From c6cf8e0c004324d46fc6113dddd0e39ca5dd9447 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 20 Sep 2022 14:27:19 +0200
Subject: [PATCH 35/46] add STUFF mode decompression remove
 setup->max_stream_len assume now that the max cw_len is always 32 bits add a
 input parameter check for the rice_decoder() function change input parameter
 check for get_n_bits32() function

---
 lib/decmp.c | 80 ++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 58 insertions(+), 22 deletions(-)

diff --git a/lib/decmp.c b/lib/decmp.c
index f15c943..da75d50 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -32,6 +32,8 @@
 #include "cmp_entity.h"
 
 
+#define MAX_CW_LEN 32 /* maximum Golomb code word bit length */
+
 /* maximum used bits registry */
 extern struct cmp_max_used_bits max_used_bits;
 
@@ -45,7 +47,6 @@ struct decoder_setup {
 			       const struct decoder_setup *setup); /* pointer to the decoding function */
 	uint32_t *bitstream_adr; /* start address of the compressed data bitstream */
 	uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */
-	uint32_t max_cw_len; /* TODO */
 	uint32_t encoder_par1; /* encoding parameter 1 */
 	uint32_t encoder_par2; /* encoding parameter 2 */
 	uint32_t outlier_par; /* outlier parameter */
@@ -93,8 +94,8 @@ static unsigned int count_leading_ones(uint32_t value)
  *	0 on failure
  */
 
-static int rice_decoder(uint32_t code_word, unsigned int m,
-				 unsigned int log2_m, unsigned int *decoded_cw)
+static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m,
+			unsigned int *decoded_cw)
 {
 	unsigned int q; /* quotient code */
 	unsigned int ql; /* length of the quotient code */
@@ -104,6 +105,9 @@ static int rice_decoder(uint32_t code_word, unsigned int m,
 
 	(void)m; /* we don't need the Golomb parameter */
 
+	if (log2_m > 32)
+		return 0;
+
 	q = count_leading_ones(code_word); /* decode unary coding */
 	ql = q + 1; /* Number of 1's + following 0 */
 
@@ -124,7 +128,7 @@ static int rice_decoder(uint32_t code_word, unsigned int m,
 	else
 		r = code_word >> (32 - rl);
 
-	*decoded_cw = (q << log2_m) + r;
+	*decoded_cw = (q << rl) + r;
 
 	return cw_len;
 }
@@ -206,16 +210,15 @@ static decoder_ptr select_decoder(unsigned int golomb_par)
 /**
  * @brief read a value of up to 32 bits from a bitstream
  *
- * @param p_value		pointer to the read value (can be NULL), the
+ * @param p_value		pointer to the read value, the
  *				read value will be converted to the system
  *				endianness
  * @param n_bits		number of bits to read from the bitstream
  * @param bit_offset		bit index where the bits will be read, seen from
  *				the very beginning of the bitstream
  * @param bitstream_adr		this is the pointer to the beginning of the
- *				bitstream (can be NULL)
- * @param max_stream_len	maximum length of the bitstream in bits; is
- *				ignored if bitstream_adr is NULL
+ *				bitstream
+ * @param max_stream_len	maximum length of the bitstream in bits *
  *
  * @returns bit position of the last read bit in the bitstream on success;
  *	returns negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF
@@ -238,12 +241,10 @@ static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
 		return -1;
 	if (n_bits > 32)
 		return -1;
-
-	/* nothing to read */
 	if (!bitstream_adr)
-		return stream_len;
+		return -1;
 	if (!p_value)
-		return stream_len;
+		return -1;
 
 	/* Check if bitstream buffer is large enough */
 	if ((unsigned int)stream_len > max_stream_len) {
@@ -310,10 +311,10 @@ static int decode_normal(uint32_t *decoded_value, int stream_pos,
 
 	/* check if we can read max_cw_len or less; we do not now how long the
 	 * code word actually is so we try to read the maximum cw length */
-	if ((unsigned int)stream_pos + setup->max_cw_len > setup->max_stream_len)
+	if ((unsigned int)stream_pos + 32 > setup->max_stream_len)
 		n_read_bits = setup->max_stream_len - (unsigned int)stream_pos;
 	else
-		n_read_bits = setup->max_cw_len;
+		n_read_bits = MAX_CW_LEN;
 
 	stream_pos_read = get_n_bits32(&read_val, n_read_bits, stream_pos,
 				       setup->bitstream_adr, setup->max_stream_len);
@@ -410,13 +411,37 @@ static int decode_multi(uint32_t *decoded_value, int stream_pos,
 
 		stream_pos = get_n_bits32(&unencoded_val, unencoded_len, stream_pos,
 					  setup->bitstream_adr, setup->max_stream_len);
-
-		*decoded_value = unencoded_val + setup->outlier_par;
+		if (stream_pos >= 0)
+			*decoded_value = unencoded_val + setup->outlier_par;
 	}
 	return stream_pos;
 }
 
 
+/**
+ * @brief get the value unencoded with setup->cmp_par_1 bits without any
+ *	additional changes from the bitstream
+ *
+ * @param decoded_value	pointer to the decoded value
+ * @param stream_pos	start bit position code word to be decoded in the bitstream
+ * @param setup		pointer to the decoder setup
+ *
+ * @returns bit index of the next code word in the bitstream on success; returns
+ *	negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the
+ *	bitstream buffer is too small to read the value from the bitstream
+ *
+ */
+
+static int decode_none(uint32_t *decoded_value, int stream_pos,
+		       const struct decoder_setup *setup)
+{
+	stream_pos = get_n_bits32(decoded_value, setup->encoder_par1, stream_pos,
+				  setup->bitstream_adr, setup->max_stream_len);
+
+	return stream_pos;
+}
+
+
 /**
  * @brief remap a unsigned value back to a signed value
  * @note this is the reverse function of map_to_pos()
@@ -461,11 +486,14 @@ static int decode_value(uint32_t *decoded_value, uint32_t model,
 	if (stream_pos <= 0)
 		return stream_pos;
 
+	if (setup->decode_method_f == decode_none) /* we are done here in stuff mode */
+		return stream_pos;
+
 	*decoded_value = re_map_to_pos(*decoded_value);
 
 	*decoded_value += round_fwd(model, setup->lossy_par);
 
-	*decoded_value &= mask;
+	*decoded_value &= mask; /* TODO: why?? */
 
 	*decoded_value = round_inv(*decoded_value, setup->lossy_par);
 
@@ -482,7 +510,10 @@ static int configure_decoder_setup(struct decoder_setup *setup,
 		setup->decode_method_f = &decode_multi;
 	else if (zero_escape_mech_is_used(cfg->cmp_mode))
 		setup->decode_method_f = &decode_zero;
+	else if (cfg->cmp_mode == CMP_MODE_STUFF)
+		setup->decode_method_f = &decode_none;
 	else {
+		setup->decode_method_f = NULL;
 		debug_print("Error: Compression mode not supported.\n");
 		return -1;
 	}
@@ -493,11 +524,9 @@ static int configure_decoder_setup(struct decoder_setup *setup,
 		return -1;
 	}
 	setup->max_stream_len = (cfg->buffer_length) * CHAR_BIT;  /* maximum length of the bitstream/icu_output_buf in bits */
-	if (rdcu_supported_data_type_is_used(cfg->data_type))
-		setup->max_cw_len = 16;
-	else
-		setup->max_cw_len = 32;
 	setup->encoder_par1 = cmp_par; /* encoding parameter 1 */
+	if (ilog_2(cmp_par) < 0)
+		return -1;
 	setup->encoder_par2 = ilog_2(cmp_par); /* encoding parameter 2 */
 	setup->outlier_par = spill; /* outlier parameter */
 	setup->lossy_par = lossy_par; /* lossy compression parameter */
@@ -1708,6 +1737,12 @@ static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 				cfg->model_value, setup_ncob.lossy_par);
 			up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y,
 				cfg->model_value, setup_ncob.lossy_par);
+			up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx,
+				cfg->model_value, setup_efx.lossy_par);
+			up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x,
+				cfg->model_value, setup_ecob.lossy_par);
+			up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y,
+				cfg->model_value, setup_ecob.lossy_par);
 			up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance,
 				cfg->model_value, setup_fx_var.lossy_par);
 			up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance,
@@ -1968,7 +2003,8 @@ static int decompressed_data_internal(struct cmp_cfg *cfg)
 	int data_size, strem_len_bit = -1;
 
 	if (!cfg)
-		return 0; /* or -1? */
+		return -1;
+
 	if (!cfg->icu_output_buf)
 		return -1;
 
-- 
GitLab


From a814557224662714df6395ab765a292d15738f1b Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 26 Sep 2022 11:54:31 +0200
Subject: [PATCH 36/46] restrict the maximum compression golomb parameter for
 imagette compression, in order that the compression parameter fit into the
 imagette compression entity header; refactor the compression check functions

---
 include/cmp_support.h       |  24 ++--
 lib/cmp_guess.c             |  18 +--
 lib/cmp_icu.c               |  28 +++--
 lib/cmp_rdcu.c              |  46 +++----
 lib/cmp_support.c           | 245 ++++++++++++++++++------------------
 test/cmp_icu/test_cmp_icu.c |  35 +++---
 test/cmp_icu/test_decmp.c   |  54 +++++---
 7 files changed, 237 insertions(+), 213 deletions(-)

diff --git a/include/cmp_support.h b/include/cmp_support.h
index d0ffbe3..be598aa 100644
--- a/include/cmp_support.h
+++ b/include/cmp_support.h
@@ -38,11 +38,11 @@
 #define MAX_MODEL_VALUE                                                        \
 	16U /* the maximal model values used in the update equation for the new model */
 
-/* valid compression parameter ranges for RDCU compression according to PLATO-UVIE-PL-UM-0001 */
+/* valid compression parameter ranges for RDCU/ICU imagette compression according to PLATO-UVIE-PL-UM-0001 */
 #define MAX_RDCU_CMP_MODE	4U
-#define MIN_RDCU_GOLOMB_PAR	1U
-#define MAX_RDCU_GOLOMB_PAR	63U
-#define MIN_RDCU_SPILL		2U
+#define MIN_IMA_GOLOMB_PAR	1U
+#define MAX_IMA_GOLOMB_PAR	63U
+#define MIN_IMA_SPILL		2U
 #define MAX_RDCU_ROUND		2U
 /* for maximum spill value look at cmp_rdcu_max_spill function */
 
@@ -91,6 +91,8 @@
 #define CMP_DEF_IMA_DIFF_RDCU_UP_MODEL_ADR	0x000000 /* not needed for 1d-differencing cmp_mode */
 #define CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR	0x600000
 
+enum {ICU_CHECK, RDCU_CHECK}; /* option for the cmp_cfg_imagette_is_invalid() function */
+
 
 /* defined compression data product types */
 enum cmp_data_type {
@@ -237,13 +239,13 @@ int ilog_2(uint32_t x);
 
 unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit);
 
-int cmp_cfg_is_valid(const struct cmp_cfg *cfg);
-int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg);
-int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg);
-int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg);
-int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg);
-int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg);
-uint32_t cmp_rdcu_max_spill(unsigned int golomb_par);
+int cmp_cfg_is_invalid(const struct cmp_cfg *cfg);
+int cmp_cfg_icu_gen_par_is_invalid(const struct cmp_cfg *cfg);
+int cmp_cfg_icu_buffers_is_invalid(const struct cmp_cfg *cfg);
+int cmp_cfg_imagette_is_invalid(const struct cmp_cfg *cfg, int rdcu_check);
+int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg);
+int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg);
+uint32_t cmp_ima_max_spill(unsigned int golomb_par);
 uint32_t cmp_icu_max_spill(unsigned int cmp_par);
 
 int cmp_data_type_valid(enum cmp_data_type data_type);
diff --git a/lib/cmp_guess.c b/lib/cmp_guess.c
index 40e3ebe..87aec6c 100644
--- a/lib/cmp_guess.c
+++ b/lib/cmp_guess.c
@@ -83,7 +83,7 @@ uint16_t cmp_guess_model_value(int n_model_updates)
 
 uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode)
 {
-	const uint32_t LUT_RDCU_MULIT[MAX_RDCU_GOLOMB_PAR+1] = {0, 8, 16, 23,
+	const uint32_t LUT_IMA_MULIT[MAX_IMA_GOLOMB_PAR+1] = {0, 8, 16, 23,
 		30, 36, 44, 51, 58, 64, 71, 77, 84, 90, 97, 108, 115, 121, 128,
 		135, 141, 148, 155, 161, 168, 175, 181, 188, 194, 201, 207, 214,
 		229, 236, 242, 250, 256, 263, 269, 276, 283, 290, 296, 303, 310,
@@ -91,13 +91,13 @@ uint32_t cmp_rdcu_get_good_spill(unsigned int golomb_par, enum cmp_mode cmp_mode
 		405, 411, 418, 424, 431, 452 };
 
 	if (zero_escape_mech_is_used(cmp_mode))
-		return cmp_rdcu_max_spill(golomb_par);
+		return cmp_ima_max_spill(golomb_par);
 
 	if (cmp_mode == CMP_MODE_MODEL_MULTI) {
-		if (golomb_par > MAX_RDCU_GOLOMB_PAR)
+		if (golomb_par > MAX_IMA_GOLOMB_PAR)
 			return 0;
 		else
-			return LUT_RDCU_MULIT[golomb_par];
+			return LUT_IMA_MULIT[golomb_par];
 	}
 
 	if (cmp_mode == CMP_MODE_DIFF_MULTI)
@@ -123,7 +123,7 @@ static uint32_t pre_cal_method(struct cmp_cfg *cfg)
 	uint32_t golomb_par_best = 0;
 	uint32_t spill_best = 0;
 
-	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
+	for (g = MIN_IMA_GOLOMB_PAR; g < MAX_IMA_GOLOMB_PAR; g++) {
 		uint32_t s = cmp_rdcu_get_good_spill(g, cfg->cmp_mode);
 
 		cfg->golomb_par = g;
@@ -171,8 +171,8 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 	printf("0%%... ");
 	fflush(stdout);
 
-	for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; g++) {
-		for (s = MIN_RDCU_SPILL; s < cmp_rdcu_max_spill(g); s++) {
+	for (g = MIN_IMA_GOLOMB_PAR; g < MAX_IMA_GOLOMB_PAR; g++) {
+		for (s = MIN_IMA_SPILL; s < cmp_ima_max_spill(g); s++) {
 			cfg->golomb_par = g;
 			cfg->spill = s;
 
@@ -211,11 +211,11 @@ static uint32_t brute_force(struct cmp_cfg *cfg)
 
 static void add_rdcu_pars_internal(struct cmp_cfg *cfg)
 {
-	if (cfg->golomb_par == MIN_RDCU_GOLOMB_PAR) {
+	if (cfg->golomb_par == MIN_IMA_GOLOMB_PAR) {
 		cfg->ap1_golomb_par = cfg->golomb_par + 1;
 		cfg->ap2_golomb_par = cfg->golomb_par + 2;
 
-	} else if (cfg->golomb_par == MAX_RDCU_GOLOMB_PAR) {
+	} else if (cfg->golomb_par == MAX_IMA_GOLOMB_PAR) {
 		cfg->ap1_golomb_par = cfg->golomb_par - 2;
 		cfg->ap2_golomb_par = cfg->golomb_par - 1;
 	} else {
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index a05a98f..79d1a64 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -79,7 +79,6 @@ struct encoder_setupt {
 struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode,
 				  uint32_t model_value, uint32_t lossy_par)
 {
-	int cfg_valid;
 	struct cmp_cfg cfg;
 
 	memset(&cfg, 0, sizeof(cfg));
@@ -89,8 +88,7 @@ struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cm
 	cfg.model_value = model_value;
 	cfg.round = lossy_par;
 
-	cfg_valid = cmp_cfg_icu_gen_par_is_valid(&cfg);
-	if (!cfg_valid)
+	if (cmp_cfg_icu_gen_par_is_invalid(&cfg))
 		cfg.data_type = DATA_TYPE_UNKNOWN;
 
 	return cfg;
@@ -138,7 +136,7 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress,
 	cfg->icu_output_buf = compressed_data;
 	cfg->buffer_length = compressed_data_len_samples;
 
-	if (!cmp_cfg_icu_buffers_is_valid(cfg))
+	if (cmp_cfg_icu_buffers_is_invalid(cfg))
 		return 0;
 
 	data_size = cmp_cal_size_of_data(compressed_data_len_samples, cfg->data_type);
@@ -173,7 +171,7 @@ int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par,
 	cfg->golomb_par = cmp_par;
 	cfg->spill = spillover_par;
 
-	if (!cmp_cfg_imagette_is_valid(cfg))
+	if (cmp_cfg_imagette_is_invalid(cfg, ICU_CHECK))
 		return -1;
 
 	return 0;
@@ -227,7 +225,7 @@ int cmp_cfg_fx_cob(struct cmp_cfg *cfg,
 	cfg->spill_ecob = spillover_ecob;
 	cfg->spill_fx_cob_variance = spillover_fx_cob_variance;
 
-	if (!cmp_cfg_fx_cob_is_valid(cfg))
+	if (cmp_cfg_fx_cob_is_invalid(cfg))
 		return -1;
 
 	return 0;
@@ -268,7 +266,7 @@ int cmp_cfg_aux(struct cmp_cfg *cfg,
 	cfg->spill_variance = spillover_variance;
 	cfg->spill_pixels_error = spillover_pixels_error;
 
-	if (!cmp_cfg_aux_is_valid(cfg))
+	if (cmp_cfg_aux_is_invalid(cfg))
 		return -1;
 
 	return 0;
@@ -2250,7 +2248,10 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size)
 	if (cmp_size < 0)
 		return cmp_size;
 
-	/* no padding in RAW mode; DIFFERENCE ENDIANNESS */
+	if (!cfg->icu_output_buf)
+		return cmp_size;
+
+	/* no padding in RAW mode; ALWAYS BIG-ENDIAN */
 	if (cfg->cmp_mode == CMP_MODE_RAW)
 		return cmp_size;
 
@@ -2288,6 +2289,9 @@ static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, int cmp_size)
 	if (cmp_size < 0)
 		return cmp_size;
 
+	if (!cfg->icu_output_buf)
+		return cmp_size;
+
 	if (cfg->cmp_mode == CMP_MODE_RAW) {
 		if (s & 0x7) /* size must be a multiple of 8 in RAW mode */
 			return -1;
@@ -2343,7 +2347,7 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 		if (cfg->samples > cfg->buffer_length)
 			return CMP_ERROR_SMALL_BUF;
 
-	if (!cmp_cfg_is_valid(cfg))
+	if (cmp_cfg_is_invalid(cfg))
 		return -1;
 
 	if (raw_mode_is_used(cfg->cmp_mode)) {
@@ -2425,10 +2429,8 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 		/* LCOV_EXCL_STOP */
 	}
 
-	if (cfg->icu_output_buf) {
-		cmp_size = pad_bitstream(cfg, cmp_size);
-		cmp_size = cmp_data_to_big_endian(cfg, cmp_size);
-	}
+	cmp_size = pad_bitstream(cfg, cmp_size);
+	cmp_size = cmp_data_to_big_endian(cfg, cmp_size);
 
 	return cmp_size;
 }
diff --git a/lib/cmp_rdcu.c b/lib/cmp_rdcu.c
index c3ffb7c..6a73545 100644
--- a/lib/cmp_rdcu.c
+++ b/lib/cmp_rdcu.c
@@ -413,60 +413,60 @@ static int rdcu_cfg_imagette_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 
-	if (cfg->golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		debug_print("Error: The selected Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%u, %u].\n",
-			    cfg->golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+	if (cfg->golomb_par < MIN_IMA_GOLOMB_PAR ||
+	    cfg->golomb_par > MAX_IMA_GOLOMB_PAR) {
+		debug_print("Error: The selected Golomb parameter: %u is not supported. The Golomb parameter has to be between [%u, %u].\n",
+			    cfg->golomb_par, MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
 		cfg_invalid++;
 	}
 
-	if (cfg->ap1_golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->ap1_golomb_par > MAX_RDCU_GOLOMB_PAR) {
-		debug_print("Error: The selected adaptive 1 Golomb parameter: %u is not supported. The Golomb parameter has to  be between [%u, %u].\n",
-			    cfg->ap1_golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+	if (cfg->ap1_golomb_par < MIN_IMA_GOLOMB_PAR ||
+	    cfg->ap1_golomb_par > MAX_IMA_GOLOMB_PAR) {
+		debug_print("Error: The selected adaptive 1 Golomb parameter: %u is not supported. The Golomb parameter has to be between [%u, %u].\n",
+			    cfg->ap1_golomb_par, MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
 		cfg_invalid++;
 	}
 
-	if (cfg->ap2_golomb_par < MIN_RDCU_GOLOMB_PAR ||
-	    cfg->ap2_golomb_par > MAX_RDCU_GOLOMB_PAR) {
+	if (cfg->ap2_golomb_par < MIN_IMA_GOLOMB_PAR ||
+	    cfg->ap2_golomb_par > MAX_IMA_GOLOMB_PAR) {
 		debug_print("Error: The selected adaptive 2 Golomb parameter: %u is not supported. The Golomb parameter has to be between [%u, %u].\n",
-			    cfg->ap2_golomb_par, MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+			    cfg->ap2_golomb_par, MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
 		cfg_invalid++;
 	}
 
-	if (cfg->spill < MIN_RDCU_SPILL) {
+	if (cfg->spill < MIN_IMA_SPILL) {
 		debug_print("Error: The selected spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
-			    cfg->spill, MIN_RDCU_SPILL);
+			    cfg->spill, MIN_IMA_SPILL);
 		cfg_invalid++;
 	}
 
-	if (cfg->spill > cmp_rdcu_max_spill(cfg->golomb_par)) {
+	if (cfg->spill > cmp_ima_max_spill(cfg->golomb_par)) {
 		debug_print("Error: The selected spillover threshold value: %u is too large for the selected Golomb parameter: %u, the largest possible spillover value is: %u.\n",
-			    cfg->spill, cfg->golomb_par, cmp_rdcu_max_spill(cfg->golomb_par));
+			    cfg->spill, cfg->golomb_par, cmp_ima_max_spill(cfg->golomb_par));
 		cfg_invalid++;
 	}
 
-	if (cfg->ap1_spill < MIN_RDCU_SPILL) {
+	if (cfg->ap1_spill < MIN_IMA_SPILL) {
 		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
-			    cfg->ap1_spill, MIN_RDCU_SPILL);
+			    cfg->ap1_spill, MIN_IMA_SPILL);
 		cfg_invalid++;
 	}
 
-	if (cfg->ap1_spill > cmp_rdcu_max_spill(cfg->ap1_golomb_par)) {
+	if (cfg->ap1_spill > cmp_ima_max_spill(cfg->ap1_golomb_par)) {
 		debug_print("Error: The selected adaptive 1 spillover threshold value: %u is too large for the selected adaptive 1 Golomb parameter: %u, the largest possible adaptive 1 spillover value is: %u.\n",
-			    cfg->ap1_spill, cfg->ap1_golomb_par, cmp_rdcu_max_spill(cfg->ap1_golomb_par));
+			    cfg->ap1_spill, cfg->ap1_golomb_par, cmp_ima_max_spill(cfg->ap1_golomb_par));
 		cfg_invalid++;
 	}
 
-	if (cfg->ap2_spill < MIN_RDCU_SPILL) {
+	if (cfg->ap2_spill < MIN_IMA_SPILL) {
 		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
-			    cfg->ap2_spill, MIN_RDCU_SPILL);
+			    cfg->ap2_spill, MIN_IMA_SPILL);
 		cfg_invalid++;
 	}
 
-	if (cfg->ap2_spill > cmp_rdcu_max_spill(cfg->ap2_golomb_par)) {
+	if (cfg->ap2_spill > cmp_ima_max_spill(cfg->ap2_golomb_par)) {
 		debug_print("Error: The selected adaptive 2 spillover threshold value: %u is too large for the selected adaptive 2 Golomb parameter: %u, the largest possible adaptive 2 spillover value is: %u.\n",
-			    cfg->ap2_spill, cfg->ap2_golomb_par, cmp_rdcu_max_spill(cfg->ap2_golomb_par));
+			    cfg->ap2_spill, cfg->ap2_golomb_par, cmp_ima_max_spill(cfg->ap2_golomb_par));
 		cfg_invalid++;
 	}
 
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index 5572a90..17deeed 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -389,8 +389,8 @@ unsigned int cmp_up_model(unsigned int data, unsigned int model,
 
 
 /**
- * @brief get the maximum valid spill threshold value for a RDCU HW compression
- *	in diff or model mode
+ * @brief get the maximum valid spill threshold value for a RDCU HW imagette
+ *	compression in diff or model mode
  *
  * @param golomb_par	Golomb parameter
  *
@@ -398,10 +398,10 @@ unsigned int cmp_up_model(unsigned int data, unsigned int model,
  *	 mode compression; 0 if golomb_par is invalid
  */
 
-uint32_t cmp_rdcu_max_spill(unsigned int golomb_par)
+uint32_t cmp_ima_max_spill(unsigned int golomb_par)
 {
 	/* the RDCU can only generate 16 bit long code words -> lower max spill needed */
-	const uint32_t LUT_MAX_RDCU[MAX_RDCU_GOLOMB_PAR+1] = { 0, 8, 22, 35, 48,
+	const uint32_t LUT_MAX_RDCU[MAX_IMA_GOLOMB_PAR+1] = { 0, 8, 22, 35, 48,
 		60, 72, 84, 96, 107, 118, 129, 140, 151, 162, 173, 184, 194,
 		204, 214, 224, 234, 244, 254, 264, 274, 284, 294, 304, 314, 324,
 		334, 344, 353, 362, 371, 380, 389, 398, 407, 416, 425, 434, 443,
@@ -409,7 +409,7 @@ uint32_t cmp_rdcu_max_spill(unsigned int golomb_par)
 		569, 578, 587, 596, 605, 614, 623 };
 
 
-	if (golomb_par > MAX_RDCU_GOLOMB_PAR)
+	if (golomb_par > MAX_IMA_GOLOMB_PAR)
 		return 0;
 
 	return LUT_MAX_RDCU[golomb_par];
@@ -458,14 +458,14 @@ unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
 
 /**
  * @brief check if the compression data type, compression mode, model value and
- *	the lossy rounding parameters are valid for a ICU compression
+ *	the lossy rounding parameters are invalid for a ICU compression
  *
  * @param cfg	pointer to the compressor configuration
  *
- * @returns 1 if generic compression parameters are valid, otherwise 0
+ * @returns 0 if generic compression parameters are valid, otherwise invalid
  */
 
-int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg)
+int cmp_cfg_icu_gen_par_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 
@@ -496,22 +496,19 @@ int cmp_cfg_icu_gen_par_is_valid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (cfg_invalid)
-		return 0;
-
-	return 1;
+	return cfg_invalid;
 }
 
 
 /**
- * @brief check if the buffer parameters are valid
+ * @brief check if the buffer parameters are invalid
  *
  * @param cfg	pointer to the compressor configuration
  *
- * @returns 1 if the buffer parameters are valid, otherwise 0
+ * @returns 0 if the buffer parameters are valid, otherwise invalid
  */
 
-int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
+int cmp_cfg_icu_buffers_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 
@@ -572,65 +569,81 @@ int cmp_cfg_icu_buffers_is_valid(const struct cmp_cfg *cfg)
 		}
 	}
 
-	if (cfg_invalid)
-		return 0;
-
-	return 1;
+	return cfg_invalid;
 }
 
 
 /**
- * @brief check if the combination of the different compression parameters is valid
+ * @brief check if the combination of the different compression parameters is invalid
  *
  * @param cmp_par	compression parameter
  * @param spill		spillover threshold parameter
  * @param cmp_mode	compression mode
+ * @param data_type	compression data type
  * @param par_name	string describing the use of the compression par. for
  *			debug messages (can be NULL)
  *
- * @returns 1 if the parameter combination is valid, otherwise 0
+ * @returns 0 if the parameter combination is valid, otherwise the combination is invalid
  */
 
-static int cmp_pars_are_valid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cmp_mode,
-			      char *par_name)
+static int cmp_pars_are_invalid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cmp_mode,
+				enum cmp_data_type data_type, char *par_name)
 {
 	int cfg_invalid = 0;
+	uint32_t min_golomb_par;
+	uint32_t max_golomb_par;
+	uint32_t min_spill;
+	uint32_t max_spill;
 
 	if (!par_name)
 		par_name = "";
 
+	/* The maximum compression parameter for imagette data are smaller to
+	 * fit into the imagette compression entity header */
+	if (cmp_imagette_data_type_is_used(data_type)) {
+		min_golomb_par = MIN_IMA_GOLOMB_PAR;
+		max_golomb_par = MAX_IMA_GOLOMB_PAR;
+		min_spill = MIN_IMA_SPILL;
+		max_spill = cmp_ima_max_spill(cmp_par);
+	} else {
+		min_golomb_par = MIN_ICU_GOLOMB_PAR;
+		max_golomb_par = MAX_ICU_GOLOMB_PAR;
+		min_spill = MIN_ICU_SPILL;
+		max_spill = cmp_icu_max_spill(cmp_par);
+	}
+
+
 	switch (cmp_mode) {
 	case CMP_MODE_RAW:
 		/* no checks needed */
 		break;
-	case CMP_MODE_STUFF:
-		if (cmp_par > MAX_STUFF_CMP_PAR) {
-			debug_print("Error: The selected %s stuff mode compression parameter: %u is too large, the largest possible value in the selected compression mode is: %u.\n",
-				    par_name, cmp_par, MAX_STUFF_CMP_PAR);
-			cfg_invalid++;
-		}
-		break;
 	case CMP_MODE_DIFF_ZERO:
 	case CMP_MODE_DIFF_MULTI:
 	case CMP_MODE_MODEL_ZERO:
 	case CMP_MODE_MODEL_MULTI:
-		if (cmp_par < MIN_ICU_GOLOMB_PAR ||
-		    cmp_par > MAX_ICU_GOLOMB_PAR) {
+		if (cmp_par < min_golomb_par || cmp_par > max_golomb_par) {
 			debug_print("Error: The selected %s compression parameter: %u is not supported. The compression parameter has to be between [%u, %u].\n",
-				    par_name, cmp_par, MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+				    par_name, cmp_par, min_golomb_par, max_golomb_par);
 			cfg_invalid++;
 		}
-		if (spill < MIN_ICU_SPILL) {
+		if (spill < min_spill) {
 			debug_print("Error: The selected %s spillover threshold value: %u is too small. Smallest possible spillover value is: %u.\n",
-				    par_name, spill, MIN_ICU_SPILL);
+				    par_name, spill, min_spill);
 			cfg_invalid++;
 		}
-		if (spill > cmp_icu_max_spill(cmp_par)) {
+		if (spill > max_spill) {
 			debug_print("Error: The selected %s spillover threshold value: %u is too large for the selected %s compression parameter: %u, the largest possible spillover value in the selected compression mode is: %u.\n",
-				    par_name, spill, par_name, cmp_par, cmp_icu_max_spill(cmp_par));
+				    par_name, spill, par_name, cmp_par, max_spill);
 			cfg_invalid++;
 		}
 
+		break;
+	case CMP_MODE_STUFF:
+		if (cmp_par > MAX_STUFF_CMP_PAR) {
+			debug_print("Error: The selected %s stuff mode compression parameter: %u is too large, the largest possible value in the selected compression mode is: %u.\n",
+				    par_name, cmp_par, MAX_STUFF_CMP_PAR);
+			cfg_invalid++;
+		}
 		break;
 	default:
 		debug_print("Error: The compression mode is not supported.\n");
@@ -638,24 +651,24 @@ static int cmp_pars_are_valid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cm
 		break;
 	}
 
-	if (cfg_invalid)
-		return 0;
-
-	return 1;
+	return cfg_invalid;
 }
 
 
 /**
- * @brief check if the imagette specific compression parameters are valid
+ * @brief check if the imagette specific compression parameters are invalid
  *
- * @param cfg	pointer to the compressor configuration
+ * @param cfg		pointer to the compressor configuration
+ * @param rdcu_check	set to non-zero if a check for a imagette RDCU compression
+ *			should be done; zero for imagette ICU compression
  *
- * @returns 1 if the imagette specific parameters are valid, otherwise 0
+ * @returns 0 if the imagette specific parameters are valid, otherwise invalid
  */
 
-int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg)
+int cmp_cfg_imagette_is_invalid(const struct cmp_cfg *cfg, int rdcu_check)
 {
 	int cfg_invalid = 0;
+	enum cmp_mode cmp_mode;
 
 	if (!cfg)
 		return 0;
@@ -665,35 +678,37 @@ int cmp_cfg_imagette_is_valid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (!cmp_pars_are_valid(cfg->golomb_par, cfg->spill, cfg->cmp_mode,
-				"imagette"))
-		cfg_invalid++;
-
-	if (cmp_ap_imagette_data_type_is_used(cfg->data_type)) {
-		if (!cmp_pars_are_valid(cfg->ap1_golomb_par, cfg->ap1_spill,
-					cfg->cmp_mode, "adaptive 1 imagette"))
-			cfg_invalid++;
-		if (!cmp_pars_are_valid(cfg->ap2_golomb_par, cfg->ap2_spill,
-					cfg->cmp_mode, "adaptive 2 imagette"))
-			cfg_invalid++;
+	/* The RDCU needs valid compression parameters also in RAW_MODE */
+	if (rdcu_check && cfg->cmp_mode == CMP_MODE_RAW)
+		cmp_mode = CMP_MODE_MODEL_ZERO;
+	else
+		cmp_mode = cfg->cmp_mode;
+
+	cfg_invalid += cmp_pars_are_invalid(cfg->golomb_par, cfg->spill, cmp_mode,
+					    cfg->data_type, "imagette");
+
+	/* for the RDCU the adaptive parameters have to be always valid */
+	if (rdcu_check || cmp_ap_imagette_data_type_is_used(cfg->data_type)) {
+		cfg_invalid += cmp_pars_are_invalid(cfg->ap1_golomb_par, cfg->ap1_spill,
+				cmp_mode, cfg->data_type, "adaptive 1 imagette");
+		cfg_invalid += cmp_pars_are_invalid(cfg->ap2_golomb_par, cfg->ap2_spill,
+				cmp_mode, cfg->data_type, "adaptive 2 imagette");
 	}
 
-	if (cfg_invalid)
-		return 0;
-
-	return 1;
+	return cfg_invalid;
 }
 
 
 /**
- * @brief check if the flux/center of brightness specific compression parameters are valid
+ * @brief check if the flux/center of brightness specific compression parameters
+ *	are invalid
  *
  * @param cfg	pointer to the compressor configuration
  *
- * @returns 1 if the flux/center of brightness specific parameters are valid, otherwise 0
+ * @returns 0 if the flux/center of brightness specific parameters are valid, otherwise invalid
  */
 
-int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
+int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 	int check_exp_flags = 0, check_ncob = 0, check_efx = 0, check_ecob = 0, check_var = 0;
@@ -706,8 +721,8 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 	/* flux parameter is needed for every fx_cob data_type */
-	if (!cmp_pars_are_valid(cfg->cmp_par_fx, cfg->spill_fx, cfg->cmp_mode, "flux"))
-		cfg_invalid++;
+	cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_fx, cfg->spill_fx,
+					    cfg->cmp_mode, cfg->data_type, "flux");
 
 	switch (cfg->data_type) {
 	case DATA_TYPE_S_FX:
@@ -766,39 +781,37 @@ int cmp_cfg_fx_cob_is_valid(const struct cmp_cfg *cfg)
 		break;
 	}
 
-	if (check_exp_flags && !cmp_pars_are_valid(cfg->cmp_par_exp_flags,
-			cfg->spill_exp_flags, cfg->cmp_mode, "exposure flags"))
-		cfg_invalid++;
-	if (check_ncob && !cmp_pars_are_valid(cfg->cmp_par_ncob, cfg->spill_ncob,
-			cfg->cmp_mode, "center of brightness"))
-		cfg_invalid++;
-	if (check_efx && !cmp_pars_are_valid(cfg->cmp_par_efx, cfg->spill_efx,
-			cfg->cmp_mode, "extended flux"))
-		cfg_invalid++;
-	if (check_ecob && !cmp_pars_are_valid(cfg->cmp_par_ecob, cfg->spill_ecob,
-			cfg->cmp_mode, "extended center of brightness"))
-		cfg_invalid++;
-	if (check_var && !cmp_pars_are_valid(cfg->cmp_par_fx_cob_variance,
-			cfg->spill_fx_cob_variance, cfg->cmp_mode, "flux COB varianc"))
-		cfg_invalid++;
-
-	if (cfg_invalid)
-		return 0;
-
-	return 1;
+	if (check_exp_flags)
+		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_exp_flags, cfg->spill_exp_flags,
+			cfg->cmp_mode, cfg->data_type, "exposure flags");
+	if (check_ncob)
+		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_ncob, cfg->spill_ncob,
+			cfg->cmp_mode, cfg->data_type, "center of brightness");
+	if (check_efx)
+		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_efx, cfg->spill_efx,
+			cfg->cmp_mode, cfg->data_type, "extended flux");
+	if (check_ecob)
+		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_ecob, cfg->spill_ecob,
+			cfg->cmp_mode, cfg->data_type, "extended center of brightness");
+	if (check_var)
+		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_fx_cob_variance,
+			cfg->spill_fx_cob_variance, cfg->cmp_mode, cfg->data_type, "flux COB varianc");
+
+	return cfg_invalid;
 }
 
 
 /**
- * @brief check if the auxiliary science specific compression parameters are valid
+ * @brief check if the auxiliary science specific compression parameters are invalid
  *
  * @param cfg	pointer to the compressor configuration
  *
- * @returns 1 if the auxiliary science specific parameters are valid, otherwise 0
+ * @returns 0 if the auxiliary science specific parameters are valid, otherwise
+ *	invalid
  * TODO: implemented DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND
  */
 
-int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
+int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 
@@ -810,63 +823,49 @@ int cmp_cfg_aux_is_valid(const struct cmp_cfg *cfg)
 		cfg_invalid++;
 	}
 
-	if (!cmp_pars_are_valid(cfg->cmp_par_mean, cfg->spill_mean,
-				cfg->cmp_mode, "mean"))
-		cfg_invalid++;
-	if (!cmp_pars_are_valid(cfg->cmp_par_variance, cfg->spill_variance,
-				cfg->cmp_mode, "variance"))
-		cfg_invalid++;
+	cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_mean, cfg->spill_mean,
+					    cfg->cmp_mode, cfg->data_type, "mean");
+	cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_variance, cfg->spill_variance,
+					    cfg->cmp_mode, cfg->data_type, "variance");
+
 	/* if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET) */
 	if (cfg->data_type != DATA_TYPE_OFFSET)
-		if (!cmp_pars_are_valid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
-					cfg->cmp_mode, "outlier pixls num"))
-			cfg_invalid++;
-
-	if (cfg_invalid)
-		return 0;
+		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+						    cfg->cmp_mode, cfg->data_type, "outlier pixls num");
 
-	return 1;
+	return cfg_invalid;
 }
 
 
 /**
- * @brief check if a compression configuration is valid
+ * @brief check if a compression configuration is invalid
  *
  * @param cfg	pointer to the compressor configuration
  *
- * @returns 1 if the compression configuration is valid, otherwise 0
+ * @returns 0 if the compression configuration is valid, otherwise invalid
  */
 
-int cmp_cfg_is_valid(const struct cmp_cfg *cfg)
+int cmp_cfg_is_invalid(const struct cmp_cfg *cfg)
 {
 	int cfg_invalid = 0;
 
 	if (!cfg)
 		return 0;
 
-	if (!cmp_cfg_icu_gen_par_is_valid(cfg))
-		cfg_invalid++;
+	cfg_invalid += cmp_cfg_icu_gen_par_is_invalid(cfg);
 
-	if (!cmp_cfg_icu_buffers_is_valid(cfg))
-		cfg_invalid++;
+	cfg_invalid += cmp_cfg_icu_buffers_is_invalid(cfg);
 
-	if (cmp_imagette_data_type_is_used(cfg->data_type)) {
-		if (!cmp_cfg_imagette_is_valid(cfg))
-			cfg_invalid++;
-	} else if (cmp_fx_cob_data_type_is_used(cfg->data_type)) {
-		if (!cmp_cfg_fx_cob_is_valid(cfg))
-			cfg_invalid++;
-	} else if (cmp_aux_data_type_is_used(cfg->data_type)) {
-		if (!cmp_cfg_aux_is_valid(cfg))
-			cfg_invalid++;
-	} else {
+	if (cmp_imagette_data_type_is_used(cfg->data_type))
+		cfg_invalid += cmp_cfg_imagette_is_invalid(cfg, ICU_CHECK);
+	else if (cmp_fx_cob_data_type_is_used(cfg->data_type))
+		cfg_invalid += cmp_cfg_fx_cob_is_invalid(cfg);
+	else if (cmp_aux_data_type_is_used(cfg->data_type))
+		cfg_invalid += cmp_cfg_aux_is_invalid(cfg);
+	else
 		cfg_invalid++;
-	}
-
-	if (cfg_invalid)
-		return 0;
 
-	return 1;
+	return cfg_invalid;
 }
 
 
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index 3eae4be..65ab545 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -1,6 +1,5 @@
-#include "cmp_support.h"
-#include <string.h>
 #include <stdlib.h>
+
 #if defined __has_include
 #  if __has_include(<time.h>)
 #    include <time.h>
@@ -436,8 +435,8 @@ void test_cmp_cfg_icu_imagette(void)
 
 	/* lowest values 1d/model mode */
 	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 0, CMP_LOSSLESS);
-	cmp_par = MIN_ICU_GOLOMB_PAR;
-	spillover_par = MIN_ICU_SPILL;
+	cmp_par = MIN_IMA_GOLOMB_PAR;
+	spillover_par = MIN_IMA_SPILL;
 	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
 	TEST_ASSERT_FALSE(error);
 	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 1);
@@ -445,12 +444,12 @@ void test_cmp_cfg_icu_imagette(void)
 
 	/* highest values 1d/model mode */
 	cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_IMAGETTE, CMP_MODE_DIFF_MULTI, 16, CMP_LOSSLESS);
-	cmp_par = MAX_ICU_GOLOMB_PAR;
-	spillover_par = cmp_icu_max_spill(cmp_par);
+	cmp_par = MAX_IMA_GOLOMB_PAR;
+	spillover_par = cmp_ima_max_spill(cmp_par);
 	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
 	TEST_ASSERT_FALSE(error);
-	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 0xFFFF);
-	TEST_ASSERT_EQUAL_INT(cfg.spill, 1048545);
+	TEST_ASSERT_EQUAL_INT(cfg.golomb_par, MAX_IMA_GOLOMB_PAR);
+	TEST_ASSERT_EQUAL_INT(cfg.spill, cmp_ima_max_spill(MAX_IMA_GOLOMB_PAR));
 
 	/* wrong data type  test */
 	for (data_type = 0; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) {
@@ -461,8 +460,8 @@ void test_cmp_cfg_icu_imagette(void)
 		    data_type == DATA_TYPE_F_CAM_IMAGETTE) {
 			TEST_ASSERT_FALSE(error);
 			TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
-			TEST_ASSERT_EQUAL_INT(cfg.golomb_par, 0xFFFF);
-			TEST_ASSERT_EQUAL_INT(cfg.spill, 1048545);
+			TEST_ASSERT_EQUAL_INT(cfg.golomb_par, MAX_IMA_GOLOMB_PAR);
+			TEST_ASSERT_EQUAL_INT(cfg.spill, cmp_ima_max_spill(MAX_IMA_GOLOMB_PAR));
 		} else {
 			TEST_ASSERT_TRUE(error);
 		}
@@ -472,8 +471,8 @@ void test_cmp_cfg_icu_imagette(void)
 
 	/* cmp_par to big */
 	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_MULTI, 16, CMP_LOSSLESS);
-	cmp_par = MAX_ICU_GOLOMB_PAR + 1;
-	spillover_par = MIN_ICU_SPILL;
+	cmp_par = MAX_IMA_GOLOMB_PAR + 1;
+	spillover_par = MIN_IMA_SPILL;
 	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
 	TEST_ASSERT_TRUE(error);
 	/* ignore in RAW MODE */
@@ -483,8 +482,8 @@ void test_cmp_cfg_icu_imagette(void)
 
 	/* cmp_par to small */
 	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_MULTI, 16, CMP_LOSSLESS);
-	cmp_par = MIN_ICU_GOLOMB_PAR - 1;
-	spillover_par = MIN_ICU_SPILL;
+	cmp_par = MIN_IMA_GOLOMB_PAR - 1;
+	spillover_par = MIN_IMA_SPILL;
 	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
 	TEST_ASSERT_TRUE(error);
 	/* ignore in RAW MODE */
@@ -494,8 +493,8 @@ void test_cmp_cfg_icu_imagette(void)
 
 	/* spillover_par to big */
 	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_MULTI, 16, CMP_LOSSLESS);
-	cmp_par = MIN_ICU_GOLOMB_PAR;
-	spillover_par = cmp_icu_max_spill(cmp_par)+1;
+	cmp_par = MIN_IMA_GOLOMB_PAR;
+	spillover_par = cmp_ima_max_spill(cmp_par)+1;
 	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
 	TEST_ASSERT_TRUE(error);
 	/* ignore in RAW MODE */
@@ -505,8 +504,8 @@ void test_cmp_cfg_icu_imagette(void)
 
 	/* spillover_par to small */
 	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS);
-	cmp_par = MAX_ICU_GOLOMB_PAR;
-	spillover_par = MIN_ICU_SPILL -1 ;
+	cmp_par = MAX_IMA_GOLOMB_PAR;
+	spillover_par = MIN_IMA_SPILL -1 ;
 	error = cmp_cfg_icu_imagette(&cfg, cmp_par, spillover_par);
 	TEST_ASSERT_TRUE(error);
 	/* ignore in RAW MODE */
diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c
index cb00bb0..244bbe8 100644
--- a/test/cmp_icu/test_decmp.c
+++ b/test/cmp_icu/test_decmp.c
@@ -49,9 +49,8 @@ size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cf
 	if (cmp_size_bits < 0)
 		return 0;
 
-	/* XXX overwrite the size of the compression entity with the size of the
-	 * actual size of the compressed data */
-	/* not all allocated memory is normally needed */
+	/* XXX overwrite the size of the compression entity with the size of the actual
+	 * size of the compressed data; not all allocated memory is normally used */
 	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW,
 			   cmp_bit_to_4byte(cmp_size_bits));
 
@@ -161,9 +160,28 @@ void test_re_map_to_pos(void)
 }
 
 
+void test_rice_decoder(void)
+{
+	int cw_len;
+	uint32_t code_word;
+	unsigned int m = ~0;/* we don't need this value */
+	unsigned int log2_m;
+	unsigned int decoded_cw;
+
+	/* test log_2 to big */
+	code_word = 0xE0000000;
+	log2_m = 33;
+	cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw);
+	TEST_ASSERT_EQUAL(0, cw_len);
+	log2_m = UINT_MAX;
+	cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw);
+	TEST_ASSERT_EQUAL(0, cw_len);
+}
+
+
 void test_decode_normal(void)
 {
-	uint32_t decoded_value;
+	uint32_t decoded_value = ~0;
 	int stream_pos, sample;
 	 /* compressed data from 0 to 6; */
 	uint32_t cmp_data[] = {0x5BBDF7E0};
@@ -176,7 +194,6 @@ void test_decode_normal(void)
 	setup.encoder_par2 = ilog_2(setup.encoder_par1);
 	setup.bitstream_adr = cmp_data;
 	setup.max_stream_len = 32;
-	setup.max_cw_len = 16;
 
 	stream_pos = 0;
 	for (sample = 0; sample < 7; sample++) {
@@ -190,7 +207,7 @@ void test_decode_normal(void)
 
 void test_decode_zero(void)
 {
-	uint32_t decoded_value;
+	uint32_t decoded_value = ~0;
 	int stream_pos;
 	uint32_t cmp_data[] = {0x88449FE0};
 	struct decoder_setup setup = {0};
@@ -221,7 +238,7 @@ void test_decode_zero(void)
 
 void test_decode_multi(void)
 {
-	uint32_t decoded_value;
+	uint32_t decoded_value = ~0;
 	int stream_pos;
 	uint32_t cmp_data[] = {0x16B66DF8, 0x84360000};
 	struct decoder_setup setup = {0};
@@ -297,7 +314,6 @@ void test_decompress_imagette_model(void)
 
 
 
-#define CMP_PAR_UNUSED 0 /*TODO: remove this*/
 #define DATA_SAMPLES 5
 void test_cmp_decmp_s_fx_diff(void)
 {
@@ -471,8 +487,8 @@ void test_imagette_random(void)
 					    NULL, compressed_data_len_samples);
 	TEST_ASSERT_TRUE(cmp_data_size);
 
-	uint32_t golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
-	uint32_t max_spill = cmp_icu_max_spill(golomb_par);
+	uint32_t golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
+	uint32_t max_spill = cmp_ima_max_spill(golomb_par);
 	TEST_ASSERT(max_spill > 1);
 	uint32_t spill = my_random(2, max_spill);
 
@@ -663,9 +679,9 @@ void test_random_compression_decompression(void)
 		/* cfg.round = my_random(0,3); /1* XXX *1/ */
 		cfg.round = 0;
 
-		cfg.golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
-		cfg.ap1_golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
-		cfg.ap2_golomb_par = my_random(MIN_RDCU_GOLOMB_PAR, MAX_RDCU_GOLOMB_PAR);
+		cfg.golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
+		cfg.ap1_golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
+		cfg.ap2_golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
 		cfg.cmp_par_exp_flags = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
 		cfg.cmp_par_fx = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
 		cfg.cmp_par_ncob = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
@@ -676,9 +692,9 @@ void test_random_compression_decompression(void)
 		cfg.cmp_par_variance = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
 		cfg.cmp_par_pixels_error = my_random(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
 
-		cfg.spill = my_random(MIN_RDCU_SPILL, cmp_icu_max_spill(cfg.golomb_par));
-		cfg.ap1_spill = my_random(MIN_RDCU_SPILL, cmp_icu_max_spill(cfg.ap1_golomb_par));
-		cfg.ap2_spill = my_random(MIN_RDCU_SPILL, cmp_icu_max_spill(cfg.ap2_golomb_par));
+		cfg.spill = my_random(MIN_IMA_SPILL, cmp_ima_max_spill(cfg.golomb_par));
+		cfg.ap1_spill = my_random(MIN_IMA_SPILL, cmp_ima_max_spill(cfg.ap1_golomb_par));
+		cfg.ap2_spill = my_random(MIN_IMA_SPILL, cmp_ima_max_spill(cfg.ap2_golomb_par));
 		if (!rdcu_supported_data_type_is_used(cfg.data_type)) {
 			cfg.spill_exp_flags = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_exp_flags));
 			cfg.spill_fx = my_random(MIN_ICU_SPILL, cmp_icu_max_spill(cfg.cmp_par_fx));
@@ -734,3 +750,9 @@ void test_random_compression_decompression(void)
 
 	}
 }
+
+void test_decompression_error_cases(void)
+{
+	/* error cases model decompression without a model Buffer */
+	/* error cases wrong cmp parameter; model value; usw */
+}
-- 
GitLab


From 67619fa739c5eac69c30cfd65e66814117650f8f Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 26 Sep 2022 11:55:22 +0200
Subject: [PATCH 37/46] some code formatting

---
 lib/cmp_data_types.c |  3 ++-
 lib/cmp_io.c         | 10 +++++-----
 lib/decmp.c          |  3 +--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index ee0131f..ed7d5e6 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -99,7 +99,8 @@ struct cmp_max_used_bits cmp_get_max_used_bits(void)
  * @returns version of the max used bits registry
  */
 
-uint8_t cmp_get_max_used_bits_version(void) {
+uint8_t cmp_get_max_used_bits_version(void)
+{
 	return max_used_bits.version;
 }
 
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index be0f8ed..d8772fd 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -414,7 +414,7 @@ enum cmp_data_type string2data_type(const char *data_type_str)
 		if (isalpha(data_type_str[0])) {  /* check if mode is given as text */
 			size_t j;
 
-			for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
+			for (j = 0; j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
 				if (!strcmp(data_type_str, data_type_string_table[j].str)) {
 					data_type = data_type_string_table[j].data_type;
 					break;
@@ -447,7 +447,7 @@ const char *data_type2string(enum cmp_data_type data_type)
 	size_t j;
 	const char *string = "DATA_TYPE_UNKNOWN";
 
-	for (j = 0;  j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
+	for (j = 0; j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) {
 		if (data_type == data_type_string_table[j].data_type) {
 			string = data_type_string_table[j].str;
 			break;
@@ -472,7 +472,7 @@ int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
 {
 	size_t j;
 	static const struct {
-		uint32_t  cmp_mode;
+		uint32_t cmp_mode;
 		const char *str;
 	} conversion[] = {
 		{CMP_MODE_RAW, "MODE_RAW"},
@@ -493,7 +493,7 @@ int cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode)
 		return -1;
 
 	if (isalpha(cmp_mode_str[0])) {  /* check if mode is given as text */
-		for (j = 0;  j < sizeof(conversion) / sizeof(conversion[0]);  ++j) {
+		for (j = 0; j < sizeof(conversion) / sizeof(conversion[0]); ++j) {
 			if (!strcmp(cmp_mode_str, conversion[j].str)) {
 				*cmp_mode = conversion[j].cmp_mode;
 				return 0;
@@ -825,7 +825,7 @@ int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en)
 
 
 /**
- * @brief  parse a file containing a decompression information
+ * @brief parse a file containing a decompression information
  * @note internal use only!
  *
  * @param fp	FILE pointer
diff --git a/lib/decmp.c b/lib/decmp.c
index da75d50..c266e64 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -148,8 +148,7 @@ static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m,
  */
 
 static int golomb_decoder(unsigned int code_word, unsigned int m,
-				   unsigned int log2_m, unsigned int
-				   *decoded_cw)
+			  unsigned int log2_m, unsigned int *decoded_cw)
 {
 	unsigned int q; /* quotient code */
 	unsigned int r1; /* remainder code group 1 */
-- 
GitLab


From 7ee4798b5700e7696c9e51df6c06a8bfb9e8e322 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Mon, 26 Sep 2022 11:59:12 +0200
Subject: [PATCH 38/46] Add compression decompression test

---
 test/cmp_icu/meson.build      |  18 +-
 test/cmp_icu/test_cmp_decmp.c | 614 ++++++++++++++++++++++++++++++++++
 test/meson.build              |   1 +
 3 files changed, 631 insertions(+), 2 deletions(-)
 create mode 100644 test/cmp_icu/test_cmp_decmp.c

diff --git a/test/cmp_icu/meson.build b/test/cmp_icu/meson.build
index 405d376..7c9b356 100644
--- a/test/cmp_icu/meson.build
+++ b/test/cmp_icu/meson.build
@@ -12,10 +12,24 @@ test_cmp_icu = executable('test_cmp_icu',
 test('cmp_icu Unit Tests', test_cmp_icu)
 
 
+test_case = files('test_cmp_decmp.c')
+test_runner = test_runner_generator.process(test_case)
+
+test_cmp_decmp = executable('test_cmp_decmp',
+   test_case, test_runner,
+   include_directories : incdir,
+   link_with : cmp_lib,
+   dependencies : unity_dep,
+   build_by_default : false
+)
+
+test('Compression Decompression Unit Tests', test_cmp_decmp)
+
+
 test_case = files('test_decmp.c')
 test_runner = test_runner_generator.process(test_case)
 
-test_cmp_decomp = executable('test_cmp_decomp',
+test_decmp = executable('test_decmp',
    test_case, test_runner,
    include_directories : incdir,
    link_with : cmp_lib,
@@ -23,4 +37,4 @@ test_cmp_decomp = executable('test_cmp_decomp',
    build_by_default : false
 )
 
-test('Compression Decompression Unit Tests', test_cmp_decomp)
+test('Decompression Unit Tests', test_decmp)
diff --git a/test/cmp_icu/test_cmp_decmp.c b/test/cmp_icu/test_cmp_decmp.c
new file mode 100644
index 0000000..e961ffc
--- /dev/null
+++ b/test/cmp_icu/test_cmp_decmp.c
@@ -0,0 +1,614 @@
+/**
+ * @file   test_cmp_decmp.c
+ * @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
+ * @date   2022
+ *
+ * @copyright GPLv2
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * @brief random compression decompression test
+ * @detail We generate random data and compress them with random parameters.
+ *	After that we put the data in a compression entity. We decompress the
+ *	compression entity and compare the decompressed data with the original
+ *	data.
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <unity.h>
+
+#include <cmp_icu.h>
+#include <decmp.h>
+#include <cmp_data_types.h>
+
+#if defined __has_include
+#  if __has_include(<time.h>)
+#    include <time.h>
+#    include <unistd.h>
+#    define HAS_TIME_H 1
+#  endif
+#endif
+
+#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
+#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
+
+#define set_n_bits(n)  (~(~0UL << (n)))
+
+
+/**
+ * @brief  Seeds the pseudo-random number generator used by rand()
+ */
+
+void setUp(void)
+{
+	unsigned int seed;
+	static int n;
+
+#if HAS_TIME_H
+	seed = time(NULL) * getpid();
+#else
+	seed = 1;
+#endif
+
+	if (!n) {
+		n = 1;
+		srand(seed);
+		printf("seed: %u\n", seed);
+	}
+}
+
+
+/**
+ * @brief generate a uint32_t random number
+ *
+ * @return a "random" uint32_t value
+ * @see https://stackoverflow.com/a/33021408
+ */
+
+uint32_t rand32(void)
+{
+	int i;
+	uint32_t r = 0;
+
+	for (i = 0; i < 32; i += RAND_MAX_WIDTH) {
+		r <<= RAND_MAX_WIDTH;
+		r ^= (unsigned int) rand();
+	}
+	return r;
+}
+
+
+/**
+ * @brief generate a random number in a range
+ *
+ * @param min minimum value (inclusive)
+ * @param max maximum value (inclusive)
+ *
+ * @returns "random" numbers in the range [min, max]
+ *
+ * @see https://c-faq.com/lib/randrange.html
+ */
+
+uint32_t random_between(unsigned int min, unsigned int max)
+{
+	TEST_ASSERT(min < max);
+	if (max-min < RAND_MAX)
+		return min + rand() / (RAND_MAX / (max - min + 1ULL) + 1);
+	else
+		return min + rand32() / (UINT32_MAX / (max - min + 1ULL) + 1);
+}
+
+
+static void gen_ima_data(uint16_t *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i] = random_between(0, set_n_bits(max_used_bits.nc_imagette));
+	}
+}
+
+
+static void gen_offset_data(struct nc_offset *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].mean = random_between(0, set_n_bits(max_used_bits.nc_offset_mean));
+		data[i].variance = random_between(0, set_n_bits(max_used_bits.nc_offset_variance));
+	}
+}
+
+
+static void gen_background_data(struct nc_background *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].mean = random_between(0, set_n_bits(max_used_bits.nc_background_mean));
+		data[i].variance = random_between(0, set_n_bits(max_used_bits.nc_background_variance));
+		data[i].outlier_pixels = random_between(0, set_n_bits(max_used_bits.nc_background_outlier_pixels));
+	}
+}
+
+
+static void gen_smearing_data(struct smearing *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].mean = random_between(0, set_n_bits(max_used_bits.smearing_mean));
+		data[i].variance_mean = random_between(0, set_n_bits(max_used_bits.smearing_variance_mean));
+		data[i].outlier_pixels = random_between(0, set_n_bits(max_used_bits.smearing_outlier_pixels));
+	}
+}
+
+
+static void gen_s_fx_data(struct s_fx *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
+	}
+}
+
+
+static void gen_s_fx_efx_data(struct s_fx_efx *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
+		data[i].efx = random_between(0, set_n_bits(max_used_bits.s_efx));
+	}
+}
+
+
+static void gen_s_fx_ncob_data(struct s_fx_ncob *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
+		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.s_ncob));
+		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.s_ncob));
+	}
+}
+
+
+static void gen_s_fx_efx_ncob_ecob_data(struct s_fx_efx_ncob_ecob *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.s_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.s_fx));
+		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.s_ncob));
+		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.s_ncob));
+		data[i].efx = random_between(0, set_n_bits(max_used_bits.s_efx));
+		data[i].ecob_x = random_between(0, set_n_bits(max_used_bits.s_ecob));
+		data[i].ecob_y = random_between(0, set_n_bits(max_used_bits.s_ecob));
+	}
+}
+
+
+static void gen_f_fx_data(struct f_fx *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
+	}
+}
+
+
+static void gen_f_fx_efx_data(struct f_fx_efx *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
+		data[i].efx = random_between(0, set_n_bits(max_used_bits.f_efx));
+	}
+}
+
+
+static void gen_f_fx_ncob_data(struct f_fx_ncob *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
+		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.f_ncob));
+		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.f_ncob));
+	}
+}
+
+
+static void gen_f_fx_efx_ncob_ecob_data(struct f_fx_efx_ncob_ecob *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.f_fx));
+		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.f_ncob));
+		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.f_ncob));
+		data[i].efx = random_between(0, set_n_bits(max_used_bits.f_efx));
+		data[i].ecob_x = random_between(0, set_n_bits(max_used_bits.f_ecob));
+		data[i].ecob_y = random_between(0, set_n_bits(max_used_bits.f_ecob));
+	}
+}
+
+
+static void gen_l_fx_data(struct l_fx *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
+		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
+	}
+}
+
+
+static void gen_l_fx_efx_data(struct l_fx_efx *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
+		data[i].efx = random_between(0, set_n_bits(max_used_bits.l_efx));
+		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
+	}
+}
+
+
+static void gen_l_fx_ncob_data(struct l_fx_ncob *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
+		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.l_ncob));
+		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.l_ncob));
+		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
+		data[i].cob_x_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
+		data[i].cob_y_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
+	}
+}
+
+
+static void gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint32_t samples)
+{
+	uint32_t i;
+	struct cmp_max_used_bits max_used_bits = cmp_get_max_used_bits();
+
+	for (i = 0; i < samples; i++) {
+		data[i].exp_flags = random_between(0, set_n_bits(max_used_bits.l_exp_flags));
+		data[i].fx = random_between(0, set_n_bits(max_used_bits.l_fx));
+		data[i].ncob_x = random_between(0, set_n_bits(max_used_bits.l_ncob));
+		data[i].ncob_y = random_between(0, set_n_bits(max_used_bits.l_ncob));
+		data[i].efx = random_between(0, set_n_bits(max_used_bits.l_efx));
+		data[i].ecob_x = random_between(0, set_n_bits(max_used_bits.l_ecob));
+		data[i].ecob_y = random_between(0, set_n_bits(max_used_bits.l_ecob));
+		data[i].fx_variance = random_between(0, set_n_bits(max_used_bits.l_fx_variance));
+		data[i].cob_x_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
+		data[i].cob_y_variance = random_between(0, set_n_bits(max_used_bits.l_cob_variance));
+	}
+}
+
+
+/**
+ * @brief generate random test data
+ *
+ * @param samples	number of random test samples
+ * @param data_type	compression data type of the test data
+ *
+ * @returns a pointer to the generated random test data
+ */
+
+void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type)
+{
+	size_t data_size = cmp_cal_size_of_data(samples, data_type);
+	void *data = malloc(data_size);
+	void *data_cpy = data;
+	uint8_t *p = data;
+
+	TEST_ASSERT_NOT_EQUAL_INT(data_size, 0);
+	TEST_ASSERT(data_size < (CMP_ENTITY_MAX_SIZE - NON_IMAGETTE_HEADER_SIZE));
+	TEST_ASSERT_NOT_NULL(data);
+
+	if (!rdcu_supported_data_type_is_used(data_type)) {
+		int i;
+		TEST_ASSERT(data_size > MULTI_ENTRY_HDR_SIZE);
+		for (i = 0; i < MULTI_ENTRY_HDR_SIZE; ++i) {
+			*p++ = random_between(0, UINT8_MAX);
+		}
+		data = p;
+	}
+
+	switch (data_type) {
+	case DATA_TYPE_IMAGETTE:
+	case DATA_TYPE_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_SAT_IMAGETTE:
+	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
+		gen_ima_data(data, samples);
+		break;
+	case DATA_TYPE_OFFSET:
+		gen_offset_data(data, samples);
+		break;
+	case DATA_TYPE_BACKGROUND:
+		gen_background_data(data, samples);
+		break;
+	case DATA_TYPE_SMEARING:
+		gen_smearing_data(data, samples);
+		break;
+	case DATA_TYPE_S_FX:
+		gen_s_fx_data(data, samples);
+		break;
+	case DATA_TYPE_S_FX_EFX:
+		gen_s_fx_efx_data(data, samples);
+		break;
+	case DATA_TYPE_S_FX_NCOB:
+		gen_s_fx_ncob_data(data, samples);
+		break;
+	case DATA_TYPE_S_FX_EFX_NCOB_ECOB:
+		gen_s_fx_efx_ncob_ecob_data(data, samples);
+		break;
+	case DATA_TYPE_L_FX:
+		gen_l_fx_data(data, samples);
+		break;
+	case DATA_TYPE_L_FX_EFX:
+		gen_l_fx_efx_data(data, samples);
+		break;
+	case DATA_TYPE_L_FX_NCOB:
+		gen_l_fx_ncob_data(data, samples);
+		break;
+	case DATA_TYPE_L_FX_EFX_NCOB_ECOB:
+		gen_l_fx_efx_ncob_ecob_data(data, samples);
+		break;
+	case DATA_TYPE_F_FX:
+		gen_f_fx_data(data, samples);
+		break;
+	case DATA_TYPE_F_FX_EFX:
+		gen_f_fx_efx_data(data, samples);
+		break;
+	case DATA_TYPE_F_FX_NCOB:
+		gen_f_fx_ncob_data(data, samples);
+		break;
+	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
+		gen_f_fx_efx_ncob_ecob_data(data, samples);
+		break;
+	case DATA_TYPE_F_CAM_OFFSET: /* TODO: implement this */
+	case DATA_TYPE_F_CAM_BACKGROUND: /* TODO: implement this */
+	default:
+		TEST_FAIL();
+	}
+
+	return data_cpy;
+}
+
+
+/**
+ * @brief generate random compression configuration
+ *
+ * @param cfg	pointer to a compression configuration
+ *
+ */
+
+void generate_random_cmp_par(struct cmp_cfg *cfg)
+{
+	cfg->golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
+	cfg->ap1_golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
+	cfg->ap2_golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
+
+	cfg->cmp_par_exp_flags = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_fx = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_ncob = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_efx = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_ecob = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_fx_cob_variance = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_mean = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_variance = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+	cfg->cmp_par_pixels_error = random_between(MIN_ICU_GOLOMB_PAR, MAX_ICU_GOLOMB_PAR);
+
+
+	cfg->spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->golomb_par));
+	cfg->ap1_spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap1_golomb_par));
+	cfg->ap2_spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap2_golomb_par));
+
+	cfg->spill_exp_flags = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_exp_flags));
+	cfg->spill_fx = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx));
+	cfg->spill_ncob = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_ncob));
+	cfg->spill_efx = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_efx));
+	cfg->spill_ecob = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_ecob));
+	cfg->spill_fx_cob_variance = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx_cob_variance));
+	cfg->spill_mean = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_mean));
+	cfg->spill_variance = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_variance));
+	cfg->spill_pixels_error = random_between(MIN_ICU_SPILL, cmp_icu_max_spill(cfg->cmp_par_pixels_error));
+#if 0
+	if (cfg->cmp_mode == CMP_MODE_STUFF) {
+		/* cfg->golomb_par = random_between(16, MAX_STUFF_CMP_PAR); */
+		cfg->golomb_par = 16;
+		cfg->ap1_golomb_par = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->ap2_golomb_par = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_exp_flags = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_fx = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_ncob = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_efx = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_ecob = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_fx_cob_variance = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_mean = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_variance = random_between(0, MAX_STUFF_CMP_PAR);
+		cfg->cmp_par_pixels_error = random_between(0, MAX_STUFF_CMP_PAR);
+		return;
+	}
+#endif
+}
+
+
+/**
+ * @brief compress the given configuration and decompress it afterwards; finally
+ *	compare the results
+ *
+ * @param cfg	pointer to a compression configuration
+ */
+
+void compression_decompression(struct cmp_cfg *cfg)
+{
+	int cmp_size_bits, s, error;
+	int data_size, cmp_data_size;
+	struct cmp_entity *ent;
+	void *decompressed_data;
+	static void *model_of_data;
+	void *updated_model = NULL;
+
+	TEST_ASSERT_NOT_NULL(cfg);
+
+	TEST_ASSERT_NULL(cfg->icu_output_buf);
+
+	data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type);
+
+	/* create a compression entity */
+	cmp_data_size = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type);
+	cmp_data_size &= ~0x3; /* the size of the compressed data should be a multiple of 4 */
+	TEST_ASSERT_NOT_EQUAL_INT(0, cmp_data_size);
+
+	s = cmp_ent_create(NULL, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size);
+	TEST_ASSERT_NOT_EQUAL_INT(0, s);
+	ent = malloc(s); TEST_ASSERT_TRUE(ent);
+	s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size);
+	TEST_ASSERT_NOT_EQUAL_INT(0, s);
+
+	/* we put the coompressed data direct into the compression entity */
+	cfg->icu_output_buf = cmp_ent_get_data_buf(ent);
+	TEST_ASSERT_NOT_NULL(cfg->icu_output_buf);
+
+	/* now compress the data */
+	cmp_size_bits = icu_compress_data(cfg);
+	TEST_ASSERT(cmp_size_bits > 0);
+
+	/* put the compression parameters in the entity header */
+	error = cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits);
+	TEST_ASSERT_FALSE(error);
+
+	/* allocate the buffers for decompression */
+	TEST_ASSERT_NOT_EQUAL_INT(0, data_size);
+	s = decompress_cmp_entiy(ent, model_of_data, NULL, NULL);
+	decompressed_data = malloc(s); TEST_ASSERT_NOT_NULL(decompressed_data);
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		updated_model = malloc(data_size);
+		TEST_ASSERT_NOT_NULL(updated_model);
+	}
+
+	/* now we try to decompress the data */
+	s = decompress_cmp_entiy(ent, model_of_data, updated_model, decompressed_data);
+	TEST_ASSERT_EQUAL_INT(data_size, s);
+	TEST_ASSERT_FALSE(memcmp(decompressed_data, cfg->input_buf, data_size));
+
+	if (model_mode_is_used(cfg->cmp_mode)) {
+		TEST_ASSERT_NOT_NULL(updated_model);
+		TEST_ASSERT_NOT_NULL(model_of_data);
+		TEST_ASSERT_FALSE(memcmp(updated_model, cfg->icu_new_model_buf, data_size));
+		memcpy(model_of_data, updated_model, data_size);
+	} else { /* non-model mode */
+		/* reset model */
+		free(model_of_data);
+		model_of_data = malloc(data_size);
+		memcpy(model_of_data, decompressed_data, data_size);
+	}
+
+	cfg->icu_output_buf = NULL;
+	free(ent);
+	free(decompressed_data);
+	free(updated_model);
+}
+
+
+#define CMP_BUFFER_FAKTOR 3 /* compression data buffer size / data to compress buffer size */
+
+/**
+ * @brief random compression decompression test
+ * @detail We generate random data and compress them with random parameters.
+ *	After that we put the data in a compression entity. We decompress the
+ *	compression entity and compare the decompressed data with the original
+ *	data.
+ * @test icu_compress_data
+ * @test decompress_cmp_entiy
+ */
+
+void test_random_compression_decompression(void)
+{
+	enum cmp_data_type data_type;
+	enum cmp_mode cmp_mode;
+	struct cmp_cfg cfg;
+	int cmp_buffer_size;
+
+	/* TODO: extend test for DATA_TYPE_F_CAM_BACKGROUND, DATA_TYPE_F_CAM_OFFSET  */
+	for (data_type = 1; data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; data_type++) {
+		/* printf("%s\n", data_type2string(data_type)); */
+		/* generate random data*/
+		uint32_t samples = random_between(1, 430179/CMP_BUFFER_FAKTOR);
+		uint32_t model_value = random_between(0, MAX_MODEL_VALUE);
+		void *data_to_compress1 = generate_random_test_data(samples, data_type);
+		void *data_to_compress2 = generate_random_test_data(samples, data_type);
+		void *updated_model = calloc(1, cmp_cal_size_of_data(samples, data_type));
+		/* for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_STUFF; cmp_mode++) { */
+		for (cmp_mode = CMP_MODE_RAW; cmp_mode < CMP_MODE_STUFF; cmp_mode++) {
+			/* printf("cmp_mode: %i\n", cmp_mode); */
+			cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value,
+						 CMP_LOSSLESS);
+			TEST_ASSERT_NOT_EQUAL_INT(cfg.data_type, DATA_TYPE_UNKNOWN);
+
+			generate_random_cmp_par(&cfg);
+
+			if (!model_mode_is_used(cmp_mode))
+				cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data_to_compress1,
+					samples, NULL, NULL, NULL, samples*CMP_BUFFER_FAKTOR);
+			else
+				cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data_to_compress2,
+					samples, data_to_compress1, updated_model, NULL, samples*CMP_BUFFER_FAKTOR);
+
+			TEST_ASSERT_EQUAL_INT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*samples, data_type));
+
+			compression_decompression(&cfg);
+		}
+		free(data_to_compress1);
+		free(data_to_compress2);
+		free(updated_model);
+	}
+}
diff --git a/test/meson.build b/test/meson.build
index 145cdb8..11ddac0 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -38,3 +38,4 @@ unity_dep = dependency('unity', fallback : ['unity', 'unity_dep'])
 
 subdir('cmp_icu')
 subdir('cmp_data_types')
+subdir('cmp_entity')
-- 
GitLab


From 7690fa65a4c6cc77db7d218d78ba9dfe84e9029e Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 27 Sep 2022 11:25:24 +0200
Subject: [PATCH 39/46] now the adaptive compression size (ap1_cmp_size,
 ap2_cmp_size) is calculate when the --rdcu_par option is used

---
 cmp_tool.c                                 | 74 +++++++++++++---------
 test/cmp_tool/cmp_tool_integration_test.py |  4 +-
 2 files changed, 45 insertions(+), 33 deletions(-)

diff --git a/cmp_tool.c b/cmp_tool.c
index 86302b3..3572c23 100644
--- a/cmp_tool.c
+++ b/cmp_tool.c
@@ -90,7 +90,7 @@ static const char *output_prefix = DEFAULT_OUTPUT_PREFIX;
 
 /* if non zero additional RDCU parameters are included in the compression
  * configuration and decompression information files */
-static int print_rdcu_cfg;
+static int add_rdcu_pars;
 
 /* if non zero generate RDCU setup packets */
 static int rdcu_pkt_mode;
@@ -160,7 +160,7 @@ int main(int argc, char **argv)
 				  NULL)) != -1) {
 		switch (opt) {
 		case 'a': /* --rdcu_par */
-			print_rdcu_cfg = 1;
+			add_rdcu_pars = 1;
 			break;
 		case 'c':
 			cmp_operation = 1;
@@ -271,7 +271,7 @@ int main(int argc, char **argv)
 				  CMP_DEF_IMA_MODEL_GOLOMB_PAR, CMP_DEF_IMA_MODEL_SPILL_PAR,
 				  CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP1_SPILL_PAR,
 				  CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP2_SPILL_PAR);
-		print_cfg(&cfg, print_rdcu_cfg);
+		print_cfg(&cfg, add_rdcu_pars);
 		exit(EXIT_SUCCESS);
 	}
 
@@ -285,7 +285,7 @@ int main(int argc, char **argv)
 				  CMP_DEF_IMA_DIFF_GOLOMB_PAR, CMP_DEF_IMA_DIFF_SPILL_PAR,
 				  CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR, CMP_DEF_IMA_DIFF_AP1_SPILL_PAR,
 				   CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR, CMP_DEF_IMA_DIFF_AP2_SPILL_PAR);
-		print_cfg(&cfg, print_rdcu_cfg);
+		print_cfg(&cfg, add_rdcu_pars);
 		exit(EXIT_SUCCESS);
 	}
 
@@ -369,7 +369,7 @@ int main(int argc, char **argv)
 
 			ent_size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW,
 						  cmp_size_byte);
-			if (ent_size <= 0)
+			if (!ent_size)
 				goto fail;
 			decomp_entity = malloc(ent_size);
 			if (!decomp_entity) {
@@ -378,7 +378,7 @@ int main(int argc, char **argv)
 			}
 			ent_size = cmp_ent_create(decomp_entity, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW,
 						  cmp_size_byte);
-			if (ent_size <= 0)
+			if (!ent_size)
 				goto fail;
 
 			if (info.cmp_mode_used == CMP_MODE_RAW)
@@ -531,7 +531,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 
 	printf("Search for a good set of compression parameters (level: %d) ... ", guess_level);
 	if (!strcmp(guess_cmp_mode, "RDCU")) {
-		if (print_rdcu_cfg)
+		if (add_rdcu_pars)
 			cfg->data_type = DATA_TYPE_IMAGETTE_ADAPTIVE;
 		else
 			cfg->data_type = DATA_TYPE_IMAGETTE;
@@ -563,7 +563,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
 	printf("DONE\n");
 
 	printf("Write the guessed compression configuration to file %s.cfg ... ", output_prefix);
-	error = write_cfg(cfg, output_prefix, print_rdcu_cfg, verbose_en);
+	error = write_cfg(cfg, output_prefix, add_rdcu_pars, verbose_en);
 	if (error)
 		return -1;
 	printf("DONE\n");
@@ -624,10 +624,11 @@ static int gen_rdcu_write_pkts(struct cmp_cfg *cfg)
  * @note set cmp_size, ap1_cmp_size, ap2_cmp_size will be set to 0
  *
  * @returns 0 on success, error otherwise
- * TODO: set cmp_err in error case
+ * TODO: set cmp_mode_err, set model_value_err, etc, in error case
  */
 
-static int cmp_gernate_rdcu_info(const struct cmp_cfg *cfg, int cmp_size_bit, struct cmp_info *info)
+static int cmp_gernate_rdcu_info(const struct cmp_cfg *cfg, int cmp_size_bit,
+				 struct cmp_info *info)
 {
 	if (!cfg)
 		return -1;
@@ -649,21 +650,39 @@ static int cmp_gernate_rdcu_info(const struct cmp_cfg *cfg, int cmp_size_bit, st
 		info->spill_used = cfg->spill;
 		info->golomb_par_used = cfg->golomb_par;
 		info->samples_used = cfg->samples;
-		info->cmp_size = 0;
-		info->ap1_cmp_size = 0;
-		info->ap2_cmp_size = 0;
 		info->rdcu_new_model_adr_used = cfg->rdcu_new_model_adr;
 		info->rdcu_cmp_adr_used = cfg->rdcu_buffer_adr;
 
 		if (cmp_size_bit == CMP_ERROR_SMALL_BUF)
 			/* the icu_output_buf is to small to store the whole bitstream */
 			info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
-		if (cmp_size_bit < 0)
+		if (cmp_size_bit < 0) {
 			info->cmp_size = 0;
-		else
+			info->ap1_cmp_size = 0;
+			info->ap2_cmp_size = 0;
+		} else {
 			info->cmp_size = (uint32_t)cmp_size_bit;
-	}
 
+			if (add_rdcu_pars) {
+				struct cmp_cfg cfg_cpy = *cfg;
+
+				cfg_cpy.icu_output_buf = NULL;
+				cfg_cpy.icu_new_model_buf = NULL;
+
+				cfg_cpy.golomb_par = cfg_cpy.ap1_golomb_par;
+				cfg_cpy.spill = cfg_cpy.ap1_spill;
+				info->ap1_cmp_size = icu_compress_data(&cfg_cpy);
+				if ((int)info->ap1_cmp_size < 0)
+					info->ap1_cmp_size = 0;
+
+				cfg_cpy.golomb_par = cfg_cpy.ap2_golomb_par;
+				cfg_cpy.spill = cfg_cpy.ap2_spill;
+				info->ap2_cmp_size = icu_compress_data(&cfg_cpy);
+				if ((int)info->ap2_cmp_size < 0)
+					info->ap2_cmp_size = 0;
+			}
+		}
+	}
 	return 0;
 }
 
@@ -711,15 +730,8 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 	cfg->icu_output_buf = cmp_ent_get_data_buf(cmp_entity);
 
 	cmp_size = icu_compress_data(cfg);
-	cmp_gernate_rdcu_info(cfg, cmp_size, info);
-	if (cmp_size < 0 || info->cmp_err != 0) {
-		if (info->cmp_err)
-			printf("\nCompression error 0x%02X\n... ", info->cmp_err);
-		/* TODO: add a parse cmp error function */
-		/* if ((info->cmp_err >> SMALL_BUFFER_ERR_BIT) & 1U) */
-		/*	fprintf(stderr, "%s: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n", PROGRAM_NAME); */
+	if (cmp_size < 0)
 		goto error_cleanup;
-	}
 
 	if (model_id_str) {
 		uint32_t red_val;
@@ -750,6 +762,8 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 		data_to_write_to_file = cmp_entity;
 		cmp_size_byte = cmp_ent_get_size(cmp_entity);
 	} else {
+		if (cmp_gernate_rdcu_info(cfg, cmp_size, info))
+			goto error_cleanup;
 		data_to_write_to_file = cmp_ent_get_data_buf(cmp_entity);
 		if (cfg->cmp_mode == CMP_MODE_RAW)
 			cmp_size_byte = info->cmp_size/CHAR_BIT;
@@ -777,16 +791,16 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
 	if (!include_cmp_header) {
 		printf("Write decompression information to file %s.info ... ",
 		       output_prefix);
-		error = write_info(info, output_prefix, print_rdcu_cfg);
+		error = write_info(info, output_prefix, add_rdcu_pars);
 		if (error)
 			goto error_cleanup;
 		printf("DONE\n");
-	}
 
-	if (verbose_en) {
-		printf("\n");
-		print_cmp_info(info);
-		printf("\n");
+		if (verbose_en) {
+			printf("\n");
+			print_cmp_info(info);
+			printf("\n");
+		}
 	}
 
 	free(cmp_entity);
diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py
index f08d53b..7d58943 100755
--- a/test/cmp_tool/cmp_tool_integration_test.py
+++ b/test/cmp_tool/cmp_tool_integration_test.py
@@ -831,9 +831,7 @@ def test_small_buf_err():
         assert(stdout == CMP_START_STR_CMP +
                "Importing configuration file %s ... DONE\n" % (cfg_file_name) +
                "Importing data file %s ... DONE\n" % (data_file_name) +
-               "Compress data ... \n"
-               "Compression error 0x01\n"
-               "... FAILED\n")
+               "Compress data ... FAILED\n")
         # assert(stderr == "cmp_tool: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n")
         assert(stderr == "Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n")
         assert(returncode == EXIT_FAILURE)
-- 
GitLab


From 6cd59968613e183b70644fd8da714ede238e66f3 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 27 Sep 2022 16:39:27 +0200
Subject: [PATCH 40/46] Refactor code; add documentation

---
 include/decmp.h           |   9 +-
 lib/decmp.c               | 242 +++++++++++++++++++++++---------------
 test/cmp_icu/test_decmp.c |  83 +++++++++----
 3 files changed, 214 insertions(+), 120 deletions(-)

diff --git a/include/decmp.h b/include/decmp.h
index 4046798..826eb89 100644
--- a/include/decmp.h
+++ b/include/decmp.h
@@ -22,10 +22,11 @@
 #include <cmp_entity.h>
 #include <cmp_support.h>
 
-int decompress_data(uint32_t *compressed_data, void *de_model_buf,
-		    const struct cmp_info *info, void *decompressed_data);
-
-int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_of_data,
 			 void *up_model_buf, void *decompressed_data);
 
+int decompress_rdcu_data(uint32_t *compressed_data, const struct cmp_info *info,
+			 uint16_t *model_of_data, uint16_t *up_model_buf,
+			 uint16_t *decompressed_data);
+
 #endif /* DECMP_H_ */
diff --git a/lib/decmp.c b/lib/decmp.c
index c266e64..7bea1e1 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -16,7 +16,8 @@
  * @brief software decompression library
  * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
  *
- * TODO: how to decomprss?
+ * To decompress a compression entity (consisting of a compression entity header
+ * and the compressed data) use the decompress_cmp_entiy() function.
  */
 
 #include <stdint.h>
@@ -34,6 +35,7 @@
 
 #define MAX_CW_LEN 32 /* maximum Golomb code word bit length */
 
+
 /* maximum used bits registry */
 extern struct cmp_max_used_bits max_used_bits;
 
@@ -59,7 +61,7 @@ struct decoder_setup {
 /**
  * @brief count leading 1-bits
  *
- * @param value	input vale
+ * @param value	input vale to count
  *
  * @returns the number of leading 1-bits in value, starting at the most
  *	significant bit position
@@ -67,18 +69,10 @@ struct decoder_setup {
 
 static unsigned int count_leading_ones(uint32_t value)
 {
-	unsigned int n_ones = 0; /* number of leading 1s */
-
-	while (1) {
-		uint32_t leading_bit = value & 0x80000000;
+	if (value == 0xFFFFFFFF)
+		return 32;
 
-		if (!leading_bit)
-			break;
-
-		n_ones++;
-		value <<= 1;
-	}
-	return n_ones;
+	return __builtin_clz(~value);
 }
 
 
@@ -100,19 +94,17 @@ static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m,
 	unsigned int q; /* quotient code */
 	unsigned int ql; /* length of the quotient code */
 	unsigned int r; /* remainder code */
-	unsigned int rl; /* length of the remainder code */
+	unsigned int rl = log2_m; /* length of the remainder code */
 	unsigned int cw_len; /* length of the decoded code word in bits */
 
 	(void)m; /* we don't need the Golomb parameter */
 
-	if (log2_m > 32)
+	if (log2_m > 32) /* because m has 32 bits log2_m can not be bigger than 32 */
 		return 0;
 
 	q = count_leading_ones(code_word); /* decode unary coding */
 	ql = q + 1; /* Number of 1's + following 0 */
 
-	rl = log2_m;
-
 	cw_len = rl + ql;
 
 	if (cw_len > 32) /* can only decode code words with maximum 32 bits */
@@ -121,8 +113,7 @@ static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m,
 	code_word = code_word << ql;  /* shift quotient code out */
 
 	/* Right shifting an integer by a number of bits equal or greater than
-	 * its size is undefined behavior
-	 */
+	 * its size is undefined behavior */
 	if (rl == 0)
 		r = 0;
 	else
@@ -308,7 +299,7 @@ static int decode_normal(uint32_t *decoded_value, int stream_pos,
 	unsigned int n_read_bits;
 	int stream_pos_read, cw_len;
 
-	/* check if we can read max_cw_len or less; we do not now how long the
+	/* check if we can read max_cw_len or less; we do not know how long the
 	 * code word actually is so we try to read the maximum cw length */
 	if ((unsigned int)stream_pos + 32 > setup->max_stream_len)
 		n_read_bits = setup->max_stream_len - (unsigned int)stream_pos;
@@ -327,7 +318,7 @@ static int decode_normal(uint32_t *decoded_value, int stream_pos,
 				    setup->encoder_par2, decoded_value);
 	if (cw_len <= 0)
 		return -1;
-	/* consistency check: code word length can not be bigger than read bits */
+	/* consistency check: code word length can not be bigger than the read bits */
 	if (cw_len > (int)n_read_bits)
 		return -1;
 
@@ -400,6 +391,8 @@ static int decode_multi(uint32_t *decoded_value, int stream_pos,
 			const struct decoder_setup *setup)
 {
 	stream_pos = decode_normal(decoded_value, stream_pos, setup);
+	if (stream_pos < 0)
+		return stream_pos;
 
 	if (*decoded_value >= setup->outlier_par) {
 		/* escape symbol mechanism was used; read unencoded value */
@@ -442,7 +435,7 @@ static int decode_none(uint32_t *decoded_value, int stream_pos,
 
 
 /**
- * @brief remap a unsigned value back to a signed value
+ * @brief remap an unsigned value back to a signed value
  * @note this is the reverse function of map_to_pos()
  *
  * @param value_to_unmap	unsigned value to remap
@@ -481,27 +474,46 @@ static int decode_value(uint32_t *decoded_value, uint32_t model,
 {
 	uint32_t mask = (~0U >> (32 - setup->max_data_bits)); /* mask the used bits */
 
+	/* decode the next value from the bitstream */
 	stream_pos = setup->decode_method_f(decoded_value, stream_pos, setup);
 	if (stream_pos <= 0)
 		return stream_pos;
 
-	if (setup->decode_method_f == decode_none) /* we are done here in stuff mode */
+	if (setup->decode_method_f == decode_none)
+		/* we are done here in stuff mode */
 		return stream_pos;
 
+	/* map the unsigned decode value back to a signed value */
 	*decoded_value = re_map_to_pos(*decoded_value);
 
+	/* decorate data the data with the model */
 	*decoded_value += round_fwd(model, setup->lossy_par);
 
-	*decoded_value &= mask; /* TODO: why?? */
+	/* we mask only the used bits in case there is an overflow when adding the model */
+	*decoded_value &= mask;
 
+	/* inverse step of the lossy compression */
 	*decoded_value = round_inv(*decoded_value, setup->lossy_par);
 
 	return stream_pos;
 }
 
 
+/**
+ * @brief configure a decoder setup structure to have a setup to decode a vale
+ *
+ * @param setup		pointer to the decoder setup
+ * @param cmp_par	compression parameter
+ * @param spillover	spillover_par parameter
+ * @param lossy_par	lossy compression parameter
+ * @param max_data_bits	how many bits are needed to represent the highest possible value
+ * @param cfg		pointer to the compression configuration structure
+ *
+ * @returns 0 on success; otherwise error
+ */
+
 static int configure_decoder_setup(struct decoder_setup *setup,
-				   uint32_t cmp_par, uint32_t spill,
+				   uint32_t cmp_par, uint32_t spillover,
 				   uint32_t lossy_par, uint32_t max_data_bits,
 				   const struct cmp_cfg *cfg)
 {
@@ -527,7 +539,7 @@ static int configure_decoder_setup(struct decoder_setup *setup,
 	if (ilog_2(cmp_par) < 0)
 		return -1;
 	setup->encoder_par2 = ilog_2(cmp_par); /* encoding parameter 2 */
-	setup->outlier_par = spill; /* outlier parameter */
+	setup->outlier_par = spillover; /* outlier parameter */
 	setup->lossy_par = lossy_par; /* lossy compression parameter */
 	setup->model_value = cfg->model_value; /* model value parameter */
 	setup->max_data_bits = max_data_bits; /* how many bits are needed to represent the highest possible value */
@@ -537,6 +549,16 @@ static int configure_decoder_setup(struct decoder_setup *setup,
 }
 
 
+/**
+ * @brief decompress imagette data
+ *
+ * @param cfg	pointer to the compression configuration structure
+ *
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
+ */
+
 static int decompress_imagette(struct cmp_cfg *cfg)
 {
 	int err;
@@ -577,7 +599,7 @@ static int decompress_imagette(struct cmp_cfg *cfg)
 
 
 /**
- * @brief TODO: decompress the multi-entry packet header structure and sets the data,
+ * @brief decompress the multi-entry packet header structure and sets the data,
  *	model and up_model pointers to the data after the header
  *
  * @param data		pointer to a pointer pointing to the data to be compressed
@@ -585,7 +607,7 @@ static int decompress_imagette(struct cmp_cfg *cfg)
  * @param up_model	pointer to a pointer pointing to the updated model buffer
  * @param cfg		pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
+ * @returns the bit length of the bitstream on success
  *
  * @note the (void **) cast relies on all pointer types having the same internal
  *	representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html
@@ -624,9 +646,9 @@ static int decompress_multi_entry_hdr(void **data, void **model, void **up_model
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_s_fx(const struct cmp_cfg *cfg)
@@ -696,9 +718,9 @@ static int decompress_s_fx(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_s_fx_efx(const struct cmp_cfg *cfg)
@@ -779,9 +801,9 @@ static int decompress_s_fx_efx(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_s_fx_ncob(const struct cmp_cfg *cfg)
@@ -870,9 +892,9 @@ static int decompress_s_fx_ncob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
@@ -991,9 +1013,9 @@ static int decompress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_f_fx(const struct cmp_cfg *cfg)
@@ -1051,9 +1073,9 @@ static int decompress_f_fx(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_f_fx_efx(const struct cmp_cfg *cfg)
@@ -1123,9 +1145,9 @@ static int decompress_f_fx_efx(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_f_fx_ncob(const struct cmp_cfg *cfg)
@@ -1203,9 +1225,9 @@ static int decompress_f_fx_ncob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
@@ -1313,9 +1335,9 @@ static int decompress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_l_fx(const struct cmp_cfg *cfg)
@@ -1396,9 +1418,9 @@ static int decompress_l_fx(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_l_fx_efx(const struct cmp_cfg *cfg)
@@ -1490,9 +1512,9 @@ static int decompress_l_fx_efx(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_l_fx_ncob(const struct cmp_cfg *cfg)
@@ -1612,9 +1634,9 @@ static int decompress_l_fx_ncob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
@@ -1764,9 +1786,9 @@ static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_nc_offset(const struct cmp_cfg *cfg)
@@ -1836,9 +1858,9 @@ static int decompress_nc_offset(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_nc_background(const struct cmp_cfg *cfg)
@@ -1919,9 +1941,9 @@ static int decompress_nc_background(const struct cmp_cfg *cfg)
  *
  * @param cfg	pointer to the compression configuration structure
  *
- * @returns the bit length of the bitstream on success; negative on error,
- *	CMP_ERROR_SMALL_BUF if the bitstream buffer is too small to put the
- *	value in the bitstream
+ * @returns bit position of the last read bit in the bitstream on success;
+ *	returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream
+ *	buffer is too small to read the value from the bitstream
  */
 
 static int decompress_smearing(const struct cmp_cfg *cfg)
@@ -1997,6 +2019,17 @@ static int decompress_smearing(const struct cmp_cfg *cfg)
 }
 
 
+/**
+ * @brief decompress the data based on a compression configuration
+ *
+ * @param cfg	pointer to a compression configuration
+ *
+ * @note cfg->buffer_length is measured in bytes (instead of samples as by the
+ *	compression)
+ *
+ * @returns the size of the decompressed data on success; returns negative on failure
+ */
+
 static int decompressed_data_internal(struct cmp_cfg *cfg)
 {
 	int data_size, strem_len_bit = -1;
@@ -2094,9 +2127,7 @@ static int decompressed_data_internal(struct cmp_cfg *cfg)
 			debug_print("Error: Compressed data type not supported.\n");
 			break;
 		}
-
 	}
-	/* TODO: is this usefull? if (strem_len_bit != data_size * CHAR_BIT) { */
 	if (strem_len_bit <= 0)
 		return -1;
 
@@ -2104,13 +2135,27 @@ static int decompressed_data_internal(struct cmp_cfg *cfg)
 }
 
 
-int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
+/**
+ * @brief decompress a compression entity
+ *
+ * @param ent			pointer to the compression entity to be decompressed
+ * @param model_of_data		pointer to model data buffer (can be NULL if no
+ *				model compression mode is used)
+ * @param updated_model		pointer to store the updated model for the next model
+ *				mode compression (can be the same as the model_of_data
+ *				buffer for in-place update or NULL if updated model is not needed)
+ * @param decompressed_data	pointer to the decompressed data buffer (can be NULL)
+ *
+ * @returns the size of the decompressed data on success; returns negative on failure
+ */
+
+int decompress_cmp_entiy(struct cmp_entity *ent, void *model_of_data,
 			 void *up_model_buf, void *decompressed_data)
 {
 	int err;
 	struct cmp_cfg cfg = {0};
 
-	cfg.model_buf = model_buf;
+	cfg.model_buf = model_of_data;
 	cfg.icu_new_model_buf = up_model_buf;
 	cfg.input_buf = decompressed_data;
 
@@ -2125,12 +2170,26 @@ int decompress_cmp_entiy(struct cmp_entity *ent, void *model_buf,
 }
 
 
-/* model buffer is overwritten with updated model */
+/**
+ * @brief decompress RDCU compressed data without a compression entity header
+ *
+ * @param compressed_data	pointer to the RDCU compressed data (without a
+ *				compression entity header)
+ * @param model_of_data		pointer to model data buffer (can be NULL if no
+ *				model compression mode is used)
+ * @param updated_model		pointer to store the updated model for the next model
+ *				mode compression (can be the same as the model_of_data
+ *				buffer for in-place update or NULL if updated model is not needed)
+ * @param decompressed_data	pointer to the decompressed data buffer (can be NULL)
+ *
+ * @returns the size of the decompressed data on success; returns negative on failure
+ */
+
+int decompress_rdcu_data(uint32_t *compressed_data, const struct cmp_info *info,
+			 uint16_t *model_of_data, uint16_t *up_model_buf,
+			 uint16_t *decompressed_data)
 
-int decompress_data(uint32_t *compressed_data, void *de_model_buf,
-		    const struct cmp_info *info, void *decompressed_data)
 {
-	int size_decomp_data;
 	struct cmp_cfg cfg = {0};
 
 	if (!compressed_data)
@@ -2142,15 +2201,11 @@ int decompress_data(uint32_t *compressed_data, void *de_model_buf,
 	if (info->cmp_err)
 		return -1;
 
-	if (model_mode_is_used(info->cmp_mode_used))
-		if (!de_model_buf)
-			return -1;
-	/* TODO: add ohter modes */
-
-	if (!decompressed_data)
-		return -1;
+	cfg.data_type = DATA_TYPE_IMAGETTE;
+	cfg.model_buf = model_of_data;
+	cfg.icu_new_model_buf = up_model_buf;
+	cfg.input_buf = decompressed_data;
 
-	/* cfg.data_type = info->data_type_used; */
 	cfg.cmp_mode = info->cmp_mode_used;
 	cfg.model_value = info->model_value_used;
 	cfg.round = info->round_used;
@@ -2159,11 +2214,6 @@ int decompress_data(uint32_t *compressed_data, void *de_model_buf,
 	cfg.samples = info->samples_used;
 	cfg.icu_output_buf = compressed_data;
 	cfg.buffer_length = cmp_bit_to_4byte(info->cmp_size);
-	cfg.input_buf = decompressed_data;
-	cfg.model_buf = de_model_buf;
-	size_decomp_data = decompressed_data_internal(&cfg);
-	if (size_decomp_data <= 0)
-		return -1;
-	else
-		return 0;
+
+	return decompressed_data_internal(&cfg);
 }
diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c
index 244bbe8..efcf3e1 100644
--- a/test/cmp_icu/test_decmp.c
+++ b/test/cmp_icu/test_decmp.c
@@ -110,7 +110,69 @@ void test_cmp_decmp_n_imagette_raw(void)
 }
 
 
-/*
+/**
+ * @test count_leading_ones
+ */
+
+void test_count_leading_ones(void)
+{
+	unsigned int n_leading_bit;
+	uint32_t value;
+
+	value = 0;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(0, n_leading_bit);
+
+	value = 0x7FFFFFFF;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(0, n_leading_bit);
+
+	value = 0x80000000;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(1, n_leading_bit);
+
+	value = 0xBFFFFFFF;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(1, n_leading_bit);
+
+	value = 0xFFFF0000;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(16, n_leading_bit);
+
+	value = 0xFFFF7FFF;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(16, n_leading_bit);
+
+	value = 0xFFFFFFFF;
+	n_leading_bit = count_leading_ones(value);
+	TEST_ASSERT_EQUAL_INT(32, n_leading_bit);
+}
+
+
+/**
+ * @test rice_decoder
+ */
+
+void test_rice_decoder(void)
+{
+	int cw_len;
+	uint32_t code_word;
+	unsigned int m = ~0;  /* we don't need this value */
+	unsigned int log2_m;
+	unsigned int decoded_cw;
+
+	/* test log_2 to big */
+	code_word = 0xE0000000;
+	log2_m = 33;
+	cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw);
+	TEST_ASSERT_EQUAL(0, cw_len);
+	log2_m = UINT_MAX;
+	cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw);
+	TEST_ASSERT_EQUAL(0, cw_len);
+}
+
+
+/**
  * @test re_map_to_pos
  */
 
@@ -160,25 +222,6 @@ void test_re_map_to_pos(void)
 }
 
 
-void test_rice_decoder(void)
-{
-	int cw_len;
-	uint32_t code_word;
-	unsigned int m = ~0;/* we don't need this value */
-	unsigned int log2_m;
-	unsigned int decoded_cw;
-
-	/* test log_2 to big */
-	code_word = 0xE0000000;
-	log2_m = 33;
-	cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw);
-	TEST_ASSERT_EQUAL(0, cw_len);
-	log2_m = UINT_MAX;
-	cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw);
-	TEST_ASSERT_EQUAL(0, cw_len);
-}
-
-
 void test_decode_normal(void)
 {
 	uint32_t decoded_value = ~0;
-- 
GitLab


From d4eb52bb92ce2ed2150b74395b6ac4e0823cf52b Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 27 Sep 2022 16:49:17 +0200
Subject: [PATCH 41/46] add compression entity tests cases

---
 test/cmp_entity/meson.build       | 12 ++++++++
 test/cmp_entity/test_cmp_entity.c | 51 +++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 test/cmp_entity/meson.build
 create mode 100644 test/cmp_entity/test_cmp_entity.c

diff --git a/test/cmp_entity/meson.build b/test/cmp_entity/meson.build
new file mode 100644
index 0000000..7221912
--- /dev/null
+++ b/test/cmp_entity/meson.build
@@ -0,0 +1,12 @@
+test_case = files('test_cmp_entity.c')
+test_runner = test_runner_generator.process(test_case)
+
+test_cmp_entity = executable('test_cmp_data_types',
+   test_case, test_runner,
+   include_directories : incdir,
+   link_with : cmp_lib,
+   dependencies : unity_dep,
+   build_by_default : false
+)
+
+test('Compression Entity Unit Tests', test_cmp_entity)
diff --git a/test/cmp_entity/test_cmp_entity.c b/test/cmp_entity/test_cmp_entity.c
new file mode 100644
index 0000000..8493e32
--- /dev/null
+++ b/test/cmp_entity/test_cmp_entity.c
@@ -0,0 +1,51 @@
+#include <unity.h>
+
+#include <cmp_entity.h>
+#include <cmp_io.h>
+
+void test_cmp_ent_get_data_buf(void)
+{
+	enum cmp_data_type data_type;/*TODO: implement: DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */
+	struct cmp_entity ent = {0};
+	char *adr;
+	uint32_t s, hdr_size;
+
+	for (data_type = DATA_TYPE_IMAGETTE;
+	     data_type <=DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE;
+	     data_type++) {
+		s = cmp_ent_create(&ent, data_type, 0, 0);
+		TEST_ASSERT_NOT_EQUAL_INT(0, s);
+
+		adr = cmp_ent_get_data_buf(&ent);
+		TEST_ASSERT_NOT_NULL(adr);
+
+		hdr_size = cmp_ent_cal_hdr_size(data_type, 0);
+		TEST_ASSERT_EQUAL_INT(hdr_size, adr-(char *)&ent);
+	}
+
+	/* RAW mode test */
+	for (data_type = DATA_TYPE_IMAGETTE;
+	     data_type <=DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE;
+	     data_type++) {
+		s = cmp_ent_create(&ent, data_type, 1, 0);
+		TEST_ASSERT_NOT_EQUAL_INT(0, s);
+
+		adr = cmp_ent_get_data_buf(&ent);
+		TEST_ASSERT_NOT_NULL(adr);
+
+		hdr_size = cmp_ent_cal_hdr_size(data_type, 1);
+		TEST_ASSERT_EQUAL_INT(hdr_size, adr-(char *)&ent);
+	}
+
+	/* ent = NULL test */
+	adr = cmp_ent_get_data_buf(NULL);
+	TEST_ASSERT_NULL(adr);
+
+	/* compression data type not supported test */
+	s = cmp_ent_set_data_type(&ent, DATA_TYPE_UNKNOWN, 0);
+	TEST_ASSERT_FALSE(s);
+
+	adr = cmp_ent_get_data_buf(&ent);
+	TEST_ASSERT_NULL(adr);
+}
+
-- 
GitLab


From 8ba76f758c4252e3f517a4cd8745192e61a6f30a Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 29 Sep 2022 13:15:25 +0200
Subject: [PATCH 42/46] fix some issues with sparc and windows compiler

---
 lib/cmp_entity.c              |  2 +-
 lib/cmp_io.c                  |  2 +-
 lib/decmp.c                   | 10 +++----
 test/cmp_icu/test_cmp_decmp.c | 53 +++++++++++++++++++++++++++++++++--
 test/meson.build              |  2 +-
 5 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index b66216c..daa1e11 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -1692,7 +1692,7 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
  *	compressed data is copied to (can be NULL)
  * @param data_buf_size	size of the destination data buffer
  *
- * @returns the size in bytes to store the compressed data; negative on error
+ * @returns the size in bytes to store the compressed data; -1 on error
  *
  * @note the destination and source buffer can overlap
  * @note converts the data to the correct endianness
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index d8772fd..0dfcc8d 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -1334,7 +1334,7 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t buf_size, int v
 		fclose(fp);
 		return 0;
 	}
-	if (file_size < buf_size) {
+	if ((unsigned long)file_size < buf_size) {
 		fprintf(stderr, "%s: %s: Error: The files do not contain enough data as requested.\n", PROGRAM_NAME, file_name);
 		goto fail;
 	}
diff --git a/lib/decmp.c b/lib/decmp.c
index 7bea1e1..3be77c9 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -40,7 +40,7 @@
 extern struct cmp_max_used_bits max_used_bits;
 
 /* function pointer to a code word decoder function */
-typedef int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
+typedef int (*decoder_ptr)(uint32_t, unsigned int, unsigned int, uint32_t *);
 
 /* structure to hold a setup to encode a value */
 struct decoder_setup {
@@ -89,7 +89,7 @@ static unsigned int count_leading_ones(uint32_t value)
  */
 
 static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m,
-			unsigned int *decoded_cw)
+			uint32_t *decoded_cw)
 {
 	unsigned int q; /* quotient code */
 	unsigned int ql; /* length of the quotient code */
@@ -138,8 +138,8 @@ static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m,
  *	0 on failure
  */
 
-static int golomb_decoder(unsigned int code_word, unsigned int m,
-			  unsigned int log2_m, unsigned int *decoded_cw)
+static int golomb_decoder(uint32_t code_word, unsigned int m,
+			  unsigned int log2_m, uint32_t *decoded_cw)
 {
 	unsigned int q; /* quotient code */
 	unsigned int r1; /* remainder code group 1 */
@@ -219,7 +219,7 @@ static decoder_ptr select_decoder(unsigned int golomb_par)
 static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset,
 			uint32_t *bitstream_adr, unsigned int max_stream_len)
 {
-	const unsigned int *local_adr;
+	uint32_t *local_adr;
 	unsigned int bitsLeft, bitsRight, localEndPos;
 	unsigned int mask;
 	int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */
diff --git a/test/cmp_icu/test_cmp_decmp.c b/test/cmp_icu/test_cmp_decmp.c
index e961ffc..9eb587e 100644
--- a/test/cmp_icu/test_cmp_decmp.c
+++ b/test/cmp_icu/test_cmp_decmp.c
@@ -41,7 +41,7 @@
 #define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
 #define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
 
-#define set_n_bits(n)  (~(~0UL << (n)))
+#define set_n_bits(n)  (n!=32?~(~0UL << (n)):0xFFFFFFFF)
 
 
 /**
@@ -588,7 +588,7 @@ void test_random_compression_decompression(void)
 		void *data_to_compress2 = generate_random_test_data(samples, data_type);
 		void *updated_model = calloc(1, cmp_cal_size_of_data(samples, data_type));
 		/* for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_STUFF; cmp_mode++) { */
-		for (cmp_mode = CMP_MODE_RAW; cmp_mode < CMP_MODE_STUFF; cmp_mode++) {
+		for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) {
 			/* printf("cmp_mode: %i\n", cmp_mode); */
 			cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value,
 						 CMP_LOSSLESS);
@@ -612,3 +612,52 @@ void test_random_compression_decompression(void)
 		free(updated_model);
 	}
 }
+
+#define N_SAMPLES 5
+
+void test_random_compression_decompression2(void)
+{
+	struct cmp_cfg cfg;
+	struct cmp_info info = {0};
+	uint32_t cmp_buffer_size;
+	int s, i, cmp_size_bits;
+	void *compressed_data;
+	uint16_t *decompressed_data;
+	uint16_t data[N_SAMPLES] = {0, UINT16_MAX, INT16_MAX, 42, 23};
+
+	cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 8, CMP_LOSSLESS);
+	TEST_ASSERT_NOT_EQUAL_INT(cfg.data_type, DATA_TYPE_UNKNOWN);
+
+	cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data, N_SAMPLES, NULL, NULL,
+					      NULL, N_SAMPLES*CMP_BUFFER_FAKTOR);
+	compressed_data = malloc(cmp_buffer_size);
+	cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data, N_SAMPLES, NULL, NULL,
+					      compressed_data, N_SAMPLES*CMP_BUFFER_FAKTOR);
+	TEST_ASSERT_EQUAL_INT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*N_SAMPLES, DATA_TYPE_IMAGETTE));
+
+	cmp_size_bits = icu_compress_data(&cfg);
+	TEST_ASSERT(cmp_size_bits > 0);
+	info.cmp_size = cmp_size_bits;
+	info.cmp_mode_used = (uint8_t)cfg.cmp_mode;
+	info.model_value_used = (uint8_t)cfg.model_value;
+	info.round_used = (uint8_t)cfg.round;
+	info.spill_used = cfg.spill;
+	info.golomb_par_used = cfg.golomb_par;
+	info.samples_used = cfg.samples;
+	info.rdcu_new_model_adr_used = cfg.rdcu_new_model_adr;
+	info.rdcu_cmp_adr_used = cfg.rdcu_buffer_adr;
+
+	s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, NULL);
+	TEST_ASSERT(s > 0);
+	decompressed_data = malloc(s);
+	s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, decompressed_data);
+	TEST_ASSERT(s > 0);
+
+	for (i = 0; i < N_SAMPLES; i++) {
+		TEST_ASSERT_EQUAL_HEX16(data[i], decompressed_data[i]);
+	}
+
+
+	free(compressed_data);
+	free(decompressed_data);
+}
diff --git a/test/meson.build b/test/meson.build
index 11ddac0..36fee6c 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -8,7 +8,7 @@ if checkpatch.found()
     '--ignore', 'SPDX_LICENSE_TAG,PREFER_DEFINED_ATTRIBUTE_MACRO,EMBEDDED_FILENAME,BLOCK_COMMENT_STYLE,EMBEDDED_FUNCTION_NAME',
   ]
   run_target('syntax-check',
-   command : [checkpatch, checkpatch_args, main, cmplib_sources])
+  command : [checkpatch, checkpatch_args, main, cmplib_sources])
 endif
 
 # add cppcheck inspector target
-- 
GitLab


From bba157525213e4f417defce60cc1c393ec1c053f Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 29 Sep 2022 15:39:27 +0200
Subject: [PATCH 43/46] generalize rand() function

---
 test/cmp_icu/test_decmp.c | 35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c
index efcf3e1..6f2fe2d 100644
--- a/test/cmp_icu/test_decmp.c
+++ b/test/cmp_icu/test_decmp.c
@@ -10,6 +10,30 @@
 #include "../../lib/decmp.c" /* .c file included to test static functions */
 
 
+#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
+#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
+
+
+/**
+ * @brief generate a uint32_t random number
+ *
+ * @return a "random" uint32_t value
+ * @see https://stackoverflow.com/a/33021408
+ */
+
+uint32_t rand32(void)
+{
+	int i;
+	uint32_t r = 0;
+
+	for (i = 0; i < 32; i += RAND_MAX_WIDTH) {
+		r <<= RAND_MAX_WIDTH;
+		r ^= (unsigned int) rand();
+	}
+	return r;
+}
+
+
 /**
  * returns the needed size of the compression entry header plus the max size of the
  * compressed data if ent ==  NULL if ent is set the size of the compression
@@ -419,11 +443,12 @@ void test_cmp_decmp_s_fx_diff(void)
 
 int my_random(unsigned int min, unsigned int max)
 {
-	if (min > max)
-		TEST_ASSERT(0);
-	if (max-min > RAND_MAX)
-		TEST_ASSERT(0);
-	return min + rand() / (RAND_MAX / (max - min + 1) + 1);
+	TEST_ASSERT(min < max);
+	if (max-min < RAND_MAX)
+		return min + rand() / (RAND_MAX / (max - min + 1ULL) + 1);
+	else
+		return min + rand32() / (UINT32_MAX / (max - min + 1ULL) + 1);
+
 }
 
 /* #include <cmp_io.h> */
-- 
GitLab


From 23ced4e5b809621d37863fab963f7e787d4375cd Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 29 Sep 2022 16:02:23 +0200
Subject: [PATCH 44/46] set windows flags if system is cygwin

---
 meson.build               | 3 ++-
 test/cmp_tool/meson.build | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/meson.build b/meson.build
index 6757167..9705be6 100644
--- a/meson.build
+++ b/meson.build
@@ -7,7 +7,8 @@ project('cmp_tool', 'c',
 
 add_project_arguments('-DDEBUGLEVEL=1', language : 'c')
 
-if host_machine.system() == 'windows' and meson.get_compiler('c').get_id() == 'gcc'
+if (host_machine.system() == 'windows' or host_machine.system() == 'cygwin')
+    and meson.get_compiler('c').get_id() == 'gcc'
   # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)),
   # you need to add -mno-ms-bitfields to make it work as expected.
   # See: https://wintermade.it/blog/posts/__attribute__packed-on-windows-is-ignored-with-mingw.html
diff --git a/test/cmp_tool/meson.build b/test/cmp_tool/meson.build
index be04bb7..b53f4e0 100644
--- a/test/cmp_tool/meson.build
+++ b/test/cmp_tool/meson.build
@@ -8,5 +8,5 @@ if pytest.found()
     depends : cmp_tool_exe,
     workdir : meson.project_build_root())
 else
-  message('Pytest framework not found! Skipping integration tests.')
+  message('Pytest framework not found! Skipping integration tests. Run pip install pytest.')
 endif
-- 
GitLab


From 638bf43d5a02b4827c15acb1ed7340bb59185d85 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 30 Sep 2022 18:01:34 +0200
Subject: [PATCH 45/46] add some documentation

---
 CHANGELOG.md              | 16 ++++++++++++
 INSTALL.md                | 55 +++++++++++++++++++++++----------------
 meson.build               |  3 +--
 test/cmp_tool/meson.build |  2 +-
 4 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18386d4..57a3c6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,19 @@
 All notable changes to this project will be documented in this file.
 
 ## [Unreleased]
+
+## [0.09] - 30-09-2022
+### Added
+- decompression/compression for non-imagette data
+- functions to create and configure a compression configuration
+- add max_used_bits feature
+- add max used bit version field to the compression entity
+###Changed
+- Change the build system form make to meson
+- Change DEFAULT_CFG_MODEL and DEFAULT_CFG_DIFF to CMP_DIF_XXX constats
+### Fixed
+- now the adaptive compression size (ap1_cmp_size, ap2_cmp_size) is calculate when the --rdcu_par option is used
+
 ## [0.08] - 19-01-2021
 ### Added
 - Relax the requirements on the input format
@@ -16,6 +29,9 @@ E.g. "# comment\n ABCD 1    2\n34B 12\n" are interpreted as {0xAB, 0xCD,
 ### Changed
 - update the header definition according to PLATO-UVIE-PL-UM-0001 Draft 6
     - changed version_id from 16 to 32 bit in the generic header. Add spare bits to the adaptive imagette header and the non-imagette header, so that the compressed data start address is 4 byte-aligned.
+### Fixed
+- Fix a bug in the definition in imagette header
+### Changed
 - Rename cmp_tool_lib.c to cmp_io.c
 
 ## [0.07] - 13-12-2021
diff --git a/INSTALL.md b/INSTALL.md
index 3653d0a..7665bcb 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,15 +1,15 @@
-## Installation Instructions
+# Installation Instructions
+## Getting started
 
-### Install git and python 3.6+
+### Install git and python 3.7+
 
 If you're on Linux, you probably already have these. On macOS and Windows, you can use the
-[official Python installer](https://www.python.org/downloads/).
+[official Python installer](https://www.python.org/downloads).
 
 ### Install meson and ninja
 
-Meson 0.56 or newer is required.
-
-You can get meson through the Python package manager or using:
+Meson 0.56 or newer is required.  
+You can get meson through your package manager or using:
 
 ```pip3 install meson```
 
@@ -21,58 +21,67 @@ binary in your PATH.
 
 ### Get the Source Code
 
-We use the version control system git to get a copy of the source code.
+We use the version control system [git](https://git-scm.com/downloads) to get a copy of the source code.
 
 ```
 git clone https://gitlab.phaidra.org/loidoltd15/cmp_tool.git  
 cd cmp_tool
 ```
+## Build the cmp\_tool
+### Build the cmp\_tool for Debugging
 
-### Build the cmp_tool for Debugging
-
-You can build the cmp_tool running:
+First, we create the `builddir` directory. Everything we build will be inside this directory.
 
 ```
-meson builddir
+meson setup builddir
 ```
 
-This will automatically create the `builddir` directory and build **everything** **inside** it.
+We change to the build directory and build the cmp_tool:
 
 ```
 cd builddir
-meson compile
+meson compile cmp_tool
 ```
 
-Now you should find the cmp_tool executable in the folder.
+Now you should find the cmp\_tool executable in the folder.
 
 ### Release Build
 
-If you want to build an optimized release build run:
+If you want to create an optimized release version, we can create a build directory for it:
 
 ```
-meson build_relase_dir --buildtype=release
+meson setup build_relase_dir --buildtype=release
 cd build_relase_dir
-meson compile
+meson compile cmp_tool
 ```
 
 You find the build executable in the `build_relase_dir` directory
 
-### Cross-compiling to native Windows
+### Build for Windows
 
-To build the cmp_tool you can use the [Mingw-w64](https://www.mingw-w64.org).
-Unfortunately, the cmp_tool does not support the Microsoft MSVC compiler. But with the Mingw-w64 GCC compiler, we can compile the cmp_tool for Windows. For this, you need the [Mingw-w64 tool chain](https://www.mingw-w64.org/downloads/). This also works on Linux and macOS. To compile for Windows, do this:
+Unfortunately, the cmp\_tool does not support the Microsoft MSVC compiler. To build the cmp\_tool for Windows you can use the Mingw-w64 GCC compiler.
+For this, you need the [Mingw-w64 toolchain](https://www.mingw-w64.org/downloads/). To compile on Windows, do this in the Cygwin64 Terminal:
 
 ```
-meson setup buiddir_win --cross-file=mingw-w64-64.txt
+meson setup buiddir_win --native-file=mingw-w64-64.txt
 cd buiddir_win
 meson compile
 ```
 
+### Cross-compile for Windows
+Cross-compile for Windows is also possible with the [Mingw-w64 toolchain](https://www.mingw-w64.org/downloads/). To cross-compile for Windows use the following commands: 
+
+```
+meson setup buiddir_cross_win --cross-file=mingw-w64-64.txt
+cd buiddir_cross_win
+meson compile
+```
+
 ## Tests
 ### External dependencies
 
-To run the unit tests you need the [c unit testing framework](https://sourceforge.net/projects/cunit/).  
-To run the integration tests you need the [pytest](https://docs.pytest.org/en/7.0.x/index.html) framework. The easiest way to install pytest is with `pip3`:
+To run the unit tests you need the [ruby interpreter](https://www.ruby-lang.org/en/documentation/installation/).  
+To run the cmp\_tool interface test you need the [pytest](https://docs.pytest.org/en/7.0.x/index.html) framework. The easiest way to install pytest is with `pip3`:
 
 ```
 pip3 install pytest
diff --git a/meson.build b/meson.build
index 9705be6..53603ee 100644
--- a/meson.build
+++ b/meson.build
@@ -7,8 +7,7 @@ project('cmp_tool', 'c',
 
 add_project_arguments('-DDEBUGLEVEL=1', language : 'c')
 
-if (host_machine.system() == 'windows' or host_machine.system() == 'cygwin')
-    and meson.get_compiler('c').get_id() == 'gcc'
+if (host_machine.system() == 'windows' or host_machine.system() == 'cygwin') and meson.get_compiler('c').get_id() == 'gcc'
   # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)),
   # you need to add -mno-ms-bitfields to make it work as expected.
   # See: https://wintermade.it/blog/posts/__attribute__packed-on-windows-is-ignored-with-mingw.html
diff --git a/test/cmp_tool/meson.build b/test/cmp_tool/meson.build
index b53f4e0..065cc45 100644
--- a/test/cmp_tool/meson.build
+++ b/test/cmp_tool/meson.build
@@ -2,7 +2,7 @@ int_test_file = files('cmp_tool_integration_test.py')
 
 pytest = find_program('pytest', required : false)
 if pytest.found()
-  test('Integration Test',
+  test('cmp_tool Interface Test',
     pytest,
     args : ['--color=yes', '-vvv', int_test_file],
     depends : cmp_tool_exe,
-- 
GitLab


From 4839a0411dc6c3a68c929c30cb74abacaf71bff4 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Fri, 30 Sep 2022 18:35:04 +0200
Subject: [PATCH 46/46] Data Compression User Manual

---
 ..._0r6.pdf => PLATO-UVIE-PL-UM-0001_1r0.pdf} | Bin 746694 -> 795667 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename doc/{PLATO-UVIE-PL-UM-0001_0r6.pdf => PLATO-UVIE-PL-UM-0001_1r0.pdf} (71%)

diff --git a/doc/PLATO-UVIE-PL-UM-0001_0r6.pdf b/doc/PLATO-UVIE-PL-UM-0001_1r0.pdf
similarity index 71%
rename from doc/PLATO-UVIE-PL-UM-0001_0r6.pdf
rename to doc/PLATO-UVIE-PL-UM-0001_1r0.pdf
index 581a47061c76f787b75e04ccf88a5064f370704e..bc2bb546c36edbf8fcfa043a9735e321cf0597e4 100644
GIT binary patch
delta 234219
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%0AbFQ}&B}+m=;!%O^kVykXY0b6GYY
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
QmWBo<CS0njuKsRZ0LIQ?FaQ7m

delta 185410
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%0Dov*5#v
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%0DDp9chbCPO_C-^7YF^r#*+C6)Inw
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
CSr6<0

-- 
GitLab