Compare commits
45
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b6365732a | ||
|
|
68c6b62b4b | ||
|
|
ec505c7d5a | ||
|
|
e1b24895e6 | ||
|
|
ac3d43b691 | ||
|
|
fbc48b39c6 | ||
|
|
29009a8e51 | ||
|
|
4beec37a1d | ||
|
|
933a38a460 | ||
|
|
64715f43d8 | ||
|
|
2526dcf136 | ||
|
|
b36260b443 | ||
|
|
345a2204ca | ||
|
|
81dd27c4f6 | ||
|
|
55f9b17864 | ||
|
|
3119997522 | ||
|
|
fc9a3bbc78 | ||
|
|
25e2b1dd25 | ||
|
|
4b479c1e0b | ||
|
|
bf1f2ab6eb | ||
|
|
fde1856728 | ||
|
|
16350adcff | ||
|
|
012aea0351 | ||
|
|
c52c62ba78 | ||
|
|
3b04521726 | ||
|
|
fa3268c3df | ||
|
|
5d4a4acf95 | ||
|
|
0063fb3c76 | ||
|
|
d8251013ce | ||
|
|
444fd2bd0f | ||
|
|
3e9e8c9c4d | ||
|
|
c46e2aa03e | ||
|
|
a497817ca0 | ||
|
|
8b6f831c68 | ||
|
|
6aa706d879 | ||
|
|
6caecf9630 | ||
|
|
be66b3a1cf | ||
|
|
478de5b188 | ||
|
|
9e15720bc7 | ||
|
|
4523a7615e | ||
|
|
b15aabb39a | ||
|
|
d86ed7fbaa | ||
|
|
8dcbd5b11b | ||
|
|
49e08aac08 | ||
|
|
51c0b2f742 |
@@ -0,0 +1,45 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.c text
|
||||
*.h text
|
||||
*.cpp text
|
||||
*.def text
|
||||
*.rc text
|
||||
*.i text
|
||||
*.sh text
|
||||
*.csh text
|
||||
*.mk text
|
||||
*.java text
|
||||
*.csv text
|
||||
*.lst text
|
||||
*.asm text
|
||||
*.cfg text
|
||||
*.css text
|
||||
*.inc text
|
||||
*.js text
|
||||
*.rb text
|
||||
*.strings text
|
||||
*.txt text
|
||||
*export.lst text
|
||||
*.xml text
|
||||
*.py text
|
||||
*.md text
|
||||
*.classpath text
|
||||
*.cproject text
|
||||
*.project text
|
||||
*.properties text
|
||||
*.java text
|
||||
*.gradle text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.sln text eol=crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.ico binary
|
||||
*.spir binary
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
SCAN_TARGET=$1
|
||||
|
||||
SKIP_PATTERN='*/.github/*'
|
||||
|
||||
# Ignored cases
|
||||
IGNORE_COMMAND="sed -e /.*\\sOd\\s*=.*/d \
|
||||
-e /.*\\sOt\\s*=.*/d \
|
||||
-e /.*\\siff\\s*=.*/d \
|
||||
-e /.*\\sith\\s*=.*/d \
|
||||
-e /.*\\scas\\s*=.*/d \
|
||||
-e /.*\\sCAS\\s*=.*/d \
|
||||
-e /.*\\ssom\\s*=.*/d \
|
||||
-e /.*\\sSOM\\s*=.*/d \
|
||||
-e /.*\\suint\\s*=.*/d \
|
||||
-e /.*\\sUINT\\s*=.*/d \
|
||||
-e /.*\\scopyable\\s*=.*/d \
|
||||
-e /.*\\sCopyable\\s*=.*/d \
|
||||
-e /.*\\sFo\\s*=.*/d \
|
||||
-e /.*pipeline_filters.h.*nd\\s*=.*/d \
|
||||
-e /.*ittnotify.h.*unx\\s*=.*/d \
|
||||
-e /.*bzlib.cpp.*MSDOS\\s*=.*/d \
|
||||
-e /.*test_task.cpp.*tE\\s*=.*/d \
|
||||
-e /.*backend.cpp.*resSize\\s*=.*/d \
|
||||
-e /.*test_join_node.h.*Ned\\s*=.*/d \
|
||||
-e /.*test_indexer_node.cpp.*OT\\s*=.*/d \
|
||||
-e /.*allocator_stl_test_common.h.*Aci*\\s*=.*/d \
|
||||
-e /.*seismic_video.cpp.*DialogBox\\s*=.*/d \
|
||||
-e /.*test_composite_node.cpp.*que\\s*=.*/d \
|
||||
-e /.*blocksort.cpp.*hiSt\\s*=.*/d \
|
||||
-e /.*compress.cpp.*fave\\s*=.*/d \
|
||||
-e /.*count_strings.cpp.*ue\\s*=.*/d \
|
||||
-e /.*count_strings.cpp.*nd\\s*=.*/d \
|
||||
-e /.*count_strings.cpp.*ths\\s*=.*/d \
|
||||
-e /.*polygon_overlay\/README.md.*ist\\s*=.*/d \
|
||||
-e /.*_pipeline_filters.h.*nd\\s*=.*/d \
|
||||
-e /.*sub_string_finder\/README.md.*ba\\s*=.*/d"
|
||||
|
||||
SCAN_RESULT=`codespell --quiet-level=2 --skip "${SKIP_PATTERN}" ${SCAN_TARGET}`
|
||||
SCAN_RESULT=`echo -e "${SCAN_RESULT}" | ${IGNORE_COMMAND}`
|
||||
echo "${SCAN_RESULT}"
|
||||
|
||||
if [[ ! -z ${SCAN_RESULT} ]]; then
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,264 @@
|
||||
# Copyright (c) 2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
name: oneTBB CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
pull_request:
|
||||
branches: [master]
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
|
||||
env:
|
||||
BUILD_CONCURRENCY: 2
|
||||
MACOS_BUILD_CONCURRENCY: 3
|
||||
TEST_TIMEOUT: 180
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
runs-on: [ubuntu-20.04]
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run scan
|
||||
run: |
|
||||
sudo apt update && sudo apt install -y codespell
|
||||
${GITHUB_WORKSPACE}/.github/scripts/codespell.sh `pwd`
|
||||
|
||||
examples_clang-format:
|
||||
runs-on: [ubuntu-20.04]
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run scan
|
||||
run: |
|
||||
cp -r examples examples_formatted
|
||||
find examples_formatted -regex '.*\.\(cpp\|hpp\)' -exec clang-format-9 -style=file -i {} \;
|
||||
diff -r examples examples_formatted
|
||||
|
||||
python_module_test_ubuntu18-04:
|
||||
runs-on: [ubuntu-18.04]
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake -DTBB4PY_BUILD=ON -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc ..
|
||||
make VERBOSE=1 -j${BUILD_CONCURRENCY} python_build
|
||||
ctest -R python_test --output-on-failure --timeout ${TEST_TIMEOUT}
|
||||
|
||||
linux-testing:
|
||||
name: ${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
|
||||
runs-on: ['${{ matrix.os }}']
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
c_compiler: gcc
|
||||
cxx_compiler: g++
|
||||
std: 14
|
||||
build_type: relwithdebinfo
|
||||
preview: 'OFF'
|
||||
- os: ubuntu-20.04
|
||||
c_compiler: gcc
|
||||
cxx_compiler: g++
|
||||
std: 17
|
||||
build_type: release
|
||||
preview: 'ON'
|
||||
- os: ubuntu-20.04
|
||||
c_compiler: gcc-10
|
||||
cxx_compiler: g++-10
|
||||
std: 20
|
||||
build_type: debug
|
||||
preview: 'ON'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} ..
|
||||
make VERBOSE=1 -j${BUILD_CONCURRENCY}
|
||||
ctest --timeout ${TEST_TIMEOUT} --output-on-failure
|
||||
|
||||
macos-testing:
|
||||
name: ${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
|
||||
runs-on: ['${{ matrix.os }}']
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-10.15
|
||||
c_compiler: clang
|
||||
cxx_compiler: clang++
|
||||
std: 14
|
||||
build_type: relwithdebinfo
|
||||
preview: 'ON'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} ..
|
||||
make VERBOSE=1 -j${MACOS_BUILD_CONCURRENCY}
|
||||
ctest --timeout ${TEST_TIMEOUT} --output-on-failure
|
||||
|
||||
windows-testing:
|
||||
name: ${{ matrix.job_name }}
|
||||
runs-on: ['${{ matrix.os }}']
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2016
|
||||
generator: Visual Studio 15 2017
|
||||
c_compiler: cl
|
||||
cxx_compiler: cl
|
||||
std: 14
|
||||
build_type: relwithdebinfo
|
||||
preview: 'ON'
|
||||
job_name: windows_cl2017_cxx14_relwithdebinfo_preview=ON
|
||||
- os: windows-2019
|
||||
generator: Visual Studio 16 2019
|
||||
c_compiler: cl
|
||||
cxx_compiler: cl
|
||||
std: 17
|
||||
build_type: relwithdebinfo
|
||||
preview: 'OFF'
|
||||
job_name: windows_cl2019_cxx17_relwithdebinfo_preview=OFF
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "${{ matrix.generator }}" -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.std }} `
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} `
|
||||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} ..
|
||||
cmake --build . --config ${{ matrix.build_type }} -j -v
|
||||
ctest -C ${{ matrix.build_type }} --timeout ${env:TEST_TIMEOUT} --output-on-failure
|
||||
|
||||
linux-examples-testing:
|
||||
name: examples_${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
|
||||
runs-on: ['${{ matrix.os }}']
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
c_compiler: gcc
|
||||
cxx_compiler: g++
|
||||
std: 14
|
||||
build_type: relwithdebinfo
|
||||
preview: 'OFF'
|
||||
- os: ubuntu-20.04
|
||||
c_compiler: gcc
|
||||
cxx_compiler: g++
|
||||
std: 17
|
||||
build_type: release
|
||||
preview: 'ON'
|
||||
- os: ubuntu-20.04
|
||||
c_compiler: gcc-10
|
||||
cxx_compiler: g++-10
|
||||
std: 20
|
||||
build_type: debug
|
||||
preview: 'ON'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \
|
||||
-DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
|
||||
cmake --build . -v --target light_test_examples
|
||||
|
||||
macos-examples-testing:
|
||||
name: examples_${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
|
||||
runs-on: ['${{ matrix.os }}']
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-10.15
|
||||
c_compiler: clang
|
||||
cxx_compiler: clang++
|
||||
std: 14
|
||||
build_type: relwithdebinfo
|
||||
preview: 'ON'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \
|
||||
-DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
|
||||
cmake --build . -v --target light_test_examples
|
||||
|
||||
windows-examples-testing:
|
||||
name: ${{ matrix.job_name }}
|
||||
runs-on: ['${{ matrix.os }}']
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2016
|
||||
generator: Visual Studio 15 2017
|
||||
c_compiler: cl
|
||||
cxx_compiler: cl
|
||||
std: 14
|
||||
build_type: relwithdebinfo
|
||||
preview: 'ON'
|
||||
job_name: examples_windows_cl2017_cxx14_relwithdebinfo_preview=ON
|
||||
- os: windows-2019
|
||||
generator: Visual Studio 16 2019
|
||||
c_compiler: cl
|
||||
cxx_compiler: cl
|
||||
std: 17
|
||||
build_type: relwithdebinfo
|
||||
preview: 'OFF'
|
||||
job_name: examples_windows_cl2019_cxx17_relwithdebinfo_preview=OFF
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run testing
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "${{ matrix.generator }}" -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.std }} `
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} `
|
||||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
|
||||
cmake --build . -v --target light_test_examples
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
# -------- C++ --------
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# -------- CMake --------
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
build/*
|
||||
|
||||
# -------- Python --------
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# -------- IDE --------
|
||||
.vscode/*
|
||||
.vs/*
|
||||
out/*
|
||||
CMakeSettings.json
|
||||
|
||||
# -------- CTags --------
|
||||
.tags
|
||||
.ctags
|
||||
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
# Enable CMake policies
|
||||
|
||||
if (POLICY CMP0091)
|
||||
# The NEW behavior for this policy is to not place MSVC runtime library flags in the default
|
||||
# CMAKE_<LANG>_FLAGS_<CONFIG> cache entries and use CMAKE_MSVC_RUNTIME_LIBRARY abstraction instead.
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
elseif (DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||
message(FATAL_ERROR "CMAKE_MSVC_RUNTIME_LIBRARY was defined while policy CMP0091 is not available. Use CMake 3.15 or newer.")
|
||||
endif()
|
||||
|
||||
if (TBB_WINDOWS_DRIVER AND (NOT ("${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL MultiThreaded OR "${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL MultiThreadedDebug)))
|
||||
message(FATAL_ERROR "Enabled TBB_WINDOWS_DRIVER requires CMAKE_MSVC_RUNTIME_LIBRARY to be set to MultiThreaded or MultiThreadedDebug.")
|
||||
endif()
|
||||
|
||||
# Enable support of minimum supported macOS version flag
|
||||
if (APPLE)
|
||||
if (NOT CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG)
|
||||
set(CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG "-mmacosx-version-min=" CACHE STRING "Minimum macOS version flag")
|
||||
endif()
|
||||
if (NOT CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG)
|
||||
set(CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG "-mmacosx-version-min=" CACHE STRING "Minimum macOS version flag")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Until CMake 3.4.0 FindThreads.cmake requires C language enabled.
|
||||
# Enable C language before CXX to avoid possible override of CMAKE_SIZEOF_VOID_P.
|
||||
if (CMAKE_VERSION VERSION_LESS 3.4)
|
||||
enable_language(C)
|
||||
endif()
|
||||
|
||||
file(READ include/oneapi/tbb/version.h _tbb_version_info)
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" _tbb_ver_major "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" _tbb_ver_minor "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_PATCH ([0-9]+).*" "\\1" _tbb_ver_patch "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define __TBB_BINARY_VERSION ([0-9]+).*" "\\1" TBB_BINARY_VERSION "${_tbb_version_info}")
|
||||
set(TBB_BINARY_MINOR_VERSION ${_tbb_ver_minor})
|
||||
set(TBBMALLOC_BINARY_VERSION 2)
|
||||
set(TBBBIND_BINARY_VERSION 3)
|
||||
|
||||
project(TBB VERSION ${_tbb_ver_major}.${_tbb_ver_minor}.${_tbb_ver_patch} LANGUAGES CXX)
|
||||
unset(_tbb_ver_major)
|
||||
unset(_tbb_ver_minor)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------
|
||||
# Handle C++ standard version.
|
||||
if (NOT MSVC) # no need to cover MSVC as it uses C++14 by default.
|
||||
if (NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION) # if standard option was detected by CMake
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
else() # if standard option wasn't detected by CMake (e.g. for Intel Compiler with CMake 3.1)
|
||||
# TBB_CXX_STD_FLAG should be added to targets via target_compile_options
|
||||
set(TBB_CXX_STD_FLAG -std=c++${CMAKE_CXX_STANDARD})
|
||||
|
||||
check_cxx_compiler_flag(${TBB_CXX_STD_FLAG} c++${CMAKE_CXX_STANDARD})
|
||||
if (NOT c++${CMAKE_CXX_STANDARD})
|
||||
message(FATAL_ERROR "C++${CMAKE_CXX_STANDARD} (${TBB_CXX_STD_FLAG}) support is required")
|
||||
endif()
|
||||
unset(c++${CMAKE_CXX_STANDARD})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_EXTENSIONS OFF) # use -std=c++... instead of -std=gnu++...
|
||||
# ---------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Detect architecture (bitness).
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(TBB_ARCH 32)
|
||||
else()
|
||||
set(TBB_ARCH 64)
|
||||
endif()
|
||||
|
||||
option(TBB_TEST "Enable testing" ON)
|
||||
option(TBB_EXAMPLES "Enable examples" OFF)
|
||||
option(TBB_STRICT "Treat compiler warnings as errors" ON)
|
||||
option(TBB_WINDOWS_DRIVER "Build as Universal Windows Driver (UWD)" OFF)
|
||||
option(TBB_NO_APPCONTAINER "Apply /APPCONTAINER:NO (for testing binaries for Windows Store)" OFF)
|
||||
option(TBB4PY_BUILD "Enable tbb4py build" OFF)
|
||||
option(TBB_CPF "Enable preview features of the library" OFF)
|
||||
option(TBB_FIND_PACKAGE "Enable search for external oneTBB using find_package instead of build from sources" OFF)
|
||||
|
||||
if (NOT DEFINED BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
endif()
|
||||
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
message(WARNING "You are building oneTBB as a static library. This is highly discouraged and such configuration is not supported. Consider building a dynamic library to avoid unforeseen issues.")
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type" FORCE)
|
||||
message(STATUS "CMAKE_BUILD_TYPE is not specified. Using default: ${CMAKE_BUILD_TYPE}")
|
||||
# Possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Files and folders naming
|
||||
set(CMAKE_DEBUG_POSTFIX _debug)
|
||||
|
||||
if (NOT DEFINED TBB_OUTPUT_DIR_BASE)
|
||||
if (MSVC)
|
||||
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES DLL)
|
||||
set(_tbb_msvc_runtime _md)
|
||||
else()
|
||||
set(_tbb_msvc_runtime _mt)
|
||||
endif()
|
||||
|
||||
if (WINDOWS_STORE)
|
||||
if (TBB_NO_APPCONTAINER)
|
||||
set(_tbb_win_store _wsnoappcont)
|
||||
else()
|
||||
set(_tbb_win_store _ws)
|
||||
endif()
|
||||
elseif(TBB_WINDOWS_DRIVER)
|
||||
set(_tbb_win_store _wd)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(REGEX MATCH "^([0-9]+\.[0-9]+|[0-9]+)" _tbb_compiler_version_short ${CMAKE_CXX_COMPILER_VERSION})
|
||||
string(TOLOWER ${CMAKE_CXX_COMPILER_ID}_${_tbb_compiler_version_short}_cxx${CMAKE_CXX_STANDARD}_${TBB_ARCH}${_tbb_msvc_runtime}${_tbb_win_store} TBB_OUTPUT_DIR_BASE)
|
||||
unset(_tbb_msvc_runtime)
|
||||
unset(_tbb_win_store)
|
||||
unset(_tbb_compiler_version_short)
|
||||
endif()
|
||||
|
||||
foreach(output_type LIBRARY ARCHIVE PDB RUNTIME)
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} _tbb_build_type_lower)
|
||||
set(CMAKE_${output_type}_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${TBB_OUTPUT_DIR_BASE}_${_tbb_build_type_lower})
|
||||
unset(_tbb_build_type_lower)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CONFIGURATION_TYPES)
|
||||
foreach(suffix ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER ${suffix} _tbb_suffix_upper)
|
||||
string(TOLOWER ${suffix} _tbb_suffix_lower)
|
||||
set(CMAKE_${output_type}_OUTPUT_DIRECTORY_${_tbb_suffix_upper} ${CMAKE_BINARY_DIR}/${TBB_OUTPUT_DIR_BASE}_${_tbb_suffix_lower})
|
||||
endforeach()
|
||||
unset(_tbb_suffix_lower)
|
||||
unset(_tbb_suffix_upper)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Common dependencies
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
file(GLOB FILES_WITH_EXTRA_TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/*.cmake)
|
||||
foreach(FILE_WITH_EXTRA_TARGETS ${FILES_WITH_EXTRA_TARGETS})
|
||||
include(${FILE_WITH_EXTRA_TARGETS})
|
||||
endforeach()
|
||||
|
||||
set(TBB_COMPILER_SETTINGS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compilers/${CMAKE_CXX_COMPILER_ID}.cmake)
|
||||
if (EXISTS ${TBB_COMPILER_SETTINGS_FILE})
|
||||
include(${TBB_COMPILER_SETTINGS_FILE})
|
||||
else()
|
||||
message(WARNING "TBB compiler settings not found ${TBB_COMPILER_SETTINGS_FILE}")
|
||||
endif()
|
||||
|
||||
if (TBB_FIND_PACKAGE OR TBB_DIR)
|
||||
# Allow specifying external TBB to test with.
|
||||
# Do not add main targets and installation instructions in that case.
|
||||
message(STATUS "Using external TBB for testing")
|
||||
find_package(TBB REQUIRED)
|
||||
else()
|
||||
add_subdirectory(src/tbb)
|
||||
if (NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
|
||||
add_subdirectory(src/tbbmalloc)
|
||||
add_subdirectory(src/tbbmalloc_proxy)
|
||||
if (APPLE)
|
||||
message(STATUS "TBBBind build target is disabled due to unsupported environment")
|
||||
else()
|
||||
add_subdirectory(src/tbbbind)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Installation instructions
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
install(DIRECTORY include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
COMPONENT devel)
|
||||
|
||||
install(EXPORT ${PROJECT_NAME}Targets
|
||||
NAMESPACE TBB::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
COMPONENT devel)
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
"include(\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}Targets.cmake)\n")
|
||||
|
||||
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
COMPONENT devel)
|
||||
|
||||
install(FILES "README.md"
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||
COMPONENT devel)
|
||||
# -------------------------------------------------------------------
|
||||
endif()
|
||||
|
||||
if (TBB_TEST)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if (TBB_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
if (TBB_BENCH)
|
||||
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/benchmark)
|
||||
message(FATAL_ERROR "Benchmarks are not supported yet")
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(benchmark)
|
||||
endif()
|
||||
|
||||
if (ANDROID_PLATFORM)
|
||||
if (${ANDROID_STL} STREQUAL "c++_shared")
|
||||
configure_file(
|
||||
"${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libc++_shared.so"
|
||||
"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libc++_shared.so"
|
||||
COPYONLY)
|
||||
endif()
|
||||
# This custom target may be implemented without separate CMake script, but it requires
|
||||
# ADB(Android Debug Bridge) executable file availability, so to incapsulate this requirement
|
||||
# only for corresponding custom target, it was implemented by this way.
|
||||
add_custom_target(device_environment_cleanup COMMAND ${CMAKE_COMMAND}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/device_environment_cleanup.cmake)
|
||||
endif()
|
||||
|
||||
if (TBB4PY_BUILD)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
# Keep it the last instruction.
|
||||
add_subdirectory(cmake/post_install)
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,30 +1,48 @@
|
||||
# Intel(R) Threading Building Blocks
|
||||
# oneAPI Threading Building Blocks
|
||||
[](LICENSE.txt) [](https://github.com/oneapi-src/oneTBB/actions/workflows/ci.yml?query=branch%3Amaster)
|
||||
|
||||
Intel(R) Threading Building Blocks (Intel(R) TBB) lets you easily write parallel C++ programs that take
|
||||
oneAPI Threading Building Blocks (oneTBB) lets you easily write parallel C++ programs that take
|
||||
full advantage of multicore performance, that are portable, composable and have future-proof scalability.
|
||||
|
||||
## Intel(R) TBB Distribution
|
||||
* Commercial version: [https://software.intel.com/en-us/intel-tbb](https://software.intel.com/en-us/intel-tbb)
|
||||
* Community licensing: [https://software.intel.com/sites/campaigns/nest/](https://software.intel.com/sites/campaigns/nest/)
|
||||
* Open source version: [https://www.threadingbuildingblocks.org/](https://www.threadingbuildingblocks.org/)
|
||||
* Intel(R) TBB for Python\*: [http://anaconda.org/intel/tbb](http://anaconda.org/intel/tbb)
|
||||
## Release Information
|
||||
Here are [Release Notes]( https://software.intel.com/en-us/articles/intel-oneapi-threading-building-blocks-release-notes) and
|
||||
[System Requirements](https://software.intel.com/en-us/articles/intel-oneapi-threading-building-blocks-system-requirements).
|
||||
|
||||
## Repository Content
|
||||
This is an official Intel(R) TBB public GitHub repository. All source and binary packages starting from Intel(R) TBB 4.4
|
||||
can be found at the [Release page](https://github.com/01org/tbb/releases). Links to the packages with older versions of
|
||||
Intel(R) TBB can be found in the [download.md](download.md) file.
|
||||
## Documentation
|
||||
* [oneTBB Specification](https://spec.oneapi.com/versions/latest/elements/oneTBB/source/nested-index.html)
|
||||
* [oneTBB Developer Guide and Reference](https://software.intel.com/en-us/oneapi-tbb-documentation)
|
||||
* [Migrating from TBB to oneTBB](https://software.intel.com/content/www/us/en/develop/documentation/onetbb-documentation/top/onetbb-developer-guide/migrating-from-threading-building-blocks-tbb.html)
|
||||
* README for build system: [cmake/README.md](cmake/README.md)
|
||||
|
||||
## Repository Structure
|
||||
The Master branch is empty and contains only README.md and download.md files.
|
||||
## Support
|
||||
Please report issues and suggestions via
|
||||
[GitHub issues](https://github.com/oneapi-src/oneTBB/issues) or start a topic on the
|
||||
[oneTBB forum](https://community.intel.com/t5/Intel-oneAPI-Threading-Building/bd-p/oneapi-threading-building-blocks).
|
||||
|
||||
tbb_\<major_version\> - branch for the new major version. All minor versions of the major release will be committed in this branch.
|
||||
## How to Contribute
|
||||
To contribute to oneTBB, please open a GitHub pull request (preferred) or send us a patch by e-mail.
|
||||
|
||||
For example:
|
||||
* Intel(R) TBB 2017 initial release goes to branch tbb_2017.
|
||||
* Intel(R) TBB 2017 Update 1 will go to branch tbb_2017 too.
|
||||
* Intel(R) TBB 2018 initial release will go to branch tbb_2018.
|
||||
Please use the sign-off line at the end of the patch.
|
||||
Your signature certifies that you wrote the patch or
|
||||
otherwise have the right to pass it on as an open-source patch.
|
||||
The rules are pretty simple:
|
||||
if you can certify the https://developercertificate.org then you just add a line to every git commit message:
|
||||
```
|
||||
Signed-off-by: Name Surname <user@email.com>
|
||||
```
|
||||
Use your real name (sorry, no pseudonyms or anonymous contributions).
|
||||
|
||||
## Сontact engineering team
|
||||
If you set your `user.name` and `user.email` git configs, you can sign your
|
||||
commit automatically with `git commit -s`.
|
||||
|
||||
## License
|
||||
oneAPI Threading Building Blocks is licensed under [Apache License, Version 2.0](LICENSE.txt).
|
||||
By its terms, contributions submitted to the project are also done under that license.
|
||||
|
||||
## Security
|
||||
To report security issues please go to https://intel.com/security.
|
||||
|
||||
## Engineering team contacts
|
||||
* [E-mail us.](mailto:inteltbbdevelopers@intel.com)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
# Build system description
|
||||
|
||||
The project uses CMake build configuration.
|
||||
|
||||
The following controls are available during the configure stage:
|
||||
```
|
||||
TBB_TEST:BOOL - Enable testing (ON by default)
|
||||
TBB_STRICT:BOOL - Treat compiler warnings as errors (ON by default)
|
||||
TBB_SANITIZE:STRING - Sanitizer parameter, passed to compiler/linker
|
||||
TBB_SIGNTOOL:FILEPATH - Tool for digital signing, used in post install step for libraries if provided.
|
||||
TBB_SIGNTOOL_ARGS:STRING - Additional arguments for TBB_SIGNTOOL, used if TBB_SIGNTOOL is set.
|
||||
TBB4PY_BUILD:BOOL - Enable Intel(R) oneAPI Threading Building Blocks (oneTBB) Python module build (OFF by default)
|
||||
TBB_CPF:BOOL - Enable preview features of the library (OFF by default)
|
||||
TBB_INSTALL_VARS:BOOL - Enable auto-generated vars installation(packages generated by `cpack` and `make install` will also include the vars script)(OFF by default)
|
||||
TBB_VALGRIND_MEMCHECK:BOOL - Enable scan for memory leaks using Valgrind (OFF by default)
|
||||
```
|
||||
|
||||
## Configure, build and test
|
||||
|
||||
### Prerequisites
|
||||
|
||||
* CMake >= 3.1
|
||||
|
||||
### Preparation
|
||||
|
||||
In order to perform out-of-source build you have to create a build directory and go there:
|
||||
|
||||
```bash
|
||||
mkdir /tmp/my-build
|
||||
cd /tmp/my-build
|
||||
```
|
||||
|
||||
### Configure
|
||||
|
||||
```bash
|
||||
cmake <options> <repo_root>
|
||||
```
|
||||
|
||||
Some useful options:
|
||||
- `-G <generator>` - specify particular project generator, see `cmake --help` for details.
|
||||
- `-DCMAKE_BUILD_TYPE=Debug` - specify for Debug build, it isn't applicable for multi-config generators, e.g. for Visual Studio generator).
|
||||
|
||||
#### TBBBind library configuration
|
||||
|
||||
The TBBbind library has two versions: `tbbbind` and `tbbbind_2_0`. Each of these versions is linked with corresponding HWLOC library version: `tbbbind` links with HWLOC 1.11.x , `tbbbind_2_0` links with HWLOC 2.x.
|
||||
|
||||
To enable the TBBBind library build or special tests that performed inside the HWLOC environment, please specify the following CMake variables:
|
||||
|
||||
- `CMAKE_HWLOC_<HWLOC_VER>_LIBRARY_PATH` - path to the corresponding HWLOC version shared library on Linux or path to `.lib` file on Windows.
|
||||
- `CMAKE_HWLOC_<HWLOC_VER>_INCLUDE_PATH` - path to the corresponding HWLOC version includes directory.
|
||||
|
||||
Windows requires one additional variable for correct TBBBind library building:
|
||||
- `CMAKE_HWLOC_<HWLOC_VER>_DLL_PATH` - path to the corresponding HWLOC version `.dll` file.
|
||||
|
||||
`HWLOC_VER` variable used above can be replaced with one of the two values: `1_11` for the `tbbbind` library configuration and `2` for the `tbbbind_2_0` library configuration.
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
cmake --build . <options>
|
||||
```
|
||||
|
||||
Some useful options:
|
||||
- `--target <target>` - specific target, "all" is default.
|
||||
- `--config <Release|Debug>` - build configuration, applicable only for multi-config generators, e.g. Visual Studio generator.
|
||||
|
||||
Binaries are placed to `./<compiler-id>_<compiler-ver>_cxx<stdver>_<build-type>` (for example, `./gnu_4.8_cxx11_release`)
|
||||
|
||||
#### Build for 32-bit
|
||||
|
||||
* Intel Compiler: just source Intel(R) C++ Compiler with `ia32` and build as usual.
|
||||
* MSVC: use switch for [generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) (e.g. `-A Win32` for [VS2019](https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2016%202019.html)) during the configuration stage and then build as usual.
|
||||
* GCC/Clang: specify `-m32` during the configuration: `CXXFLAGS=-m32 cmake ..` or `cmake -DCMAKE_CXX_FLAGS=-m32 ..`
|
||||
* Any other compiler which builds for 64-bit by default: specify 32-bit compiler key during the configuration as above.
|
||||
|
||||
#### Windows specific builds (CMake 3.15 or newer is required)
|
||||
|
||||
* Dynamic linkage with CRT: default behavior, can be explicitly specified by setting `CMAKE_MSVC_RUNTIME_LIBRARY` to `MultiThreadedDLL` or `MultiThreadedDebugDLL`.
|
||||
```bash
|
||||
cmake .. # dynamic linkage is used by default
|
||||
```
|
||||
```bash
|
||||
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ..
|
||||
```
|
||||
```bash
|
||||
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL -DCMAKE_BUILD_TYPE=Debug ..
|
||||
```
|
||||
* Static linkage with CRT: set `CMAKE_MSVC_RUNTIME_LIBRARY` to `MultiThreaded` or `MultiThreadedDebug`.
|
||||
```bash
|
||||
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ..
|
||||
```
|
||||
```bash
|
||||
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug -DCMAKE_BUILD_TYPE=Debug ..
|
||||
```
|
||||
* Windows 10 Universal Windows application build: set `CMAKE_SYSTEM_NAME` to `WindowsStore` and `CMAKE_SYSTEM_VERSION` to `10.0`.
|
||||
|
||||
_Note: set `TBB_NO_APPCONTAINER` to `ON` in order to apply `/APPCONTAINER:NO` option during the compilation (used for testing)._
|
||||
```bash
|
||||
cmake -DCMAKE_SYSTEM_NAME:STRING=WindowsStore -DCMAKE_SYSTEM_VERSION:STRING=10.0 ..
|
||||
```
|
||||
* Universal Windows Driver build: set `TBB_WINDOWS_DRIVER` to `ON` and use static linkage with CRT (see above).
|
||||
|
||||
```bash
|
||||
cmake -DTBB_WINDOWS_DRIVER=ON -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ..
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
#### Build test
|
||||
Using default ('all') target:
|
||||
```
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
or using specific test target:
|
||||
```
|
||||
cmake --build . --target <test> # e.g. test_version
|
||||
```
|
||||
|
||||
#### Run test
|
||||
|
||||
Using CTest:
|
||||
```bash
|
||||
ctest
|
||||
```
|
||||
|
||||
or using 'test' target:
|
||||
```bash
|
||||
cmake --build . --target test # currently doesn't work on Windows
|
||||
```
|
||||
|
||||
## Sanitizers - сonfigure, build and run
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DTBB_SANITIZE=thread .. # or -DTBB_SANITIZE=memory or any other sanitizer
|
||||
make -j
|
||||
ctest -V
|
||||
```
|
||||
|
||||
## Valgrind memcheck - configure, build and run
|
||||
|
||||
### Prerequisites
|
||||
* Valgrind tool executable
|
||||
### Example
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DTBB_VALGRIND_MEMCHECK=ON ..
|
||||
make -j memcheck-<test name> # or memcheck-all to scan all tests
|
||||
```
|
||||
|
||||
## Test specification (Doxygen)
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DTBB_TEST_SPEC=ON ..
|
||||
make test_spec
|
||||
```
|
||||
|
||||
## Intallation and packaging
|
||||
|
||||
**NOTE: be careful about installation: avoid commands like `make install` unless you fully understand the consequences.**
|
||||
|
||||
The following install components are supported:
|
||||
- `runtime` - oneTBB runtime package (core shared libraries and `.dll` files on Windows).
|
||||
- `devel` - oneTBB development package (header files, CMake integration files, library symbolic links and `.lib` files on Windows).
|
||||
- `tbb4py` - [oneTBB Module for Python](#onetbb-python-module-support).
|
||||
|
||||
How to install specific components after configuration and build:
|
||||
|
||||
```bash
|
||||
cmake -DCOMPONENT=<component> [-DBUILD_TYPE=<build-type>] -P cmake_install.cmake
|
||||
```
|
||||
|
||||
Simple packaging using CPack is supported.
|
||||
The following commands allow to create a simple portable package which includes header files, libraries and integration files for CMake:
|
||||
|
||||
```bash
|
||||
cmake <options> ..
|
||||
cpack
|
||||
```
|
||||
|
||||
## TBBConfig - integration of binary packages
|
||||
|
||||
It is a configuration module that is used for integration of prebuilt oneTBB. It consists of two files (TBBConfig.cmake and TBBConfigVersion.cmake) and can be used via [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) function.
|
||||
|
||||
How to use this module in your CMake project:
|
||||
1. Let CMake know where to search for TBBConfig, e.g. specify location of TBBConfig.cmake in `TBB_DIR` (for more details about search paths see [find_package](https://cmake.org/cmake/help/latest/command/find_package.html)).
|
||||
2. Use [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) to find oneTBB.
|
||||
3. Use provided variables and/or imported targets (described below) to work with the found oneTBB.
|
||||
|
||||
Example:
|
||||
|
||||
```cmake
|
||||
add_executable(foo foo.cpp)
|
||||
find_package(TBB)
|
||||
target_link_libraries(foo TBB::tbb)
|
||||
```
|
||||
|
||||
oneTBB components can be passed to [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) after keyword ``COMPONENTS`` or ``REQUIRED``.
|
||||
Use basic names of components (`tbb`, `tbbmalloc`, etc.).
|
||||
|
||||
If components are not specified then the default set is used: `tbb`, `tbbmalloc` and ``tbbmalloc_proxy``.
|
||||
|
||||
If `tbbmalloc_proxy` is requested, `tbbmalloc` component will also be added and set as dependency for `tbbmalloc_proxy`.
|
||||
|
||||
TBBConfig creates [imported targets](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#imported-targets>) as
|
||||
shared libraries using the following format: `TBB::<component>` (for example, `TBB::tbb`, `TBB::tbbmalloc`).
|
||||
|
||||
Set `TBB_FIND_RELEASE_ONLY` to `TRUE` before calling `find_package` in order to search only for release oneTBB version. This variable helps to avoid simultaneous linkage of release and debug oneTBB versions when CMake configuration is `Debug` but a third-party component depends on release oneTBB version.
|
||||
|
||||
Variables set during TBB configuration:
|
||||
|
||||
Variable | Description
|
||||
--- | ---
|
||||
`TBB_FOUND` | oneTBB is found
|
||||
`TBB_<component>_FOUND` | Specific oneTBB component is found
|
||||
`TBB_VERSION` | oneTBB version (format: `<major>.<minor>.<patch>.<tweak>`)
|
||||
`TBB_IMPORTED_TARGETS` | All created oneTBB imported targets (not supported for builds from source code)
|
||||
|
||||
Starting from [oneTBB 2021.1](https://github.com/oneapi-src/oneTBB/releases/tag/v2021.1) GitHub release TBBConfig files in the binary packages are located under `<tbb-root>/lib/cmake/TBB`.
|
||||
For example, `TBB_DIR` should be set to `<tbb-root>/lib/cmake/TBB`.
|
||||
|
||||
TBBConfig files are automatically created during the build from source code and can be installed together with the library.
|
||||
Also oneTBB provides a helper function that creates TBBConfig files from predefined templates: see `tbb_generate_config` in `cmake/config_generation.cmake`.
|
||||
|
||||
## oneTBB Python Module support
|
||||
`TBB4PY_BUILD` Cmake option provides ability to build Python module for oneTBB.
|
||||
|
||||
### Targets:
|
||||
- `irml` - build IPC RML server
|
||||
- `python_build` - build oneTBB module for Python
|
||||
|
||||
`python_build` target requirements:
|
||||
- Python version 3.5 or newer
|
||||
- SWIG version 3.0.6 or newer
|
||||
|
||||
## CMake files
|
||||
|
||||
### Compile/link options
|
||||
|
||||
Compile and link options may be specific for certain compilers. This part is handled in `cmake/compilers/*` files.
|
||||
|
||||
Options in TBB CMake are handled via variables in two ways for convenience:
|
||||
|
||||
* by options group
|
||||
* by specific option
|
||||
|
||||
#### Options group
|
||||
|
||||
Naming convention is the following: `TBB_<SCOPE>_<STAGE>_<CATEGORY>`, where
|
||||
|
||||
* `<SCOPE>` could be
|
||||
* `LIB` - options applied during libraries build.
|
||||
* `TEST` - options applied during test build.
|
||||
* `BENCH` - options applied during benchmarks build.
|
||||
* `COMMON` - options applied during all (libraries, test, benchmarks) builds.
|
||||
* `<STAGE>` could be
|
||||
* `COMPILE` - options applied during the compilation.
|
||||
* `LINK` - options applied during the linkage.
|
||||
* `<CATEGORY>` could be
|
||||
* `FLAGS` - list of flags
|
||||
* `LIBS` - list of libraries
|
||||
|
||||
*Examples*
|
||||
|
||||
Variable | Description
|
||||
--- | ---
|
||||
`TBB_COMMON_COMPILE_FLAGS` | Applied to libraries, tests and benchmarks as compile options
|
||||
`TBB_LIB_LINK_FLAGS` | Applied to libraries as link options
|
||||
`TBB_LIB_LINK_LIBS ` | Applied to libraries as link libraries
|
||||
`TBB_TEST_COMPILE_FLAGS` | Applied to tests as compile options
|
||||
|
||||
|
||||
#### Specific options
|
||||
|
||||
If the option used only in part of the places (library, tests, benchmarks) as well as adding this option to the group of other options is not possible,
|
||||
then the option must be named using common sense.
|
||||
|
||||
Warnings supperssions should be added into `TBB_WARNING_SUPPRESS` variable which is applied during the compilation of libraries, tests and benchmarks.
|
||||
Additional warnings should be added into `TBB_WARNING_TEST_FLAGS` variable which is applied during the compilation of tests.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/environment.cmake)
|
||||
|
||||
execute_on_device("rm -rf ${ANDROID_DEVICE_TESTING_DIRECTORY}")
|
||||
@@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(ANDROID_DEVICE_TESTING_DIRECTORY "/data/local/tmp/tbb_testing")
|
||||
|
||||
find_program(adb_executable adb)
|
||||
if (NOT adb_executable)
|
||||
message(FATAL_ERROR "Could not find adb")
|
||||
endif()
|
||||
|
||||
macro(execute_on_device cmd)
|
||||
execute_process(COMMAND ${adb_executable} shell ${cmd} RESULT_VARIABLE CMD_RESULT)
|
||||
if (CMD_RESULT)
|
||||
message(FATAL_ERROR "Error while on device execution: ${cmd} error_code: ${CMD_RESULT}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(transfer_data data_path)
|
||||
execute_process(COMMAND ${adb_executable} push --sync ${data_path} ${ANDROID_DEVICE_TESTING_DIRECTORY}
|
||||
RESULT_VARIABLE CMD_RESULT OUTPUT_QUIET)
|
||||
if (CMD_RESULT)
|
||||
message(FATAL_ERROR "Error while data transferring: ${data_path} error_code: ${CMD_RESULT}")
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -0,0 +1,27 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/environment.cmake)
|
||||
|
||||
# transfer data to device
|
||||
execute_on_device("mkdir -m 755 -p ${ANDROID_DEVICE_TESTING_DIRECTORY}")
|
||||
|
||||
file (GLOB_RECURSE BINARIES_LIST "${BINARIES_PATH}/*.so*" "${BINARIES_PATH}/${TEST_NAME}")
|
||||
foreach(BINARY_FILE ${BINARIES_LIST})
|
||||
transfer_data(${BINARY_FILE})
|
||||
endforeach()
|
||||
|
||||
# execute binary
|
||||
execute_on_device("chmod -R 755 ${ANDROID_DEVICE_TESTING_DIRECTORY}")
|
||||
execute_on_device("LD_LIBRARY_PATH=${ANDROID_DEVICE_TESTING_DIRECTORY} ${ANDROID_DEVICE_TESTING_DIRECTORY}/${TEST_NAME}")
|
||||
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(TBB_LINK_DEF_FILE_FLAG -Wl,-exported_symbols_list,)
|
||||
set(TBB_DEF_FILE_PREFIX mac${TBB_ARCH})
|
||||
set(TBB_WARNING_LEVEL -Wall -Wextra $<$<BOOL:${TBB_STRICT}>:-Werror>)
|
||||
set(TBB_TEST_WARNING_FLAGS -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor)
|
||||
set(TBB_WARNING_SUPPRESS -Wno-parentheses -Wno-non-virtual-dtor -Wno-dangling-else)
|
||||
# For correct ucontext.h structures layout
|
||||
set(TBB_COMMON_COMPILE_FLAGS -D_XOPEN_SOURCE)
|
||||
|
||||
# Depfile options (e.g. -MD) are inserted automatically in some cases.
|
||||
# Don't add -MMD to avoid conflicts in such cases.
|
||||
if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
|
||||
set(TBB_MMD_FLAG -MMD)
|
||||
endif()
|
||||
|
||||
# Ignore -Werror set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
|
||||
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
|
||||
tbb_remove_compile_flag(-Werror)
|
||||
endif()
|
||||
|
||||
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) on relevant processors
|
||||
if (NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES "^arm64$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|AMD64)") # OSX systems are 64-bit only
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm)
|
||||
endif()
|
||||
|
||||
# TBB malloc settings
|
||||
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if (APPLE)
|
||||
set(TBB_LINK_DEF_FILE_FLAG -Wl,-exported_symbols_list,)
|
||||
set(TBB_DEF_FILE_PREFIX mac${TBB_ARCH})
|
||||
|
||||
# For correct ucontext.h structures layout
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -D_XOPEN_SOURCE)
|
||||
else()
|
||||
set(TBB_LINK_DEF_FILE_FLAG -Wl,--version-script=)
|
||||
set(TBB_DEF_FILE_PREFIX lin${TBB_ARCH})
|
||||
endif()
|
||||
|
||||
# Depfile options (e.g. -MD) are inserted automatically in some cases.
|
||||
# Don't add -MMD to avoid conflicts in such cases.
|
||||
if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
|
||||
set(TBB_MMD_FLAG -MMD)
|
||||
endif()
|
||||
|
||||
set(TBB_WARNING_LEVEL -Wall -Wextra $<$<BOOL:${TBB_STRICT}>:-Werror>)
|
||||
set(TBB_TEST_WARNING_FLAGS -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor)
|
||||
|
||||
# Ignore -Werror set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
|
||||
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
|
||||
tbb_remove_compile_flag(-Werror)
|
||||
endif()
|
||||
|
||||
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},12.0>>:-mwaitpkg>)
|
||||
endif()
|
||||
|
||||
set(TBB_COMMON_LINK_LIBS dl)
|
||||
|
||||
if (ANDROID_PLATFORM)
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} $<$<NOT:$<CONFIG:Debug>>:-D_FORTIFY_SOURCE=2>)
|
||||
endif()
|
||||
|
||||
# Enabling LTO on Android causes the NDK bug.
|
||||
# NDK throws the warning: "argument unused during compilation: '-Wa,--noexecstack'"
|
||||
if (NOT ANDROID_PLATFORM)
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
|
||||
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
|
||||
endif()
|
||||
|
||||
# TBB malloc settings
|
||||
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
|
||||
@@ -0,0 +1,62 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if (APPLE)
|
||||
set(TBB_LINK_DEF_FILE_FLAG -Wl,-exported_symbols_list,)
|
||||
set(TBB_DEF_FILE_PREFIX mac${TBB_ARCH})
|
||||
|
||||
# For correct ucontext.h structures layout
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -D_XOPEN_SOURCE)
|
||||
else()
|
||||
set(TBB_LINK_DEF_FILE_FLAG -Wl,--version-script=)
|
||||
set(TBB_DEF_FILE_PREFIX lin${TBB_ARCH})
|
||||
endif()
|
||||
|
||||
set(TBB_WARNING_LEVEL -Wall -Wextra $<$<BOOL:${TBB_STRICT}>:-Werror> -Wfatal-errors)
|
||||
set(TBB_TEST_WARNING_FLAGS -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor)
|
||||
|
||||
# Depfile options (e.g. -MD) are inserted automatically in some cases.
|
||||
# Don't add -MMD to avoid conflicts in such cases.
|
||||
if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
|
||||
set(TBB_MMD_FLAG -MMD)
|
||||
endif()
|
||||
|
||||
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<AND:$<NOT:$<CXX_COMPILER_ID:Intel>>,$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},11.0>>>:-mwaitpkg>)
|
||||
endif()
|
||||
|
||||
set(TBB_COMMON_LINK_LIBS dl)
|
||||
|
||||
# Ignore -Werror set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
|
||||
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
|
||||
tbb_remove_compile_flag(-Werror)
|
||||
endif()
|
||||
|
||||
if (NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL Intel)
|
||||
# gcc 6.0 and later have -flifetime-dse option that controls elimination of stores done outside the object lifetime
|
||||
set(TBB_DSE_FLAG $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},6.0>>:-flifetime-dse=1>)
|
||||
endif()
|
||||
|
||||
# Workaround for heavy tests and too many symbols in debug (rellocation truncated to fit: R_MIPS_CALL16)
|
||||
if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
|
||||
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} -DTBB_TEST_LOW_WORKLOAD $<$<CONFIG:DEBUG>:-mxgot>)
|
||||
endif()
|
||||
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
|
||||
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
|
||||
|
||||
# TBB malloc settings
|
||||
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
|
||||
set(TBB_OPENMP_FLAG -fopenmp)
|
||||
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if (MSVC)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/MSVC.cmake)
|
||||
set(TBB_WARNING_LEVEL ${TBB_WARNING_LEVEL} /W3)
|
||||
set(TBB_OPENMP_FLAG /Qopenmp)
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/Qipo>)
|
||||
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:/INCREMENTAL:NO>)
|
||||
elseif (APPLE)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/AppleClang.cmake)
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -fstack-protector -Wformat -Wformat-security
|
||||
$<$<NOT:$<CONFIG:Debug>>:-fno-omit-frame-pointer -qno-opt-report-embed -D_FORTIFY_SOURCE=2>)
|
||||
set(TBB_OPENMP_FLAG -qopenmp)
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-ipo>)
|
||||
else()
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/GNU.cmake)
|
||||
set(TBB_LIB_LINK_FLAGS ${TBB_LIB_LINK_FLAGS} -static-intel -Wl,-z,relro,-z,now,)
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -fstack-protector -Wformat -Wformat-security
|
||||
$<$<NOT:$<CONFIG:Debug>>:-qno-opt-report-embed -D_FORTIFY_SOURCE=2>
|
||||
$<$<EQUAL:${TBB_ARCH},32>:-falign-stack=maintain-16-byte>)
|
||||
set(TBB_OPENMP_FLAG -qopenmp)
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-ipo>)
|
||||
endif()
|
||||
set(TBB_IPO_LINK_FLAGS ${TBB_IPO_LINK_FLAGS} ${TBB_IPO_COMPILE_FLAGS})
|
||||
@@ -0,0 +1,27 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if (WIN32)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/MSVC.cmake)
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/Qipo>)
|
||||
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:/INCREMENTAL:NO>)
|
||||
else()
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/Clang.cmake)
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-ipo>)
|
||||
endif()
|
||||
set(TBB_IPO_LINK_FLAGS ${TBB_IPO_LINK_FLAGS} ${TBB_IPO_COMPILE_FLAGS})
|
||||
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm -mwaitpkg)
|
||||
endif()
|
||||
@@ -0,0 +1,75 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(TBB_LINK_DEF_FILE_FLAG ${CMAKE_LINK_DEF_FILE_FLAG})
|
||||
set(TBB_DEF_FILE_PREFIX win${TBB_ARCH})
|
||||
|
||||
# Workaround for CMake issue https://gitlab.kitware.com/cmake/cmake/issues/18317.
|
||||
# TODO: consider use of CMP0092 CMake policy.
|
||||
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# Warning suppression C4324: structure was padded due to alignment specifier
|
||||
set(TBB_WARNING_LEVEL $<$<NOT:$<CXX_COMPILER_ID:Intel>>:/W4> $<$<BOOL:${TBB_STRICT}>:/WX>)
|
||||
set(TBB_WARNING_SUPPRESS /wd4324)
|
||||
set(TBB_TEST_COMPILE_FLAGS /bigobj)
|
||||
if (MSVC_VERSION LESS_EQUAL 1900)
|
||||
# Warning suppression C4503 for VS2015 and earlier:
|
||||
# decorated name length exceeded, name was truncated.
|
||||
# More info can be found at
|
||||
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4503
|
||||
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} /wd4503)
|
||||
endif()
|
||||
set(TBB_LIB_COMPILE_FLAGS -D_CRT_SECURE_NO_WARNINGS /GS)
|
||||
set(TBB_COMMON_COMPILE_FLAGS /volatile:iso /FS)
|
||||
|
||||
# Ignore /WX set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
|
||||
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
|
||||
tbb_remove_compile_flag(/WX)
|
||||
endif()
|
||||
|
||||
if (WINDOWS_STORE OR TBB_WINDOWS_DRIVER)
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} /D_WIN32_WINNT=0x0A00)
|
||||
set(TBB_COMMON_LINK_FLAGS /NODEFAULTLIB:kernel32.lib /INCREMENTAL:NO)
|
||||
set(TBB_COMMON_LINK_LIBS OneCore.lib)
|
||||
endif()
|
||||
|
||||
if (WINDOWS_STORE)
|
||||
if (NOT CMAKE_SYSTEM_VERSION EQUAL 10.0)
|
||||
message(FATAL_ERROR "CMAKE_SYSTEM_VERSION must be equal to 10.0")
|
||||
endif()
|
||||
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} /ZW /ZW:nostdlib)
|
||||
|
||||
# CMake define this extra lib, remove it for this build type
|
||||
string(REGEX REPLACE "WindowsApp.lib" "" CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES}")
|
||||
|
||||
if (TBB_NO_APPCONTAINER)
|
||||
set(TBB_LIB_LINK_FLAGS ${TBB_LIB_LINK_FLAGS} /APPCONTAINER:NO)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (TBB_WINDOWS_DRIVER)
|
||||
# Since this is universal driver disable this variable
|
||||
set(CMAKE_SYSTEM_PROCESSOR "")
|
||||
|
||||
# CMake define list additional libs, remove it for this build type
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "")
|
||||
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} /D _UNICODE /DUNICODE /DWINAPI_FAMILY=WINAPI_FAMILY_APP /D__WRL_NO_DEFAULT_LIB__)
|
||||
endif()
|
||||
|
||||
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/GL>)
|
||||
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:/LTCG /INCREMENTAL:NO>)
|
||||
|
||||
set(TBB_OPENMP_FLAG /openmp)
|
||||
@@ -0,0 +1,112 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Save current location,
|
||||
# see for details: https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_LIST_DIR.html
|
||||
set(_tbb_gen_cfg_path ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(tbb_generate_config)
|
||||
set(options HANDLE_SUBDIRS)
|
||||
set(oneValueArgs INSTALL_DIR
|
||||
SYSTEM_NAME
|
||||
LIB_REL_PATH INC_REL_PATH DLL_REL_PATH
|
||||
VERSION
|
||||
TBB_BINARY_VERSION
|
||||
TBBMALLOC_BINARY_VERSION
|
||||
TBBMALLOC_PROXY_BINARY_VERSION
|
||||
TBBBIND_BINARY_VERSION)
|
||||
|
||||
cmake_parse_arguments(tbb_gen_cfg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
get_filename_component(config_install_dir ${tbb_gen_cfg_INSTALL_DIR} ABSOLUTE)
|
||||
file(MAKE_DIRECTORY ${config_install_dir})
|
||||
|
||||
file(TO_CMAKE_PATH "${tbb_gen_cfg_LIB_REL_PATH}" TBB_LIB_REL_PATH)
|
||||
file(TO_CMAKE_PATH "${tbb_gen_cfg_DLL_REL_PATH}" TBB_DLL_REL_PATH)
|
||||
file(TO_CMAKE_PATH "${tbb_gen_cfg_INC_REL_PATH}" TBB_INC_REL_PATH)
|
||||
|
||||
set(TBB_VERSION ${tbb_gen_cfg_VERSION})
|
||||
|
||||
set(TBB_COMPONENTS_BIN_VERSION "
|
||||
set(_tbb_bin_version ${tbb_gen_cfg_TBB_BINARY_VERSION})
|
||||
set(_tbbmalloc_bin_version ${tbb_gen_cfg_TBBMALLOC_BINARY_VERSION})
|
||||
set(_tbbmalloc_proxy_bin_version ${tbb_gen_cfg_TBBMALLOC_PROXY_BINARY_VERSION})
|
||||
set(_tbbbind_bin_version ${tbb_gen_cfg_TBBBIND_BINARY_VERSION})
|
||||
")
|
||||
|
||||
if (tbb_gen_cfg_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(TBB_LIB_PREFIX "lib")
|
||||
set(TBB_LIB_EXT "so.\${_\${_tbb_component}_bin_version}")
|
||||
set(TBB_IMPLIB_RELEASE "")
|
||||
set(TBB_IMPLIB_DEBUG "")
|
||||
if (tbb_gen_cfg_HANDLE_SUBDIRS)
|
||||
set(TBB_HANDLE_SUBDIRS "
|
||||
if (CMAKE_SIZEOF_VOID_P STREQUAL \"8\")
|
||||
set(_tbb_subdir intel64/gcc4.8)
|
||||
else ()
|
||||
set(_tbb_subdir ia32/gcc4.8)
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
elseif (tbb_gen_cfg_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(TBB_LIB_PREFIX "lib")
|
||||
set(TBB_LIB_EXT "\${_\${_tbb_component}_bin_version}.dylib")
|
||||
set(TBB_IMPLIB_RELEASE "")
|
||||
set(TBB_IMPLIB_DEBUG "")
|
||||
elseif (tbb_gen_cfg_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(TBB_LIB_PREFIX "")
|
||||
set(TBB_LIB_EXT "dll")
|
||||
set(TBB_COMPILE_DEFINITIONS "
|
||||
INTERFACE_COMPILE_DEFINITIONS \"__TBB_NO_IMPLICIT_LINKAGE=1\"")
|
||||
|
||||
# .lib files installed to TBB_LIB_REL_PATH (e.g. <prefix>/lib);
|
||||
# .dll files installed to TBB_DLL_REL_PATH (e.g. <prefix>/bin);
|
||||
# Expand TBB_LIB_REL_PATH here in IMPORTED_IMPLIB property and
|
||||
# redefine it with TBB_DLL_REL_PATH value to properly fill IMPORTED_LOCATION property in TBBConfig.cmake.in template.
|
||||
set(TBB_IMPLIB_RELEASE "
|
||||
IMPORTED_IMPLIB_RELEASE \"\${_tbb_root}/${TBB_LIB_REL_PATH}/\${_tbb_subdir}/\${_tbb_component}\${_bin_version}.lib\"")
|
||||
set(TBB_IMPLIB_DEBUG "
|
||||
IMPORTED_IMPLIB_DEBUG \"\${_tbb_root}/${TBB_LIB_REL_PATH}/\${_tbb_subdir}/\${_tbb_component}\${_bin_version}_debug.lib\"")
|
||||
set(TBB_LIB_REL_PATH ${TBB_DLL_REL_PATH})
|
||||
|
||||
if (tbb_gen_cfg_HANDLE_SUBDIRS)
|
||||
set(TBB_HANDLE_SUBDIRS "
|
||||
set(_tbb_subdir vc14)
|
||||
if (WINDOWS_STORE)
|
||||
set(_tbb_subdir \${_tbb_subdir}_uwp)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P STREQUAL \"8\")
|
||||
set(_tbb_subdir intel64/\${_tbb_subdir})
|
||||
else ()
|
||||
set(_tbb_subdir ia32/\${_tbb_subdir})
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
|
||||
set(TBB_HANDLE_BIN_VERSION "
|
||||
unset(_bin_version)
|
||||
if (_tbb_component STREQUAL tbb)
|
||||
set(_bin_version \${_tbb_bin_version})
|
||||
endif()
|
||||
")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported OS name: ${tbb_system_name}")
|
||||
endif()
|
||||
|
||||
configure_file(${_tbb_gen_cfg_path}/templates/TBBConfig.cmake.in ${config_install_dir}/TBBConfig.cmake @ONLY)
|
||||
configure_file(${_tbb_gen_cfg_path}/templates/TBBConfigVersion.cmake.in ${config_install_dir}/TBBConfigVersion.cmake @ONLY)
|
||||
endfunction()
|
||||
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
list(APPEND HWLOC_REQUIRED_VERSIONS 1_11 2 2_4)
|
||||
|
||||
foreach(hwloc_version ${HWLOC_REQUIRED_VERSIONS})
|
||||
if (NOT WIN32)
|
||||
set(CMAKE_HWLOC_${hwloc_version}_DLL_PATH STUB)
|
||||
endif()
|
||||
set(HWLOC_TARGET_NAME HWLOC::hwloc_${hwloc_version})
|
||||
|
||||
if (NOT TARGET ${HWLOC_TARGET_NAME} AND
|
||||
CMAKE_HWLOC_${hwloc_version}_LIBRARY_PATH AND
|
||||
CMAKE_HWLOC_${hwloc_version}_DLL_PATH AND
|
||||
CMAKE_HWLOC_${hwloc_version}_INCLUDE_PATH
|
||||
)
|
||||
add_library(${HWLOC_TARGET_NAME} SHARED IMPORTED)
|
||||
set_target_properties(${HWLOC_TARGET_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${CMAKE_HWLOC_${hwloc_version}_INCLUDE_PATH}")
|
||||
if (WIN32)
|
||||
set_target_properties(${HWLOC_TARGET_NAME} PROPERTIES
|
||||
IMPORTED_LOCATION "${CMAKE_HWLOC_${hwloc_version}_DLL_PATH}"
|
||||
IMPORTED_IMPLIB "${CMAKE_HWLOC_${hwloc_version}_LIBRARY_PATH}")
|
||||
else()
|
||||
set_target_properties(${HWLOC_TARGET_NAME} PROPERTIES
|
||||
IMPORTED_LOCATION "${CMAKE_HWLOC_${hwloc_version}_LIBRARY_PATH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (TARGET ${HWLOC_TARGET_NAME})
|
||||
set(HWLOC_TARGET_EXPLICITLY_DEFINED TRUE)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
unset(HWLOC_TARGET_NAME)
|
||||
|
||||
if (NOT HWLOC_TARGET_EXPLICITLY_DEFINED AND
|
||||
# No hwloc auto detection for cross compilation
|
||||
NOT CMAKE_CROSSCOMPILING
|
||||
)
|
||||
find_package(PkgConfig QUIET)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(HWLOC hwloc)
|
||||
if (HWLOC_FOUND)
|
||||
if (HWLOC_VERSION VERSION_LESS 2)
|
||||
set(TBBBIND_LIBRARY_NAME tbbbind)
|
||||
elseif(HWLOC_VERSION VERSION_LESS 2.4)
|
||||
set(TBBBIND_LIBRARY_NAME tbbbind_2_0)
|
||||
else()
|
||||
set(TBBBIND_LIBRARY_NAME tbbbind_2_4)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
option(TBB_VALGRIND_MEMCHECK "Enable scan for memory leaks using Valgrind" OFF)
|
||||
|
||||
if (NOT TBB_VALGRIND_MEMCHECK)
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_custom_target(memcheck-all
|
||||
COMMENT "Run memcheck on all tests")
|
||||
|
||||
find_program(VALGRIND_EXE valgrind)
|
||||
|
||||
if (NOT VALGRIND_EXE)
|
||||
message(FATAL_ERROR "Valgrind executable is not found, add tool to PATH or turn off TBB_VALGRIND_MEMCHECK")
|
||||
else()
|
||||
message(STATUS "Found Valgrind to run memory leak scan")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/memcheck)
|
||||
|
||||
function(_tbb_run_memcheck test_target)
|
||||
set(target_name memcheck-${test_target})
|
||||
add_custom_target(${target_name}
|
||||
COMMAND ${VALGRIND_EXE} --leak-check=full --show-leak-kinds=all --log-file=${CMAKE_BINARY_DIR}/memcheck/${target_name}.log -v $<TARGET_FILE:${test_target}>)
|
||||
add_dependencies(memcheck-all ${target_name})
|
||||
endfunction()
|
||||
|
||||
add_custom_target(memcheck-short
|
||||
COMMENT "Run memcheck scan on specified list")
|
||||
|
||||
# List of reasonable and quick enough tests to use in automated memcheck
|
||||
add_dependencies(memcheck-short
|
||||
memcheck-test_allocators
|
||||
memcheck-test_arena_constraints
|
||||
memcheck-test_dynamic_link
|
||||
memcheck-test_concurrent_lru_cache
|
||||
memcheck-conformance_concurrent_unordered_map
|
||||
memcheck-conformance_concurrent_unordered_set
|
||||
memcheck-conformance_concurrent_map
|
||||
memcheck-conformance_concurrent_set
|
||||
memcheck-conformance_concurrent_priority_queue
|
||||
memcheck-conformance_concurrent_vector
|
||||
memcheck-conformance_concurrent_queue
|
||||
memcheck-conformance_concurrent_hash_map
|
||||
memcheck-test_parallel_for
|
||||
memcheck-test_parallel_for_each
|
||||
memcheck-test_parallel_reduce
|
||||
memcheck-test_parallel_sort
|
||||
memcheck-test_parallel_invoke
|
||||
memcheck-test_parallel_scan
|
||||
memcheck-test_parallel_pipeline
|
||||
memcheck-test_eh_algorithms
|
||||
memcheck-test_task_group
|
||||
memcheck-test_task_arena
|
||||
memcheck-test_enumerable_thread_specific
|
||||
memcheck-test_resumable_tasks
|
||||
memcheck-conformance_mutex
|
||||
memcheck-test_function_node
|
||||
memcheck-test_multifunction_node
|
||||
memcheck-test_broadcast_node
|
||||
memcheck-test_buffer_node
|
||||
memcheck-test_composite_node
|
||||
memcheck-test_continue_node
|
||||
memcheck-test_eh_flow_graph
|
||||
memcheck-test_flow_graph
|
||||
memcheck-test_flow_graph_priorities
|
||||
memcheck-test_flow_graph_whitebox
|
||||
memcheck-test_indexer_node
|
||||
memcheck-test_join_node
|
||||
memcheck-test_join_node_key_matching
|
||||
memcheck-test_join_node_msg_key_matching
|
||||
memcheck-test_priority_queue_node
|
||||
memcheck-test_sequencer_node
|
||||
memcheck-test_split_node
|
||||
memcheck-test_tagged_msg
|
||||
memcheck-test_overwrite_node
|
||||
memcheck-test_write_once_node
|
||||
memcheck-test_async_node
|
||||
memcheck-test_input_node
|
||||
memcheck-test_profiling
|
||||
memcheck-test_concurrent_queue_whitebox
|
||||
memcheck-test_intrusive_list
|
||||
memcheck-test_semaphore
|
||||
memcheck-test_environment_whitebox
|
||||
memcheck-test_handle_perror
|
||||
memcheck-test_hw_concurrency
|
||||
memcheck-test_eh_thread
|
||||
memcheck-test_global_control
|
||||
memcheck-test_task
|
||||
memcheck-test_concurrent_monitor
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Note: current implementation uses CMAKE_BUILD_TYPE,
|
||||
# this parameter is not defined for multi-config generators.
|
||||
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
|
||||
set(CPACK_PACKAGE_VERSION "${TBB_VERSION}")
|
||||
string(TOLOWER ${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}_${TBB_OUTPUT_DIR_BASE}_${CMAKE_BUILD_TYPE} CPACK_PACKAGE_FILE_NAME)
|
||||
set(CPACK_GENERATOR ZIP)
|
||||
include(CPack)
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Add code signing as post-install step.
|
||||
if (DEFINED TBB_SIGNTOOL)
|
||||
install(CODE "
|
||||
file(GLOB_RECURSE FILES_TO_SIGN \${CMAKE_INSTALL_PREFIX}/*${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
execute_process(COMMAND ${TBB_SIGNTOOL} \${FILES_TO_SIGN} ${TBB_SIGNTOOL_ARGS})
|
||||
")
|
||||
endif()
|
||||
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
find_package(PythonInterp 3.5 REQUIRED)
|
||||
|
||||
file(GLOB_RECURSE MODULES_LIST "${PYTHON_MODULE_BUILD_PATH}/*TBB.py*" )
|
||||
list(LENGTH MODULES_LIST MODULES_COUNT)
|
||||
|
||||
if (MODULES_COUNT EQUAL 0)
|
||||
message(FATAL_ERROR "Cannot find oneTBB Python module")
|
||||
elseif (MODULES_COUNT GREATER 1)
|
||||
message(WARNING "Found more than oneTBB Python modules, the only first found module will be tested")
|
||||
endif()
|
||||
|
||||
list(GET MODULES_LIST 0 PYTHON_MODULE)
|
||||
get_filename_component(PYTHON_MODULE_PATH ${PYTHON_MODULE} DIRECTORY)
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env LD_LIBRARY_PATH=${TBB_BINARIES_PATH}
|
||||
${PYTHON_EXECUTABLE} -m tbb test
|
||||
WORKING_DIRECTORY ${PYTHON_MODULE_PATH}
|
||||
RESULT_VARIABLE CMD_RESULT
|
||||
)
|
||||
if (CMD_RESULT)
|
||||
message(FATAL_ERROR "Error while test execution: ${cmd} error_code: ${CMD_RESULT}")
|
||||
endif()
|
||||
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(TBB_SANITIZE ${TBB_SANITIZE} CACHE STRING "Sanitizer parameter passed to compiler/linker" FORCE)
|
||||
# Possible values of sanitizer parameter for cmake-gui for convenience, user still can use any other value.
|
||||
set_property(CACHE TBB_SANITIZE PROPERTY STRINGS "thread" "memory" "leak" "address -fno-omit-frame-pointer")
|
||||
|
||||
if (NOT TBB_SANITIZE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(TBB_SANITIZE_OPTION -fsanitize=${TBB_SANITIZE})
|
||||
|
||||
# It is required to add sanitizer option to CMAKE_REQUIRED_LIBRARIES to make check_cxx_compiler_flag working properly:
|
||||
# sanitizer option should be passed during the compilation phase as well as during the compilation.
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${TBB_SANITIZE_OPTION} ${CMAKE_REQUIRED_LIBRARIES}")
|
||||
|
||||
string(MAKE_C_IDENTIFIER ${TBB_SANITIZE_OPTION} FLAG_DISPLAY_NAME)
|
||||
check_cxx_compiler_flag(${TBB_SANITIZE_OPTION} ${FLAG_DISPLAY_NAME})
|
||||
if (NOT ${FLAG_DISPLAY_NAME})
|
||||
message(FATAL_ERROR
|
||||
"${TBB_SANITIZE_OPTION} is not supported by compiler ${CMAKE_CXX_COMPILER_ID}:${CMAKE_CXX_COMPILER_VERSION}, "
|
||||
"please try another compiler or omit TBB_SANITIZE variable")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TBB_SANITIZE_OPTION}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TBB_SANITIZE_OPTION}")
|
||||
@@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../config_generation.cmake)
|
||||
|
||||
# TBBConfig in TBB provided packages are expected to be placed into: <tbb-root>/lib/cmake/tbb*
|
||||
set(TBB_ROOT_REL_PATH "../../..")
|
||||
|
||||
# Paths relative to TBB root directory
|
||||
set(INC_REL_PATH "include")
|
||||
set(LIB_REL_PATH "lib")
|
||||
set(DLL_REL_PATH "redist")
|
||||
|
||||
# Parse version info
|
||||
file(READ ${CMAKE_CURRENT_LIST_DIR}/../../include/oneapi/tbb/version.h _tbb_version_info)
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" _tbb_ver_major "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" _tbb_ver_minor "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_PATCH ([0-9]+).*" "\\1" _tbb_ver_patch "${_tbb_version_info}")
|
||||
string(REGEX REPLACE ".*#define __TBB_BINARY_VERSION ([0-9]+).*" "\\1" TBB_BINARY_VERSION "${_tbb_version_info}")
|
||||
file(READ ${CMAKE_CURRENT_LIST_DIR}/../../CMakeLists.txt _tbb_cmakelist)
|
||||
string(REGEX REPLACE ".*TBBMALLOC_BINARY_VERSION ([0-9]+).*" "\\1" TBBMALLOC_BINARY_VERSION "${_tbb_cmakelist}")
|
||||
set(TBBMALLOC_PROXY_BINARY_VERSION ${TBBMALLOC_BINARY_VERSION})
|
||||
string(REGEX REPLACE ".*TBBBIND_BINARY_VERSION ([0-9]+).*" "\\1" TBBBIND_BINARY_VERSION "${_tbb_cmakelist}")
|
||||
|
||||
set(COMMON_ARGS
|
||||
TBB_ROOT_REL_PATH ${TBB_ROOT_REL_PATH}
|
||||
INC_REL_PATH ${INC_REL_PATH}
|
||||
LIB_REL_PATH ${LIB_REL_PATH}
|
||||
VERSION ${_tbb_ver_major}.${_tbb_ver_minor}.${_tbb_ver_patch}
|
||||
TBB_BINARY_VERSION ${TBB_BINARY_VERSION}
|
||||
TBBMALLOC_BINARY_VERSION ${TBBMALLOC_BINARY_VERSION}
|
||||
TBBMALLOC_PROXY_BINARY_VERSION ${TBBMALLOC_PROXY_BINARY_VERSION}
|
||||
TBBBIND_BINARY_VERSION ${TBBBIND_BINARY_VERSION}
|
||||
)
|
||||
|
||||
tbb_generate_config(INSTALL_DIR ${INSTALL_DIR}/linux SYSTEM_NAME Linux HANDLE_SUBDIRS ${COMMON_ARGS})
|
||||
tbb_generate_config(INSTALL_DIR ${INSTALL_DIR}/windows SYSTEM_NAME Windows HANDLE_SUBDIRS DLL_REL_PATH ${DLL_REL_PATH} ${COMMON_ARGS})
|
||||
tbb_generate_config(INSTALL_DIR ${INSTALL_DIR}/darwin SYSTEM_NAME Darwin ${COMMON_ARGS})
|
||||
message(STATUS "TBBConfig files were created in ${INSTALL_DIR}")
|
||||
@@ -0,0 +1,98 @@
|
||||
# Copyright (c) 2017-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# It defines the following variables:
|
||||
# TBB_<component>_FOUND
|
||||
# TBB_IMPORTED_TARGETS
|
||||
#
|
||||
# TBBConfigVersion.cmake defines TBB_VERSION
|
||||
#
|
||||
# Initialize to default values
|
||||
if (NOT TBB_IMPORTED_TARGETS)
|
||||
set(TBB_IMPORTED_TARGETS "")
|
||||
endif()
|
||||
|
||||
if (NOT TBB_FIND_COMPONENTS)
|
||||
set(TBB_FIND_COMPONENTS "tbb;tbbmalloc;tbbmalloc_proxy")
|
||||
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
|
||||
set(TBB_FIND_REQUIRED_${_tbb_component} 1)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
get_filename_component(_tbb_root "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
|
||||
get_filename_component(_tbb_root "${_tbb_root}/@TBB_ROOT_REL_PATH@" ABSOLUTE)
|
||||
|
||||
set(TBB_INTERFACE_VERSION @TBB_INTERFACE_VERSION@)
|
||||
@TBB_COMPONENTS_BIN_VERSION@
|
||||
# Add components with internal dependencies: tbbmalloc_proxy -> tbbmalloc
|
||||
list(FIND TBB_FIND_COMPONENTS tbbmalloc_proxy _tbbmalloc_proxy_ix)
|
||||
if (NOT _tbbmalloc_proxy_ix EQUAL -1)
|
||||
list(APPEND TBB_FIND_COMPONENTS tbbmalloc)
|
||||
list(REMOVE_DUPLICATES TBB_FIND_COMPONENTS)
|
||||
set(TBB_FIND_REQUIRED_tbbmalloc ${TBB_FIND_REQUIRED_tbbmalloc_proxy})
|
||||
endif()
|
||||
unset(_tbbmalloc_proxy_ix)
|
||||
@TBB_HANDLE_SUBDIRS@
|
||||
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
|
||||
set(TBB_${_tbb_component}_FOUND 0)
|
||||
@TBB_HANDLE_BIN_VERSION@
|
||||
get_filename_component(_tbb_release_lib "${_tbb_root}/@TBB_LIB_REL_PATH@/${_tbb_subdir}/@TBB_LIB_PREFIX@${_tbb_component}${_bin_version}.@TBB_LIB_EXT@" ABSOLUTE)
|
||||
|
||||
if (NOT TBB_FIND_RELEASE_ONLY)
|
||||
get_filename_component(_tbb_debug_lib "${_tbb_root}/@TBB_LIB_REL_PATH@/${_tbb_subdir}/@TBB_LIB_PREFIX@${_tbb_component}${_bin_version}_debug.@TBB_LIB_EXT@" ABSOLUTE)
|
||||
endif()
|
||||
|
||||
if (EXISTS "${_tbb_release_lib}" OR EXISTS "${_tbb_debug_lib}")
|
||||
if (NOT TARGET TBB::${_tbb_component})
|
||||
add_library(TBB::${_tbb_component} SHARED IMPORTED)
|
||||
|
||||
get_filename_component(_tbb_include_dir "${_tbb_root}/@TBB_INC_REL_PATH@" ABSOLUTE)
|
||||
set_target_properties(TBB::${_tbb_component} PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_tbb_include_dir}"@TBB_COMPILE_DEFINITIONS@)
|
||||
unset(_tbb_current_realpath)
|
||||
unset(_tbb_include_dir)
|
||||
|
||||
if (EXISTS "${_tbb_release_lib}")
|
||||
set_target_properties(TBB::${_tbb_component} PROPERTIES
|
||||
IMPORTED_LOCATION_RELEASE "${_tbb_release_lib}"@TBB_IMPLIB_RELEASE@)
|
||||
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
endif()
|
||||
|
||||
if (EXISTS "${_tbb_debug_lib}")
|
||||
set_target_properties(TBB::${_tbb_component} PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${_tbb_debug_lib}"@TBB_IMPLIB_DEBUG@)
|
||||
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
|
||||
endif()
|
||||
|
||||
# Add internal dependencies for imported targets: TBB::tbbmalloc_proxy -> TBB::tbbmalloc
|
||||
if (_tbb_component STREQUAL tbbmalloc_proxy)
|
||||
set_target_properties(TBB::tbbmalloc_proxy PROPERTIES INTERFACE_LINK_LIBRARIES TBB::tbbmalloc)
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
|
||||
set(TBB_${_tbb_component}_FOUND 1)
|
||||
elseif (TBB_FIND_REQUIRED AND TBB_FIND_REQUIRED_${_tbb_component})
|
||||
message(STATUS "Missed required oneTBB component: ${_tbb_component}")
|
||||
if (TBB_FIND_RELEASE_ONLY)
|
||||
message(STATUS " ${_tbb_release_lib} must exist.")
|
||||
else()
|
||||
message(STATUS " one or both of:\n ${_tbb_release_lib}\n ${_tbb_debug_lib}\n files must exist.")
|
||||
endif()
|
||||
set(TBB_FOUND FALSE)
|
||||
endif()
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES TBB_IMPORTED_TARGETS)
|
||||
unset(_tbb_release_lib)
|
||||
unset(_tbb_debug_lib)
|
||||
unset(_tbb_root)
|
||||
@@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2017-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(PACKAGE_VERSION @TBB_VERSION@)
|
||||
|
||||
if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
option(TBB_TEST_SPEC "Generate test specification (Doxygen)" OFF)
|
||||
|
||||
if (TBB_TEST_SPEC)
|
||||
find_package(Doxygen REQUIRED)
|
||||
|
||||
set(DOXYGEN_PREDEFINED_MACROS
|
||||
"TBB_USE_EXCEPTIONS \
|
||||
__TBB_RESUMABLE_TASKS \
|
||||
__TBB_HWLOC_PRESENT \
|
||||
__TBB_CPP17_DEDUCTION_GUIDES_PRESENT \
|
||||
__TBB_CPP17_MEMORY_RESOURCE_PRESENT \
|
||||
__TBB_CPP14_GENERIC_LAMBDAS_PRESENT"
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
test_spec ALL
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
COMMENT "Generating test specification with Doxygen"
|
||||
VERBATIM)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
|
||||
endif()
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Prevent double invocation.
|
||||
if (MIPS_TOOLCHAIN_INCLUDED)
|
||||
return()
|
||||
endif()
|
||||
set(MIPS_TOOLCHAIN_INCLUDED TRUE)
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
set(CMAKE_SYSTEM_PROCESSOR mips)
|
||||
|
||||
set(CMAKE_C_COMPILER ${CMAKE_FIND_ROOT_PATH}/bin/mips-img-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${CMAKE_FIND_ROOT_PATH}/bin/mips-img-linux-gnu-g++)
|
||||
set(CMAKE_LINKER ${CMAKE_FIND_ROOT_PATH}/bin/mips-img-linux-gnu-ld)
|
||||
|
||||
# Define result for try_run used in find_package(Threads).
|
||||
# In old CMake versions (checked on 3.5) there is invocation of try_run command in FindThreads.cmake module.
|
||||
# It can't be executed on host system in case of cross-compilation for MIPS architecture.
|
||||
# Define return code for this try_run as 0 since threads are expected to be available on target machine.
|
||||
set(THREADS_PTHREAD_ARG "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -EL -mabi=64 -march=mips64r6 -mcrc -mfp64 -mmt -mtune=mips64r6 -ggdb -ffp-contract=off -mhard-float" CACHE INTERNAL "")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mvirt -mxpa" CACHE INTERNAL "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mvirt -mxpa" CACHE INTERNAL "") # for tests
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
macro(tbb_remove_compile_flag flag)
|
||||
get_property(_tbb_compile_options DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS)
|
||||
list(REMOVE_ITEM _tbb_compile_options ${flag})
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS ${_tbb_compile_options})
|
||||
unset(_tbb_compile_options)
|
||||
if (CMAKE_CXX_FLAGS)
|
||||
string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(tbb_install_target target)
|
||||
install(TARGETS ${target}
|
||||
EXPORT TBBTargets
|
||||
LIBRARY
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
NAMELINK_SKIP
|
||||
COMPONENT runtime
|
||||
RUNTIME
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT runtime
|
||||
ARCHIVE
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT devel)
|
||||
|
||||
install(TARGETS ${target}
|
||||
LIBRARY
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
NAMELINK_ONLY
|
||||
COMPONENT devel)
|
||||
endmacro()
|
||||
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
option(TBB_INSTALL_VARS "Enable auto-generated vars installation" OFF)
|
||||
|
||||
if (WIN32)
|
||||
set(TBB_VARS_TEMPLATE "windows/env/vars.bat.in")
|
||||
elseif (APPLE)
|
||||
set(TBB_VARS_TEMPLATE "mac/env/vars.sh.in")
|
||||
else()
|
||||
set(TBB_VARS_TEMPLATE "linux/env/vars.sh.in")
|
||||
endif()
|
||||
|
||||
get_filename_component(TBB_VARS_TEMPLATE_NAME ${PROJECT_SOURCE_DIR}/integration/${TBB_VARS_TEMPLATE} NAME)
|
||||
string(REPLACE ".in" "" TBB_VARS_NAME ${TBB_VARS_TEMPLATE_NAME})
|
||||
|
||||
macro(tbb_gen_vars target)
|
||||
if (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
|
||||
add_custom_command(TARGET ${target} POST_BUILD COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DBINARY_DIR=${CMAKE_BINARY_DIR}
|
||||
-DSOURCE_DIR=${PROJECT_SOURCE_DIR}
|
||||
-DBIN_PATH=$<TARGET_FILE_DIR:${target}>
|
||||
-DVARS_TEMPLATE=${TBB_VARS_TEMPLATE}
|
||||
-DVARS_NAME=${TBB_VARS_NAME}
|
||||
-DTBB_INSTALL_VARS=${TBB_INSTALL_VARS}
|
||||
-DTBB_CMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
|
||||
-P ${PROJECT_SOURCE_DIR}/integration/cmake/generate_vars.cmake
|
||||
)
|
||||
endif()
|
||||
endmacro(tbb_gen_vars)
|
||||
|
||||
if (TBB_INSTALL_VARS)
|
||||
install(PROGRAMS "${CMAKE_BINARY_DIR}/internal_install_vars"
|
||||
DESTINATION env
|
||||
RENAME ${TBB_VARS_NAME})
|
||||
endif()
|
||||
+2495
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.14 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="no" title=""/>
|
||||
<tab type="pages" visible="no" title="" intro=""/>
|
||||
<tab type="modules" visible="yes" title="" intro=""/>
|
||||
<tab type="namespaces" visible="yes" title="">
|
||||
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="classes" visible="no" title="">
|
||||
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
||||
<tab type="classmembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="files" visible="yes" title="Test Suites">
|
||||
<tab type="filelist" visible="no" title="" intro=""/>
|
||||
<tab type="globals" visible="no" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="user" url="@ref test_classification" visible="yes" title="Test Classification"/>
|
||||
<tab type="examples" visible="yes" title="" intro=""/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
||||
@@ -0,0 +1,35 @@
|
||||
/// \page test_classification Test classification
|
||||
/// The list of test classes attributed to test cases.
|
||||
///
|
||||
/// \section interface \\\#interface
|
||||
/// This class of tests covers interface availability and checks basic
|
||||
/// interface behavior.
|
||||
///
|
||||
/// \section requirement \\\#requirement
|
||||
/// This class of tests covers one or more statements in the
|
||||
/// specification document.
|
||||
///
|
||||
/// \section negative \\\#negative
|
||||
/// This class of tests checks that input specified as invalid is
|
||||
/// processed correctly. Additionally, this class of tests might
|
||||
/// check imposibility to call particular interfaces that are not
|
||||
/// described by the specification.
|
||||
///
|
||||
/// \section resource_usage \\\#resource usage
|
||||
/// This class of tests checks correct resource usage and absence of
|
||||
/// resource leaks.
|
||||
///
|
||||
/// \section boundary \\\#boundary
|
||||
/// This class of tests checks boundary values, possible overflows, etc.
|
||||
///
|
||||
/// \section stress \\\#stress
|
||||
/// This class of tests tries to detect synchronization and other issues
|
||||
/// under heavy load and extensive usage of the functionality.
|
||||
///
|
||||
/// \section error_guessing \\\#error guessing
|
||||
/// This class of tests tries to detect issues that implementation might
|
||||
/// have but these issues cannot be deduced from the specification.
|
||||
///
|
||||
/// \section regression \\\#regression
|
||||
/// This class of tests covers issues that were detected and fixed after
|
||||
/// functionality release.
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
# Download links for old Intel(R) Threading Building Blocks packages
|
||||
|
||||
* 4.3 Update 6:
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150611oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150611oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150611oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150611oss_osx.tgz);
|
||||
|
||||
* 4.3 Update 5
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150424oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150424oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150424oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150424oss_osx.tgz);
|
||||
|
||||
* 4.3 Update 4
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150316oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150316oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150316oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150316oss_osx.tgz);
|
||||
|
||||
* 4.3 Update 3
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150209oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz);
|
||||
|
||||
* 4.3 Update 2
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20141204oss_src_0.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20141204oss_win_1.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20141204oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20141204oss_osx_1.tgz);
|
||||
|
||||
* 4.3 Update 1
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20141023oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20141023oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20141023oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20141023oss_osx.tgz);
|
||||
|
||||
* 4.3 Initial Release
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20140724oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20140724oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20140724oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20140724oss_osx.tgz);
|
||||
|
||||
* 4.2 Update 5
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20140601oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20140601oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20140601oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20140601oss_osx.tgz);
|
||||
|
||||
* 4.2 Update 4
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20140416oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20140416oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20140416oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20140416oss_osx.tgz);
|
||||
|
||||
* 4.2 Update 3
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20140122oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20140122oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20140122oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20140122oss_osx_0.tgz);
|
||||
|
||||
* 4.2 Update 2
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20131118oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20131118oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20131118oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20131118oss_osx.tgz);
|
||||
|
||||
* 4.2 Update 1
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20131003oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20131003oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20131003oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20131003oss_osx.tgz);
|
||||
|
||||
* 4.2 Initial Release
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20130725oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20130725oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20130725oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20130725oss_osx.tgz);
|
||||
|
||||
* 4.1 Update 4
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130613oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20130613oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20130613oss_lin_0.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20130613oss_osx.tgz);
|
||||
|
||||
* 4.1 Update 3
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130314oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20130314oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20130314oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20130314oss_osx.tgz);
|
||||
|
||||
* 4.1 Update 2
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130116oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20130116oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20130116oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20130116oss_osx.tgz);
|
||||
|
||||
* 4.1 Update 1
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20121003oss_src_1.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20121003oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20121003oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20121003oss_osx.tgz);
|
||||
|
||||
* 4.1 Initial Release
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20120718oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20120718oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20120718oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20120718oss_osx.tgz);
|
||||
|
||||
* 4.0 Update 5
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20120613oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20120613oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20120613oss_lin_0.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20120613oss_mac.tgz);
|
||||
|
||||
* 4.0 Update 4
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20120408oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20120408oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20120408oss_lin_0.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20120408oss_mac.tgz);
|
||||
|
||||
* 4.0 Update 3
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20120201oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20120201oss_win_2.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20120201oss_lin_1.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20120201oss_mac_0.tgz);
|
||||
|
||||
* 4.0 Update 2
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20111130oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20111130oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20111130oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20111130oss_mac.tgz);
|
||||
|
||||
* 4.0 Update 1
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20111003oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20111003oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20111003oss_lin_0.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20111003oss_mac.tgz);
|
||||
|
||||
* 4.0 Initial Release
|
||||
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20110809oss_src.tgz);
|
||||
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20110809oss_win.zip);
|
||||
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20110809oss_lin.tgz);
|
||||
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20110809oss_mac.tgz);
|
||||
@@ -0,0 +1,159 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignConsecutiveMacros: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: Empty
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 1
|
||||
UseTab: Never
|
||||
...
|
||||
@@ -0,0 +1,75 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(tbb_examples CXX)
|
||||
|
||||
add_custom_target(build_examples)
|
||||
add_custom_target(run_examples)
|
||||
add_dependencies(run_examples build_examples)
|
||||
|
||||
add_custom_target(light_test_examples)
|
||||
add_dependencies(light_test_examples build_examples)
|
||||
|
||||
macro(tbb_add_example subdir name)
|
||||
add_subdirectory(${subdir}/${name})
|
||||
add_dependencies(build_examples ${name})
|
||||
add_dependencies(run_examples run_${name})
|
||||
if (TARGET light_test_${name})
|
||||
add_dependencies(light_test_examples light_test_${name})
|
||||
else()
|
||||
add_dependencies(light_test_examples run_${name})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
tbb_add_example(concurrent_hash_map count_strings)
|
||||
tbb_add_example(concurrent_priority_queue shortpath)
|
||||
|
||||
tbb_add_example(getting_started sub_string_finder)
|
||||
|
||||
tbb_add_example(graph binpack)
|
||||
|
||||
# TODO: Consider using FindMKL module
|
||||
find_library(MKL_INTEL_LP64_LIB mkl_intel_lp64 PATHS ENV LIBRARY_PATH)
|
||||
find_library(MKL_SEQUENTIAL_LIB mkl_sequential PATHS ENV LIBRARY_PATH)
|
||||
find_library(MKL_CORE_LIB mkl_core PATHS ENV LIBRARY_PATH)
|
||||
if(MKL_INTEL_LP64_LIB AND MKL_SEQUENTIAL_LIB AND MKL_CORE_LIB)
|
||||
tbb_add_example(graph cholesky)
|
||||
else()
|
||||
message(WARNING "Intel(R) Math Kernel Library (Intel(R) MKL) libraries were not found, graph/cholesky example is excluded from the build.")
|
||||
endif()
|
||||
|
||||
tbb_add_example(graph dining_philosophers)
|
||||
tbb_add_example(graph fgbzip2)
|
||||
tbb_add_example(graph logic_sim)
|
||||
tbb_add_example(graph som)
|
||||
|
||||
tbb_add_example(parallel_for game_of_life)
|
||||
tbb_add_example(parallel_for polygon_overlay)
|
||||
tbb_add_example(parallel_for seismic)
|
||||
tbb_add_example(parallel_for tachyon)
|
||||
|
||||
tbb_add_example(parallel_for_each parallel_preorder)
|
||||
|
||||
tbb_add_example(parallel_pipeline square)
|
||||
|
||||
tbb_add_example(parallel_reduce convex_hull)
|
||||
tbb_add_example(parallel_reduce primes)
|
||||
|
||||
tbb_add_example(task_arena fractal)
|
||||
|
||||
tbb_add_example(task_group sudoku)
|
||||
|
||||
tbb_add_example(test_all fibonacci)
|
||||
@@ -0,0 +1,40 @@
|
||||
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
|
||||
This directory contains example usages of oneAPI Threading Building Blocks.
|
||||
|
||||
| Code sample name | Description
|
||||
|:--- |:---
|
||||
| getting_started/sub_string_finder | Example referenced by the [oneAPI Threading Building Blocks Get Started Guide](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html). Finds largest matching substrings.
|
||||
| concurrent_hash_map/count_strings | Concurrently inserts strings into a `concurrent_hash_map` container.
|
||||
| concurrent_priority_queue/shortpath | Solves the single source shortest path problem using a `concurrent_priority_queue` container.
|
||||
| graph/binpack | A solution to the binpacking problem using a `queue_node`, a `buffer_node` and `function_node`s.
|
||||
| graph/cholesky | Several versions of Cholesky Factorization algorithm implementation.
|
||||
| graph/dining_philosophers | An implementation of dining philosophers in graph using the reserving `join_node`.
|
||||
| graph/fgbzip2 | A parallel implementation of bzip2 block-sorting file compressor.
|
||||
| graph/logic_sim | An example of a collection of digital logic gates that can be easily composed into larger circuits.
|
||||
| graph/som | An example of a Kohonen Self-Organizing Map using cancellation.
|
||||
| parallel_for/game_of_life | Game of life overlay.
|
||||
| parallel_for/polygon_overlay | polygon overlay.
|
||||
| parallel_for/seismic | Parallel seismic wave simulation.
|
||||
| parallel_for/tachyon | Parallel 2-D raytracer/renderer.
|
||||
| parallel_for_each/parallel_preorder | Parallel preorder traversal of a graph.
|
||||
| parallel_pipeline/square | Another string transformation example that squares numbers read from a file.
|
||||
| parallel_reduce/convex_hull | Parallel version of convex hull algorithm (quick hull).
|
||||
| parallel_reduce/primes | Parallel version of the Sieve of Eratosthenes.
|
||||
| task_arena/fractal |The example calculates two classical Mandelbrot fractals with different concurrency limits.
|
||||
| task_group/sudoku | Compute all solutions for a Sudoku board.
|
||||
| test_all/fibonacci | Compute Fibonacci numbers in different ways.
|
||||
|
||||
## System Requirements
|
||||
"Refer to the [System Requirements](https://software.intel.com/content/www/us/en/develop/articles/intel-oneapi-threading-building-blocks-system-requirements.html) for the list of supported hardware and software".
|
||||
|
||||
### Graphical User Interface (GUI)
|
||||
Some examples (fractal, seismic, tachyon, polygon_overlay) supports different GUI modes, which may be defined via the `EXAMPLES_UI_MODE` CMake variable. Supported values are:
|
||||
- Cross-platform:
|
||||
- `con` - Console mode (Default).
|
||||
- Windows:
|
||||
- `gdi` - `GDI+` based implementation.
|
||||
- `d2d` - `Direct 2D` based implementation. May offer superior performance, but can only be used if the Microsoft* DirectX* SDK is installed on your system(`DXSDK_DIR` should be defined).
|
||||
- Linux:
|
||||
- `x` - `X11` based implementation. Also `libXext` may be required to display the output correctly.
|
||||
- MacOS:
|
||||
- `mac` - `OpenGL` based implementation. Also requires the `Foundation` and `Cocoa` libraries availability.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
macro(set_common_project_settings required_components)
|
||||
# Path to common headers
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
|
||||
if (NOT TARGET TBB::tbb)
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../common/cmake/modules)
|
||||
find_package(TBB REQUIRED COMPONENTS ${required_components})
|
||||
endif()
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------
|
||||
# Handle C++ standard version.
|
||||
if (NOT MSVC) # no need to cover MSVC as it uses C++14 by default.
|
||||
if (NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
if (CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION) # if standard option was detected by CMake
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_EXTENSIONS OFF) # use -std=c++... instead of -std=gnu++...
|
||||
# ---------------------------------------------------------------------------------------------------------
|
||||
endmacro()
|
||||
|
||||
macro(add_execution_target TARGET_NAME TARGET_DEPENDENCIES EXECUTABLE ARGS)
|
||||
if (WIN32)
|
||||
add_custom_target(${TARGET_NAME} set "PATH=$<TARGET_FILE_DIR:TBB::tbb>\\;$ENV{PATH}" & ${EXECUTABLE} ${ARGS})
|
||||
else()
|
||||
add_custom_target(${TARGET_NAME} ${EXECUTABLE} ${ARGS})
|
||||
endif()
|
||||
|
||||
add_dependencies(${TARGET_NAME} ${TARGET_DEPENDENCIES})
|
||||
endmacro()
|
||||
@@ -0,0 +1,89 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
# Firstly search for TBB in config mode (i.e. search for TBBConfig.cmake).
|
||||
find_package(TBB QUIET CONFIG)
|
||||
if (TBB_FOUND)
|
||||
find_package_handle_standard_args(TBB CONFIG_MODE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (NOT TBB_FIND_COMPONENTS)
|
||||
set(TBB_FIND_COMPONENTS tbb tbbmalloc)
|
||||
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
|
||||
set(TBB_FIND_REQUIRED_${_tbb_component} 1)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND ADDITIONAL_LIB_DIRS ENV PATH ENV LIB)
|
||||
list(APPEND ADDITIONAL_INCLUDE_DIRS ENV INCLUDE ENV CPATH)
|
||||
else()
|
||||
list(APPEND ADDITIONAL_LIB_DIRS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
|
||||
list(APPEND ADDITIONAL_INCLUDE_DIRS ENV CPATH ENV C_INCLUDE_PATH ENV CPLUS_INCLUDE_PATH ENV INCLUDE_PATH)
|
||||
endif()
|
||||
|
||||
find_path(_tbb_include_dir NAMES tbb/tbb.h PATHS ${ADDITIONAL_INCLUDE_DIRS})
|
||||
|
||||
if (_tbb_include_dir)
|
||||
# TODO: consider TBB_VERSION handling
|
||||
set(_TBB_BUILD_MODES RELEASE DEBUG)
|
||||
set(_TBB_DEBUG_SUFFIX _debug)
|
||||
|
||||
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
|
||||
if (NOT TARGET TBB::${_tbb_component})
|
||||
add_library(TBB::${_tbb_component} SHARED IMPORTED)
|
||||
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${_tbb_include_dir})
|
||||
|
||||
foreach(_TBB_BUILD_MODE ${_TBB_BUILD_MODES})
|
||||
set(_tbb_component_lib_name ${_tbb_component}${_TBB_${_TBB_BUILD_MODE}_SUFFIX})
|
||||
if (WIN32)
|
||||
find_library(${_tbb_component_lib_name}_lib ${_tbb_component_lib_name} PATHS ${ADDITIONAL_LIB_DIRS})
|
||||
find_file(${_tbb_component_lib_name}_dll ${_tbb_component_lib_name}.dll PATHS ${ADDITIONAL_LIB_DIRS})
|
||||
|
||||
set_target_properties(TBB::${_tbb_component} PROPERTIES
|
||||
IMPORTED_LOCATION_${_TBB_BUILD_MODE} "${${_tbb_component_lib_name}_dll}"
|
||||
IMPORTED_IMPLIB_${_TBB_BUILD_MODE} "${${_tbb_component_lib_name}_lib}"
|
||||
)
|
||||
else()
|
||||
find_library(${_tbb_component_lib_name}_so ${_tbb_component_lib_name} PATHS ${ADDITIONAL_LIB_DIRS})
|
||||
|
||||
set_target_properties(TBB::${_tbb_component} PROPERTIES
|
||||
IMPORTED_LOCATION_${_TBB_BUILD_MODE} "${${_tbb_component_lib_name}_so}"
|
||||
)
|
||||
endif()
|
||||
if (${_tbb_component_lib_name}_lib AND ${_tbb_component_lib_name}_dll OR ${_tbb_component_lib_name}_so)
|
||||
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${_TBB_BUILD_MODE})
|
||||
list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
|
||||
set(TBB_${_tbb_component}_FOUND 1)
|
||||
endif()
|
||||
unset(${_tbb_component_lib_name}_lib CACHE)
|
||||
unset(${_tbb_component_lib_name}_dll CACHE)
|
||||
unset(${_tbb_component_lib_name}_so CACHE)
|
||||
unset(_tbb_component_lib_name)
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
unset(_TBB_BUILD_MODESS)
|
||||
unset(_TBB_DEBUG_SUFFIX)
|
||||
endif()
|
||||
unset(_tbb_include_dir CACHE)
|
||||
|
||||
list(REMOVE_DUPLICATES TBB_IMPORTED_TARGETS)
|
||||
|
||||
find_package_handle_standard_args(TBB
|
||||
REQUIRED_VARS TBB_IMPORTED_TARGETS
|
||||
HANDLE_COMPONENTS)
|
||||
@@ -0,0 +1,127 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
set(EXAMPLES_UI_MODE "con" CACHE STRING "EXAMPLES_UI_MODE")
|
||||
|
||||
if (WIN32)
|
||||
set_property(CACHE EXAMPLES_UI_MODE PROPERTY STRINGS "con" "gdi" "d2d")
|
||||
elseif (APPLE)
|
||||
set_property(CACHE EXAMPLES_UI_MODE PROPERTY STRINGS "con" "mac")
|
||||
else()
|
||||
set_property(CACHE EXAMPLES_UI_MODE PROPERTY STRINGS "con" "x")
|
||||
endif()
|
||||
|
||||
get_property(_available_ui_modes CACHE EXAMPLES_UI_MODE PROPERTY STRINGS)
|
||||
|
||||
list(FIND _available_ui_modes ${EXAMPLES_UI_MODE} _find_index)
|
||||
if (NOT _find_index EQUAL -1)
|
||||
add_library(UI_LIB_${PROJECT_NAME} STATIC ${CMAKE_CURRENT_LIST_DIR}/${EXAMPLES_UI_MODE}video.cpp)
|
||||
|
||||
if (EXAMPLES_UI_MODE STREQUAL "mac")
|
||||
enable_language(C)
|
||||
add_library(UI_LIB_OBJECT_${PROJECT_NAME} OBJECT
|
||||
${CMAKE_CURRENT_LIST_DIR}/xcode/tbbExample/main.m
|
||||
${CMAKE_CURRENT_LIST_DIR}/xcode/tbbExample/OpenGLView.m
|
||||
${CMAKE_CURRENT_LIST_DIR}/xcode/tbbExample/tbbAppDelegate.m
|
||||
)
|
||||
target_sources(UI_LIB_${PROJECT_NAME} PUBLIC $<TARGET_OBJECTS:UI_LIB_OBJECT_${PROJECT_NAME}>)
|
||||
endif()
|
||||
else()
|
||||
string(REPLACE ";" ", " _available_ui_modes "${_available_ui_modes}")
|
||||
message(FATAL_ERROR
|
||||
"Selected UI mode (${EXAMPLES_UI_MODE}) is not supported on ${CMAKE_SYSTEM_NAME}.
|
||||
Supported UI modes: ${_available_ui_modes}"
|
||||
)
|
||||
endif()
|
||||
|
||||
macro(set_gdi_ui_project_settings)
|
||||
find_program(RC rc REQUIRED)
|
||||
add_custom_command(TARGET UI_LIB_${PROJECT_NAME} PRE_BUILD COMMAND
|
||||
${RC} /r -fo ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.res ${PROJECT_SOURCE_DIR}/gui/${PROJECT_NAME}.rc
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||
if (COMMAND target_link_options)
|
||||
target_link_options(UI_LIB_${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.res)
|
||||
else()
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.res)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(set_d2d_ui_project_settings)
|
||||
set_gdi_ui_project_settings()
|
||||
|
||||
if (IS_DIRECTORY $ENV{DXSDK_DIR})
|
||||
target_include_directories(UI_LIB_${PROJECT_NAME} PUBLIC $ENV{DXSDK_DIR}\\include)
|
||||
target_link_directories(UI_LIB_${PROJECT_NAME} PUBLIC $ENV{DXSDK_DIR}\\lib\\x64)
|
||||
else()
|
||||
message(FATAL_ERROR "Cannot find the DirectX library (required by the 'd2d' UI mode)")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(set_x_ui_project_settings)
|
||||
find_package(X11 REQUIRED)
|
||||
target_link_libraries(UI_LIB_${PROJECT_NAME} PUBLIC ${X11_LIBRARIES})
|
||||
target_include_directories(UI_LIB_${PROJECT_NAME} PUBLIC ${X11_INCLUDE_DIR})
|
||||
|
||||
find_library(LIB_Xext Xext PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
|
||||
if (LIB_Xext)
|
||||
target_link_libraries(UI_LIB_${PROJECT_NAME} PUBLIC ${LIB_Xext})
|
||||
else()
|
||||
target_compile_definitions(UI_LIB_${PROJECT_NAME} PUBLIC -DX_NOSHMEM)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(set_mac_ui_project_settings)
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
find_library(FOUNDATION_LIBRARY Foundation PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
|
||||
if (NOT FOUNDATION_LIBRARY)
|
||||
message(FATAL_ERROR "Cannot find the Foundation library (required by the 'mac' UI mode)")
|
||||
endif()
|
||||
|
||||
find_library(COCOA_LIBRARY Cocoa PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
|
||||
if (NOT COCOA_LIBRARY)
|
||||
message(FATAL_ERROR "Cannot find the Cocoa library (required by the 'mac' UI mode)")
|
||||
endif()
|
||||
|
||||
target_link_libraries(UI_LIB_${PROJECT_NAME} PUBLIC ${OPENGL_LIBRARIES} ${FOUNDATION_LIBRARY} ${COCOA_LIBRARY})
|
||||
target_include_directories(UI_LIB_${PROJECT_NAME} PUBLIC ${OPENGL_INCLUDE_DIR})
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/Resources)
|
||||
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/MacOS)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../../common/gui/xcode/tbbExample/PkgInfo DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents)
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../../common/gui/xcode/tbbExample/en.lproj DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/Resources)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../common/gui/xcode/tbbExample/tbbExample-Info.plist ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/Info.plist COPYONLY)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "MacUI/${PROJECT_NAME}.app/Contents/MacOS/")
|
||||
endmacro()
|
||||
|
||||
if (NOT _find_index EQUAL -1)
|
||||
if ("${EXAMPLES_UI_MODE}" STREQUAL "gdi")
|
||||
set_gdi_ui_project_settings()
|
||||
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "d2d")
|
||||
set_d2d_ui_project_settings()
|
||||
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "mac")
|
||||
set_mac_ui_project_settings()
|
||||
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "x")
|
||||
set_x_ui_project_settings()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
unset(_available_ui_modes)
|
||||
unset(_find_index)
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "video.hpp"
|
||||
|
||||
unsigned int *g_pImg = 0;
|
||||
int g_sizex, g_sizey;
|
||||
static video *g_video = 0;
|
||||
static int g_fps = 0;
|
||||
|
||||
#if _WIN32 || _WIN64
|
||||
|
||||
static DWORD g_msec = 0;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
HINSTANCE video::win_hInstance = 0;
|
||||
int video::win_iCmdShow = 0;
|
||||
void video::win_set_class(WNDCLASSEX &wcex) {}
|
||||
void video::win_load_accelerators(int idc) {}
|
||||
#endif //_WINDOWS
|
||||
|
||||
#else
|
||||
#include <sched.h>
|
||||
#include <sys/time.h>
|
||||
struct timeval g_time;
|
||||
#endif //_WIN32||_WIN64
|
||||
|
||||
#define CALC_FPS_ENABLED ((WINAPI_FAMILY != WINAPI_FAMILY_APP) && (!__ANDROID__))
|
||||
|
||||
video::video()
|
||||
// OpenGL* RGBA byte order for little-endian CPU
|
||||
: depth(24),
|
||||
red_shift(0),
|
||||
green_shift(8),
|
||||
blue_shift(16),
|
||||
red_mask(0xff),
|
||||
green_mask(0xff00),
|
||||
blue_mask(0xff0000) {
|
||||
assert(g_video == 0);
|
||||
g_video = this;
|
||||
title = "Video";
|
||||
updating = calc_fps = false;
|
||||
}
|
||||
|
||||
bool video::init_window(int x, int y) {
|
||||
g_sizex = x;
|
||||
g_sizey = y;
|
||||
g_pImg = new unsigned int[x * y];
|
||||
running = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool video::init_console() {
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void video::terminate() {
|
||||
#if CALC_FPS_ENABLED
|
||||
if (calc_fps) {
|
||||
double fps = g_fps;
|
||||
#if _WIN32 || _WIN64
|
||||
fps /= (GetTickCount() - g_msec) / 1000.0;
|
||||
#else
|
||||
struct timezone tz;
|
||||
struct timeval end_time;
|
||||
gettimeofday(&end_time, &tz);
|
||||
fps /= (end_time.tv_sec + 1.0 * end_time.tv_usec / 1000000.0) -
|
||||
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0);
|
||||
#endif
|
||||
printf("%s: %.1f fps\n", title, fps);
|
||||
}
|
||||
#endif
|
||||
g_video = 0;
|
||||
running = false;
|
||||
if (g_pImg) {
|
||||
delete[] g_pImg;
|
||||
g_pImg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
video::~video() {
|
||||
if (g_video)
|
||||
terminate();
|
||||
}
|
||||
|
||||
//! Count and display FPS count in titlebar
|
||||
bool video::next_frame() {
|
||||
#if CALC_FPS_ENABLED
|
||||
if (calc_fps) {
|
||||
if (!g_fps) {
|
||||
#if _WIN32 || _WIN64
|
||||
g_msec = GetTickCount();
|
||||
#else
|
||||
struct timezone tz;
|
||||
gettimeofday(&g_time, &tz);
|
||||
#endif
|
||||
}
|
||||
g_fps++;
|
||||
}
|
||||
#endif
|
||||
return running;
|
||||
}
|
||||
|
||||
//! Do standard loop
|
||||
void video::main_loop() {
|
||||
on_process();
|
||||
}
|
||||
|
||||
//! Change window title
|
||||
void video::show_title() {}
|
||||
|
||||
///////////////////////////////////////////// public methods of video class ///////////////////////
|
||||
|
||||
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
|
||||
: base_index(y * g_sizex + x),
|
||||
max_index(g_sizex * g_sizey),
|
||||
index_stride(g_sizex),
|
||||
pixel_depth(24),
|
||||
ptr32(g_pImg),
|
||||
start_x(x),
|
||||
start_y(y),
|
||||
size_x(sizex),
|
||||
size_y(sizey) {
|
||||
assert(x < g_sizex);
|
||||
assert(y < g_sizey);
|
||||
assert(x + sizex <= g_sizex);
|
||||
assert(y + sizey <= g_sizey);
|
||||
|
||||
index = base_index; // current index
|
||||
}
|
||||
|
||||
void drawing_area::update() {}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// common Windows parts
|
||||
#include "winvideo.hpp"
|
||||
|
||||
// and another headers
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include <dxsdkver.h>
|
||||
#if _DXSDK_PRODUCT_MAJOR < 9
|
||||
#error DXSDK Version 9 and above required.
|
||||
#endif
|
||||
#include <d2d1.h>
|
||||
#include <d2d1helper.h>
|
||||
#pragma comment(lib, "d2d1.lib")
|
||||
|
||||
ID2D1Factory *m_pD2DFactory;
|
||||
ID2D1HwndRenderTarget *m_pRenderTarget;
|
||||
ID2D1Bitmap *m_pBitmap;
|
||||
D2D1_SIZE_U bitmapSize;
|
||||
|
||||
HANDLE g_hVSync;
|
||||
|
||||
#include <DXErr.h>
|
||||
#pragma comment(lib, "DxErr.lib")
|
||||
|
||||
//! Create a dialog box and tell the user what went wrong
|
||||
bool DisplayError(LPSTR lpstrErr, HRESULT hres) {
|
||||
if (hres != S_OK) {
|
||||
static bool InError = false;
|
||||
int retval = 0;
|
||||
if (!InError) {
|
||||
InError = true;
|
||||
const char *message = hres ? DXGetErrorString(hres) : 0;
|
||||
retval =
|
||||
MessageBoxA(g_hAppWnd, lpstrErr, hres ? message : "Error!", MB_OK | MB_ICONERROR);
|
||||
InError = false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawBitmap() {
|
||||
HRESULT hr = S_OK;
|
||||
if (m_pRenderTarget) {
|
||||
m_pRenderTarget->BeginDraw();
|
||||
if (m_pBitmap)
|
||||
hr = m_pBitmap->CopyFromMemory(NULL, (BYTE *)g_pImg, 4 * g_sizex);
|
||||
DisplayError("DrawBitmap error", hr);
|
||||
m_pRenderTarget->DrawBitmap(m_pBitmap);
|
||||
m_pRenderTarget->EndDraw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline void mouse(int k, LPARAM lParam) {
|
||||
int x = (int)LOWORD(lParam);
|
||||
int y = (int)HIWORD(lParam);
|
||||
RECT rc;
|
||||
GetClientRect(g_hAppWnd, &rc);
|
||||
g_video->on_mouse(x * g_sizex / (rc.right - rc.left), y * g_sizey / (rc.bottom - rc.top), k);
|
||||
}
|
||||
|
||||
//! Win event processing function
|
||||
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (iMsg) {
|
||||
case WM_MOVE:
|
||||
// Check to make sure our window exists before we tell it to repaint.
|
||||
// This will fail the first time (while the window is being created).
|
||||
if (hwnd) {
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
UpdateWindow(hwnd);
|
||||
}
|
||||
return 0L;
|
||||
|
||||
case WM_SIZE:
|
||||
case WM_PAINT:
|
||||
if (g_video->running && g_video->updating) {
|
||||
DrawBitmap();
|
||||
Sleep(0);
|
||||
}
|
||||
break;
|
||||
// Process all mouse and keyboard events
|
||||
case WM_LBUTTONDOWN: mouse(1, lParam); break;
|
||||
case WM_LBUTTONUP: mouse(-1, lParam); break;
|
||||
case WM_RBUTTONDOWN: mouse(2, lParam); break;
|
||||
case WM_RBUTTONUP: mouse(-2, lParam); break;
|
||||
case WM_MBUTTONDOWN: mouse(3, lParam); break;
|
||||
case WM_MBUTTONUP: mouse(-3, lParam); break;
|
||||
case WM_CHAR: g_video->on_key((int)wParam); break;
|
||||
|
||||
// some useless stuff
|
||||
case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop
|
||||
case WM_DISPLAYCHANGE: return 0;
|
||||
|
||||
// Now, shut down the window...
|
||||
case WM_DESTROY: PostQuitMessage(0); return 0;
|
||||
}
|
||||
// call user defined proc, if exists
|
||||
return g_pUserProc ? g_pUserProc(hwnd, iMsg, wParam, lParam)
|
||||
: DefWindowProc(hwnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
bool video::init_window(int sizex, int sizey) {
|
||||
assert(win_hInstance != 0);
|
||||
g_sizex = sizex;
|
||||
g_sizey = sizey;
|
||||
if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, false)) {
|
||||
DisplayError("Unable to initialize the program's window.");
|
||||
return false;
|
||||
}
|
||||
ShowWindow(g_hAppWnd, SW_SHOW);
|
||||
g_pImg = new unsigned int[sizex * sizey];
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
|
||||
// Create a Direct2D render target.
|
||||
if (SUCCEEDED(hr) && !m_pRenderTarget) {
|
||||
RECT rc;
|
||||
GetClientRect(g_hAppWnd, &rc);
|
||||
|
||||
bitmapSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
|
||||
|
||||
hr = m_pD2DFactory->CreateHwndRenderTarget(
|
||||
D2D1::RenderTargetProperties(),
|
||||
D2D1::HwndRenderTargetProperties(g_hAppWnd, bitmapSize),
|
||||
&m_pRenderTarget);
|
||||
if (SUCCEEDED(hr) && !m_pBitmap) {
|
||||
D2D1_PIXEL_FORMAT pixelFormat =
|
||||
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
|
||||
D2D1_BITMAP_PROPERTIES bitmapProperties;
|
||||
bitmapProperties.pixelFormat = pixelFormat;
|
||||
m_pRenderTarget->GetDpi(&bitmapProperties.dpiX, &bitmapProperties.dpiY);
|
||||
m_pRenderTarget->CreateBitmap(bitmapSize, bitmapProperties, &m_pBitmap);
|
||||
m_pRenderTarget->DrawBitmap(m_pBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void video::terminate() {
|
||||
if (m_pBitmap)
|
||||
m_pBitmap->Release();
|
||||
if (m_pRenderTarget)
|
||||
m_pRenderTarget->Release();
|
||||
if (m_pD2DFactory)
|
||||
m_pD2DFactory->Release();
|
||||
g_video = 0;
|
||||
running = false;
|
||||
if (g_pImg) {
|
||||
delete[] g_pImg;
|
||||
g_pImg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////// drawing area constructor & destructor /////////////
|
||||
|
||||
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
|
||||
: base_index(y * g_sizex + x),
|
||||
max_index(g_sizex * g_sizey),
|
||||
index_stride(g_sizex),
|
||||
pixel_depth(24),
|
||||
ptr32(g_pImg),
|
||||
start_x(x),
|
||||
start_y(y),
|
||||
size_x(sizex),
|
||||
size_y(sizey) {
|
||||
assert(x < g_sizex);
|
||||
assert(y < g_sizey);
|
||||
assert(x + sizex <= g_sizex);
|
||||
assert(y + sizey <= g_sizey);
|
||||
|
||||
index = base_index; // current index
|
||||
}
|
||||
|
||||
void drawing_area::update() {
|
||||
if (g_video->updating) {
|
||||
RECT r;
|
||||
r.left = start_x;
|
||||
r.right = start_x + size_x;
|
||||
r.top = start_y;
|
||||
r.bottom = start_y + size_y;
|
||||
InvalidateRect(g_hAppWnd, &r, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// common Windows parts
|
||||
#include "winvideo.hpp"
|
||||
// include GDI+ headers
|
||||
#include <gdiplus.h>
|
||||
// and another headers
|
||||
#include <stdio.h>
|
||||
|
||||
// tag linking library
|
||||
#pragma comment(lib, "gdiplus.lib")
|
||||
|
||||
// global specific variables
|
||||
Gdiplus::Bitmap* g_pBitmap; // main drawing bitmap
|
||||
ULONG_PTR gdiplusToken;
|
||||
Gdiplus::GdiplusStartupInput gdiplusStartupInput; // GDI+
|
||||
|
||||
//! display system error
|
||||
bool DisplayError(LPSTR lpstrErr, HRESULT hres) {
|
||||
static bool InError = false;
|
||||
int retval = 0;
|
||||
if (!InError) {
|
||||
InError = true;
|
||||
LPCSTR lpMsgBuf;
|
||||
if (!hres)
|
||||
hres = GetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
hres,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
retval = MessageBox(g_hAppWnd, lpstrErr, lpMsgBuf, MB_OK | MB_ICONERROR);
|
||||
LocalFree((HLOCAL)lpMsgBuf);
|
||||
InError = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Win event processing function
|
||||
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (iMsg) {
|
||||
case WM_MOVE:
|
||||
// Check to make sure our window exists before we tell it to repaint.
|
||||
// This will fail the first time (while the window is being created).
|
||||
if (hwnd) {
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
UpdateWindow(hwnd);
|
||||
}
|
||||
return 0L;
|
||||
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
Gdiplus::Graphics graphics(BeginPaint(hwnd, &ps));
|
||||
// redraw just requested area. This call is as fast as simple DrawImage() call.
|
||||
if (g_video->updating)
|
||||
graphics.DrawImage(g_pBitmap,
|
||||
ps.rcPaint.left,
|
||||
ps.rcPaint.top,
|
||||
ps.rcPaint.left,
|
||||
ps.rcPaint.top,
|
||||
ps.rcPaint.right,
|
||||
ps.rcPaint.bottom,
|
||||
Gdiplus::UnitPixel);
|
||||
EndPaint(hwnd, &ps);
|
||||
}
|
||||
return 0L;
|
||||
|
||||
// Process all mouse and keyboard events
|
||||
case WM_LBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 1); break;
|
||||
case WM_LBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -1); break;
|
||||
case WM_RBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 2); break;
|
||||
case WM_RBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -2); break;
|
||||
case WM_MBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 3); break;
|
||||
case WM_MBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -3); break;
|
||||
case WM_CHAR: g_video->on_key((int)wParam); break;
|
||||
|
||||
// some useless stuff
|
||||
case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop
|
||||
case WM_DISPLAYCHANGE: return 0;
|
||||
|
||||
// Now, shut down the window...
|
||||
case WM_DESTROY: PostQuitMessage(0); return 0;
|
||||
}
|
||||
// call user defined proc, if exists
|
||||
return g_pUserProc ? g_pUserProc(hwnd, iMsg, wParam, lParam)
|
||||
: DefWindowProc(hwnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
///////////// video functions ////////////////
|
||||
|
||||
bool video::init_window(int sizex, int sizey) {
|
||||
assert(win_hInstance != 0);
|
||||
g_sizex = sizex;
|
||||
g_sizey = sizey;
|
||||
if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, true)) {
|
||||
DisplayError("Unable to initialize the program's window.");
|
||||
return false;
|
||||
}
|
||||
ShowWindow(g_hAppWnd, SW_SHOW);
|
||||
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||
g_pImg = new unsigned int[sizex * sizey];
|
||||
g_pBitmap =
|
||||
new Gdiplus::Bitmap(g_sizex, g_sizey, 4 * g_sizex, PixelFormat32bppRGB, (BYTE*)g_pImg);
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void video::terminate() {
|
||||
if (g_pBitmap) {
|
||||
delete g_pBitmap;
|
||||
g_pBitmap = 0;
|
||||
}
|
||||
Gdiplus::GdiplusShutdown(gdiplusToken);
|
||||
g_video = 0;
|
||||
running = false;
|
||||
if (g_pImg) {
|
||||
delete[] g_pImg;
|
||||
g_pImg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////// drawing area constructor & destructor /////////////
|
||||
|
||||
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
|
||||
: base_index(y * g_sizex + x),
|
||||
max_index(g_sizex * g_sizey),
|
||||
index_stride(g_sizex),
|
||||
pixel_depth(24),
|
||||
ptr32(g_pImg),
|
||||
start_x(x),
|
||||
start_y(y),
|
||||
size_x(sizex),
|
||||
size_y(sizey) {
|
||||
assert(x < g_sizex);
|
||||
assert(y < g_sizey);
|
||||
assert(x + sizex <= g_sizex);
|
||||
assert(y + sizey <= g_sizey);
|
||||
|
||||
index = base_index; // current index
|
||||
}
|
||||
|
||||
void drawing_area::update() {
|
||||
if (g_video->updating) {
|
||||
RECT r;
|
||||
r.left = start_x;
|
||||
r.right = start_x + size_x;
|
||||
r.top = start_y;
|
||||
r.bottom = start_y + size_y;
|
||||
InvalidateRect(g_hAppWnd, &r, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "video.hpp"
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <pthread.h>
|
||||
|
||||
unsigned int *g_pImg = 0;
|
||||
int g_sizex = 0, g_sizey = 0;
|
||||
static video *g_video = 0;
|
||||
static int g_fps = 0;
|
||||
char *window_title = NULL;
|
||||
#define WINDOW_TITLE_SIZE 256
|
||||
int cocoa_update = 0;
|
||||
|
||||
#include <sched.h>
|
||||
#include <sys/time.h>
|
||||
struct timeval g_time;
|
||||
|
||||
video::video()
|
||||
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
|
||||
: depth(24),
|
||||
red_shift(0),
|
||||
green_shift(8),
|
||||
blue_shift(16),
|
||||
red_mask(0xff),
|
||||
green_mask(0xff00),
|
||||
blue_mask(0xff0000)
|
||||
#else
|
||||
: depth(24),
|
||||
red_shift(16),
|
||||
green_shift(8),
|
||||
blue_shift(0),
|
||||
red_mask(0xff0000),
|
||||
green_mask(0xff00),
|
||||
blue_mask(0xff)
|
||||
#endif
|
||||
{
|
||||
assert(g_video == 0);
|
||||
g_video = this;
|
||||
title = "Video";
|
||||
cocoa_update = 1;
|
||||
updating = true;
|
||||
calc_fps = false;
|
||||
}
|
||||
|
||||
bool video::init_window(int x, int y) {
|
||||
g_sizex = x;
|
||||
g_sizey = y;
|
||||
g_pImg = new unsigned int[x * y];
|
||||
if (window_title == NULL)
|
||||
window_title = (char *)malloc(WINDOW_TITLE_SIZE);
|
||||
strncpy(window_title, title, WINDOW_TITLE_SIZE - 1);
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool video::init_console() {
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void video::terminate() {
|
||||
if (calc_fps) {
|
||||
double fps = g_fps;
|
||||
struct timezone tz;
|
||||
struct timeval end_time;
|
||||
gettimeofday(&end_time, &tz);
|
||||
fps /= (end_time.tv_sec + 1.0 * end_time.tv_usec / 1000000.0) -
|
||||
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0);
|
||||
printf("%s: %.1f fps\n", title, fps);
|
||||
}
|
||||
g_video = 0;
|
||||
running = false;
|
||||
if (g_pImg) {
|
||||
delete[] g_pImg;
|
||||
g_pImg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
video::~video() {
|
||||
if (g_video)
|
||||
terminate();
|
||||
}
|
||||
|
||||
//! Count and display FPS count in titlebar
|
||||
bool video::next_frame() {
|
||||
if (calc_fps) {
|
||||
if (!g_fps) {
|
||||
struct timezone tz;
|
||||
gettimeofday(&g_time, &tz);
|
||||
}
|
||||
g_fps++;
|
||||
}
|
||||
struct timezone tz;
|
||||
struct timeval now_time;
|
||||
gettimeofday(&now_time, &tz);
|
||||
double sec = ((now_time.tv_sec + 1.0 * now_time.tv_usec / 1000000.0) -
|
||||
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0));
|
||||
if (sec > 1) {
|
||||
if (calc_fps) {
|
||||
memcpy(&g_time, &now_time, sizeof(g_time));
|
||||
int fps;
|
||||
fps = g_fps / sec;
|
||||
cocoa_update = (int)updating;
|
||||
snprintf(window_title,
|
||||
WINDOW_TITLE_SIZE,
|
||||
"%s%s: %d fps",
|
||||
title,
|
||||
updating ? "" : " (no updating)",
|
||||
int(fps));
|
||||
g_fps = 0;
|
||||
}
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
void *thread_func(void *) {
|
||||
g_video->on_process();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
extern "C" void on_mouse_func(int x, int y, int k) {
|
||||
g_video->on_mouse(x, y, k);
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" void on_key_func(int x) {
|
||||
g_video->on_key(x);
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" int cocoa_main(int argc, char *argv[]);
|
||||
//! Do standard loop
|
||||
void video::main_loop() {
|
||||
pthread_t handle;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_create(&handle, &attr, &thread_func, (void *)NULL);
|
||||
pthread_detach(handle);
|
||||
cocoa_main(0, NULL);
|
||||
}
|
||||
|
||||
//! Change window title
|
||||
void video::show_title() {
|
||||
if (title)
|
||||
strncpy(window_title, title, WINDOW_TITLE_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////// public methods of video class ///////////////////////
|
||||
|
||||
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
|
||||
: base_index(y * g_sizex + x),
|
||||
max_index(g_sizex * g_sizey),
|
||||
index_stride(g_sizex),
|
||||
pixel_depth(24),
|
||||
ptr32(g_pImg),
|
||||
start_x(x),
|
||||
start_y(y),
|
||||
size_x(sizex),
|
||||
size_y(sizey) {
|
||||
assert(x < g_sizex);
|
||||
assert(y < g_sizey);
|
||||
assert(x + sizex <= g_sizex);
|
||||
assert(y + sizey <= g_sizey);
|
||||
|
||||
index = base_index; // current index
|
||||
}
|
||||
|
||||
void drawing_area::update() {
|
||||
//nothing to do, updating via timer in cocoa part.
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TBB_examples_video_H
|
||||
#define TBB_examples_video_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#if _MSC_VER
|
||||
#include <stddef.h> // for uintptr_t
|
||||
#else
|
||||
#include <stdint.h> // for uintptr_t
|
||||
#endif
|
||||
#if _WIN32 || _WIN64
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef unsigned int color_t;
|
||||
typedef unsigned char colorcomp_t;
|
||||
typedef signed char depth_t;
|
||||
|
||||
//! Class for getting access to drawing memory
|
||||
class drawing_memory {
|
||||
uintptr_t my_address;
|
||||
|
||||
public:
|
||||
depth_t pixel_depth;
|
||||
int sizex, sizey;
|
||||
//! Get drawing memory
|
||||
inline char *get_address() const {
|
||||
return reinterpret_cast<char *>(my_address);
|
||||
}
|
||||
//! Get drawing memory size
|
||||
inline int get_size() const {
|
||||
return ((pixel_depth > 16) ? 4 : 2) * sizex * sizey;
|
||||
}
|
||||
//! Set drawing memory
|
||||
inline void set_address(char *mem) {
|
||||
my_address = reinterpret_cast<uintptr_t>(mem);
|
||||
}
|
||||
|
||||
friend class drawing_area;
|
||||
friend class video;
|
||||
};
|
||||
|
||||
//! Simple proxy class for managing of different video systems
|
||||
class video {
|
||||
//! colorspace information
|
||||
depth_t depth, red_shift, green_shift, blue_shift;
|
||||
color_t red_mask, green_mask, blue_mask;
|
||||
friend class drawing_area;
|
||||
|
||||
public:
|
||||
//! Constructor
|
||||
video();
|
||||
//! Destructor
|
||||
~video();
|
||||
//! member to set window name
|
||||
const char *title;
|
||||
//! true is enable to show fps
|
||||
bool calc_fps;
|
||||
//! if true: on windows fork processing thread for on_process(), on non-windows note that next_frame() is called concurrently.
|
||||
bool threaded;
|
||||
//! true while running within main_loop()
|
||||
bool running;
|
||||
//! if true, do gui updating
|
||||
bool updating;
|
||||
//! initialize graphical video system
|
||||
bool init_window(int sizex, int sizey);
|
||||
//! initialize console. returns true if console is available
|
||||
bool init_console();
|
||||
//! terminate video system
|
||||
void terminate();
|
||||
//! Do standard event & processing loop. Use threaded = true to separate event/updating loop from frame processing
|
||||
void main_loop();
|
||||
//! Process next frame
|
||||
bool next_frame();
|
||||
//! Change window title
|
||||
void show_title();
|
||||
//! translate RGB components into packed type
|
||||
inline color_t get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const;
|
||||
//! Get drawing memory descriptor
|
||||
inline drawing_memory get_drawing_memory() const;
|
||||
|
||||
//! code of the ESCape key
|
||||
static const int esc_key = 27;
|
||||
//! Mouse events handler.
|
||||
virtual void on_mouse(int x, int y, int key) {}
|
||||
//! Mouse events handler.
|
||||
virtual void on_key(int key) {}
|
||||
//! Main processing loop. Redefine with your own
|
||||
virtual void on_process() {
|
||||
while (next_frame())
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
//! Windows specific members
|
||||
//! if VIDEO_WINMAIN isn't defined then set this just before init() by arguments of WinMain
|
||||
static HINSTANCE win_hInstance;
|
||||
static int win_iCmdShow;
|
||||
//! optionally call it just before init() to set own. Use ascii strings convention
|
||||
void win_set_class(WNDCLASSEX &);
|
||||
//! load and set accelerator table from resources
|
||||
void win_load_accelerators(int idc);
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Drawing class
|
||||
class drawing_area {
|
||||
const std::size_t base_index, max_index, index_stride;
|
||||
const depth_t pixel_depth;
|
||||
unsigned int *const ptr32;
|
||||
std::size_t index;
|
||||
|
||||
public:
|
||||
const int start_x, start_y, size_x, size_y;
|
||||
//! constructors
|
||||
drawing_area(int x, int y, int sizex, int sizey);
|
||||
inline drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem);
|
||||
//! destructor
|
||||
inline ~drawing_area();
|
||||
//! update the image
|
||||
void update();
|
||||
//! set current position. local_x could be bigger then size_x
|
||||
inline void set_pos(int local_x, int local_y);
|
||||
//! put pixel in current position with incremental address calculating to next right pixel
|
||||
inline void put_pixel(color_t color);
|
||||
//! draw pixel at position by packed color
|
||||
void set_pixel(int localx, int localy, color_t color) {
|
||||
set_pos(localx, localy);
|
||||
put_pixel(color);
|
||||
}
|
||||
};
|
||||
|
||||
extern int g_sizex;
|
||||
extern int g_sizey;
|
||||
extern unsigned int *g_pImg;
|
||||
|
||||
inline drawing_memory video::get_drawing_memory() const {
|
||||
drawing_memory dmem;
|
||||
dmem.pixel_depth = depth;
|
||||
dmem.my_address = reinterpret_cast<uintptr_t>(g_pImg);
|
||||
dmem.sizex = g_sizex;
|
||||
dmem.sizey = g_sizey;
|
||||
return dmem;
|
||||
}
|
||||
|
||||
inline color_t video::get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const {
|
||||
if (red_shift == 16) // only for depth == 24 && red_shift > blue_shift
|
||||
return (red << 16) | (green << 8) | blue;
|
||||
else if (depth >= 24)
|
||||
return
|
||||
#if __ANDROID__
|
||||
// Setting Alpha to 0xFF
|
||||
0xFF000000 |
|
||||
#endif
|
||||
(red << red_shift) | (green << green_shift) | (blue << blue_shift);
|
||||
else if (depth > 0) {
|
||||
depth_t bs = blue_shift, rs = red_shift;
|
||||
if (blue_shift < 0)
|
||||
blue >>= -bs, bs = 0;
|
||||
else /*red_shift < 0*/
|
||||
red >>= -rs, rs = 0;
|
||||
return ((red << rs) & red_mask) | ((green << green_shift) & green_mask) |
|
||||
((blue << bs) & blue_mask);
|
||||
}
|
||||
else { // UYVY colorspace
|
||||
unsigned y, u, v;
|
||||
y = red * 77 + green * 150 + blue * 29; // sum(77+150+29=256) * max(=255): limit->2^16
|
||||
u = (2048 + (blue << 3) - (y >> 5)) >> 4; // (limit->2^12)>>4
|
||||
v = (2048 + (red << 3) - (y >> 5)) >> 4;
|
||||
y = y >> 8;
|
||||
return u | (y << 8) | (v << 16) | (y << 24);
|
||||
}
|
||||
}
|
||||
|
||||
inline drawing_area::drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem)
|
||||
: base_index(y * dmem.sizex + x),
|
||||
max_index(dmem.sizex * dmem.sizey),
|
||||
index_stride(dmem.sizex),
|
||||
pixel_depth(dmem.pixel_depth),
|
||||
ptr32(reinterpret_cast<unsigned int *>(dmem.my_address)),
|
||||
start_x(x),
|
||||
start_y(y),
|
||||
size_x(sizex),
|
||||
size_y(sizey) {
|
||||
assert(x < dmem.sizex);
|
||||
assert(y < dmem.sizey);
|
||||
assert(x + sizex <= dmem.sizex);
|
||||
assert(y + sizey <= dmem.sizey);
|
||||
|
||||
index = base_index; // current index
|
||||
}
|
||||
|
||||
inline void drawing_area::set_pos(int local_x, int local_y) {
|
||||
index = base_index + local_x + local_y * index_stride;
|
||||
}
|
||||
|
||||
inline void drawing_area::put_pixel(color_t color) {
|
||||
assert(index < max_index);
|
||||
if (pixel_depth > 16)
|
||||
ptr32[index++] = color;
|
||||
else if (pixel_depth > 0)
|
||||
((unsigned short *)ptr32)[index++] = (unsigned short)color;
|
||||
else { // UYVY colorspace
|
||||
if (index & 1)
|
||||
color >>= 16;
|
||||
((unsigned short *)ptr32)[index++] = (unsigned short)color;
|
||||
}
|
||||
}
|
||||
|
||||
inline drawing_area::~drawing_area() {}
|
||||
|
||||
#if defined(_WINDOWS) && (defined(VIDEO_WINMAIN) || defined(VIDEO_WINMAIN_ARGS))
|
||||
#include <cstdlib>
|
||||
//! define WinMain for subsystem:windows.
|
||||
#ifdef VIDEO_WINMAIN_ARGS
|
||||
int main(int, char *[]);
|
||||
#else
|
||||
int main();
|
||||
#endif
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow) {
|
||||
video::win_hInstance = hInstance;
|
||||
video::win_iCmdShow = iCmdShow;
|
||||
#ifdef VIDEO_WINMAIN_ARGS
|
||||
return main(__argc, __argv);
|
||||
#else
|
||||
return main();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TBB_examples_video_H */
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/////// Common internal implementation of Windows-specific stuff //////////////
|
||||
/////// Must be the first included header //////////////
|
||||
|
||||
#ifndef __WINVIDEO_H__
|
||||
#define __WINVIDEO_H__
|
||||
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
// Check that the target Windows version has all API calls required.
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#if _WIN32_WINNT < 0x0400
|
||||
#define YIELD_TO_THREAD() Sleep(0)
|
||||
#else
|
||||
#define YIELD_TO_THREAD() SwitchToThread()
|
||||
#endif
|
||||
#include "video.hpp"
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#pragma comment(lib, "gdi32.lib")
|
||||
#pragma comment(lib, "user32.lib")
|
||||
|
||||
// maximum number of lines the output console should have
|
||||
static const WORD MAX_CONSOLE_LINES = 500;
|
||||
const COLORREF RGBKEY = RGB(8, 8, 16); // at least 8 for 16-bit palette
|
||||
HWND g_hAppWnd; // The program's window handle
|
||||
HANDLE g_handles[2] = { 0, 0 }; // thread and wake up event
|
||||
unsigned int *g_pImg = 0; // drawing memory
|
||||
int g_sizex, g_sizey;
|
||||
static video *g_video = 0;
|
||||
WNDPROC g_pUserProc = 0;
|
||||
HINSTANCE video::win_hInstance = 0;
|
||||
int video::win_iCmdShow = 0;
|
||||
static WNDCLASSEX *gWndClass = 0;
|
||||
static HACCEL hAccelTable = 0;
|
||||
static DWORD g_msec = 0;
|
||||
static int g_fps = 0, g_updates = 0, g_skips = 0;
|
||||
|
||||
bool DisplayError(LPSTR lpstrErr, HRESULT hres = 0); // always returns false
|
||||
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
//! Create window
|
||||
bool WinInit(HINSTANCE hInstance,
|
||||
int nCmdShow,
|
||||
WNDCLASSEX *uwc,
|
||||
const char *title,
|
||||
bool fixedsize) {
|
||||
WNDCLASSEX wndclass; // Our app's windows class
|
||||
if (uwc) {
|
||||
memcpy(&wndclass, uwc, sizeof(wndclass));
|
||||
g_pUserProc = uwc->lpfnWndProc;
|
||||
}
|
||||
else {
|
||||
memset(&wndclass, 0, sizeof(wndclass));
|
||||
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wndclass.lpszClassName = title;
|
||||
}
|
||||
wndclass.cbSize = sizeof(wndclass);
|
||||
wndclass.hInstance = hInstance;
|
||||
wndclass.lpfnWndProc = InternalWndProc;
|
||||
wndclass.style |= CS_HREDRAW | CS_VREDRAW;
|
||||
wndclass.hbrBackground = CreateSolidBrush(RGBKEY);
|
||||
|
||||
if (!RegisterClassExA(&wndclass))
|
||||
return false;
|
||||
int xaddend = GetSystemMetrics(fixedsize ? SM_CXFIXEDFRAME : SM_CXFRAME) * 2;
|
||||
int yaddend = GetSystemMetrics(fixedsize ? SM_CYFIXEDFRAME : SM_CYFRAME) * 2 +
|
||||
GetSystemMetrics(SM_CYCAPTION);
|
||||
if (wndclass.lpszMenuName)
|
||||
yaddend += GetSystemMetrics(SM_CYMENU);
|
||||
|
||||
// Setup the new window's physical parameters - and tell Windows to create it
|
||||
g_hAppWnd = CreateWindowA(wndclass.lpszClassName, // Window class name
|
||||
title, // Window caption
|
||||
!fixedsize ? WS_OVERLAPPEDWINDOW : // Window style
|
||||
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||
CW_USEDEFAULT, // Initial x pos: use default placement
|
||||
0, // Initial y pos: not used here
|
||||
g_sizex + xaddend, // Initial x size
|
||||
g_sizey + yaddend, // Initial y size
|
||||
NULL, // parent window handle
|
||||
NULL, // window menu handle
|
||||
hInstance, // program instance handle
|
||||
NULL); // Creation parameters
|
||||
return g_hAppWnd != NULL;
|
||||
}
|
||||
|
||||
//! create console window with redirection
|
||||
static bool RedirectIOToConsole(void) {
|
||||
int hConHandle;
|
||||
size_t lStdHandle;
|
||||
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
||||
FILE *fp;
|
||||
// allocate a console for this app
|
||||
AllocConsole();
|
||||
|
||||
// set the screen buffer to be big enough to let us scroll text
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
|
||||
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
|
||||
|
||||
// redirect unbuffered STDOUT to the console
|
||||
lStdHandle = (size_t)GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
|
||||
if (hConHandle <= 0)
|
||||
return false;
|
||||
fp = _fdopen(hConHandle, "w");
|
||||
*stdout = *fp;
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
// redirect unbuffered STDERR to the console
|
||||
lStdHandle = (size_t)GetStdHandle(STD_ERROR_HANDLE);
|
||||
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
|
||||
if (hConHandle > 0) {
|
||||
fp = _fdopen(hConHandle, "w");
|
||||
*stderr = *fp;
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
// redirect unbuffered STDIN to the console
|
||||
lStdHandle = (size_t)GetStdHandle(STD_INPUT_HANDLE);
|
||||
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
|
||||
if (hConHandle > 0) {
|
||||
fp = _fdopen(hConHandle, "r");
|
||||
*stdin = *fp;
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
|
||||
// point to console as well
|
||||
std::ios::sync_with_stdio();
|
||||
return true;
|
||||
}
|
||||
|
||||
video::video()
|
||||
: depth(24),
|
||||
red_shift(16),
|
||||
green_shift(8),
|
||||
blue_shift(0),
|
||||
red_mask(0xff0000),
|
||||
green_mask(0xff00),
|
||||
blue_mask(0xff) {
|
||||
assert(g_video == 0);
|
||||
g_video = this;
|
||||
title = "Video";
|
||||
running = threaded = calc_fps = false;
|
||||
updating = true;
|
||||
}
|
||||
|
||||
//! optionally call it just before init() to set own
|
||||
void video::win_set_class(WNDCLASSEX &wcex) {
|
||||
gWndClass = &wcex;
|
||||
}
|
||||
|
||||
void video::win_load_accelerators(int idc) {
|
||||
hAccelTable = LoadAccelerators(win_hInstance, MAKEINTRESOURCE(idc));
|
||||
}
|
||||
|
||||
bool video::init_console() {
|
||||
if (RedirectIOToConsole()) {
|
||||
if (!g_pImg && g_sizex && g_sizey)
|
||||
g_pImg = new unsigned int[g_sizex * g_sizey];
|
||||
if (g_pImg)
|
||||
running = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
video::~video() {
|
||||
if (g_video)
|
||||
terminate();
|
||||
}
|
||||
|
||||
DWORD WINAPI thread_video(LPVOID lpParameter) {
|
||||
video *v = (video *)lpParameter;
|
||||
v->on_process();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool loop_once(video *v) {
|
||||
// screen update notify
|
||||
if (int updates = g_updates) {
|
||||
g_updates = 0;
|
||||
if (g_video->updating) {
|
||||
g_skips += updates - 1;
|
||||
g_fps++;
|
||||
}
|
||||
else
|
||||
g_skips += updates;
|
||||
UpdateWindow(g_hAppWnd);
|
||||
}
|
||||
// update fps
|
||||
DWORD msec = GetTickCount();
|
||||
if (v->calc_fps && msec >= g_msec + 1000) {
|
||||
double sec = (msec - g_msec) / 1000.0;
|
||||
char buffer[256],
|
||||
n = _snprintf(buffer, 128, "%s: %d fps", v->title, int(double(g_fps + g_skips) / sec));
|
||||
if (g_skips)
|
||||
_snprintf(buffer + n,
|
||||
128,
|
||||
" - %d skipped = %d updates",
|
||||
int(g_skips / sec),
|
||||
int(g_fps / sec));
|
||||
SetWindowTextA(g_hAppWnd, buffer);
|
||||
g_msec = msec;
|
||||
g_skips = g_fps = 0;
|
||||
}
|
||||
// event processing, including painting
|
||||
MSG msg;
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
v->running = false;
|
||||
return false;
|
||||
}
|
||||
if (!hAccelTable || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return true; // try again
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Do standard event loop
|
||||
void video::main_loop() {
|
||||
// let Windows draw and unroll the window
|
||||
InvalidateRect(g_hAppWnd, 0, false);
|
||||
g_msec = GetTickCount(); // let's stay for 0,5 sec
|
||||
while (g_msec + 500 > GetTickCount()) {
|
||||
loop_once(this);
|
||||
Sleep(1);
|
||||
}
|
||||
g_msec = GetTickCount();
|
||||
// now, start main process
|
||||
if (threaded) {
|
||||
g_handles[0] = CreateThread(NULL, // LPSECURITY_ATTRIBUTES security_attrs
|
||||
0, // SIZE_T stacksize
|
||||
(LPTHREAD_START_ROUTINE)thread_video,
|
||||
this, // argument
|
||||
0,
|
||||
0);
|
||||
if (!g_handles[0]) {
|
||||
DisplayError("Can't create thread");
|
||||
return;
|
||||
}
|
||||
else // harmless race is possible here
|
||||
g_handles[1] = CreateEvent(NULL, false, false, NULL);
|
||||
while (running) {
|
||||
while (loop_once(this))
|
||||
;
|
||||
YIELD_TO_THREAD(); // give time for processing when running on single CPU
|
||||
DWORD r = MsgWaitForMultipleObjects(
|
||||
2, g_handles, false, INFINITE, QS_ALLINPUT ^ QS_MOUSEMOVE);
|
||||
if (r == WAIT_OBJECT_0)
|
||||
break; // thread terminated
|
||||
}
|
||||
running = false;
|
||||
if (WaitForSingleObject(g_handles[0], 3000) == WAIT_TIMEOUT) {
|
||||
// there was not enough time for graceful shutdown, killing the example with code 1.
|
||||
exit(1);
|
||||
}
|
||||
if (g_handles[0])
|
||||
CloseHandle(g_handles[0]);
|
||||
if (g_handles[1])
|
||||
CloseHandle(g_handles[1]);
|
||||
g_handles[0] = g_handles[1] = 0;
|
||||
}
|
||||
else
|
||||
on_process();
|
||||
}
|
||||
|
||||
//! Refresh screen picture
|
||||
bool video::next_frame() {
|
||||
if (!running)
|
||||
return false;
|
||||
g_updates++; // Fast but inaccurate counter. The data race here is benign.
|
||||
if (!threaded)
|
||||
while (loop_once(this))
|
||||
;
|
||||
else if (g_handles[1]) {
|
||||
SetEvent(g_handles[1]);
|
||||
YIELD_TO_THREAD();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Change window title
|
||||
void video::show_title() {
|
||||
if (g_hAppWnd)
|
||||
SetWindowTextA(g_hAppWnd, title);
|
||||
}
|
||||
|
||||
#endif //__WINVIDEO_H__
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "OpenGLES/ES2/gl.h"
|
||||
|
||||
@interface OpenGLView : UIView {
|
||||
NSTimer *timer;
|
||||
CGRect imageRect;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) NSTimer *timer;
|
||||
@property (nonatomic) CGRect imageRect;
|
||||
|
||||
- (void) drawRect:(CGRect)rect;
|
||||
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
|
||||
@end
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface OpenGLView : NSOpenGLView{
|
||||
NSTimer *timer;
|
||||
}
|
||||
|
||||
@property (nonatomic,retain) NSTimer *timer;
|
||||
|
||||
- (void) drawRect:(NSRect)start;
|
||||
- (void) mouseDown:(NSEvent *)theEvent;
|
||||
- (void) keyDown:(NSEvent *)theEvent;
|
||||
- (BOOL) acceptsFirstResponder;
|
||||
- (void) viewDidEndLiveResize;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OpenGLView.h"
|
||||
|
||||
// defined in macvideo.cpp
|
||||
extern char* window_title;
|
||||
extern int cocoa_update;
|
||||
extern int g_sizex, g_sizey;
|
||||
extern unsigned int *g_pImg;
|
||||
void on_mouse_func(int x, int y, int k);
|
||||
void on_key_func(int x);
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#import "OpenGLES/ES2/gl.h"
|
||||
|
||||
@implementation OpenGLView
|
||||
|
||||
@synthesize timer;
|
||||
@synthesize imageRect;
|
||||
|
||||
- (void)drawRect:(CGRect)start
|
||||
{
|
||||
if (initialized == false) {
|
||||
NSLog(@"INITIALIZE");
|
||||
timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(update_window) userInfo:nil repeats:YES];
|
||||
imageRect = [[UIScreen mainScreen] bounds];
|
||||
CGFloat full_height = imageRect.size.height;
|
||||
const float ratio=(float)g_sizex/g_sizey;
|
||||
imageRect.size.height=imageRect.size.width/ratio;
|
||||
imageRect.origin.y=(full_height-imageRect.size.height)/2;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, g_pImg, 4*g_sizex*g_sizey, NULL);
|
||||
|
||||
CGImageRef inputImage = CGImageCreate(g_sizex, g_sizey, 8, 32, g_sizex * 4, colourSpace,(CGBitmapInfo)kCGImageAlphaNoneSkipLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);
|
||||
UIImage *image = [UIImage imageWithCGImage:inputImage];
|
||||
|
||||
CGDataProviderRelease(dataProvider);
|
||||
CGColorSpaceRelease(colourSpace);
|
||||
CGImageRelease(inputImage);
|
||||
|
||||
[image drawInRect:imageRect];
|
||||
|
||||
}
|
||||
|
||||
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
CGPoint point = [[touches anyObject] locationInView:self];
|
||||
const int x = point.x;
|
||||
const int y = point.y;
|
||||
if ( (y-imageRect.origin.y) > 0 && y < (imageRect.origin.y + imageRect.size.height ))
|
||||
on_mouse_func( x*g_sizex/(imageRect.size.width), (y-imageRect.origin.y)*g_sizey/imageRect.size.height,1);
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
-(void) update_window{
|
||||
if( cocoa_update ) [self setNeedsDisplay];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
#import <OpenGL/gl.h>
|
||||
|
||||
@implementation OpenGLView
|
||||
|
||||
@synthesize timer;
|
||||
|
||||
- (void) drawRect:(NSRect)start
|
||||
{
|
||||
if (initialized == false) {
|
||||
NSLog(@"INITIALIZE");
|
||||
timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(update_window) userInfo:nil repeats:YES];
|
||||
initialized = true;
|
||||
}
|
||||
glWindowPos2i(0, (int)self.visibleRect.size.height);
|
||||
glPixelZoom( (float)self.visibleRect.size.width /(float)g_sizex,
|
||||
-(float)self.visibleRect.size.height/(float)g_sizey);
|
||||
glDrawPixels(g_sizex, g_sizey, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, g_pImg);
|
||||
glFlush();
|
||||
}
|
||||
|
||||
-(void) update_window{
|
||||
if( cocoa_update ) [self setNeedsDisplay:YES];
|
||||
if( window_title ) [self.window setTitle:[NSString stringWithFormat:@"%s", window_title]];
|
||||
}
|
||||
|
||||
-(void) keyDown:(NSEvent *)theEvent{
|
||||
on_key_func([theEvent.characters characterAtIndex:0]);
|
||||
}
|
||||
|
||||
-(void) mouseDown:(NSEvent *)theEvent{
|
||||
// mouse event for seismic and fractal
|
||||
NSPoint point= theEvent.locationInWindow;
|
||||
const int x = (int)point.x;
|
||||
const int y = (int)point.y;
|
||||
NSRect rect = self.visibleRect;
|
||||
on_mouse_func(x*g_sizex/(int)rect.size.width,((int)rect.size.height-y)*g_sizey/(int)rect.size.height,1);
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (BOOL) acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-(void) viewDidEndLiveResize
|
||||
{
|
||||
NSRect rect = self.visibleRect;
|
||||
const int x=(int)rect.size.width;
|
||||
const int y=(int)rect.size.height;
|
||||
[self.window setTitle:[NSString stringWithFormat:@"X=%d Y=%d", x,y]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
APPL????
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9060"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="494" id="495"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<menu title="AMainMenu" systemMenu="main" id="29">
|
||||
<items>
|
||||
<menuItem title="tbbExample" id="56">
|
||||
<menu key="submenu" title="tbbExample" systemMenu="apple" id="57">
|
||||
<items>
|
||||
<menuItem title="Quit tbbExample" keyEquivalent="q" id="136">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-3" id="449"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="tbbExample" allowsToolTipsWhenApplicationIsInactive="NO" deferred="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="100" y="100" width="480" height="360"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="1002"/>
|
||||
<view key="contentView" focusRingType="none" horizontalHuggingPriority="1" verticalHuggingPriority="9" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" id="372" customClass="OpenGLView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</view>
|
||||
</window>
|
||||
<customObject id="494" customClass="tbbAppDelegate">
|
||||
<connections>
|
||||
<outlet property="window" destination="371" id="532"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="420" customClass="NSFontManager"/>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="AKo-RD-jUr">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="aF8-QV-POo">
|
||||
<objects>
|
||||
<viewController id="AKo-RD-jUr" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="SEe-ff-xUc"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Cp9-IV-SKb"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="1aY-my-944" customClass="OpenGLView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="wcZ-9q-FxX" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="90" y="88"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Availability.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "tbbAppDelegate.h"
|
||||
|
||||
void get_screen_resolution(int *x, int *y) {
|
||||
// Getting landscape screen resolution in any case
|
||||
CGRect imageRect = [[UIScreen mainScreen] bounds];
|
||||
*x=imageRect.size.width>imageRect.size.height?imageRect.size.width:imageRect.size.height;
|
||||
*y=imageRect.size.width<imageRect.size.height?imageRect.size.width:imageRect.size.height;
|
||||
return;
|
||||
}
|
||||
|
||||
int cocoa_main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([tbbAppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int cocoa_main(int argc, char *argv[])
|
||||
{
|
||||
return NSApplicationMain(argc, (const char **)argv);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Xcode* 4.3.2
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface tbbAppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface tbbAppDelegate : NSObject <NSApplicationDelegate>{
|
||||
__unsafe_unretained NSWindow *_window;
|
||||
}
|
||||
|
||||
@property (assign) IBOutlet NSWindow *window;
|
||||
|
||||
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "tbbAppDelegate.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
@implementation tbbAppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||
{
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
@implementation tbbAppDelegate
|
||||
|
||||
@synthesize window = _window;
|
||||
|
||||
//declared in macvideo.cpp file
|
||||
extern int g_sizex, g_sizey;
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
// Insert code here to initialize your application
|
||||
NSRect windowSize;
|
||||
windowSize.size.height = g_sizey;
|
||||
windowSize.size.width = g_sizex;
|
||||
windowSize.origin=_window.frame.origin;
|
||||
[_window setFrame:windowSize display:YES];
|
||||
|
||||
}
|
||||
|
||||
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>iOS</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>iOS</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string></string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.business</string>
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>DYLD_LIBRARY_PATH</key>
|
||||
<string>Resources:.:../Resources:/tmp:$DYLD_LIBRARY_PATH</string>
|
||||
<key>LIBRARY_PATH</key>
|
||||
<string>Resources:.:../:/tmp:$DYLD_LIBRARY_PATH</string>
|
||||
</dict>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright 2005-2021 Intel Corporation. All Rights Reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Uncomment next line to disable shared memory features if you do not have libXext
|
||||
// (http://www.xfree86.org/current/mit-shm.html)
|
||||
//#define X_NOSHMEM
|
||||
|
||||
// Note that it may happen that the build environment supports the shared-memory extension
|
||||
// (so there's no build-time reason to disable the relevant code by defining X_NOSHMEM),
|
||||
// but that using shared memory still fails at run time.
|
||||
// This situation will (ultimately) cause the error handler set by XSetErrorHandler()
|
||||
// to be invoked with XErrorEvent::minor_code==X_ShmAttach. The code below tries to make
|
||||
// such a determination at XShmAttach() time, which seems plausible, but unfortunately
|
||||
// it has also been observed in a specific environment that the error may be reported
|
||||
// at a later time instead, even after video::init_window() has returned.
|
||||
// It is not clear whether this may happen in that way in any environment where it might
|
||||
// depend on the kind of display, e.g., local vs. over "ssh -X", so #define'ing X_NOSHMEM
|
||||
// may not always be the appropriate solution, therefore an environment variable
|
||||
// has been introduced to disable shared memory at run time.
|
||||
// A diagnostic has been added to advise the user about possible workarounds.
|
||||
// X_ShmAttach macro was changed to 1 due to recent changes to X11/extensions/XShm.h header.
|
||||
|
||||
#include "video.hpp"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifndef X_NOSHMEM
|
||||
#include <errno.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
static XShmSegmentInfo shmseginfo;
|
||||
static Pixmap pixmap = 0;
|
||||
static bool already_called_X_ShmAttach = false;
|
||||
static bool already_advised_about_NOSHMEM_workarounds = false;
|
||||
#endif
|
||||
static char *display_name = NULL;
|
||||
static Display *dpy = NULL;
|
||||
static Screen *scrn;
|
||||
static Visual *vis;
|
||||
static Colormap cmap;
|
||||
static GC gc;
|
||||
static Window win, rootW;
|
||||
static int dispdepth = 0;
|
||||
static XGCValues xgcv;
|
||||
static XImage *ximage;
|
||||
static int x_error = 0;
|
||||
static int vidtype = 3;
|
||||
int g_sizex, g_sizey;
|
||||
static video *g_video = 0;
|
||||
unsigned int *g_pImg = 0;
|
||||
static int g_fps = 0;
|
||||
struct timeval g_time;
|
||||
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
Atom _XA_WM_DELETE_WINDOW = 0; // like in Xatom.h
|
||||
|
||||
///////////////////////////////////////////// public methods of video class ///////////////////////
|
||||
|
||||
video::video() {
|
||||
assert(g_video == 0);
|
||||
g_video = this;
|
||||
title = "Video";
|
||||
calc_fps = running = false;
|
||||
updating = true;
|
||||
}
|
||||
|
||||
inline void mask2bits(unsigned int mask, unsigned int &save, depth_t &shift) {
|
||||
save = mask;
|
||||
if (!mask) {
|
||||
shift = dispdepth / 3;
|
||||
return;
|
||||
}
|
||||
shift = 0;
|
||||
while (!(mask & 1))
|
||||
++shift, mask >>= 1;
|
||||
int bits = 0;
|
||||
while (mask & 1)
|
||||
++bits, mask >>= 1;
|
||||
shift += bits - 8;
|
||||
}
|
||||
|
||||
int xerr_handler(Display *dpy_, XErrorEvent *error) {
|
||||
x_error = error->error_code;
|
||||
if (g_video)
|
||||
g_video->running = false;
|
||||
#ifndef X_NOSHMEM
|
||||
if (error->minor_code == 1 /*X_ShmAttach*/ && already_called_X_ShmAttach &&
|
||||
!already_advised_about_NOSHMEM_workarounds) {
|
||||
char err[256];
|
||||
XGetErrorText(dpy_, x_error, err, 255);
|
||||
fprintf(stderr, "Warning: Can't attach shared memory to display: %s (%d)\n", err, x_error);
|
||||
fprintf(
|
||||
stderr,
|
||||
"If you are seeing a black output window, сheck if you have installed Xext library and rebuild project");
|
||||
already_advised_about_NOSHMEM_workarounds = true;
|
||||
}
|
||||
#else
|
||||
(void)dpy_; // warning prevention
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool video::init_window(int xsize, int ysize) {
|
||||
{ //enclose local variables before fail label
|
||||
g_sizex = xsize;
|
||||
g_sizey = ysize;
|
||||
|
||||
// Open the display
|
||||
if (!dpy) {
|
||||
dpy = XOpenDisplay(display_name);
|
||||
if (!dpy) {
|
||||
fprintf(stderr, "Can't open X11 display %s\n", XDisplayName(display_name));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
int theScreen = DefaultScreen(dpy);
|
||||
scrn = ScreenOfDisplay(dpy, theScreen);
|
||||
dispdepth = DefaultDepth(dpy, theScreen);
|
||||
XVisualInfo vinfo;
|
||||
if (!((dispdepth >= 15 && dispdepth <= 32 &&
|
||||
XMatchVisualInfo(dpy, theScreen, dispdepth, TrueColor, &vinfo)) ||
|
||||
XMatchVisualInfo(dpy, theScreen, 24, TrueColor, &vinfo) ||
|
||||
XMatchVisualInfo(dpy, theScreen, 32, TrueColor, &vinfo) ||
|
||||
XMatchVisualInfo(dpy, theScreen, 16, TrueColor, &vinfo) ||
|
||||
XMatchVisualInfo(dpy, theScreen, 15, TrueColor, &vinfo))) {
|
||||
fprintf(stderr, "Display has no appropriate True Color visual\n");
|
||||
goto fail;
|
||||
}
|
||||
vis = vinfo.visual;
|
||||
depth = dispdepth = vinfo.depth;
|
||||
mask2bits(vinfo.red_mask, red_mask, red_shift);
|
||||
mask2bits(vinfo.green_mask, green_mask, green_shift);
|
||||
mask2bits(vinfo.blue_mask, blue_mask, blue_shift);
|
||||
rootW = RootWindow(dpy, theScreen);
|
||||
cmap = XCreateColormap(dpy, rootW, vis, AllocNone);
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.backing_store = Always;
|
||||
attrs.colormap = cmap;
|
||||
attrs.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask;
|
||||
attrs.background_pixel = BlackPixelOfScreen(scrn);
|
||||
attrs.border_pixel = WhitePixelOfScreen(scrn);
|
||||
win = XCreateWindow(dpy,
|
||||
rootW,
|
||||
0,
|
||||
0,
|
||||
xsize,
|
||||
ysize,
|
||||
2,
|
||||
dispdepth,
|
||||
InputOutput,
|
||||
vis,
|
||||
CWBackingStore | CWColormap | CWEventMask | CWBackPixel | CWBorderPixel,
|
||||
&attrs);
|
||||
if (!win) {
|
||||
fprintf(stderr, "Can't create the window\n");
|
||||
goto fail;
|
||||
}
|
||||
XSizeHints sh;
|
||||
sh.flags = PSize | PMinSize | PMaxSize;
|
||||
sh.width = sh.min_width = sh.max_width = xsize;
|
||||
sh.height = sh.min_height = sh.max_height = ysize;
|
||||
XSetStandardProperties(dpy, win, g_video->title, g_video->title, None, NULL, 0, &sh);
|
||||
_XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", false);
|
||||
XSetWMProtocols(dpy, win, &_XA_WM_DELETE_WINDOW, 1);
|
||||
gc = XCreateGC(dpy, win, 0L, &xgcv);
|
||||
XMapRaised(dpy, win);
|
||||
XFlush(dpy);
|
||||
#ifdef X_FULLSYNC
|
||||
XSynchronize(dpy, true);
|
||||
#endif
|
||||
XSetErrorHandler(xerr_handler);
|
||||
|
||||
int imgbytes = xsize * ysize * (dispdepth <= 16 ? 2 : 4);
|
||||
const char *vidstr;
|
||||
#ifndef X_NOSHMEM
|
||||
int major, minor, pixmaps;
|
||||
if (XShmQueryExtension(dpy) &&
|
||||
XShmQueryVersion(dpy, &major, &minor, &pixmaps)) { // Shared memory
|
||||
shmseginfo.shmid = shmget(IPC_PRIVATE, imgbytes, IPC_CREAT | 0777);
|
||||
if (shmseginfo.shmid < 0) {
|
||||
fprintf(stderr, "Warning: Can't get shared memory: %s\n", strerror(errno));
|
||||
goto generic;
|
||||
}
|
||||
g_pImg = (unsigned int *)(shmseginfo.shmaddr = (char *)shmat(shmseginfo.shmid, 0, 0));
|
||||
if (g_pImg == (unsigned int *)-1) {
|
||||
fprintf(stderr, "Warning: Can't attach to shared memory: %s\n", strerror(errno));
|
||||
shmctl(shmseginfo.shmid, IPC_RMID, NULL);
|
||||
goto generic;
|
||||
}
|
||||
shmseginfo.readOnly = false;
|
||||
if (!XShmAttach(dpy, &shmseginfo) || x_error) {
|
||||
char err[256];
|
||||
XGetErrorText(dpy, x_error, err, 255);
|
||||
fprintf(stderr,
|
||||
"Warning: Can't attach shared memory to display: %s (%d)\n",
|
||||
err,
|
||||
x_error);
|
||||
shmdt(shmseginfo.shmaddr);
|
||||
shmctl(shmseginfo.shmid, IPC_RMID, NULL);
|
||||
goto generic;
|
||||
}
|
||||
already_called_X_ShmAttach = true;
|
||||
|
||||
#ifndef X_NOSHMPIX
|
||||
if (pixmaps && XShmPixmapFormat(dpy) == ZPixmap) { // Pixmaps
|
||||
vidtype = 2;
|
||||
vidstr = "X11 shared memory pixmap";
|
||||
pixmap = XShmCreatePixmap(
|
||||
dpy, win, (char *)g_pImg, &shmseginfo, xsize, ysize, dispdepth);
|
||||
XSetWindowBackgroundPixmap(dpy, win, pixmap);
|
||||
}
|
||||
else
|
||||
#endif //!X_NOSHMPIX
|
||||
{ // Standard
|
||||
vidtype = 1;
|
||||
vidstr = "X11 shared memory";
|
||||
ximage =
|
||||
XShmCreateImage(dpy, vis, dispdepth, ZPixmap, 0, &shmseginfo, xsize, ysize);
|
||||
if (!ximage) {
|
||||
fprintf(stderr, "Can't create the shared image\n");
|
||||
goto fail;
|
||||
}
|
||||
assert(ximage->bytes_per_line == xsize * (dispdepth <= 16 ? 2 : 4));
|
||||
ximage->data = shmseginfo.shmaddr;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef X_NOSHMEM
|
||||
generic:
|
||||
#endif
|
||||
vidtype = 0;
|
||||
vidstr = "generic X11";
|
||||
g_pImg = new unsigned int[imgbytes / sizeof(int)];
|
||||
ximage = XCreateImage(dpy,
|
||||
vis,
|
||||
dispdepth,
|
||||
ZPixmap,
|
||||
0,
|
||||
(char *)g_pImg,
|
||||
xsize,
|
||||
ysize,
|
||||
32,
|
||||
imgbytes / ysize);
|
||||
if (!ximage) {
|
||||
fprintf(stderr, "Can't create the image\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (ximage) {
|
||||
// Note: It may be more efficient to adopt the server's byte order
|
||||
// and swap once per get_color() call instead of once per pixel.
|
||||
const uint32_t probe = 0x03020100;
|
||||
const bool big_endian = (((const char *)(&probe))[0] == 0x03);
|
||||
ximage->byte_order = big_endian ? MSBFirst : LSBFirst;
|
||||
}
|
||||
printf("Note: using %s with %s visual for %d-bit color depth\n",
|
||||
vidstr,
|
||||
vis == DefaultVisual(dpy, theScreen) ? "default" : "non-default",
|
||||
dispdepth);
|
||||
running = true;
|
||||
return true;
|
||||
} // end of enclosing local variables
|
||||
fail:
|
||||
terminate();
|
||||
init_console();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool video::init_console() {
|
||||
if (!g_pImg && g_sizex && g_sizey) {
|
||||
dispdepth = 24;
|
||||
red_shift = 16;
|
||||
vidtype = 3; // fake video
|
||||
g_pImg = new unsigned int[g_sizex * g_sizey];
|
||||
running = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void video::terminate() {
|
||||
running = false;
|
||||
if (dpy) {
|
||||
vidtype = 3; // stop video
|
||||
if (threaded) {
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
}
|
||||
if (ximage) {
|
||||
XDestroyImage(ximage);
|
||||
ximage = 0;
|
||||
g_pImg = 0;
|
||||
} // it frees g_pImg for vidtype == 0
|
||||
#ifndef X_NOSHMEM
|
||||
if (pixmap)
|
||||
XFreePixmap(dpy, pixmap);
|
||||
if (shmseginfo.shmaddr) {
|
||||
XShmDetach(dpy, &shmseginfo);
|
||||
shmdt(shmseginfo.shmaddr);
|
||||
g_pImg = 0;
|
||||
}
|
||||
if (shmseginfo.shmid >= 0)
|
||||
shmctl(shmseginfo.shmid, IPC_RMID, NULL);
|
||||
#endif
|
||||
if (gc)
|
||||
XFreeGC(dpy, gc);
|
||||
if (win)
|
||||
XDestroyWindow(dpy, win);
|
||||
XCloseDisplay(dpy);
|
||||
dpy = 0;
|
||||
}
|
||||
if (g_pImg) {
|
||||
delete[] g_pImg;
|
||||
g_pImg = 0;
|
||||
} // if was allocated for console mode
|
||||
}
|
||||
|
||||
video::~video() {
|
||||
if (g_video)
|
||||
terminate();
|
||||
g_video = 0;
|
||||
}
|
||||
|
||||
//! Do standard event loop
|
||||
void video::main_loop() {
|
||||
struct timezone tz;
|
||||
gettimeofday(&g_time, &tz);
|
||||
on_process();
|
||||
}
|
||||
|
||||
//! Check for pending events once
|
||||
bool video::next_frame() {
|
||||
if (!running)
|
||||
return false;
|
||||
//! try acquire mutex if threaded code, returns on failure
|
||||
if (vidtype == 3 || threaded && pthread_mutex_trylock(&g_mutex))
|
||||
return running;
|
||||
//! Refresh screen picture
|
||||
g_fps++;
|
||||
#ifndef X_NOSHMPIX
|
||||
if (vidtype == 2 && updating)
|
||||
XClearWindow(dpy, win);
|
||||
#endif
|
||||
while (XPending(dpy)) {
|
||||
XEvent report;
|
||||
XNextEvent(dpy, &report);
|
||||
switch (report.type) {
|
||||
case ClientMessage:
|
||||
if (report.xclient.format != 32 || report.xclient.data.l[0] != _XA_WM_DELETE_WINDOW)
|
||||
break;
|
||||
case DestroyNotify: running = false;
|
||||
case KeyPress: on_key(XLookupKeysym(&report.xkey, 0)); break;
|
||||
case ButtonPress:
|
||||
on_mouse(report.xbutton.x, report.xbutton.y, report.xbutton.button);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
on_mouse(report.xbutton.x, report.xbutton.y, -report.xbutton.button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
struct timezone tz;
|
||||
struct timeval now_time;
|
||||
gettimeofday(&now_time, &tz);
|
||||
double sec = (now_time.tv_sec + 1.0 * now_time.tv_usec / 1000000.0) -
|
||||
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0);
|
||||
if (sec > 1) {
|
||||
memcpy(&g_time, &now_time, sizeof(g_time));
|
||||
if (calc_fps) {
|
||||
double fps = g_fps;
|
||||
g_fps = 0;
|
||||
char buffer[256];
|
||||
snprintf(buffer,
|
||||
256,
|
||||
"%s%s: %d fps",
|
||||
title,
|
||||
updating ? "" : " (no updating)",
|
||||
int(fps / sec));
|
||||
XStoreName(dpy, win, buffer);
|
||||
}
|
||||
#ifndef X_FULLSYNC
|
||||
XSync(dpy, false); // It is often better then using XSynchronize(dpy, true)
|
||||
#endif //X_FULLSYNC
|
||||
}
|
||||
if (threaded)
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Change window title
|
||||
void video::show_title() {
|
||||
if (vidtype < 3)
|
||||
XStoreName(dpy, win, title);
|
||||
}
|
||||
|
||||
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
|
||||
: base_index(y * g_sizex + x),
|
||||
max_index(g_sizex * g_sizey),
|
||||
index_stride(g_sizex),
|
||||
pixel_depth(dispdepth),
|
||||
ptr32(g_pImg),
|
||||
start_x(x),
|
||||
start_y(y),
|
||||
size_x(sizex),
|
||||
size_y(sizey) {
|
||||
assert(x < g_sizex);
|
||||
assert(y < g_sizey);
|
||||
assert(x + sizex <= g_sizex);
|
||||
assert(y + sizey <= g_sizey);
|
||||
|
||||
index = base_index; // current index
|
||||
}
|
||||
|
||||
void drawing_area::update() {
|
||||
if (!g_video->updating)
|
||||
return;
|
||||
#ifndef X_NOSHMEM
|
||||
switch (vidtype) {
|
||||
case 0:
|
||||
#endif
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
if (vidtype == 0)
|
||||
XPutImage(dpy, win, gc, ximage, start_x, start_y, start_x, start_y, size_x, size_y);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
#ifndef X_NOSHMEM
|
||||
break;
|
||||
case 1:
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
if (vidtype == 1)
|
||||
XShmPutImage(dpy,
|
||||
win,
|
||||
gc,
|
||||
ximage,
|
||||
start_x,
|
||||
start_y,
|
||||
start_x,
|
||||
start_y,
|
||||
size_x,
|
||||
size_y,
|
||||
false);
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
break;
|
||||
/*case 2: make it in next_frame(); break;*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TBB_examples_fast_random_H
|
||||
#define TBB_examples_fast_random_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace utility {
|
||||
//------------------------------------------------------------------------
|
||||
// FastRandom
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
namespace internal {
|
||||
std::size_t GetPrime(std::size_t seed);
|
||||
}
|
||||
|
||||
//! A fast random number generator.
|
||||
/** Uses linear congruential method. */
|
||||
class FastRandom {
|
||||
std::size_t x, a;
|
||||
|
||||
public:
|
||||
//! Get a random number.
|
||||
unsigned short get() {
|
||||
return get(x);
|
||||
}
|
||||
//! Get a random number for the given seed; update the seed for next use.
|
||||
unsigned short get(std::size_t& seed) {
|
||||
unsigned short r = (unsigned short)(seed >> 16);
|
||||
seed = seed * a + 1;
|
||||
return r;
|
||||
}
|
||||
//! Construct a random number generator.
|
||||
FastRandom(std::size_t seed) {
|
||||
x = seed * internal::GetPrime(seed);
|
||||
a = internal::GetPrime(x);
|
||||
}
|
||||
};
|
||||
} // namespace utility
|
||||
|
||||
namespace utility {
|
||||
namespace internal {
|
||||
//! Table of primes used by fast random-number generator (FastRandom).
|
||||
static const unsigned Primes[] = {
|
||||
0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, 0xba5703f5, 0xb495a877, 0xe1626741, 0x79695e6b,
|
||||
0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231, 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b,
|
||||
0xbe4d6fe9, 0x5f15e201, 0x99afc3fd, 0xf3f16801, 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3,
|
||||
0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, 0x085a3d61, 0x46eb5ea7, 0x3d9910ed, 0x2e687b5b,
|
||||
0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9, 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7,
|
||||
0x54581edb, 0xf2480f45, 0x0bb9288f, 0xef1affc7, 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7,
|
||||
0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, 0xfc411073, 0xc3749363, 0xb892d829, 0x3549366b,
|
||||
0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3, 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f
|
||||
};
|
||||
std::size_t GetPrime(std::size_t seed) {
|
||||
return Primes[seed % (sizeof(Primes) / sizeof(Primes[0]))];
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace utility
|
||||
|
||||
#endif /* TBB_examples_fast_random_H */
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TBB_examples_num_threads_H
|
||||
#define TBB_examples_num_threads_H
|
||||
|
||||
#include "oneapi/tbb/task_arena.h"
|
||||
|
||||
namespace utility {
|
||||
inline int get_default_num_threads() {
|
||||
return oneapi::tbb::this_task_arena::max_concurrency();
|
||||
}
|
||||
} // namespace utility
|
||||
|
||||
#endif /* TBB_examples_num_threads_H */
|
||||
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TBB_examples_utility_H
|
||||
#define TBB_examples_utility_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <numeric>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
// TBB headers should not be used, as some examples may need to be built without TBB.
|
||||
|
||||
namespace utility {
|
||||
namespace internal {
|
||||
|
||||
//TODO: add tcs
|
||||
template <class dest_type>
|
||||
dest_type& string_to(std::string const& s, dest_type& result) {
|
||||
std::stringstream stream(s);
|
||||
stream >> result;
|
||||
if ((!stream) || (stream.fail())) {
|
||||
throw std::invalid_argument("error converting string '" + std::string(s) + "'");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class dest_type>
|
||||
dest_type string_to(std::string const& s) {
|
||||
dest_type result;
|
||||
return string_to(s, result);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
struct is_bool {
|
||||
static bool value() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct is_bool<bool> {
|
||||
static bool value() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class type_base {
|
||||
type_base& operator=(const type_base&);
|
||||
|
||||
public:
|
||||
const std::string name;
|
||||
const std::string description;
|
||||
|
||||
type_base(std::string a_name, std::string a_description)
|
||||
: name(a_name),
|
||||
description(a_description) {}
|
||||
virtual void parse_and_store(const std::string& s) = 0;
|
||||
virtual std::string value() const = 0;
|
||||
virtual std::unique_ptr<type_base> clone() const = 0;
|
||||
virtual ~type_base() {}
|
||||
};
|
||||
template <typename type>
|
||||
class type_impl : public type_base {
|
||||
private:
|
||||
type_impl(const type_impl& src)
|
||||
: type_base(src.name, src.description),
|
||||
target(src.target),
|
||||
validating_function(src.validating_function) {}
|
||||
type_impl& operator=(const type_impl&);
|
||||
typedef bool (*validating_function_type)(const type&);
|
||||
type& target;
|
||||
validating_function_type validating_function;
|
||||
|
||||
public:
|
||||
type_impl(std::string a_name,
|
||||
std::string a_description,
|
||||
type& a_target,
|
||||
validating_function_type a_validating_function = nullptr)
|
||||
: type_base(a_name, a_description),
|
||||
target(a_target),
|
||||
validating_function(a_validating_function){};
|
||||
void parse_and_store(const std::string& s) /*override*/ {
|
||||
try {
|
||||
const bool is_bool = internal::is_bool<type>::value();
|
||||
if (is_bool && s.empty()) {
|
||||
//to avoid directly assigning true
|
||||
//(as it will impose additional layer of indirection)
|
||||
//so, simply pass it as string
|
||||
internal::string_to("1", target);
|
||||
}
|
||||
else {
|
||||
internal::string_to(s, target);
|
||||
}
|
||||
}
|
||||
catch (std::invalid_argument& e) {
|
||||
std::stringstream str;
|
||||
str << "'" << s << "' is incorrect input for argument '" << name << "'"
|
||||
<< " (" << e.what() << ")";
|
||||
throw std::invalid_argument(str.str());
|
||||
}
|
||||
if (validating_function) {
|
||||
if (!((validating_function)(target))) {
|
||||
std::stringstream str;
|
||||
str << "'" << target << "' is invalid value for argument '" << name << "'";
|
||||
throw std::invalid_argument(str.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename t>
|
||||
static bool is_null_c_str(t&) {
|
||||
return false;
|
||||
}
|
||||
static bool is_null_c_str(char* s) {
|
||||
return s == nullptr;
|
||||
}
|
||||
std::string value() const /*override*/ {
|
||||
std::stringstream str;
|
||||
if (!is_null_c_str(target))
|
||||
str << target;
|
||||
return str.str();
|
||||
}
|
||||
std::unique_ptr<type_base> clone() const /*override*/ {
|
||||
return std::unique_ptr<type_base>(new type_impl(*this));
|
||||
}
|
||||
};
|
||||
|
||||
class argument {
|
||||
private:
|
||||
std::unique_ptr<type_base> p_type;
|
||||
bool matched_;
|
||||
|
||||
public:
|
||||
argument(argument const& other)
|
||||
: p_type(other.p_type.get() ? (other.p_type->clone()).release() : nullptr),
|
||||
matched_(other.matched_) {}
|
||||
argument& operator=(argument a) {
|
||||
this->swap(a);
|
||||
return *this;
|
||||
}
|
||||
void swap(argument& other) {
|
||||
std::swap(p_type, other.p_type);
|
||||
std::swap(matched_, other.matched_);
|
||||
}
|
||||
template <class type>
|
||||
argument(std::string a_name,
|
||||
std::string a_description,
|
||||
type& dest,
|
||||
bool (*a_validating_function)(const type&) = nullptr)
|
||||
: p_type(new type_impl<type>(a_name, a_description, dest, a_validating_function)),
|
||||
matched_(false) {}
|
||||
std::string value() const {
|
||||
return p_type->value();
|
||||
}
|
||||
std::string name() const {
|
||||
return p_type->name;
|
||||
}
|
||||
std::string description() const {
|
||||
return p_type->description;
|
||||
}
|
||||
void parse_and_store(const std::string& s) {
|
||||
p_type->parse_and_store(s);
|
||||
matched_ = true;
|
||||
}
|
||||
bool is_matched() const {
|
||||
return matched_;
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
class cli_argument_pack {
|
||||
typedef std::map<std::string, internal::argument> args_map_type;
|
||||
typedef std::vector<std::string> args_display_order_type;
|
||||
typedef std::vector<std::string> positional_arg_names_type;
|
||||
|
||||
private:
|
||||
args_map_type args_map;
|
||||
args_display_order_type args_display_order;
|
||||
positional_arg_names_type positional_arg_names;
|
||||
std::set<std::string> bool_args_names;
|
||||
|
||||
private:
|
||||
void add_arg(internal::argument const& a) {
|
||||
std::pair<args_map_type::iterator, bool> result =
|
||||
args_map.insert(std::make_pair(a.name(), a));
|
||||
if (!result.second) {
|
||||
throw std::invalid_argument("argument with name: '" + a.name() +
|
||||
"' already registered");
|
||||
}
|
||||
args_display_order.push_back(a.name());
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename type>
|
||||
cli_argument_pack& arg(type& dest,
|
||||
std::string const& name,
|
||||
std::string const& description,
|
||||
bool (*validate)(const type&) = nullptr) {
|
||||
internal::argument a(name, description, dest, validate);
|
||||
add_arg(a);
|
||||
if (internal::is_bool<type>::value()) {
|
||||
bool_args_names.insert(name);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Positional means that argument name can be omitted in actual CL
|
||||
//only key to match values for parameters with
|
||||
template <typename type>
|
||||
cli_argument_pack& positional_arg(type& dest,
|
||||
std::string const& name,
|
||||
std::string const& description,
|
||||
bool (*validate)(const type&) = nullptr) {
|
||||
internal::argument a(name, description, dest, validate);
|
||||
add_arg(a);
|
||||
if (internal::is_bool<type>::value()) {
|
||||
bool_args_names.insert(name);
|
||||
}
|
||||
positional_arg_names.push_back(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void parse(std::size_t argc, char const* argv[]) {
|
||||
{
|
||||
std::size_t current_positional_index = 0;
|
||||
for (std::size_t j = 1; j < argc; j++) {
|
||||
internal::argument* pa = nullptr;
|
||||
std::string argument_value;
|
||||
|
||||
const char* const begin = argv[j];
|
||||
const char* const end = begin + std::strlen(argv[j]);
|
||||
|
||||
const char* const assign_sign = std::find(begin, end, '=');
|
||||
|
||||
struct throw_unknown_parameter {
|
||||
static void _(std::string const& location) {
|
||||
throw std::invalid_argument(std::string("unknown parameter starting at:'") +
|
||||
location + "'");
|
||||
}
|
||||
};
|
||||
//first try to interpret it like parameter=value string
|
||||
if (assign_sign != end) {
|
||||
std::string name_found = std::string(begin, assign_sign);
|
||||
args_map_type::iterator it = args_map.find(name_found);
|
||||
|
||||
if (it != args_map.end()) {
|
||||
pa = &((*it).second);
|
||||
argument_value = std::string(assign_sign + 1, end);
|
||||
}
|
||||
else {
|
||||
throw_unknown_parameter::_(argv[j]);
|
||||
}
|
||||
}
|
||||
//then see is it a named flag
|
||||
else {
|
||||
args_map_type::iterator it = args_map.find(argv[j]);
|
||||
if (it != args_map.end()) {
|
||||
pa = &((*it).second);
|
||||
argument_value = "";
|
||||
}
|
||||
//then try it as positional argument without name specified
|
||||
else if (current_positional_index < positional_arg_names.size()) {
|
||||
std::stringstream str(argv[j]);
|
||||
args_map_type::iterator found_positional_arg =
|
||||
args_map.find(positional_arg_names.at(current_positional_index));
|
||||
//TODO: probably use of smarter assert would help here
|
||||
assert(
|
||||
found_positional_arg !=
|
||||
args_map
|
||||
.end() /*&&"positional_arg_names and args_map are out of sync"*/);
|
||||
if (found_positional_arg == args_map.end()) {
|
||||
throw std::logic_error(
|
||||
"positional_arg_names and args_map are out of sync");
|
||||
}
|
||||
pa = &((*found_positional_arg).second);
|
||||
argument_value = argv[j];
|
||||
|
||||
current_positional_index++;
|
||||
}
|
||||
else {
|
||||
//TODO: add tc to check
|
||||
throw_unknown_parameter::_(argv[j]);
|
||||
}
|
||||
}
|
||||
assert(pa);
|
||||
if (pa->is_matched()) {
|
||||
throw std::invalid_argument(std::string("several values specified for: '") +
|
||||
pa->name() + "' argument");
|
||||
}
|
||||
pa->parse_and_store(argument_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string usage_string(const std::string& binary_name) const {
|
||||
std::string command_line_params;
|
||||
std::string summary_description;
|
||||
|
||||
for (args_display_order_type::const_iterator it = args_display_order.begin();
|
||||
it != args_display_order.end();
|
||||
++it) {
|
||||
const bool is_bool = (0 != bool_args_names.count((*it)));
|
||||
args_map_type::const_iterator argument_it = args_map.find(*it);
|
||||
//TODO: probably use of smarter assert would help here
|
||||
assert(argument_it !=
|
||||
args_map.end() /*&&"args_display_order and args_map are out of sync"*/);
|
||||
if (argument_it == args_map.end()) {
|
||||
throw std::logic_error("args_display_order and args_map are out of sync");
|
||||
}
|
||||
const internal::argument& a = (*argument_it).second;
|
||||
command_line_params += " [" + a.name() + (is_bool ? "" : "=value") + "]";
|
||||
summary_description +=
|
||||
" " + a.name() + " - " + a.description() + " (" + a.value() + ")" + "\n";
|
||||
}
|
||||
|
||||
std::string positional_arg_cl;
|
||||
for (positional_arg_names_type::const_iterator it = positional_arg_names.begin();
|
||||
it != positional_arg_names.end();
|
||||
++it) {
|
||||
positional_arg_cl += " [" + (*it);
|
||||
}
|
||||
for (std::size_t i = 0; i < positional_arg_names.size(); ++i) {
|
||||
positional_arg_cl += "]";
|
||||
}
|
||||
command_line_params += positional_arg_cl;
|
||||
std::stringstream str;
|
||||
str << " Program usage is:"
|
||||
<< "\n"
|
||||
<< " " << binary_name << command_line_params << "\n"
|
||||
<< "\n"
|
||||
<< " where:"
|
||||
<< "\n"
|
||||
<< summary_description;
|
||||
return str.str();
|
||||
}
|
||||
}; // class cli_argument_pack
|
||||
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
bool is_power_of_2(T val) {
|
||||
std::size_t intval = std::size_t(val);
|
||||
return (intval & (intval - 1)) == std::size_t(0);
|
||||
}
|
||||
int step_function_plus(int previous, double step) {
|
||||
return static_cast<int>(previous + step);
|
||||
}
|
||||
int step_function_multiply(int previous, double multiply) {
|
||||
return static_cast<int>(previous * multiply);
|
||||
}
|
||||
// "Power-of-2 ladder": nsteps is the desired number of steps between any subsequent powers of 2.
|
||||
// The actual step is the quotient of the nearest smaller power of 2 divided by that number (but at least 1).
|
||||
// E.g., '1:32:#4' means 1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32
|
||||
int step_function_power2_ladder(int previous, double nsteps) {
|
||||
int steps = int(nsteps);
|
||||
assert(is_power_of_2(steps)); // must be a power of 2
|
||||
// The actual step is 1 until the value is twice as big as nsteps
|
||||
if (previous < 2 * steps)
|
||||
return previous + 1;
|
||||
// calculate the previous power of 2
|
||||
int prev_power2 = previous / 2; // start with half the given value
|
||||
int rshift = 1; // and with the shift of 1;
|
||||
while (int shifted =
|
||||
prev_power2 >> rshift) { // shift the value right; while the result is non-zero,
|
||||
prev_power2 |= shifted; // add the bits set in 'shifted';
|
||||
rshift <<= 1; // double the shift, as twice as many top bits are set;
|
||||
} // repeat.
|
||||
++prev_power2; // all low bits set; now it's just one less than the desired power of 2
|
||||
assert(is_power_of_2(prev_power2));
|
||||
assert((prev_power2 <= previous) && (2 * prev_power2 > previous));
|
||||
// The actual step value is the previous power of 2 divided by steps
|
||||
return previous + (prev_power2 / steps);
|
||||
}
|
||||
typedef int (*step_function_ptr_type)(int, double);
|
||||
|
||||
struct step_function_descriptor {
|
||||
char mnemonic;
|
||||
step_function_ptr_type function;
|
||||
|
||||
public:
|
||||
step_function_descriptor(char a_mnemonic, step_function_ptr_type a_function)
|
||||
: mnemonic(a_mnemonic),
|
||||
function(a_function) {}
|
||||
|
||||
private:
|
||||
void operator=(step_function_descriptor const&);
|
||||
};
|
||||
step_function_descriptor step_function_descriptors[] = {
|
||||
step_function_descriptor('*', step_function_multiply),
|
||||
step_function_descriptor('+', step_function_plus),
|
||||
step_function_descriptor('#', step_function_power2_ladder)
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline std::size_t array_length(const T (&)[N]) {
|
||||
return N;
|
||||
}
|
||||
|
||||
struct thread_range_step {
|
||||
step_function_ptr_type step_function;
|
||||
double step_function_argument;
|
||||
|
||||
thread_range_step(step_function_ptr_type step_function_, double step_function_argument_)
|
||||
: step_function(step_function_),
|
||||
step_function_argument(step_function_argument_) {
|
||||
if (!step_function_)
|
||||
throw std::invalid_argument(
|
||||
"step_function for thread range step should not be nullptr");
|
||||
}
|
||||
int operator()(int previous) const {
|
||||
assert(0 <= previous); // test 0<=first and loop discipline
|
||||
const int ret = step_function(previous, step_function_argument);
|
||||
assert(previous < ret);
|
||||
return ret;
|
||||
}
|
||||
friend std::istream& operator>>(std::istream& input_stream, thread_range_step& step) {
|
||||
char function_char;
|
||||
double function_argument;
|
||||
input_stream >> function_char >> function_argument;
|
||||
std::size_t i = 0;
|
||||
while ((i < array_length(step_function_descriptors)) &&
|
||||
(step_function_descriptors[i].mnemonic != function_char))
|
||||
++i;
|
||||
if (i >= array_length(step_function_descriptors)) {
|
||||
throw std::invalid_argument("unknown step function mnemonic: " +
|
||||
std::string(1, function_char));
|
||||
}
|
||||
else if ((function_char == '#') && !is_power_of_2(function_argument)) {
|
||||
throw std::invalid_argument("the argument of # should be a power of 2");
|
||||
}
|
||||
step.step_function = step_function_descriptors[i].function;
|
||||
step.step_function_argument = function_argument;
|
||||
return input_stream;
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
struct thread_number_range {
|
||||
int (*auto_number_of_threads)();
|
||||
int first; // 0<=first (0 can be used as a special value)
|
||||
int last; // first<=last
|
||||
|
||||
::utility::internal::thread_range_step step;
|
||||
|
||||
thread_number_range(
|
||||
int (*auto_number_of_threads_)(),
|
||||
int low_ = 1,
|
||||
int high_ = -1,
|
||||
::utility::internal::thread_range_step step_ =
|
||||
::utility::internal::thread_range_step(::utility::internal::step_function_power2_ladder,
|
||||
4))
|
||||
: auto_number_of_threads(auto_number_of_threads_),
|
||||
first(low_),
|
||||
last((high_ > -1) ? high_ : auto_number_of_threads_()),
|
||||
step(step_) {
|
||||
if (first < 0) {
|
||||
throw std::invalid_argument("negative value not allowed");
|
||||
}
|
||||
if (first > last) {
|
||||
throw std::invalid_argument("decreasing sequence not allowed");
|
||||
}
|
||||
}
|
||||
friend std::istream& operator>>(std::istream& i, thread_number_range& range) {
|
||||
try {
|
||||
std::string s;
|
||||
i >> s;
|
||||
struct string_to_number_of_threads {
|
||||
int auto_value;
|
||||
string_to_number_of_threads(int auto_value_) : auto_value(auto_value_) {}
|
||||
int operator()(const std::string& value) const {
|
||||
return (value == "auto") ? auto_value : internal::string_to<int>(value);
|
||||
}
|
||||
};
|
||||
string_to_number_of_threads string_to_number_of_threads(range.auto_number_of_threads());
|
||||
int low, high;
|
||||
std::size_t colon = s.find(':');
|
||||
if (colon == std::string::npos) {
|
||||
low = high = string_to_number_of_threads(s);
|
||||
}
|
||||
else {
|
||||
//it is a range
|
||||
std::size_t second_colon = s.find(':', colon + 1);
|
||||
|
||||
low = string_to_number_of_threads(std::string(s, 0, colon)); //not copying the colon
|
||||
high = string_to_number_of_threads(
|
||||
std::string(s, colon + 1, second_colon - (colon + 1))); //not copying the colons
|
||||
if (second_colon != std::string::npos) {
|
||||
internal::string_to(std::string(s, second_colon + 1), range.step);
|
||||
}
|
||||
}
|
||||
range = thread_number_range(range.auto_number_of_threads, low, high, range.step);
|
||||
}
|
||||
catch (std::invalid_argument&) {
|
||||
i.setstate(std::ios::failbit);
|
||||
throw;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
friend std::ostream& operator<<(std::ostream& o, thread_number_range const& range) {
|
||||
using namespace internal;
|
||||
std::size_t i = 0;
|
||||
for (; i < array_length(step_function_descriptors) &&
|
||||
step_function_descriptors[i].function != range.step.step_function;
|
||||
++i) {
|
||||
}
|
||||
if (i >= array_length(step_function_descriptors)) {
|
||||
throw std::invalid_argument("unknown step function for thread range");
|
||||
}
|
||||
o << range.first << ":" << range.last << ":" << step_function_descriptors[i].mnemonic
|
||||
<< range.step.step_function_argument;
|
||||
return o;
|
||||
}
|
||||
}; // struct thread_number_range
|
||||
//TODO: fix unused warning here
|
||||
static const char* thread_number_range_desc =
|
||||
"number of threads to use; a range of the form low[:high[:(+|*|#)step]],"
|
||||
"\n\twhere low and optional high are non-negative integers or 'auto' for the default choice,"
|
||||
"\n\tand optional step expression specifies how thread numbers are chosen within the range.";
|
||||
|
||||
inline void report_elapsed_time(double seconds) {
|
||||
std::cout << "elapsed time : " << seconds << " seconds"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
inline void report_skipped() {
|
||||
std::cout << "skip"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
inline void parse_cli_arguments(int argc, const char* argv[], utility::cli_argument_pack cli_pack) {
|
||||
bool show_help = false;
|
||||
cli_pack.arg(show_help, "-h", "show this message");
|
||||
|
||||
bool invalid_input = false;
|
||||
try {
|
||||
cli_pack.parse(argc, argv);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::cerr << "error occurred while parsing command line."
|
||||
<< "\n"
|
||||
<< "error text: " << e.what() << "\n"
|
||||
<< std::flush;
|
||||
invalid_input = true;
|
||||
}
|
||||
if (show_help || invalid_input) {
|
||||
std::cout << cli_pack.usage_string(argv[0]) << std::flush;
|
||||
std::exit(0);
|
||||
}
|
||||
}
|
||||
inline void parse_cli_arguments(int argc, char* argv[], utility::cli_argument_pack cli_pack) {
|
||||
parse_cli_arguments(argc, const_cast<const char**>(argv), cli_pack);
|
||||
}
|
||||
} // namespace utility
|
||||
|
||||
#endif /* TBB_examples_utility_H */
|
||||
@@ -0,0 +1,6 @@
|
||||
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
|
||||
This directory contains examples of the `concurrent_hash_map` container.
|
||||
|
||||
| Code sample name | Description
|
||||
|:--- |:---
|
||||
| count_strings | Concurrently inserts strings into a `concurrent_hash_map` container.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(count_strings CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
add_executable(count_strings count_strings.cpp)
|
||||
|
||||
target_link_libraries(count_strings TBB::tbb Threads::Threads)
|
||||
target_compile_options(count_strings PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:count_strings>")
|
||||
set(ARGS "")
|
||||
set(PERF_ARGS auto 10000000 silent)
|
||||
|
||||
add_execution_target(run_count_strings count_strings ${EXECUTABLE} "${ARGS}")
|
||||
add_execution_target(perf_run_count_strings count_strings ${EXECUTABLE} "${PERF_ARGS}")
|
||||
@@ -0,0 +1,24 @@
|
||||
# Count_strings sample
|
||||
The example counts the number of unique words in a text.
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_count_strings` - executes the example with predefined parameters.
|
||||
* `make perf_run_count_strings` - executes the example with suggested parameters to measure the oneTBB performance.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
count_strings [n-of-threads=value] [n-of-strings=value] [verbose] [silent] [count_collisions] [-h] [n-of-threads [n-of-strings]]
|
||||
```
|
||||
* `-h` - prints the help for command line options.
|
||||
* `n-of-threads` - number of threads to use; a range of the form low\[:high\], where low and optional high are non-negative integers or `auto` for a platform-specific default number.
|
||||
* `n-of-strings` - number of strings.
|
||||
* `verbose` - prints diagnostic output to screen.
|
||||
* `silent` - no output except elapsed time.
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include <string>
|
||||
|
||||
// Apple clang and MSVC defines their own specializations for std::hash<std::basic_string<T, Traits, Alloc>>
|
||||
#if !(_LIBCPP_VERSION) && !(_CPPLIB_VER)
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename CharT, typename Traits, typename Allocator>
|
||||
class hash<std::basic_string<CharT, Traits, Allocator>> {
|
||||
public:
|
||||
std::size_t operator()(const std::basic_string<CharT, Traits, Allocator>& s) const {
|
||||
std::size_t h = 0;
|
||||
for (const CharT* c = s.c_str(); *c; ++c) {
|
||||
h = h * hash_multiplier ^ char_hash(*c);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr std::size_t hash_multiplier = (std::size_t)(
|
||||
(sizeof(std::size_t) == sizeof(unsigned)) ? 2654435769U : 11400714819323198485ULL);
|
||||
|
||||
std::hash<CharT> char_hash;
|
||||
}; // strunt hash<std::basic_string>
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // !(_LIBCPP_VERSION || _CPPLIB_VER)
|
||||
|
||||
#include "oneapi/tbb/concurrent_hash_map.h"
|
||||
#include "oneapi/tbb/blocked_range.h"
|
||||
#include "oneapi/tbb/parallel_for.h"
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
#include "oneapi/tbb/tbb_allocator.h"
|
||||
#include "oneapi/tbb/global_control.h"
|
||||
|
||||
#include "common/utility/utility.hpp"
|
||||
#include "common/utility/get_default_num_threads.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
//! Count collisions
|
||||
std::map<std::size_t, int> hashes;
|
||||
int c = 0;
|
||||
|
||||
//! String type
|
||||
typedef std::basic_string<char, std::char_traits<char>, oneapi::tbb::tbb_allocator<char>> MyString;
|
||||
|
||||
//! Set to true to counts.
|
||||
static bool verbose = false;
|
||||
static bool silent = false;
|
||||
static bool count_collisions = false;
|
||||
//! Problem size
|
||||
long N = 1000000;
|
||||
const int size_factor = 2;
|
||||
|
||||
//! A concurrent hash table that maps strings to ints.
|
||||
typedef oneapi::tbb::concurrent_hash_map<MyString, int> StringTable;
|
||||
|
||||
//! Function object for counting occurrences of strings.
|
||||
struct Tally {
|
||||
StringTable& table;
|
||||
Tally(StringTable& table_) : table(table_) {}
|
||||
void operator()(const oneapi::tbb::blocked_range<MyString*> range) const {
|
||||
for (MyString* p = range.begin(); p != range.end(); ++p) {
|
||||
StringTable::accessor a;
|
||||
table.insert(a, *p);
|
||||
a->second += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static MyString* Data;
|
||||
|
||||
static void CountOccurrences(int nthreads) {
|
||||
StringTable table;
|
||||
|
||||
oneapi::tbb::tick_count t0 = oneapi::tbb::tick_count::now();
|
||||
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<MyString*>(Data, Data + N, 1000),
|
||||
Tally(table));
|
||||
oneapi::tbb::tick_count t1 = oneapi::tbb::tick_count::now();
|
||||
|
||||
int n = 0;
|
||||
for (StringTable::iterator i = table.begin(); i != table.end(); ++i) {
|
||||
if (verbose && nthreads)
|
||||
printf("%s %d\n", i->first.c_str(), i->second);
|
||||
if (!silent && count_collisions) {
|
||||
// it doesn't count real collisions in hash_map, a mask should be applied on hash value
|
||||
hashes[std::hash<MyString>()(i->first) & 0xFFFF]++;
|
||||
}
|
||||
n += i->second;
|
||||
}
|
||||
if (!silent && count_collisions) {
|
||||
for (auto i = hashes.begin(); i != hashes.end(); ++i)
|
||||
c += i->second - 1;
|
||||
printf("hashes = %d collisions = %d ", static_cast<int>(hashes.size()), c);
|
||||
c = 0;
|
||||
hashes.clear();
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
printf(
|
||||
"total = %d unique = %u time = %g\n", n, unsigned(table.size()), (t1 - t0).seconds());
|
||||
}
|
||||
|
||||
/// Generator of random words
|
||||
|
||||
struct Sound {
|
||||
const char* chars;
|
||||
int rates[3]; // beginning, middle, ending
|
||||
};
|
||||
Sound Vowels[] = {
|
||||
{ "e", { 445, 6220, 1762 } }, { "a", { 704, 5262, 514 } }, { "i", { 402, 5224, 162 } },
|
||||
{ "o", { 248, 3726, 191 } }, { "u", { 155, 1669, 23 } }, { "y", { 4, 400, 989 } },
|
||||
{ "io", { 5, 512, 18 } }, { "ia", { 1, 329, 111 } }, { "ea", { 21, 370, 16 } },
|
||||
{ "ou", { 32, 298, 4 } }, { "ie", { 0, 177, 140 } }, { "ee", { 2, 183, 57 } },
|
||||
{ "ai", { 17, 206, 7 } }, { "oo", { 1, 215, 7 } }, { "au", { 40, 111, 2 } },
|
||||
{ "ua", { 0, 102, 4 } }, { "ui", { 0, 104, 1 } }, { "ei", { 6, 94, 3 } },
|
||||
{ "ue", { 0, 67, 28 } }, { "ay", { 1, 42, 52 } }, { "ey", { 1, 14, 80 } },
|
||||
{ "oa", { 5, 84, 3 } }, { "oi", { 2, 81, 1 } }, { "eo", { 1, 71, 5 } },
|
||||
{ "iou", { 0, 61, 0 } }, { "oe", { 2, 46, 9 } }, { "eu", { 12, 43, 0 } },
|
||||
{ "iu", { 0, 45, 0 } }, { "ya", { 12, 19, 5 } }, { "ae", { 7, 18, 10 } },
|
||||
{ "oy", { 0, 10, 13 } }, { "ye", { 8, 7, 7 } }, { "ion", { 0, 0, 20 } },
|
||||
{ "ing", { 0, 0, 20 } }, { "ium", { 0, 0, 10 } }, { "er", { 0, 0, 20 } }
|
||||
};
|
||||
Sound Consonants[] = {
|
||||
{ "r", { 483, 1414, 1110 } }, { "n", { 312, 1548, 1114 } }, { "t", { 363, 1653, 251 } },
|
||||
{ "l", { 424, 1341, 489 } }, { "c", { 734, 735, 260 } }, { "m", { 732, 785, 161 } },
|
||||
{ "d", { 558, 612, 389 } }, { "s", { 574, 570, 405 } }, { "p", { 519, 361, 98 } },
|
||||
{ "b", { 528, 356, 30 } }, { "v", { 197, 598, 16 } }, { "ss", { 3, 191, 567 } },
|
||||
{ "g", { 285, 430, 42 } }, { "st", { 142, 323, 180 } }, { "h", { 470, 89, 30 } },
|
||||
{ "nt", { 0, 350, 231 } }, { "ng", { 0, 117, 442 } }, { "f", { 319, 194, 19 } },
|
||||
{ "ll", { 1, 414, 83 } }, { "w", { 249, 131, 64 } }, { "k", { 154, 179, 47 } },
|
||||
{ "nd", { 0, 279, 92 } }, { "bl", { 62, 235, 0 } }, { "z", { 35, 223, 16 } },
|
||||
{ "sh", { 112, 69, 79 } }, { "ch", { 139, 95, 25 } }, { "th", { 70, 143, 39 } },
|
||||
{ "tt", { 0, 219, 19 } }, { "tr", { 131, 104, 0 } }, { "pr", { 186, 41, 0 } },
|
||||
{ "nc", { 0, 223, 2 } }, { "j", { 184, 32, 1 } }, { "nn", { 0, 188, 20 } },
|
||||
{ "rt", { 0, 148, 51 } }, { "ct", { 0, 160, 29 } }, { "rr", { 0, 182, 3 } },
|
||||
{ "gr", { 98, 87, 0 } }, { "ck", { 0, 92, 86 } }, { "rd", { 0, 81, 88 } },
|
||||
{ "x", { 8, 102, 48 } }, { "ph", { 47, 101, 10 } }, { "br", { 115, 43, 0 } },
|
||||
{ "cr", { 92, 60, 0 } }, { "rm", { 0, 131, 18 } }, { "ns", { 0, 124, 18 } },
|
||||
{ "sp", { 81, 55, 4 } }, { "sm", { 25, 29, 85 } }, { "sc", { 53, 83, 1 } },
|
||||
{ "rn", { 0, 100, 30 } }, { "cl", { 78, 42, 0 } }, { "mm", { 0, 116, 0 } },
|
||||
{ "pp", { 0, 114, 2 } }, { "mp", { 0, 99, 14 } }, { "rs", { 0, 96, 16 } },
|
||||
{ "rl", { 0, 97, 7 } }, { "rg", { 0, 81, 15 } }, { "pl", { 56, 39, 0 } },
|
||||
{ "sn", { 32, 62, 1 } }, { "str", { 38, 56, 0 } }, { "dr", { 47, 44, 0 } },
|
||||
{ "fl", { 77, 13, 1 } }, { "fr", { 77, 11, 0 } }, { "ld", { 0, 47, 38 } },
|
||||
{ "ff", { 0, 62, 20 } }, { "lt", { 0, 61, 19 } }, { "rb", { 0, 75, 4 } },
|
||||
{ "mb", { 0, 72, 7 } }, { "rc", { 0, 76, 1 } }, { "gg", { 0, 74, 1 } },
|
||||
{ "pt", { 1, 56, 10 } }, { "bb", { 0, 64, 1 } }, { "sl", { 48, 17, 0 } },
|
||||
{ "dd", { 0, 59, 2 } }, { "gn", { 3, 50, 4 } }, { "rk", { 0, 30, 28 } },
|
||||
{ "nk", { 0, 35, 20 } }, { "gl", { 40, 14, 0 } }, { "wh", { 45, 6, 0 } },
|
||||
{ "ntr", { 0, 50, 0 } }, { "rv", { 0, 47, 1 } }, { "ght", { 0, 19, 29 } },
|
||||
{ "sk", { 23, 17, 5 } }, { "nf", { 0, 46, 0 } }, { "cc", { 0, 45, 0 } },
|
||||
{ "ln", { 0, 41, 0 } }, { "sw", { 36, 4, 0 } }, { "rp", { 0, 36, 4 } },
|
||||
{ "dn", { 0, 38, 0 } }, { "ps", { 14, 19, 5 } }, { "nv", { 0, 38, 0 } },
|
||||
{ "tch", { 0, 21, 16 } }, { "nch", { 0, 26, 11 } }, { "lv", { 0, 35, 0 } },
|
||||
{ "wn", { 0, 14, 21 } }, { "rf", { 0, 32, 3 } }, { "lm", { 0, 30, 5 } },
|
||||
{ "dg", { 0, 34, 0 } }, { "ft", { 0, 18, 15 } }, { "scr", { 23, 10, 0 } },
|
||||
{ "rch", { 0, 24, 6 } }, { "rth", { 0, 23, 7 } }, { "rh", { 13, 15, 0 } },
|
||||
{ "mpl", { 0, 29, 0 } }, { "cs", { 0, 1, 27 } }, { "gh", { 4, 10, 13 } },
|
||||
{ "ls", { 0, 23, 3 } }, { "ndr", { 0, 25, 0 } }, { "tl", { 0, 23, 1 } },
|
||||
{ "ngl", { 0, 25, 0 } }, { "lk", { 0, 15, 9 } }, { "rw", { 0, 23, 0 } },
|
||||
{ "lb", { 0, 23, 1 } }, { "tw", { 15, 8, 0 } }, { "chr", { 18, 4, 0 } },
|
||||
{ "dl", { 0, 23, 0 } }, { "ctr", { 0, 22, 0 } }, { "nst", { 0, 21, 0 } },
|
||||
{ "lc", { 0, 22, 0 } }, { "sch", { 16, 4, 0 } }, { "ths", { 0, 1, 20 } },
|
||||
{ "nl", { 0, 21, 0 } }, { "lf", { 0, 15, 6 } }, { "ssn", { 0, 20, 0 } },
|
||||
{ "xt", { 0, 18, 1 } }, { "xp", { 0, 20, 0 } }, { "rst", { 0, 15, 5 } },
|
||||
{ "nh", { 0, 19, 0 } }, { "wr", { 14, 5, 0 } }
|
||||
};
|
||||
const int VowelsNumber = sizeof(Vowels) / sizeof(Sound);
|
||||
const int ConsonantsNumber = sizeof(Consonants) / sizeof(Sound);
|
||||
int VowelsRatesSum[3] = { 0, 0, 0 }, ConsonantsRatesSum[3] = { 0, 0, 0 };
|
||||
|
||||
int CountRateSum(Sound sounds[], const int num, const int part) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < num; i++)
|
||||
sum += sounds[i].rates[part];
|
||||
return sum;
|
||||
}
|
||||
|
||||
const char* GetLetters(int type, const int part) {
|
||||
Sound* sounds;
|
||||
int rate, i = 0;
|
||||
if (type & 1)
|
||||
sounds = Vowels, rate = rand() % VowelsRatesSum[part];
|
||||
else
|
||||
sounds = Consonants, rate = rand() % ConsonantsRatesSum[part];
|
||||
do {
|
||||
rate -= sounds[i++].rates[part];
|
||||
} while (rate > 0);
|
||||
return sounds[--i].chars;
|
||||
}
|
||||
|
||||
static void CreateData() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i);
|
||||
VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i);
|
||||
}
|
||||
for (int i = 0; i < N; ++i) {
|
||||
int type = rand();
|
||||
Data[i] = GetLetters(type++, 0);
|
||||
for (int j = 0; j < type % size_factor; ++j)
|
||||
Data[i] += GetLetters(type++, 1);
|
||||
Data[i] += GetLetters(type, 2);
|
||||
}
|
||||
MyString planet = Data[12];
|
||||
planet[0] = toupper(planet[0]);
|
||||
MyString helloworld = Data[0];
|
||||
helloworld[0] = toupper(helloworld[0]);
|
||||
helloworld += ", " + Data[1] + " " + Data[2] + " " + Data[3] + " " + Data[4] + " " + Data[5];
|
||||
if (!silent)
|
||||
printf("Message from planet '%s': %s!\nAnalyzing whole text...\n",
|
||||
planet.c_str(),
|
||||
helloworld.c_str());
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
StringTable table;
|
||||
oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now();
|
||||
srand(2);
|
||||
|
||||
//! Working threads count
|
||||
// The 1st argument is the function to obtain 'auto' value; the 2nd is the default value
|
||||
// The example interprets 0 threads as "run serially, then fully subscribed"
|
||||
utility::thread_number_range threads(utility::get_default_num_threads, 0);
|
||||
|
||||
utility::parse_cli_arguments(
|
||||
argc,
|
||||
argv,
|
||||
utility::cli_argument_pack()
|
||||
//"-h" option for displaying help is present implicitly
|
||||
.positional_arg(threads, "n-of-threads", utility::thread_number_range_desc)
|
||||
.positional_arg(N, "n-of-strings", "number of strings")
|
||||
.arg(verbose, "verbose", "verbose mode")
|
||||
.arg(silent, "silent", "no output except elapsed time")
|
||||
.arg(count_collisions, "count_collisions", "print the count of collisions"));
|
||||
|
||||
if (silent)
|
||||
verbose = false;
|
||||
|
||||
Data = new MyString[N];
|
||||
CreateData();
|
||||
|
||||
if (threads.first) {
|
||||
for (int p = threads.first; p <= threads.last; p = threads.step(p)) {
|
||||
if (!silent)
|
||||
printf("threads = %d ", p);
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p);
|
||||
CountOccurrences(p);
|
||||
}
|
||||
}
|
||||
else { // Number of threads wasn't set explicitly. Run serial and parallel version
|
||||
{ // serial run
|
||||
if (!silent)
|
||||
printf("serial run ");
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, 1);
|
||||
CountOccurrences(1);
|
||||
}
|
||||
{ // parallel run (number of threads is selected automatically)
|
||||
if (!silent)
|
||||
printf("parallel run ");
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
|
||||
utility::get_default_num_threads());
|
||||
CountOccurrences(0);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] Data;
|
||||
|
||||
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - mainStartTime).seconds());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
|
||||
This directory contains examples of the `concurrent_priority_queue` container.
|
||||
|
||||
| Code sample name | Description
|
||||
|:--- |:---
|
||||
| shortpath | Solves the single source shortest path problem using a `concurrent_priority_queue` container.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(shortpath CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
add_executable(shortpath shortpath.cpp)
|
||||
|
||||
target_link_libraries(shortpath TBB::tbb Threads::Threads)
|
||||
target_compile_options(shortpath PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:shortpath>")
|
||||
set(ARGS 4 N=1000 start=0 end=999 verbose)
|
||||
set(PERF_ARGS auto N=1000 start=0 end=99 silent)
|
||||
|
||||
add_execution_target(run_shortpath shortpath ${EXECUTABLE} "${ARGS}")
|
||||
add_execution_target(perf_run_shortpath shortpath ${EXECUTABLE} "${PERF_ARGS}")
|
||||
@@ -0,0 +1,36 @@
|
||||
# Shortpath sample
|
||||
This directory contains an example that solves the single source shortest path problem.
|
||||
|
||||
It is parameterized by `N`, a number of nodes, and a start and end node in `[0..N)`. A graph is generated with `N` nodes and some random number of connections between those nodes. A parallel algorithm based on `A*` is used to find the shortest path.
|
||||
|
||||
This algorithm varies from serial `A*` in that it needs to add nodes back to the open set when the `g` estimate (shortest path from start to the node) is improved, even if the node has already been "visited". This is because nodes are added and removed from the open-set in parallel, resulting in some less optimal paths being explored. The open-set is implemented with the `concurrent_priority_queue`.
|
||||
|
||||
Note that since we re-visit nodes, the `f` estimate (on which the priority queue is sorted) is not technically needed, so we could use this same parallel algorithm with just a `concurrent_queue`. However, keeping the `f` estimate and using `concurrent_priority_queue` results in much better performance.
|
||||
|
||||
Silent mode prints run time only, regular mode prints the shortest path length, and verbose mode prints out the shortest path.
|
||||
|
||||
The generated graph follows a pattern in which the closer two pairs of node ids are together, the fewer hops there are in a typical path between those nodes. So, for example, the path between 5 and 7 likely has few hops whereas 14 to 78 has more and 0 to 9999 has even more, etc.
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_shortpath` - executes the example with predefined parameters.
|
||||
* `make perf_run_shortpath` - executes the example with suggested parameters to measure the oneTBB performance.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
shortpath [#threads=value] [verbose] [silent] [N=value] [start=value] [end=value] [-h] [#threads]
|
||||
```
|
||||
* `-h` - prints the help for command line options.
|
||||
* `n-of-threads` - number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or `auto` for a platform-specific default number.
|
||||
* `verbose` - prints diagnostic output to screen.
|
||||
* `silent` - no output except elapsed time.
|
||||
* `N` - number of nodes in graph.
|
||||
* `start` - node to start path at.
|
||||
* `end` - node to end path at.
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
#include "oneapi/tbb/task_group.h"
|
||||
#include "oneapi/tbb/concurrent_priority_queue.h"
|
||||
#include "oneapi/tbb/spin_mutex.h"
|
||||
#include "oneapi/tbb/parallel_for.h"
|
||||
#include "oneapi/tbb/blocked_range.h"
|
||||
#include "oneapi/tbb/global_control.h"
|
||||
|
||||
#include "common/utility/utility.hpp"
|
||||
#include "common/utility/fast_random.hpp"
|
||||
#include "common/utility/get_default_num_threads.hpp"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_Wp64)
|
||||
// Workaround for overzealous compiler warnings in /Wp64 mode
|
||||
#pragma warning(disable : 4267)
|
||||
#endif /* _MSC_VER && _Wp64 */
|
||||
|
||||
struct point {
|
||||
double x, y;
|
||||
point() {}
|
||||
point(double _x, double _y) : x(_x), y(_y) {}
|
||||
point(const point& p) : x(p.x), y(p.y) {}
|
||||
};
|
||||
|
||||
double get_distance(const point& p1, const point& p2) {
|
||||
double xdiff = p1.x - p2.x, ydiff = p1.y - p2.y;
|
||||
return sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
}
|
||||
|
||||
// generates random points on 2D plane within a box of maxsize width & height
|
||||
point generate_random_point(utility::FastRandom& mr) {
|
||||
const std::size_t maxsize = 500;
|
||||
double x = (double)(mr.get() % maxsize);
|
||||
double y = (double)(mr.get() % maxsize);
|
||||
return point(x, y);
|
||||
}
|
||||
|
||||
// weighted toss makes closer nodes (in the point vector) heavily connected
|
||||
bool die_toss(std::size_t a, std::size_t b, utility::FastRandom& mr) {
|
||||
int node_diff = std::abs(int(a - b));
|
||||
// near nodes
|
||||
if (node_diff < 16)
|
||||
return true;
|
||||
// mid nodes
|
||||
if (node_diff < 64)
|
||||
return ((int)mr.get() % 8 == 0);
|
||||
// far nodes
|
||||
if (node_diff < 512)
|
||||
return ((int)mr.get() % 16 == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef std::vector<point> point_set;
|
||||
typedef std::size_t vertex_id;
|
||||
typedef std::pair<vertex_id, double> vertex_rec;
|
||||
typedef std::vector<std::vector<vertex_id>> edge_set;
|
||||
|
||||
bool verbose = false; // prints bin details and other diagnostics to screen
|
||||
bool silent = false; // suppress all output except for time
|
||||
std::size_t N = 1000; // number of vertices
|
||||
std::size_t src = 0; // start of path
|
||||
std::size_t dst = N - 1; // end of path
|
||||
double INF = 100000.0; // infinity
|
||||
std::size_t grainsize = 16; // number of vertices per task on average
|
||||
std::size_t max_spawn; // max tasks to spawn
|
||||
std::atomic<std::size_t> num_spawn; // number of active tasks
|
||||
|
||||
point_set vertices; // vertices
|
||||
edge_set edges; // edges
|
||||
std::vector<vertex_id> predecessor; // for recreating path from src to dst
|
||||
|
||||
std::vector<double> f_distance; // estimated distances at particular vertex
|
||||
std::vector<double> g_distance; // current shortest distances from src vertex
|
||||
oneapi::tbb::spin_mutex* locks; // a lock for each vertex
|
||||
oneapi::tbb::task_group* sp_group; // task group for tasks executing sub-problems
|
||||
|
||||
struct compare_f {
|
||||
bool operator()(const vertex_rec& u, const vertex_rec& v) const {
|
||||
return u.second > v.second;
|
||||
}
|
||||
};
|
||||
|
||||
oneapi::tbb::concurrent_priority_queue<vertex_rec, compare_f> open_set; // tentative vertices
|
||||
|
||||
void shortpath_helper();
|
||||
|
||||
void shortpath() {
|
||||
sp_group = new oneapi::tbb::task_group;
|
||||
g_distance[src] = 0.0; // src's distance from src is zero
|
||||
f_distance[src] =
|
||||
get_distance(vertices[src], vertices[dst]); // estimate distance from src to dst
|
||||
open_set.emplace(src, f_distance[src]); // emplace src into open_set
|
||||
sp_group->run([]() {
|
||||
shortpath_helper();
|
||||
});
|
||||
sp_group->wait();
|
||||
delete sp_group;
|
||||
}
|
||||
|
||||
void shortpath_helper() {
|
||||
vertex_rec u_rec;
|
||||
while (open_set.try_pop(u_rec)) {
|
||||
vertex_id u = u_rec.first;
|
||||
if (u == dst)
|
||||
continue;
|
||||
double f = u_rec.second;
|
||||
double old_g_u = 0.0;
|
||||
{
|
||||
oneapi::tbb::spin_mutex::scoped_lock l(locks[u]);
|
||||
if (f > f_distance[u])
|
||||
continue; // prune search space
|
||||
old_g_u = g_distance[u];
|
||||
}
|
||||
for (std::size_t i = 0; i < edges[u].size(); ++i) {
|
||||
vertex_id v = edges[u][i];
|
||||
double new_g_v = old_g_u + get_distance(vertices[u], vertices[v]);
|
||||
double new_f_v = 0.0;
|
||||
// the push flag lets us move some work out of the critical section below
|
||||
bool push = false;
|
||||
{
|
||||
oneapi::tbb::spin_mutex::scoped_lock l(locks[v]);
|
||||
if (new_g_v < g_distance[v]) {
|
||||
predecessor[v] = u;
|
||||
g_distance[v] = new_g_v;
|
||||
new_f_v = f_distance[v] =
|
||||
g_distance[v] + get_distance(vertices[v], vertices[dst]);
|
||||
push = true;
|
||||
}
|
||||
}
|
||||
if (push) {
|
||||
open_set.push(std::make_pair(v, new_f_v));
|
||||
std::size_t n_spawn = ++num_spawn;
|
||||
if (n_spawn < max_spawn) {
|
||||
sp_group->run([] {
|
||||
shortpath_helper();
|
||||
});
|
||||
}
|
||||
else
|
||||
--num_spawn;
|
||||
}
|
||||
}
|
||||
}
|
||||
--num_spawn;
|
||||
}
|
||||
|
||||
void make_path(vertex_id src, vertex_id dst, std::vector<vertex_id>& path) {
|
||||
vertex_id at = predecessor[dst];
|
||||
if (at == N)
|
||||
path.push_back(src);
|
||||
else if (at == src) {
|
||||
path.push_back(src);
|
||||
path.push_back(dst);
|
||||
}
|
||||
else {
|
||||
make_path(src, at, path);
|
||||
path.push_back(dst);
|
||||
}
|
||||
}
|
||||
|
||||
void print_path() {
|
||||
std::vector<vertex_id> path;
|
||||
double path_length = 0.0;
|
||||
make_path(src, dst, path);
|
||||
if (verbose)
|
||||
printf("\n ");
|
||||
for (std::size_t i = 0; i < path.size(); ++i) {
|
||||
if (path[i] != dst) {
|
||||
double seg_length = get_distance(vertices[path[i]], vertices[path[i + 1]]);
|
||||
if (verbose)
|
||||
printf("%6.1f ", seg_length);
|
||||
path_length += seg_length;
|
||||
}
|
||||
else if (verbose)
|
||||
printf("\n");
|
||||
}
|
||||
if (verbose) {
|
||||
for (std::size_t i = 0; i < path.size(); ++i) {
|
||||
if (path[i] != dst)
|
||||
printf("(%4d)------>", (int)path[i]);
|
||||
else
|
||||
printf("(%4d)\n", (int)path[i]);
|
||||
}
|
||||
}
|
||||
if (verbose)
|
||||
printf("Total distance = %5.1f\n", path_length);
|
||||
else if (!silent)
|
||||
printf(" %5.1f\n", path_length);
|
||||
}
|
||||
|
||||
void InitializeGraph() {
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
|
||||
utility::get_default_num_threads());
|
||||
vertices.resize(N);
|
||||
edges.resize(N);
|
||||
predecessor.resize(N);
|
||||
g_distance.resize(N);
|
||||
f_distance.resize(N);
|
||||
locks = new oneapi::tbb::spin_mutex[N];
|
||||
|
||||
if (verbose)
|
||||
printf("Generating vertices...\n");
|
||||
oneapi::tbb::parallel_for(
|
||||
oneapi::tbb::blocked_range<std::size_t>(0, N, 64),
|
||||
[&](oneapi::tbb::blocked_range<std::size_t>& r) {
|
||||
utility::FastRandom my_random(r.begin());
|
||||
for (std::size_t i = r.begin(); i != r.end(); ++i) {
|
||||
vertices[i] = generate_random_point(my_random);
|
||||
}
|
||||
},
|
||||
oneapi::tbb::simple_partitioner());
|
||||
|
||||
if (verbose)
|
||||
printf("Generating edges...\n");
|
||||
oneapi::tbb::parallel_for(
|
||||
oneapi::tbb::blocked_range<std::size_t>(0, N, 64),
|
||||
[&](oneapi::tbb::blocked_range<std::size_t>& r) {
|
||||
utility::FastRandom my_random(r.begin());
|
||||
for (std::size_t i = r.begin(); i != r.end(); ++i) {
|
||||
for (std::size_t j = 0; j < i; ++j) {
|
||||
if (die_toss(i, j, my_random))
|
||||
edges[i].push_back(j);
|
||||
}
|
||||
}
|
||||
},
|
||||
oneapi::tbb::simple_partitioner());
|
||||
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
for (std::size_t j = 0; j < edges[i].size(); ++j) {
|
||||
vertex_id k = edges[i][j];
|
||||
edges[k].push_back(i);
|
||||
}
|
||||
}
|
||||
if (verbose)
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
void ReleaseGraph() {
|
||||
delete[] locks;
|
||||
}
|
||||
|
||||
void ResetGraph() {
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
|
||||
utility::get_default_num_threads());
|
||||
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, N),
|
||||
[&](oneapi::tbb::blocked_range<std::size_t>& r) {
|
||||
for (std::size_t i = r.begin(); i != r.end(); ++i) {
|
||||
f_distance[i] = g_distance[i] = INF;
|
||||
predecessor[i] = N;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
utility::thread_number_range threads(utility::get_default_num_threads);
|
||||
utility::parse_cli_arguments(
|
||||
argc,
|
||||
argv,
|
||||
utility::cli_argument_pack()
|
||||
//"-h" option for displaying help is present implicitly
|
||||
.positional_arg(threads, "#threads", utility::thread_number_range_desc)
|
||||
.arg(verbose, "verbose", " print diagnostic output to screen")
|
||||
.arg(silent, "silent", " limits output to timing info; overrides verbose")
|
||||
.arg(N, "N", " number of vertices")
|
||||
.arg(src, "start", " start of path")
|
||||
.arg(dst, "end", " end of path"));
|
||||
if (silent)
|
||||
verbose = false; // make silent override verbose
|
||||
else
|
||||
printf("shortpath will run with %d vertices to find shortest path between vertices"
|
||||
" %d and %d using %d:%d threads.\n",
|
||||
(int)N,
|
||||
(int)src,
|
||||
(int)dst,
|
||||
(int)threads.first,
|
||||
(int)threads.last);
|
||||
|
||||
if (dst >= N) {
|
||||
if (verbose)
|
||||
printf("end value %d is invalid for %d vertices; correcting to %d\n",
|
||||
(int)dst,
|
||||
(int)N,
|
||||
(int)N - 1);
|
||||
dst = N - 1;
|
||||
}
|
||||
|
||||
num_spawn = 0;
|
||||
max_spawn = N / grainsize;
|
||||
oneapi::tbb::tick_count t0, t1;
|
||||
InitializeGraph();
|
||||
for (int n_thr = threads.first; n_thr <= threads.last; n_thr = threads.step(n_thr)) {
|
||||
ResetGraph();
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, n_thr);
|
||||
t0 = oneapi::tbb::tick_count::now();
|
||||
shortpath();
|
||||
t1 = oneapi::tbb::tick_count::now();
|
||||
if (!silent) {
|
||||
if (predecessor[dst] != N) {
|
||||
printf("%d threads: [%6.6f] The shortest path from vertex %d to vertex %d is:",
|
||||
(int)n_thr,
|
||||
(t1 - t0).seconds(),
|
||||
(int)src,
|
||||
(int)dst);
|
||||
print_path();
|
||||
}
|
||||
else {
|
||||
printf("%d threads: [%6.6f] There is no path from vertex %d to vertex %d\n",
|
||||
(int)n_thr,
|
||||
(t1 - t0).seconds(),
|
||||
(int)src,
|
||||
(int)dst);
|
||||
}
|
||||
}
|
||||
else
|
||||
utility::report_elapsed_time((t1 - t0).seconds());
|
||||
}
|
||||
ReleaseGraph();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
|
||||
This directory contains the examples referenced by the [oneAPI Threading Building Blocks Get Started Guide](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html)
|
||||
|
||||
| Code sample name | Description
|
||||
|:--- |:---
|
||||
| sub_string_finder | Finds largest matching substrings.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(sub_string_finder_simple CXX)
|
||||
project(sub_string_finder_extended CXX)
|
||||
project(sub_string_finder_pretty CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
add_executable(sub_string_finder_simple sub_string_finder.cpp)
|
||||
add_executable(sub_string_finder_extended sub_string_finder_extended.cpp)
|
||||
add_executable(sub_string_finder_pretty sub_string_finder_pretty.cpp)
|
||||
|
||||
target_link_libraries(sub_string_finder_simple TBB::tbb Threads::Threads)
|
||||
target_link_libraries(sub_string_finder_extended TBB::tbb Threads::Threads)
|
||||
target_link_libraries(sub_string_finder_pretty TBB::tbb Threads::Threads)
|
||||
|
||||
target_compile_options(sub_string_finder_simple PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
target_compile_options(sub_string_finder_extended PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
target_compile_options(sub_string_finder_pretty PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
add_custom_target(sub_string_finder)
|
||||
add_dependencies(sub_string_finder sub_string_finder_simple sub_string_finder_extended sub_string_finder_pretty)
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:sub_string_finder_extended>")
|
||||
set(LIGHT_EXECUTABLE "$<TARGET_FILE:sub_string_finder_simple>")
|
||||
set(ARGS "")
|
||||
set(LIGHT_ARGS "silent")
|
||||
|
||||
add_execution_target(run_sub_string_finder sub_string_finder ${EXECUTABLE} "${ARGS}")
|
||||
add_execution_target(light_test_sub_string_finder sub_string_finder ${LIGHT_EXECUTABLE} "${LIGHT_ARGS}")
|
||||
@@ -0,0 +1,31 @@
|
||||
# Sub_string_finder sample
|
||||
An example that uses the `parallel_for` template in a substring matching program. The [oneAPI Threading Building Blocks [](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html) describes this example.
|
||||
|
||||
For each position in a string, the program displays the length of the largest matching substring elsewhere in the string. The program also displays the location of a largest match for each position. Consider the string "babba" as an example. Starting at position 0, "ba" is the largest substring with a match elsewhere in the string (position 3).
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
### Predefined make targets
|
||||
* `make sub_string_finder_simple` - builds the example as it appears in the Get Started Guide.
|
||||
* `make sub_string_finder_extended` - builds the similar example with more attractive printing of the results.
|
||||
* `make sub_string_finder_pretty` - builds the example extended with a sequential implementation.
|
||||
* `make sub_string_finder` - builds all sample versions.
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_sub_string_finder` - executes the example with predefined parameters.
|
||||
* `make light_test_sub_string_finder` - executes the example with suggested parameters to reduce execution time.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
sub_string_finder_simple
|
||||
sub_string_finder_extended
|
||||
sub_string_finder_pretty
|
||||
```
|
||||
|
||||
The example does not requires application parameters.
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm> // std::max
|
||||
|
||||
#include "oneapi/tbb/parallel_for.h"
|
||||
#include "oneapi/tbb/blocked_range.h"
|
||||
|
||||
#include "common/utility/utility.hpp"
|
||||
|
||||
bool silent = false;
|
||||
|
||||
static const std::size_t N = 23;
|
||||
|
||||
class SubStringFinder {
|
||||
const std::string &str;
|
||||
std::vector<std::size_t> &max_array;
|
||||
std::vector<std::size_t> &pos_array;
|
||||
|
||||
public:
|
||||
void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
|
||||
for (std::size_t i = r.begin(); i != r.end(); ++i) {
|
||||
std::size_t max_size = 0, max_pos = 0;
|
||||
for (std::size_t j = 0; j < str.size(); ++j) {
|
||||
if (j != i) {
|
||||
std::size_t limit = str.size() - (std::max)(i, j);
|
||||
for (std::size_t k = 0; k < limit; ++k) {
|
||||
if (str[i + k] != str[j + k])
|
||||
break;
|
||||
if (k > max_size) {
|
||||
max_size = k;
|
||||
max_pos = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
max_array[i] = max_size;
|
||||
pos_array[i] = max_pos;
|
||||
}
|
||||
}
|
||||
|
||||
SubStringFinder(const std::string &s, std::vector<std::size_t> &m, std::vector<std::size_t> &p)
|
||||
: str(s),
|
||||
max_array(m),
|
||||
pos_array(p) {}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// command line parsing
|
||||
utility::parse_cli_arguments(argc,
|
||||
argv,
|
||||
utility::cli_argument_pack()
|
||||
//"-h" option for displaying help is present implicitly
|
||||
.arg(silent, "silent", "no output"));
|
||||
|
||||
std::string str[N] = { std::string("a"), std::string("b") };
|
||||
for (std::size_t i = 2; i < N; ++i)
|
||||
str[i] = str[i - 1] + str[i - 2];
|
||||
std::string &to_scan = str[N - 1];
|
||||
const std::size_t num_elem = to_scan.size();
|
||||
|
||||
std::vector<std::size_t> max(num_elem);
|
||||
std::vector<std::size_t> pos(num_elem);
|
||||
|
||||
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem),
|
||||
SubStringFinder(to_scan, max, pos));
|
||||
|
||||
for (std::size_t i = 0; i < num_elem; ++i)
|
||||
if (!silent)
|
||||
std::cout << " " << max[i] << "(" << pos[i] << ")"
|
||||
<< "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm> // std::max
|
||||
|
||||
#include "oneapi/tbb/parallel_for.h"
|
||||
#include "oneapi/tbb/blocked_range.h"
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
|
||||
static const std::size_t N = 22;
|
||||
|
||||
void SerialSubStringFinder(const std::string &str,
|
||||
std::vector<std::size_t> &max_array,
|
||||
std::vector<std::size_t> &pos_array) {
|
||||
for (std::size_t i = 0; i < str.size(); ++i) {
|
||||
std::size_t max_size = 0, max_pos = 0;
|
||||
for (std::size_t j = 0; j < str.size(); ++j)
|
||||
if (j != i) {
|
||||
std::size_t limit = str.size() - (std::max)(i, j);
|
||||
for (std::size_t k = 0; k < limit; ++k) {
|
||||
if (str[i + k] != str[j + k])
|
||||
break;
|
||||
if (k > max_size) {
|
||||
max_size = k;
|
||||
max_pos = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
max_array[i] = max_size;
|
||||
pos_array[i] = max_pos;
|
||||
}
|
||||
}
|
||||
|
||||
class SubStringFinder {
|
||||
const char *str;
|
||||
const std::size_t len;
|
||||
std::size_t *max_array;
|
||||
std::size_t *pos_array;
|
||||
|
||||
public:
|
||||
void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
|
||||
for (std::size_t i = r.begin(); i != r.end(); ++i) {
|
||||
std::size_t max_size = 0, max_pos = 0;
|
||||
for (std::size_t j = 0; j < len; ++j) {
|
||||
if (j != i) {
|
||||
std::size_t limit = len - (std::max)(i, j);
|
||||
for (std::size_t k = 0; k < limit; ++k) {
|
||||
if (str[i + k] != str[j + k])
|
||||
break;
|
||||
if (k > max_size) {
|
||||
max_size = k;
|
||||
max_pos = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
max_array[i] = max_size;
|
||||
pos_array[i] = max_pos;
|
||||
}
|
||||
}
|
||||
// We do not use std::vector for compatibility with offload execution
|
||||
SubStringFinder(const char *s, const std::size_t s_len, std::size_t *m, std::size_t *p)
|
||||
: str(s),
|
||||
len(s_len),
|
||||
max_array(m),
|
||||
pos_array(p) {}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::string str[N] = { std::string("a"), std::string("b") };
|
||||
for (std::size_t i = 2; i < N; ++i)
|
||||
str[i] = str[i - 1] + str[i - 2];
|
||||
std::string &to_scan = str[N - 1];
|
||||
const std::size_t num_elem = to_scan.size();
|
||||
|
||||
std::vector<std::size_t> max1(num_elem);
|
||||
std::vector<std::size_t> pos1(num_elem);
|
||||
std::vector<std::size_t> max2(num_elem);
|
||||
std::vector<std::size_t> pos2(num_elem);
|
||||
|
||||
std::cout << " Done building string."
|
||||
<< "\n";
|
||||
|
||||
oneapi::tbb::tick_count serial_t0 = oneapi::tbb::tick_count::now();
|
||||
SerialSubStringFinder(to_scan, max2, pos2);
|
||||
oneapi::tbb::tick_count serial_t1 = oneapi::tbb::tick_count::now();
|
||||
std::cout << " Done with serial version."
|
||||
<< "\n";
|
||||
|
||||
oneapi::tbb::tick_count parallel_t0 = oneapi::tbb::tick_count::now();
|
||||
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem, 100),
|
||||
SubStringFinder(to_scan.c_str(), num_elem, &max1[0], &pos1[0]));
|
||||
oneapi::tbb::tick_count parallel_t1 = oneapi::tbb::tick_count::now();
|
||||
std::cout << " Done with parallel version."
|
||||
<< "\n";
|
||||
|
||||
for (std::size_t i = 0; i < num_elem; ++i) {
|
||||
if (max1[i] != max2[i] || pos1[i] != pos2[i]) {
|
||||
std::cout << "ERROR: Serial and Parallel Results are Different!"
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cout << " Done validating results."
|
||||
<< "\n";
|
||||
|
||||
std::cout << "Serial version ran in " << (serial_t1 - serial_t0).seconds() << " seconds"
|
||||
<< "\n"
|
||||
<< "Parallel version ran in " << (parallel_t1 - parallel_t0).seconds() << " seconds"
|
||||
<< "\n"
|
||||
<< "Resulting in a speedup of "
|
||||
<< (serial_t1 - serial_t0).seconds() / (parallel_t1 - parallel_t0).seconds() << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <algorithm> // std::max
|
||||
|
||||
#include "oneapi/tbb/parallel_for.h"
|
||||
#include "oneapi/tbb/blocked_range.h"
|
||||
|
||||
static const std::size_t N = 9;
|
||||
|
||||
class SubStringFinder {
|
||||
const std::string &str;
|
||||
std::vector<std::size_t> &max_array;
|
||||
std::vector<std::size_t> &pos_array;
|
||||
|
||||
public:
|
||||
void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
|
||||
for (std::size_t i = r.begin(); i != r.end(); ++i) {
|
||||
std::size_t max_size = 0, max_pos = 0;
|
||||
for (std::size_t j = 0; j < str.size(); ++j) {
|
||||
if (j != i) {
|
||||
std::size_t limit = str.size() - (std::max)(i, j);
|
||||
for (std::size_t k = 0; k < limit; ++k) {
|
||||
if (str[i + k] != str[j + k])
|
||||
break;
|
||||
if (k + 1 > max_size) {
|
||||
max_size = k + 1;
|
||||
max_pos = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
max_array[i] = max_size;
|
||||
pos_array[i] = max_pos;
|
||||
}
|
||||
}
|
||||
|
||||
SubStringFinder(const std::string &s, std::vector<std::size_t> &m, std::vector<std::size_t> &p)
|
||||
: str(s),
|
||||
max_array(m),
|
||||
pos_array(p) {}
|
||||
};
|
||||
|
||||
int main() {
|
||||
std::string str[N] = { std::string("a"), std::string("b") };
|
||||
for (std::size_t i = 2; i < N; ++i)
|
||||
str[i] = str[i - 1] + str[i - 2];
|
||||
std::string &to_scan = str[N - 1];
|
||||
const std::size_t num_elem = to_scan.size();
|
||||
std::cout << "String to scan: " << to_scan << "\n";
|
||||
|
||||
std::vector<std::size_t> max(num_elem);
|
||||
std::vector<std::size_t> pos(num_elem);
|
||||
|
||||
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem, 100),
|
||||
SubStringFinder(to_scan, max, pos));
|
||||
|
||||
for (std::size_t i = 0; i < num_elem; ++i) {
|
||||
for (std::size_t j = 0; j < num_elem; ++j) {
|
||||
if (j >= i && j < i + max[i])
|
||||
std::cout << "_";
|
||||
else
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "\n" << to_scan << "\n";
|
||||
|
||||
for (std::size_t j = 0; j < num_elem; ++j) {
|
||||
if (j >= pos[i] && j < pos[i] + max[i])
|
||||
std::cout << "*";
|
||||
else
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
|
||||
Examples using oneTBB Flow Graph feature.
|
||||
|
||||
| Code sample name | Description
|
||||
|:--- |:---
|
||||
| binpack | A solution to the binpacking problem using a `queue_node`, a `buffer_node` and `function_node`s.
|
||||
| cholesky | Several versions of Cholesky Factorization algorithm implementation.
|
||||
| dining_philosophers | An implementation of dining philosophers in graph using the reserving `join_node`.
|
||||
| fgbzip2 | A parallel implementation of bzip2 block-sorting file compressor.
|
||||
| logic_sim | An example of a collection of digital logic gates that can be easily composed into larger circuits.
|
||||
| som | An example of a Kohonen Self-Organizing Map using cancellation.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(binpack CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
add_executable(binpack binpack.cpp)
|
||||
|
||||
target_link_libraries(binpack TBB::tbb Threads::Threads)
|
||||
target_compile_options(binpack PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:binpack>")
|
||||
set(ARGS 4 elements_num=1000)
|
||||
set(PERF_ARGS auto elements_num=1000 silent)
|
||||
|
||||
add_execution_target(run_binpack binpack ${EXECUTABLE} "${ARGS}")
|
||||
add_execution_target(perf_run_binpack binpack ${EXECUTABLE} "${PERF_ARGS}")
|
||||
@@ -0,0 +1,29 @@
|
||||
# Binpack sample
|
||||
This directory contains an `oneapi::tbb::flow` example that performs binpacking of `N` integer values into a near-optimal number of bins of capacity `V`.
|
||||
|
||||
It features a `source_node` which passes randomly generated integer values of `size <= V` to a `queue_node`. Multiple function nodes set about taking values from this `queue_node` and packing them into bins according to a best-fit policy. Items that cannot be made to fit are rejected and returned to the queue. When a bin is packed as well as it can be, it is passed to a `buffer_node` where it waits to be picked up by another `function_node`. This final function node gathers stats about the bin and optionally prints its contents. When all bins are accounted for, it optionally prints a summary of the quality of the bin-packing.
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_binpack` - executes the example with predefined parameters.
|
||||
* `make perf_run_binpack` - executes the example with suggested parameters to measure the oneTBB performance.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
binpack [#threads=value] [verbose] [silent] [elements_num=value] [bin_capacity=value] [#packers=value] [optimality=value] [-h] [#threads]
|
||||
```
|
||||
* `-h` - prints the help for command line options.
|
||||
* `#threads` - the number of threads to use; a range of the form low\[:high\] where low and optional high are non-negative integers, or `auto` for a platform-specific default number.
|
||||
* `verbose` - prints diagnostic output to screen.
|
||||
* `silent` - limits output to timing info; overrides verbose.
|
||||
* `N` - number of values to pack.
|
||||
* `V` - capacity of each bin.
|
||||
* `#packers` - number of concurrent bin packers to use (`default=#threads`).
|
||||
* `optimality` - controls optimality of solution; 1 is highest, use larger numbers for less optimal but faster solution.
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/* Bin-packing algorithm that attempts to use minimal number of bins B of
|
||||
size desired_bin_capacity to contain elements_num items of varying sizes. */
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
#include "oneapi/tbb/flow_graph.h"
|
||||
#include "oneapi/tbb/global_control.h"
|
||||
|
||||
#include "common/utility/utility.hpp"
|
||||
#include "common/utility/get_default_num_threads.hpp"
|
||||
|
||||
typedef std::size_t size_type; // to represent non-zero indices, capacities, etc.
|
||||
typedef std::size_t value_type; // the type of items we are attempting to pack into bins
|
||||
typedef std::vector<value_type> bin; // we use a simple vector to represent a bin
|
||||
// Our bin packers will be function nodes in the graph that take value_type items and
|
||||
// return a dummy value. They will also implicitly send packed bins to the bin_buffer
|
||||
// node, and unused items back to the value_pool node:
|
||||
typedef oneapi::tbb::flow::
|
||||
multifunction_node<value_type, std::tuple<value_type, bin>, oneapi::tbb::flow::rejecting>
|
||||
bin_packer;
|
||||
// Items are placed into a pool that all bin packers grab from, represent by a queue_node:
|
||||
typedef oneapi::tbb::flow::queue_node<value_type> value_pool;
|
||||
// Packed bins are placed in this buffer waiting to be serially printed and/or accounted for:
|
||||
typedef oneapi::tbb::flow::buffer_node<bin> bin_buffer;
|
||||
// Packed bins are taken from the_bin_buffer and processed by the_writer:
|
||||
typedef oneapi::tbb::flow::
|
||||
function_node<bin, oneapi::tbb::flow::continue_msg, oneapi::tbb::flow::rejecting>
|
||||
bin_writer;
|
||||
// Items are injected into the graph when this node sends them to the_value_pool:
|
||||
typedef oneapi::tbb::flow::input_node<value_type> value_source;
|
||||
|
||||
// User-specified globals with default values
|
||||
size_type desired_bin_capacity = 42;
|
||||
size_type elements_num = 1000; // number of elements to generate
|
||||
bool verbose = false; // prints bin details and other diagnostics to screen
|
||||
bool silent = false; // suppress all output except for time
|
||||
int num_bin_packers = -1; // number of concurrent bin packers in operation; default is #threads;
|
||||
// larger values can result in more bins at less than full capacity
|
||||
size_type optimality =
|
||||
1; // 1 (default) is highest the algorithm can obtain; larger numbers run faster
|
||||
|
||||
// Calculated globals
|
||||
size_type bins_num_min; // lower bound on the optimal number of bins
|
||||
size_type bins_num; // the answer, i.e. number of bins used by the algorithm
|
||||
std::vector<size_type> input_array; // stores randomly generated input values
|
||||
value_type item_sum; // sum of all randomly generated input values
|
||||
std::atomic<value_type> packed_sum; // sum of all values currently packed into all bins
|
||||
std::atomic<size_type> packed_items; // number of values currently packed into all bins
|
||||
std::atomic<size_type> active_bins; // number of active bin_packers
|
||||
std::vector<bin_packer*> bins; // the array of bin packers
|
||||
|
||||
// This class is the Body type for bin_packer
|
||||
class bin_filler {
|
||||
typedef bin_packer::output_ports_type ports_type;
|
||||
bin my_bin; // the current bin that this bin_filler is packing
|
||||
size_type
|
||||
my_used; // capacity of bin used by current contents (not to be confused with my_bin.size())
|
||||
size_type relax,
|
||||
relax_val; // relaxation counter for determining when to settle for a non-full bin
|
||||
bin_packer* my_bin_packer; // ptr to the bin packer that this body object is associated with
|
||||
size_type bin_index; // index of the encapsulating bin packer in the global bins array
|
||||
value_type looking_for; // the minimum size of item this bin_packer will accept
|
||||
value_pool* the_value_pool; // the queue of incoming values
|
||||
bool done; // flag to indicate that this binpacker has been deactivated
|
||||
public:
|
||||
bin_filler(std::size_t bidx, value_pool* _q)
|
||||
: my_used(0),
|
||||
relax(0),
|
||||
relax_val(0),
|
||||
my_bin_packer(nullptr),
|
||||
bin_index(bidx),
|
||||
looking_for(desired_bin_capacity),
|
||||
the_value_pool(_q),
|
||||
done(false) {}
|
||||
void operator()(const value_type& item, ports_type& p) {
|
||||
if (!my_bin_packer)
|
||||
my_bin_packer = bins[bin_index];
|
||||
if (done)
|
||||
// this bin_packer is done packing items; put item back to pool
|
||||
std::get<0>(p).try_put(item);
|
||||
else if (
|
||||
item >
|
||||
desired_bin_capacity) { // signal that packed_sum has reached item_sum at some point
|
||||
size_type remaining = active_bins--;
|
||||
if (remaining == 1 &&
|
||||
packed_sum == item_sum) { // this is the last bin and it has seen everything
|
||||
// this bin_packer may not have seen everything, so stay active
|
||||
if (my_used > 0)
|
||||
std::get<1>(p).try_put(my_bin);
|
||||
my_bin.clear();
|
||||
my_used = 0;
|
||||
looking_for = desired_bin_capacity;
|
||||
++active_bins;
|
||||
}
|
||||
else if (remaining == 1) { // this is the last bin, but there are remaining items
|
||||
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
|
||||
++active_bins;
|
||||
}
|
||||
else if (remaining > 1) { // this is not the last bin; deactivate
|
||||
// this bin is ill-utilized; throw back items and deactivate
|
||||
if (my_used < desired_bin_capacity / (1 + optimality * .1)) {
|
||||
packed_sum -= my_used;
|
||||
packed_items -= my_bin.size();
|
||||
for (size_type i = 0; i < my_bin.size(); ++i)
|
||||
std::get<0>(p).try_put(my_bin[i]);
|
||||
oneapi::tbb::flow::remove_edge(*the_value_pool, *my_bin_packer); // deactivate
|
||||
done = true;
|
||||
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
|
||||
}
|
||||
else { // this bin is well-utilized; send out bin and deactivate
|
||||
oneapi::tbb::flow::remove_edge(*the_value_pool,
|
||||
*my_bin_packer); // build no more bins
|
||||
done = true;
|
||||
if (my_used > 0)
|
||||
std::get<1>(p).try_put(my_bin);
|
||||
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item <= desired_bin_capacity - my_used &&
|
||||
item >= looking_for) { // this item can be packed
|
||||
my_bin.push_back(item);
|
||||
my_used += item;
|
||||
packed_sum += item;
|
||||
++packed_items;
|
||||
looking_for = desired_bin_capacity - my_used;
|
||||
relax = 0;
|
||||
if (packed_sum == item_sum) {
|
||||
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
|
||||
}
|
||||
if (my_used == desired_bin_capacity) {
|
||||
std::get<1>(p).try_put(my_bin);
|
||||
my_bin.clear();
|
||||
my_used = 0;
|
||||
looking_for = desired_bin_capacity;
|
||||
}
|
||||
}
|
||||
else { // this item can't be packed; relax constraints
|
||||
++relax;
|
||||
// this bin_packer has looked through enough items
|
||||
if (relax >= (elements_num - packed_items) / optimality) {
|
||||
relax = 0;
|
||||
--looking_for; // accept a wider range of items
|
||||
if (looking_for == 0 && my_used < desired_bin_capacity / (1 + optimality * .1) &&
|
||||
my_used > 0 && active_bins > 1) {
|
||||
// this bin_packer is ill-utilized and can't find items; deactivate and throw back items
|
||||
size_type remaining = active_bins--;
|
||||
if (remaining > 1) { // not the last bin_packer
|
||||
oneapi::tbb::flow::remove_edge(*the_value_pool,
|
||||
*my_bin_packer); // deactivate
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
active_bins++; // can't deactivate last bin_packer
|
||||
packed_sum -= my_used;
|
||||
packed_items -= my_bin.size();
|
||||
for (size_type i = 0; i < my_bin.size(); ++i)
|
||||
std::get<0>(p).try_put(my_bin[i]);
|
||||
my_bin.clear();
|
||||
my_used = 0;
|
||||
}
|
||||
else if (looking_for == 0 &&
|
||||
(my_used >= desired_bin_capacity / (1 + optimality * .1) ||
|
||||
active_bins == 1)) {
|
||||
// this bin_packer can't find items but is well-utilized, so send it out and reset
|
||||
std::get<1>(p).try_put(my_bin);
|
||||
my_bin.clear();
|
||||
my_used = 0;
|
||||
looking_for = desired_bin_capacity;
|
||||
}
|
||||
}
|
||||
std::get<0>(p).try_put(item); // put unused item back to pool
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// input node uses this to send the values to the value_pool
|
||||
class item_generator {
|
||||
size_type counter;
|
||||
|
||||
public:
|
||||
item_generator() : counter(0) {}
|
||||
value_type operator()(oneapi::tbb::flow_control& fc) {
|
||||
if (counter < elements_num) {
|
||||
value_type result = input_array[counter];
|
||||
++counter;
|
||||
return result;
|
||||
}
|
||||
|
||||
fc.stop();
|
||||
return value_type{};
|
||||
}
|
||||
};
|
||||
|
||||
// the terminal function_node uses this to gather stats and print bin information
|
||||
class bin_printer {
|
||||
value_type running_count;
|
||||
size_type item_count;
|
||||
value_type my_min, my_max;
|
||||
double avg;
|
||||
|
||||
public:
|
||||
bin_printer()
|
||||
: running_count(0),
|
||||
item_count(0),
|
||||
my_min(desired_bin_capacity),
|
||||
my_max(0),
|
||||
avg(0) {}
|
||||
oneapi::tbb::flow::continue_msg operator()(bin b) {
|
||||
value_type sum = 0;
|
||||
++bins_num;
|
||||
if (verbose)
|
||||
std::cout << "[ ";
|
||||
for (size_type i = 0; i < b.size(); ++i) {
|
||||
if (verbose)
|
||||
std::cout << b[i] << " ";
|
||||
sum += b[i];
|
||||
++item_count;
|
||||
}
|
||||
my_min = std::min(sum, my_min);
|
||||
my_max = std::max(sum, my_max);
|
||||
avg += sum;
|
||||
running_count += sum;
|
||||
if (verbose) {
|
||||
std::cout << "]=" << sum << "; Done/Packed/Total cap: " << running_count << "/"
|
||||
<< packed_sum << "/" << item_sum << " items:" << item_count << "/"
|
||||
<< packed_items << "/" << elements_num << " bins_num=" << bins_num << "\n";
|
||||
}
|
||||
if (item_count == elements_num) { // should be the last; print stats
|
||||
avg = avg / (double)bins_num;
|
||||
if (!silent)
|
||||
std::cout << "SUMMARY: #Bins used: " << bins_num << "; Avg size: " << avg
|
||||
<< "; Max size: " << my_max << "; Min size: " << my_min << "\n"
|
||||
<< " Lower bound on optimal #bins: " << bins_num_min
|
||||
<< "; Start #bins: " << num_bin_packers << "\n";
|
||||
}
|
||||
return oneapi::tbb::flow::continue_msg(); // need to return something
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
utility::thread_number_range threads(utility::get_default_num_threads);
|
||||
utility::parse_cli_arguments(
|
||||
argc,
|
||||
argv,
|
||||
utility::cli_argument_pack()
|
||||
//"-h" option for displaying help is present implicitly
|
||||
.positional_arg(threads, "#threads", utility::thread_number_range_desc)
|
||||
.arg(verbose, "verbose", " print diagnostic output to screen")
|
||||
.arg(silent, "silent", " limits output to timing info; overrides verbose")
|
||||
.arg(elements_num, "elements_num", " number of values to pack")
|
||||
.arg(desired_bin_capacity, "bin_capacity", " capacity of each bin")
|
||||
.arg(num_bin_packers,
|
||||
"#packers",
|
||||
" number of concurrent bin packers to use "
|
||||
"(default=#threads)")
|
||||
.arg(optimality,
|
||||
"optimality",
|
||||
"controls optimality of solution; 1 is highest, use\n"
|
||||
" larger numbers for less optimal but faster solution"));
|
||||
|
||||
if (silent)
|
||||
verbose = false; // make silent override verbose
|
||||
// Generate random input data
|
||||
srand(42);
|
||||
input_array.resize(elements_num);
|
||||
item_sum = 0;
|
||||
for (auto& item : input_array) {
|
||||
item = rand() % desired_bin_capacity + 1; // generate items that fit in a bin
|
||||
item_sum += item;
|
||||
}
|
||||
bins_num_min = (item_sum % desired_bin_capacity) ? item_sum / desired_bin_capacity + 1
|
||||
: item_sum / desired_bin_capacity;
|
||||
|
||||
oneapi::tbb::tick_count start = oneapi::tbb::tick_count::now();
|
||||
for (int p = threads.first; p <= threads.last; p = threads.step(p)) {
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p);
|
||||
packed_sum = 0;
|
||||
packed_items = 0;
|
||||
bins_num = 0;
|
||||
if (num_bin_packers == -1)
|
||||
num_bin_packers = p;
|
||||
active_bins = num_bin_packers;
|
||||
if (!silent)
|
||||
std::cout << "binpack running with " << item_sum << " capacity over " << elements_num
|
||||
<< " items, optimality=" << optimality << ", " << num_bin_packers
|
||||
<< " bins of capacity=" << desired_bin_capacity << " on " << p << " threads."
|
||||
<< "\n";
|
||||
oneapi::tbb::flow::graph g;
|
||||
value_source the_source(g, item_generator());
|
||||
value_pool the_value_pool(g);
|
||||
oneapi::tbb::flow::make_edge(the_source, the_value_pool);
|
||||
bin_buffer the_bin_buffer(g);
|
||||
bins.resize(num_bin_packers);
|
||||
for (int i = 0; i < num_bin_packers; ++i) {
|
||||
bins[i] = new bin_packer(g, 1, bin_filler(i, &the_value_pool));
|
||||
oneapi::tbb::flow::make_edge(the_value_pool, *(bins[i]));
|
||||
oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<0>(*(bins[i])),
|
||||
the_value_pool);
|
||||
oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<1>(*(bins[i])),
|
||||
the_bin_buffer);
|
||||
}
|
||||
bin_writer the_writer(g, 1, bin_printer());
|
||||
make_edge(the_bin_buffer, the_writer);
|
||||
the_source.activate();
|
||||
g.wait_for_all();
|
||||
for (int i = 0; i < num_bin_packers; ++i) {
|
||||
delete bins[i];
|
||||
}
|
||||
}
|
||||
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - start).seconds());
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(cholesky CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
# TODO: Consider using FindMKL module
|
||||
find_library(MKL_INTEL_LP64_LIB mkl_intel_lp64 PATHS ENV LIBRARY_PATH)
|
||||
find_library(MKL_SEQUENTIAL_LIB mkl_sequential PATHS ENV LIBRARY_PATH)
|
||||
find_library(MKL_CORE_LIB mkl_core PATHS ENV LIBRARY_PATH)
|
||||
if(NOT (MKL_INTEL_LP64_LIB OR MKL_SEQUENTIAL_LIB OR MKL_CORE_LIB))
|
||||
message(FATAL_ERROR "Cannot find Intel(R) Math Kernel Library (Intel(R) MKL).")
|
||||
endif()
|
||||
|
||||
add_executable(cholesky init.cpp cholesky.cpp)
|
||||
target_link_libraries(cholesky
|
||||
${MKL_INTEL_LP64_LIB}
|
||||
${MKL_SEQUENTIAL_LIB}
|
||||
${MKL_CORE_LIB}
|
||||
TBB::tbb
|
||||
Threads::Threads
|
||||
)
|
||||
target_compile_options(cholesky PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:cholesky>")
|
||||
set(ARGS 4 2)
|
||||
add_execution_target(run_cholesky cholesky ${EXECUTABLE} "${ARGS}")
|
||||
@@ -0,0 +1,37 @@
|
||||
# Cholesky sample
|
||||
This directory contains an example of several versions of Cholesky Factorization algorithm.
|
||||
|
||||
**dpotrf**: An implementation that calls the oneAPI Math Kernel Library (oneMKL) `dpotrf` function to directly perform the factorization. This can be a serial implementation or threaded implementation depending on the version of the oneMKL library that is linked against.
|
||||
|
||||
**crout**: A serial implementation that uses the Crout-Cholesky algorithm for factorization. The same approach is parallelized for the other oneAPI Threading Building Blocks (oneTBB) based approaches below.
|
||||
|
||||
**depend**: A parallel version of Crout-Cholesky factorization that uses the oneTBB flow graph. This version uses a dependency graph made solely of `continue_node` objects. This an inspector-executor approach, where a loop nest that is similar to the serial implementation is used to create an unrolled version of the computation. Where the oneMKL calls would have been made in the original serial implementation of Crout-Cholesky, graph nodes are created instead and these nodes are linked by edges to the other nodes they are dependent upon. The resulting graph is relatively large, with a node for each instance of each oneMKL call. For example, there are many nodes that call `dtrsm`; one for each invocation of `dtrsm` in the serial implementation. The is very little overhead in message management for this version and so it is often the highest performing.
|
||||
|
||||
**join**: A parallel version of Crout-Cholesky factorization that uses the oneTBB flow graph. This version uses a data flow approach. This is a small, compact graph that passes tiles along its edges. There is one node per type of oneMKL call, plus `join_node`s that combine the inputs required for each call. So for example, there is only a single node that applies all calls to `dtrsm`. This node is invoked when the tiles that hold the inputs and outputs for an invocation are matched together in the tag-matching `join_node` that precedes it. The tag represents the iteration values of the `i`, `j`, `k` loops in the serial implementation at that invocation of the call. There is some overhead in message matching and forwarding, so it may not perform as well as the dependency graph implementation.
|
||||
|
||||
This sample code requires a oneTBB library and also the oneMKL library.
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_cholesky` - executes the example with predefined parameters.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
cholesky [size=value] [blocksize=value] [num_trials=value] [output_prefix=value] [algorithm=value] [num_tbb_threads=value] [input_file=value] [-x] [-h] [size [blocksize [num_trials [output_prefix [algorithm [num_tbb_threads]]]]]]
|
||||
```
|
||||
* `-h` - prints the help for command line options.
|
||||
* `size` - the row/column size of `NxN` matrix (size <= 46000).
|
||||
* `blocksize` - the block size; size must be a multiple of the blocksize.
|
||||
* `num_trials` - the number of times to run each algorithm.
|
||||
* `output_prefix` - if provided the prefix will be prepended to output files: <output_prefix>_posdef.txt and <output_prefix>_X.txt; where `X` is the algorithm used. If `output_prefix` is not provided, no output will be written.
|
||||
* `algorithm` - name of the used algorithm - can be dpotrf, crout, depend or join.
|
||||
* `num_tbb_threads` - number of oneTBB threads.
|
||||
* `input_file` - input matrix (optional). If omitted, randomly generated values are used.
|
||||
* `-x` - skips all validation.
|
||||
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
|
||||
#include "mkl_lapack.h"
|
||||
#include "mkl.h"
|
||||
|
||||
#include "oneapi/tbb/flow_graph.h"
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
#include "oneapi/tbb/global_control.h"
|
||||
|
||||
// Application command line arguments parsing
|
||||
#include "common/utility/utility.hpp"
|
||||
#include "common/utility/get_default_num_threads.hpp"
|
||||
|
||||
/************************************************************
|
||||
FORWARD DECLARATIONS
|
||||
************************************************************/
|
||||
|
||||
/**********************************************
|
||||
Read or generate a positive-definite matrix
|
||||
-- reads from file if fname != nullptr
|
||||
-- sets n to matrix size
|
||||
-- allocates and reads values in to A
|
||||
-- otherwise generates a matrix
|
||||
-- uses n to determine size
|
||||
-- allocates and generates values in to A
|
||||
**********************************************/
|
||||
void matrix_init(double *&A, int &n, const char *fname);
|
||||
|
||||
/**********************************************
|
||||
Writes a lower triangular matrix to a file
|
||||
-- first line of file is n
|
||||
-- subsequently 1 row per line
|
||||
**********************************************/
|
||||
void matrix_write(double *A, int n, const char *fname, bool is_triangular = false);
|
||||
|
||||
/************************************************************
|
||||
GLOBAL VARIABLES
|
||||
************************************************************/
|
||||
bool g_benchmark_run = false;
|
||||
int g_n = -1, g_b = -1, g_num_trials = 1;
|
||||
char *g_input_file_name = nullptr;
|
||||
char *g_output_prefix = nullptr;
|
||||
std::string g_alg_name;
|
||||
int g_num_tbb_threads;
|
||||
|
||||
// Creates tiled array
|
||||
static double ***create_tile_array(double *A, int n, int b) {
|
||||
const int p = n / b;
|
||||
double ***tile = (double ***)calloc(sizeof(double **), p);
|
||||
|
||||
for (int j = 0; j < p; ++j) {
|
||||
tile[j] = (double **)calloc(sizeof(double *), p);
|
||||
}
|
||||
|
||||
for (int j = 0; j < p; ++j) {
|
||||
for (int i = 0; i < p; ++i) {
|
||||
double *temp_block = (double *)calloc(sizeof(double), b * b);
|
||||
|
||||
for (int A_j = j * b, T_j = 0; T_j < b; ++A_j, ++T_j) {
|
||||
for (int A_i = i * b, T_i = 0; T_i < b; ++A_i, ++T_i) {
|
||||
temp_block[T_j * b + T_i] = A[A_j * n + A_i];
|
||||
}
|
||||
}
|
||||
|
||||
tile[j][i] = temp_block;
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
static void collapse_tile_array(double ***tile, double *A, int n, int b) {
|
||||
const int p = n / b;
|
||||
|
||||
for (int j = 0; j < p; ++j) {
|
||||
for (int i = 0; i < p; ++i) {
|
||||
double *temp_block = tile[j][i];
|
||||
|
||||
for (int A_j = j * b, T_j = 0; T_j < b; ++A_j, ++T_j) {
|
||||
for (int A_i = i * b, T_i = 0; T_i < b; ++A_i, ++T_i) {
|
||||
A[A_j * n + A_i] = temp_block[T_j * b + T_i];
|
||||
}
|
||||
}
|
||||
|
||||
free(temp_block);
|
||||
tile[j][i] = nullptr;
|
||||
}
|
||||
|
||||
free(tile[j]);
|
||||
}
|
||||
|
||||
free(tile);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Helper base class: algorithm
|
||||
************************************************************/
|
||||
class algorithm {
|
||||
std::string name;
|
||||
bool is_tiled;
|
||||
|
||||
bool check_if_valid(double *A0, double *C, double *A, int n) {
|
||||
char transa = 'n', transb = 't';
|
||||
double alpha = 1;
|
||||
double beta = 0;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (int j = i + 1; j < n; ++j) {
|
||||
A0[j * n + i] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
dgemm(&transa, &transb, &n, &n, &n, &alpha, A0, &n, A0, &n, &beta, C, &n);
|
||||
|
||||
for (int j = 0; j < n; ++j) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const double epsilon = std::abs(A[j * n + i] * 0.1);
|
||||
|
||||
if (std::abs(C[j * n + i] - A[j * n + i]) > epsilon) {
|
||||
printf("ERROR: %s did not validate at C(%d,%d) = %lf != A(%d,%d) = %lf\n",
|
||||
name.c_str(),
|
||||
i,
|
||||
j,
|
||||
C[j * n + i],
|
||||
i,
|
||||
j,
|
||||
A[j * n + i]);
|
||||
printf("ERROR: %g; %g < %g < %g\n",
|
||||
epsilon,
|
||||
A[j * n + i] - epsilon,
|
||||
C[j * n + i],
|
||||
A[j * n + i] + epsilon);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
algorithm(const std::string &alg_name, bool t) : name(alg_name), is_tiled(t) {}
|
||||
|
||||
double operator()(double *A, int n, int b, int trials) {
|
||||
oneapi::tbb::tick_count t0, t1;
|
||||
double elapsed_time = 0.0;
|
||||
double *A0 = (double *)calloc(sizeof(double), n * n);
|
||||
double *C = (double *)calloc(sizeof(double), n * n);
|
||||
|
||||
for (int i = 0; i < trials + 1; ++i) {
|
||||
if (is_tiled) {
|
||||
double ***tile = create_tile_array(A, n, b);
|
||||
t0 = oneapi::tbb::tick_count::now();
|
||||
func(tile, n, b);
|
||||
t1 = oneapi::tbb::tick_count::now();
|
||||
|
||||
collapse_tile_array(tile, A0, n, b);
|
||||
}
|
||||
else {
|
||||
memcpy(A0, A, sizeof(double) * n * n);
|
||||
t0 = oneapi::tbb::tick_count::now();
|
||||
func(A0, n, b);
|
||||
t1 = oneapi::tbb::tick_count::now();
|
||||
}
|
||||
|
||||
if (i)
|
||||
elapsed_time += (t1 - t0).seconds();
|
||||
|
||||
if (!g_benchmark_run && !check_if_valid(A0, C, A, n)) {
|
||||
if (g_output_prefix) {
|
||||
std::string s(g_output_prefix);
|
||||
s += "_" + name + ".txt";
|
||||
matrix_write(A0, g_n, s.c_str(), true);
|
||||
free(A0);
|
||||
free(C);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_output_prefix) {
|
||||
std::string s(g_output_prefix);
|
||||
s += "_" + name + ".txt";
|
||||
matrix_write(A0, g_n, s.c_str(), true);
|
||||
}
|
||||
|
||||
printf("%s %d %d %d %d %lf %lf\n",
|
||||
name.c_str(),
|
||||
g_num_tbb_threads,
|
||||
trials,
|
||||
n,
|
||||
b,
|
||||
elapsed_time,
|
||||
elapsed_time / trials);
|
||||
free(A0);
|
||||
free(C);
|
||||
return elapsed_time;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Main algorithm body function must be defined in any direved class
|
||||
virtual void func(void *ptr, int n, int b) = 0;
|
||||
};
|
||||
|
||||
/***********************************************************/
|
||||
|
||||
static void call_dpotf2(double ***tile, int b, int k) {
|
||||
double *A_block = tile[k][k];
|
||||
char uplo = 'l';
|
||||
int info = 0;
|
||||
dpotf2(&uplo, &b, A_block, &b, &info);
|
||||
return;
|
||||
}
|
||||
|
||||
static void call_dtrsm(double ***tile, int b, int k, int j) {
|
||||
double *A_block = tile[k][j];
|
||||
double *L_block = tile[k][k];
|
||||
char uplo = 'l', side = 'r', transa = 't', diag = 'n';
|
||||
double alpha = 1;
|
||||
dtrsm(&side, &uplo, &transa, &diag, &b, &b, &alpha, L_block, &b, A_block, &b);
|
||||
return;
|
||||
}
|
||||
|
||||
static void call_dsyr2k(double ***tile, int b, int k, int j, int i) {
|
||||
double *A_block = tile[i][j];
|
||||
char transa = 'n', transb = 't';
|
||||
char uplo = 'l';
|
||||
double alpha = -1;
|
||||
double beta = 1;
|
||||
|
||||
if (i == j) { // Diagonal block
|
||||
double *L_block = tile[k][i];
|
||||
dsyrk(&uplo, &transa, &b, &b, &alpha, L_block, &b, &beta, A_block, &b);
|
||||
}
|
||||
else { // Non-diagonal block
|
||||
double *L2_block = tile[k][i];
|
||||
double *L1_block = tile[k][j];
|
||||
dgemm(&transa, &transb, &b, &b, &b, &alpha, L1_block, &b, L2_block, &b, &beta, A_block, &b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
class algorithm_crout : public algorithm {
|
||||
public:
|
||||
algorithm_crout() : algorithm("crout_cholesky", true) {}
|
||||
|
||||
protected:
|
||||
virtual void func(void *ptr, int n, int b) {
|
||||
double ***tile = (double ***)ptr;
|
||||
const int p = n / b;
|
||||
|
||||
for (int k = 0; k < p; ++k) {
|
||||
call_dpotf2(tile, b, k);
|
||||
|
||||
for (int j = k + 1; j < p; ++j) {
|
||||
call_dtrsm(tile, b, k, j);
|
||||
|
||||
for (int i = k + 1; i <= j; ++i) {
|
||||
call_dsyr2k(tile, b, k, j, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class algorithm_dpotrf : public algorithm {
|
||||
public:
|
||||
algorithm_dpotrf() : algorithm("dpotrf_cholesky", false) {}
|
||||
|
||||
protected:
|
||||
virtual void func(void *ptr, int n, int /* b */) {
|
||||
double *A = (double *)ptr;
|
||||
int lda = n;
|
||||
int info = 0;
|
||||
char uplo = 'l';
|
||||
dpotrf(&uplo, &n, A, &lda, &info);
|
||||
}
|
||||
};
|
||||
|
||||
/************************************************************
|
||||
Begin data join graph based version of cholesky
|
||||
************************************************************/
|
||||
|
||||
typedef union {
|
||||
char a[4];
|
||||
std::size_t tag;
|
||||
} tag_t;
|
||||
|
||||
typedef double *tile_t;
|
||||
|
||||
typedef std::pair<tag_t, tile_t> tagged_tile_t;
|
||||
typedef std::tuple<tagged_tile_t> t1_t;
|
||||
typedef std::tuple<tagged_tile_t, tagged_tile_t> t2_t;
|
||||
typedef std::tuple<tagged_tile_t, tagged_tile_t, tagged_tile_t> t3_t;
|
||||
|
||||
typedef oneapi::tbb::flow::multifunction_node<tagged_tile_t, t1_t> dpotf2_node_t;
|
||||
typedef oneapi::tbb::flow::multifunction_node<t2_t, t2_t> dtrsm_node_t;
|
||||
typedef oneapi::tbb::flow::multifunction_node<t3_t, t3_t> dsyr2k_node_t;
|
||||
|
||||
typedef oneapi::tbb::flow::join_node<t2_t, oneapi::tbb::flow::tag_matching> dtrsm_join_t;
|
||||
typedef oneapi::tbb::flow::join_node<t3_t, oneapi::tbb::flow::tag_matching> dsyr2k_join_t;
|
||||
|
||||
class dpotf2_body {
|
||||
int p;
|
||||
int b;
|
||||
|
||||
public:
|
||||
dpotf2_body(int p_, int b_) : p(p_), b(b_) {}
|
||||
|
||||
void operator()(const tagged_tile_t &in, dpotf2_node_t::output_ports_type &ports) {
|
||||
int k = in.first.a[0];
|
||||
tile_t A_block = in.second;
|
||||
tag_t t;
|
||||
t.tag = 0;
|
||||
t.a[0] = k;
|
||||
char uplo = 'l';
|
||||
int info = 0;
|
||||
dpotf2(&uplo, &b, A_block, &b, &info);
|
||||
|
||||
// Send to dtrsms in same column
|
||||
// k == k j == k
|
||||
t.a[2] = k;
|
||||
for (int j = k + 1; j < p; ++j) {
|
||||
t.a[1] = j;
|
||||
std::get<0>(ports).try_put(std::make_pair(t, A_block));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class dtrsm_body {
|
||||
int p;
|
||||
int b;
|
||||
|
||||
public:
|
||||
dtrsm_body(int p_, int b_) : p(p_), b(b_) {}
|
||||
|
||||
void operator()(const t2_t &in, dtrsm_node_t::output_ports_type &ports) {
|
||||
tagged_tile_t in0 = std::get<0>(in);
|
||||
tagged_tile_t in1 = std::get<1>(in);
|
||||
int k = in0.first.a[0];
|
||||
int j = in0.first.a[1];
|
||||
tile_t L_block = in0.second;
|
||||
tile_t A_block = in1.second;
|
||||
tag_t t;
|
||||
t.tag = 0;
|
||||
t.a[0] = k;
|
||||
char uplo = 'l', side = 'r', transa = 't', diag = 'n';
|
||||
double alpha = 1;
|
||||
dtrsm(&side, &uplo, &transa, &diag, &b, &b, &alpha, L_block, &b, A_block, &b);
|
||||
|
||||
// Send to rest of my row
|
||||
t.a[1] = j;
|
||||
for (int i = k + 1; i <= j; ++i) {
|
||||
t.a[2] = i;
|
||||
std::get<0>(ports).try_put(std::make_pair(t, A_block));
|
||||
}
|
||||
|
||||
// Send to transposed row
|
||||
t.a[2] = j;
|
||||
for (int i = j; i < p; ++i) {
|
||||
t.a[1] = i;
|
||||
std::get<1>(ports).try_put(std::make_pair(t, A_block));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class dsyr2k_body {
|
||||
int p;
|
||||
int b;
|
||||
|
||||
public:
|
||||
dsyr2k_body(int p_, int b_) : p(p_), b(b_) {}
|
||||
|
||||
void operator()(const t3_t &in, dsyr2k_node_t::output_ports_type &ports) {
|
||||
tag_t t;
|
||||
t.tag = 0;
|
||||
char transa = 'n', transb = 't';
|
||||
char uplo = 'l';
|
||||
double alpha = -1;
|
||||
double beta = 1;
|
||||
|
||||
tagged_tile_t in0 = std::get<0>(in);
|
||||
tagged_tile_t in1 = std::get<1>(in);
|
||||
tagged_tile_t in2 = std::get<2>(in);
|
||||
int k = in2.first.a[0];
|
||||
int j = in2.first.a[1];
|
||||
int i = in2.first.a[2];
|
||||
|
||||
tile_t A_block = in2.second;
|
||||
if (i == j) { // Diagonal block
|
||||
tile_t L_block = in0.second;
|
||||
dsyrk(&uplo, &transa, &b, &b, &alpha, L_block, &b, &beta, A_block, &b);
|
||||
}
|
||||
else { // Non-diagonal block
|
||||
tile_t L1_block = in0.second;
|
||||
tile_t L2_block = in1.second;
|
||||
dgemm(&transa,
|
||||
&transb,
|
||||
&b,
|
||||
&b,
|
||||
&b,
|
||||
&alpha,
|
||||
L1_block,
|
||||
&b,
|
||||
L2_block,
|
||||
&b,
|
||||
&beta,
|
||||
A_block,
|
||||
&b);
|
||||
}
|
||||
|
||||
// All outputs flow to next step
|
||||
t.a[0] = k + 1;
|
||||
t.a[1] = j;
|
||||
t.a[2] = i;
|
||||
if (k != p - 1 && j == k + 1 && i == k + 1) {
|
||||
std::get<0>(ports).try_put(std::make_pair(t, A_block));
|
||||
}
|
||||
|
||||
if (k < p - 2) {
|
||||
if (i == k + 1 && j > i) {
|
||||
t.a[0] = k + 1;
|
||||
t.a[1] = j;
|
||||
std::get<1>(ports).try_put(std::make_pair(t, A_block));
|
||||
}
|
||||
|
||||
if (j != k + 1 && i != k + 1) {
|
||||
t.a[0] = k + 1;
|
||||
t.a[1] = j;
|
||||
t.a[2] = i;
|
||||
std::get<2>(ports).try_put(std::make_pair(t, A_block));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct tagged_tile_to_size_t {
|
||||
std::size_t operator()(const tagged_tile_t &t) {
|
||||
return t.first.tag;
|
||||
}
|
||||
};
|
||||
|
||||
class algorithm_join : public algorithm {
|
||||
public:
|
||||
algorithm_join() : algorithm("data_join_cholesky", true) {}
|
||||
|
||||
protected:
|
||||
virtual void func(void *ptr, int n, int b) {
|
||||
using oneapi::tbb::flow::unlimited;
|
||||
using oneapi::tbb::flow::output_port;
|
||||
using oneapi::tbb::flow::input_port;
|
||||
|
||||
double ***tile = (double ***)ptr;
|
||||
const int p = n / b;
|
||||
oneapi::tbb::flow::graph g;
|
||||
|
||||
dpotf2_node_t dpotf2_node(g, unlimited, dpotf2_body(p, b));
|
||||
dtrsm_node_t dtrsm_node(g, unlimited, dtrsm_body(p, b));
|
||||
dsyr2k_node_t dsyr2k_node(g, unlimited, dsyr2k_body(p, b));
|
||||
dtrsm_join_t dtrsm_join(g, tagged_tile_to_size_t(), tagged_tile_to_size_t());
|
||||
dsyr2k_join_t dsyr2k_join(
|
||||
g, tagged_tile_to_size_t(), tagged_tile_to_size_t(), tagged_tile_to_size_t());
|
||||
|
||||
make_edge(output_port<0>(dsyr2k_node), dpotf2_node);
|
||||
|
||||
make_edge(output_port<0>(dpotf2_node), input_port<0>(dtrsm_join));
|
||||
make_edge(output_port<1>(dsyr2k_node), input_port<1>(dtrsm_join));
|
||||
make_edge(dtrsm_join, dtrsm_node);
|
||||
|
||||
make_edge(output_port<0>(dtrsm_node), input_port<0>(dsyr2k_join));
|
||||
make_edge(output_port<1>(dtrsm_node), input_port<1>(dsyr2k_join));
|
||||
make_edge(output_port<2>(dsyr2k_node), input_port<2>(dsyr2k_join));
|
||||
make_edge(dsyr2k_join, dsyr2k_node);
|
||||
|
||||
// Now we need to send out the tiles to their first nodes
|
||||
tag_t t;
|
||||
t.tag = 0;
|
||||
t.a[0] = 0;
|
||||
t.a[1] = 0;
|
||||
t.a[2] = 0;
|
||||
|
||||
// Send to feedback input of first dpotf2
|
||||
// k == 0, j == 0, i == 0
|
||||
dpotf2_node.try_put(std::make_pair(t, tile[0][0]));
|
||||
|
||||
// Send to feedback input (port 1) of each dtrsm
|
||||
// k == 0, j == 1..p-1
|
||||
for (int j = 1; j < p; ++j) {
|
||||
t.a[1] = j;
|
||||
input_port<1>(dtrsm_join).try_put(std::make_pair(t, tile[0][j]));
|
||||
}
|
||||
|
||||
// Send to feedback input (port 2) of each dsyr2k
|
||||
// k == 0
|
||||
for (int i = 1; i < p; ++i) {
|
||||
t.a[2] = i;
|
||||
|
||||
for (int j = i; j < p; ++j) {
|
||||
t.a[1] = j;
|
||||
input_port<2>(dsyr2k_join).try_put(std::make_pair(t, tile[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
g.wait_for_all();
|
||||
}
|
||||
};
|
||||
|
||||
/************************************************************
|
||||
End data join graph based version of cholesky
|
||||
************************************************************/
|
||||
|
||||
/************************************************************
|
||||
Begin dependence graph based version of cholesky
|
||||
************************************************************/
|
||||
|
||||
typedef oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg> continue_type;
|
||||
typedef continue_type *continue_ptr_type;
|
||||
|
||||
class algorithm_depend : public algorithm {
|
||||
public:
|
||||
algorithm_depend() : algorithm("depend_cholesky", true) {}
|
||||
|
||||
protected:
|
||||
virtual void func(void *ptr, int n, int b) {
|
||||
double ***tile = (double ***)ptr;
|
||||
|
||||
const int p = n / b;
|
||||
continue_ptr_type *c = new continue_ptr_type[p];
|
||||
continue_ptr_type **t = new continue_ptr_type *[p];
|
||||
continue_ptr_type ***u = new continue_ptr_type **[p];
|
||||
|
||||
oneapi::tbb::flow::graph g;
|
||||
for (int k = p - 1; k >= 0; --k) {
|
||||
c[k] = new continue_type(g, [=](const oneapi::tbb::flow::continue_msg &) {
|
||||
call_dpotf2(tile, b, k);
|
||||
});
|
||||
t[k] = new continue_ptr_type[p];
|
||||
u[k] = new continue_ptr_type *[p];
|
||||
|
||||
for (int j = k + 1; j < p; ++j) {
|
||||
t[k][j] = new continue_type(g, [=](const oneapi::tbb::flow::continue_msg &) {
|
||||
call_dtrsm(tile, b, k, j);
|
||||
});
|
||||
make_edge(*c[k], *t[k][j]);
|
||||
u[k][j] = new continue_ptr_type[p];
|
||||
|
||||
for (int i = k + 1; i <= j; ++i) {
|
||||
u[k][j][i] = new continue_type(g, [=](const oneapi::tbb::flow::continue_msg &) {
|
||||
call_dsyr2k(tile, b, k, j, i);
|
||||
});
|
||||
|
||||
if (k < p - 2 && k + 1 != j && k + 1 != i) {
|
||||
make_edge(*u[k][j][i], *u[k + 1][j][i]);
|
||||
}
|
||||
|
||||
make_edge(*t[k][j], *u[k][j][i]);
|
||||
|
||||
if (i != j) {
|
||||
make_edge(*t[k][i], *u[k][j][i]);
|
||||
}
|
||||
|
||||
if (k < p - 2 && j > i && i == k + 1) {
|
||||
make_edge(*u[k][j][i], *t[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k != p - 1) {
|
||||
make_edge(*u[k][k + 1][k + 1], *c[k + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
c[0]->try_put(oneapi::tbb::flow::continue_msg());
|
||||
g.wait_for_all();
|
||||
|
||||
for (int k = p - 1; k >= 0; --k) {
|
||||
for (int j = k + 1; j < p; ++j) {
|
||||
for (int i = k + 1; i <= j; ++i) {
|
||||
delete u[k][j][i];
|
||||
}
|
||||
delete t[k][j];
|
||||
delete[] u[k][j];
|
||||
}
|
||||
delete c[k];
|
||||
delete[] t[k];
|
||||
delete[] u[k];
|
||||
}
|
||||
delete[] c;
|
||||
delete[] t;
|
||||
delete[] u;
|
||||
}
|
||||
}; // class algorithm_depend
|
||||
|
||||
/************************************************************
|
||||
End dependence graph based version of cholesky
|
||||
************************************************************/
|
||||
|
||||
bool process_args(int argc, char *argv[]) {
|
||||
utility::parse_cli_arguments(
|
||||
argc,
|
||||
argv,
|
||||
utility::cli_argument_pack()
|
||||
//"-h" option for displaying help is present implicitly
|
||||
.positional_arg(g_n, "size", "the row/column size of NxN matrix (size <= 46000)")
|
||||
.positional_arg(
|
||||
g_b, "blocksize", "the block size; size must be a multiple of the blocksize")
|
||||
.positional_arg(g_num_trials, "num_trials", "the number of times to run each algorithm")
|
||||
.positional_arg(
|
||||
g_output_prefix,
|
||||
"output_prefix",
|
||||
"if provided the prefix will be preappended to output files:\n"
|
||||
" output_prefix_posdef.txt\n"
|
||||
" output_prefix_X.txt; where X is the algorithm used\n"
|
||||
" if output_prefix is not provided, no output will be written")
|
||||
.positional_arg(g_alg_name,
|
||||
"algorithm",
|
||||
"name of the used algorithm - can be dpotrf, crout, depend or join")
|
||||
.positional_arg(g_num_tbb_threads, "num_tbb_threads", "number of started TBB threads")
|
||||
|
||||
.arg(g_input_file_name,
|
||||
"input_file",
|
||||
"if provided it will be read to get the input matrix")
|
||||
.arg(g_benchmark_run, "-x", "skips all validation"));
|
||||
|
||||
if (g_n > 46000) {
|
||||
printf("ERROR: invalid 'size' value (must be less or equal 46000): %d\n", g_n);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_n % g_b != 0) {
|
||||
printf("ERROR: size %d must be a multiple of the blocksize %d\n", g_n, g_b);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_n / g_b > 256) {
|
||||
// Because tile index size is 1 byte only in tag_t type
|
||||
printf("ERROR: size / blocksize must be less or equal 256, but %d / %d = %d\n",
|
||||
g_n,
|
||||
g_b,
|
||||
g_n / g_b);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_b == -1 || (g_n == -1 && g_input_file_name == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
g_num_tbb_threads = utility::get_default_num_threads();
|
||||
typedef std::map<std::string, algorithm *> algmap_t;
|
||||
algmap_t algmap;
|
||||
|
||||
// Init algorithms
|
||||
algmap.insert(std::pair<std::string, algorithm *>("dpotrf", new algorithm_dpotrf));
|
||||
algmap.insert(std::pair<std::string, algorithm *>("crout", new algorithm_crout));
|
||||
algmap.insert(std::pair<std::string, algorithm *>("depend", new algorithm_depend));
|
||||
algmap.insert(std::pair<std::string, algorithm *>("join", new algorithm_join));
|
||||
|
||||
if (!process_args(argc, argv)) {
|
||||
printf("ERROR: Invalid arguments. Run: %s -h\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
|
||||
g_num_tbb_threads);
|
||||
double *A = nullptr;
|
||||
|
||||
// Read input matrix
|
||||
matrix_init(A, g_n, g_input_file_name);
|
||||
|
||||
// Write input matrix if output_prefix is set and we didn't read from a file
|
||||
if (!g_input_file_name && g_output_prefix) {
|
||||
std::string s(g_output_prefix);
|
||||
s += "_posdef.txt";
|
||||
matrix_write(A, g_n, s.c_str());
|
||||
}
|
||||
|
||||
if (g_alg_name.empty()) {
|
||||
for (algmap_t::iterator i = algmap.begin(); i != algmap.end(); ++i) {
|
||||
algorithm *const alg = i->second;
|
||||
(*alg)(A, g_n, g_b, g_num_trials);
|
||||
}
|
||||
}
|
||||
else {
|
||||
algmap_t::iterator alg_iter = algmap.find(g_alg_name);
|
||||
|
||||
if (alg_iter != algmap.end()) {
|
||||
algorithm *const alg = alg_iter->second;
|
||||
(*alg)(A, g_n, g_b, g_num_trials);
|
||||
}
|
||||
else {
|
||||
printf("ERROR: Invalid algorithm name: %s\n", g_alg_name.c_str());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(A);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <mkl_cblas.h>
|
||||
|
||||
static void posdef_gen(double *A, int n) {
|
||||
/* Allocate memory for the matrix and its transpose */
|
||||
double *L = (double *)calloc(sizeof(double), n * n);
|
||||
assert(L);
|
||||
|
||||
double *LT = (double *)calloc(sizeof(double), n * n);
|
||||
assert(LT);
|
||||
|
||||
memset(A, 0, sizeof(double) * n * n);
|
||||
|
||||
/* Generate a conditioned matrix and fill it with random numbers */
|
||||
for (int j = 0; j < n; ++j) {
|
||||
for (int k = 0; k < j; ++k) {
|
||||
// The initial value has to be between [0,1].
|
||||
L[k * n + j] =
|
||||
(((j * k) / ((double)(j + 1)) / ((double)(k + 2)) * 2.0) - 1.0) / ((double)n);
|
||||
}
|
||||
|
||||
L[j * n + j] = 1;
|
||||
}
|
||||
|
||||
/* Compute transpose of the matrix */
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (int j = 0; j < n; ++j) {
|
||||
LT[j * n + i] = L[i * n + j];
|
||||
}
|
||||
}
|
||||
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1, L, n, LT, n, 0, A, n);
|
||||
|
||||
free(L);
|
||||
free(LT);
|
||||
}
|
||||
|
||||
// Read the matrix from the input file
|
||||
void matrix_init(double *&A, int &n, const char *fname) {
|
||||
if (fname) {
|
||||
int i;
|
||||
int j;
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
if (fp == nullptr) {
|
||||
fprintf(stderr, "\nFile does not exist\n");
|
||||
std::exit(0);
|
||||
}
|
||||
if (fscanf(fp, "%d", &n) <= 0) {
|
||||
fprintf(stderr, "\nCouldn't read n from %s\n", fname);
|
||||
std::exit(-1);
|
||||
}
|
||||
A = (double *)calloc(sizeof(double), n * n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j <= i; ++j) {
|
||||
if (fscanf(fp, "%lf ", &A[i * n + j]) <= 0) {
|
||||
fprintf(stderr, "\nMatrix size incorrect %i %i\n", i, j);
|
||||
std::exit(-1);
|
||||
}
|
||||
if (i != j) {
|
||||
A[j * n + i] = A[i * n + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
else {
|
||||
A = (double *)calloc(sizeof(double), n * n);
|
||||
posdef_gen(A, n);
|
||||
}
|
||||
}
|
||||
|
||||
// write matrix to file
|
||||
void matrix_write(double *A, int n, const char *fname, bool is_triangular = false) {
|
||||
if (fname) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
FILE *fp = nullptr;
|
||||
|
||||
fp = fopen(fname, "w");
|
||||
if (fp == nullptr) {
|
||||
fprintf(stderr, "\nCould not open file %s for writing.\n", fname);
|
||||
std::exit(0);
|
||||
}
|
||||
fprintf(fp, "%d\n", n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j <= i; ++j) {
|
||||
fprintf(fp, "%lf ", A[j * n + i]);
|
||||
}
|
||||
if (!is_triangular) {
|
||||
for (; j < n; ++j) {
|
||||
fprintf(fp, "%lf ", A[i * n + j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; j < n; ++j) {
|
||||
fprintf(fp, "%lf ", 0.0);
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
if (is_triangular) {
|
||||
fprintf(fp, "\n");
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < i; ++j) {
|
||||
fprintf(fp, "%lf ", 0.0);
|
||||
}
|
||||
for (; j < n; ++j) {
|
||||
fprintf(fp, "%lf ", A[i * n + j]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(dining_philosophers CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
add_executable(dining_philosophers dining_philosophers.cpp)
|
||||
|
||||
target_link_libraries(dining_philosophers TBB::tbb Threads::Threads)
|
||||
target_compile_options(dining_philosophers PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:dining_philosophers>")
|
||||
set(ARGS auto 5)
|
||||
set(LIGHT_ARGS auto 3)
|
||||
|
||||
add_execution_target(run_dining_philosophers dining_philosophers ${EXECUTABLE} "${ARGS}")
|
||||
add_execution_target(light_test_dining_philosophers dining_philosophers ${EXECUTABLE} "${LIGHT_ARGS}")
|
||||
@@ -0,0 +1,25 @@
|
||||
# Dining_philosophers sample
|
||||
The Dining Philosophers problem demonstrates `oneapi::tbb::flow` and the use of the reserving `join_node` to solve the potential deadlock.
|
||||
|
||||
This program runs some number of philosophers in parallel, each thinking and then waiting for chopsticks to be available before eating. Eating and thinking are implemented with `sleep()`. The chopstick positions are represented by a `queue_node` with one item.
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_dining_philosophers` - executes the example with predefined parameters.
|
||||
* `make light_test_dining_philosophers` - executes the example with suggested parameters to reduce execution time.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
dining_philosophers [n-of_threads=value] [n-of-philosophers=value] [verbose] [-h] [n-of_threads [n-of-philosophers]]
|
||||
```
|
||||
* `-h` - prints the help for command line options.
|
||||
* `n-of_threads` - number of threads to use; a range of the form low\[:high\[:(+|*|#)step\]\], where low and optional high are non-negative integers or 'auto' for the default choice, and optional step expression specifies how thread numbers are chosen within the range.
|
||||
* `n-of-philosophers` - how many philosophers, from 2-26.
|
||||
* `verbose` - prints diagnostic output to screen.
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#if _MSC_VER
|
||||
// Suppress "decorated name length exceeded, name was truncated" warning
|
||||
#pragma warning(disable : 4503)
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <tuple>
|
||||
|
||||
#include "oneapi/tbb/flow_graph.h"
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
#include "oneapi/tbb/spin_mutex.h"
|
||||
#include "oneapi/tbb/global_control.h"
|
||||
|
||||
#include "common/utility/utility.hpp"
|
||||
#include "common/utility/get_default_num_threads.hpp"
|
||||
|
||||
// Each philosopher is an object, and is invoked in the think() function_node, the
|
||||
// eat() function_node and forward() multifunction_node.
|
||||
//
|
||||
// The graph is constructed, and each think() function_node is started with a continue_msg.
|
||||
//
|
||||
// The philosopher will think, then gather two chopsticks, eat, place the chopsticks back,
|
||||
// and if they have not completed the required number of cycles, will start to think() again
|
||||
// by sending a continue_msg to their corresponding think() function_node.
|
||||
//
|
||||
// The reserving join has as its inputs the left and right chopstick queues an a queue
|
||||
// that stores the continue_msg emitted by the function_node after think()ing is done.
|
||||
// When all three inputs are available, a tuple of the inputs will be forwarded to the
|
||||
// eat() function_node. The output of the eat() function_node is sent to the forward()
|
||||
// multifunction_node.
|
||||
|
||||
const std::chrono::seconds think_time(1);
|
||||
const std::chrono::seconds eat_time(1);
|
||||
const int num_times = 10;
|
||||
|
||||
oneapi::tbb::tick_count t0;
|
||||
bool verbose = false;
|
||||
|
||||
const char *names[] = { "Archimedes", "Bakunin", "Confucius", "Democritus", "Euclid",
|
||||
"Favorinus", "Geminus", "Heraclitus", "Ichthyas", "Jason of Nysa",
|
||||
"Kant", "Lavrov", "Metrocles", "Nausiphanes", "Onatas",
|
||||
"Phaedrus", "Quillot", "Russell", "Socrates", "Thales",
|
||||
"Udayana", "Vernadsky", "Wittgenstein", "Xenophilus", "Yen Yuan",
|
||||
"Zenodotus" };
|
||||
const int NumPhilosophers = sizeof(names) / sizeof(char *);
|
||||
|
||||
struct RunOptions {
|
||||
utility::thread_number_range threads;
|
||||
int number_of_philosophers;
|
||||
bool silent;
|
||||
RunOptions(utility::thread_number_range threads_, int number_of_philosophers_, bool silent_)
|
||||
: threads(threads_),
|
||||
number_of_philosophers(number_of_philosophers_),
|
||||
silent(silent_) {}
|
||||
};
|
||||
|
||||
RunOptions ParseCommandLine(int argc, char *argv[]) {
|
||||
int auto_threads = utility::get_default_num_threads();
|
||||
utility::thread_number_range threads(
|
||||
utility::get_default_num_threads, auto_threads, auto_threads);
|
||||
int nPhilosophers = 5;
|
||||
bool verbose = false;
|
||||
char charbuf[100];
|
||||
std::sprintf(charbuf, "%d", NumPhilosophers);
|
||||
std::string pCount = "how many philosophers, from 2-";
|
||||
pCount += charbuf;
|
||||
|
||||
utility::cli_argument_pack cli_pack;
|
||||
cli_pack.positional_arg(threads, "n-of_threads", utility::thread_number_range_desc)
|
||||
.positional_arg(nPhilosophers, "n-of-philosophers", pCount)
|
||||
.arg(verbose, "verbose", "verbose output");
|
||||
utility::parse_cli_arguments(argc, argv, cli_pack);
|
||||
if (nPhilosophers < 2 || nPhilosophers > NumPhilosophers) {
|
||||
std::cout << "Number of philosophers (" << nPhilosophers
|
||||
<< ") out of range [2:" << NumPhilosophers << "]\n";
|
||||
std::cout << cli_pack.usage_string(argv[0]) << std::flush;
|
||||
std::exit(-1);
|
||||
}
|
||||
return RunOptions(threads, nPhilosophers, !verbose);
|
||||
}
|
||||
|
||||
oneapi::tbb::spin_mutex my_mutex;
|
||||
|
||||
class chopstick {};
|
||||
|
||||
typedef std::tuple<oneapi::tbb::flow::continue_msg, chopstick, chopstick> join_output;
|
||||
typedef oneapi::tbb::flow::join_node<join_output, oneapi::tbb::flow::reserving> join_node_type;
|
||||
|
||||
typedef oneapi::tbb::flow::function_node<oneapi::tbb::flow::continue_msg,
|
||||
oneapi::tbb::flow::continue_msg>
|
||||
think_node_type;
|
||||
typedef oneapi::tbb::flow::function_node<join_output, oneapi::tbb::flow::continue_msg>
|
||||
eat_node_type;
|
||||
typedef oneapi::tbb::flow::multifunction_node<oneapi::tbb::flow::continue_msg, join_output>
|
||||
forward_node_type;
|
||||
|
||||
class philosopher {
|
||||
public:
|
||||
philosopher(const char *name) : my_name(name), my_count(num_times) {}
|
||||
|
||||
~philosopher() {}
|
||||
|
||||
void check();
|
||||
const char *name() const {
|
||||
return my_name;
|
||||
}
|
||||
|
||||
private:
|
||||
friend std::ostream &operator<<(std::ostream &o, philosopher const &p);
|
||||
|
||||
const char *my_name;
|
||||
int my_count;
|
||||
|
||||
friend class think_node_body;
|
||||
friend class eat_node_body;
|
||||
friend class forward_node_body;
|
||||
|
||||
void think();
|
||||
void eat();
|
||||
void forward(const oneapi::tbb::flow::continue_msg &in,
|
||||
forward_node_type::output_ports_type &out_ports);
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, philosopher const &p) {
|
||||
o << "< philosopher[" << reinterpret_cast<uintptr_t>(const_cast<philosopher *>(&p)) << "] "
|
||||
<< p.name() << ", my_count=" << p.my_count;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
class think_node_body {
|
||||
philosopher &my_philosopher;
|
||||
|
||||
public:
|
||||
think_node_body(philosopher &p) : my_philosopher(p) {}
|
||||
think_node_body(const think_node_body &other) : my_philosopher(other.my_philosopher) {}
|
||||
oneapi::tbb::flow::continue_msg operator()(oneapi::tbb::flow::continue_msg /*m*/) {
|
||||
my_philosopher.think();
|
||||
return oneapi::tbb::flow::continue_msg();
|
||||
}
|
||||
};
|
||||
|
||||
class eat_node_body {
|
||||
philosopher &my_philosopher;
|
||||
|
||||
public:
|
||||
eat_node_body(philosopher &p) : my_philosopher(p) {}
|
||||
eat_node_body(const eat_node_body &other) : my_philosopher(other.my_philosopher) {}
|
||||
oneapi::tbb::flow::continue_msg operator()(const join_output &in) {
|
||||
my_philosopher.eat();
|
||||
return oneapi::tbb::flow::continue_msg();
|
||||
}
|
||||
};
|
||||
|
||||
class forward_node_body {
|
||||
philosopher &my_philosopher;
|
||||
|
||||
public:
|
||||
forward_node_body(philosopher &p) : my_philosopher(p) {}
|
||||
forward_node_body(const forward_node_body &other) : my_philosopher(other.my_philosopher) {}
|
||||
void operator()(const oneapi::tbb::flow::continue_msg &in,
|
||||
forward_node_type::output_ports_type &out) {
|
||||
my_philosopher.forward(in, out);
|
||||
}
|
||||
};
|
||||
|
||||
void philosopher::check() {
|
||||
if (my_count != 0) {
|
||||
std::printf("ERROR: philosopher %s still had to run %d more times\n", name(), my_count);
|
||||
std::exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void philosopher::forward(const oneapi::tbb::flow::continue_msg & /*in*/,
|
||||
forward_node_type::output_ports_type &out_ports) {
|
||||
if (my_count < 0)
|
||||
abort();
|
||||
--my_count;
|
||||
(void)std::get<1>(out_ports).try_put(chopstick());
|
||||
(void)std::get<2>(out_ports).try_put(chopstick());
|
||||
if (my_count > 0) {
|
||||
(void)std::get<0>(out_ports).try_put(
|
||||
oneapi::tbb::flow::continue_msg()); //start thinking again
|
||||
}
|
||||
else {
|
||||
if (verbose) {
|
||||
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
|
||||
std::printf("%s has left the building\n", name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void philosopher::eat() {
|
||||
if (verbose) {
|
||||
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
|
||||
std::printf("%s eating\n", name());
|
||||
}
|
||||
std::this_thread::sleep_for(eat_time);
|
||||
if (verbose) {
|
||||
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
|
||||
std::printf("%s done eating\n", name());
|
||||
}
|
||||
}
|
||||
|
||||
void philosopher::think() {
|
||||
if (verbose) {
|
||||
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
|
||||
std::printf("%s thinking\n", name());
|
||||
}
|
||||
std::this_thread::sleep_for(think_time);
|
||||
if (verbose) {
|
||||
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
|
||||
std::printf("%s done thinking\n", name());
|
||||
}
|
||||
}
|
||||
|
||||
typedef oneapi::tbb::flow::queue_node<oneapi::tbb::flow::continue_msg> thinking_done_type;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
using oneapi::tbb::flow::make_edge;
|
||||
using oneapi::tbb::flow::input_port;
|
||||
using oneapi::tbb::flow::output_port;
|
||||
|
||||
oneapi::tbb::tick_count main_time = oneapi::tbb::tick_count::now();
|
||||
int num_threads;
|
||||
int num_philosophers;
|
||||
|
||||
RunOptions options = ParseCommandLine(argc, argv);
|
||||
num_philosophers = options.number_of_philosophers;
|
||||
verbose = !options.silent;
|
||||
|
||||
for (num_threads = options.threads.first; num_threads <= options.threads.last;
|
||||
num_threads = options.threads.step(num_threads)) {
|
||||
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
|
||||
num_threads);
|
||||
|
||||
oneapi::tbb::flow::graph g;
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "\n"
|
||||
<< num_philosophers << " philosophers with " << num_threads << " threads"
|
||||
<< "\n"
|
||||
<< "\n";
|
||||
}
|
||||
t0 = oneapi::tbb::tick_count::now();
|
||||
|
||||
std::vector<oneapi::tbb::flow::queue_node<chopstick>> places(
|
||||
num_philosophers, oneapi::tbb::flow::queue_node<chopstick>(g));
|
||||
std::vector<philosopher> philosophers;
|
||||
philosophers.reserve(num_philosophers);
|
||||
std::vector<think_node_type *> think_nodes;
|
||||
think_nodes.reserve(num_philosophers);
|
||||
std::vector<thinking_done_type> done_vector(num_philosophers, thinking_done_type(g));
|
||||
std::vector<join_node_type> join_vector(num_philosophers, join_node_type(g));
|
||||
std::vector<eat_node_type *> eat_nodes;
|
||||
eat_nodes.reserve(num_philosophers);
|
||||
std::vector<forward_node_type *> forward_nodes;
|
||||
forward_nodes.reserve(num_philosophers);
|
||||
for (int i = 0; i < num_philosophers; ++i) {
|
||||
places[i].try_put(chopstick());
|
||||
philosophers.push_back(
|
||||
philosopher(names[i])); // allowed because of default generated assignment
|
||||
if (verbose) {
|
||||
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
|
||||
std::cout << "Built philosopher " << philosophers[i] << "\n";
|
||||
}
|
||||
think_nodes.push_back(new think_node_type(
|
||||
g, oneapi::tbb::flow::unlimited, think_node_body(philosophers[i])));
|
||||
eat_nodes.push_back(
|
||||
new eat_node_type(g, oneapi::tbb::flow::unlimited, eat_node_body(philosophers[i])));
|
||||
forward_nodes.push_back(new forward_node_type(
|
||||
g, oneapi::tbb::flow::unlimited, forward_node_body(philosophers[i])));
|
||||
}
|
||||
|
||||
// attach chopstick buffers and think function_nodes to joins
|
||||
for (int i = 0; i < num_philosophers; ++i) {
|
||||
make_edge(*think_nodes[i], done_vector[i]);
|
||||
make_edge(done_vector[i], input_port<0>(join_vector[i]));
|
||||
make_edge(places[i], input_port<1>(join_vector[i])); // left chopstick
|
||||
make_edge(places[(i + 1) % num_philosophers],
|
||||
input_port<2>(join_vector[i])); // right chopstick
|
||||
make_edge(join_vector[i], *eat_nodes[i]);
|
||||
make_edge(*eat_nodes[i], *forward_nodes[i]);
|
||||
make_edge(output_port<0>(*forward_nodes[i]), *think_nodes[i]);
|
||||
make_edge(output_port<1>(*forward_nodes[i]), places[i]);
|
||||
make_edge(output_port<2>(*forward_nodes[i]), places[(i + 1) % num_philosophers]);
|
||||
}
|
||||
|
||||
// start all the philosophers thinking
|
||||
for (int i = 0; i < num_philosophers; ++i)
|
||||
think_nodes[i]->try_put(oneapi::tbb::flow::continue_msg());
|
||||
|
||||
g.wait_for_all();
|
||||
|
||||
oneapi::tbb::tick_count t1 = oneapi::tbb::tick_count::now();
|
||||
if (verbose)
|
||||
std::cout << "\n"
|
||||
<< num_philosophers << " philosophers with " << num_threads
|
||||
<< " threads have taken " << (t1 - t0).seconds() << "seconds"
|
||||
<< "\n";
|
||||
|
||||
for (int i = 0; i < num_philosophers; ++i)
|
||||
philosophers[i].check();
|
||||
|
||||
for (int i = 0; i < num_philosophers; ++i) {
|
||||
delete think_nodes[i];
|
||||
delete eat_nodes[i];
|
||||
delete forward_nodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - main_time).seconds());
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(fgbzip2 CXX)
|
||||
|
||||
include(../../common/cmake/common.cmake)
|
||||
|
||||
set_common_project_settings(tbb)
|
||||
|
||||
add_executable(fgbzip2
|
||||
blocksort.cpp
|
||||
bzlib.cpp
|
||||
compress.cpp
|
||||
crctable.cpp
|
||||
decompress.cpp
|
||||
fgbzip2.cpp
|
||||
huffman.cpp
|
||||
randtable.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(fgbzip2 TBB::tbb Threads::Threads)
|
||||
target_compile_options(fgbzip2 PRIVATE ${TBB_CXX_STD_FLAG})
|
||||
|
||||
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL IntelLLVM)
|
||||
target_compile_options(fgbzip2 PRIVATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
endif()
|
||||
|
||||
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Intel)
|
||||
if (COMMAND target_link_options)
|
||||
target_link_options(fgbzip2 PRIVATE /FORCE:MULTIPLE /INCREMENTAL:NO)
|
||||
else()
|
||||
set_target_properties(fgbzip2 PROPERTIES LINK_FLAGS /FORCE:MULTIPLE /INCREMENTAL:NO)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(EXECUTABLE "$<TARGET_FILE:fgbzip2>")
|
||||
set(ARGS -b=9 -async "$<TARGET_FILE:fgbzip2>")
|
||||
|
||||
add_execution_target(run_fgbzip2 fgbzip2 ${EXECUTABLE} "${ARGS}")
|
||||
add_execution_target(perf_run_fgbzip2 fgbzip2 ${EXECUTABLE} "${ARGS}")
|
||||
@@ -0,0 +1,28 @@
|
||||
# fgbzip2 sample
|
||||
fgbzip2 is a parallel implementation of bzip2 block-sorting file compressor that uses `oneapi::tbb::flow`. The output of this application is fully compatible with bzip2 v1.0.6 or newer.
|
||||
|
||||
This example includes software developed by Julian R Seward. See here for copyright information.
|
||||
It exemplifies support for asynchronous capabilities in the flow graph API.
|
||||
|
||||
## Building the example
|
||||
```
|
||||
cmake <path_to_example>
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
### Predefined make targets
|
||||
* `make run_fgbzip2` - executes the example with predefined parameters.
|
||||
* `make perf_run_fgbzip2` - executes the example with suggested parameters to measure the oneTBB performance.
|
||||
|
||||
### Application parameters
|
||||
Usage:
|
||||
```
|
||||
fgbzip2 [-b=value] [-v] [-l=value] [-async] [filename=value] [-h] [filename]
|
||||
```
|
||||
* `-h` - prints the help for command line options.
|
||||
* `-b` - block size in 100 KB chunks, [1 .. 9].
|
||||
* `-v` - prints diagnostic output to screen.
|
||||
* `-l` - use memory limit for compression algorithm with 1 MB (minimum) granularity.
|
||||
* `-async` - use graph `async_node`-based implementation.
|
||||
* `filename` - name of the file to compress.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Public header file for the library. ---*/
|
||||
/*--- bzlib.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#ifndef _BZLIB_H
|
||||
#define _BZLIB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BZ_RUN 0
|
||||
#define BZ_FLUSH 1
|
||||
#define BZ_FINISH 2
|
||||
|
||||
#define BZ_OK 0
|
||||
#define BZ_RUN_OK 1
|
||||
#define BZ_FLUSH_OK 2
|
||||
#define BZ_FINISH_OK 3
|
||||
#define BZ_STREAM_END 4
|
||||
#define BZ_SEQUENCE_ERROR (-1)
|
||||
#define BZ_PARAM_ERROR (-2)
|
||||
#define BZ_MEM_ERROR (-3)
|
||||
#define BZ_DATA_ERROR (-4)
|
||||
#define BZ_DATA_ERROR_MAGIC (-5)
|
||||
#define BZ_IO_ERROR (-6)
|
||||
#define BZ_UNEXPECTED_EOF (-7)
|
||||
#define BZ_OUTBUFF_FULL (-8)
|
||||
#define BZ_CONFIG_ERROR (-9)
|
||||
|
||||
typedef struct {
|
||||
char* next_in;
|
||||
unsigned int avail_in;
|
||||
unsigned int total_in_lo32;
|
||||
unsigned int total_in_hi32;
|
||||
|
||||
char* next_out;
|
||||
unsigned int avail_out;
|
||||
unsigned int total_out_lo32;
|
||||
unsigned int total_out_hi32;
|
||||
|
||||
void* state;
|
||||
|
||||
void* (*bzalloc)(void*, int, int);
|
||||
void (*bzfree)(void*, void*);
|
||||
void* opaque;
|
||||
} bz_stream;
|
||||
|
||||
#ifndef BZ_IMPORT
|
||||
#define BZ_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
/* Need a definitition for FILE */
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#ifdef small
|
||||
/* windows.h define small to char */
|
||||
#undef small
|
||||
#endif
|
||||
#ifdef BZ_EXPORT
|
||||
#define BZ_API(func) WINAPI func
|
||||
#define BZ_EXTERN extern
|
||||
#else
|
||||
/* import windows dll dynamically */
|
||||
#define BZ_API(func) (WINAPI * func)
|
||||
#define BZ_EXTERN
|
||||
#endif
|
||||
#else
|
||||
#define BZ_API(func) func
|
||||
#define BZ_EXTERN extern
|
||||
#endif
|
||||
|
||||
/*-- Core (low-level) library functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressInit)(bz_stream* strm,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompress)(bz_stream* strm, int action);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd)(bz_stream* strm);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit)(bz_stream* strm, int verbosity, int small);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompress)(bz_stream* strm);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd)(bz_stream* strm);
|
||||
|
||||
/*-- High(er) level library functions --*/
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
#define BZ_MAX_UNUSED 5000
|
||||
|
||||
typedef void BZFILE;
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(
|
||||
BZ2_bzReadOpen)(int* bzerror, FILE* f, int verbosity, int small, void* unused, int nUnused);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadClose)(int* bzerror, BZFILE* b);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused)(int* bzerror, BZFILE* b, void** unused, int* nUnused);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzRead)(int* bzerror, BZFILE* b, void* buf, int len);
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(
|
||||
BZ2_bzWriteOpen)(int* bzerror, FILE* f, int blockSize100k, int verbosity, int workFactor);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWrite)(int* bzerror, BZFILE* b, void* buf, int len);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose)(int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in,
|
||||
unsigned int* nbytes_out);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64)(int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in_lo32,
|
||||
unsigned int* nbytes_in_hi32,
|
||||
unsigned int* nbytes_out_lo32,
|
||||
unsigned int* nbytes_out_hi32);
|
||||
#endif
|
||||
|
||||
/*-- Utility functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress)(char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress)(char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int small,
|
||||
int verbosity);
|
||||
|
||||
/*--
|
||||
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
|
||||
to support better zlib compatibility.
|
||||
This code is not _officially_ part of libbzip2 (yet);
|
||||
I haven't tested it, documented it, or considered the
|
||||
threading-safeness of it.
|
||||
If this code breaks, please contact both Yoshioka and me.
|
||||
--*/
|
||||
|
||||
BZ_EXTERN const char* BZ_API(BZ2_bzlibVersion)(void);
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzopen)(const char* path, const char* mode);
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzdopen)(int fd, const char* mode);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzread)(BZFILE* b, void* buf, int len);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzwrite)(BZFILE* b, void* buf, int len);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzflush)(BZFILE* b);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzclose)(BZFILE* b);
|
||||
|
||||
BZ_EXTERN const char* BZ_API(BZ2_bzerror)(BZFILE* b, int* errnum);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end bzlib.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Private header file for the library. ---*/
|
||||
/*--- bzlib_private.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#ifndef _BZLIB_PRIVATE_H
|
||||
#define _BZLIB_PRIVATE_H
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "bzlib.hpp"
|
||||
|
||||
/*-- General stuff. --*/
|
||||
|
||||
#define BZ_VERSION "1.0.6, 6-Sept-2010"
|
||||
|
||||
typedef char Char;
|
||||
typedef unsigned char Bool;
|
||||
typedef unsigned char UChar;
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#define True ((Bool)1)
|
||||
#define False ((Bool)0)
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __inline__ /* */
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
|
||||
extern void BZ2_bz__AssertH__fail(int errcode);
|
||||
#define AssertH(cond, errcode) \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
BZ2_bz__AssertH__fail(errcode); \
|
||||
}
|
||||
|
||||
#if BZ_DEBUG
|
||||
#define AssertD(cond, msg) \
|
||||
{ \
|
||||
if (!(cond)) { \
|
||||
fprintf(stderr, "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg); \
|
||||
std::exit(-1); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define AssertD(cond, msg) /* */
|
||||
#endif
|
||||
|
||||
#define VPrintf0(zf) fprintf(stderr, zf)
|
||||
#define VPrintf1(zf, za1) fprintf(stderr, zf, za1)
|
||||
#define VPrintf2(zf, za1, za2) fprintf(stderr, zf, za1, za2)
|
||||
#define VPrintf3(zf, za1, za2, za3) fprintf(stderr, zf, za1, za2, za3)
|
||||
#define VPrintf4(zf, za1, za2, za3, za4) fprintf(stderr, zf, za1, za2, za3, za4)
|
||||
#define VPrintf5(zf, za1, za2, za3, za4, za5) fprintf(stderr, zf, za1, za2, za3, za4, za5)
|
||||
|
||||
#else
|
||||
|
||||
extern void bz_internal_error(int errcode);
|
||||
#define AssertH(cond, errcode) \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
bz_internal_error(errcode); \
|
||||
}
|
||||
#define AssertD(cond, msg) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VPrintf0(zf) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VPrintf1(zf, za1) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VPrintf2(zf, za1, za2) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VPrintf3(zf, za1, za2, za3) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VPrintf4(zf, za1, za2, za3, za4) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define VPrintf5(zf, za1, za2, za3, za4, za5) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque, (nnn), 1)
|
||||
#define BZFREE(ppp) (strm->bzfree)(strm->opaque, (ppp))
|
||||
|
||||
/*-- Header bytes. --*/
|
||||
|
||||
#define BZ_HDR_B 0x42 /* 'B' */
|
||||
#define BZ_HDR_Z 0x5a /* 'Z' */
|
||||
#define BZ_HDR_h 0x68 /* 'h' */
|
||||
#define BZ_HDR_0 0x30 /* '0' */
|
||||
|
||||
/*-- Constants for the back end. --*/
|
||||
|
||||
#define BZ_MAX_ALPHA_SIZE 258
|
||||
#define BZ_MAX_CODE_LEN 23
|
||||
|
||||
#define BZ_RUNA 0
|
||||
#define BZ_RUNB 1
|
||||
|
||||
#define BZ_N_GROUPS 6
|
||||
#define BZ_G_SIZE 50
|
||||
#define BZ_N_ITERS 4
|
||||
|
||||
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
|
||||
|
||||
/*-- Stuff for randomising repetitive blocks. --*/
|
||||
|
||||
extern Int32 BZ2_rNums[512];
|
||||
|
||||
#define BZ_RAND_DECLS \
|
||||
Int32 rNToGo; \
|
||||
Int32 rTPos
|
||||
|
||||
#define BZ_RAND_INIT_MASK \
|
||||
s->rNToGo = 0; \
|
||||
s->rTPos = 0
|
||||
|
||||
#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
|
||||
|
||||
#define BZ_RAND_UPD_MASK \
|
||||
if (s->rNToGo == 0) { \
|
||||
s->rNToGo = BZ2_rNums[s->rTPos]; \
|
||||
s->rTPos++; \
|
||||
if (s->rTPos == 512) \
|
||||
s->rTPos = 0; \
|
||||
} \
|
||||
s->rNToGo--;
|
||||
|
||||
/*-- Stuff for doing CRCs. --*/
|
||||
|
||||
extern UInt32 BZ2_crc32Table[256];
|
||||
|
||||
#define BZ_INITIALISE_CRC(crcVar) \
|
||||
{ crcVar = 0xffffffffL; }
|
||||
|
||||
#define BZ_FINALISE_CRC(crcVar) \
|
||||
{ crcVar = ~(crcVar); }
|
||||
|
||||
#define BZ_UPDATE_CRC(crcVar, cha) \
|
||||
{ crcVar = (crcVar << 8) ^ BZ2_crc32Table[(crcVar >> 24) ^ ((UChar)cha)]; }
|
||||
|
||||
/*-- States and modes for compression. --*/
|
||||
|
||||
#define BZ_M_IDLE 1
|
||||
#define BZ_M_RUNNING 2
|
||||
#define BZ_M_FLUSHING 3
|
||||
#define BZ_M_FINISHING 4
|
||||
|
||||
#define BZ_S_OUTPUT 1
|
||||
#define BZ_S_INPUT 2
|
||||
|
||||
#define BZ_N_RADIX 2
|
||||
#define BZ_N_QSORT 12
|
||||
#define BZ_N_SHELL 18
|
||||
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
|
||||
|
||||
/*-- Structure holding all the compression-side stuff. --*/
|
||||
|
||||
typedef struct {
|
||||
/* pointer back to the struct bz_stream */
|
||||
bz_stream* strm;
|
||||
|
||||
/* mode this stream is in, and whether inputting */
|
||||
/* or outputting data */
|
||||
Int32 mode;
|
||||
Int32 state;
|
||||
|
||||
/* remembers avail_in when flush/finish requested */
|
||||
UInt32 avail_in_expect;
|
||||
|
||||
/* for doing the block sorting */
|
||||
UInt32* arr1;
|
||||
UInt32* arr2;
|
||||
UInt32* ftab;
|
||||
Int32 origPtr;
|
||||
|
||||
/* aliases for arr1 and arr2 */
|
||||
UInt32* ptr;
|
||||
UChar* block;
|
||||
UInt16* mtfv;
|
||||
UChar* zbits;
|
||||
|
||||
/* for deciding when to use the fallback sorting algorithm */
|
||||
Int32 workFactor;
|
||||
|
||||
/* run-length-encoding of the input */
|
||||
UInt32 state_in_ch;
|
||||
Int32 state_in_len;
|
||||
BZ_RAND_DECLS;
|
||||
|
||||
/* input and output limits and current posns */
|
||||
Int32 nblock;
|
||||
Int32 nblockMAX;
|
||||
Int32 numZ;
|
||||
Int32 state_out_pos;
|
||||
|
||||
/* map of bytes used in block */
|
||||
Int32 nInUse;
|
||||
Bool inUse[256];
|
||||
UChar unseqToSeq[256];
|
||||
|
||||
/* the buffer for bit stream creation */
|
||||
UInt32 bsBuff;
|
||||
Int32 bsLive;
|
||||
|
||||
/* block and combined CRCs */
|
||||
UInt32 blockCRC;
|
||||
UInt32 combinedCRC;
|
||||
|
||||
/* misc administratium */
|
||||
Int32 verbosity;
|
||||
Int32 blockNo;
|
||||
Int32 blockSize100k;
|
||||
|
||||
/* stuff for coding the MTF values */
|
||||
Int32 nMTF;
|
||||
Int32 mtfFreq[BZ_MAX_ALPHA_SIZE];
|
||||
UChar selector[BZ_MAX_SELECTORS];
|
||||
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||
|
||||
UChar len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
/* second dimension: only 3 needed; 4 makes index calculations faster */
|
||||
UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
|
||||
|
||||
} EState;
|
||||
|
||||
/*-- externs for compression. --*/
|
||||
|
||||
extern void BZ2_blockSort(EState*);
|
||||
|
||||
extern void BZ2_compressBlock(EState*, Bool);
|
||||
|
||||
extern void BZ2_bsInitWrite(EState*);
|
||||
|
||||
extern void BZ2_hbAssignCodes(Int32*, UChar*, Int32, Int32, Int32);
|
||||
|
||||
extern void BZ2_hbMakeCodeLengths(UChar*, Int32*, Int32, Int32);
|
||||
|
||||
/*-- states for decompression. --*/
|
||||
|
||||
#define BZ_X_IDLE 1
|
||||
#define BZ_X_OUTPUT 2
|
||||
|
||||
#define BZ_X_MAGIC_1 10
|
||||
#define BZ_X_MAGIC_2 11
|
||||
#define BZ_X_MAGIC_3 12
|
||||
#define BZ_X_MAGIC_4 13
|
||||
#define BZ_X_BLKHDR_1 14
|
||||
#define BZ_X_BLKHDR_2 15
|
||||
#define BZ_X_BLKHDR_3 16
|
||||
#define BZ_X_BLKHDR_4 17
|
||||
#define BZ_X_BLKHDR_5 18
|
||||
#define BZ_X_BLKHDR_6 19
|
||||
#define BZ_X_BCRC_1 20
|
||||
#define BZ_X_BCRC_2 21
|
||||
#define BZ_X_BCRC_3 22
|
||||
#define BZ_X_BCRC_4 23
|
||||
#define BZ_X_RANDBIT 24
|
||||
#define BZ_X_ORIGPTR_1 25
|
||||
#define BZ_X_ORIGPTR_2 26
|
||||
#define BZ_X_ORIGPTR_3 27
|
||||
#define BZ_X_MAPPING_1 28
|
||||
#define BZ_X_MAPPING_2 29
|
||||
#define BZ_X_SELECTOR_1 30
|
||||
#define BZ_X_SELECTOR_2 31
|
||||
#define BZ_X_SELECTOR_3 32
|
||||
#define BZ_X_CODING_1 33
|
||||
#define BZ_X_CODING_2 34
|
||||
#define BZ_X_CODING_3 35
|
||||
#define BZ_X_MTF_1 36
|
||||
#define BZ_X_MTF_2 37
|
||||
#define BZ_X_MTF_3 38
|
||||
#define BZ_X_MTF_4 39
|
||||
#define BZ_X_MTF_5 40
|
||||
#define BZ_X_MTF_6 41
|
||||
#define BZ_X_ENDHDR_2 42
|
||||
#define BZ_X_ENDHDR_3 43
|
||||
#define BZ_X_ENDHDR_4 44
|
||||
#define BZ_X_ENDHDR_5 45
|
||||
#define BZ_X_ENDHDR_6 46
|
||||
#define BZ_X_CCRC_1 47
|
||||
#define BZ_X_CCRC_2 48
|
||||
#define BZ_X_CCRC_3 49
|
||||
#define BZ_X_CCRC_4 50
|
||||
|
||||
/*-- Constants for the fast MTF decoder. --*/
|
||||
|
||||
#define MTFA_SIZE 4096
|
||||
#define MTFL_SIZE 16
|
||||
|
||||
/*-- Structure holding all the decompression-side stuff. --*/
|
||||
|
||||
typedef struct {
|
||||
/* pointer back to the struct bz_stream */
|
||||
bz_stream* strm;
|
||||
|
||||
/* state indicator for this stream */
|
||||
Int32 state;
|
||||
|
||||
/* for doing the final run-length decoding */
|
||||
UChar state_out_ch;
|
||||
Int32 state_out_len;
|
||||
Bool blockRandomised;
|
||||
BZ_RAND_DECLS;
|
||||
|
||||
/* the buffer for bit stream reading */
|
||||
UInt32 bsBuff;
|
||||
Int32 bsLive;
|
||||
|
||||
/* misc administratium */
|
||||
Int32 blockSize100k;
|
||||
Bool smallDecompress;
|
||||
Int32 currBlockNo;
|
||||
Int32 verbosity;
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform */
|
||||
Int32 origPtr;
|
||||
UInt32 tPos;
|
||||
Int32 k0;
|
||||
Int32 unzftab[256];
|
||||
Int32 nblock_used;
|
||||
Int32 cftab[257];
|
||||
Int32 cftabCopy[257];
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform (FAST) */
|
||||
UInt32* tt;
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform (SMALL) */
|
||||
UInt16* ll16;
|
||||
UChar* ll4;
|
||||
|
||||
/* stored and calculated CRCs */
|
||||
UInt32 storedBlockCRC;
|
||||
UInt32 storedCombinedCRC;
|
||||
UInt32 calculatedBlockCRC;
|
||||
UInt32 calculatedCombinedCRC;
|
||||
|
||||
/* map of bytes used in block */
|
||||
Int32 nInUse;
|
||||
Bool inUse[256];
|
||||
Bool inUse16[16];
|
||||
UChar seqToUnseq[256];
|
||||
|
||||
/* for decoding the MTF values */
|
||||
UChar mtfa[MTFA_SIZE];
|
||||
Int32 mtfbase[256 / MTFL_SIZE];
|
||||
UChar selector[BZ_MAX_SELECTORS];
|
||||
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||
UChar len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
|
||||
Int32 limit[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 base[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 perm[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 minLens[BZ_N_GROUPS];
|
||||
|
||||
/* save area for scalars in the main decompress code */
|
||||
Int32 save_i;
|
||||
Int32 save_j;
|
||||
Int32 save_t;
|
||||
Int32 save_alphaSize;
|
||||
Int32 save_nGroups;
|
||||
Int32 save_nSelectors;
|
||||
Int32 save_EOB;
|
||||
Int32 save_groupNo;
|
||||
Int32 save_groupPos;
|
||||
Int32 save_nextSym;
|
||||
Int32 save_nblockMAX;
|
||||
Int32 save_nblock;
|
||||
Int32 save_es;
|
||||
Int32 save_N;
|
||||
Int32 save_curr;
|
||||
Int32 save_zt;
|
||||
Int32 save_zn;
|
||||
Int32 save_zvec;
|
||||
Int32 save_zj;
|
||||
Int32 save_gSel;
|
||||
Int32 save_gMinlen;
|
||||
Int32* save_gLimit;
|
||||
Int32* save_gBase;
|
||||
Int32* save_gPerm;
|
||||
|
||||
} DState;
|
||||
|
||||
/*-- Macros for decompression. --*/
|
||||
|
||||
#define BZ_GET_FAST(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) \
|
||||
return True; \
|
||||
s->tPos = s->tt[s->tPos]; \
|
||||
cccc = (UChar)(s->tPos & 0xff); \
|
||||
s->tPos >>= 8;
|
||||
|
||||
#define BZ_GET_FAST_C(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) \
|
||||
return True; \
|
||||
c_tPos = c_tt[c_tPos]; \
|
||||
cccc = (UChar)(c_tPos & 0xff); \
|
||||
c_tPos >>= 8;
|
||||
|
||||
#define SET_LL4(i, n) \
|
||||
{ \
|
||||
if (((i)&0x1) == 0) \
|
||||
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); \
|
||||
else \
|
||||
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
|
||||
}
|
||||
|
||||
#define GET_LL4(i) ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
|
||||
|
||||
#define SET_LL(i, n) \
|
||||
{ \
|
||||
s->ll16[i] = (UInt16)(n & 0x0000ffff); \
|
||||
SET_LL4(i, n >> 16); \
|
||||
}
|
||||
|
||||
#define GET_LL(i) (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
|
||||
|
||||
#define BZ_GET_SMALL(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) \
|
||||
return True; \
|
||||
cccc = BZ2_indexIntoF(s->tPos, s->cftab); \
|
||||
s->tPos = GET_LL(s->tPos);
|
||||
|
||||
/*-- externs for decompression. --*/
|
||||
|
||||
extern Int32 BZ2_indexIntoF(Int32, Int32*);
|
||||
|
||||
extern Int32 BZ2_decompress(DState*);
|
||||
|
||||
extern void BZ2_hbCreateDecodeTables(Int32*, Int32*, Int32*, UChar*, Int32, Int32, Int32);
|
||||
|
||||
#endif
|
||||
|
||||
/*-- BZ_NO_STDIO seems to make nullptr disappear on some platforms. --*/
|
||||
|
||||
#ifdef BZ_NO_STDIO
|
||||
#ifndef nullptr
|
||||
#define nullptr 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end bzlib_private.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
@@ -0,0 +1,854 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Compression machinery (not incl block sorting) ---*/
|
||||
/*--- compress.cpp ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
/* CHANGES
|
||||
0.9.0 -- original version.
|
||||
0.9.0a/b -- no changes in this file.
|
||||
0.9.0c -- changed setting of nGroups in sendMTFValues()
|
||||
so as to do a bit better on small files
|
||||
*/
|
||||
|
||||
#include "bzlib_private.hpp"
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- Bit stream I/O ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_bsInitWrite(EState* s) {
|
||||
s->bsLive = 0;
|
||||
s->bsBuff = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static void bsFinishWrite(EState* s) {
|
||||
while (s->bsLive > 0) {
|
||||
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
|
||||
s->numZ++;
|
||||
s->bsBuff <<= 8;
|
||||
s->bsLive -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define bsNEEDW(nz) \
|
||||
{ \
|
||||
while (s->bsLive >= 8) { \
|
||||
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); \
|
||||
s->numZ++; \
|
||||
s->bsBuff <<= 8; \
|
||||
s->bsLive -= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static __inline__ void bsW(EState* s, Int32 n, UInt32 v) {
|
||||
bsNEEDW(n);
|
||||
s->bsBuff |= (v << (32 - s->bsLive - n));
|
||||
s->bsLive += n;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static void bsPutUInt32(EState* s, UInt32 u) {
|
||||
bsW(s, 8, (u >> 24) & 0xffL);
|
||||
bsW(s, 8, (u >> 16) & 0xffL);
|
||||
bsW(s, 8, (u >> 8) & 0xffL);
|
||||
bsW(s, 8, u & 0xffL);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static void bsPutUChar(EState* s, UChar c) {
|
||||
bsW(s, 8, (UInt32)c);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- The back end proper ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static void makeMaps_e(EState* s) {
|
||||
Int32 i;
|
||||
s->nInUse = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (s->inUse[i]) {
|
||||
s->unseqToSeq[i] = s->nInUse;
|
||||
s->nInUse++;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static void generateMTFValues(EState* s) {
|
||||
UChar yy[256];
|
||||
Int32 i, j;
|
||||
Int32 zPend;
|
||||
Int32 wr;
|
||||
Int32 EOB;
|
||||
|
||||
/*
|
||||
After sorting (eg, here),
|
||||
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
|
||||
and
|
||||
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
|
||||
holds the original block data.
|
||||
|
||||
The first thing to do is generate the MTF values,
|
||||
and put them in
|
||||
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
|
||||
Because there are strictly fewer or equal MTF values
|
||||
than block values, ptr values in this area are overwritten
|
||||
with MTF values only when they are no longer needed.
|
||||
|
||||
The final compressed bitstream is generated into the
|
||||
area starting at
|
||||
(UChar*) (&((UChar*)s->arr2)[s->nblock])
|
||||
|
||||
These storage aliases are set up in bzCompressInit(),
|
||||
except for the last one, which is arranged in
|
||||
compressBlock().
|
||||
*/
|
||||
UInt32* ptr = s->ptr;
|
||||
UChar* block = s->block;
|
||||
UInt16* mtfv = s->mtfv;
|
||||
|
||||
makeMaps_e(s);
|
||||
EOB = s->nInUse + 1;
|
||||
|
||||
for (i = 0; i <= EOB; i++)
|
||||
s->mtfFreq[i] = 0;
|
||||
|
||||
wr = 0;
|
||||
zPend = 0;
|
||||
for (i = 0; i < s->nInUse; i++)
|
||||
yy[i] = (UChar)i;
|
||||
|
||||
for (i = 0; i < s->nblock; i++) {
|
||||
UChar ll_i;
|
||||
AssertD(wr <= i, "generateMTFValues(1)");
|
||||
j = ptr[i] - 1;
|
||||
if (j < 0)
|
||||
j += s->nblock;
|
||||
ll_i = s->unseqToSeq[block[j]];
|
||||
AssertD(ll_i < s->nInUse, "generateMTFValues(2a)");
|
||||
|
||||
if (yy[0] == ll_i) {
|
||||
zPend++;
|
||||
}
|
||||
else {
|
||||
if (zPend > 0) {
|
||||
zPend--;
|
||||
while (True) {
|
||||
if (zPend & 1) {
|
||||
mtfv[wr] = BZ_RUNB;
|
||||
wr++;
|
||||
s->mtfFreq[BZ_RUNB]++;
|
||||
}
|
||||
else {
|
||||
mtfv[wr] = BZ_RUNA;
|
||||
wr++;
|
||||
s->mtfFreq[BZ_RUNA]++;
|
||||
}
|
||||
if (zPend < 2)
|
||||
break;
|
||||
zPend = (zPend - 2) / 2;
|
||||
};
|
||||
zPend = 0;
|
||||
}
|
||||
{
|
||||
UChar rtmp;
|
||||
UChar* ryy_j;
|
||||
UChar rll_i;
|
||||
rtmp = yy[1];
|
||||
yy[1] = yy[0];
|
||||
ryy_j = &(yy[1]);
|
||||
rll_i = ll_i;
|
||||
while (rll_i != rtmp) {
|
||||
UChar rtmp2;
|
||||
ryy_j++;
|
||||
rtmp2 = rtmp;
|
||||
rtmp = *ryy_j;
|
||||
*ryy_j = rtmp2;
|
||||
};
|
||||
yy[0] = rtmp;
|
||||
j = ryy_j - &(yy[0]);
|
||||
mtfv[wr] = j + 1;
|
||||
wr++;
|
||||
s->mtfFreq[j + 1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (zPend > 0) {
|
||||
zPend--;
|
||||
while (True) {
|
||||
if (zPend & 1) {
|
||||
mtfv[wr] = BZ_RUNB;
|
||||
wr++;
|
||||
s->mtfFreq[BZ_RUNB]++;
|
||||
}
|
||||
else {
|
||||
mtfv[wr] = BZ_RUNA;
|
||||
wr++;
|
||||
s->mtfFreq[BZ_RUNA]++;
|
||||
}
|
||||
if (zPend < 2)
|
||||
break;
|
||||
zPend = (zPend - 2) / 2;
|
||||
};
|
||||
zPend = 0;
|
||||
}
|
||||
|
||||
mtfv[wr] = EOB;
|
||||
wr++;
|
||||
s->mtfFreq[EOB]++;
|
||||
|
||||
s->nMTF = wr;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define BZ_LESSER_ICOST 0
|
||||
#define BZ_GREATER_ICOST 15
|
||||
|
||||
static void sendMTFValues(EState* s) {
|
||||
Int32 t, i, j, k, gs, ge, totc, bt, bc;
|
||||
Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
|
||||
Int32 nGroups, nBytes;
|
||||
|
||||
/*--
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
is a global since the decoder also needs it.
|
||||
|
||||
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
are also globals only used in this proc.
|
||||
Made global to keep stack frame size small.
|
||||
--*/
|
||||
|
||||
UInt16 cost[BZ_N_GROUPS];
|
||||
Int32 fave[BZ_N_GROUPS];
|
||||
|
||||
UInt16* mtfv = s->mtfv;
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf3(" %d in block, %d after MTF & 1-2 coding, "
|
||||
"%d+2 syms in use\n",
|
||||
s->nblock,
|
||||
s->nMTF,
|
||||
s->nInUse);
|
||||
|
||||
alphaSize = s->nInUse + 2;
|
||||
for (i = 0; i < BZ_N_GROUPS; i++)
|
||||
for (j = 0; j < alphaSize; j++)
|
||||
s->len[i][j] = BZ_GREATER_ICOST;
|
||||
|
||||
/*--- Decide how many coding tables to use ---*/
|
||||
AssertH(s->nMTF > 0, 3001);
|
||||
if (s->nMTF < 200)
|
||||
nGroups = 2;
|
||||
else if (s->nMTF < 600)
|
||||
nGroups = 3;
|
||||
else if (s->nMTF < 1200)
|
||||
nGroups = 4;
|
||||
else if (s->nMTF < 2400)
|
||||
nGroups = 5;
|
||||
else
|
||||
nGroups = 6;
|
||||
|
||||
/*--- Generate an initial set of coding tables ---*/
|
||||
{
|
||||
Int32 nPart, remF, tFreq, aFreq;
|
||||
|
||||
nPart = nGroups;
|
||||
remF = s->nMTF;
|
||||
gs = 0;
|
||||
while (nPart > 0) {
|
||||
tFreq = remF / nPart;
|
||||
ge = gs - 1;
|
||||
aFreq = 0;
|
||||
while (aFreq < tFreq && ge < alphaSize - 1) {
|
||||
ge++;
|
||||
aFreq += s->mtfFreq[ge];
|
||||
}
|
||||
|
||||
if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) {
|
||||
aFreq -= s->mtfFreq[ge];
|
||||
ge--;
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf5(" initial group %d, [%d .. %d], "
|
||||
"has %d syms (%4.1f%%)\n",
|
||||
nPart,
|
||||
gs,
|
||||
ge,
|
||||
aFreq,
|
||||
(100.0 * (float)aFreq) / (float)(s->nMTF));
|
||||
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
if (i >= gs && i <= ge)
|
||||
s->len[nPart - 1][i] = BZ_LESSER_ICOST;
|
||||
else
|
||||
s->len[nPart - 1][i] = BZ_GREATER_ICOST;
|
||||
|
||||
nPart--;
|
||||
gs = ge + 1;
|
||||
remF -= aFreq;
|
||||
}
|
||||
}
|
||||
|
||||
/*---
|
||||
Iterate up to BZ_N_ITERS times to improve the tables.
|
||||
---*/
|
||||
for (k = 0; k < BZ_N_ITERS; k++) {
|
||||
for (i = 0; i < nGroups; i++)
|
||||
fave[i] = 0;
|
||||
|
||||
for (i = 0; i < nGroups; i++)
|
||||
for (j = 0; j < alphaSize; j++)
|
||||
s->rfreq[i][j] = 0;
|
||||
|
||||
/*---
|
||||
Set up an auxiliary length table which is used to fast-track
|
||||
the common case (nGroups == 6).
|
||||
---*/
|
||||
if (nGroups == 6) {
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
s->len_pack[i][0] = (s->len[1][i] << 16) | s->len[0][i];
|
||||
s->len_pack[i][1] = (s->len[3][i] << 16) | s->len[2][i];
|
||||
s->len_pack[i][2] = (s->len[5][i] << 16) | s->len[4][i];
|
||||
}
|
||||
}
|
||||
|
||||
nSelectors = 0;
|
||||
totc = 0;
|
||||
gs = 0;
|
||||
while (True) {
|
||||
/*--- Set group start & end marks. --*/
|
||||
if (gs >= s->nMTF)
|
||||
break;
|
||||
ge = gs + BZ_G_SIZE - 1;
|
||||
if (ge >= s->nMTF)
|
||||
ge = s->nMTF - 1;
|
||||
|
||||
/*--
|
||||
Calculate the cost of this group as coded
|
||||
by each of the coding tables.
|
||||
--*/
|
||||
for (i = 0; i < nGroups; i++)
|
||||
cost[i] = 0;
|
||||
|
||||
if (nGroups == 6 && 50 == ge - gs + 1) {
|
||||
/*--- fast track the common case ---*/
|
||||
UInt32 cost01, cost23, cost45;
|
||||
UInt16 icv;
|
||||
cost01 = cost23 = cost45 = 0;
|
||||
|
||||
#define BZ_ITER(nn) \
|
||||
icv = mtfv[gs + (nn)]; \
|
||||
cost01 += s->len_pack[icv][0]; \
|
||||
cost23 += s->len_pack[icv][1]; \
|
||||
cost45 += s->len_pack[icv][2];
|
||||
|
||||
BZ_ITER(0);
|
||||
BZ_ITER(1);
|
||||
BZ_ITER(2);
|
||||
BZ_ITER(3);
|
||||
BZ_ITER(4);
|
||||
BZ_ITER(5);
|
||||
BZ_ITER(6);
|
||||
BZ_ITER(7);
|
||||
BZ_ITER(8);
|
||||
BZ_ITER(9);
|
||||
BZ_ITER(10);
|
||||
BZ_ITER(11);
|
||||
BZ_ITER(12);
|
||||
BZ_ITER(13);
|
||||
BZ_ITER(14);
|
||||
BZ_ITER(15);
|
||||
BZ_ITER(16);
|
||||
BZ_ITER(17);
|
||||
BZ_ITER(18);
|
||||
BZ_ITER(19);
|
||||
BZ_ITER(20);
|
||||
BZ_ITER(21);
|
||||
BZ_ITER(22);
|
||||
BZ_ITER(23);
|
||||
BZ_ITER(24);
|
||||
BZ_ITER(25);
|
||||
BZ_ITER(26);
|
||||
BZ_ITER(27);
|
||||
BZ_ITER(28);
|
||||
BZ_ITER(29);
|
||||
BZ_ITER(30);
|
||||
BZ_ITER(31);
|
||||
BZ_ITER(32);
|
||||
BZ_ITER(33);
|
||||
BZ_ITER(34);
|
||||
BZ_ITER(35);
|
||||
BZ_ITER(36);
|
||||
BZ_ITER(37);
|
||||
BZ_ITER(38);
|
||||
BZ_ITER(39);
|
||||
BZ_ITER(40);
|
||||
BZ_ITER(41);
|
||||
BZ_ITER(42);
|
||||
BZ_ITER(43);
|
||||
BZ_ITER(44);
|
||||
BZ_ITER(45);
|
||||
BZ_ITER(46);
|
||||
BZ_ITER(47);
|
||||
BZ_ITER(48);
|
||||
BZ_ITER(49);
|
||||
|
||||
#undef BZ_ITER
|
||||
|
||||
cost[0] = cost01 & 0xffff;
|
||||
cost[1] = cost01 >> 16;
|
||||
cost[2] = cost23 & 0xffff;
|
||||
cost[3] = cost23 >> 16;
|
||||
cost[4] = cost45 & 0xffff;
|
||||
cost[5] = cost45 >> 16;
|
||||
}
|
||||
else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++) {
|
||||
UInt16 icv = mtfv[i];
|
||||
for (j = 0; j < nGroups; j++)
|
||||
cost[j] += s->len[j][icv];
|
||||
}
|
||||
}
|
||||
|
||||
/*--
|
||||
Find the coding table which is best for this group,
|
||||
and record its identity in the selector table.
|
||||
--*/
|
||||
bc = 999999999;
|
||||
bt = -1;
|
||||
for (i = 0; i < nGroups; i++)
|
||||
if (cost[i] < bc) {
|
||||
bc = cost[i];
|
||||
bt = i;
|
||||
};
|
||||
totc += bc;
|
||||
fave[bt]++;
|
||||
s->selector[nSelectors] = bt;
|
||||
nSelectors++;
|
||||
|
||||
/*--
|
||||
Increment the symbol frequencies for the selected table.
|
||||
--*/
|
||||
if (nGroups == 6 && 50 == ge - gs + 1) {
|
||||
/*--- fast track the common case ---*/
|
||||
|
||||
#define BZ_ITUR(nn) s->rfreq[bt][mtfv[gs + (nn)]]++
|
||||
|
||||
BZ_ITUR(0);
|
||||
BZ_ITUR(1);
|
||||
BZ_ITUR(2);
|
||||
BZ_ITUR(3);
|
||||
BZ_ITUR(4);
|
||||
BZ_ITUR(5);
|
||||
BZ_ITUR(6);
|
||||
BZ_ITUR(7);
|
||||
BZ_ITUR(8);
|
||||
BZ_ITUR(9);
|
||||
BZ_ITUR(10);
|
||||
BZ_ITUR(11);
|
||||
BZ_ITUR(12);
|
||||
BZ_ITUR(13);
|
||||
BZ_ITUR(14);
|
||||
BZ_ITUR(15);
|
||||
BZ_ITUR(16);
|
||||
BZ_ITUR(17);
|
||||
BZ_ITUR(18);
|
||||
BZ_ITUR(19);
|
||||
BZ_ITUR(20);
|
||||
BZ_ITUR(21);
|
||||
BZ_ITUR(22);
|
||||
BZ_ITUR(23);
|
||||
BZ_ITUR(24);
|
||||
BZ_ITUR(25);
|
||||
BZ_ITUR(26);
|
||||
BZ_ITUR(27);
|
||||
BZ_ITUR(28);
|
||||
BZ_ITUR(29);
|
||||
BZ_ITUR(30);
|
||||
BZ_ITUR(31);
|
||||
BZ_ITUR(32);
|
||||
BZ_ITUR(33);
|
||||
BZ_ITUR(34);
|
||||
BZ_ITUR(35);
|
||||
BZ_ITUR(36);
|
||||
BZ_ITUR(37);
|
||||
BZ_ITUR(38);
|
||||
BZ_ITUR(39);
|
||||
BZ_ITUR(40);
|
||||
BZ_ITUR(41);
|
||||
BZ_ITUR(42);
|
||||
BZ_ITUR(43);
|
||||
BZ_ITUR(44);
|
||||
BZ_ITUR(45);
|
||||
BZ_ITUR(46);
|
||||
BZ_ITUR(47);
|
||||
BZ_ITUR(48);
|
||||
BZ_ITUR(49);
|
||||
|
||||
#undef BZ_ITUR
|
||||
}
|
||||
else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++)
|
||||
s->rfreq[bt][mtfv[i]]++;
|
||||
}
|
||||
|
||||
gs = ge + 1;
|
||||
}
|
||||
if (s->verbosity >= 3) {
|
||||
VPrintf2(" pass %d: size is %d, grp uses are ", k + 1, totc / 8);
|
||||
for (i = 0; i < nGroups; i++)
|
||||
VPrintf1("%d ", fave[i]);
|
||||
VPrintf0("\n");
|
||||
}
|
||||
|
||||
/*--
|
||||
Recompute the tables based on the accumulated frequencies.
|
||||
--*/
|
||||
/* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
|
||||
comment in huffman.c for details. */
|
||||
for (i = 0; i < nGroups; i++)
|
||||
BZ2_hbMakeCodeLengths(&(s->len[i][0]), &(s->rfreq[i][0]), alphaSize, 17 /*20*/);
|
||||
}
|
||||
|
||||
AssertH(nGroups < 8, 3002);
|
||||
AssertH(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZ_G_SIZE)), 3003);
|
||||
|
||||
/*--- Compute MTF values for the selectors. ---*/
|
||||
{
|
||||
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
|
||||
for (i = 0; i < nGroups; i++)
|
||||
pos[i] = i;
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
ll_i = s->selector[i];
|
||||
j = 0;
|
||||
tmp = pos[j];
|
||||
while (ll_i != tmp) {
|
||||
j++;
|
||||
tmp2 = tmp;
|
||||
tmp = pos[j];
|
||||
pos[j] = tmp2;
|
||||
};
|
||||
pos[0] = tmp;
|
||||
s->selectorMtf[i] = j;
|
||||
}
|
||||
};
|
||||
|
||||
/*--- Assign actual codes for the tables. --*/
|
||||
for (j = 0; j < nGroups; j++) {
|
||||
minLen = 32;
|
||||
maxLen = 0;
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
if (s->len[j][i] > maxLen)
|
||||
maxLen = s->len[j][i];
|
||||
if (s->len[j][i] < minLen)
|
||||
minLen = s->len[j][i];
|
||||
}
|
||||
AssertH(!(maxLen > 17 /*20*/), 3004);
|
||||
AssertH(!(minLen < 1), 3005);
|
||||
BZ2_hbAssignCodes(&(s->code[j][0]), &(s->len[j][0]), minLen, maxLen, alphaSize);
|
||||
}
|
||||
|
||||
/*--- Transmit the mapping table. ---*/
|
||||
{
|
||||
Bool inUse16[16];
|
||||
for (i = 0; i < 16; i++) {
|
||||
inUse16[i] = False;
|
||||
for (j = 0; j < 16; j++)
|
||||
if (s->inUse[i * 16 + j])
|
||||
inUse16[i] = True;
|
||||
}
|
||||
|
||||
nBytes = s->numZ;
|
||||
for (i = 0; i < 16; i++)
|
||||
if (inUse16[i])
|
||||
bsW(s, 1, 1);
|
||||
else
|
||||
bsW(s, 1, 0);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (inUse16[i])
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (s->inUse[i * 16 + j])
|
||||
bsW(s, 1, 1);
|
||||
else
|
||||
bsW(s, 1, 0);
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1(" bytes: mapping %d, ", s->numZ - nBytes);
|
||||
}
|
||||
|
||||
/*--- Now the selectors. ---*/
|
||||
nBytes = s->numZ;
|
||||
bsW(s, 3, nGroups);
|
||||
bsW(s, 15, nSelectors);
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
for (j = 0; j < s->selectorMtf[i]; j++)
|
||||
bsW(s, 1, 1);
|
||||
bsW(s, 1, 0);
|
||||
}
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1("selectors %d, ", s->numZ - nBytes);
|
||||
|
||||
/*--- Now the coding tables. ---*/
|
||||
nBytes = s->numZ;
|
||||
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
Int32 curr = s->len[t][0];
|
||||
bsW(s, 5, curr);
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
while (curr < s->len[t][i]) {
|
||||
bsW(s, 2, 2);
|
||||
curr++; /* 10 */
|
||||
};
|
||||
while (curr > s->len[t][i]) {
|
||||
bsW(s, 2, 3);
|
||||
curr--; /* 11 */
|
||||
};
|
||||
bsW(s, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1("code lengths %d, ", s->numZ - nBytes);
|
||||
|
||||
/*--- And finally, the block data proper ---*/
|
||||
nBytes = s->numZ;
|
||||
selCtr = 0;
|
||||
gs = 0;
|
||||
while (True) {
|
||||
if (gs >= s->nMTF)
|
||||
break;
|
||||
ge = gs + BZ_G_SIZE - 1;
|
||||
if (ge >= s->nMTF)
|
||||
ge = s->nMTF - 1;
|
||||
AssertH(s->selector[selCtr] < nGroups, 3006);
|
||||
|
||||
if (nGroups == 6 && 50 == ge - gs + 1) {
|
||||
/*--- fast track the common case ---*/
|
||||
UInt16 mtfv_i;
|
||||
UChar* s_len_sel_selCtr = &(s->len[s->selector[selCtr]][0]);
|
||||
Int32* s_code_sel_selCtr = &(s->code[s->selector[selCtr]][0]);
|
||||
|
||||
#define BZ_ITAH(nn) \
|
||||
mtfv_i = mtfv[gs + (nn)]; \
|
||||
bsW(s, s_len_sel_selCtr[mtfv_i], s_code_sel_selCtr[mtfv_i])
|
||||
|
||||
BZ_ITAH(0);
|
||||
BZ_ITAH(1);
|
||||
BZ_ITAH(2);
|
||||
BZ_ITAH(3);
|
||||
BZ_ITAH(4);
|
||||
BZ_ITAH(5);
|
||||
BZ_ITAH(6);
|
||||
BZ_ITAH(7);
|
||||
BZ_ITAH(8);
|
||||
BZ_ITAH(9);
|
||||
BZ_ITAH(10);
|
||||
BZ_ITAH(11);
|
||||
BZ_ITAH(12);
|
||||
BZ_ITAH(13);
|
||||
BZ_ITAH(14);
|
||||
BZ_ITAH(15);
|
||||
BZ_ITAH(16);
|
||||
BZ_ITAH(17);
|
||||
BZ_ITAH(18);
|
||||
BZ_ITAH(19);
|
||||
BZ_ITAH(20);
|
||||
BZ_ITAH(21);
|
||||
BZ_ITAH(22);
|
||||
BZ_ITAH(23);
|
||||
BZ_ITAH(24);
|
||||
BZ_ITAH(25);
|
||||
BZ_ITAH(26);
|
||||
BZ_ITAH(27);
|
||||
BZ_ITAH(28);
|
||||
BZ_ITAH(29);
|
||||
BZ_ITAH(30);
|
||||
BZ_ITAH(31);
|
||||
BZ_ITAH(32);
|
||||
BZ_ITAH(33);
|
||||
BZ_ITAH(34);
|
||||
BZ_ITAH(35);
|
||||
BZ_ITAH(36);
|
||||
BZ_ITAH(37);
|
||||
BZ_ITAH(38);
|
||||
BZ_ITAH(39);
|
||||
BZ_ITAH(40);
|
||||
BZ_ITAH(41);
|
||||
BZ_ITAH(42);
|
||||
BZ_ITAH(43);
|
||||
BZ_ITAH(44);
|
||||
BZ_ITAH(45);
|
||||
BZ_ITAH(46);
|
||||
BZ_ITAH(47);
|
||||
BZ_ITAH(48);
|
||||
BZ_ITAH(49);
|
||||
|
||||
#undef BZ_ITAH
|
||||
}
|
||||
else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++) {
|
||||
bsW(s, s->len[s->selector[selCtr]][mtfv[i]], s->code[s->selector[selCtr]][mtfv[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
gs = ge + 1;
|
||||
selCtr++;
|
||||
}
|
||||
AssertH(selCtr == nSelectors, 3007);
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1("codes %d\n", s->numZ - nBytes);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_compressBlock(EState* s, Bool is_last_block) {
|
||||
if (s->nblock > 0) {
|
||||
BZ_FINALISE_CRC(s->blockCRC);
|
||||
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
|
||||
s->combinedCRC ^= s->blockCRC;
|
||||
if (s->blockNo > 1)
|
||||
s->numZ = 0;
|
||||
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf4(" block %d: crc = 0x%08x, "
|
||||
"combined CRC = 0x%08x, size = %d\n",
|
||||
s->blockNo,
|
||||
s->blockCRC,
|
||||
s->combinedCRC,
|
||||
s->nblock);
|
||||
|
||||
BZ2_blockSort(s);
|
||||
}
|
||||
|
||||
s->zbits = (UChar*)(&((UChar*)s->arr2)[s->nblock]);
|
||||
|
||||
/*-- If this is the first block, create the stream header. --*/
|
||||
if (s->blockNo == 1) {
|
||||
BZ2_bsInitWrite(s);
|
||||
bsPutUChar(s, BZ_HDR_B);
|
||||
bsPutUChar(s, BZ_HDR_Z);
|
||||
bsPutUChar(s, BZ_HDR_h);
|
||||
bsPutUChar(s, (UChar)(BZ_HDR_0 + s->blockSize100k));
|
||||
}
|
||||
|
||||
if (s->nblock > 0) {
|
||||
bsPutUChar(s, 0x31);
|
||||
bsPutUChar(s, 0x41);
|
||||
bsPutUChar(s, 0x59);
|
||||
bsPutUChar(s, 0x26);
|
||||
bsPutUChar(s, 0x53);
|
||||
bsPutUChar(s, 0x59);
|
||||
|
||||
/*-- Now the block's CRC, so it is in a known place. --*/
|
||||
bsPutUInt32(s, s->blockCRC);
|
||||
|
||||
/*--
|
||||
Now a single bit indicating (non-)randomisation.
|
||||
As of version 0.9.5, we use a better sorting algorithm
|
||||
which makes randomisation unnecessary. So always set
|
||||
the randomised bit to 'no'. Of course, the decoder
|
||||
still needs to be able to handle randomised blocks
|
||||
so as to maintain backwards compatibility with
|
||||
older versions of bzip2.
|
||||
--*/
|
||||
bsW(s, 1, 0);
|
||||
|
||||
bsW(s, 24, s->origPtr);
|
||||
generateMTFValues(s);
|
||||
sendMTFValues(s);
|
||||
}
|
||||
|
||||
/*-- If this is the last block, add the stream trailer. --*/
|
||||
if (is_last_block) {
|
||||
bsPutUChar(s, 0x17);
|
||||
bsPutUChar(s, 0x72);
|
||||
bsPutUChar(s, 0x45);
|
||||
bsPutUChar(s, 0x38);
|
||||
bsPutUChar(s, 0x50);
|
||||
bsPutUChar(s, 0x90);
|
||||
bsPutUInt32(s, s->combinedCRC);
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf1(" final combined CRC = 0x%08x\n ", s->combinedCRC);
|
||||
bsFinishWrite(s);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end compress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Table for doing CRCs ---*/
|
||||
/*--- crctable.cpp ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#include "bzlib_private.hpp"
|
||||
|
||||
/*--
|
||||
I think this is an implementation of the AUTODIN-II,
|
||||
Ethernet & FDDI 32-bit CRC standard. Vaguely derived
|
||||
from code by Rob Warnock, in Section 51 of the
|
||||
comp.compression FAQ.
|
||||
--*/
|
||||
|
||||
UInt32 BZ2_crc32Table[256] = {
|
||||
|
||||
/*-- Ugly, innit? --*/
|
||||
|
||||
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, 0x130476dcL, 0x17c56b6bL, 0x1a864db2L,
|
||||
0x1e475005L, 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, 0x350c9b64L, 0x31cd86d3L,
|
||||
0x3c8ea00aL, 0x384fbdbdL, 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, 0x5f15adacL,
|
||||
0x5bd4b01bL, 0x569796c2L, 0x52568b75L, 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
|
||||
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL,
|
||||
0x95609039L, 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, 0xbe2b5b58L, 0xbaea46efL,
|
||||
0xb7a96036L, 0xb3687d81L, 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, 0xd4326d90L,
|
||||
0xd0f37027L, 0xddb056feL, 0xd9714b49L, 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
|
||||
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL,
|
||||
0xec7dd02dL, 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, 0x278206abL, 0x23431b1cL,
|
||||
0x2e003dc5L, 0x2ac12072L, 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, 0x018aeb13L,
|
||||
0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
|
||||
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L,
|
||||
0x53dc6066L, 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, 0xaca5c697L, 0xa864db20L,
|
||||
0xa527fdf9L, 0xa1e6e04eL, 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, 0x8aad2b2fL,
|
||||
0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
|
||||
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, 0xf3b06b3bL, 0xf771768cL, 0xfa325055L,
|
||||
0xfef34de2L, 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, 0xd5b88683L, 0xd1799b34L,
|
||||
0xdc3abdedL, 0xd8fba05aL, 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, 0x7a089632L,
|
||||
0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
|
||||
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L,
|
||||
0x285e1d47L, 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, 0x0315d626L, 0x07d4cb91L,
|
||||
0x0a97ed48L, 0x0e56f0ffL, 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, 0xf12f560eL,
|
||||
0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
|
||||
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L,
|
||||
0xc960ebb3L, 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, 0xae3afba2L, 0xaafbe615L,
|
||||
0xa7b8c0ccL, 0xa379dd7bL, 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, 0x8832161aL,
|
||||
0x8cf30badL, 0x81b02d74L, 0x857130c3L, 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
|
||||
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, 0x7b827d21L, 0x7f436096L, 0x7200464fL,
|
||||
0x76c15bf8L, 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, 0x119b4be9L, 0x155a565eL,
|
||||
0x18197087L, 0x1cd86d30L, 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, 0x3793a651L,
|
||||
0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
|
||||
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL,
|
||||
0xdbee767cL, 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, 0xf0a5bd1dL, 0xf464a0aaL,
|
||||
0xf9278673L, 0xfde69bc4L, 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, 0x9abc8bd5L,
|
||||
0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
|
||||
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end crctable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
@@ -0,0 +1,732 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Decompression machinery ---*/
|
||||
/*--- decompress.cpp ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#include "bzlib_private.hpp"
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static void makeMaps_d(DState* s) {
|
||||
Int32 i;
|
||||
s->nInUse = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (s->inUse[i]) {
|
||||
s->seqToUnseq[s->nInUse] = i;
|
||||
s->nInUse++;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define RETURN(rrr) \
|
||||
{ \
|
||||
retVal = rrr; \
|
||||
goto save_state_and_return; \
|
||||
};
|
||||
|
||||
#define GET_BITS(lll, vvv, nnn) \
|
||||
case lll: \
|
||||
s->state = lll; \
|
||||
while (True) { \
|
||||
if (s->bsLive >= nnn) { \
|
||||
UInt32 v; \
|
||||
v = (s->bsBuff >> (s->bsLive - nnn)) & ((1 << nnn) - 1); \
|
||||
s->bsLive -= nnn; \
|
||||
vvv = v; \
|
||||
break; \
|
||||
} \
|
||||
if (s->strm->avail_in == 0) \
|
||||
RETURN(BZ_OK); \
|
||||
s->bsBuff = (s->bsBuff << 8) | ((UInt32)(*((UChar*)(s->strm->next_in)))); \
|
||||
s->bsLive += 8; \
|
||||
s->strm->next_in++; \
|
||||
s->strm->avail_in--; \
|
||||
s->strm->total_in_lo32++; \
|
||||
if (s->strm->total_in_lo32 == 0) \
|
||||
s->strm->total_in_hi32++; \
|
||||
}
|
||||
|
||||
#define GET_UCHAR(lll, uuu) GET_BITS(lll, uuu, 8)
|
||||
|
||||
#define GET_BIT(lll, uuu) GET_BITS(lll, uuu, 1)
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define GET_MTF_VAL(label1, label2, lval) \
|
||||
{ \
|
||||
if (groupPos == 0) { \
|
||||
groupNo++; \
|
||||
if (groupNo >= nSelectors) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
groupPos = BZ_G_SIZE; \
|
||||
gSel = s->selector[groupNo]; \
|
||||
gMinlen = s->minLens[gSel]; \
|
||||
gLimit = &(s->limit[gSel][0]); \
|
||||
gPerm = &(s->perm[gSel][0]); \
|
||||
gBase = &(s->base[gSel][0]); \
|
||||
} \
|
||||
groupPos--; \
|
||||
zn = gMinlen; \
|
||||
GET_BITS(label1, zvec, zn); \
|
||||
while (1) { \
|
||||
if (zn > 20 /* the longest code */) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
if (zvec <= gLimit[zn]) \
|
||||
break; \
|
||||
zn++; \
|
||||
GET_BIT(label2, zj); \
|
||||
zvec = (zvec << 1) | zj; \
|
||||
}; \
|
||||
if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
lval = gPerm[zvec - gBase[zn]]; \
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
Int32 BZ2_decompress(DState* s) {
|
||||
UChar uc;
|
||||
Int32 retVal;
|
||||
Int32 minLen, maxLen;
|
||||
bz_stream* strm = s->strm;
|
||||
|
||||
/* stuff that needs to be saved/restored */
|
||||
Int32 i;
|
||||
Int32 j;
|
||||
Int32 t;
|
||||
Int32 alphaSize;
|
||||
Int32 nGroups;
|
||||
Int32 nSelectors;
|
||||
Int32 EOB;
|
||||
Int32 groupNo;
|
||||
Int32 groupPos;
|
||||
Int32 nextSym;
|
||||
Int32 nblockMAX;
|
||||
Int32 nblock;
|
||||
Int32 es;
|
||||
Int32 N;
|
||||
Int32 curr;
|
||||
Int32 zt;
|
||||
Int32 zn;
|
||||
Int32 zvec;
|
||||
Int32 zj;
|
||||
Int32 gSel;
|
||||
Int32 gMinlen;
|
||||
Int32* gLimit;
|
||||
Int32* gBase;
|
||||
Int32* gPerm;
|
||||
|
||||
if (s->state == BZ_X_MAGIC_1) {
|
||||
/*initialise the save area*/
|
||||
s->save_i = 0;
|
||||
s->save_j = 0;
|
||||
s->save_t = 0;
|
||||
s->save_alphaSize = 0;
|
||||
s->save_nGroups = 0;
|
||||
s->save_nSelectors = 0;
|
||||
s->save_EOB = 0;
|
||||
s->save_groupNo = 0;
|
||||
s->save_groupPos = 0;
|
||||
s->save_nextSym = 0;
|
||||
s->save_nblockMAX = 0;
|
||||
s->save_nblock = 0;
|
||||
s->save_es = 0;
|
||||
s->save_N = 0;
|
||||
s->save_curr = 0;
|
||||
s->save_zt = 0;
|
||||
s->save_zn = 0;
|
||||
s->save_zvec = 0;
|
||||
s->save_zj = 0;
|
||||
s->save_gSel = 0;
|
||||
s->save_gMinlen = 0;
|
||||
s->save_gLimit = nullptr;
|
||||
s->save_gBase = nullptr;
|
||||
s->save_gPerm = nullptr;
|
||||
}
|
||||
|
||||
/*restore from the save area*/
|
||||
i = s->save_i;
|
||||
j = s->save_j;
|
||||
t = s->save_t;
|
||||
alphaSize = s->save_alphaSize;
|
||||
nGroups = s->save_nGroups;
|
||||
nSelectors = s->save_nSelectors;
|
||||
EOB = s->save_EOB;
|
||||
groupNo = s->save_groupNo;
|
||||
groupPos = s->save_groupPos;
|
||||
nextSym = s->save_nextSym;
|
||||
nblockMAX = s->save_nblockMAX;
|
||||
nblock = s->save_nblock;
|
||||
es = s->save_es;
|
||||
N = s->save_N;
|
||||
curr = s->save_curr;
|
||||
zt = s->save_zt;
|
||||
zn = s->save_zn;
|
||||
zvec = s->save_zvec;
|
||||
zj = s->save_zj;
|
||||
gSel = s->save_gSel;
|
||||
gMinlen = s->save_gMinlen;
|
||||
gLimit = s->save_gLimit;
|
||||
gBase = s->save_gBase;
|
||||
gPerm = s->save_gPerm;
|
||||
|
||||
retVal = BZ_OK;
|
||||
|
||||
switch (s->state) {
|
||||
GET_UCHAR(BZ_X_MAGIC_1, uc);
|
||||
if (uc != BZ_HDR_B)
|
||||
RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_2, uc);
|
||||
if (uc != BZ_HDR_Z)
|
||||
RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_3, uc)
|
||||
if (uc != BZ_HDR_h)
|
||||
RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
|
||||
if (s->blockSize100k < (BZ_HDR_0 + 1) || s->blockSize100k > (BZ_HDR_0 + 9))
|
||||
RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
s->blockSize100k -= BZ_HDR_0;
|
||||
|
||||
if (s->smallDecompress) {
|
||||
s->ll16 = (UInt16*)BZALLOC(s->blockSize100k * 100000 * sizeof(UInt16));
|
||||
s->ll4 = (UChar*)BZALLOC(((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar));
|
||||
if (s->ll16 == nullptr || s->ll4 == nullptr)
|
||||
RETURN(BZ_MEM_ERROR);
|
||||
}
|
||||
else {
|
||||
s->tt = (UInt32*)BZALLOC(s->blockSize100k * 100000 * sizeof(Int32));
|
||||
if (s->tt == nullptr)
|
||||
RETURN(BZ_MEM_ERROR);
|
||||
}
|
||||
|
||||
GET_UCHAR(BZ_X_BLKHDR_1, uc);
|
||||
|
||||
if (uc == 0x17)
|
||||
goto endhdr_2;
|
||||
if (uc != 0x31)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_2, uc);
|
||||
if (uc != 0x41)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_3, uc);
|
||||
if (uc != 0x59)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_4, uc);
|
||||
if (uc != 0x26)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_5, uc);
|
||||
if (uc != 0x53)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_6, uc);
|
||||
if (uc != 0x59)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
s->currBlockNo++;
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf1("\n [%d: huff+mtf ", s->currBlockNo);
|
||||
|
||||
s->storedBlockCRC = 0;
|
||||
GET_UCHAR(BZ_X_BCRC_1, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_2, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_3, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_4, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
|
||||
GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
|
||||
|
||||
s->origPtr = 0;
|
||||
GET_UCHAR(BZ_X_ORIGPTR_1, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
GET_UCHAR(BZ_X_ORIGPTR_2, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
GET_UCHAR(BZ_X_ORIGPTR_3, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
|
||||
if (s->origPtr < 0)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
if (s->origPtr > 10 + 100000 * s->blockSize100k)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*--- Receive the mapping table ---*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
GET_BIT(BZ_X_MAPPING_1, uc);
|
||||
if (uc == 1)
|
||||
s->inUse16[i] = True;
|
||||
else
|
||||
s->inUse16[i] = False;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
s->inUse[i] = False;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (s->inUse16[i])
|
||||
for (j = 0; j < 16; j++) {
|
||||
GET_BIT(BZ_X_MAPPING_2, uc);
|
||||
if (uc == 1)
|
||||
s->inUse[i * 16 + j] = True;
|
||||
}
|
||||
makeMaps_d(s);
|
||||
if (s->nInUse == 0)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
alphaSize = s->nInUse + 2;
|
||||
|
||||
/*--- Now the selectors ---*/
|
||||
GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
|
||||
if (nGroups < 2 || nGroups > 6)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
|
||||
if (nSelectors < 1)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
j = 0;
|
||||
while (True) {
|
||||
GET_BIT(BZ_X_SELECTOR_3, uc);
|
||||
if (uc == 0)
|
||||
break;
|
||||
j++;
|
||||
if (j >= nGroups)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
s->selectorMtf[i] = j;
|
||||
}
|
||||
|
||||
/*--- Undo the MTF values for the selectors. ---*/
|
||||
{
|
||||
UChar pos[BZ_N_GROUPS], tmp, v;
|
||||
for (i = 0; i < nGroups; i++)
|
||||
pos[i] = i;
|
||||
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
v = s->selectorMtf[i];
|
||||
tmp = pos[v];
|
||||
while (v > 0) {
|
||||
pos[v] = pos[v - 1];
|
||||
v--;
|
||||
}
|
||||
pos[0] = tmp;
|
||||
s->selector[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*--- Now the coding tables ---*/
|
||||
for (j = 0; j < nGroups; j++) {
|
||||
GET_BITS(BZ_X_CODING_1, curr, 5);
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
while (True) {
|
||||
if (curr < 1 || curr > 20)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_BIT(BZ_X_CODING_2, uc);
|
||||
if (uc == 0)
|
||||
break;
|
||||
GET_BIT(BZ_X_CODING_3, uc);
|
||||
if (uc == 0)
|
||||
curr++;
|
||||
else
|
||||
curr--;
|
||||
}
|
||||
s->len[j][i] = curr;
|
||||
}
|
||||
}
|
||||
|
||||
/*--- Create the Huffman decoding tables ---*/
|
||||
for (j = 0; j < nGroups; j++) {
|
||||
minLen = 32;
|
||||
maxLen = 0;
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
if (s->len[j][i] > maxLen)
|
||||
maxLen = s->len[j][i];
|
||||
if (s->len[j][i] < minLen)
|
||||
minLen = s->len[j][i];
|
||||
}
|
||||
BZ2_hbCreateDecodeTables(&(s->limit[j][0]),
|
||||
&(s->base[j][0]),
|
||||
&(s->perm[j][0]),
|
||||
&(s->len[j][0]),
|
||||
minLen,
|
||||
maxLen,
|
||||
alphaSize);
|
||||
s->minLens[j] = minLen;
|
||||
}
|
||||
|
||||
/*--- Now the MTF values ---*/
|
||||
|
||||
EOB = s->nInUse + 1;
|
||||
nblockMAX = 100000 * s->blockSize100k;
|
||||
groupNo = -1;
|
||||
groupPos = 0;
|
||||
|
||||
for (i = 0; i <= 255; i++)
|
||||
s->unzftab[i] = 0;
|
||||
|
||||
/*-- MTF init --*/
|
||||
{
|
||||
Int32 l, j, k;
|
||||
k = MTFA_SIZE - 1;
|
||||
for (l = 256 / MTFL_SIZE - 1; l >= 0; l--) {
|
||||
for (j = MTFL_SIZE - 1; j >= 0; j--) {
|
||||
s->mtfa[k] = (UChar)(l * MTFL_SIZE + j);
|
||||
k--;
|
||||
}
|
||||
s->mtfbase[l] = k + 1;
|
||||
}
|
||||
}
|
||||
/*-- end MTF init --*/
|
||||
|
||||
nblock = 0;
|
||||
GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
|
||||
|
||||
while (True) {
|
||||
if (nextSym == EOB)
|
||||
break;
|
||||
|
||||
if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
|
||||
es = -1;
|
||||
N = 1;
|
||||
do {
|
||||
/* Check that N doesn't get too big, so that es doesn't
|
||||
go negative. The maximum value that can be
|
||||
RUNA/RUNB encoded is equal to the block size (post
|
||||
the initial RLE), viz, 900k, so bounding N at 2
|
||||
million should guard against overflow without
|
||||
rejecting any legitimate inputs. */
|
||||
if (N >= 2 * 1024 * 1024)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
if (nextSym == BZ_RUNA)
|
||||
es = es + (0 + 1) * N;
|
||||
else if (nextSym == BZ_RUNB)
|
||||
es = es + (1 + 1) * N;
|
||||
N = N * 2;
|
||||
GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
|
||||
} while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
|
||||
|
||||
es++;
|
||||
uc = s->seqToUnseq[s->mtfa[s->mtfbase[0]]];
|
||||
s->unzftab[uc] += es;
|
||||
|
||||
if (s->smallDecompress)
|
||||
while (es > 0) {
|
||||
if (nblock >= nblockMAX)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
s->ll16[nblock] = (UInt16)uc;
|
||||
nblock++;
|
||||
es--;
|
||||
}
|
||||
else
|
||||
while (es > 0) {
|
||||
if (nblock >= nblockMAX)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
s->tt[nblock] = (UInt32)uc;
|
||||
nblock++;
|
||||
es--;
|
||||
};
|
||||
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (nblock >= nblockMAX)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- uc = MTF ( nextSym-1 ) --*/
|
||||
{
|
||||
Int32 i, j, k, l, lno, off;
|
||||
UInt32 nn;
|
||||
nn = (UInt32)(nextSym - 1);
|
||||
|
||||
if (nn < MTFL_SIZE) {
|
||||
/* avoid general-case expense */
|
||||
l = s->mtfbase[0];
|
||||
uc = s->mtfa[l + nn];
|
||||
while (nn > 3) {
|
||||
Int32 z = l + nn;
|
||||
s->mtfa[(z)] = s->mtfa[(z)-1];
|
||||
s->mtfa[(z)-1] = s->mtfa[(z)-2];
|
||||
s->mtfa[(z)-2] = s->mtfa[(z)-3];
|
||||
s->mtfa[(z)-3] = s->mtfa[(z)-4];
|
||||
nn -= 4;
|
||||
}
|
||||
while (nn > 0) {
|
||||
s->mtfa[(l + nn)] = s->mtfa[(l + nn) - 1];
|
||||
nn--;
|
||||
};
|
||||
s->mtfa[l] = uc;
|
||||
}
|
||||
else {
|
||||
/* general case */
|
||||
lno = nn / MTFL_SIZE;
|
||||
off = nn % MTFL_SIZE;
|
||||
l = s->mtfbase[lno] + off;
|
||||
uc = s->mtfa[l];
|
||||
while (l > s->mtfbase[lno]) {
|
||||
s->mtfa[l] = s->mtfa[l - 1];
|
||||
l--;
|
||||
};
|
||||
s->mtfbase[lno]++;
|
||||
while (lno > 0) {
|
||||
s->mtfbase[lno]--;
|
||||
s->mtfa[s->mtfbase[lno]] = s->mtfa[s->mtfbase[lno - 1] + MTFL_SIZE - 1];
|
||||
lno--;
|
||||
}
|
||||
s->mtfbase[0]--;
|
||||
s->mtfa[s->mtfbase[0]] = uc;
|
||||
if (s->mtfbase[0] == 0) {
|
||||
k = MTFA_SIZE - 1;
|
||||
for (i = 256 / MTFL_SIZE - 1; i >= 0; i--) {
|
||||
for (j = MTFL_SIZE - 1; j >= 0; j--) {
|
||||
s->mtfa[k] = s->mtfa[s->mtfbase[i] + j];
|
||||
k--;
|
||||
}
|
||||
s->mtfbase[i] = k + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-- end uc = MTF ( nextSym-1 ) --*/
|
||||
|
||||
s->unzftab[s->seqToUnseq[uc]]++;
|
||||
if (s->smallDecompress)
|
||||
s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]);
|
||||
else
|
||||
s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
|
||||
nblock++;
|
||||
|
||||
GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we know what nblock is, we can do a better sanity
|
||||
check on s->origPtr.
|
||||
*/
|
||||
if (s->origPtr < 0 || s->origPtr >= nblock)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- Set up cftab to facilitate generation of T^(-1) --*/
|
||||
/* Check: unzftab entries in range. */
|
||||
for (i = 0; i <= 255; i++) {
|
||||
if (s->unzftab[i] < 0 || s->unzftab[i] > nblock)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
/* Actually generate cftab. */
|
||||
s->cftab[0] = 0;
|
||||
for (i = 1; i <= 256; i++)
|
||||
s->cftab[i] = s->unzftab[i - 1];
|
||||
for (i = 1; i <= 256; i++)
|
||||
s->cftab[i] += s->cftab[i - 1];
|
||||
/* Check: cftab entries in range. */
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
|
||||
/* s->cftab[i] can legitimately be == nblock */
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
/* Check: cftab entries non-descending. */
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (s->cftab[i - 1] > s->cftab[i]) {
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
s->state_out_len = 0;
|
||||
s->state_out_ch = 0;
|
||||
BZ_INITIALISE_CRC(s->calculatedBlockCRC);
|
||||
s->state = BZ_X_OUTPUT;
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf0("rt+rld");
|
||||
|
||||
if (s->smallDecompress) {
|
||||
/*-- Make a copy of cftab, used in generation of T --*/
|
||||
for (i = 0; i <= 256; i++)
|
||||
s->cftabCopy[i] = s->cftab[i];
|
||||
|
||||
/*-- compute the T vector --*/
|
||||
for (i = 0; i < nblock; i++) {
|
||||
uc = (UChar)(s->ll16[i]);
|
||||
SET_LL(i, s->cftabCopy[uc]);
|
||||
s->cftabCopy[uc]++;
|
||||
}
|
||||
|
||||
/*-- Compute T^(-1) by pointer reversal on T --*/
|
||||
i = s->origPtr;
|
||||
j = GET_LL(i);
|
||||
do {
|
||||
Int32 tmp = GET_LL(j);
|
||||
SET_LL(j, i);
|
||||
i = j;
|
||||
j = tmp;
|
||||
} while (i != s->origPtr);
|
||||
|
||||
s->tPos = s->origPtr;
|
||||
s->nblock_used = 0;
|
||||
if (s->blockRandomised) {
|
||||
BZ_RAND_INIT_MASK;
|
||||
BZ_GET_SMALL(s->k0);
|
||||
s->nblock_used++;
|
||||
BZ_RAND_UPD_MASK;
|
||||
s->k0 ^= BZ_RAND_MASK;
|
||||
}
|
||||
else {
|
||||
BZ_GET_SMALL(s->k0);
|
||||
s->nblock_used++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*-- compute the T^(-1) vector --*/
|
||||
for (i = 0; i < nblock; i++) {
|
||||
uc = (UChar)(s->tt[i] & 0xff);
|
||||
s->tt[s->cftab[uc]] |= (i << 8);
|
||||
s->cftab[uc]++;
|
||||
}
|
||||
|
||||
s->tPos = s->tt[s->origPtr] >> 8;
|
||||
s->nblock_used = 0;
|
||||
if (s->blockRandomised) {
|
||||
BZ_RAND_INIT_MASK;
|
||||
BZ_GET_FAST(s->k0);
|
||||
s->nblock_used++;
|
||||
BZ_RAND_UPD_MASK;
|
||||
s->k0 ^= BZ_RAND_MASK;
|
||||
}
|
||||
else {
|
||||
BZ_GET_FAST(s->k0);
|
||||
s->nblock_used++;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN(BZ_OK);
|
||||
|
||||
endhdr_2:
|
||||
|
||||
GET_UCHAR(BZ_X_ENDHDR_2, uc);
|
||||
if (uc != 0x72)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_3, uc);
|
||||
if (uc != 0x45)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_4, uc);
|
||||
if (uc != 0x38)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_5, uc);
|
||||
if (uc != 0x50)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_6, uc);
|
||||
if (uc != 0x90)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
s->storedCombinedCRC = 0;
|
||||
GET_UCHAR(BZ_X_CCRC_1, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_2, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_3, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_4, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
|
||||
s->state = BZ_X_IDLE;
|
||||
RETURN(BZ_STREAM_END);
|
||||
|
||||
default: AssertH(False, 4001);
|
||||
}
|
||||
|
||||
AssertH(False, 4002);
|
||||
|
||||
save_state_and_return:
|
||||
|
||||
s->save_i = i;
|
||||
s->save_j = j;
|
||||
s->save_t = t;
|
||||
s->save_alphaSize = alphaSize;
|
||||
s->save_nGroups = nGroups;
|
||||
s->save_nSelectors = nSelectors;
|
||||
s->save_EOB = EOB;
|
||||
s->save_groupNo = groupNo;
|
||||
s->save_groupPos = groupPos;
|
||||
s->save_nextSym = nextSym;
|
||||
s->save_nblockMAX = nblockMAX;
|
||||
s->save_nblock = nblock;
|
||||
s->save_es = es;
|
||||
s->save_N = N;
|
||||
s->save_curr = curr;
|
||||
s->save_zt = zt;
|
||||
s->save_zn = zn;
|
||||
s->save_zvec = zvec;
|
||||
s->save_zj = zj;
|
||||
s->save_gSel = gSel;
|
||||
s->save_gMinlen = gMinlen;
|
||||
s->save_gLimit = gLimit;
|
||||
s->save_gBase = gBase;
|
||||
s->save_gPerm = gPerm;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end decompress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
#include "bzlib.hpp"
|
||||
|
||||
#include "common/utility/utility.hpp"
|
||||
|
||||
#include "oneapi/tbb/flow_graph.h"
|
||||
#include "oneapi/tbb/tick_count.h"
|
||||
#include "oneapi/tbb/concurrent_queue.h"
|
||||
|
||||
// TODO: change memory allocation/deallocation to be managed in constructor/destructor
|
||||
struct Buffer {
|
||||
std::size_t len;
|
||||
char* b;
|
||||
};
|
||||
|
||||
struct BufferMsg {
|
||||
BufferMsg() {}
|
||||
BufferMsg(Buffer& inputBuffer, Buffer& outputBuffer, std::size_t seqId, bool isLast = false)
|
||||
: inputBuffer(inputBuffer),
|
||||
outputBuffer(outputBuffer),
|
||||
seqId(seqId),
|
||||
isLast(isLast) {}
|
||||
|
||||
static BufferMsg createBufferMsg(std::size_t seqId, std::size_t chunkSize) {
|
||||
Buffer inputBuffer;
|
||||
inputBuffer.b = new char[chunkSize];
|
||||
inputBuffer.len = chunkSize;
|
||||
|
||||
Buffer outputBuffer;
|
||||
std::size_t compressedChunkSize = chunkSize * 1.01 + 600; // compression overhead
|
||||
outputBuffer.b = new char[compressedChunkSize];
|
||||
outputBuffer.len = compressedChunkSize;
|
||||
|
||||
return BufferMsg(inputBuffer, outputBuffer, seqId);
|
||||
}
|
||||
|
||||
static void destroyBufferMsg(const BufferMsg& destroyMsg) {
|
||||
delete[] destroyMsg.inputBuffer.b;
|
||||
delete[] destroyMsg.outputBuffer.b;
|
||||
}
|
||||
|
||||
void markLast(std::size_t lastId) {
|
||||
isLast = true;
|
||||
seqId = lastId;
|
||||
}
|
||||
|
||||
std::size_t seqId;
|
||||
Buffer inputBuffer;
|
||||
Buffer outputBuffer;
|
||||
bool isLast;
|
||||
};
|
||||
|
||||
class BufferCompressor {
|
||||
public:
|
||||
BufferCompressor(int blockSizeIn100KB) : m_blockSize(blockSizeIn100KB) {}
|
||||
|
||||
BufferMsg operator()(BufferMsg buffer) const {
|
||||
if (!buffer.isLast) {
|
||||
unsigned int outSize = buffer.outputBuffer.len;
|
||||
BZ2_bzBuffToBuffCompress(buffer.outputBuffer.b,
|
||||
&outSize,
|
||||
buffer.inputBuffer.b,
|
||||
buffer.inputBuffer.len,
|
||||
m_blockSize,
|
||||
0,
|
||||
30);
|
||||
buffer.outputBuffer.len = outSize;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_blockSize;
|
||||
};
|
||||
|
||||
class IOOperations {
|
||||
public:
|
||||
IOOperations(std::ifstream& inputStream, std::ofstream& outputStream, std::size_t chunkSize)
|
||||
: m_inputStream(inputStream),
|
||||
m_outputStream(outputStream),
|
||||
m_chunkSize(chunkSize),
|
||||
m_chunksRead(0) {}
|
||||
|
||||
void readChunk(Buffer& buffer) {
|
||||
m_inputStream.read(buffer.b, m_chunkSize);
|
||||
buffer.len = static_cast<std::size_t>(m_inputStream.gcount());
|
||||
m_chunksRead++;
|
||||
}
|
||||
|
||||
void writeChunk(const Buffer& buffer) {
|
||||
m_outputStream.write(buffer.b, buffer.len);
|
||||
}
|
||||
|
||||
std::size_t chunksRead() const {
|
||||
return m_chunksRead;
|
||||
}
|
||||
|
||||
std::size_t chunkSize() const {
|
||||
return m_chunkSize;
|
||||
}
|
||||
|
||||
bool hasDataToRead() const {
|
||||
return m_inputStream.is_open() && !m_inputStream.eof();
|
||||
}
|
||||
|
||||
private:
|
||||
std::ifstream& m_inputStream;
|
||||
std::ofstream& m_outputStream;
|
||||
|
||||
std::size_t m_chunkSize;
|
||||
std::size_t m_chunksRead;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//---------------------------------------Compression example based on async_node-----------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
typedef oneapi::tbb::flow::async_node<oneapi::tbb::flow::continue_msg, BufferMsg>
|
||||
async_file_reader_node;
|
||||
typedef oneapi::tbb::flow::async_node<BufferMsg, oneapi::tbb::flow::continue_msg>
|
||||
async_file_writer_node;
|
||||
|
||||
class AsyncNodeActivity {
|
||||
public:
|
||||
AsyncNodeActivity(IOOperations& io)
|
||||
: m_io(io),
|
||||
m_fileWriterThread(&AsyncNodeActivity::writingLoop, this) {}
|
||||
|
||||
~AsyncNodeActivity() {
|
||||
m_fileReaderThread.join();
|
||||
m_fileWriterThread.join();
|
||||
}
|
||||
|
||||
void submitRead(async_file_reader_node::gateway_type& gateway) {
|
||||
gateway.reserve_wait();
|
||||
std::thread(&AsyncNodeActivity::readingLoop, this, std::ref(gateway))
|
||||
.swap(m_fileReaderThread);
|
||||
}
|
||||
|
||||
void submitWrite(const BufferMsg& bufferMsg) {
|
||||
m_writeQueue.push(bufferMsg);
|
||||
}
|
||||
|
||||
private:
|
||||
void readingLoop(async_file_reader_node::gateway_type& gateway) {
|
||||
while (m_io.hasDataToRead()) {
|
||||
BufferMsg bufferMsg = BufferMsg::createBufferMsg(m_io.chunksRead(), m_io.chunkSize());
|
||||
m_io.readChunk(bufferMsg.inputBuffer);
|
||||
gateway.try_put(bufferMsg);
|
||||
}
|
||||
sendLastMessage(gateway);
|
||||
gateway.release_wait();
|
||||
}
|
||||
|
||||
void writingLoop() {
|
||||
BufferMsg buffer;
|
||||
m_writeQueue.pop(buffer);
|
||||
while (!buffer.isLast) {
|
||||
m_io.writeChunk(buffer.outputBuffer);
|
||||
m_writeQueue.pop(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void sendLastMessage(async_file_reader_node::gateway_type& gateway) {
|
||||
BufferMsg lastMsg;
|
||||
lastMsg.markLast(m_io.chunksRead());
|
||||
gateway.try_put(lastMsg);
|
||||
}
|
||||
|
||||
IOOperations& m_io;
|
||||
|
||||
oneapi::tbb::concurrent_bounded_queue<BufferMsg> m_writeQueue;
|
||||
|
||||
std::thread m_fileReaderThread;
|
||||
std::thread m_fileWriterThread;
|
||||
};
|
||||
|
||||
void fgCompressionAsyncNode(IOOperations& io, int blockSizeIn100KB) {
|
||||
oneapi::tbb::flow::graph g;
|
||||
|
||||
AsyncNodeActivity asyncNodeActivity(io);
|
||||
|
||||
async_file_reader_node file_reader(
|
||||
g,
|
||||
oneapi::tbb::flow::unlimited,
|
||||
[&asyncNodeActivity](const oneapi::tbb::flow::continue_msg& msg,
|
||||
async_file_reader_node::gateway_type& gateway) {
|
||||
asyncNodeActivity.submitRead(gateway);
|
||||
});
|
||||
|
||||
oneapi::tbb::flow::function_node<BufferMsg, BufferMsg> compressor(
|
||||
g, oneapi::tbb::flow::unlimited, BufferCompressor(blockSizeIn100KB));
|
||||
|
||||
oneapi::tbb::flow::sequencer_node<BufferMsg> ordering(g,
|
||||
[](const BufferMsg& bufferMsg) -> size_t {
|
||||
return bufferMsg.seqId;
|
||||
});
|
||||
|
||||
// The node is serial to preserve the right order of buffers set by the preceding sequencer_node
|
||||
async_file_writer_node output_writer(
|
||||
g,
|
||||
oneapi::tbb::flow::serial,
|
||||
[&asyncNodeActivity](const BufferMsg& bufferMsg,
|
||||
async_file_writer_node::gateway_type& gateway) {
|
||||
asyncNodeActivity.submitWrite(bufferMsg);
|
||||
});
|
||||
|
||||
make_edge(file_reader, compressor);
|
||||
make_edge(compressor, ordering);
|
||||
make_edge(ordering, output_writer);
|
||||
|
||||
file_reader.try_put(oneapi::tbb::flow::continue_msg());
|
||||
|
||||
g.wait_for_all();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
//---------------------------------------------Simple compression example------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void fgCompression(IOOperations& io, int blockSizeIn100KB) {
|
||||
oneapi::tbb::flow::graph g;
|
||||
|
||||
oneapi::tbb::flow::input_node<BufferMsg> file_reader(
|
||||
g, [&io](oneapi::tbb::flow_control& fc) -> BufferMsg {
|
||||
if (io.hasDataToRead()) {
|
||||
BufferMsg bufferMsg = BufferMsg::createBufferMsg(io.chunksRead(), io.chunkSize());
|
||||
io.readChunk(bufferMsg.inputBuffer);
|
||||
return bufferMsg;
|
||||
}
|
||||
fc.stop();
|
||||
return BufferMsg{};
|
||||
});
|
||||
file_reader.activate();
|
||||
|
||||
oneapi::tbb::flow::function_node<BufferMsg, BufferMsg> compressor(
|
||||
g, oneapi::tbb::flow::unlimited, BufferCompressor(blockSizeIn100KB));
|
||||
|
||||
oneapi::tbb::flow::sequencer_node<BufferMsg> ordering(g, [](const BufferMsg& buffer) -> size_t {
|
||||
return buffer.seqId;
|
||||
});
|
||||
|
||||
oneapi::tbb::flow::function_node<BufferMsg> output_writer(
|
||||
g, oneapi::tbb::flow::serial, [&io](const BufferMsg& bufferMsg) {
|
||||
io.writeChunk(bufferMsg.outputBuffer);
|
||||
BufferMsg::destroyBufferMsg(bufferMsg);
|
||||
});
|
||||
|
||||
make_edge(file_reader, compressor);
|
||||
make_edge(compressor, ordering);
|
||||
make_edge(ordering, output_writer);
|
||||
|
||||
g.wait_for_all();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool endsWith(const std::string& str, const std::string& suffix) {
|
||||
return str.find(suffix, str.length() - suffix.length()) != std::string::npos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now();
|
||||
|
||||
const std::string archiveExtension = ".bz2";
|
||||
bool verbose = false;
|
||||
bool asyncType;
|
||||
std::string inputFileName;
|
||||
int blockSizeIn100KB = 1; // block size in 100KB chunks
|
||||
std::size_t memoryLimitIn1MB = 1; // memory limit for compression in megabytes granularity
|
||||
|
||||
utility::parse_cli_arguments(
|
||||
argc,
|
||||
argv,
|
||||
utility::cli_argument_pack()
|
||||
//"-h" option for displaying help is present implicitly
|
||||
.arg(blockSizeIn100KB, "-b", "\t block size in 100KB chunks, [1 .. 9]")
|
||||
.arg(verbose, "-v", "verbose mode")
|
||||
.arg(memoryLimitIn1MB,
|
||||
"-l",
|
||||
"used memory limit for compression algorithm in 1MB (minimum) granularity")
|
||||
.arg(asyncType, "-async", "use graph async_node-based implementation")
|
||||
.positional_arg(inputFileName, "filename", "input file name"));
|
||||
|
||||
if (inputFileName.empty()) {
|
||||
throw std::invalid_argument(
|
||||
"Input file name is not specified. Try 'fgbzip2 -h' for more information.");
|
||||
}
|
||||
|
||||
if (blockSizeIn100KB < 1 || blockSizeIn100KB > 9) {
|
||||
throw std::invalid_argument("Incorrect block size. Try 'fgbzip2 -h' for more information.");
|
||||
}
|
||||
|
||||
if (memoryLimitIn1MB < 1) {
|
||||
throw std::invalid_argument(
|
||||
"Incorrect memory limit size. Try 'fgbzip2 -h' for more information.");
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
std::cout << "Input file name: " << inputFileName << "\n";
|
||||
if (endsWith(inputFileName, archiveExtension)) {
|
||||
throw std::invalid_argument("Input file already have " + archiveExtension + " extension.");
|
||||
}
|
||||
|
||||
std::ifstream inputStream(inputFileName.c_str(), std::ios::in | std::ios::binary);
|
||||
if (!inputStream.is_open()) {
|
||||
throw std::invalid_argument("Cannot open " + inputFileName + " file.");
|
||||
}
|
||||
|
||||
std::string outputFileName(inputFileName + archiveExtension);
|
||||
|
||||
std::ofstream outputStream(outputFileName.c_str(),
|
||||
std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!outputStream.is_open()) {
|
||||
throw std::invalid_argument("Cannot open " + outputFileName + " file.");
|
||||
}
|
||||
|
||||
// General interface to work with I/O buffers operations
|
||||
std::size_t chunkSize = blockSizeIn100KB * 100 * 1024;
|
||||
IOOperations io(inputStream, outputStream, chunkSize);
|
||||
|
||||
if (asyncType) {
|
||||
if (verbose)
|
||||
std::cout
|
||||
<< "Running flow graph based compression algorithm with async_node based asynchronous IO operations."
|
||||
<< "\n";
|
||||
fgCompressionAsyncNode(io, blockSizeIn100KB);
|
||||
}
|
||||
else {
|
||||
if (verbose)
|
||||
std::cout << "Running flow graph based compression algorithm."
|
||||
<< "\n";
|
||||
fgCompression(io, blockSizeIn100KB);
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
|
||||
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - mainStartTime).seconds());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Huffman coding low-level stuff ---*/
|
||||
/*--- huffman.cpp ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#include "bzlib_private.hpp"
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define WEIGHTOF(zz0) ((zz0)&0xffffff00)
|
||||
#define DEPTHOF(zz1) ((zz1)&0x000000ff)
|
||||
#define MYMAX(zz2, zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
|
||||
|
||||
#define ADDWEIGHTS(zw1, zw2) \
|
||||
(WEIGHTOF(zw1) + WEIGHTOF(zw2)) | (1 + MYMAX(DEPTHOF(zw1), DEPTHOF(zw2)))
|
||||
|
||||
#define UPHEAP(z) \
|
||||
{ \
|
||||
Int32 zz, tmp; \
|
||||
zz = z; \
|
||||
tmp = heap[zz]; \
|
||||
while (weight[tmp] < weight[heap[zz >> 1]]) { \
|
||||
heap[zz] = heap[zz >> 1]; \
|
||||
zz >>= 1; \
|
||||
} \
|
||||
heap[zz] = tmp; \
|
||||
}
|
||||
|
||||
#define DOWNHEAP(z) \
|
||||
{ \
|
||||
Int32 zz, yy, tmp; \
|
||||
zz = z; \
|
||||
tmp = heap[zz]; \
|
||||
while (True) { \
|
||||
yy = zz << 1; \
|
||||
if (yy > nHeap) \
|
||||
break; \
|
||||
if (yy < nHeap && weight[heap[yy + 1]] < weight[heap[yy]]) \
|
||||
yy++; \
|
||||
if (weight[tmp] < weight[heap[yy]]) \
|
||||
break; \
|
||||
heap[zz] = heap[yy]; \
|
||||
zz = yy; \
|
||||
} \
|
||||
heap[zz] = tmp; \
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbMakeCodeLengths(UChar *len, Int32 *freq, Int32 alphaSize, Int32 maxLen) {
|
||||
/*--
|
||||
Nodes and heap entries run from 1. Entry 0
|
||||
for both the heap and nodes is a sentinel.
|
||||
--*/
|
||||
Int32 nNodes, nHeap, n1, n2, i, j, k;
|
||||
Bool tooLong;
|
||||
|
||||
Int32 heap[BZ_MAX_ALPHA_SIZE + 2];
|
||||
Int32 weight[BZ_MAX_ALPHA_SIZE * 2];
|
||||
Int32 parent[BZ_MAX_ALPHA_SIZE * 2];
|
||||
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
|
||||
|
||||
while (True) {
|
||||
nNodes = alphaSize;
|
||||
nHeap = 0;
|
||||
|
||||
heap[0] = 0;
|
||||
weight[0] = 0;
|
||||
parent[0] = -2;
|
||||
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
parent[i] = -1;
|
||||
nHeap++;
|
||||
heap[nHeap] = i;
|
||||
UPHEAP(nHeap);
|
||||
}
|
||||
|
||||
AssertH(nHeap < (BZ_MAX_ALPHA_SIZE + 2), 2001);
|
||||
|
||||
while (nHeap > 1) {
|
||||
n1 = heap[1];
|
||||
heap[1] = heap[nHeap];
|
||||
nHeap--;
|
||||
DOWNHEAP(1);
|
||||
n2 = heap[1];
|
||||
heap[1] = heap[nHeap];
|
||||
nHeap--;
|
||||
DOWNHEAP(1);
|
||||
nNodes++;
|
||||
parent[n1] = parent[n2] = nNodes;
|
||||
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
|
||||
parent[nNodes] = -1;
|
||||
nHeap++;
|
||||
heap[nHeap] = nNodes;
|
||||
UPHEAP(nHeap);
|
||||
}
|
||||
|
||||
AssertH(nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002);
|
||||
|
||||
tooLong = False;
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
j = 0;
|
||||
k = i;
|
||||
while (parent[k] >= 0) {
|
||||
k = parent[k];
|
||||
j++;
|
||||
}
|
||||
len[i - 1] = j;
|
||||
if (j > maxLen)
|
||||
tooLong = True;
|
||||
}
|
||||
|
||||
if (!tooLong)
|
||||
break;
|
||||
|
||||
/* 17 Oct 04: keep-going condition for the following loop used
|
||||
to be 'i < alphaSize', which missed the last element,
|
||||
theoretically leading to the possibility of the compressor
|
||||
looping. However, this count-scaling step is only needed if
|
||||
one of the generated Huffman code words is longer than
|
||||
maxLen, which up to and including version 1.0.2 was 20 bits,
|
||||
which is extremely unlikely. In version 1.0.3 maxLen was
|
||||
changed to 17 bits, which has minimal effect on compression
|
||||
ratio, but does mean this scaling step is used from time to
|
||||
time, enough to verify that it works.
|
||||
|
||||
This means that bzip2-1.0.3 and later will only produce
|
||||
Huffman codes with a maximum length of 17 bits. However, in
|
||||
order to preserve backwards compatibility with bitstreams
|
||||
produced by versions pre-1.0.3, the decompressor must still
|
||||
handle lengths of up to 20. */
|
||||
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
j = weight[i] >> 8;
|
||||
j = 1 + (j / 2);
|
||||
weight[i] = j << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbAssignCodes(Int32 *code, UChar *length, Int32 minLen, Int32 maxLen, Int32 alphaSize) {
|
||||
Int32 j, vec, i;
|
||||
|
||||
vec = 0;
|
||||
for (j = minLen; j <= maxLen; j++) {
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
if (length[i] == j) {
|
||||
code[i] = vec;
|
||||
vec++;
|
||||
};
|
||||
vec <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbCreateDecodeTables(Int32 *limit,
|
||||
Int32 *base,
|
||||
Int32 *perm,
|
||||
UChar *length,
|
||||
Int32 minLen,
|
||||
Int32 maxLen,
|
||||
Int32 alphaSize) {
|
||||
Int32 pp, i, j, vec;
|
||||
|
||||
pp = 0;
|
||||
for (i = minLen; i <= maxLen; i++)
|
||||
for (j = 0; j < alphaSize; j++)
|
||||
if (length[j] == i) {
|
||||
perm[pp] = j;
|
||||
pp++;
|
||||
};
|
||||
|
||||
for (i = 0; i < BZ_MAX_CODE_LEN; i++)
|
||||
base[i] = 0;
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
base[length[i] + 1]++;
|
||||
|
||||
for (i = 1; i < BZ_MAX_CODE_LEN; i++)
|
||||
base[i] += base[i - 1];
|
||||
|
||||
for (i = 0; i < BZ_MAX_CODE_LEN; i++)
|
||||
limit[i] = 0;
|
||||
vec = 0;
|
||||
|
||||
for (i = minLen; i <= maxLen; i++) {
|
||||
vec += (base[i + 1] - base[i]);
|
||||
limit[i] = vec - 1;
|
||||
vec <<= 1;
|
||||
}
|
||||
for (i = minLen + 1; i <= maxLen; i++)
|
||||
base[i] = ((limit[i - 1] + 1) << 1) - base[i];
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end huffman.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Table for randomising repetitive blocks ---*/
|
||||
/*--- randtable.cpp ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
The original source for this example:
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2010 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@bzip.org
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#include "bzlib_private.hpp"
|
||||
|
||||
/*---------------------------------------------*/
|
||||
Int32 BZ2_rNums[512] = {
|
||||
619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863, 491, 741, 242, 949,
|
||||
214, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 419, 436, 278, 496, 867, 210, 399, 680,
|
||||
480, 51, 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807,
|
||||
591, 733, 623, 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727, 476,
|
||||
693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 909, 545, 703, 919, 874,
|
||||
474, 882, 500, 594, 612, 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 161, 604, 958, 533,
|
||||
221, 400, 386, 867, 600, 782, 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163,
|
||||
354, 666, 933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 469, 68,
|
||||
770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 715,
|
||||
67, 618, 276, 204, 918, 873, 777, 604, 560, 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
||||
652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820,
|
||||
908, 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680, 81, 927, 626,
|
||||
789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 170, 774, 972, 275, 999, 639, 495,
|
||||
78, 352, 126, 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992,
|
||||
809, 743, 168, 974, 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511,
|
||||
655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 433, 837, 553, 268,
|
||||
926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 946, 670, 656,
|
||||
610, 738, 392, 760, 799, 887, 653, 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879,
|
||||
194, 572, 640, 724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 297,
|
||||
59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
||||
343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 140, 206, 73, 263, 980, 736, 876, 478, 430,
|
||||
305, 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790,
|
||||
288, 923, 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524, 462, 293,
|
||||
465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 768, 550, 608, 933, 378, 286,
|
||||
215, 979, 792, 961, 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 372, 567, 466, 434, 645,
|
||||
210, 389, 550, 919, 135, 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713,
|
||||
857, 265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 936, 638
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end randtable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user