diff --git a/.gitignore b/.gitignore index 83df0da..8632a7b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,11 @@ build # Visual Studio Code -.vscode \ No newline at end of file +.vscode + +# temporary directories +tmp +temp + +# distribution directories and files +dist/inform-* diff --git a/CMakeLists.txt b/CMakeLists.txt index b3f357a..57a0450 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,14 +2,16 @@ cmake_minimum_required(VERSION 2.8) project(inform C) set(${PROJECT_NAME}_VERSION_MAJOR 0) -set(${PROJECT_NAME}_VERSION_MINOR 0.2) +set(${PROJECT_NAME}_VERSION_MINOR 0.3) set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}) +message(STATUS "inform version: ${${PROJECT_NAME}_VERSION}") + if (UNIX) add_definitions("-Wall -Wextra -Werror -Wno-unused-parameter -std=gnu1x") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -pg") elseif(MSVC) - add_definitions("/Wall") + add_definitions("/DLIBRARY_EXPORTS") endif() if (APPLE) @@ -19,16 +21,20 @@ endif() include_directories(include) add_subdirectory(src) add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES}) -add_library(${PROJECT_NAME}_STATIC ${${PROJECT_NAME}_SOURCES}) +add_library(${PROJECT_NAME}_static ${${PROJECT_NAME}_SOURCES}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME} VERSION ${${PROJECT_NAME}_VERSION}) -set_target_properties(${PROJECT_NAME}_STATIC PROPERTIES OUTPUT_NAME ${PROJECT_NAME} VERSION ${${PROJECT_NAME}_VERSION}) +if (MSVC) + set_target_properties(${PROJECT_NAME}_static PROPERTIES VERSION ${${PROJECT_NAME}_VERSION}) +else() + set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME ${PROJECT_NAME} VERSION ${${PROJECT_NAME}_VERSION}) +endif() if (UNIX) target_link_libraries(${PROJECT_NAME} m) endif() install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME} DESTINATION lib) -install(TARGETS ${PROJECT_NAME}_STATIC EXPORT ${PROJECT_NAME} DESTINATION lib) +install(TARGETS ${PROJECT_NAME}_static EXPORT ${PROJECT_NAME} DESTINATION lib) install(DIRECTORY include/ DESTINATION include) enable_testing() diff --git a/README.md b/README.md index f7fe6e8..45d16c6 100644 --- a/README.md +++ b/README.md @@ -40,5 +40,5 @@ Inform is still under heavy development. As such, the API and the feature set ar ## Build Status - Linux/OSX: [![Build Status](https://travis-ci.org/ELIFE-ASU/Inform.svg?branch=master)](https://travis-ci.org/ELIFE-ASU/Inform) -- Windows: **Appveyor Support Pending** +- Windows: [![Build Status](https://ci.appveyor.com/api/projects/status/7y015h6p7n0q7097/branch/master?svg=true)](https://ci.appveyor.com/project/dglmoore/inform-vx977) - Code Coverage: **Coming Soon** diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..7be5f45 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,15 @@ +version: 0.0.3.{build} +configuration: +- Debug +- Release +platform: +- x64 +- x86 +- Any CPU +before_build: +- ps: cmake . +build: + project: ALL_BUILD.vcxproj + verbosity: normal +test_script: +- cmd: test\%CONFIGURATION%\inform_unittest.exe diff --git a/dist/install.sh b/dist/install.sh new file mode 100755 index 0000000..11735ea --- /dev/null +++ b/dist/install.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +function usage { + echo "Usage: ${0##*/} [--prefix=]" + exit 1 +} + +if [[ $# -eq 0 ]]; then + prefix=/usr/local +elif [[ $# -eq 1 ]]; then + prefix=${1#"--prefix="} + if [[ $prefix == $1 ]]; then + prefix=${1#"--PREFIX="} + if [[ $prefix == $1 ]]; then + usage + fi + fi +else + usage +fi + +mkdir -p $prefix +cp -R include $prefix +cp -R lib $prefix diff --git a/dist/package.ps1 b/dist/package.ps1 new file mode 100644 index 0000000..529c2b6 --- /dev/null +++ b/dist/package.ps1 @@ -0,0 +1,20 @@ +$version = (cmake . -Bbuild/production -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles" | Select-String '-- inform version: ') +$version = $version.ToString().Split(' ')[3] + +$prefix = "inform-$version" +$target = "dist/$prefix" +$archive = "$($target)_win-amd64.zip" + +cmake . -Bbuild/production -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$target" | Out-Null +cd build/production +nmake +test/inform_unittest.exe +nmake install +cd ../.. +Copy-Item LICENSE $target +Copy-Item README.md $target + +Remove-Item -force $archive +Add-Type -Assembly System.IO.Compression.FileSystem +$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal +[System.IO.Compression.ZipFile]::CreateFromDirectory($target, $archive, $compressionLevel, $true) diff --git a/dist/package.sh b/dist/package.sh new file mode 100755 index 0000000..fafce3d --- /dev/null +++ b/dist/package.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +version=$(cmake -H. -Bbuild/production -DCMAKE_BUILD_TYPE=Release | grep "\-\- inform version:") +version=${version#"-- inform version: "} + +target=inform-$version +prefix=dist/$target +tarball=$target"_linux-x86_64.tar.gz" + +cmake -H. -Bbuild/production -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix > /dev/null +make -C build/production all test +make -C build/production install > /dev/null +cp dist/install.sh $prefix > /dev/null +cp LICENSE $prefix > /dev/null +cp README.md $prefix > /dev/null + +cd dist +echo "Creating tarball: dist/$tarball" +tar czf $tarball $target diff --git a/include/inform/active_info.h b/include/inform/active_info.h index e877038..b37f1ef 100644 --- a/include/inform/active_info.h +++ b/include/inform/active_info.h @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. #pragma once -#include +#include #ifdef __cplusplus extern "C" @@ -18,9 +18,11 @@ extern "C" * @param[in] m the number of time steps in each time series * @param[in] b the base or number of distinct states at each time step * @param[in] k the history length used to calculate the active information + * @param[out] err an error structure * @return the active information for the ensemble */ -double inform_active_info(uint64_t const *series, size_t n, size_t m, uint64_t b, uint64_t k); +EXPORT double inform_active_info(int const *series, size_t n, size_t m, int b, + size_t k, inform_error *err); /** * Compute the local active information of a ensemble of time series @@ -31,10 +33,11 @@ double inform_active_info(uint64_t const *series, size_t n, size_t m, uint64_t b * @param[in] b the base or number of distinct states at each time step * @param[in] k the history length used to calculate the active information * @param[out] ai the local active information - * @return an error code + * @param[out] err an error structure + * @return a pointer to the local active information array */ -int inform_local_active_info(uint64_t const *series, size_t n, size_t m, - uint64_t b, uint64_t k, double *ai); +EXPORT double *inform_local_active_info(int const *series, size_t n, size_t m, int b, + size_t k, double *ai, inform_error *err); #ifdef __cplusplus } diff --git a/include/inform/block_entropy.h b/include/inform/block_entropy.h new file mode 100644 index 0000000..c89d659 --- /dev/null +++ b/include/inform/block_entropy.h @@ -0,0 +1,44 @@ +// Copyright 2016 ELIFE. All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Compute the block entropy of an ensemble of time series + * + * @param[in] series the ensemble of time series + * @param[in] n the number of initial conditions + * @param[in] m the number of time steps in each time series + * @param[in] b the base or number of distinct states at each time step + * @param[in] k the history length used to calculate the active information + * @param[out] err an error structure + * @return the block entropy for the ensemble + */ +EXPORT double inform_block_entropy(int const *series, size_t n, size_t m, int b, + size_t k, inform_error *err); + +/** + * Compute the local block entropy of a ensemble of time series + * + * @param[in] series the ensemble of time series + * @param[in] n the number of initial conditions + * @param[in] m the number of time steps in each time series + * @param[in] b the base or number of distinct states at each time step + * @param[in] k the history length used to calculate the active information + * @param[out] ent the local entropy + * @param[out] err an error structure + * @return a pointer to the local block entropy array + */ +EXPORT double *inform_local_block_entropy(int const *series, size_t n, size_t m, + int b, size_t k, double *ent, inform_error *err); + +#ifdef __cplusplus +} +#endif diff --git a/include/inform/dist.h b/include/inform/dist.h index 6d9d71b..4d5945d 100644 --- a/include/inform/dist.h +++ b/include/inform/dist.h @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. #pragma once +#include #include #include #include @@ -46,7 +47,7 @@ extern "C" typedef struct inform_distribution { /// the histogram or array of observation frequencies - uint64_t *histogram; + uint32_t *histogram; /// the size of the support size_t size; /// the number of observations made so far @@ -64,7 +65,7 @@ typedef struct inform_distribution * @param[in] n the number of distinct events that could be observed * @return the distribution */ -inform_dist* inform_dist_alloc(size_t n); +EXPORT inform_dist* inform_dist_alloc(size_t n); /** * Resize the distribution to have new support. * @@ -88,7 +89,7 @@ inform_dist* inform_dist_alloc(size_t n); * @param[in] n the desired support size * @return the reallocated distribution */ -inform_dist* inform_dist_realloc(inform_dist *dist, size_t n); +EXPORT inform_dist* inform_dist_realloc(inform_dist *dist, size_t n); /** * Copy a distribution to a destination. * @@ -103,7 +104,7 @@ inform_dist* inform_dist_realloc(inform_dist *dist, size_t n); * @param[in,out] the destination distribution * @return a pointer to the copied distribution */ -inform_dist* inform_dist_copy(inform_dist const *src, inform_dist *dest); +EXPORT inform_dist* inform_dist_copy(inform_dist const *src, inform_dist *dest); /** * Duplicate a distribution. * @@ -117,7 +118,7 @@ inform_dist* inform_dist_copy(inform_dist const *src, inform_dist *dest); * @param[in] dist the source distribution * @return the new distribution */ -inform_dist* inform_dist_dup(inform_dist const *dist); +EXPORT inform_dist* inform_dist_dup(inform_dist const *dist); /** * Create a distribution from an underlying histogram. * @@ -125,13 +126,13 @@ inform_dist* inform_dist_dup(inform_dist const *dist); * @param[in] n the number of events in the histogram * @return the new distribution */ -inform_dist* inform_dist_create(uint64_t const *data, size_t n); +EXPORT inform_dist* inform_dist_create(uint32_t const *data, size_t n); /** * Free all dynamically allocated memory associated with a distribution. * * @param[in] dist the distribution to free */ -void inform_dist_free(inform_dist *dist); +EXPORT void inform_dist_free(inform_dist *dist); /** * Get the size of the distribution's support. @@ -141,7 +142,7 @@ void inform_dist_free(inform_dist *dist); * @param[in] dist the distribution * @return the size of the distribution's support */ -size_t inform_dist_size(inform_dist const *dist); +EXPORT size_t inform_dist_size(inform_dist const *dist); /** * Get the total number of observations so far made. * @@ -150,7 +151,7 @@ size_t inform_dist_size(inform_dist const *dist); * @param[in] dist the distribution * @return the number of observations thus far made */ -uint64_t inform_dist_counts(inform_dist const *dist); +EXPORT uint64_t inform_dist_counts(inform_dist const *dist); /** * Determine whether or not the distribution is valid. * @@ -162,7 +163,7 @@ uint64_t inform_dist_counts(inform_dist const *dist); * @param[in] dist the distribution * @return the validity of the distribution */ -bool inform_dist_is_valid(inform_dist const *dist); +EXPORT bool inform_dist_is_valid(inform_dist const *dist); /** * Get the number of occurances of a given event. @@ -176,7 +177,7 @@ bool inform_dist_is_valid(inform_dist const *dist); * * @see inform_dist_set */ -uint64_t inform_dist_get(inform_dist const *dist, uint64_t event); +EXPORT uint32_t inform_dist_get(inform_dist const *dist, size_t event); /** * Set the number of occurances of a given event. * @@ -195,7 +196,7 @@ uint64_t inform_dist_get(inform_dist const *dist, uint64_t event); * @see inform_dist_get * @see inform_dist_tick */ -uint64_t inform_dist_set(inform_dist *dist, uint64_t event, uint64_t x); +EXPORT uint32_t inform_dist_set(inform_dist *dist, size_t event, uint32_t x); /** * Increment the number of observations of a given event. @@ -213,7 +214,7 @@ uint64_t inform_dist_set(inform_dist *dist, uint64_t event, uint64_t x); * * @see inform_dist_set */ -uint64_t inform_dist_tick(inform_dist *dist, uint64_t event); +EXPORT uint32_t inform_dist_tick(inform_dist *dist, size_t event); /** * Extact the probability of an event. @@ -231,7 +232,7 @@ uint64_t inform_dist_tick(inform_dist *dist, uint64_t event); * @see inform_dist_get * @see inform_dist_dump */ -double inform_dist_prob(inform_dist const *dist, uint64_t event); +EXPORT double inform_dist_prob(inform_dist const *dist, size_t event); /** * Dump the probabilities of all events to an array. * @@ -248,7 +249,7 @@ double inform_dist_prob(inform_dist const *dist, uint64_t event); * @param[in] probs the size of the preallocated array * @return the number of probabilities written to the array */ -size_t inform_dist_dump(inform_dist const *dist, double *probs, size_t n); +EXPORT size_t inform_dist_dump(inform_dist const *dist, double *probs, size_t n); #ifdef __cplusplus } diff --git a/include/inform/entropy_rate.h b/include/inform/entropy_rate.h index d24f2c7..99d0872 100644 --- a/include/inform/entropy_rate.h +++ b/include/inform/entropy_rate.h @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. #pragma once -#include +#include #ifdef __cplusplus extern "C" @@ -18,24 +18,26 @@ extern "C" * @param[in] m the number of time steps in each time series * @param[in] b the base or number of distinct states at each time step * @param[in] k the history length used to calculate the entropy rate + * @param[out] err an error structure * @return the entropy rate for the ensemble */ -double inform_entropy_rate(uint64_t const *series, size_t n, size_t m, - uint64_t b, uint64_t k); +EXPORT double inform_entropy_rate(int const *series, size_t n, size_t m, int b, + size_t k, inform_error *err); /** - * Compute the entropy rate of an ensemble of time series + * Compute the local entropy rate of an ensemble of time series * * @param[in] series the ensemble of time series * @param[in] n the number of initial conditions * @param[in] m the number of time steps in each time series * @param[in] b the base or number of distinct states at each time step * @param[in] k the history length used to calculate the entropy rate - * @param[out] err the local entropy rate of the ensemble - * @return an error code + * @param[out] er the local entropy rate of the ensemble + * @param[out] err an error structures + * @return a pointer to the local entropy rate array */ -int inform_local_entropy_rate(uint64_t const *series, size_t n, size_t m, - uint64_t b, uint64_t k, double *er); +EXPORT double *inform_local_entropy_rate(int const *series, size_t n, size_t m, int b, + size_t k, double *er, inform_error *err); #ifdef __cplusplus } diff --git a/include/inform/error.h b/include/inform/error.h index a01b005..afc9ad5 100644 --- a/include/inform/error.h +++ b/include/inform/error.h @@ -3,8 +3,9 @@ // license that can be found in the LICENSE file. #pragma once -#include +#include #include +#include #ifdef __cplusplus extern "C" @@ -12,45 +13,68 @@ extern "C" #endif /** - * Determine whether or not a potential NaN tag is valid. - * - * NaN tags are bounded above by `0x0007ffffffffffff`. This function - * returns true if the potential tag exceeds that value. - * - * @param[in] tag the desired tag - * @return a true if the tag is below `0x0007ffffffffffff` + * Error tags to be used in conjunction with `inform_error` */ -bool inform_tag_is_valid(uint64_t tag); +typedef enum +{ + INFORM_SUCCESS = 0, /// no error occurred + INFORM_FAILURE = -1, /// an unspecified error occurred + INFORM_EFAULT = 1, /// invalid pointer + INFORM_EARG = 2, /// invalid argument + INFORM_ENOMEM = 3, /// malloc/calloc/realloc failed + INFORM_ETIMESERIES = 4, /// time series is NULL + INFORM_ENOINITS = 5, /// time series has no initial conditions + INFORM_ESHORTSERIES = 6, /// time series has less than two timesteps + INFORM_EKZERO = 7, /// history length is zero + INFORM_EKLONG = 8, /// history is too long for the time series + INFORM_EBASE = 9, /// the provided base is invalid + INFORM_ENEGSTATE = 10, /// time series has negative state + INFORM_EBADSTATE = 11, /// time series has states inconsistent with expected base + INFORM_EDIST = 12, /// invalid distribution +} inform_error; + +/// set an error as pointed to by ERR +#define INFORM_ERROR(ERR, TAG) do {\ + if ((ERR) != NULL) {\ + *(ERR) = (inform_error) TAG;\ + }\ + } while(0) + +/// set an error and return a result +#define INFORM_ERROR_RETURN(ERR, TAG, RET) do {\ + INFORM_ERROR(ERR, TAG); \ + return RET; \ + } while(0) + +/// set an error and return a void result +#define INFORM_ERROR_RETURN_VOID(ERR, TAG) do {\ + INFORM_ERROR(ERR, TAG); \ + return; \ + } while(0) /** - * Construct a tagged NaN with a given `tag` - * - * At 64-bits, any value of the form `0x7ff8XXXXXXXXXXXX` is identified - * as a NaN value. We can thus "tag" the NaN by embedding numeric value - * in the unspecified region. + * Determine if an error code signifies a success. * - * The tag is expected to be between `0` and `0x0007ffffffffffff` inclusive. - * If the tag is out of range, -1 is returned. - * - * @param[in] tag the tag to embed - * @return the tagged NaN will be returned. - * - * @see inform_nan_tag + * @param[in] err a pointer to an error code + * @return `true` if the error is success, and `false` otherwise */ -double inform_nan(uint64_t tag); +EXPORT bool inform_succeeded(inform_error const *err); /** - * Extract the tag from a NaN value - * - * This function is the ivnerse of inform_tagnan. If the provided argument - * is non NaN, then 0x0008000000000000` is returned. + * Determine if an error code signifies a failure. * - * @param[in] the NaN value - * @return the NaN tag + * @param[in] err a pointer to an error code + * @return `true` if the error is not success, and `false` otherwise + */ +EXPORT bool inform_failed(inform_error const *err); + +/** + * Provide a string describing an error code. * - * @see inform_nan + * @param[in] err a pointer to an error code + * @return a descrptive string */ -uint64_t inform_nan_tag(double x); +EXPORT char const *inform_strerror(inform_error const *err); #ifdef __cplusplus } diff --git a/include/inform/export.h b/include/inform/export.h new file mode 100644 index 0000000..accbbc2 --- /dev/null +++ b/include/inform/export.h @@ -0,0 +1,14 @@ +// Copyright 2016 ELIFE. All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. +#pragma once + +#ifdef _WIN32 + #ifdef LIBRARY_EXPORTS + #define EXPORT __declspec(dllexport) + #else + #define EXPORT __declspec(dllimport) + #endif +#else + #define EXPORT +#endif diff --git a/include/inform/inform.h b/include/inform/inform.h index d0baef6..ca95d47 100644 --- a/include/inform/inform.h +++ b/include/inform/inform.h @@ -4,9 +4,10 @@ #pragma once #include +#include #include -#include +#include #include #include #include diff --git a/include/inform/shannon.h b/include/inform/shannon.h index 8ac0820..1508909 100644 --- a/include/inform/shannon.h +++ b/include/inform/shannon.h @@ -21,7 +21,7 @@ extern "C" * @param[in] base the logarithmic base * @return the self-information of the event */ -double inform_shannon_si(inform_dist const *dist, uint64_t event, double base); +EXPORT double inform_shannon_si(inform_dist const *dist, size_t event, double base); /** * Compute the Shannon information of a distribution. @@ -33,7 +33,7 @@ double inform_shannon_si(inform_dist const *dist, uint64_t event, double base); * @param[in] base the logarithmic base * @return the shannon information */ -double inform_shannon(inform_dist const *dist, double base); +EXPORT double inform_shannon(inform_dist const *dist, double base); /** * Compute the pointwise mutual information of an combination of events @@ -47,9 +47,9 @@ double inform_shannon(inform_dist const *dist, double base); * @param[in] base the logarithmic base * @return the pointwise mutual information of the events */ -double inform_shannon_pmi(inform_dist const *joint, +EXPORT double inform_shannon_pmi(inform_dist const *joint, inform_dist const *marginal_x, inform_dist const *marginal_y, - uint64_t event_joint, uint64_t event_x, uint64_t enent_y, double base); + size_t event_joint, size_t event_x, size_t event_y, double base); /** * Compute the Shannon-based mutual information of a distribution and @@ -64,7 +64,7 @@ double inform_shannon_pmi(inform_dist const *joint, * @param[in] base the logarithmic base * @return the mutual information */ -double inform_shannon_mi(inform_dist const *joint, +EXPORT double inform_shannon_mi(inform_dist const *joint, inform_dist const *marginal_x, inform_dist const *marginal_y, double base); /** @@ -77,8 +77,8 @@ double inform_shannon_mi(inform_dist const *joint, * @param[in] base the logarithmic base * @return the pointwise conditional entropy of the events */ -double inform_shannon_pce(inform_dist const *joint, inform_dist const *marginal, - uint64_t event_joint, uint64_t event_marginal, double base); +EXPORT double inform_shannon_pce(inform_dist const *joint, inform_dist const *marginal, + size_t event_joint, size_t event_marginal, double base); /** * Compute the Shannon-based conditional entropy of a joint distribution and @@ -92,7 +92,7 @@ double inform_shannon_pce(inform_dist const *joint, inform_dist const *marginal, * @param[in] base the logarithmic base * @return the conditional information */ -double inform_shannon_ce(inform_dist const* joint, inform_dist const *marginal, +EXPORT double inform_shannon_ce(inform_dist const* joint, inform_dist const *marginal, double base); /** @@ -109,11 +109,11 @@ double inform_shannon_ce(inform_dist const* joint, inform_dist const *marginal, * @param[in] base the logarithmic base * @return the pointwise conditional mutual information */ -double inform_shannon_pcmi(inform_dist const *joint, +EXPORT double inform_shannon_pcmi(inform_dist const *joint, inform_dist const *marginal_xz, inform_dist const *marginal_yz, - inform_dist const *marginal_z, uint64_t event_joint, - uint64_t event_marginal_xz, uint64_t event_marginal_yz, - uint64_t event_marginal_z, double base); + inform_dist const *marginal_z, size_t event_joint, + size_t event_marginal_xz, size_t event_marginal_yz, + size_t event_marginal_z, double base); /** * Compute the conditional mutual entropy of a joint distribution, and @@ -126,7 +126,7 @@ double inform_shannon_pcmi(inform_dist const *joint, * @param[in] base the logarithmic base * @return the conditional mutual information; */ -double inform_shannon_cmi(inform_dist const *joint, +EXPORT double inform_shannon_cmi(inform_dist const *joint, inform_dist const *marginal_xz, inform_dist const *marginal_yz, inform_dist const *marginal_z, double base); diff --git a/include/inform/state_encoding.h b/include/inform/state_encoding.h deleted file mode 100644 index aa2f984..0000000 --- a/include/inform/state_encoding.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2016 ELIFE. All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define INFORM_ENCODING_ERROR(n) (inform_encoding_error + n) -static uint64_t const inform_encoding_error = 0x8000000000000000; - -/** - * Encode a sequence of unsigned integers into a single integer. - * - * Note that this because the encodings are 64-bits in length, - * for a base @f b @f the maximum number of base-@f b @f digits - * that can be encoded is @f \frac{64}{log_2 b} @f. - * - * However, due to limitations in C's error handling we've opted - * to admit up to 63-bits of the integer for the encoding. In the - * event that an error occurs the returned value is - * `inform_encoding_error` or larger. - * - * Several possible errors and their associated error codes are: - * - if `state == NULL` return `INFORM_ENCODING_ERROR(0)` - * - if `base < 2` return `INFORM_ENCODING_ERROR(1)` - * - if `n >= 64 / log2(base)` return `INFORM_ENCODING_ERROR(2)` - * - if `state[i] >= base` return `INFORM_ENCODING_ERROR(3 + i)` - * - * @param[in] state the sequence of digits - * @param[in] n the number of digits - * @param[in] base the base or number of distict digits - * @return the integer encoding - * - * @see inform_decode - */ -uint64_t inform_encode(uint64_t const *state, uint64_t n, uint64_t base); -/** - * Decode an integer into a sequence of values. - * - * Note that this function is (roughly) the inverse of inform_encode. - * - * In the event that a decoding error occurs, a `NULL` value is - * returned. A few situtations in which this may occur are - * - `encoding >= inform_encoding_error` - * - `base < 2` - * - `n >= 64 / log2(base)` - * - allocation of the memory for the decoded array fails - * - * @param[in] encoding the integral value to decode - * @param[in] n the number of digits to decode to - * @param[in] base the base of the decoding - * @return a dynamic array containing the decoded digits - * - * @see inform_encode - */ -uint64_t* inform_decode(uint64_t encoding, uint64_t n, uint64_t base); - -#ifdef __cplusplus -} -#endif - diff --git a/include/inform/transfer_entropy.h b/include/inform/transfer_entropy.h index ec21c6d..7436ae9 100644 --- a/include/inform/transfer_entropy.h +++ b/include/inform/transfer_entropy.h @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. #pragma once -#include +#include #ifdef __cplusplus extern "C" @@ -19,13 +19,14 @@ extern "C" * @param[in] m the number of time steps in each time series * @param[in] b the base or number of distinct states at each time step * @param[in] k the history length used to calculate the transfer entropy + * @param[out] err an error structure * @return the transfer entropy of the ensemble */ -double inform_transfer_entropy(uint64_t const *series_y, - uint64_t const *series_x, size_t n, size_t m, uint64_t b, uint64_t k); +EXPORT double inform_transfer_entropy(int const *series_y, int const *series_x, + size_t n, size_t m, int b, size_t k, inform_error *err); /** - * Compute the transfer entropy from one time series to another + * Compute the local transfer entropy from one time series to another * * @param[in] series_y the ensemble of the source node * @param[in] series_x the ensemble of the target node @@ -34,11 +35,11 @@ double inform_transfer_entropy(uint64_t const *series_y, * @param[in] b the base or number of distinct states at each time step * @param[in] k the history length used to calculate the transfer entropy * @param[out] te the transfer entropy - * @return an error code + * @param[out] err an error structure + * @return a pointer to the transfer entropy array */ -int inform_local_transfer_entropy(uint64_t const *series_y, - uint64_t const *series_x, size_t n, size_t m, uint64_t b, uint64_t k, - double *te); +EXPORT double *inform_local_transfer_entropy(int const *series_y, int const *series_x, + size_t n, size_t m, int b, size_t k, double *te, inform_error *err); #ifdef __cplusplus } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2daadd..77ff013 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,9 @@ set(${PROJECT_NAME}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/active_info.c + ${CMAKE_CURRENT_SOURCE_DIR}/block_entropy.c ${CMAKE_CURRENT_SOURCE_DIR}/dist.c ${CMAKE_CURRENT_SOURCE_DIR}/entropy_rate.c ${CMAKE_CURRENT_SOURCE_DIR}/error.c ${CMAKE_CURRENT_SOURCE_DIR}/shannon.c - ${CMAKE_CURRENT_SOURCE_DIR}/state_encoding.c ${CMAKE_CURRENT_SOURCE_DIR}/transfer_entropy.c PARENT_SCOPE) diff --git a/src/active_info.c b/src/active_info.c index 0ed6533..3405739 100644 --- a/src/active_info.c +++ b/src/active_info.c @@ -1,20 +1,20 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include #include +#include -static void accumulate_observations(uint64_t const* series, size_t n, uint64_t b, - uint64_t k, inform_dist *states, inform_dist *histories, inform_dist *futures) +static void accumulate_observations(int const* series, size_t n, int b, + size_t k, inform_dist *states, inform_dist *histories, inform_dist *futures) { - uint64_t history = 0, q = 1, state, future; - for (uint64_t i = 0; i < k; ++i) + int history = 0, q = 1, state, future; + for (size_t i = 0; i < k; ++i) { q *= b; history *= b; history += series[i]; } - for (uint64_t i = k; i < n; ++i) + for (size_t i = k; i < n; ++i) { future = series[i]; state = history * b + future; @@ -27,159 +27,156 @@ static void accumulate_observations(uint64_t const* series, size_t n, uint64_t b } } -static void accumulate_local_observations(uint64_t const* series, size_t n, uint64_t b, - uint64_t k, inform_dist *states, inform_dist *histories, inform_dist *futures, - uint64_t *state, uint64_t *history, uint64_t *future) +static void accumulate_local_observations(int const* series, size_t n, int b, + size_t k, inform_dist *states, inform_dist *histories, inform_dist *futures, + int *state, int *history, int *future) { history[0] = 0; - uint64_t q = 1; - for (uint64_t i = 0; i < k; ++i) + int q = 1; + for (size_t i = 0; i < k; ++i) { q *= b; history[0] *= b; history[0] += series[i]; } - for (uint64_t i = k; i < n; ++i) + for (size_t i = k; i < n; ++i) { - uint64_t l = i - k; + size_t l = i - k; future[l] = series[i]; state[l] = history[l] * b + future[l]; - states->histogram[state[l]]++; - histories->histogram[history[l]]++; - futures->histogram[future[l]]++; + states->histogram[state[l]]++; + histories->histogram[history[l]]++; + futures->histogram[future[l]]++; if (i + 1 != n) - { history[l + 1] = state[l] - series[l]*q; - } } } -double inform_active_info(uint64_t const *series, size_t n, size_t m, uint64_t b, uint64_t k) +static bool check_arguments(int const *series, size_t n, size_t m, int b, size_t k, inform_error *err) { - // ensure that the time series is not NULL if (series == NULL) { - return inform_nan(1); + INFORM_ERROR_RETURN(err, INFORM_ETIMESERIES, true); } - // ensure that the dimensions of the time series make sense - else if (m <= 1 || n < 1) + else if (n < 1) { - return inform_nan(2); + INFORM_ERROR_RETURN(err, INFORM_ENOINITS, true); } - // ensure that the number of time steps greater than the history length - else if (m <= k) + else if (m < 2) + { + INFORM_ERROR_RETURN(err, INFORM_ESHORTSERIES, true); + } + else if (b < 2) { - return inform_nan(3); + INFORM_ERROR_RETURN(err, INFORM_EBASE, true); } - // ensure that the history length is reasonable given memory constraints - else if (k > 25 / log2((double) b)) + else if (k == 0) { - return inform_nan(4); + INFORM_ERROR_RETURN(err, INFORM_EKZERO, true); + } + else if (m <= k) + { + INFORM_ERROR_RETURN(err, INFORM_EKLONG, true); } - // ensure that the base is compatible with the time series for (size_t i = 0; i < n * m; ++i) { - if (b <= series[i]) + if (series[i] < 0) + { + INFORM_ERROR_RETURN(err, INFORM_ENEGSTATE, true); + } + else if (b <= series[i]) { - return inform_nan(5); + INFORM_ERROR_RETURN(err, INFORM_EBADSTATE, true); } } + return false; +} + +double inform_active_info(int const *series, size_t n, size_t m, int b, size_t k, inform_error *err) +{ + if (check_arguments(series, n, m, b, k, err)) return NAN; - // compute the number of observations to be made size_t const N = n * (m - k); - // compute the sizes of the various histograms size_t const states_size = (size_t) (b * pow((double) b,(double) k)); size_t const histories_size = states_size / b; size_t const futures_size = b; size_t const total_size = states_size + histories_size + futures_size; - uint64_t *data = calloc(total_size, sizeof(uint64_t)); + uint32_t *data = calloc(total_size, sizeof(uint32_t)); if (data == NULL) { - return inform_nan(6); + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NAN); } inform_dist states = { data, states_size, N }; inform_dist histories = { data + states_size, histories_size, N }; inform_dist futures = { data + states_size + histories_size, futures_size, N }; - // for each initial condition - for (uint64_t i = 0; i < n; ++i, series += m) + for (size_t i = 0; i < n; ++i, series += m) { - // allocate the observations accumulate_observations(series, m, b, k, &states, &histories, &futures); } - // compute the active information double ai = inform_shannon_mi(&states, &histories, &futures, (double) b); - // free up the data array free(data); - // return the active information return ai; } -int inform_local_active_info(uint64_t const *series, size_t n, size_t m, - uint64_t b, uint64_t k, double *ai) +double *inform_local_active_info(int const *series, size_t n, size_t m, + int b, size_t k, double *ai, inform_error *err) { - if (series == NULL) - { - return 1; - } - else if (ai == NULL) - { - return 2; - } - else if (m <= 1 || n < 1) - { - return 3; - } - else if (m <= k) - { - return 4; - } - else if (k > 25 / log2((double) b)) - { - return 5; - } - for (size_t i = 0; i < n * m; ++i) + if (check_arguments(series, n, m, b, k, err)) return NULL; + + size_t const N = n * (m - k); + + if (ai == NULL) { - if (b <= series[i]) + ai = malloc(N * sizeof(double)); + if (ai == NULL) { - return 6; + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } } - // compute the number of observations to be made - size_t const N = n * (m - k); - - // compute the sizes of the various histograms size_t const states_size = (size_t) (b*pow((double) b,(double) k)); size_t const histories_size = states_size / b; size_t const futures_size = b; size_t const total_size = states_size + histories_size + futures_size; - uint64_t *data = calloc(total_size, sizeof(uint64_t)); + uint32_t *data = calloc(total_size, sizeof(uint32_t)); if (data == NULL) { - return 6; + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } inform_dist states = { data, states_size, N }; inform_dist histories = { data + states_size, histories_size, N }; inform_dist futures = { data + states_size + histories_size, futures_size, N }; - uint64_t *state = malloc(N * sizeof(uint64_t)); - uint64_t *history = malloc(N * sizeof(uint64_t)); - uint64_t *future = malloc(N * sizeof(uint64_t)); + int *state = malloc(N * sizeof(int)); + if (state == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + int *history = malloc(N * sizeof(int)); + if (history == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + int *future = malloc(N * sizeof(int)); + if (future == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } - uint64_t const *series_ptr = series; - uint64_t *state_ptr = state, *history_ptr = history, *future_ptr = future; - for (uint64_t i = 0; i < n; ++i) + int const *series_ptr = series; + int *state_ptr = state, *history_ptr = history, *future_ptr = future; + for (size_t i = 0; i < n; ++i) { accumulate_local_observations(series_ptr, m, b, k, &states, &histories, &futures, state_ptr, history_ptr, future_ptr); @@ -195,12 +192,10 @@ int inform_local_active_info(uint64_t const *series, size_t n, size_t m, history[i], future[i], (double) b); } - // free up the data array free(future); free(history); free(state); free(data); - // return the error code - return 0; + return ai; } diff --git a/src/block_entropy.c b/src/block_entropy.c new file mode 100644 index 0000000..3aab88c --- /dev/null +++ b/src/block_entropy.c @@ -0,0 +1,170 @@ +// Copyright 2016 ELIFE. All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. +#include +#include + +static void accumulate_observations(int const* series, size_t n, int b, + size_t k, inform_dist *states) +{ + k -= 1; + int history = 0, q = 1, state; + for (size_t i = 0; i < k; ++i) + { + q *= b; + history *= b; + history += series[i]; + } + for (size_t i = k; i < n; ++i) + { + state = history * b + series[i]; + states->histogram[state]++; + history = state - series[i - k]*q; + } +} + +static void accumulate_local_observations(int const* series, size_t n, int b, + size_t k, inform_dist *states, int *state) +{ + k -= 1; + int history = 0; + int q = 1; + for (size_t i = 0; i < k; ++i) + { + q *= b; + history *= b; + history += series[i]; + } + for (size_t i = k; i < n; ++i) + { + size_t l = i - k; + state[l] = history * b + series[i]; + + states->histogram[state[l]]++; + + if (i + 1 != n) + history = state[l] - series[l]*q; + } +} + +static bool check_arguments(int const *series, size_t n, size_t m, int b, + size_t k, inform_error *err) +{ + if (series == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ETIMESERIES, true); + } + else if (n < 1) + { + INFORM_ERROR_RETURN(err, INFORM_ENOINITS, true); + } + else if (m < 2) + { + INFORM_ERROR_RETURN(err, INFORM_ESHORTSERIES, true); + } + else if (b < 2) + { + INFORM_ERROR_RETURN(err, INFORM_EBASE, true); + } + else if (k == 0) + { + INFORM_ERROR_RETURN(err, INFORM_EKZERO, true); + } + else if (m <= k) + { + INFORM_ERROR_RETURN(err, INFORM_EKLONG, true); + } + for (size_t i = 0; i < n * m; ++i) + { + if (series[i] < 0) + { + INFORM_ERROR_RETURN(err, INFORM_ENEGSTATE, true); + } + else if (b <= series[i]) + { + INFORM_ERROR_RETURN(err, INFORM_EBADSTATE, true); + } + } + return false; +} + +double inform_block_entropy(int const *series, size_t n, size_t m, int b, + size_t k, inform_error *err) +{ + if (check_arguments(series, n, m, b, k, err)) return NAN; + + size_t const states_size = (size_t) pow((double) b, (double) k); + + uint32_t *data = calloc(states_size, sizeof(uint32_t)); + if (data == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NAN); + } + + size_t const N = n * (m - k + 1); + + inform_dist states = { data, states_size, N }; + + for (size_t i = 0; i < n; ++i, series += m) + { + accumulate_observations(series, m, b, k, &states); + } + + double be = inform_shannon(&states, (double) b); + + free(data); + + return be; +} + +double *inform_local_block_entropy(int const *series, size_t n, size_t m, int b, + size_t k, double *be, inform_error *err) +{ + if (check_arguments(series, n, m, b, k, err)) return NULL; + + size_t const N = n * (m - k + 1); + + if (be == NULL) + { + be = malloc(N * sizeof(double)); + if (be == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + } + + size_t const states_size = (size_t) pow((double) b, (double) k); + + uint32_t *data = calloc(states_size, sizeof(uint32_t)); + if (data == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + + inform_dist states = { data, states_size, N }; + + int *state = malloc(N * sizeof(int)); + if (state == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + + int const *series_ptr = series; + int *state_ptr = state; + for (size_t i = 0; i < n; ++i) + { + accumulate_local_observations(series_ptr, m, b, k, &states, state_ptr); + series_ptr += m; + state_ptr += (m - k + 1); + } + + for (size_t i = 0; i < N; ++i) + { + be[i] = inform_shannon_si(&states, state[i], (double) b); + } + + free(state); + free(data); + + return be; +} diff --git a/src/dist.c b/src/dist.c index a2883aa..b7435ea 100644 --- a/src/dist.c +++ b/src/dist.c @@ -2,7 +2,6 @@ // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. #include - #include inform_dist* inform_dist_alloc(size_t n) @@ -18,7 +17,7 @@ inform_dist* inform_dist_alloc(size_t n) if (dist != NULL) { // allocate the underlying histogram - dist->histogram = calloc(n, sizeof(uint64_t)); + dist->histogram = calloc(n, sizeof(uint32_t)); // if the allocation succeeded if (dist->histogram != NULL) { @@ -49,7 +48,7 @@ inform_dist* inform_dist_realloc(inform_dist *dist, size_t n) if (dist != NULL && dist->size != n) { // realloc the histogram - uint64_t *histogram = realloc(dist->histogram, n * sizeof(uint64_t)); + uint32_t *histogram = realloc(dist->histogram, n * sizeof(uint32_t)); // if the reallocation succeeded if (histogram != NULL) { @@ -123,7 +122,7 @@ inform_dist* inform_dist_copy(inform_dist const *src, inform_dist *dest) return dest; } // copy the contents of the histogram from the source to the destination - memcpy(dest->histogram, src->histogram, src->size * sizeof(uint64_t)); + memcpy(dest->histogram, src->histogram, src->size * sizeof(uint32_t)); // set the counts appropriately dest->counts = src->counts; // return the modified destination @@ -149,7 +148,7 @@ inform_dist* inform_dist_dup(inform_dist const *dist) return dup; } -inform_dist* inform_dist_create(uint64_t const *data, size_t n) +inform_dist* inform_dist_create(uint32_t const *data, size_t n) { // if the requested support size is zero, return NULL if (n == 0) @@ -162,12 +161,12 @@ inform_dist* inform_dist_create(uint64_t const *data, size_t n) if (dist != NULL) { // allocate the underlying histogram - dist->histogram = calloc(n, sizeof(uint64_t)); + dist->histogram = calloc(n, sizeof(uint32_t)); // if the allocation succeeded if (dist->histogram != NULL) { // set the distribution content, size and counts - memcpy(dist->histogram, data, n*sizeof(uint64_t)); + memcpy(dist->histogram, data, n*sizeof(uint32_t)); dist->size = n; dist->counts = 0; for (size_t i = 0; i < n; ++i) @@ -213,7 +212,7 @@ bool inform_dist_is_valid(inform_dist const *dist) return dist != NULL && dist->size != 0 && dist->counts != 0; } -uint64_t inform_dist_get(inform_dist const *dist, uint64_t event) +uint32_t inform_dist_get(inform_dist const *dist, size_t event) { // if the distribution is NULL or the event is outsize of the support if (dist == NULL || event >= dist->size) @@ -224,7 +223,7 @@ uint64_t inform_dist_get(inform_dist const *dist, uint64_t event) return dist->histogram[event]; } -uint64_t inform_dist_set(inform_dist *dist, uint64_t event, uint64_t x) +uint32_t inform_dist_set(inform_dist *dist, size_t event, uint32_t x) { // if the distribution is NULL or the event is outsize of the support if (dist == NULL || event >= dist->size) @@ -239,7 +238,7 @@ uint64_t inform_dist_set(inform_dist *dist, uint64_t event, uint64_t x) return (dist->histogram[event] = x); } -uint64_t inform_dist_tick(inform_dist *dist, uint64_t event) +uint32_t inform_dist_tick(inform_dist *dist, size_t event) { // if the distribution is NULL or the event is outsize of the support if (dist == NULL || event >= dist->size) @@ -252,14 +251,14 @@ uint64_t inform_dist_tick(inform_dist *dist, uint64_t event) return (dist->histogram[event] += 1); } -static double inform_dist_unsafe_prob(inform_dist const *dist, uint64_t event) +static double inform_dist_unsafe_prob(inform_dist const *dist, size_t event) { // unsafely compute the probability of an event // this will fail if there have been no observations made return (double)(dist->histogram[event]) / dist->counts; } -double inform_dist_prob(inform_dist const *dist, uint64_t event) +double inform_dist_prob(inform_dist const *dist, size_t event) { // if the distribution is NULL, no observations have been made // or the event is outsize of the support @@ -276,15 +275,15 @@ size_t inform_dist_dump(inform_dist const *dist, double *probs, size_t n) // if the distribution is NULL or the event is outsize of the support if (dist == NULL || dist->size == 0) { - return -1; + return 0; } if (probs == NULL) { - return -2; + return 0; } if (n != dist->size) { - return -3; + return 0; } // loop over the events for (size_t i = 0; i < inform_dist_size(dist); ++i) @@ -292,5 +291,5 @@ size_t inform_dist_dump(inform_dist const *dist, double *probs, size_t n) // store their probabilities in the array probs[i] = inform_dist_unsafe_prob(dist,i); } - return n; + return (int) n; } diff --git a/src/entropy_rate.c b/src/entropy_rate.c index 61e7baf..d478361 100644 --- a/src/entropy_rate.c +++ b/src/entropy_rate.c @@ -1,21 +1,20 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include -#include #include +#include -static void accumulate_observations(uint64_t const* series, size_t n, - uint64_t b, uint64_t k, inform_dist *states, inform_dist *histories) +static void accumulate_observations(int const* series, size_t n, + int b, size_t k, inform_dist *states, inform_dist *histories) { - uint64_t history = 0, q = 1, state, future; - for (uint64_t i = 0; i < k; ++i) + int history = 0, q = 1, state, future; + for (size_t i = 0; i < k; ++i) { q *= b; history *= b; history += series[i]; } - for (uint64_t i = k; i < n; ++i) + for (size_t i = k; i < n; ++i) { future = series[i]; state = history * b + future; @@ -27,21 +26,21 @@ static void accumulate_observations(uint64_t const* series, size_t n, } } -static void accumulate_local_observations(uint64_t const* series, size_t n, - uint64_t b, uint64_t k, inform_dist *states, inform_dist *histories, - uint64_t *state, uint64_t *history) +static void accumulate_local_observations(int const* series, size_t n, + int b, size_t k, inform_dist *states, inform_dist *histories, + int *state, int *history) { - uint64_t q = 1; + int q = 1; history[0] = 0; - for (uint64_t i = 0; i < k; ++i) + for (size_t i = 0; i < k; ++i) { q *= b; history[0] *= b; history[0] += series[i]; } - for (uint64_t i = k; i < n; ++i) + for (size_t i = k; i < n; ++i) { - uint64_t l = i - k; + size_t l = i - k; state[l] = history[l] * b + series[i]; states->histogram[state[l]]++; @@ -54,154 +53,136 @@ static void accumulate_local_observations(uint64_t const* series, size_t n, } } -double inform_entropy_rate(uint64_t const *series, size_t n, size_t m, uint64_t b, uint64_t k) +static bool check_arguments(int const *series, size_t n, size_t m, int b, size_t k, inform_error *err) { - // ensure that the time series is not NULL if (series == NULL) { - return inform_nan(1); + INFORM_ERROR_RETURN(err, INFORM_ETIMESERIES, true); } - // ensure that the dimensions of the time series make sense - else if (m <= 1 || n < 1) + else if (n < 1) { - return inform_nan(2); + INFORM_ERROR_RETURN(err, INFORM_ENOINITS, true); } - // ensure that the number of time steps greater than the history length - else if (m <= k) + else if (m < 2) + { + INFORM_ERROR_RETURN(err, INFORM_ESHORTSERIES, true); + } + else if (b < 2) { - return inform_nan(3); + INFORM_ERROR_RETURN(err, INFORM_EBASE, true); } - // ensure that the history length is reasonable given memory constraints - else if (k > 25 / log2((double) b)) + else if (k == 0) { - return inform_nan(4); + INFORM_ERROR_RETURN(err, INFORM_EKZERO, true); + } + else if (m <= k) + { + INFORM_ERROR_RETURN(err, INFORM_EKLONG, true); } - // ensure that the base is compatible with the time series for (size_t i = 0; i < n * m; ++i) { - if (b <= series[i]) + if (series[i] < 0) + { + INFORM_ERROR_RETURN(err, INFORM_ENEGSTATE, true); + } + else if (b <= series[i]) { - return inform_nan(5); + INFORM_ERROR_RETURN(err, INFORM_EBADSTATE, true); } } + return false; +} + +double inform_entropy_rate(int const *series, size_t n, size_t m, int b, + size_t k, inform_error *err) +{ + if (check_arguments(series, n, m, b, k, err)) return NAN; size_t const N = n * (m - k); - // compute the sizes of the histograms size_t const states_size = (size_t) (b * pow((double) b, (double) k)); size_t const histories_size = states_size / b; size_t const total_size = states_size + histories_size; - // allocate memory to store the histograms - uint64_t *data = calloc(total_size, sizeof(uint64_t)); - // ensure that the memory was allocated + uint32_t *data = calloc(total_size, sizeof(uint32_t)); if (data == NULL) { - return inform_nan(6); + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NAN); } - // create the distributions inform_dist states = { data, states_size, N }; inform_dist histories = { data + states_size, histories_size, N }; - // for each initial condition - for (uint64_t i = 0; i < n; ++i, series += m) + for (size_t i = 0; i < n; ++i, series += m) { - // accumulate the observations accumulate_observations(series, m, b, k, &states, &histories); } - // compute the entropy rate double er = inform_shannon_ce(&states, &histories, (double) b); - // free up the data array free(data); - // return the active information return er; } -int inform_local_entropy_rate(uint64_t const *series, size_t n, size_t m, uint64_t b, uint64_t k, double *er) +double *inform_local_entropy_rate(int const *series, size_t n, size_t m, int b, + size_t k, double *er, inform_error *err) { - // ensure that the time series is not NULL - if (series == NULL) - { - return 1; - } - // ensure that the entropy rate array is not NULL - else if (er == NULL) - { - return 2; - } - // ensure that the dimensions of the time series make sense - else if (m <= 1 || n < 1) - { - return 3; - } - // ensure that the number of time steps greater than the history length - else if (m <= k) - { - return 4; - } - // ensure that the history length is reasonable given memory constraints - else if (k > 25 / log2((double) b)) - { - return 5; - } - // ensure that the base is compatible with the time series - for (size_t i = 0; i < n * m; ++i) + if (check_arguments(series, n, m, b, k, err)) return NULL; + + size_t const N = n * (m - k); + + if (er == NULL) { - if (b <= series[i]) + er = malloc(N * sizeof(double)); + if (er == NULL) { - return 6; + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } } - size_t const N = n * (m - k); - - // compute the sizes of the histograms size_t const states_size = (size_t) (b * pow((double) b, (double) k)); size_t const histories_size = states_size / b; size_t const total_size = states_size + histories_size; - // allocate memory to store the histograms - uint64_t *data = calloc(total_size, sizeof(uint64_t)); - // ensure that the memory was allocated + uint32_t *data = calloc(total_size, sizeof(uint32_t)); if (data == NULL) { - return 7; + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } - // create the distributions inform_dist states = { data, states_size, N }; inform_dist histories = { data + states_size, histories_size, N }; - uint64_t *state = malloc(N * sizeof(uint64_t)); - uint64_t *history = malloc(N * sizeof(uint64_t)); + int *state = malloc(N * sizeof(uint64_t)); + if (state == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + int *history = malloc(N * sizeof(uint64_t)); + if (history == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } - // for each initial condition - uint64_t const *series_ptr = series; - uint64_t *state_ptr = state, *history_ptr = history; - for (uint64_t i = 0; i < n; ++i) + int const *series_ptr = series; + int *state_ptr = state, *history_ptr = history; + for (size_t i = 0; i < n; ++i) { - // accumulate the observations - accumulate_local_observations(series_ptr, m, b, k, &states, &histories, - state_ptr, history_ptr); + accumulate_local_observations(series_ptr, m, b, k, &states, &histories, state_ptr, history_ptr); series_ptr += m; state_ptr += (m - k); history_ptr += (m - k); } - // compute the entropy rate for (size_t i = 0; i < N; ++i) { - er[i] = inform_shannon_pce(&states, &histories, state[i], history[i], - (double) b); + er[i] = inform_shannon_pce(&states, &histories, state[i], history[i], (double) b); } - // free up the data array + free(history); + free(state); free(data); - // return the active information - return 0; + return er; } diff --git a/src/error.c b/src/error.c index 84a6da1..6363fba 100644 --- a/src/error.c +++ b/src/error.c @@ -3,38 +3,38 @@ // license that can be found in the LICENSE file. #include -#include - -/// The largest admissable NaN tag -static uint64_t const inform_max_tag = 0x0007ffffffffffff; -/// The binary encoding of the zero-tagged NaN -static uint64_t const inform_raw_nan = 0x7ff8000000000000; - -bool inform_tag_is_valid(uint64_t tag) +bool inform_succeeded(inform_error const *err) { - return tag <= inform_max_tag; + return err == NULL || *err == INFORM_SUCCESS; } -double inform_nan(uint64_t tag) +bool inform_failed(inform_error const *err) { - if (!inform_tag_is_valid(tag)) - { - return -1.; - } - tag ^= inform_raw_nan; - double *nan = (double*)&tag; - return *nan; + return !inform_succeeded(err); } -uint64_t inform_nan_tag(double x) +char const *inform_strerror(inform_error const *err) { - if (!isnan(x)) + if (err == NULL) { - return inform_max_tag + 1; + return "success"; } - else + switch (*err) { - uint64_t *y = (uint64_t*)&x; - return *y ^ inform_raw_nan; + case INFORM_SUCCESS: return "success"; + case INFORM_FAILURE: return "generic failure"; + case INFORM_EFAULT: return "invalid pointer encountered"; + case INFORM_EARG: return "invalid argument provided"; + case INFORM_ENOMEM: return "memory allocation failed"; + case INFORM_ETIMESERIES: return "timeseries is NULL"; + case INFORM_ENOINITS: return "timeseries has no initial conditions"; + case INFORM_ESHORTSERIES: return "timeseries is too short"; + case INFORM_EKZERO: return "history length is zero"; + case INFORM_EKLONG: return "history length is too long"; + case INFORM_EBASE: return "base is invalid"; + case INFORM_ENEGSTATE: return "negative state in timeseries"; + case INFORM_EBADSTATE: return "unexpected state in timeseries"; + case INFORM_EDIST: return "invalid distribution encountered"; + default: return "unrecognized error"; } } diff --git a/src/shannon.c b/src/shannon.c index 4854cbb..6b1a297 100644 --- a/src/shannon.c +++ b/src/shannon.c @@ -4,13 +4,13 @@ #include #include -double inform_shannon_si(inform_dist const *dist, uint64_t event, double base) +double inform_shannon_si(inform_dist const *dist, size_t event, double base) { if (inform_dist_is_valid(dist)) { return -log2(inform_dist_prob(dist, event)) / log2(base); } - return inform_nan(1); + return NAN; } double inform_shannon(inform_dist const *dist, double base) @@ -18,29 +18,31 @@ double inform_shannon(inform_dist const *dist, double base) // ensure that the distribution is valid if (inform_dist_is_valid(dist)) { + // get the size of the distribution's support + size_t const n = inform_dist_size(dist); double h = 0.; // for each element of the distribution's support - for (size_t i = 0; i < inform_dist_size(dist); ++i) + for (size_t i = 0; i < n; ++i) { - // get the probability - double const p = inform_dist_prob(dist, i); - // the the probability is non-zero - if (p != 0) + // the observation_count is non-zero + if (dist->histogram[i] != 0) { + // get the probability + double const p = (double) dist->histogram[i] / dist->counts; // accumulate the weighted self-information of the event - h -= p * log2(p)/log2(base); + h -= p * log2(p); } } // return the entropy - return h; + return h / log2(base); } // return NaN if the distribution is invalid - return inform_nan(1); + return NAN; } double inform_shannon_pmi(inform_dist const *joint, inform_dist const * marginal_x, inform_dist const *marginal_y, - uint64_t event_joint, uint64_t event_x, uint64_t event_y, double base) + size_t event_joint, size_t event_x, size_t event_y, double base) { return inform_shannon_si(marginal_x, event_x, base) + inform_shannon_si(marginal_y, event_y, base) - @@ -50,12 +52,12 @@ double inform_shannon_pmi(inform_dist const *joint, double inform_shannon_mi(inform_dist const *joint, inform_dist const *marginal_x, inform_dist const *marginal_y, double base) { - return inform_shannon(marginal_x,base) + inform_shannon(marginal_y,base) - - inform_shannon(joint,base); + return inform_shannon(marginal_x, base) + inform_shannon(marginal_y, base) + - inform_shannon(joint, base); } double inform_shannon_pce(inform_dist const *joint, inform_dist const *marginal, - uint64_t event_joint,uint64_t event_marginal, double base) + size_t event_joint,size_t event_marginal, double base) { return inform_shannon_si(joint, event_joint, base) - inform_shannon_si(marginal, event_marginal, base); @@ -69,9 +71,9 @@ double inform_shannon_ce(inform_dist const *joint, inform_dist const *marginal, double inform_shannon_pcmi(inform_dist const *joint, inform_dist const *marginal_xz, inform_dist const *marginal_yz, - inform_dist const *marginal_z, uint64_t event_joint, - uint64_t event_marginal_xz, uint64_t event_marginal_yz, - uint64_t event_marginal_z, double base) + inform_dist const *marginal_z, size_t event_joint, + size_t event_marginal_xz, size_t event_marginal_yz, + size_t event_marginal_z, double base) { return inform_shannon_si(marginal_xz, event_marginal_xz, base) + inform_shannon_si(marginal_yz, event_marginal_yz, base) - diff --git a/src/state_encoding.c b/src/state_encoding.c deleted file mode 100644 index 8436152..0000000 --- a/src/state_encoding.c +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2016 ELIFE. All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. -#include - -#include -#include - -uint64_t inform_encode(uint64_t const *state, uint64_t n, uint64_t base) -{ - // if the state is NULL, return an error - if (state == NULL) - { - return INFORM_ENCODING_ERROR(0); - } - // if the base is less than two, return an error - else if (base < 2) - { - return INFORM_ENCODING_ERROR(1); - } - // if the encoding will exceed 63 bits, return an error - else if (n >= (uint64_t) 64 / log2((double) base)) - { - return INFORM_ENCODING_ERROR(2); - } - - uint64_t encoding = 0; - // for each digit - for (uint64_t i = 0; i < n; ++i) - { - // if the digit is too large, return an error - if (base <= state[i]) - { - return INFORM_ENCODING_ERROR(3+i); - } - // otherwise, encode that value - encoding *= base; - encoding += state[i]; - } - // return the encoding - return encoding; -} - -uint64_t* inform_decode(uint64_t encoding, uint64_t n, uint64_t base) -{ - // If the encoding is invalid, the base is too small, or the requested - // decoded length is too large, then return NULL. - if (encoding >= inform_encoding_error || base < 2 || n >= 64 / log2((double) base)) - { - return NULL; - } - // allocate the memory for the decoded state - uint64_t *state = calloc(n, sizeof(uint64_t)); - // if the allocation succeeds - if (state != NULL) - { - // loop over the digits and extract the decoded value - for (uint64_t i = 0; i < n; ++i, encoding /= base) - { - state[n-i-1] = encoding % base; - } - } - // return the (possibly NULL) state - return state; -} diff --git a/src/transfer_entropy.c b/src/transfer_entropy.c index 9e04abb..1cc4abc 100644 --- a/src/transfer_entropy.c +++ b/src/transfer_entropy.c @@ -1,23 +1,21 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include +#include #include -static void accumulate_observations(uint64_t const *series_y, - uint64_t const *series_x, size_t n, uint64_t b, uint64_t k, - inform_dist *states, inform_dist *histories, inform_dist *sources, - inform_dist *predicates) - +static void accumulate_observations(int const *series_y, int const *series_x, + size_t n, int b, size_t k, inform_dist *states, + inform_dist *histories, inform_dist *sources, inform_dist *predicates) { - uint64_t history = 0, q = 1, y_state, future, state, source, predicate; - for (uint64_t i = 0; i < k; ++i) + int history = 0, q = 1, y_state, future, state, source, predicate; + for (size_t i = 0; i < k; ++i) { q *= b; history *= b; history += series_x[i]; } - for (uint64_t i = k; i < n; ++i) + for (size_t i = k; i < n; ++i) { y_state = series_y[i-1]; future = series_x[i]; @@ -34,28 +32,28 @@ static void accumulate_observations(uint64_t const *series_y, } } -static void accumulate_local_observations(uint64_t const *series_y, - uint64_t const *series_x, size_t n, uint64_t b, uint64_t k, +static void accumulate_local_observations(int const *series_y, + int const *series_x, size_t n, int b, size_t k, inform_dist *states, inform_dist *histories, inform_dist *sources, - inform_dist *predicates, uint64_t *state, uint64_t *history, - uint64_t *source, uint64_t *predicate) + inform_dist *predicates, int *state, int *history, + int *source, int *predicate) { history[0] = 0; - uint64_t q = 1; - for (uint64_t i = 0; i < k; ++i) + int q = 1; + for (size_t i = 0; i < k; ++i) { q *= b; history[0] *= b; history[0] += series_x[i]; } - for (uint64_t i = k; i < n; ++i) + for (size_t i = k; i < n; ++i) { - uint64_t l = i - k; - uint64_t y_state = series_y[i-1]; - uint64_t future = series_x[i]; - predicate[l] = history[l] * b + future; - state[l] = predicate[l] * b + y_state; - source[l] = history[l] * b + y_state; + size_t l = i - k; + int y_state = series_y[i-1]; + int future = series_x[i]; + predicate[l] = history[l] * b + future; + state[l] = predicate[l] * b + y_state; + source[l] = history[l] * b + y_state; states->histogram[state[l]]++; histories->histogram[history[l]]++; @@ -69,155 +67,150 @@ static void accumulate_local_observations(uint64_t const *series_y, } } -double inform_transfer_entropy(uint64_t const *node_y, - uint64_t const *node_x, size_t n, size_t m, uint64_t b, uint64_t k) +static bool check_arguments(int const *node_y, int const *node_x, + size_t n, size_t m, int b, size_t k, inform_error *err) { - // ensure that neither of the time series are NULL - if (node_x == NULL || node_y == NULL) + if (node_y == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ETIMESERIES, true); + } + else if (node_x == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ETIMESERIES, true); + } + else if (n < 1) + { + INFORM_ERROR_RETURN(err, INFORM_ENOINITS, true); + } + else if (m < 2) { - return inform_nan(1); + INFORM_ERROR_RETURN(err, INFORM_ESHORTSERIES, true); } - // ensure that the dimensions of the time series make sense - else if (m <= 1 || n < 1) + else if (b < 2) { - return inform_nan(2); + INFORM_ERROR_RETURN(err, INFORM_EBASE, true); } - // ensure that the number of time steps greater than the history length else if (m <= k) { - return inform_nan(3); + INFORM_ERROR_RETURN(err, INFORM_EKLONG, true); } - // ensure that the history is reasonable given the history length - else if (k > 25 / log2((double) b)) + else if (k == 0) { - return inform_nan(4); + INFORM_ERROR_RETURN(err, INFORM_EKZERO, true); } for (size_t i = 0; i < n * m; ++i) { - if (b <= node_x[i] || b <= node_y[i]) + if (b <= node_y[i] || b <= node_x[i]) + { + INFORM_ERROR_RETURN(err, INFORM_EBADSTATE, true); + } + else if (node_y[i] < 0 || node_x[i] < 0) { - return inform_nan(6); + INFORM_ERROR_RETURN(err, INFORM_ENEGSTATE, true); } } + return false; +} + +double inform_transfer_entropy(int const *node_y, int const *node_x, size_t n, + size_t m, int b, size_t k, inform_error *err) +{ + if (check_arguments(node_y, node_x, n, m, b, k, err)) return NAN; - // compute the number of observations to be made size_t const N = n * (m - k); - // compute the sizes of the various histograms size_t const q = (size_t) pow((double) b, (double) k); size_t const states_size = b*b*q; size_t const histories_size = q; size_t const sources_size = b*q; size_t const predicates_size = b*q; - size_t const total_size = states_size + histories_size + sources_size - + predicates_size; + size_t const total_size = states_size + histories_size + sources_size + predicates_size; - // allocate memory to store the basic histograms - uint64_t *data = calloc(total_size, sizeof(uint64_t)); + uint32_t *data = calloc(total_size, sizeof(uint32_t)); if (data == NULL) { - return inform_nan(7); + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NAN); } - // create some pointers to facilitate observation accumulation inform_dist states = { data, states_size, N }; inform_dist histories = { data + states_size, histories_size, N }; inform_dist sources = { data + states_size + histories_size, sources_size, N }; inform_dist predicates = { data + states_size + histories_size + sources_size, predicates_size, N }; - // for each initial condition - for (uint64_t i = 0; i < n; ++i, node_x += m, node_y += m) + for (size_t i = 0; i < n; ++i, node_x += m, node_y += m) { - // accumulate the observations accumulate_observations(node_y, node_x, m, b, k, &states, &histories, &sources, &predicates); } - // compute the transfer entropy from the distributions double te = inform_shannon(&sources, (double) b) + inform_shannon(&predicates, (double) b) - inform_shannon(&states, (double) b) - inform_shannon(&histories, (double) b); - // free up the data array free(data); - // return the transfer entropy return te; } -int inform_local_transfer_entropy(uint64_t const *node_y, - uint64_t const *node_x, size_t n, size_t m, uint64_t b, uint64_t k, - double *te) +double *inform_local_transfer_entropy(int const *node_y, int const *node_x, + size_t n, size_t m, int b, size_t k, double *te, inform_error *err) { - // ensure that neither of the time series are NULL - if (node_x == NULL || node_y == NULL) - { - return 1; - } - // ensure that the transfer entropy array is not NULL - else if (te == NULL) - { - return 2; - } - // ensure that the dimensions of the time series make sense - else if (m <= 1 || n < 1) - { - return 3; - } - // ensure that the number of time steps greater than the history length - else if (m <= k) - { - return 4; - } - // ensure that the history is reasonable given the history length - else if (k > 25 / log2((double) b)) - { - return 5; - } - for (size_t i = 0; i < n * m; ++i) + if (check_arguments(node_y, node_x, n, m, b, k, err)) return NULL; + + size_t const N = n * (m - k); + + if (te == NULL) { - if (b <= node_x[i] || b <= node_y[i]) + te = malloc(N * sizeof(double)); + if (te == NULL) { - return 6; + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } } - // compute the number of observations to be made - size_t const N = n * (m - k); - - // compute the sizes of the various histograms size_t const q = (size_t) pow((double) b, (double) k); size_t const states_size = b*b*q; size_t const histories_size = q; size_t const sources_size = b*q; size_t const predicates_size = b*q; - size_t const total_size = states_size + histories_size + sources_size - + predicates_size; + size_t const total_size = states_size + histories_size + sources_size + predicates_size; - // allocate memory to store the basic histograms - uint64_t *data = calloc(total_size, sizeof(uint64_t)); + uint32_t *data = calloc(total_size, sizeof(uint32_t)); if (data == NULL) { - return 7; + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); } - // create some pointers to facilitate observation accumulation inform_dist states = { data, states_size, N }; inform_dist histories = { data + states_size, histories_size, N }; inform_dist sources = { data + states_size + histories_size, sources_size, N }; inform_dist predicates = { data + states_size + histories_size + sources_size, predicates_size, N }; - uint64_t *state = malloc(N * sizeof(uint64_t)); - uint64_t *history = malloc(N * sizeof(uint64_t)); - uint64_t *source = malloc(N * sizeof(uint64_t)); - uint64_t *predicate = malloc(N * sizeof(uint64_t)); + int *state = malloc(N * sizeof(int)); + if (state == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + int *history = malloc(N * sizeof(int)); + if (history == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + int *source = malloc(N * sizeof(int)); + if (source == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } + int *predicate = malloc(N * sizeof(int)); + if (predicate == NULL) + { + INFORM_ERROR_RETURN(err, INFORM_ENOMEM, NULL); + } - // for each initial condition - uint64_t const *node_y_ptr = node_y, *node_x_ptr = node_x; - uint64_t *state_ptr = state, *source_ptr = source, *history_ptr = history, *predicate_ptr = predicate; - for (uint64_t i = 0; i < n; ++i) + int const *node_y_ptr = node_y, *node_x_ptr = node_x; + int *state_ptr = state, *source_ptr = source, *history_ptr = history, *predicate_ptr = predicate; + for (size_t i = 0; i < n; ++i) { - // accumulate the observations accumulate_local_observations(node_y_ptr, node_x_ptr, m, b, k, &states, &histories, &sources, &predicates, state_ptr, history_ptr, source_ptr, predicate_ptr); @@ -229,20 +222,17 @@ int inform_local_transfer_entropy(uint64_t const *node_y, predicate_ptr += (m - k); } - // compute the transfer entropy from the distributions for (size_t i = 0; i < N; ++i) { te[i] = inform_shannon_pcmi(&states, &sources, &predicates, &histories, state[i], source[i], predicate[i], history[i], (double) b); } - // free up the data array free(predicate); free(source); free(history); free(state); free(data); - // return the transfer entropy - return 0; + return te; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 17bdfe8..9b2d81a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,10 @@ include_directories(unit) add_subdirectory(unittests) add_executable(${PROJECT_NAME}_unittest ${${PROJECT_NAME}_UNITTEST_SOURCES}) -target_link_libraries(${PROJECT_NAME}_unittest ${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME}_unittest ${PROJECT_NAME}_static) +if (UNIX) + target_link_libraries(${PROJECT_NAME}_unittest m) +endif() foreach(UNITTEST_SOURCE ${${PROJECT_NAME}_UNITTEST_SOURCES}) file(STRINGS ${UNITTEST_SOURCE} TEST_NAMES REGEX ^BEGIN_SUITE) diff --git a/test/unit/unit.h b/test/unit/unit.h index 240a0e8..11dcf5d 100644 --- a/test/unit/unit.h +++ b/test/unit/unit.h @@ -14,7 +14,7 @@ struct unit { char const *name; - void (*run)(); + void (*run)(void); }; struct unit_suite @@ -74,12 +74,12 @@ inline static void run_unit_suite(struct unit_suite *suite) #define __FUNCNAME(NAME) __unit_test_##NAME##_body #define __UNITNAME(NAME) __unit_test_##NAME #define UNIT(NAME) \ - static void __FUNCNAME(NAME)(); \ + static void __FUNCNAME(NAME)(void); \ static struct unit __UNITNAME(NAME) = { \ .name = #NAME, \ .run = __FUNCNAME(NAME) \ }; \ - static void __FUNCNAME(NAME)() + static void __FUNCNAME(NAME)(void) #define __SUITENAME(NAME) __unit_suite_##NAME #define BEGIN_SUITE(NAME) \ diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index 25b2a9c..c8de474 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -1,12 +1,11 @@ set(${PROJECT_NAME}_UNITTEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/active_info.c + ${CMAKE_CURRENT_SOURCE_DIR}/block_entropy.c ${CMAKE_CURRENT_SOURCE_DIR}/canary.c ${CMAKE_CURRENT_SOURCE_DIR}/dist.c ${CMAKE_CURRENT_SOURCE_DIR}/entropy_rate.c - ${CMAKE_CURRENT_SOURCE_DIR}/error.c ${CMAKE_CURRENT_SOURCE_DIR}/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/random.c ${CMAKE_CURRENT_SOURCE_DIR}/shannon.c - ${CMAKE_CURRENT_SOURCE_DIR}/state_encoding.c ${CMAKE_CURRENT_SOURCE_DIR}/transfer_entropy.c + ${CMAKE_CURRENT_SOURCE_DIR}/util.c PARENT_SCOPE) diff --git a/test/unittests/active_info.c b/test/unittests/active_info.c index 5e476f1..e486aa8 100644 --- a/test/unittests/active_info.c +++ b/test/unittests/active_info.c @@ -1,125 +1,167 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include -#include +#include "util.h" #include -#include "random.h" +#include +#include -#include +UNIT(ActiveInfoSeriesNULLSeries) +{ + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_active_info(NULL, 1, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); +} -UNIT(ActiveInfoSeriesTooShort) +UNIT(ActiveInfoSeriesNoInits) { - uint64_t const series[] = {1,1,0,0,1,0,0,1}; - ASSERT_TRUE(isnan(inform_active_info(series, 1, 0, 2, 2))); - ASSERT_TRUE(isnan(inform_active_info(series, 1, 1, 2, 2))); + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_active_info(series, 0, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); } -UNIT(ActiveInfoHistoryTooLong) +UNIT(ActiveInfoSeriesTooShort) { - { - uint64_t const series[] = {1,1,0,0,1,0,0,1}; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; - ASSERT_TRUE(isnan(inform_active_info(series, 1, 2, 2, 2))); - ASSERT_FALSE(isnan(inform_active_info(series, 1, 3, 2, 2))); + for (size_t i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_active_info(series, 1, i, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); } +} +UNIT(ActiveInfoHistoryTooLong) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 2; i < 4; ++i) { - size_t const size = 30; - - uint64_t *series = random_series(size, 2); - ASSERT_TRUE(isnan(inform_active_info(series, 1, size, 2, 26))); - free(series); + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_active_info(series, 1, 2, 2, i, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); + } +} - series = random_series(size, 3); - ASSERT_TRUE(isnan(inform_active_info(series, 1, size, 3, 16))); - free(series); +UNIT(ActiveInfoZeroHistory) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_active_info(series, 1, 2, 2, 0, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} - series = random_series(size, 4); - ASSERT_TRUE(isnan(inform_active_info(series, 1, size, 4, 13))); - free(series); +UNIT(ActiveInfoInvalidBase) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_active_info(series, 1, 2, i, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); } } -UNIT(ActiveInfoEncodingError) +UNIT(ActiveInfoNegativeState) { - uint64_t const series[] = {2,1,0,0,1,0,0,1}; - ASSERT_FALSE(isnan(inform_active_info(series, 1, 8, 3, 2))); - ASSERT_TRUE(isnan(inform_active_info(series, 1, 8, 2, 2))); + int const series[] = {-1,1,0,0,1,0,0,1}; + inform_error err; + ASSERT_TRUE(isnan(inform_active_info(series, 1, 8, 3, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); +} + +UNIT(ActiveInfoBadState) +{ + int const series[] = {1,2,0,0,1,0,0,1}; + inform_error err; + ASSERT_TRUE(isnan(inform_active_info(series, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); } UNIT(ActiveInfoSingleSeries_Base2) { ASSERT_DBL_NEAR_TOL(0.918296, - inform_active_info((uint64_t[]){1,1,0,0,1,0,0,1}, 1, 8, 2, 2), + inform_active_info((int[]){1,1,0,0,1,0,0,1}, 1, 8, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_active_info((uint64_t[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2), + inform_active_info((int[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.305958, - inform_active_info((uint64_t[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2), + inform_active_info((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.347458, - inform_active_info((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2), + inform_active_info((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.347458, - inform_active_info((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2), + inform_active_info((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.399533, - inform_active_info((uint64_t[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2), + inform_active_info((int[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.399533, - inform_active_info((uint64_t[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2), + inform_active_info((int[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.305958, - inform_active_info((uint64_t[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2), + inform_active_info((int[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.305958, - inform_active_info((uint64_t[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2), + inform_active_info((int[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.347458, - inform_active_info((uint64_t[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2), + inform_active_info((int[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, NULL), 1e-6); } UNIT(ActiveInfoSingleSeries_Base4) { ASSERT_DBL_NEAR_TOL(0.635471, - inform_active_info((uint64_t[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2), + inform_active_info((int[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.635471, - inform_active_info((uint64_t[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2), + inform_active_info((int[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.234783, - inform_active_info((uint64_t[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2), + inform_active_info((int[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, NULL), 1e-6); } UNIT(ActiveInfoEnsemble) { { - uint64_t series[16] = { + int series[16] = { 1,1,0,0,1,0,0,1, 0,0,0,1,0,0,0,1, }; ASSERT_DBL_NEAR_TOL(0.459148, - inform_active_info(series, 2, 8, 2, 2), + inform_active_info(series, 2, 8, 2, 2, NULL), 1e-6); } { - uint64_t series[81] = { + int series[81] = { 1,0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0,0, 1,0,0,0,0,0,0,1,1, @@ -131,7 +173,7 @@ UNIT(ActiveInfoEnsemble) 0,0,0,0,0,0,1,1,0, }; ASSERT_DBL_NEAR_TOL(0.3080467, - inform_active_info(series, 9, 9, 2, 2), + inform_active_info(series, 9, 9, 2, 2, NULL), 1e-6); } } @@ -139,116 +181,162 @@ UNIT(ActiveInfoEnsemble) UNIT(ActiveInfoEnsemble_Base4) { { - uint64_t series[36] = { + int series[36] = { 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 2, 2, }; ASSERT_DBL_NEAR_TOL(0.662146, - inform_active_info(series, 4, 9, 4, 2), + inform_active_info(series, 4, 9, 4, 2, NULL), 1e-6); } } -#define AVERAGE(XS) average(XS, sizeof(XS) / sizeof(double)) +UNIT(LocalActiveInfoSeriesNULLSeries) +{ + double ai[8]; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_active_info(NULL, 1, 3, 2, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); +} -static double average(double *xs, size_t n) +UNIT(LocalActiveInfoSeriesNoInits) { - double x = 0; - for (size_t i = 0; i < n; ++i) - { - x += xs[i]; - } - return x / n; + double ai[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_active_info(series, 0, 3, 2, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); } UNIT(LocalActiveInfoSeriesTooShort) { double ai[8]; - uint64_t const series[] = {1,1,0,0,1,0,0,1}; - ASSERT_EQUAL(3, inform_local_active_info(series, 1, 0, 2, 2, ai)); - ASSERT_EQUAL(3, inform_local_active_info(series, 1, 1, 2, 2, ai)); + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_active_info(series, 1, i, 2, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); + } } UNIT(LocalActiveInfoHistoryTooLong) { - { - double ai[6]; - uint64_t const series[] = {1,1,0,0,1,0,0,1}; + double ai[6]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; - ASSERT_EQUAL(4, inform_local_active_info(series, 1, 2, 2, 2, ai)); - ASSERT_EQUAL(0, inform_local_active_info(series, 1, 3, 2, 2, ai)); + for (size_t i = 2; i < 4; ++i) + { + ASSERT_NULL(inform_local_active_info(series, 1, 2, 2, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); } +} - { - double ai[30]; - size_t const size = 30; +UNIT(LocalActiveInfoZeroHistory) +{ + double ai[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_active_info(series, 1, 2, 2, 0, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} - uint64_t *series = random_series(size, 2); - ASSERT_EQUAL(5, inform_local_active_info(series, 1, size, 2, 26, ai)); - free(series); +UNIT(LocalActiveInfoInvalidBase) +{ + double ai[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_active_info(series, 1, 2, i, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); + } +} - series = random_series(size, 3); - ASSERT_EQUAL(5, inform_local_active_info(series, 1, size, 3, 16, ai)); - free(series); +UNIT(LocalActiveInfoNegativeState) +{ + double ai[8]; + int const series[] = {-1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; - series = random_series(size, 4); - ASSERT_EQUAL(5, inform_local_active_info(series, 1, size, 4, 13, ai)); - free(series); - } + ASSERT_NULL(inform_local_active_info(series, 1, 8, 2, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); } -UNIT(LocalActiveInfoEncodingError) +UNIT(LocalActiveInfoBadState) { double ai[8]; - uint64_t const series[] = {2,1,0,0,1,0,0,1}; - ASSERT_EQUAL(0, inform_local_active_info(series, 1, 8, 3, 2, ai)); - ASSERT_EQUAL(6, inform_local_active_info(series, 1, 8, 2, 2, ai)); + int const series[] = {2,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_NULL(inform_local_active_info(series, 1, 8, 2, 2, ai, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); +} + +UNIT(LocalActiveInfoAllocatesOutput) +{ + inform_error err = INFORM_SUCCESS; + double *ai = inform_local_active_info((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, NULL, &err); + ASSERT_NOT_NULL(ai); + ASSERT_EQUAL(INFORM_SUCCESS, err); + free(ai); } UNIT(LocalActiveInfoSingleSeries_Base2) { double ai[7] = {0, 0, 0, 0, 0, 0, 0}; - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.305958, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.347458, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.347458, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.399533, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.399533, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.305958, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.305958, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.347458, AVERAGE(ai), 1e-6); } UNIT(LocalActiveInfoSingleSeries_Base4) { double ai[7]; - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.635471, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.635471, AVERAGE(ai), 1e-6); - ASSERT_EQUAL(0, inform_local_active_info((uint64_t[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info((int[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.234783, AVERAGE(ai), 1e-6); } @@ -256,17 +344,17 @@ UNIT(LocalActiveInfoEnsemble) { { double ai[12]; - uint64_t series[16] = { + int series[16] = { 1,1,0,0,1,0,0,1, 0,0,0,1,0,0,0,1, }; - ASSERT_EQUAL(0, inform_local_active_info(series, 2, 8, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info(series, 2, 8, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.459148, AVERAGE(ai), 1e-6); } { double ai[63]; - uint64_t series[81] = { + int series[81] = { 1,0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0,0, 1,0,0,0,0,0,0,1,1, @@ -277,7 +365,7 @@ UNIT(LocalActiveInfoEnsemble) 0,0,0,1,1,1,1,0,0, 0,0,0,0,0,0,1,1,0, }; - ASSERT_EQUAL(0, inform_local_active_info(series, 9, 9, 2, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info(series, 9, 9, 2, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.3080467, AVERAGE(ai), 1e-6); } } @@ -286,28 +374,39 @@ UNIT(LocalActiveInfoEnsemble_Base4) { { double ai[28]; - uint64_t series[36] = { + int series[36] = { 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 2, 2, }; - ASSERT_EQUAL(0, inform_local_active_info(series, 4, 9, 4, 2, ai)); + ASSERT_NOT_NULL(inform_local_active_info(series, 4, 9, 4, 2, ai, NULL)); ASSERT_DBL_NEAR_TOL(0.662146, AVERAGE(ai), 1e-6); } } BEGIN_SUITE(ActiveInformation) + ADD_UNIT(ActiveInfoSeriesNULLSeries) + ADD_UNIT(ActiveInfoSeriesNoInits) ADD_UNIT(ActiveInfoSeriesTooShort) ADD_UNIT(ActiveInfoHistoryTooLong) - ADD_UNIT(ActiveInfoEncodingError) + ADD_UNIT(ActiveInfoZeroHistory) + ADD_UNIT(ActiveInfoInvalidBase) + ADD_UNIT(ActiveInfoNegativeState) + ADD_UNIT(ActiveInfoBadState) ADD_UNIT(ActiveInfoSingleSeries_Base2) ADD_UNIT(ActiveInfoSingleSeries_Base4) ADD_UNIT(ActiveInfoEnsemble) ADD_UNIT(ActiveInfoEnsemble_Base4) + ADD_UNIT(LocalActiveInfoSeriesNULLSeries) + ADD_UNIT(LocalActiveInfoSeriesNoInits) ADD_UNIT(LocalActiveInfoSeriesTooShort) ADD_UNIT(LocalActiveInfoHistoryTooLong) - ADD_UNIT(LocalActiveInfoEncodingError) + ADD_UNIT(LocalActiveInfoZeroHistory) + ADD_UNIT(LocalActiveInfoInvalidBase) + ADD_UNIT(LocalActiveInfoNegativeState) + ADD_UNIT(LocalActiveInfoBadState) + ADD_UNIT(LocalActiveInfoAllocatesOutput) ADD_UNIT(LocalActiveInfoSingleSeries_Base2) ADD_UNIT(LocalActiveInfoSingleSeries_Base4) ADD_UNIT(LocalActiveInfoEnsemble) diff --git a/test/unittests/block_entropy.c b/test/unittests/block_entropy.c new file mode 100644 index 0000000..ec95642 --- /dev/null +++ b/test/unittests/block_entropy.c @@ -0,0 +1,414 @@ +// Copyright 2016 ELIFE. All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. +#include "util.h" +#include +#include +#include + +UNIT(BlockEntropyNULLSeries) +{ + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_block_entropy(NULL, 1, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); +} + +UNIT(BlockEntropyNoInits) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_block_entropy(series, 0, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); +} + +UNIT(BlockEntropySeriesTooShort) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + for (size_t i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_block_entropy(series, 1, i, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); + } +} + +UNIT(BlockEntropyHistoryTooLong) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 2; i < 4; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_block_entropy(series, 1, 2, 2, i, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); + } +} + +UNIT(BlockEntropyZeroHistory) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_block_entropy(series, 1, 2, 2, 0, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} + +UNIT(BlockEntropyInvalidBase) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_block_entropy(series, 1, 2, i, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); + } +} + +UNIT(BlockEntropyNegativeState) +{ + int const series[] = {-1,1,0,0,1,0,0,1}; + inform_error err; + ASSERT_TRUE(isnan(inform_block_entropy(series, 1, 8, 3, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); +} + +UNIT(BlockEntropyBadState) +{ + int const series[] = {1,2,0,0,1,0,0,1}; + inform_error err; + ASSERT_TRUE(isnan(inform_block_entropy(series, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); +} + +UNIT(BlockEntropySingleSeries_Base2) +{ + ASSERT_DBL_NEAR_TOL(1.950212, + inform_block_entropy((int[]){1,1,0,0,1,0,0,1}, 1, 8, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(0.543564, + inform_block_entropy((int[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.811278, + inform_block_entropy((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.548795, + inform_block_entropy((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.548795, + inform_block_entropy((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.548795, + inform_block_entropy((int[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.548795, + inform_block_entropy((int[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.811278, + inform_block_entropy((int[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.811278, + inform_block_entropy((int[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.548795, + inform_block_entropy((int[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, NULL), + 1e-6); +} + +UNIT(BlockEntropySingleSeries_Base4) +{ + ASSERT_DBL_NEAR_TOL(1.250000, + inform_block_entropy((int[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(1.202820, + inform_block_entropy((int[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, NULL), + 1e-6); + + ASSERT_DBL_NEAR_TOL(0.649397, + inform_block_entropy((int[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, NULL), + 1e-6); +} + +UNIT(BlockEntropyEnsemble) +{ + { + int series[16] = { + 1,1,0,0,1,0,0,1, + 0,0,0,1,0,0,0,1, + }; + ASSERT_DBL_NEAR_TOL(1.788450, + inform_block_entropy(series, 2, 8, 2, 2, NULL), + 1e-6); + } + + { + int series[81] = { + 1,0,0,0,0,0,0,0,0, + 0,0,1,1,1,1,0,0,0, + 1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,1,1, + 0,0,0,0,0,1,1,0,0, + 0,0,0,0,1,1,0,0,0, + 1,1,1,0,0,0,0,1,1, + 0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,0, + }; + ASSERT_DBL_NEAR_TOL(1.649204, + inform_block_entropy(series, 9, 9, 2, 2, NULL), + 1e-6); + } +} + +UNIT(BlockEntropyEnsemble_Base4) +{ + { + int series[36] = { + 3, 3, 3, 2, 1, 0, 0, 0, 1, + 2, 2, 3, 3, 3, 3, 2, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 2, 2, + }; + ASSERT_DBL_NEAR_TOL(1.505488, + inform_block_entropy(series, 4, 9, 4, 2, NULL), + 1e-6); + } +} + +UNIT(LocalBlockEntropyNULLSeries) +{ + double be[8]; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_block_entropy(NULL, 1, 3, 2, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); +} + +UNIT(LocalBlockEntropyNoInits) +{ + double be[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_block_entropy(series, 0, 3, 2, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); +} + +UNIT(LocalBlockEntropySeriesTooShort) +{ + double be[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_block_entropy(series, 1, i, 2, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); + } +} + +UNIT(LocalBlockEntropyHistoryTooLong) +{ + double be[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + for (size_t i = 2; i < 4; ++i) + { + ASSERT_NULL(inform_local_block_entropy(series, 1, 2, 2, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); + } +} + +UNIT(LocalBlockEntropyZeroHistory) +{ + double be[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_block_entropy(series, 1, 2, 2, 0, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} + +UNIT(LocalBlockEntropyInvalidBase) +{ + double be[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_block_entropy(series, 1, 2, i, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); + } +} + +UNIT(LocalBlockEntropyNegativeState) +{ + double be[8]; + int const series[] = {-1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_NULL(inform_local_block_entropy(series, 1, 8, 2, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); +} + +UNIT(LocalBlockEntropyBadState) +{ + double be[8]; + int const series[] = {2,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_NULL(inform_local_block_entropy(series, 1, 8, 2, 2, be, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); +} + +UNIT(LocalBlockEntropyAllocatesOutput) +{ + inform_error err = INFORM_SUCCESS; + double *be = inform_local_block_entropy((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, NULL, &err); + ASSERT_NOT_NULL(be); + ASSERT_EQUAL(INFORM_SUCCESS, err); + free(be); +} + +UNIT(LocalBlockEntropySingleSeries_Base2) +{ + double be[8] = {0, 0, 0, 0, 0, 0, 0}; + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(0.543564, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.811278, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.548795, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.548795, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.548795, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.548795, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.811278, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.811278, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.548795, AVERAGE(be), 1e-6); +} + +UNIT(LocalBlockEntropySingleSeries_Base4) +{ + double be[8]; + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.250000, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.202820, AVERAGE(be), 1e-6); + + ASSERT_NOT_NULL(inform_local_block_entropy((int[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(0.649397, AVERAGE(be), 1e-6); +} + +UNIT(LocalBlockEntropyEnsemble) +{ + { + double be[14]; + int series[16] = { + 1,1,0,0,1,0,0,1, + 0,0,0,1,0,0,0,1, + }; + ASSERT_NOT_NULL(inform_local_block_entropy(series, 2, 8, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.788450, AVERAGE(be), 1e-6); + } + + { + double be[72]; + int series[81] = { + 1,0,0,0,0,0,0,0,0, + 0,0,1,1,1,1,0,0,0, + 1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,1,1, + 0,0,0,0,0,1,1,0,0, + 0,0,0,0,1,1,0,0,0, + 1,1,1,0,0,0,0,1,1, + 0,0,0,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,0, + }; + ASSERT_NOT_NULL(inform_local_block_entropy(series, 9, 9, 2, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.649204, AVERAGE(be), 1e-6); + } +} + +UNIT(LocalBlockEntropyEnsemble_Base4) +{ + { + double be[32]; + int series[36] = { + 3, 3, 3, 2, 1, 0, 0, 0, 1, + 2, 2, 3, 3, 3, 3, 2, 1, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 1, 1, 2, 2, + }; + ASSERT_NOT_NULL(inform_local_block_entropy(series, 4, 9, 4, 2, be, NULL)); + ASSERT_DBL_NEAR_TOL(1.505488, AVERAGE(be), 1e-6); + } +} + +BEGIN_SUITE(BlockEntropy) + ADD_UNIT(BlockEntropyNULLSeries) + ADD_UNIT(BlockEntropyNoInits) + ADD_UNIT(BlockEntropySeriesTooShort) + ADD_UNIT(BlockEntropyHistoryTooLong) + ADD_UNIT(BlockEntropyZeroHistory) + ADD_UNIT(BlockEntropyInvalidBase) + ADD_UNIT(BlockEntropyNegativeState) + ADD_UNIT(BlockEntropyBadState) + ADD_UNIT(BlockEntropySingleSeries_Base2) + ADD_UNIT(BlockEntropySingleSeries_Base4) + ADD_UNIT(BlockEntropyEnsemble) + ADD_UNIT(BlockEntropyEnsemble_Base4) + ADD_UNIT(LocalBlockEntropyNULLSeries) + ADD_UNIT(LocalBlockEntropyNoInits) + ADD_UNIT(LocalBlockEntropySeriesTooShort) + ADD_UNIT(LocalBlockEntropyHistoryTooLong) + ADD_UNIT(LocalBlockEntropyZeroHistory) + ADD_UNIT(LocalBlockEntropyInvalidBase) + ADD_UNIT(LocalBlockEntropyNegativeState) + ADD_UNIT(LocalBlockEntropyBadState) + ADD_UNIT(LocalBlockEntropyAllocatesOutput) + ADD_UNIT(LocalBlockEntropySingleSeries_Base2) + ADD_UNIT(LocalBlockEntropySingleSeries_Base4) + ADD_UNIT(LocalBlockEntropyEnsemble) + ADD_UNIT(LocalBlockEntropyEnsemble_Base4) +END_SUITE diff --git a/test/unittests/dist.c b/test/unittests/dist.c index 908f953..0cb0a81 100644 --- a/test/unittests/dist.c +++ b/test/unittests/dist.c @@ -62,7 +62,7 @@ UNIT(Set) ASSERT_EQUAL(3, inform_dist_size(dist)); ASSERT_EQUAL(6, inform_dist_counts(dist)); - for (uint64_t i = 0; i < inform_dist_size(dist); ++i) + for (size_t i = 0; i < inform_dist_size(dist); ++i) { inform_dist_set(dist, i, 0); } @@ -110,7 +110,7 @@ UNIT(ReallocGrow) ASSERT_NOT_NULL(dist); for (size_t i = 0; i < inform_dist_size(dist); ++i) { - inform_dist_set(dist, i, i+1); + inform_dist_set(dist, i, (uint32_t) i+1); } ASSERT_EQUAL(3, inform_dist_size(dist)); ASSERT_EQUAL(6, inform_dist_counts(dist)); @@ -137,7 +137,7 @@ UNIT(ReallocShrink) ASSERT_NOT_NULL(dist); for (size_t i = 0; i < inform_dist_size(dist); ++i) { - inform_dist_set(dist, i, i+1); + inform_dist_set(dist, i, (uint32_t) i+1); } ASSERT_EQUAL(5, inform_dist_size(dist)); ASSERT_EQUAL(15, inform_dist_counts(dist)); @@ -168,7 +168,7 @@ UNIT(CopyToNULL) ASSERT_NOT_NULL(source); for (size_t i = 0; i < inform_dist_size(source); ++i) { - inform_dist_set(source, i, i+1); + inform_dist_set(source, i, (uint32_t) i+1); } inform_dist *dest = NULL; ASSERT_NULL(dest); @@ -198,7 +198,7 @@ UNIT(CopySameSize) inform_dist *source = inform_dist_alloc(3); for (size_t i = 0; i < inform_dist_size(source); ++i) { - inform_dist_set(source, i, i+1); + inform_dist_set(source, i, (uint32_t) i+1); } inform_dist *dest = inform_dist_alloc(3); @@ -222,7 +222,7 @@ UNIT(CopyResize) inform_dist *source = inform_dist_alloc(3); for (size_t i = 0; i < inform_dist_size(source); ++i) { - inform_dist_set(source, i, i+1); + inform_dist_set(source, i, (uint32_t) i+1); } inform_dist *dest = inform_dist_alloc(5); @@ -254,7 +254,7 @@ UNIT(Dup) ASSERT_NOT_NULL(dist); for (size_t i = 0; i < inform_dist_size(dist); ++i) { - inform_dist_set(dist, i, i*i); + inform_dist_set(dist, i, (uint32_t) (i*i)); } inform_dist *dup = inform_dist_dup(dist); ASSERT_NOT_NULL(dup); @@ -302,7 +302,7 @@ UNIT(Prob) for (size_t i = 0; i < inform_dist_size(dist); ++i) { - inform_dist_set(dist, i, i+1); + inform_dist_set(dist, i, (uint32_t) i+1); } ASSERT_EQUAL(15, inform_dist_counts(dist)); for (size_t i = 0; i < inform_dist_size(dist); ++i) @@ -316,22 +316,22 @@ UNIT(Prob) UNIT(Dump) { inform_dist *dist = NULL; - ASSERT_EQUAL(-1, inform_dist_dump(dist, NULL, 0)); + ASSERT_EQUAL(0, inform_dist_dump(dist, NULL, 0)); dist = inform_dist_alloc(5); ASSERT_NOT_NULL(dist); - ASSERT_EQUAL(-2, inform_dist_dump(dist, NULL, 0)); + ASSERT_EQUAL(0, inform_dist_dump(dist, NULL, 0)); for (size_t i = 1; i < inform_dist_size(dist); ++i) { - inform_dist_set(dist, i, i+1); + inform_dist_set(dist, i, (uint32_t) i+1); } ASSERT_EQUAL(14, inform_dist_counts(dist)); double expect[5] = {0., 2./14, 3./14, 4./14, 5./14}; double got[7] = {0., 0., 0., 0., 0., 0.}; - ASSERT_EQUAL(-3, inform_dist_dump(dist, got, 4)); - ASSERT_EQUAL(-3, inform_dist_dump(dist, got, 6)); + ASSERT_EQUAL(0, inform_dist_dump(dist, got, 4)); + ASSERT_EQUAL(0, inform_dist_dump(dist, got, 6)); ASSERT_EQUAL(5, inform_dist_dump(dist, got, 5)); for (size_t i = 0; i < inform_dist_size(dist); ++i) { diff --git a/test/unittests/entropy_rate.c b/test/unittests/entropy_rate.c index 8efd76d..6401454 100644 --- a/test/unittests/entropy_rate.c +++ b/test/unittests/entropy_rate.c @@ -1,135 +1,169 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include -#include +#include "util.h" #include -#include "random.h" - -#define AVERAGE(XS) average(XS, sizeof(XS) / sizeof(double)) +#include +#include -static double average(double *xs, size_t n) +UNIT(EntropyRateNULLSeries) { - double x = 0; - for (size_t i = 0; i < n; ++i) - { - x += xs[i]; - } - return x / n; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_entropy_rate(NULL, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); } -UNIT(EntropyRateSeriesTooShort) +UNIT(EntropyRateNoInits) { - uint64_t const series[] = {1,1,0,0,1,0,0,1}; - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 0, 2, 2))); - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 1, 2, 2))); + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_entropy_rate(series, 0, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); } -UNIT(EntropyRateHistoryTooLong) +UNIT(EntropyRateSeriesTooShort) { + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + for (size_t i = 0; i < 2; ++i) { - uint64_t const series[] = {1,1,0,0,1,0,0,1}; - - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 2, 2, 2))); - ASSERT_FALSE(isnan(inform_entropy_rate(series, 1, 3, 2, 2))); + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, i, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); } +} +UNIT(EntropyRateInvalidBase) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + for (int i = 0; i < 2; ++i) { - size_t const size = 30; + ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 2, i, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); + } +} - uint64_t *series = random_series(size, 2); - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, size, 2, 26))); - free(series); +UNIT(EntropyRateZeroHistory) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 2, 2, 0, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} - series = random_series(size, 3); - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, size, 3, 16))); - free(series); +UNIT(EntropyRateHistoryTooLong) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; - series = random_series(size, 4); - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, size, 4, 13))); - free(series); + for (size_t i = 2; i < 4; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 2, 2, i, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); } } -UNIT(EntropyRateEncodingError) +UNIT(EntropyRateNegativeState) { - uint64_t const series[] = {2,1,0,0,1,0,0,1}; - ASSERT_FALSE(isnan(inform_entropy_rate(series, 1, 8, 3, 2))); - ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 8, 2, 2))); + int const series[] = {-1,1,0,0,1,0,0,1}; + inform_error err; + ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 8, 3, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); +} + +UNIT(EntropyRateBadState) +{ + int const series[] = {1,2,0,0,1,0,0,1}; + inform_error err; + ASSERT_TRUE(isnan(inform_entropy_rate(series, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); } UNIT(EntropyRateSingleSeries_Base2) { ASSERT_DBL_NEAR_TOL(0.000000, - inform_entropy_rate((uint64_t[]){1,1,0,0,1,0,0,1}, 1, 8, 2, 2), + inform_entropy_rate((int[]){1,1,0,0,1,0,0,1}, 1, 8, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_entropy_rate((uint64_t[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2), + inform_entropy_rate((int[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.679270, - inform_entropy_rate((uint64_t[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2), + inform_entropy_rate((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.515663, - inform_entropy_rate((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2), + inform_entropy_rate((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.515663, - inform_entropy_rate((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2), + inform_entropy_rate((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.463587, - inform_entropy_rate((uint64_t[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2), + inform_entropy_rate((int[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.463587, - inform_entropy_rate((uint64_t[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2), + inform_entropy_rate((int[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.679270, - inform_entropy_rate((uint64_t[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2), + inform_entropy_rate((int[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.679270, - inform_entropy_rate((uint64_t[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2), + inform_entropy_rate((int[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.515663, - inform_entropy_rate((uint64_t[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2), + inform_entropy_rate((int[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, NULL), 1e-6); } UNIT(EntropyRateSingleSeries_Base4) { ASSERT_DBL_NEAR_TOL(0.285715, - inform_entropy_rate((uint64_t[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2), + inform_entropy_rate((int[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.196778, - inform_entropy_rate((uint64_t[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2), + inform_entropy_rate((int[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.257831, - inform_entropy_rate((uint64_t[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2), + inform_entropy_rate((int[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, NULL), 1e-6); } UNIT(EntropyRateEnsemble) { { - uint64_t series[16] = { + int series[16] = { 1,1,0,0,1,0,0,1, 0,0,0,1,0,0,0,1, }; ASSERT_DBL_NEAR_TOL(0.459148, - inform_entropy_rate(series, 2, 8, 2, 2), + inform_entropy_rate(series, 2, 8, 2, 2, NULL), 1e-6); } { - uint64_t series[81] = { + int series[81] = { 1,0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0,0, 1,0,0,0,0,0,0,1,1, @@ -141,7 +175,7 @@ UNIT(EntropyRateEnsemble) 0,0,0,0,0,0,1,1,0, }; ASSERT_DBL_NEAR_TOL(0.610249, - inform_entropy_rate(series, 9, 9, 2, 2), + inform_entropy_rate(series, 9, 9, 2, 2, NULL), 1e-6); } } @@ -149,90 +183,149 @@ UNIT(EntropyRateEnsemble) UNIT(EntropyRateEnsemble_Base4) { { - uint64_t series[36] = { + int series[36] = { 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 2, 2, }; ASSERT_DBL_NEAR_TOL(0.272234, - inform_entropy_rate(series, 4, 9, 4, 2), + inform_entropy_rate(series, 4, 9, 4, 2, NULL), 1e-6); } } +UNIT(LocalEntropyRateNULLSeries) +{ + double er[8]; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_entropy_rate(NULL, 1, 3, 2, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); +} + +UNIT(LocalEntropyRateNoInits) +{ + double er[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_entropy_rate(series, 0, 3, 2, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); +} + UNIT(LocalEntropyRateSeriesTooShort) { - double er[6]; - uint64_t const series[] = {1,1,0,0,1,0,0,1}; - ASSERT_EQUAL(3, inform_local_entropy_rate(series, 1, 0, 2, 2, er)); - ASSERT_EQUAL(3, inform_local_entropy_rate(series, 1, 1, 2, 2, er)); + double er[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_entropy_rate(series, 1, i, 2, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); + } } UNIT(LocalEntropyRateHistoryTooLong) { - { - double er[6]; - uint64_t const series[] = {1,1,0,0,1,0,0,1}; + double er[6]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; - ASSERT_EQUAL(4, inform_local_entropy_rate(series, 1, 2, 2, 2, er)); - ASSERT_EQUAL(0, inform_local_entropy_rate(series, 1, 3, 2, 2, er)); + for (size_t i = 2; i < 4; ++i) + { + ASSERT_NULL(inform_local_entropy_rate(series, 1, 2, 2, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); } +} +UNIT(LocalEntropyRateZeroHistory) +{ + double er[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_entropy_rate(series, 1, 2, 2, 0, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} + +UNIT(LocalEntropyRateInvalidBase) +{ + double er[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) { - size_t const size = 30; + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_entropy_rate(series, 1, 2, i, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); + } +} - double er[30]; - uint64_t *series = random_series(size, 2); - ASSERT_EQUAL(5, inform_local_entropy_rate(series, 1, size, 2, 26, er)); - free(series); +UNIT(LocalEntropyRateNegativeState) +{ + double er[8]; + int const series[] = {-1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; - series = random_series(size, 3); - ASSERT_EQUAL(5, inform_local_entropy_rate(series, 1, size, 3, 16, er)); - free(series); + ASSERT_NULL(inform_local_entropy_rate(series, 1, 8, 2, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); +} - series = random_series(size, 4); - ASSERT_EQUAL(5, inform_local_entropy_rate(series, 1, size, 4, 13, er)); - free(series); - } +UNIT(LocalEntropyRateBadState) +{ + double er[8]; + int const series[] = {2,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_NULL(inform_local_entropy_rate(series, 1, 8, 2, 2, er, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); } -UNIT(LocalEntropyRateEncodingError) + +UNIT(LocalEntropyRateAllocatesOutput) { - double er[6]; - uint64_t const series[] = {2,1,0,0,1,0,0,1}; - ASSERT_EQUAL(0, inform_local_entropy_rate(series, 1, 8, 3, 2, er)); - ASSERT_EQUAL(6, inform_local_entropy_rate(series, 1, 8, 2, 2, er)); + inform_error err = INFORM_SUCCESS; + double *er = inform_local_entropy_rate((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, NULL, &err); + ASSERT_NOT_NULL(er); + ASSERT_EQUAL(INFORM_SUCCESS, err); + free(er); } UNIT(LocalEntropyRateSingleSeries_Base2) { double er[7]; - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){1,0,0,0,0,0,0,0,0}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){0,0,1,1,1,1,0,0,0}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.679270, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.515663, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){1,0,0,0,0,0,0,1,1}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.515663, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){0,0,0,0,0,1,1,0,0}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.463587, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){0,0,0,0,1,1,0,0,0}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.463587, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){1,1,1,0,0,0,0,1,1}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.679270, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){0,0,0,1,1,1,1,0,0}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.679270, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){0,0,0,0,0,0,1,1,0}, 1, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.515663, AVERAGE(er), 1e-6); } @@ -240,13 +333,13 @@ UNIT(LocalEntropyRateSingleSeries_Base4) { double er[7]; - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){3,3,3,2,1,0,0,0,1}, 1, 9, 4, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.285715, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){2,2,3,3,3,3,2,1,0}, 1, 9, 4, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.196778, AVERAGE(er), 1e-6); - ASSERT_EQUAL(0, inform_local_entropy_rate((uint64_t[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate((int[]){2,2,2,2,2,2,1,1,1}, 1, 9, 4, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.257831, AVERAGE(er), 1e-6); } @@ -254,17 +347,17 @@ UNIT(LocalEntropyRateEnsemble) { { double er[12]; - uint64_t series[16] = { + int series[16] = { 1,1,0,0,1,0,0,1, 0,0,0,1,0,0,0,1, }; - ASSERT_EQUAL(0, inform_local_entropy_rate(series, 2, 8, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate(series, 2, 8, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.459148, AVERAGE(er), 1e-6); } { double er[63]; - uint64_t series[81] = { + int series[81] = { 1,0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0,0, 1,0,0,0,0,0,0,1,1, @@ -275,7 +368,7 @@ UNIT(LocalEntropyRateEnsemble) 0,0,0,1,1,1,1,0,0, 0,0,0,0,0,0,1,1,0, }; - ASSERT_EQUAL(0, inform_local_entropy_rate(series, 9, 9, 2, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate(series, 9, 9, 2, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.610249, AVERAGE(er), 1e-6); } } @@ -284,28 +377,39 @@ UNIT(LocalEntropyRateEnsemble_Base4) { { double er[28]; - uint64_t series[36] = { + int series[36] = { 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 2, 2, }; - ASSERT_EQUAL(0, inform_local_entropy_rate(series, 4, 9, 4, 2, er)); + ASSERT_NOT_NULL(inform_local_entropy_rate(series, 4, 9, 4, 2, er, NULL)); ASSERT_DBL_NEAR_TOL(0.272234, AVERAGE(er), 1e-6); } } BEGIN_SUITE(EntropyRate) + ADD_UNIT(EntropyRateNULLSeries) + ADD_UNIT(EntropyRateNoInits) ADD_UNIT(EntropyRateSeriesTooShort) + ADD_UNIT(EntropyRateInvalidBase) + ADD_UNIT(EntropyRateZeroHistory) ADD_UNIT(EntropyRateHistoryTooLong) - ADD_UNIT(EntropyRateEncodingError) + ADD_UNIT(EntropyRateNegativeState) + ADD_UNIT(EntropyRateBadState) ADD_UNIT(EntropyRateSingleSeries_Base2) ADD_UNIT(EntropyRateSingleSeries_Base4) ADD_UNIT(EntropyRateEnsemble) ADD_UNIT(EntropyRateEnsemble_Base4) + ADD_UNIT(LocalEntropyRateNULLSeries) + ADD_UNIT(LocalEntropyRateNoInits) ADD_UNIT(LocalEntropyRateSeriesTooShort) + ADD_UNIT(LocalEntropyRateInvalidBase) + ADD_UNIT(LocalEntropyRateZeroHistory) ADD_UNIT(LocalEntropyRateHistoryTooLong) - ADD_UNIT(LocalEntropyRateEncodingError) + ADD_UNIT(LocalEntropyRateNegativeState) + ADD_UNIT(LocalEntropyRateBadState) + ADD_UNIT(LocalEntropyRateAllocatesOutput) ADD_UNIT(LocalEntropyRateSingleSeries_Base2) ADD_UNIT(LocalEntropyRateSingleSeries_Base4) ADD_UNIT(LocalEntropyRateEnsemble) diff --git a/test/unittests/error.c b/test/unittests/error.c deleted file mode 100644 index 6d13c24..0000000 --- a/test/unittests/error.c +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 ELIFE. All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. -#include - -#include -#include -#include - -UNIT(TagNaN) -{ - double x = inform_nan(0); - uint64_t *y = (uint64_t*)&x; - - ASSERT_TRUE(isnan(x)); - ASSERT_EQUAL_U(0x7ff8000000000000, *y); - - x = inform_nan(1); - ASSERT_TRUE(isnan(x)); - ASSERT_EQUAL_U(0x7ff8000000000001, *y); - - x = inform_nan(2); - ASSERT_TRUE(isnan(x)); - ASSERT_EQUAL_U(0x7ff8000000000002, *y); - - x = inform_nan(15); - ASSERT_TRUE(isnan(x)); - ASSERT_EQUAL_U(0x7ff800000000000f, *y); - - x = inform_nan(255); - ASSERT_TRUE(isnan(x)); - ASSERT_EQUAL_U(0x7ff80000000000ff, *y); - - x = inform_nan(2251799813685247); - ASSERT_TRUE(isnan(x)); - ASSERT_EQUAL_U(0x7fffffffffffffff, *y); - - x = inform_nan(2251799813685248); - ASSERT_FALSE(isnan(x)); - ASSERT_EQUAL_U(0xbff0000000000000, *y); -} - -UNIT(NaNTag) -{ - for (uint64_t x = 0; x <= 0xffff; ++x) - { - ASSERT_EQUAL_U(x, inform_nan_tag(inform_nan(x))); - } - - ASSERT_FALSE(inform_tag_is_valid(inform_nan_tag(0))); -} - -BEGIN_SUITE(Error) - ADD_UNIT(TagNaN) - ADD_UNIT(NaNTag) -END_SUITE diff --git a/test/unittests/main.c b/test/unittests/main.c index 8a96c8c..b923302 100644 --- a/test/unittests/main.c +++ b/test/unittests/main.c @@ -4,22 +4,20 @@ #include IMPORT_SUITE(ActiveInformation); +IMPORT_SUITE(BlockEntropy); IMPORT_SUITE(Canary); IMPORT_SUITE(Distribution); IMPORT_SUITE(Entropy); IMPORT_SUITE(EntropyRate); -IMPORT_SUITE(Error); -IMPORT_SUITE(StateEncoding); IMPORT_SUITE(TransferEntropy); BEGIN_REGISTRATION REGISTER(ActiveInformation) + REGISTER(BlockEntropy) REGISTER(Canary) REGISTER(Distribution) REGISTER(Entropy) REGISTER(EntropyRate) - REGISTER(Error) - REGISTER(StateEncoding) REGISTER(TransferEntropy) END_REGISTRATION diff --git a/test/unittests/shannon.c b/test/unittests/shannon.c index e982f68..f1c282f 100644 --- a/test/unittests/shannon.c +++ b/test/unittests/shannon.c @@ -7,13 +7,13 @@ #define inform_dist_fill_array(dist, array) \ ASSERT_NOT_NULL(dist); \ - ASSERT_EQUAL(sizeof(array)/sizeof(uint64_t), inform_dist_size(dist)); \ + ASSERT_EQUAL(sizeof(array)/sizeof(int), inform_dist_size(dist)); \ for (size_t i = 0; i < inform_dist_size(dist); ++i) \ { \ inform_dist_set(dist, i, array[i]); \ } -#define inform_dist_fill(dist, ...) inform_dist_fill_array(dist, ((uint64_t[]){__VA_ARGS__})) +#define inform_dist_fill(dist, ...) inform_dist_fill_array(dist, ((int[]){__VA_ARGS__})) UNIT(ShannonInvalidDistribution) { diff --git a/test/unittests/state_encoding.c b/test/unittests/state_encoding.c deleted file mode 100644 index 774b6a1..0000000 --- a/test/unittests/state_encoding.c +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2016 ELIFE. All rights reserved. -// Use of this source code is governed by a MIT -// license that can be found in the LICENSE file. -#include - -#include -#include - -UNIT(EncodeNULL) -{ - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(0), inform_encode(NULL,0,2)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(0), inform_encode(NULL,1,2)); -} - -UNIT(EncodeInvalidBase) -{ - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(1), inform_encode((uint64_t[]){0},1, 0)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(1), inform_encode((uint64_t[]){0},1, 1)); -} - -UNIT(EncodeTooLong_Base2) -{ - uint64_t *ones = calloc(63, sizeof(uint64_t)); - for (size_t i = 0; i < 63; ++i) ones[i] = 1; - ASSERT_EQUAL_U(0x7fffffffffffffff, inform_encode(ones,63,2)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(2), inform_encode(ones,64,2)); - free(ones); -} - -UNIT(EncodeTooLong_Base3) -{ - uint64_t *twos = calloc(40, sizeof(uint64_t)); - for (size_t i = 0; i < 40; ++i) twos[i] = 2; - ASSERT_EQUAL_U(0xa8b8b452291fe820, inform_encode(twos,40,3)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(2), inform_encode(twos,41,3)); - free(twos); -} - -UNIT(EncodeTooLong_Base4) -{ - uint64_t *threes = calloc(31, sizeof(uint64_t)); - for (size_t i = 0; i < 31; ++i) threes[i] = 3; - ASSERT_EQUAL_U(0x3fffffffffffffff, inform_encode(threes,31,4)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(2), inform_encode(threes,32,4)); - free(threes); -} - -UNIT(EncodeTooLong_Base5) -{ - uint64_t *fours = calloc(27, sizeof(uint64_t)); - for (size_t i = 0; i < 27; ++i) fours[i] = 4; - ASSERT_EQUAL_U(0x6765c793fa10079c, inform_encode(fours,27,5)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(2), inform_encode(fours,28,5)); - free(fours); -} - -UNIT(EncodeLengthOne_Base2) -{ - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0},1,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){1},1,2)); - - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,0},1,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){1,0},1,2)); - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,1},1,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){1,1},1,2)); -} - -UNIT(EncodeLengthOne_Base5) -{ - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0},1,5)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){1},1,5)); - ASSERT_EQUAL_U(2, inform_encode((uint64_t[]){2},1,5)); - ASSERT_EQUAL_U(3, inform_encode((uint64_t[]){3},1,5)); - ASSERT_EQUAL_U(4, inform_encode((uint64_t[]){4},1,5)); - - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,1},1,5)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){1,1},1,5)); - ASSERT_EQUAL_U(2, inform_encode((uint64_t[]){2,1},1,5)); - ASSERT_EQUAL_U(3, inform_encode((uint64_t[]){3,1},1,5)); - ASSERT_EQUAL_U(4, inform_encode((uint64_t[]){4,1},1,5)); -} - -UNIT(EncodeLengthTwo_Base2) -{ - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,0},2,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){0,1},2,2)); - ASSERT_EQUAL_U(2, inform_encode((uint64_t[]){1,0},2,2)); - ASSERT_EQUAL_U(3, inform_encode((uint64_t[]){1,1},2,2)); - - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,0,0},2,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){0,1,0},2,2)); - ASSERT_EQUAL_U(2, inform_encode((uint64_t[]){1,0,0},2,2)); - ASSERT_EQUAL_U(3, inform_encode((uint64_t[]){1,1,0},2,2)); - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,0,1},2,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){0,1,1},2,2)); - ASSERT_EQUAL_U(2, inform_encode((uint64_t[]){1,0,1},2,2)); - ASSERT_EQUAL_U(3, inform_encode((uint64_t[]){1,1,1},2,2)); - -} - -UNIT(EncodeLengthTwo_Base5) -{ - ASSERT_EQUAL_U( 0, inform_encode((uint64_t[]){0,0},2,5)); - ASSERT_EQUAL_U( 1, inform_encode((uint64_t[]){0,1},2,5)); - ASSERT_EQUAL_U( 2, inform_encode((uint64_t[]){0,2},2,5)); - ASSERT_EQUAL_U( 3, inform_encode((uint64_t[]){0,3},2,5)); - ASSERT_EQUAL_U( 4, inform_encode((uint64_t[]){0,4},2,5)); - ASSERT_EQUAL_U( 5, inform_encode((uint64_t[]){1,0},2,5)); - ASSERT_EQUAL_U( 6, inform_encode((uint64_t[]){1,1},2,5)); - ASSERT_EQUAL_U( 7, inform_encode((uint64_t[]){1,2},2,5)); - ASSERT_EQUAL_U( 8, inform_encode((uint64_t[]){1,3},2,5)); - ASSERT_EQUAL_U( 9, inform_encode((uint64_t[]){1,4},2,5)); - ASSERT_EQUAL_U(10, inform_encode((uint64_t[]){2,0},2,5)); - ASSERT_EQUAL_U(11, inform_encode((uint64_t[]){2,1},2,5)); - ASSERT_EQUAL_U(12, inform_encode((uint64_t[]){2,2},2,5)); - ASSERT_EQUAL_U(13, inform_encode((uint64_t[]){2,3},2,5)); - ASSERT_EQUAL_U(14, inform_encode((uint64_t[]){2,4},2,5)); - ASSERT_EQUAL_U(15, inform_encode((uint64_t[]){3,0},2,5)); - ASSERT_EQUAL_U(16, inform_encode((uint64_t[]){3,1},2,5)); - ASSERT_EQUAL_U(17, inform_encode((uint64_t[]){3,2},2,5)); - ASSERT_EQUAL_U(18, inform_encode((uint64_t[]){3,3},2,5)); - ASSERT_EQUAL_U(19, inform_encode((uint64_t[]){3,4},2,5)); - ASSERT_EQUAL_U(20, inform_encode((uint64_t[]){4,0},2,5)); - ASSERT_EQUAL_U(21, inform_encode((uint64_t[]){4,1},2,5)); - ASSERT_EQUAL_U(22, inform_encode((uint64_t[]){4,2},2,5)); - ASSERT_EQUAL_U(23, inform_encode((uint64_t[]){4,3},2,5)); - ASSERT_EQUAL_U(24, inform_encode((uint64_t[]){4,4},2,5)); -} - -UNIT(EncodeLengthThree_Base2) -{ - ASSERT_EQUAL_U(0, inform_encode((uint64_t[]){0,0,0},3,2)); - ASSERT_EQUAL_U(1, inform_encode((uint64_t[]){0,0,1},3,2)); - ASSERT_EQUAL_U(2, inform_encode((uint64_t[]){0,1,0},3,2)); - ASSERT_EQUAL_U(3, inform_encode((uint64_t[]){0,1,1},3,2)); - ASSERT_EQUAL_U(4, inform_encode((uint64_t[]){1,0,0},3,2)); - ASSERT_EQUAL_U(5, inform_encode((uint64_t[]){1,0,1},3,2)); - ASSERT_EQUAL_U(6, inform_encode((uint64_t[]){1,1,0},3,2)); - ASSERT_EQUAL_U(7, inform_encode((uint64_t[]){1,1,1},3,2)); -} - -UNIT(EncodeLengthThree_Base3) -{ - ASSERT_EQUAL_U( 0, inform_encode((uint64_t[]){0,0,0},3,3)); - ASSERT_EQUAL_U( 1, inform_encode((uint64_t[]){0,0,1},3,3)); - ASSERT_EQUAL_U( 2, inform_encode((uint64_t[]){0,0,2},3,3)); - ASSERT_EQUAL_U( 3, inform_encode((uint64_t[]){0,1,0},3,3)); - ASSERT_EQUAL_U( 4, inform_encode((uint64_t[]){0,1,1},3,3)); - ASSERT_EQUAL_U( 5, inform_encode((uint64_t[]){0,1,2},3,3)); - ASSERT_EQUAL_U( 6, inform_encode((uint64_t[]){0,2,0},3,3)); - ASSERT_EQUAL_U( 7, inform_encode((uint64_t[]){0,2,1},3,3)); - ASSERT_EQUAL_U( 8, inform_encode((uint64_t[]){0,2,2},3,3)); - ASSERT_EQUAL_U( 9, inform_encode((uint64_t[]){1,0,0},3,3)); - ASSERT_EQUAL_U(10, inform_encode((uint64_t[]){1,0,1},3,3)); - ASSERT_EQUAL_U(11, inform_encode((uint64_t[]){1,0,2},3,3)); - ASSERT_EQUAL_U(12, inform_encode((uint64_t[]){1,1,0},3,3)); - ASSERT_EQUAL_U(13, inform_encode((uint64_t[]){1,1,1},3,3)); - ASSERT_EQUAL_U(14, inform_encode((uint64_t[]){1,1,2},3,3)); - ASSERT_EQUAL_U(15, inform_encode((uint64_t[]){1,2,0},3,3)); - ASSERT_EQUAL_U(16, inform_encode((uint64_t[]){1,2,1},3,3)); - ASSERT_EQUAL_U(17, inform_encode((uint64_t[]){1,2,2},3,3)); - ASSERT_EQUAL_U(18, inform_encode((uint64_t[]){2,0,0},3,3)); - ASSERT_EQUAL_U(19, inform_encode((uint64_t[]){2,0,1},3,3)); - ASSERT_EQUAL_U(20, inform_encode((uint64_t[]){2,0,2},3,3)); - ASSERT_EQUAL_U(21, inform_encode((uint64_t[]){2,1,0},3,3)); - ASSERT_EQUAL_U(22, inform_encode((uint64_t[]){2,1,1},3,3)); - ASSERT_EQUAL_U(23, inform_encode((uint64_t[]){2,1,2},3,3)); - ASSERT_EQUAL_U(24, inform_encode((uint64_t[]){2,2,0},3,3)); - ASSERT_EQUAL_U(25, inform_encode((uint64_t[]){2,2,1},3,3)); - ASSERT_EQUAL_U(26, inform_encode((uint64_t[]){2,2,2},3,3)); -} - -UNIT(EncodingInvalidState_Base2) -{ - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){-1},1,2)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){2},1,2)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){3},1,2)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,2},2,2)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,3},2,2)); -} - -UNIT(EncodingInvalidState_Base3) -{ - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){-1},1,3)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){3},1,3)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){4},1,3)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,3},2,3)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,4},2,3)); -} - -UNIT(EncodingInvalidState_Base4) -{ - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){-1},1,4)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){4},1,4)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){5},1,4)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,4},2,4)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,5},2,4)); -} - -UNIT(EncodingInvalidState_Base5) -{ - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){-1},1,5)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){5},1,5)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(3), inform_encode((uint64_t[]){6},1,5)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,5},2,5)); - ASSERT_EQUAL_U(INFORM_ENCODING_ERROR(4), inform_encode((uint64_t[]){0,6},2,5)); -} - -UNIT(EncodeInvertsDecode_Base2) -{ - uint64_t const base = 2; - uint64_t const M = 10; - for (uint64_t x = 0; x < (uint64_t) pow((double) base, (double) M); ++x) - { - uint64_t *state = inform_decode(x,M,base); - ASSERT_EQUAL_U(x, inform_encode(state,M,base)); - free(state); - } -} - -UNIT(EncodeInvertsDecode_Base3) -{ - uint64_t const base = 3; - uint64_t const M = 6; - for (uint64_t x = 0; x < (uint64_t) pow((double) base, (double) M); ++x) - { - uint64_t *state = inform_decode(x,M,base); - ASSERT_EQUAL_U(x, inform_encode(state,M,base)); - free(state); - } -} - -UNIT(EncodeInvertsDecode_Base4) -{ - uint64_t const base = 4; - uint64_t const M = 5; - for (uint64_t x = 0; x < (uint64_t) pow((double) base, (double) M); ++x) - { - uint64_t *state = inform_decode(x,M,base); - ASSERT_EQUAL_U(x, inform_encode(state,M,base)); - free(state); - } -} - -UNIT(EncodeInvertsDecode_Base5) -{ - uint64_t const base = 5; - uint64_t const M = 4; - for (uint64_t x = 0; x < (uint64_t) pow((double) base, (double) M); ++x) - { - uint64_t *state = inform_decode(x,M,base); - ASSERT_EQUAL_U(x, inform_encode(state,M,base)); - free(state); - } -} - -UNIT(DecodeErrors) -{ - ASSERT_NULL(inform_decode(inform_encoding_error,1,2)); - ASSERT_NULL(inform_decode(inform_encoding_error + 1,1,2)); - ASSERT_NULL(inform_decode(inform_encoding_error + 2,1,2)); - - ASSERT_NULL(inform_decode(inform_encoding_error,1,3)); - ASSERT_NULL(inform_decode(inform_encoding_error + 1,1,3)); - ASSERT_NULL(inform_decode(inform_encoding_error + 2,1,3)); -} - -UNIT(DecodeTooManyBits_Base2) -{ - uint64_t *state = inform_decode(0,63,2); - ASSERT_NOT_NULL(state); - free(state); - - ASSERT_NULL(inform_decode(0,64,2)); -} - -UNIT(DecodeTooManyBits_Base3) -{ - uint64_t *state = inform_decode(0,40,3); - ASSERT_NOT_NULL(state); - free(state); - - ASSERT_NULL(inform_decode(0,41,3)); -} - -UNIT(DecodeTooManyBits_Base4) -{ - uint64_t *state = inform_decode(0,31,4); - ASSERT_NOT_NULL(state); - free(state); - - ASSERT_NULL(inform_decode(0,32,4)); -} - -UNIT(DecodeTooManyBits_Base5) -{ - uint64_t *state = inform_decode(0,27,5); - ASSERT_NOT_NULL(state); - free(state); - - ASSERT_NULL(inform_decode(0,28,5)); -} - -BEGIN_SUITE(StateEncoding) - ADD_UNIT(EncodeNULL) - ADD_UNIT(EncodeInvalidBase) - ADD_UNIT(EncodeTooLong_Base2) - ADD_UNIT(EncodeTooLong_Base3) - ADD_UNIT(EncodeTooLong_Base4) - ADD_UNIT(EncodeTooLong_Base5) - ADD_UNIT(EncodeLengthOne_Base2) - ADD_UNIT(EncodeLengthOne_Base5) - ADD_UNIT(EncodeLengthTwo_Base2) - ADD_UNIT(EncodeLengthTwo_Base5) - ADD_UNIT(EncodeLengthThree_Base2) - ADD_UNIT(EncodeLengthThree_Base3) - ADD_UNIT(EncodingInvalidState_Base2) - ADD_UNIT(EncodingInvalidState_Base3) - ADD_UNIT(EncodingInvalidState_Base4) - ADD_UNIT(EncodingInvalidState_Base5) - ADD_UNIT(EncodeInvertsDecode_Base2) - ADD_UNIT(EncodeInvertsDecode_Base3) - ADD_UNIT(EncodeInvertsDecode_Base4) - ADD_UNIT(EncodeInvertsDecode_Base5) - ADD_UNIT(DecodeErrors) - ADD_UNIT(DecodeTooManyBits_Base2) - ADD_UNIT(DecodeTooManyBits_Base3) - ADD_UNIT(DecodeTooManyBits_Base4) - ADD_UNIT(DecodeTooManyBits_Base5) -END_SUITE diff --git a/test/unittests/transfer_entropy.c b/test/unittests/transfer_entropy.c index 355c12a..600d29c 100644 --- a/test/unittests/transfer_entropy.c +++ b/test/unittests/transfer_entropy.c @@ -1,139 +1,175 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include -#include +#include "util.h" #include -#include "random.h" +#include +#include + +UNIT(TransferEntropyNULLSeries) +{ + int const series[] = {1,1,0,0,1,0,0,1}; -UNIT(TransferEntropyTooShort) + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(NULL, series, 1, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); + + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(series, NULL, 1, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); +} + +UNIT(TransferEntropyNoInits) { - uint64_t const series[] = {1,1,1,0,0,1,1,0,0,1}; - ASSERT_TRUE(isnan(inform_transfer_entropy(series, series+5, 1, 0, 2, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series, series+5, 1, 1, 2, 2))); + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(series, series, 0, 3, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); +} + +UNIT(TransferEntropySeriesTooShort) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + for (size_t i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(series, series, 1, i, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); + } } UNIT(TransferEntropyHistoryTooLong) { + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 2; i < 4; ++i) { - uint64_t const series[] = {1,1,1,0,0,1,1,0,0,1}; - ASSERT_TRUE(isnan(inform_transfer_entropy(series, series+5, 1, 2, 2, 2))); - ASSERT_FALSE(isnan(inform_transfer_entropy(series, series+5, 1, 3, 2, 2))); + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(series, series, 1, 2, 2, i, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); } +} +UNIT(TransferEntropyZeroHistory) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(series, series, 1, 2, 2, 0, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} + +UNIT(TransferEntropyInvalidBase) +{ + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) { - size_t const size = 30; - - uint64_t *xseries = random_series(size, 2); - uint64_t *yseries = random_series(size, 2); - ASSERT_TRUE(isnan(inform_transfer_entropy(xseries, yseries, 1, size, 2, 26))); - free(xseries); - free(yseries); - - xseries = random_series(size, 3); - yseries = random_series(size, 3); - ASSERT_TRUE(isnan(inform_transfer_entropy(xseries, yseries, 1, size, 3, 16))); - free(xseries); - free(yseries); - - xseries = random_series(size, 4); - yseries = random_series(size, 4); - ASSERT_TRUE(isnan(inform_transfer_entropy(xseries, yseries, 1, size, 4, 13))); - free(xseries); - free(yseries); + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(series, series, 1, 2, i, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); } } -UNIT(TransferEntropyEncodingError) +UNIT(TransferEntropyNegativeState) { - { - uint64_t const series[10] = {2,1,1,0,1,0,0,1,0,1}; - ASSERT_FALSE(isnan(inform_transfer_entropy(series+5, series, 1, 5, 3, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series+5, series, 1, 5, 2, 2))); - - ASSERT_FALSE(isnan(inform_transfer_entropy(series, series+5, 1, 5, 3, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series, series+5, 1, 5, 2, 2))); - } - - { - uint64_t const series[] = {1,1,1,0,2,0,0,1,0,1}; - ASSERT_FALSE(isnan(inform_transfer_entropy(series+5, series, 1, 5, 3, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series+5, series, 1, 5, 2, 2))); - - ASSERT_FALSE(isnan(inform_transfer_entropy(series, series+5, 1, 5, 3, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series, series+5, 1, 5, 2, 2))); - } - - { - uint64_t const series[] = {1,1,1,2,1,0,0,1,0,1}; - ASSERT_FALSE(isnan(inform_transfer_entropy(series+5, series, 1, 5, 3, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series+5, series, 1, 5, 2, 2))); - - ASSERT_FALSE(isnan(inform_transfer_entropy(series, series+5, 1, 5, 3, 2))); - ASSERT_TRUE(isnan(inform_transfer_entropy(series, series+5, 1, 5, 2, 2))); - } + int const seriesA[] = { 1,1,0,0,1,0,0,1}; + int const seriesB[] = {-1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_TRUE(isnan(inform_transfer_entropy(seriesA, seriesB, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); + + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(seriesB, seriesA, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); } +UNIT(TransferEntropyBadState) +{ + int const seriesA[] = {1,1,0,0,1,0,0,1}; + int const seriesB[] = {2,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_TRUE(isnan(inform_transfer_entropy(seriesA, seriesB, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); + + err = INFORM_SUCCESS; + ASSERT_TRUE(isnan(inform_transfer_entropy(seriesB, seriesA, 1, 8, 2, 2, &err))); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); +} UNIT(TransferEntropySingleSeries_Base2) { { - uint64_t series[10] = { + int series[10] = { 1,1,1,0,0, 1,1,0,0,1 }; ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series, series, 1, 5, 2, 2), 1e-6); + inform_transfer_entropy(series, series, 1, 5, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.666666, - inform_transfer_entropy(series+5, series, 1, 5, 2, 2), 1e-6); + inform_transfer_entropy(series+5, series, 1, 5, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series, series+5, 1, 5, 2, 2), 1e-6); + inform_transfer_entropy(series, series+5, 1, 5, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series+5, series+5, 1, 5, 2, 2), 1e-6); + inform_transfer_entropy(series+5, series+5, 1, 5, 2, 2, NULL), 1e-6); } { - uint64_t series[20] = { + int series[20] = { 0,0,1,1,1,0,0,0,0,1, 1,1,0,0,0,0,0,0,1,1 }; ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series, series, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series, series, 1, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.500000, - inform_transfer_entropy(series+10, series, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series+10, series, 1, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.106844, - inform_transfer_entropy(series, series+10, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series, series+10, 1, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series+10, series+10, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series+10, series+10, 1, 10, 2, 2, NULL), 1e-6); } { - uint64_t series[20] = { + int series[20] = { 0,1,0,1,0,0,1,1,0,0, 0,0,1,0,1,1,1,0,1,1 }; ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series, series, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series, series, 1, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.344361, - inform_transfer_entropy(series+10, series, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series+10, series, 1, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.250000, - inform_transfer_entropy(series, series+10, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series, series+10, 1, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(series+10, series+10, 1, 10, 2, 2), 1e-6); + inform_transfer_entropy(series+10, series+10, 1, 10, 2, 2, NULL), 1e-6); } } UNIT(TransferEntropyEnsemble_Base2) { { - uint64_t xseries[50] = { + int xseries[50] = { 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, }; - uint64_t yseries[50] = { + int yseries[50] = { 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, @@ -142,32 +178,32 @@ UNIT(TransferEntropyEnsemble_Base2) }; ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(xseries, xseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, xseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.091141, - inform_transfer_entropy(yseries, xseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, xseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.107630, - inform_transfer_entropy(xseries, yseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, yseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(yseries, yseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, yseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(xseries, xseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, xseries, 4, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.134536, - inform_transfer_entropy(yseries, xseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, xseries, 4, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.089517, - inform_transfer_entropy(xseries, yseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, yseries, 4, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(yseries, yseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, yseries, 4, 10, 2, 2, NULL), 1e-6); } { - uint64_t xseries[50] = { + int xseries[50] = { 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, }; - uint64_t yseries[50] = { + int yseries[50] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, @@ -176,158 +212,197 @@ UNIT(TransferEntropyEnsemble_Base2) }; ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(xseries, xseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, xseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.031471, - inform_transfer_entropy(yseries, xseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, xseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.152561, - inform_transfer_entropy(xseries, yseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, yseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(yseries, yseries, 5, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, yseries, 5, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(xseries, xseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, xseries, 4, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.172618, - inform_transfer_entropy(yseries, xseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, xseries, 4, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.206156, - inform_transfer_entropy(xseries, yseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(xseries, yseries, 4, 10, 2, 2, NULL), 1e-6); ASSERT_DBL_NEAR_TOL(0.000000, - inform_transfer_entropy(yseries, yseries, 4, 10, 2, 2), 1e-6); + inform_transfer_entropy(yseries, yseries, 4, 10, 2, 2, NULL), 1e-6); } } -#define AVERAGE(XS) average(XS, sizeof(XS) / sizeof(double)) - -static double average(double *xs, size_t n) +UNIT(LocalTransferEntropyNULLSeries) { - double x = 0; - for (size_t i = 0; i < n; ++i) - { - x += xs[i]; - } - return x / n; + double te[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(NULL, series, 1, 3, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); + + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(series, NULL, 1, 3, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ETIMESERIES, err); } -UNIT(LocalTransferEntropyTooShort) +UNIT(LocalTransferEntropyNoInits) { double te[8]; - uint64_t const series[] = {1,1,1,0,0,1,1,0,0,1}; - ASSERT_EQUAL(3, inform_local_transfer_entropy(series, series+5, 1, 0, 2, 2, te)); - ASSERT_EQUAL(3, inform_local_transfer_entropy(series, series+5, 1, 1, 2, 2, te)); + int const series[] = {1,1,0,0,1,0,0,1}; + + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(series, series, 0, 3, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENOINITS, err); } -UNIT(LocalTransferEntropyHistoryTooLong) +UNIT(LocalTransferEntropySeriesTooShort) { + double te[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + for (size_t i = 0; i < 2; ++i) { - double te[8]; - uint64_t const series[] = {1,1,1,0,0,1,1,0,0,1}; - ASSERT_EQUAL(4, inform_local_transfer_entropy(series, series+5, 1, 2, 2, 2, te)); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+5, 1, 3, 2, 2, te)); + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(series, series, 1, i, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ESHORTSERIES, err); } +} +UNIT(LocalTransferEntropyHistoryTooLong) +{ + double te[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (size_t i = 2; i < 4; ++i) { - size_t const size = 30; - - double te[30]; - uint64_t *xseries = random_series(size, 2); - uint64_t *yseries = random_series(size, 2); - ASSERT_EQUAL(5, inform_local_transfer_entropy(xseries, yseries, 1, size, 2, 26, te)); - free(xseries); - free(yseries); - - xseries = random_series(size, 3); - yseries = random_series(size, 3); - ASSERT_EQUAL(5, inform_local_transfer_entropy(xseries, yseries, 1, size, 3, 16, te)); - free(xseries); - free(yseries); - - xseries = random_series(size, 4); - yseries = random_series(size, 4); - ASSERT_EQUAL(5, inform_local_transfer_entropy(xseries, yseries, 1, size, 4, 13, te)); - free(xseries); - free(yseries); + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(series, series, 1, 2, 2, i, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKLONG, err); } } -UNIT(LocalTransferEntropyEncodingError) +UNIT(LocalTransferEntropyZeroHistory) { - { - double te[8]; - uint64_t const series[10] = {2,1,1,0,1,0,0,1,0,1}; - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+5, series, 1, 5, 3, 2, te)); - ASSERT_EQUAL(6, inform_local_transfer_entropy(series+5, series, 1, 5, 2, 2, te)); - - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+5, 1, 5, 3, 2, te)); - ASSERT_EQUAL(6, inform_local_transfer_entropy(series, series+5, 1, 5, 2, 2, te)); - } + double te[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(series, series, 1, 2, 2, 0, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EKZERO, err); +} - { - double te[8]; - uint64_t const series[] = {1,1,1,0,2,0,0,1,0,1}; - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+5, series, 1, 5, 3, 2, te)); - ASSERT_EQUAL(6, inform_local_transfer_entropy(series+5, series, 1, 5, 2, 2, te)); +UNIT(LocalTransferEntropyInvalidBase) +{ + double te[8]; + int const series[] = {1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + for (int i = 0; i < 2; ++i) + { + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(series, series, 1, 2, i, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBASE, err); + } +} - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+5, 1, 5, 3, 2, te)); - ASSERT_EQUAL(6, inform_local_transfer_entropy(series, series+5, 1, 5, 2, 2, te)); - } +UNIT(LocalTransferEntropyNegativeState) +{ + double te[8]; + int const seriesA[] = { 1,1,0,0,1,0,0,1}; + int const seriesB[] = {-1,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_NULL(inform_local_transfer_entropy(seriesA, seriesB, 1, 8, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); + + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(seriesB, seriesA, 1, 8, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_ENEGSTATE, err); +} - { - double te[8]; - uint64_t const series[] = {1,1,1,2,1,0,0,1,0,1}; - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+5, series, 1, 5, 3, 2, te)); - ASSERT_EQUAL(6, inform_local_transfer_entropy(series+5, series, 1, 5, 2, 2, te)); +UNIT(LocalTransferEntropyBadState) +{ + double te[8]; + int const seriesA[] = {1,1,0,0,1,0,0,1}; + int const seriesB[] = {2,1,0,0,1,0,0,1}; + inform_error err = INFORM_SUCCESS; + + ASSERT_NULL(inform_local_transfer_entropy(seriesA, seriesB, 1, 8, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); + + err = INFORM_SUCCESS; + ASSERT_NULL(inform_local_transfer_entropy(seriesB, seriesA, 1, 8, 2, 2, te, &err)); + ASSERT_TRUE(inform_failed(&err)); + ASSERT_EQUAL(INFORM_EBADSTATE, err); +} - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+5, 1, 5, 3, 2, te)); - ASSERT_EQUAL(6, inform_local_transfer_entropy(series, series+5, 1, 5, 2, 2, te)); - } +UNIT(LocalTransferEntropyAllocatesOutput) +{ + inform_error err = INFORM_SUCCESS; + int source[] = {0,0,1,0,0,1,0,1,0}; + int target[] = {0,1,0,0,1,0,0,1,0}; + double *te = inform_local_transfer_entropy(source, target, 1, 9, 2, 2, NULL, &err); + ASSERT_NOT_NULL(te); + ASSERT_EQUAL(INFORM_SUCCESS, err); + free(te); } UNIT(LocalTransferEntropySingleSeries_Base2) { { double te[3]; - uint64_t series[10] = { - 1,1,1,0,0, - 1,1,0,0,1 + int series[10] = { + 1,1,1,0,0, + 1,1,0,0,1 }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series, 1, 5, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series, series, 1, 5, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+5, series, 1, 5, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series+5, series, 1, 5, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.666666, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+5, 1, 5, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series, series+5, 1, 5, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+5, series+5, 1, 5, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series+5, series+5, 1, 5, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } { double te[8]; - uint64_t series[20] = { - 0,0,1,1,1,0,0,0,0,1, - 1,1,0,0,0,0,0,0,1,1 + int series[20] = { + 0,0,1,1,1,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1 }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series, series, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+10, series, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series+10, series, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.500000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+10, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series, series+10, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.106844, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+10, series+10, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series+10, series+10, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } { double te[8]; - uint64_t series[20] = { - 0,1,0,1,0,0,1,1,0,0, - 0,0,1,0,1,1,1,0,1,1 + int series[20] = { + 0,1,0,1,0,0,1,1,0,0, + 0,0,1,0,1,1,1,0,1,1 }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series, series, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+10, series, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series+10, series, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.344361, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series, series+10, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series, series+10, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.250000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(series+10, series+10, 1, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(series+10, series+10, 1, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } } @@ -336,14 +411,14 @@ UNIT(LocalTransferEntropyEnsemble_Base2) { { double te[40]; - uint64_t xseries[50] = { + int xseries[50] = { 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, }; - uint64_t yseries[50] = { + int yseries[50] = { 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, @@ -351,49 +426,49 @@ UNIT(LocalTransferEntropyEnsemble_Base2) 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, xseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, xseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, xseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, xseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.091141, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, yseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, yseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.107630, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, yseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, yseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } { double te[32]; - uint64_t xseries[40] = { + int xseries[40] = { 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, }; - uint64_t yseries[40] = { + int yseries[40] = { 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, xseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, xseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, xseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, xseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.134536, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, yseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, yseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.089517, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, yseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, yseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } { double te[40]; - uint64_t xseries[50] = { + int xseries[50] = { 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, }; - uint64_t yseries[50] = { + int yseries[50] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, @@ -401,25 +476,25 @@ UNIT(LocalTransferEntropyEnsemble_Base2) 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, xseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, xseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, xseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, xseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.031471, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, yseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, yseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.152561, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, yseries, 5, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, yseries, 5, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } { double te[32]; - uint64_t xseries[50] = { + int xseries[50] = { 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, }; - uint64_t yseries[50] = { + int yseries[50] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, @@ -427,26 +502,37 @@ UNIT(LocalTransferEntropyEnsemble_Base2) 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, }; - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, xseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, xseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, xseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, xseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.172618, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(xseries, yseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(xseries, yseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.206156, AVERAGE(te), 1e-6); - ASSERT_EQUAL(0, inform_local_transfer_entropy(yseries, yseries, 4, 10, 2, 2, te)); + ASSERT_NOT_NULL(inform_local_transfer_entropy(yseries, yseries, 4, 10, 2, 2, te, NULL)); ASSERT_DBL_NEAR_TOL(0.000000, AVERAGE(te), 1e-6); } } BEGIN_SUITE(TransferEntropy) - ADD_UNIT(TransferEntropyTooShort) + ADD_UNIT(TransferEntropyNULLSeries) + ADD_UNIT(TransferEntropyNoInits) + ADD_UNIT(TransferEntropySeriesTooShort) ADD_UNIT(TransferEntropyHistoryTooLong) - ADD_UNIT(TransferEntropyEncodingError) + ADD_UNIT(TransferEntropyZeroHistory) + ADD_UNIT(TransferEntropyInvalidBase) + ADD_UNIT(TransferEntropyNegativeState) + ADD_UNIT(TransferEntropyBadState) ADD_UNIT(TransferEntropySingleSeries_Base2) ADD_UNIT(TransferEntropyEnsemble_Base2) - ADD_UNIT(LocalTransferEntropyTooShort) + ADD_UNIT(LocalTransferEntropyNULLSeries) + ADD_UNIT(LocalTransferEntropyNoInits) + ADD_UNIT(LocalTransferEntropySeriesTooShort) ADD_UNIT(LocalTransferEntropyHistoryTooLong) - ADD_UNIT(LocalTransferEntropyEncodingError) + ADD_UNIT(LocalTransferEntropyZeroHistory) + ADD_UNIT(LocalTransferEntropyInvalidBase) + ADD_UNIT(LocalTransferEntropyNegativeState) + ADD_UNIT(LocalTransferEntropyBadState) + ADD_UNIT(LocalTransferEntropyAllocatesOutput) ADD_UNIT(LocalTransferEntropySingleSeries_Base2) ADD_UNIT(LocalTransferEntropyEnsemble_Base2) END_SUITE diff --git a/test/unittests/random.c b/test/unittests/util.c similarity index 54% rename from test/unittests/random.c rename to test/unittests/util.c index b6ddcdd..3478457 100644 --- a/test/unittests/random.c +++ b/test/unittests/util.c @@ -1,11 +1,11 @@ // Copyright 2016 ELIFE. All rights reserved. // Use of this source code is governed by a MIT // license that can be found in the LICENSE file. -#include "random.h" +#include "util.h" -uint64_t* random_series(size_t size, uint64_t base) +int* random_series(size_t size, int base) { - uint64_t *series = calloc(size, sizeof(uint64_t)); + int *series = calloc(size, sizeof(int)); if (series != NULL) { for (size_t i = 0; i < size; ++i) @@ -15,3 +15,13 @@ uint64_t* random_series(size_t size, uint64_t base) } return series; } + +double average(double const *xs, size_t n) +{ + double x = 0; + for (size_t i = 0; i < n; ++i) + { + x += xs[i]; + } + return x / n; +} diff --git a/test/unittests/random.h b/test/unittests/util.h similarity index 57% rename from test/unittests/random.h rename to test/unittests/util.h index 8327d2e..f6a2a8c 100644 --- a/test/unittests/random.h +++ b/test/unittests/util.h @@ -6,4 +6,7 @@ #include #include -uint64_t* random_series(size_t size, uint64_t base); +int* random_series(size_t size, int base); + +#define AVERAGE(XS) average(XS, sizeof(XS) / sizeof(double)) +double average(double const *xs, size_t n);