Skip to content
Commits on Source (117)
doc/libRaptorQ.aux
doc/libRaptorQ.bbl
doc/libRaptorQ.blg
doc/libRaptorQ.idx
doc/libRaptorQ.ilg
doc/libRaptorQ.ind
doc/libRaptorQ.log
doc/libRaptorQ.out
doc/libRaptorQ.pdf
doc/libRaptorQ.synctex.gz
doc/libRaptorQ.toc
CMakeFiles/
CMakeCache.txt
CMakeLists.txt.user
cmake_install.cmake
Makefile
/doc/*.aux
/doc/*.bbl
/doc/*.blg
/doc/*.idx
/doc/*.ilg
/doc/*.ind
/doc/*.log
/doc/*.out
/doc/*.pdf
/doc/*.synctex.gz
/doc/*.toc
/CMakeFiles/
/CMakeCache.txt
/CMakeLists.txt.user
/cmake_install.cmake
/Makefile
*~
build*
/build*
......@@ -5,12 +5,12 @@ stages:
job1:
stage: makedoc
script: mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=Release ../; make docs; cp doc/libRaptorQ.pdf ~/
script: mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=Release ../; make docs; cp doc/libRaptorQ-RFC6330.pdf ~/; cp doc/libRaptorQ-RaptorQ.pdf ~/
job2:
stage: deploydoc
script: git diff-tree --no-commit-id --name-only -r HEAD | grep ^doc/ || exit 0; cd /var/lib/gitlab-runner/libRaptorQ.wiki; git pull; cp ~/libRaptorQ.pdf .; git add libRaptorQ.pdf; git commit -m '(gitlab-runner) updated pdf'; git push;
script: git diff-tree --no-commit-id --name-only -r HEAD | grep ^doc/ || exit 0; cd /var/lib/gitlab-runner/libRaptorQ.wiki; git pull; cp ~/libRaptorQ-RFC6330.pdf .; cp ~/libRaptorQ-RaptorQ.pdf .; git add libRaptorQ-RFC6330.pdf; git add libRaptorQ-RaptorQ.pdf; git commit -m '(gitlab-runner) updated pdf'; git push;
job3:
stage: build
......
v0.2.0 (prealpha):
v1.0.0 (beta):
* C++98 compatibility (untested)
* we are now a header-only library that can be compiled and linked to C/C++98, with RFC and RAW API
* RAW API block size is now typesafe.
* RAW API does not the interleaving code.
* RAW API does not use the interleaving code.
* API reworked to easy manage old/new API in the future
* new, simpler RAW API (single-block)
* computations can be stopped
* precomputation caching
* cached result can be compressed (raw/LZ4)
* RFC API: global multithreading instead of per-class
* RFC compliance
* CLI tool for raw API
* OSX/BSD support
v0.1.10 (unreleased):
* backported MAC/FreeBSD support (and incomplete windows)
* backported RFC compliance
v0.1.9:
* remember to bump up version in the cmake -.-'
* squashed warnings for gcc & clang in 32 bit mode.
......
......@@ -23,12 +23,13 @@ enable_language(CXX)
enable_language(C)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake; ${CMAKE_MODULE_PATH})
set(RQ_VERSION 0.2-prealpha)
set(RQ_VERSION 1.0.0-rc2)
set(RQ_ABI 1)
message(STATUS "libRaptorQ version ${RQ_VERSION}")
add_definitions(-DRQ_VERSION="${RQ_VERSION}")
add_definitions(-DEIGEN_MPL2_ONLY)
# default values
if(NOT CMAKE_BUILD_TYPE)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
......@@ -38,12 +39,41 @@ include(GNUInstallDirs)
option(DYNAMIC_LIB "Build dynamic library" ON)
option(STATIC_LIB "Build static library" ON)
option(CLANG_STDLIB "Use clang's libc++" OFF)
option(USE_LZ4 "Use LZ4 compression for result caching" ON)
option(CLI "BUild CLI tools" ON)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type")
set(USE_LZ4 "ON" CACHE STRING "Use LZ4 compression for result caching")
set(RQ_LINKER CACHE STRING "linker to use (auto/gold/ld/bsd)")
set(RQ_ENDIANNESS CACHE STRING "endianness of your system")
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE USE_LZ4 PROPERTY STRINGS ON BUNDLED OFF)
set_property(CACHE RQ_LINKER PROPERTY STRINGS GOLD LD BSD)
mark_as_advanced(FORCE RQ_LINKER)
set_property(CACHE RQ_ENDIANNESS PROPERTY STRINGS Auto BigEndian LittleEndian)
mark_as_advanced(FORCE RQ_LINKER RQ_ENDIANNESS RQ_GOLD RQ_LZ4_LIB)
if (USE_LZ4 MATCHES "BUNDLED")
set(USE_LZ4 "ON")
set(RQ_LZ4_USE_OWN TRUE)
endif()
if (NOT RQ_ENDIANNESS)
set(RQ_ENDIANNESS Auto)
endif()
if (RQ_ENDIANNESS MATCHES "Auto")
include(TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if (IS_BIG_ENDIAN)
add_definitions(-DRQ_BIG_ENDIAN)
message (STATUS "Detected big endian machine")
else()
add_definitions(-DRQ_LITTLE_ENDIAN)
message (STATUS "Detected little endian machine")
endif()
elseif (RQ_ENDIANNESS MATCHES "BigEndian")
add_definitions(-DRQ_BIG_ENDIAN)
message (STATUS "Forced to big endian")
elseif (RQ_ENDIANNESS MATCHES "LittleEndian")
add_definitions(-DRQ_LITTLE_ENDIAN)
message (STATUS "Forced to little endian")
endif()
# supported linkers: gold, linux standard, bsd
if(NOT RQ_LINKER)
......@@ -69,7 +99,7 @@ else()
set(RQ_LINKER BSD)
endif()
# defaults: only enable LTO/PROFILING with known compielrs
# defaults: only enable LTO/PROFILING with known compilers
# exception: osx/BSD. llvm linker/profiling not default?
if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND
(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD"))
......@@ -114,12 +144,12 @@ if(LTO MATCHES "ON")
set(CMAKE_NM ${RQ_NM})
set(CMAKE_RANLIB ${RQ_RANLIB})
mark_as_advanced(FORCE RQ_AR RQ_NM RQ_RANLIB)
message(STATUS "Link Time Optimization activated")
message(STATUS "Link Time Optimization activated")
else()
message(FATAL_ERROR "Sorry, don't know how to do LTO with your compiler")
endif()
else()
message(STATUS "Link Time Optimization deactivated")
message(STATUS "Link Time Optimization deactivated")
endif()
# Profiling is pretty compiler-specific....
......@@ -137,30 +167,31 @@ else()
endif()
if(CLANG_STDLIB MATCHES "ON")
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
message(FATAL_ERROR "libc++ is only supported by clang")
endif()
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
message(FATAL_ERROR "libc++ is only supported by clang")
endif()
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(STDLIB stdc++)
set(STDLIB stdc++)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CLANG_STDLIB MATCHES "ON")
set(RQ_STDLIB_FLAG -stdlib=libc++)
set(STDLIB c++)
else()
set(STDLIB stdc++)
endif()
if(CLANG_STDLIB MATCHES "ON")
set(RQ_STDLIB_FLAG -stdlib=libc++)
set(STDLIB c++)
else()
set(STDLIB stdc++)
endif()
endif()
find_package(Threads REQUIRED)
find_package(git)
find_package(eigen REQUIRED)
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
include_directories(SYSTEM PUBLIC ${EIGEN3_INCLUDE_DIR})
include_directories(SYSTEM PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/external/optionparser-1.4")
if (USE_LZ4 MATCHES "ON")
find_package(RQ_LZ4 REQUIRED)
include_directories(SYSTEM ${RQ_LZ4_INCLUDE_DIR})
include_directories(SYSTEM PUBLIC ${RQ_LZ4_INCLUDE_DIR})
add_definitions(-DRQ_USE_LZ4)
endif()
#lz4 build if necessary
......@@ -191,57 +222,72 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
message(WARNING, "RaptorQ builds are not deterministic in Windows yet")
else()
add_definitions(-DRQ_UNIX)
# used by ftok to get a key. Track both the file and the version
add_definitions(-DRQ_SHMPATH="${CMAKE_INSTALL_LIBDIR}/libRaptorQ.so-${RQ_VERSION}")
endif()
SET(SOURCES
src/RaptorQ/v1/caches.cpp
src/RaptorQ/v1/Operation.cpp
src/RaptorQ/v1/Parameters.cpp
src/RaptorQ/v1/Precode_Matrix_Instantiation.cpp
src/RaptorQ/v1/Rand.cpp
src/RaptorQ/v1/Shared_Computation/Decaying_LF.cpp
src/RaptorQ/v1/Thread_Pool.cpp
#src/RaptorQ/v1/wrapper/C_RAW_API.cpp
src/RaptorQ/v1/wrapper/C_RFC_API.cpp)
src/RaptorQ/v1/wrapper/C_RAW_API.cpp
src/RaptorQ/v1/wrapper/C_RFC_API.cpp
src/RaptorQ/v1/wrapper/CPP_RAW_API_void.cpp
src/RaptorQ/v1/wrapper/CPP_RFC_API_void.cpp
src/RaptorQ/v1/wrapper/CPP_caches.cpp
)
SET(HEADERS
src/RaptorQ/v1/API_Iterators.hpp
src/RaptorQ/v1/block_sizes.hpp
src/RaptorQ/v1/caches.hpp
src/RaptorQ/v1/caches.ipp
src/RaptorQ/v1/common.hpp
src/RaptorQ/v1/De_Interleaver.hpp
src/RaptorQ/v1/Decoder.hpp
src/RaptorQ/v1/degree.hpp
src/RaptorQ/v1/Encoder.hpp
src/RaptorQ/v1/Encoder.hpp
src/RaptorQ/v1/Interleaver.hpp
src/RaptorQ/v1/multiplication.hpp
src/RaptorQ/v1/Octet.hpp
src/RaptorQ/v1/Operation.hpp
src/RaptorQ/v1/Parameters.hpp
src/RaptorQ/v1/Precode_Matrix.hpp
src/RaptorQ/v1/Precode_Matrix_Init.hpp
src/RaptorQ/v1/Precode_Matrix_Solver.hpp
src/RaptorQ/v1/Precode_Matrix_Init.hpp
src/RaptorQ/v1/Precode_Matrix_Solver.hpp
src/RaptorQ/v1/Rand.hpp
src/RaptorQ/v1/RaptorQ.hpp
src/RaptorQ/v1/RaptorQ_Iterators.hpp
src/RaptorQ/v1/RaptorQ.hpp
src/RaptorQ/v1/RaptorQ_Iterators.hpp
src/RaptorQ/v1/RFC.hpp
src/RaptorQ/v1/RFC_Iterators.hpp
src/RaptorQ/v1/Shared_Computation/Decaying_LF.hpp
src/RaptorQ/v1/table2.hpp
src/RaptorQ/v1/Thread_Pool.hpp
src/RaptorQ/v1/Thread_Pool.hpp
src/RaptorQ/v1/util/Bitmask.hpp
src/RaptorQ/v1/util/div.hpp
src/RaptorQ/v1/util/endianess.hpp
src/RaptorQ/v1/util/Graph.hpp
)
SET(HEADERS_LINKED
src/RaptorQ/RaptorQ.h
src/RaptorQ/RaptorQ_v1.hpp
src/RaptorQ/RFC6330.h
src/RaptorQ/RFC6330_v1.hpp
src/RaptorQ/v1/wrapper/C_common.h
#src/RaptorQ/v1/wrapper/C_RAW_API.h
src/RaptorQ/v1/wrapper/C_RAW_API.h
src/RaptorQ/v1/wrapper/C_RFC_API.h
src/RaptorQ/v1/wrapper/CPP_RFC_API.hpp
src/RaptorQ/v1/wrapper/CPP_RAW_API.hpp)
src/RaptorQ/v1/wrapper/CPP_RFC_API_void.hpp
src/RaptorQ/v1/wrapper/CPP_RAW_API.hpp
src/RaptorQ/v1/wrapper/CPP_RAW_API_void.hpp
)
SET(HEADERS_ONLY
src/RaptorQ/RaptorQ_v1_hdr.hpp
src/RaptorQ/RFC6330_v1_hdr.hpp
)
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
# windows-only placeholder
else()
# linux-only placeholder
endif()
if (USE_LZ4 MATCHES "ON")
SET (HEADERS ${HEADERS}
......@@ -295,13 +341,13 @@ CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/API_Wrapper_C.cpp.gcda)
endif()
# PRE-run: build a library, generate the profile.
add_library(RaptorQ_Static_Profiling STATIC ${SOURCES} ${HEADERS})
add_library(RaptorQ_Static_Profiling STATIC ${SOURCES} ${HEADERS} ${HEADERS_LINKED})
target_link_libraries(RaptorQ_Static_Profiling ${STDLIB} ${RQ_LZ4_DEP} ${RQ_UBSAN})
add_dependencies(RaptorQ_Static_Profiling LZ4)
add_dependencies(RaptorQ_Static_Profiling LZ4)
target_compile_options(
RaptorQ_Static_Profiling PRIVATE
${CXX_COMPILER_FLAGS}
${PROFILE_GET}
${PROFILE_GET}
)
set_target_properties(RaptorQ_Static_Profiling PROPERTIES COMPILER_FLAGS ${PROFILE_GET})
......@@ -311,9 +357,13 @@ CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/API_Wrapper_C.cpp.gcda)
target_compile_options(
test_c_profiled PRIVATE
${C_COMPILER_FLAGS}
${PROFILE_GET}
${PROFILE_GET}
)
target_link_libraries(test_c_profiled RaptorQ_Static_Profiling ${STDLIB} m ${CMAKE_THREAD_LIBS_INIT})
if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
target_link_libraries(test_c_profiled RaptorQ_Static_Profiling ${STDLIB} m ${CMAKE_THREAD_LIBS_INIT} ${RQ_UBSAN})
else()
target_link_libraries(test_c_profiled RaptorQ_Static_Profiling ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_UBSAN})
endif()
set_target_properties(test_c_profiled PROPERTIES LINK_FLAGS ${PROFILE_GET})
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
......@@ -353,8 +403,8 @@ endif()
# build the static library
if(STATIC_LIB MATCHES "ON")
add_library(RaptorQ_Static STATIC ${SOURCES} ${HEADERS})
add_dependencies(RaptorQ_Static LZ4)
add_library(RaptorQ_Static STATIC ${SOURCES} ${HEADERS} ${HEADERS_LINKED})
add_dependencies(RaptorQ_Static LZ4)
if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
set_target_properties(RaptorQ_Static PROPERTIES OUTPUT_NAME RaptorQ.${RQ_ABI})
endif()
......@@ -373,7 +423,7 @@ if(STATIC_LIB MATCHES "ON")
set_target_properties (
RaptorQ_Static
PROPERTIES
LINK_FLAGS "-Wl,-z,now,-z,relro -pie ${LD_OPT}"
LINK_FLAGS "-Wl,-z,now,-z,relro${RQ_LZ4_EXCLUDE_SYM} -pie ${LD_OPT}"
)
endif()
set_property(TARGET RaptorQ_Static PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
......@@ -399,12 +449,11 @@ if(STATIC_LIB MATCHES "ON")
COMMENT "Removing creation date from library..."
VERBATIM
)
add_custom_target(
make_static_deterministic ALL
DEPENDS deterministic.run
)
endif()
add_custom_target(
make_static_deterministic ALL
DEPENDS deterministic.run
)
endif()
#build dynamic library
......@@ -412,9 +461,9 @@ if(DYNAMIC_LIB MATCHES "ON")
add_definitions(-DRAPTORQ_DLL)
add_definitions(-DRAPTORQ_DLL_EXPORTS)
add_library(RaptorQ SHARED ${SOURCES} ${HEADERS})
add_dependencies(RaptorQ LZ4)
target_link_libraries(RaptorQ ${RQ_LZ4_DEP})
add_library(RaptorQ SHARED ${SOURCES} ${HEADERS} ${HEADERS_LINKED})
add_dependencies(RaptorQ LZ4)
target_link_libraries(RaptorQ ${RQ_LZ4_DEP} ${RQ_UBSAN})
target_compile_options(
RaptorQ PRIVATE
${CXX_COMPILER_FLAGS}
......@@ -431,61 +480,80 @@ if(DYNAMIC_LIB MATCHES "ON")
# with the wrong number of parameters in the next set_target_properties
set(RQ_LINK_LIB "${LD_OPT} ")
else()
set(RQ_LINK_LIB "-Wl,-z,now,-z,relro ${LD_OPT}")
set(RQ_LINK_LIB "-Wl,-z,now,-z,relro${RQ_LZ4_EXCLUDE_SYM} ${LD_OPT}")
endif()
set_target_properties (
RaptorQ
PROPERTIES
LINK_FLAGS ${RQ_LINK_LIB}
SOVERSION ${RQ_ABI}
VERSION ${RQ_VERSION}
)
SOVERSION ${RQ_ABI}
VERSION ${RQ_VERSION}
)
set_property(TARGET RaptorQ PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
endif()
# add main tests
add_executable(libRaptorQ-test EXCLUDE_FROM_ALL test/rfc_test.cpp)
# benchamrks (header only)
add_executable(libRaptorQ-test EXCLUDE_FROM_ALL test/rfc_test.cpp ${HEADERS_ONLY} ${HEADERS})
target_compile_options(
libRaptorQ-test PRIVATE
${CXX_COMPILER_FLAGS}
libRaptorQ-test PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(libRaptorQ-test RaptorQ)
target_link_libraries(libRaptorQ-test ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
add_custom_target(tests DEPENDS libRaptorQ-test)
target_link_libraries(libRaptorQ-test ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# build examples
# C interface
# C interface (linked)
add_executable(test_c EXCLUDE_FROM_ALL test/test_c.c)
target_compile_options(
test_c PRIVATE
${C_COMPILER_FLAGS}
-Wno-disabled-macro-expansion
test_c PRIVATE
${C_COMPILER_FLAGS}
)
add_dependencies(test_c RaptorQ)
target_link_libraries(test_c RaptorQ m ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
# Linux, *BSD
target_link_libraries(test_c RaptorQ m ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
else()
# windows: no "m" library
target_link_libraries(test_c RaptorQ ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
endif()
# CPP interface - RFC interface
add_executable(test_cpp_rfc EXCLUDE_FROM_ALL test/test_cpp_rfc.cpp)
# CPP interface - RFC interface (header only)
add_executable(test_cpp_rfc EXCLUDE_FROM_ALL test/test_cpp_rfc.cpp ${HEADERS_ONLY} ${HEADERS})
target_compile_options(
test_cpp_rfc PRIVATE
${CXX_COMPILER_FLAGS}
test_cpp_rfc PRIVATE
${CXX_COMPILER_FLAGS} "-DTEST_HDR_ONLY"
)
add_dependencies(test_cpp_rfc RaptorQ)
target_link_libraries(test_cpp_rfc ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
target_link_libraries(test_cpp_rfc ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# CPP interface - RAW interface
add_executable(test_cpp_raw EXCLUDE_FROM_ALL test/test_cpp_raw.cpp)
# CPP interface - RFC interface (linked version)
add_executable(test_cpp_rfc_linked EXCLUDE_FROM_ALL test/test_cpp_rfc.cpp ${HEADERS_ONLY} ${HEADERS})
target_compile_options(
test_cpp_raw PRIVATE
${CXX_COMPILER_FLAGS}
test_cpp_rfc_linked PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(test_cpp_raw RaptorQ)
target_link_libraries(test_cpp_raw ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
add_custom_target(examples DEPENDS test_c test_cpp_rfc test_cpp_raw)
add_dependencies(test_cpp_rfc_linked RaptorQ)
target_link_libraries(test_cpp_rfc_linked RaptorQ ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# CLI tool - RAW API interface
set(CLI_raw_sources src/cli/RaptorQ.cpp external/optionparser-1.4/optionparser.h)
# CPP interface - RAW interface (header only)
add_executable(test_cpp_raw EXCLUDE_FROM_ALL test/test_cpp_raw.cpp ${HEADERS_ONLY} ${HEADERS})
target_compile_options(
test_cpp_raw PRIVATE
${CXX_COMPILER_FLAGS} "-DTEST_HDR_ONLY"
)
target_link_libraries(test_cpp_raw RaptorQ ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# CPP interface - RAW interface (linked version)
add_executable(test_cpp_raw_linked EXCLUDE_FROM_ALL test/test_cpp_raw.cpp)
target_compile_options(
test_cpp_raw_linked PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(test_cpp_raw_linked RaptorQ)
target_link_libraries(test_cpp_raw_linked RaptorQ ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# CLI tool - RAW API interface (header only)
set(CLI_raw_sources src/cli/RaptorQ.cpp external/optionparser-1.4/optionparser.h ${HEADERS} ${HEADERS_ONLY})
if(CLI MATCHES "ON")
add_executable(CLI_raw ${CLI_raw_sources})
add_custom_target(CLI_tools DEPENDS CLI_raw)
......@@ -494,18 +562,37 @@ else()
add_custom_target(CLI_tools "")
endif()
target_compile_options(
CLI_raw PRIVATE
${CXX_COMPILER_FLAGS}
CLI_raw PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(CLI_raw RaptorQ)
set_target_properties(CLI_raw PROPERTIES OUTPUT_NAME RaptorQ
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
target_link_libraries(CLI_raw ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
target_link_libraries(CLI_raw ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
#### EXAMPLES
# CPP interface - RAW interface (header only)
add_executable(example_cpp_raw EXCLUDE_FROM_ALL examples/example_cpp_raw.cpp ${HEADERS_ONLY} ${HEADERS})
target_compile_options(
example_cpp_raw PRIVATE
${CXX_COMPILER_FLAGS}
)
target_link_libraries(example_cpp_raw ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
add_custom_target(examples DEPENDS test_c test_cpp_rfc test_cpp_rfc_linked test_cpp_raw test_cpp_raw_linked libRaptorQ-test example_cpp_raw)
add_custom_target(everything DEPENDS make_static_deterministic examples docs CLI_tools)
add_custom_target(everything DEPENDS make_static_deterministic tests examples docs CLI_tools)
foreach (hdr ${HEADERS} ${HEADERS_ONLY} ${HEADERS_LINKED})
get_filename_component (full_dir_of_file ${hdr} PATH)
# remove the initial "src/":
string (SUBSTRING ${full_dir_of_file} 4 -1 dir_of_file)
install (FILES ${hdr} DESTINATION "include/${dir_of_file}")
endforeach()
install(FILES ${HEADERS} DESTINATION include/RaptorQ/)
install(TARGETS RaptorQ RaptorQ_Static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib COMPONENT libraries)
......
......@@ -66,7 +66,7 @@ developer accepted the CLA and is the author of the commit.
* Always sign your commits with the "-s" option, to add the "Signed-off-by" line in the commit message
* Only the main developers are required to GPG-sign the commits.
* Run the tests to make sure you have not broken something by mistake
* Please keep commits short and to the point. Nobody wants to review 2000+ lines of code that touch everything.
## Documentation
......
......@@ -2,11 +2,15 @@
[![build status](https://www.fenrirproject.org/Luker/libRaptorQ/badges/master/build.svg)](https://www.fenrirproject.org/Luker/libRaptorQ/commits/master)
[![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=79L8P7TXWFQK4)
[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg)](https://patreon.com/Luker)
[Homepage](https://www.fenrirproject.org/Luker/libRaptorQ/wikis/home)
stable release: **v0.1.9**
current release: **v0.2-prealpha**
**CURRENTLY BREAKING APIs, stick with the stable release**
old release: **v0.1.10**
> Note: v0.1.10 is not compatible with prefivous versions, which were not RFC compliant!
current release: **v1.0.0-rc2** (use this in new projects)
RaptorQ is a **Forward Error Correction** algorithm designed to deliver your data
efficiently and without retransmissions for lost packets.
......@@ -21,17 +25,30 @@ code in this category.
**libRaptorQ** implements **RFC6330**, which specifies the RaptorQ algorithm.
Since the RFC is really complex, there is also a simpler (and maybe slightly faster)
RAW API that you can use. The RFC API is not recommended due to the RFC complexity.
libRaptorQ is entirely written in *C++11*, and uses eigen to handle matrix
manipulation.
libRaptorQ is a header-only library written in *C++11*, and uses eigen to handle matrix
manipulation.
Although header-only, the library can be compiled to create shared and static libraries
with both C and C++98 compatibility.
Currently it's only been tested under Linux, but should work well under
*BSD and MacOSX, too.
Windows _should_ work too, provided you use a complier that understands C++11
(hint: you might have some problems with VisualC++, but that's not a C++
compiler anyway)
Unfortunately Windows is not supported. support for <future> is broken,
so you can not compile it with Visual Studio 2015.
## Features
- RFC6330 API (complex, not recommended)
- RAW API (simpler, recommended)
- multi language:
- header only C++11
- compiled, C
- compiled, C++98
- cached precomputations (configurable)
## Developers ##
......@@ -58,45 +75,23 @@ you can also get it from our main server:
Once you have cloned it, it's always a good thing to check the repository gpg
signatures, so you can import my key with:
new long term key: **7393 DAD2 55BE B575 1DBD A04A B11C D823 BA27 8C85**
``$ gpg --keyserver pgp.mit.edu --recv-key 7393DAD255BEB5751DBDA04AB11CD823BA278C85``
2016 key:
``$ gpg --keyserver pgp.mit.edu --recv-key F61F6137``
2015 key:
``$ gpg --keyserver pgp.mit.edu --recv-key D42DDF0A``
please check the full fingerprint, it should be like this:
```bash
$ gpg2 --fingerprint F61F6137
pub rsa2048/F61F6137 2016-01-11 [expires: 2017-01-25]
Key fingerprint = 95EB 6FA4 03D7 29A7 13C2 FC9F F85A DA1C F61F 6137
uid [ultimate] Luca Fulchir (2016 key) <luker@fenrirproject.org>
full 2015 fingerprint:
Key fingerprint = AB35 E45F 5CA5 E35B 8B55 818F 0157 D133 D42D DF0A
```
please check the full fingerprint.
Now you have the source, and the key, it's enough to check the signature of the
last commit:
``$ git log -n 1 --show-signature``
The important part is that you get something like this:
```bash
gpg: Signature made Mon 11 Jan 2016 14:19:21 CET using RSA key ID F61F6137
gpg: Good signature from "Luca Fulchir (2016 key) <luker@fenrirproject.org>"
[unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 95EB 6FA4 03D7 29A7 13C2 FC9F F85A DA1C F61F 6137
Author: Luca Fulchir <luker@fenrirproject.org>
```
And as long as you got the right key, and you find the "gpg: Goog signature",
As long as you got the right key, and you find the "gpg: Goog signature",
you can be sure you have the right code.
TDB: The repository is using the maintainer private key for now,
it will start using a dedicated key in the (near) future.
## Install ##
......@@ -149,29 +144,43 @@ break deterministic builds, so check the cmake warnings._
You can customize the CMake build with the following variables:
```
PROFILING ON/OFF: Default:ON. Activate or deactivate profiling.
Profiling compiles everything, then runs a test to see
which code paths are more used. Then it recompiles everything
but optimizing for for those code paths.
Only for gcc/clang.
LTO ON/OFF: Default:ON. Activate or deactivate Link time Optimization
Makes the library smaller and better optimized.
Only for gcc/clang.
PROFILING ON/OFF: Default:ON. Activate or deactivate profiling.
Profiling compiles everything, then runs a test to see
which code paths are more used. Then it recompiles everything
but optimizing for for those code paths.
Only for gcc/clang.
LTO ON/OFF: Default:ON. Activate or deactivate Link time Optimization
Makes the library smaller and better optimized.
Only for gcc/clang.
CLANG_STDLIB ON/OFF: Default:OFF. use clang's libc++
Note: only clang can use its standard library
Note: only clang can use its standard library
USE_LZ4 ON/OFF: use the lz4 compression for caching precomputations.
Default: ON
CLI ON/OFF Build Command Line Interface tools.
CMAKE_C_COMPILER gcc, clang...
CMAKE_CXX_COMPILER choose between g++ or clang++.
CMAKE_C_COMPILER gcc, clang...
CMAKE_CXX_COMPILER choose between g++ or clang++.
RQ_LINKER gold/ld/bsd Choose your linker. Default:autodetect.
CMAKE_BUILD_TYPE Debug,MinSizeRel,Release,RelWithDebInfo
CMAKE_BUILD_TYPE Debug,MinSizeRel,Release,RelWithDebInfo
CMAKE_INSTALL_PREFIX Default: /usr/local
```
## Using libRaptorQ ##
C and C++11 interfaces are available.
For the C++11, header-only version, you can include:
- "RaptorQ/RaptorQ_v1_hdr.hpp"
- "RaptorQ/RFC6330_v1_hdr.hpp"
For the linked, C+98/C++11 API:
- "RaptorQ/RaptorQ_v1.hpp"
- "RaptorQ/RFC6330_v1.hpp"
For the linked, C API:
- "RaptorQ/RaptorQ.h"
- "RaptorQ/RFC6330.h"
The C++ api is completely in sync between the linked and header-only version,
so you can switch between the two just by changing the included header file.
You can compile a PDF of the documentation by doing:
``$ make docs``
......
......@@ -19,14 +19,14 @@
#
FIND_PATH(RQ_LZ4_INCLUDE_DIR
NAMES lz4.h
PATH_SUFFIXES include/ include/lz4/ lz4/
PATHS
${LZ4_ROOT}
$ENV{LZ4_ROOT}
/usr/
NAMES lz4.h
PATH_SUFFIXES include/ include/lz4/ lz4/
PATHS
${LZ4_ROOT}
$ENV{LZ4_ROOT}
/usr/
/usr/local/
${CMAKE_CURRENT_SOURCE_DIR}/external/lz4/lib
${CMAKE_CURRENT_SOURCE_DIR}/external/lz4/lib
)
FIND_LIBRARY(RQ_LZ4_LIB
......@@ -34,35 +34,39 @@ FIND_LIBRARY(RQ_LZ4_LIB
PATH_SUFFIXES lib/
PATHS
${LZ4_ROOT}
$ENV{LZ4_ROOT}
$ENV{LZ4_ROOT}
/usr/
/usr/local/
)
IF(RQ_LZ4_INCLUDE_DIR)
SET(RQ_LZ4_FOUND TRUE)
SET(RQ_LZ4_FOUND TRUE)
ELSE(RQ_LZ4_INCLUDE_DIR)
SET(RQ_LZ4_FOUND FALSE)
SET(RQ_LZ4_FOUND FALSE)
ENDIF(RQ_LZ4_INCLUDE_DIR)
IF(RQ_LZ4_FOUND)
MESSAGE(STATUS "Found lz4 in ${RQ_LZ4_INCLUDE_DIR}")
IF(RQ_LZ4_USE_OWN)
# force our own lz4 libary
SET(RQ_LZ4_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/lz4/lib)
ENDIF()
MESSAGE(STATUS "Found lz4 in ${RQ_LZ4_INCLUDE_DIR}")
# we need both headers and library, or we use our own
IF(RQ_LZ4_INCLUDE_DIR MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/external/lz4/lib" OR RQ_LZ4_LIB MATCHES "RQ_LZ4_LIB-NOTFOUND")
MESSAGE(WARNING "We will build our own lz4 library and statically link it.")
SET(RQ_BUILD_LZ4 TRUE)
ENDIF()
IF(RQ_LZ4_INCLUDE_DIR MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/external/lz4/lib" OR RQ_LZ4_LIB MATCHES "RQ_LZ4_LIB-NOTFOUND")
MESSAGE(WARNING "We will build our own lz4 library and statically link it.")
SET(RQ_BUILD_LZ4 TRUE)
ENDIF()
ELSE(RQ_LZ4_FOUND)
IF(RQ_LZ4_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find \"lz4\" library."
IF(RQ_LZ4_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find \"lz4\" library."
" Please install the \"lz4\" library"
" or at least run:\n"
" cd ${CMAKE_CURRENT_SOURCE_DIR}\n"
" git submodule init\n"
" git submodule update\n")
ENDIF(RQ_LZ4_FIND_REQUIRED)
ENDIF(RQ_LZ4_FIND_REQUIRED)
ENDIF(RQ_LZ4_FOUND)
MARK_AS_ADVANCED(
RQ_LZ4_INCLUDE_DIR
RQ_LZ4_INCLUDE_DIR
)
......@@ -19,31 +19,31 @@
#
FIND_PATH(EIGEN3_INCLUDE_DIR
NAMES Eigen
PATH_SUFFIXES include/ include/eigen3/ eigen3/
PATHS
${EIGEN3_ROOT}
$ENV{EIGEN3_ROOT}
/usr/
/usr/local/
${PROJECT_SOURCE_DIR}/external/eigen3
NAMES Eigen
PATH_SUFFIXES include/ include/eigen3/ eigen3/
PATHS
${EIGEN3_ROOT}
$ENV{EIGEN3_ROOT}
/usr/
/usr/local/
${PROJECT_SOURCE_DIR}/external/eigen3
)
IF(EIGEN3_INCLUDE_DIR)
SET(EIGEN3_FOUND TRUE)
SET(EIGEN3_FOUND TRUE)
ELSE(EIGEN3_INCLUDE_DIR)
SET(EIGEN3_FOUND FALSE)
SET(EIGEN3_FOUND FALSE)
ENDIF(EIGEN3_INCLUDE_DIR)
IF(EIGEN3_FOUND)
MESSAGE(STATUS "Found eigen3 in ${EIGEN3_INCLUDE_DIR}")
MESSAGE(STATUS "Found eigen3 in ${EIGEN3_INCLUDE_DIR}")
ELSE(EIGEN3_FOUND)
IF(EIGEN3_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find \"eigen3\" library")
ENDIF(EIGEN3_FIND_REQUIRED)
IF(EIGEN3_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find \"eigen3\" library")
ENDIF(EIGEN3_FIND_REQUIRED)
ENDIF(EIGEN3_FOUND)
MARK_AS_ADVANCED(
EIGEN3_INCLUDE_DIR
EIGEN3_INCLUDE_DIR
)
......@@ -18,29 +18,29 @@
# along with libRaptorQ. If not, see <http://www.gnu.org/licenses/>.
#
FIND_PROGRAM(GIT_EXECUTABLE git
PATHS
${PATH}
"C:/Program Files/Git/bin"
"C:/Program Files (x86)/Git/bin"
DOC "git command line client"
PATHS
${PATH}
"C:/Program Files/Git/bin"
"C:/Program Files (x86)/Git/bin"
DOC "git command line client"
)
IF(GIT_EXECUTABLE)
SET(GIT_FOUND TRUE)
SET(GIT_FOUND TRUE)
ELSE(GIT_EXECUTABLE)
SET(GIT_FOUND FALSE)
SET(GIT_FOUND FALSE)
ENDIF(GIT_EXECUTABLE)
IF(GIT_FOUND)
MESSAGE(STATUS "Found git in ${GIT_EXECUTABLE}")
MESSAGE(STATUS "Found git in ${GIT_EXECUTABLE}")
ELSE(GIT_FOUND)
IF(GIT_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find \"git\" command")
ENDIF(GIT_REQUIRED)
IF(GIT_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find \"git\" command")
ENDIF(GIT_REQUIRED)
ENDIF(GIT_FOUND)
MARK_AS_ADVANCED(
GIT_EXECUTABLE
GIT_EXECUTABLE
)
......
......@@ -33,7 +33,6 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug")
check_cxx_compiler_flag("-fsanitize=undefined" RQ_FLAG_CXX_UBSAN)
if (RQ_FLAG_C_UBSAN AND RQ_FLAG_CXX_UBSAN)
set(RQ_ENABLE_UBSAN TRUE)
set(RQ_UBSAN ubsan)
message(STATUS "UBSAN sanitizing support enabled")
else()
message(STATUS "UBSAN sanitizing support disabled")
......@@ -48,8 +47,19 @@ endif()
###################
#gnu options
set(RQ_GNU_C_OPTIONS ${RQ_DETERMINISTIC} -std=c11 -ffast-math -Wno-unknown-pragmas -Wall -Wextra -pedantic -Wno-padded -fstack-protector-all -fstrict-aliasing -fwrapv -fvisibility=hidden )
set(RQ_GNU_CXX_OPTIONS ${RQ_DETERMINISTIC} -std=c++11 -ffast-math -fno-rtti -fno-exceptions -Wno-unknown-pragmas -Wall -Wextra -pedantic -Wno-padded -Wno-unknown-pragmas -fstack-protector-all -fstrict-aliasing -fwrapv -fvisibility=hidden -fvisibility-inlines-hidden )
set(RQ_GNU_C_OPTIONS ${RQ_DETERMINISTIC} -std=c11
-Wno-unknown-pragmas -Wall -Wextra -pedantic -Wno-padded
-fstack-protector-all -fstrict-aliasing -fwrapv -fvisibility=hidden
-Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict
-Wnull-dereference -Wdouble-promotion -Wshadow -Wformat=2)
set(RQ_GNU_CXX_OPTIONS ${RQ_DETERMINISTIC} -std=c++11
-fno-rtti -fno-exceptions -Wno-unknown-pragmas -Wall -Wextra
-pedantic -Wno-padded -Wno-unknown-pragmas -fstack-protector-all
-fstrict-aliasing -fwrapv -fvisibility=hidden -fvisibility-inlines-hidden
-Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict
-Wnull-dereference -Wuseless-cast -Wdouble-promotion -Wshadow -Wformat=2
-Wno-duplicated-branches)
# GCC internal compiler errors with:
# -fsanitize=undefined
......@@ -67,8 +77,18 @@ set(RQ_GNU_C_RELWITHDEBINFO -g -Ofast -fwrapv -ftree-loop-distribution -funrol
set(RQ_GNU_CXX_RELWITHDEBINFO -g -Ofast -fwrapv -ftree-loop-distribution -funroll-loops )
# clang options
set(RQ_CLANG_C_OPTIONS ${RQ_DETERMINISTIC} -std=c11 -ffast-math -fno-math-errno -Wall -pedantic -Weverything -Wno-padded -fstack-protector-all -fstrict-aliasing -Wformat -Wformat-security -Wno-disabled-macro-expansion -fvisibility=hidden -fvisibility-inlines-hidden)
set(RQ_CLANG_CXX_OPTIONS ${RQ_STDLIB_FLAG} ${RQ_DETERMINISTIC} -std=c++11 -fno-rtti -fno-exceptions -ffast-math -fno-math-errno -Wall -pedantic -Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-padded -Wno-unknown-pragmas -fstack-protector-all -fstrict-aliasing -Wformat -Wformat-security -fvisibility=hidden -fvisibility-inlines-hidden)
set(RQ_CLANG_C_OPTIONS ${RQ_DETERMINISTIC} -std=c11
-fno-math-errno -Wall -Wextra -pedantic -Weverything -Wno-padded
-fstack-protector-all -fstrict-aliasing -Wformat -Wformat-security
-Wno-disabled-macro-expansion -fvisibility=hidden -fvisibility-inlines-hidden
-Wdouble-promotion -Wshadow -Wformat=2 -Wnull-dereference)
set(RQ_CLANG_CXX_OPTIONS ${RQ_STDLIB_FLAG} ${RQ_DETERMINISTIC}
-std=c++11 -fno-rtti -fno-exceptions -fno-math-errno
-Wall -pedantic -Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat
-Wno-padded -Wno-unknown-pragmas -fstack-protector-all -fstrict-aliasing
-Wformat -Wformat-security -fvisibility=hidden -fvisibility-inlines-hidden
-Wno-documentation -Wno-documentation-unknown-command
-Wdouble-promotion -Wshadow -Wformat=2 -Wnull-dereference)
set(RQ_CLANG_C_DEBUG -O0 -g )
set(RQ_CLANG_CXX_DEBUG -O0 -g )
......@@ -96,6 +116,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(RQ_LIST_CXX_COMPILER_FLAGS ${RQ_LIST_CXX_COMPILER_FLAGS} ${RQ_CLANG_CXX_DEBUG})
if (RQ_ENABLE_UBSAN)
set(RQ_LIST_CXX_COMPILER_FLAGS ${RQ_LIST_CXX_COMPILER_FLAGS} ${RQ_CLANG_CXX_DEBUG_SANITIZE})
set(RQ_UBSAN ${RQ_CLANG_CXX_DEBUG_SANITIZE})
endif()
elseif(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
set(RQ_LIST_CXX_COMPILER_FLAGS ${RQ_LIST_CXX_COMPILER_FLAGS} ${RQ_CLANG_CXX_MINSIZEREL})
......@@ -110,6 +131,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(RQ_LIST_CXX_COMPILER_FLAGS ${RQ_LIST_CXX_COMPILER_FLAGS} ${RQ_GNU_CXX_DEBUG})
if (RQ_ENABLE_UBSAN)
set(RQ_LIST_CXX_COMPILER_FLAGS ${RQ_LIST_CXX_COMPILER_FLAGS} ${RQ_GNU_CXX_DEBUG_SANITIZE})
set(RQ_UBSAN ${RQ_GNU_CXX_DEBUG_SANITIZE})
endif()
elseif(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
set(RQ_LIST_CXX_COMPILER_FLAGS ${RQ_LIST_CXX_COMPILER_FLAGS} ${RQ_GNU_CXX_MINSIZEREL})
......
#
# Copyright (c) 2015, Luca Fulchir<luca@fulchir.it>, All rights reserved.
# Copyright (c) 2015-2018, Luca Fulchir<luca@fulchir.it>, All rights reserved.
#
# This file is part of libRaptorQ.
#
......@@ -57,5 +57,3 @@ ELSE()
ENDIF()
ENDIF()
......@@ -23,17 +23,24 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
INCLUDE(../cmake/UseLATEX.cmake)
IF (LATEX_COMPILER AND PDFLATEX_COMPILER AND MAKEINDEX_COMPILER)
ADD_LATEX_DOCUMENT(libRaptorQ.tex
INPUTS GNU_FDL.tex
USE_INDEX
MANGLE_TARGET_NAMES
NO_DEFAULT
)
ADD_LATEX_DOCUMENT(libRaptorQ-RFC6330.tex
INPUTS GNU_FDL.tex
USE_INDEX
MANGLE_TARGET_NAMES
NO_DEFAULT
)
ADD_LATEX_DOCUMENT(libRaptorQ-RaptorQ.tex
INPUTS GNU_FDL.tex
USE_INDEX
MANGLE_TARGET_NAMES
NO_DEFAULT
)
ADD_CUSTOM_TARGET(docs DEPENDS libRaptorQ_pdf)
ADD_CUSTOM_TARGET(docs DEPENDS libRaptorQ-RFC6330_pdf libRaptorQ-RaptorQ_pdf)
ELSE()
ADD_CUSTOM_TARGET(docs)
ENDIF()
INSTALL(FILES ${CMAKE_BINARY_DIR}/doc/libRaptorQ.pdf DESTINATION share/doc/ OPTIONAL)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/doc/libRaptorQ-RFC6330.pdf DESTINATION share/doc/ OPTIONAL)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/doc/libRaptorQ-RaptorQ.pdf DESTINATION share/doc/ OPTIONAL)
This diff is collapsed.
/*
* Copyright (c) 2015-2018, Luca Fulchir<luker@fenrirproject.org>,
* All rights reserved.
*
* This file is part of "libRaptorQ".
*
* libRaptorQ is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* libRaptorQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* and a copy of the GNU Lesser General Public License
* along with libRaptorQ. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../src/RaptorQ/RaptorQ_v1_hdr.hpp"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
#include <random>
#include <stdlib.h>
#include <vector>
// Demonstration of how to use the C++ RAW interface
// it's pretty simple, we generate some input,
// then encode, drop some packets (source and repair)
// and finally decode everything.
// rename the main namespace for ease of use
namespace RaptorQ = RaptorQ__v1;
// mysize is bytes.
bool test_rq (const uint32_t mysize, std::mt19937_64 &rnd,
float drop_probability,
const uint8_t overhead);
// the "overhead" variable tells us how many symbols more than the
// minimum we will generate. RaptorQ can not always decode a block,
// but there is a small probability that it will fail.
// More overhead => less probability of failure
// overhead 0 => 1% failures
// overhead 1 => 0.01% failures
// overhead 2 => 0.0001% failures
// etc... as you can see, it make little sense to work with more than 3-4
// overhead symbols, but at least one should be considered
bool test_rq (const uint32_t mysize, std::mt19937_64 &rnd,
float drop_probability,
const uint8_t overhead)
{
// the actual input.
std::vector<uint8_t> input;
input.reserve (mysize);
// initialize vector with random data
// distr should be "uint8_t". But visual studio does not like it, so
// we use uint16_t
// generate a random distribution between all values of uint8_t
std::uniform_int_distribution<int16_t> distr (0,
std::numeric_limits<uint8_t>::max());
// fill our input with random data
for (size_t idx = 0; idx < mysize; ++idx) {
input.push_back (static_cast<uint8_t> (distr(rnd)));
}
// the input will be divided in blocks of 4 bytes.
// it's a bit low, but this is just an example.
// NOTE: the symbol size must be a multiple of the container size.
// since sizeof(uint8_t) == 1 and 4 is a multiple of 1, we are safe.
const uint16_t symbol_size = 4; // bytes
// how many symbols do we need to encode all our input in a single block?
auto min_symbols = (input.size() * sizeof(uint8_t)) / symbol_size;
if ((input.size() * sizeof(uint8_t)) % symbol_size != 0)
++min_symbols;
// convert "symbols" to a typesafe equivalent, RaptorQ::Block_Size
// This is needed becouse not all numbers are valid block sizes, and this
// helps you choose the right block size
RaptorQ::Block_Size block = RaptorQ::Block_Size::Block_10;
for (auto blk : *RaptorQ::blocks) {
// RaptorQ::blocks is a pointer to an array, just scan it to find your
// block.
if (static_cast<uint16_t> (blk) >= min_symbols) {
block = blk;
break;
}
}
// now initialize the encoder.
// the input for the encoder is std::vector<uint8_t>
// the output for the encoder is std::vector<uint8_t>
// yes, you can have different types, but most of the time you will
// want to work with uint8_t
RaptorQ::Encoder<typename std::vector<uint8_t>::iterator,
typename std::vector<uint8_t>::iterator> enc (
block, symbol_size);
// give the input to the encoder. the encoder answers with the size of what
// it can use
if (enc.set_data (input.begin(), input.end()) != mysize) {
std::cout << "Could not give data to the encoder :(\n";
return false;
}
// actual symbols. you could just use static_cast<uint16_t> (blok)
// but this way you can actually query the encoder.
uint16_t _symbols = enc.symbols();
// print some stuff in output
std::cout << "Size: " << mysize << " symbols: " <<
static_cast<uint32_t> (_symbols) <<
" symbol size: " <<
static_cast<int32_t>(enc.symbol_size()) << "\n";
// RQ need to do its magic on the input before you can ask the symbols.
// multiple ways to do this are available.
// The simplest is to run the computation and block everything until
// the work has been done. Not a problem for small sizes (<200),
// but big sizes will take **a lot** of time, consider running this with the
// asynchronous calls
if (!enc.compute_sync()) {
// if this happens it's a bug in the library.
// the **Decoder** can fail, but the **Encoder** can never fail.
std::cout << "Enc-RaptorQ failure! really bad!\n";
return false;
}
// the probability that a symbol will be dropped.
if (drop_probability > static_cast<float> (90.0))
drop_probability = 90.0; // this is still too high probably.
// we will store here all encoded and transmitted symbols
// std::pair<symbol id (esi), symbol data>
using symbol_id = uint32_t; // just a better name
std::vector<std::pair<symbol_id, std::vector<uint8_t>>> received;
{
// in this block we will generate the symbols that will be sent to
// the decoder.
// a block of size X will need at least X symbols to be decoded.
// we will randomly drop some symbols, but we will keep generating
// repari symbols until we have the required number of symbols.
std::uniform_real_distribution<float> drop_rnd (0.0, 100.0);
uint32_t received_tot = 0;
// Now get the source symbols.
// source symbols are specials because they contain the input data
// as-is, so if you get all of these, you don't need repair symbols
// to make sure that we are using the decoder, drop the first
// source symbol.
auto source_sym_it = enc.begin_source();
++source_sym_it; // ignore the first soure symbol (=> drop it)
source_sym_it++;
for (; source_sym_it != enc.end_source(); ++source_sym_it) {
// we save the symbol here:
// make sure the vector has enough space for the symbol:
// fill it with zeros for the size of the symbol
std::vector<uint8_t> source_sym_data (symbol_size, 0);
// save the data of the symbol into our vector
auto it = source_sym_data.begin();
auto written = (*source_sym_it) (it, source_sym_data.end());
if (written != symbol_size) {
// this can only happen if "source_sym_data" did not have
// enough space for a symbol (here: never)
std::cout << written << "-vs-" << symbol_size <<
" Could not get the whole source symbol!\n";
return false;
}
// can we keep this symbol or do we randomly drop it?
float dropped = drop_rnd (rnd);
if (dropped <= drop_probability) {
continue; // start the cycle again
}
// good, the symbol was received.
++received_tot;
// add it to the vector of received symbols
symbol_id tmp_id = (*source_sym_it).id();
received.emplace_back (tmp_id, std::move(source_sym_data));
}
std::cout << "Source Packet lost: " << enc.symbols() - received.size()
<< "\n";
//--------------------------------------------
// we finished working with the source symbols.
// now we need to transmit the repair symbols.
auto repair_sym_it = enc.begin_repair();
auto max_repair = enc.max_repair(); // RaptorQ can theoretically handle
// infinite repair symbols
// but computers are not so infinite
// we need to have at least enc.symbols() + overhead symbols.
for (; received.size() < (enc.symbols() + overhead) &&
repair_sym_it != enc.end_repair (max_repair);
++repair_sym_it) {
// we save the symbol here:
// make sure the vector has enough space for the symbol:
// fill it with zeros for the size of the symbol
std::vector<uint8_t> repair_sym_data (symbol_size, 0);
// save the data of the symbol into our vector
auto it = repair_sym_data.begin();
auto written = (*repair_sym_it) (it, repair_sym_data.end());
if (written != symbol_size) {
// this can only happen if "repair_sym_data" did not have
// enough space for a symbol (here: never)
std::cout << written << "-vs-" << symbol_size <<
" Could not get the whole repair symbol!\n";
return false;
}
// can we keep this symbol or do we randomly drop it?
float dropped = drop_rnd (rnd);
if (dropped <= drop_probability) {
continue; // start the cycle again
}
// good, the symbol was received.
++received_tot;
// add it to the vector of received symbols
symbol_id tmp_id = (*repair_sym_it).id();
received.emplace_back (tmp_id, std::move(repair_sym_data));
}
if (repair_sym_it == enc.end_repair (enc.max_repair())) {
// we dropped waaaay too many symbols!
// should never happen in real life. it means that we do not
// have enough repair symbols.
// at this point you can actually start to retransmit the
// repair symbols from enc.begin_repair(), but we don't care in
// this example
std::cout << "Maybe losing " << drop_probability << "% is too much?\n";
return false;
}
}
// Now we all the source and repair symbols are in "received".
// we will use those to start decoding:
// define "Decoder_type" to write less afterwards
using Decoder_type = RaptorQ::Decoder<
typename std::vector<uint8_t>::iterator,
typename std::vector<uint8_t>::iterator>;
Decoder_type dec (block, symbol_size, Decoder_type::Report::COMPLETE);
// "Decoder_type::Report::COMPLETE" means that the decoder will not
// give us any output until we have decoded all the data.
// there are modes to extract the data symbol by symbol in an ordered
// an unordered fashion, but let's keep this simple.
// we will store the output of the decoder here:
// note: the output need to have at least "mysize" bytes, and
// we fill it with zeros
std::vector<uint8_t> output (mysize, 0);
// now push every received symbol into the decoder
for (auto &rec_sym : received) {
// as a reminder:
// rec_sym.first = symbol_id (uint32_t)
// rec_sym.second = std::vector<uint8_t> symbol_data
symbol_id tmp_id = rec_sym.first;
auto it = rec_sym.second.begin();
auto err = dec.add_symbol (it, rec_sym.second.end(), tmp_id);
if (err != RaptorQ::Error::NONE && err != RaptorQ::Error::NOT_NEEDED) {
// When you add a symbol, you can get:
// NONE: no error
// NOT_NEEDED: libRaptorQ ignored it because everything is
// already decoded
// INITIALIZATION: wrong parameters to the decoder contructor
// WRONG_INPUT: not enough data on the symbol?
// some_other_error: errors in the library
std::cout << "error adding?\n";
return false;
}
}
// by now we now there will be no more input, so we tell this to the
// decoder. You can skip this call, but if the decoder does not have
// enough data it sill wait forever (or until you call .stop())
dec.end_of_input (RaptorQ::Fill_With_Zeros::NO);
// optional if you want partial decoding without using the repair
// symbols
// std::vector<bool> symbols_bitmask = dec.end_of_input (
// RaptorQ::Fill_With_Zeros::YES);
// decode, and do not return until the computation is finished.
auto res = dec.wait_sync();
if (res.error != RaptorQ::Error::NONE) {
std::cout << "Couldn't decode.\n";
return false;
}
// now save the decoded data in our output
size_t decode_from_byte = 0;
size_t skip_bytes_at_begining_of_output = 0;
auto out_it = output.begin();
auto decoded = dec.decode_bytes (out_it, output.end(), decode_from_byte,
skip_bytes_at_begining_of_output);
// "decode_from_byte" can be used to have only a part of the output.
// it can be used in advanced setups where you ask only a part
// of the block at a time.
// "skip_bytes_at_begining_of_output" is used when dealing with containers
// which size does not align with the output. For really advanced usage only
// Both should be zero for most setups.
if (decoded.written != mysize) {
if (decoded.written == 0) {
// we were really unlucky and the RQ algorithm needed
// more symbols!
std::cout << "Couldn't decode, RaptorQ Algorithm failure. "
"Can't Retry.\n";
} else {
// probably a library error
std::cout << "Partial Decoding? This should not have happened: " <<
decoded.written << " vs " << mysize << "\n";
}
return false;
} else {
std::cout << "Decoded: " << mysize << "\n";
}
// byte-wise check: did we actually decode everything the right way?
for (uint64_t i = 0; i < mysize; ++i) {
if (input[i] != output[i]) {
// this is a bug in the library, please report
std::cout << "The output does not correspond to the input!\n";
return false;
}
}
return true;
}
int main (void)
{
// get a random number generator
std::mt19937_64 rnd;
std::ifstream rand("/dev/urandom");
uint64_t seed = 0;
rand.read (reinterpret_cast<char *> (&seed), sizeof(seed));
rand.close ();
rnd.seed (seed);
// keep some computation in memory. If you use only one block size it
// will make things faster on bigger block size.
// allocate 5Mb
RaptorQ__v1::local_cache_size (5000000);
// for our test, we use an input of random size, between 100 and 10.000
// bytes.
std::uniform_int_distribution<uint32_t> distr(100, 10000);
uint32_t input_size = distr (rnd);
if (!test_rq (input_size, rnd, 20.0, 4))
return -1;
std::cout << "The example completed successfully\n";
return 0;
}
......@@ -19,31 +19,67 @@
if(RQ_BUILD_LZ4)
# build lz4, then it will be statically linked in the library
include(ExternalProject)
set(RQ_LZ4_BUILDNAME lz4_static)
ExternalProject_Add(${RQ_LZ4_BUILDNAME}
GIT_REPOSITORY file://${PROJECT_SOURCE_DIR}/external/lz4
GIT_TAG d86dc916771c126afb797637dda9f6421c0cb998
CONFIGURE_COMMAND ""
BUILD_COMMAND make lib
BUILD_IN_SOURCE 1
INSTALL_COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${RQ_LZ4_BUILDNAME}-prefix/src/${RQ_LZ4_BUILDNAME}/lib/liblz4.a ${CMAKE_CURRENT_BINARY_DIR}
)
#
# target: LZ4 static library
#
set(RQ_LZ4_VERSION_MAJOR 1)
set(RQ_LZ4_VERSION_MINOR 5)
set(RQ_LZ4_VERSION_PATCH r128)
set(RQ_LZ4_VERSION_STRING " \"${RQ_LZ4_VERSION_MAJOR}.${RQ_LZ4_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}\" ")
add_custom_command(
OUTPUT lz4_deterministic.run
COMMAND make_deterministic ${CMAKE_CURRENT_BINARY_DIR}/liblz4.a
DEPENDS ${RQ_LZ4_BUILDNAME} make_deterministic
COMMENT "Removing creation date from lz4 library..."
VERBATIM
)
add_library(rq_lz4 STATIC IMPORTED)
set_target_properties(rq_lz4 PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/liblz4.a)
add_custom_target(LZ4 DEPENDS lz4_deterministic.run)
set(RQ_LZ4_DEP rq_lz4)
set(RQ_LZ4_LIBNAME rq_lz4_static)
set(RQ_LZ4_DIR ${PROJECT_SOURCE_DIR}/external/lz4/lib/)
set(RQ_LZ4_SRCS_LIB ${RQ_LZ4_DIR}lz4.c
${RQ_LZ4_DIR}lz4hc.c
${RQ_LZ4_DIR}lz4.h
${RQ_LZ4_DIR}lz4hc.h
${RQ_LZ4_DIR}lz4frame.c
${RQ_LZ4_DIR}lz4frame.h
${RQ_LZ4_DIR}xxhash.c)
add_library(${RQ_LZ4_LIBNAME} STATIC ${RQ_LZ4_SRCS_LIB})
include(CheckCCompilerFlag)
check_c_compiler_flag("-fPIC" RQ_LZ4_PIC)
if(RQ_LZ4_PIC)
target_compile_options(
${RQ_LZ4_LIBNAME} PRIVATE
"-fPIC"
)
endif()
check_c_compiler_flag("-std=c99" RQ_FLAG_C_99)
if(RQ_FLAG_C_99)
target_compile_options(
${RQ_LZ4_LIBNAME} PRIVATE
"-std=c99"
)
endif()
set_target_properties(${RQ_LZ4_LIBNAME} PROPERTIES
SOVERSION "${RQ_LZ4_VERSION_MAJOR}.${RQ_LZ4_VERSION_MINOR}")
#set_property(TARGET lz4_static PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
ADD_DEFINITIONS("-DLZ4_VERSION=\"${RQ_LZ4_VERSION_PATCH}\"")
INCLUDE_DIRECTORIES (SYSTEM PUBLIC ${RQ_LZ4_DIR})
# NOTE: will be used like "-Wl..flag,flag,flag" . no spaces, and keep the comma
set(RQ_LZ4_EXCLUDE_SYM ",--exclude-libs lib${RQ_LZ4_LIBNAME}.a")
# set the dependency and build it all
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
add_custom_target(LZ4 DEPENDS ${RQ_LZ4_LIBNAME})
set(RQ_LZ4_DEP ${RQ_LZ4_LIBNAME})
else()
add_custom_command(
OUTPUT lz4_deterministic.run
COMMAND make_deterministic ${CMAKE_CURRENT_BINARY_DIR}/lib${RQ_LZ4_LIBNAME}.a
DEPENDS ${RQ_LZ4_LIBNAME} make_deterministic
COMMENT "Removing creation date from lz4 library..."
VERBATIM
)
add_custom_target(LZ4 DEPENDS lz4_deterministic.run)
set(RQ_LZ4_DEP ${RQ_LZ4_LIBNAME})
endif()
else()
add_custom_target(LZ4)
add_custom_target(LZ4)
if (USE_LZ4 MATCHES "ON")
set(RQ_LZ4_DEP ${RQ_LZ4_LIB})
endif()
......
repo: 8a21fd850624c931e448cbcfb38168cb2717c790
node: b9cd8366d4e8f49471c7afafc4c2a1b00e54a54d
branch: 3.2
tag: 3.2.10
node: 5a0156e40feb7c4136680b493c6e433d91a6f355
branch: 3.3
tag: 3.3.4
[patterns]
*.sh = LF
*.MINPACK = CRLF
scripts/*.in = LF
debug/msvc/*.dat = CRLF
debug/msvc/*.natvis = CRLF
unsupported/test/mpreal/*.* = CRLF
** = native
......
......@@ -30,3 +30,5 @@ log
patch
a
a.*
lapack/testing
lapack/reference
......@@ -21,15 +21,13 @@ a810d5dbab47acfe65b3350236efdd98f67d4d8a 3.1.0-alpha1
8383e883ebcc6f14695ff0b5e20bb631abab43fb 3.1.0-rc1
bf4cb8c934fa3a79f45f1e629610f0225e93e493 3.1.0-rc2
da195914abcc1d739027cbee7c52077aab30b336 3.2-beta1
4b687cad1d23066f66863f4f87298447298443df 3.2-rc1
1eeda7b1258bcd306018c0738e2b6a8543661141 3.2-rc2
ffa86ffb557094721ca71dcea6aed2651b9fd610 3.2.0
6b38706d90a9fe182e66ab88477b3dbde34b9f66 3.2.1
1306d75b4a21891e59ff9bd96678882cf831e39f 3.2.2
36fd1ba04c120cfdd90f3e4cede47f43b21d19ad 3.2.3
10219c95fe653d4962aa9db4946f6fbea96dd740 3.2.4
bdd17ee3b1b3a166cd5ec36dcad4fc1f3faf774a 3.2.5
c58038c56923e0fd86de3ded18e03df442e66dfb 3.2.6
b30b87236a1b1552af32ac34075ee5696a9b5a33 3.2.7
07105f7124f9aef00a68c85e0fc606e65d3d6c15 3.2.8
dc6cfdf9bcec5efc7b6593bddbbb3d675de53524 3.2.9
a8e0d153fc5e239ef8b06e3665f1f9e8cb8d49c8 before-evaluators
09a8e21866106b49c5dec1d6d543e5794e82efa0 3.3-alpha1
ce5a455b34c0a0ac3545a1497cb4a16c38ed90e8 3.3-beta1
69d418c0699907bcd0bf9e0b3ba0a112ed091d85 3.3-beta2
bef509908b9da05d0d07ffc0da105e2c8c6d3996 3.3-rc1
04ab5fa4b241754afcf631117572276444c67239 3.3-rc2
26667be4f70baf4f0d39e96f330714c87b399090 3.3.0
f562a193118d4f40514e2f4a0ace6e974926ef06 3.3.1
da9b4e14c2550e0d11078a3c39e6d56eba9905df 3.3.2
67e894c6cd8f5f1f604b27d37ed47fdf012674ff 3.3.3